Public: anyone can read this; the crew can change it.
Meter awake time and storage: per app and environment, the two quantities a forge charges for #527
Check · Review · Land · Live done — Landed and live in production.
This adds a meter for each app: one row for every stretch of time an environment is awake, and an hourly sample of the bytes it stores. Those are the two quantities a forge charges for. `src/core/meter.ts` reads them back for a [from, to) range as awake seconds and GB-hours (bytes × hours / 1e9).
shipped production is serving it deploy 2fa0c24
commented
Fixes the failed check on #527: forge.json was refused because check.run was longer than 1000 characters. Adding test/meter.test.ts pushed it over, and it is now 451 characters.
What changed
scripts/test-shards.tsnow accepts short test names after--, socrew-wrapupmeanstest/crew-wrapup.test.ts. A name that doesn't match^[a-z0-9][a-z0-9-]{0,99}$is refused, so a name can't point outsidetest/. Full paths before--still work as before.scripts/shards.tsgainssplitArgs, which does this split as a small function on plain data.forge.json'scheck.runlists the same 43 test files by short name.test/shards.test.tsgains a test that readsforge.jsonwith the forge's ownparseCheck, so a check that is too long now fails locally, not after a push. It also checks that every named test file exists, so a typo can't quietly drop a file from the run.
Choices
- I kept the explicit list of test files and did not switch to a glob.
forge.jsonstays the one place that says which tests the check runs.
Try it
bun x tsc --noEmitpasses.bun test test/shards.test.ts: 26 pass.- The full
check.runfromforge.json: 654 tests in 43 files across 3 shards, 0 failures.
🤖 Generated with Claude Code
Sign in to join this conversation.
new above
offline
This adds a meter for each app: one row for every stretch of time an environment is awake, and an hourly sample of the bytes it stores. Those are the two quantities a forge charges for.
src/core/meter.tsreads them back for a [from, to) range as awake seconds and GB-hours (bytes × hours / 1e9).The meter itself is unchanged from #518. The check on #518 failed on "the fork flow > a mirror whose git is not ready yet is fetched again, and lands". That test is in
test/fork-flow.test.ts, which this change doesn't touch. Main has since fixed it (#497) by seeding the upstream only once the mirror job has moved past its first fetch, instead of on a 300 ms timer. This branch now merges main to pick that fix up. Merging needed three conflicts resolved by hand:src/core/schema.ts: main's fleet-operation receipt keeps migration 40, and the meter's tables (meter,storage) move to migration 41.src/apps/runtime.ts: boot keeps main's new way of settling abandoned runs (deploys fail; checks are queued again), then closes any awake interval left open at its last heartbeat.forge.json: the check runs main's file list plustest/meter.test.ts.The full
forge.jsoncheck now passes locally: typecheck clean, 647 tests passing across 43 files in 3 shards, none failing. The fork-flow file passed 3 runs out of 3 on its own.I didn't add the meter test's timing to
scripts/test-times.json, which the test runner uses to split files into shards. It's a sub-second file, and recording it withcheck:recordcan come later.To try it:
bun test test/meter.test.tshas hand-counted cases: start, sleep, wake and stop add up to the expected seconds, a restart closes the open interval at its last heartbeat, and a fixture directory's storage matches its byte count.docs/APPS.md.🤖 Generated with Claude Code
Closes #505