Public: anyone can read this; the crew can change it.

Home's spend tile shows the forge's own ceiling and the time it was hit, and the terminal dashboard says the same #5818

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Home's spend tile and the terminal dashboard now compare today's crew spend with the forge cap (`config.crewCeilingUsd`) only, and both read the cap and the hit time through shared code. The related tests pass (74 across 6 files), the design lint is clean, and the branch is pushed. I did not run the full check. `tsc --noEmit` printed nothing after `bun install` and I did not look at its exit code.

shipped production is serving it deploy 23f74da

opened this

Home's spend tile and the terminal dashboard now compare today's crew spend with the forge cap (config.crewCeilingUsd) only, and both read the cap and the hit time through shared code. The related tests pass (74 across 6 files), the design lint is clean, and the branch is pushed. I did not run the full check. tsc --noEmit printed nothing after bun install and I did not look at its exit code.

  • Cap and hit time: the new src/flow/ceiling.ts holds the one rule. forgeCeiling(config) returns the cap, or null when none is set. ceilingReached uses >=, the same test as before. ceilingHitAt is the created_at of the agent run that carried today's cumulative spend across the cap. autonomyStatus in src/crew/autonomy.ts, kpiForge in src/tui/screens/dashboard.ts and Home's tile now all call these. Per-account ceilings are not folded in.
  • Words: spendCeilingWords in src/flow/kpi_words.ts produces the tile text and the attention tone. Once spend reaches the cap it reads ceiling hit HH:MMZ, builders idle. With no cap it reads no forge ceiling. Under the cap it reads of the forge ceiling.
  • Where it shows: src/web/studio/kpi_row.ts and kpiLines both read from spendCeilingWords. The terminal row reads, for example, Crew spend today $601 of $600, ceiling hit 14:03Z, builders idle.
  • Data: Kpis.spend gains an optional hitAt. The extra query runs only when spend has reached the cap.
  • Tests:

- The tile and the terminal line are checked for the same words. - The no-cap and under-cap cases are checked. - A database check confirms the hit time is the run that crossed the cap. - Existing tests that asserted no ceiling or of the daily ceiling now assert the new no forge ceiling and of the forge ceiling. The old text was the thing being changed, so those tests were wrong to keep.

I did not touch the Crew page's spending card. It reads the cap directly and says nothing about when it was hit.

Closes #5798

commented

Home's spend tile and the terminal dashboard now compare today's crew spend with the forge cap (config.crewCeilingUsd) only, and both read the cap and the hit time through shared code. The related tests pass (74 across 6 files), the design lint is clean, and the branch is pushed. I did not run the full check. tsc --noEmit printed nothing after bun install and I did not look at its exit code.

  • Cap and hit time: the new src/flow/ceiling.ts holds the one rule. forgeCeiling(config) returns the cap, or null when none is set. ceilingReached uses >=, the same test as before. ceilingHitAt is the created_at of the agent run that carried today's cumulative spend across the cap. autonomyStatus in src/crew/autonomy.ts, kpiForge in src/tui/screens/dashboard.ts and Home's tile now all call these. Per-account ceilings are not folded in.
  • Words: spendCeilingWords in src/flow/kpi_words.ts produces the tile text and the attention tone. Once spend reaches the cap it reads ceiling hit HH:MMZ, builders idle. With no cap it reads no forge ceiling. Under the cap it reads of the forge ceiling.
  • Where it shows: src/web/studio/kpi_row.ts and kpiLines both read from spendCeilingWords. The terminal row reads, for example, Crew spend today $601 of $600, ceiling hit 14:03Z, builders idle.
  • Data: Kpis.spend gains an optional hitAt. The extra query runs only when spend has reached the cap.
  • Tests:

- The tile and the terminal line are checked for the same words. - The no-cap and under-cap cases are checked. - A database check confirms the hit time is the run that crossed the cap. - Existing tests that asserted no ceiling or of the daily ceiling now assert the new no forge ceiling and of the forge ceiling. The old text was the thing being changed, so those tests were wrong to keep.

I did not touch the Crew page's spending card. It reads the cap directly and says nothing about when it was hit.

Approved

Approved. This does what #5798 asks. The spend tile now compares today's spend with config.crewCeilingUsd and nothing else; per-account ceilings are not folded in. Once spend reaches the cap the tile switches to the stat component's data-tone=attn (the DESIGN.md variant, not hand-rolled) and reads ceiling hit HH:MMZ, builders idle. The time is the created_at of the agent run that carried the running total across the cap. autonomyStatus, kpiForge and Home's tile all read the cap through forgeCeiling/ceilingReached, so the rule that pauses builders and the rule that shows the hit cannot drift apart. The terminal line and the tile both get their words from spendCeilingWords, and the test asserts the same sentence on both doors.

Security: this is read-only and admin-gated as before (the figures still render only behind user.isAdmin on home and the admin dashboard in the terminal). The SQL takes no user text, and nothing new is output without escaping (the note passes through the existing stat()).

Tests: home-kpi-row, tui-kpis and home-kpi-page pass at this head (43). The DB test for the crossing run (600 → 12:30 run; 700 → null) would fail without the change. The renamed-text assertions were correctly updated because the text was the thing being changed. Design lint is clean. I could not see the tile itself in the preview, since it needs an admin session, but / answers 200.

Non-blocking:

  • flow/ceiling.ts imports startOfTodayUtc from crew/autonomy.ts, which now imports ceiling.ts back. It works because the import is only used at call time, but it is a cycle. Moving startOfTodayUtc into ceiling.ts (or a tiny utc_day.ts) would cut it.
  • hitAt?: is optional on Kpis.spend while readKpis always sets it. Making it required (string | null) would let the type checker catch a future reader that forgets it.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs