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

The terminal's Usage screen, opened from the dashboard with no repository, shows the forge's spend today, in the last 24 h and each subscription's headroom #8341

Merged opened this

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

Merged

Opening Usage from the palette with no repository now draws three lines above the existing content. Each line comes from `readForgeUsage`, the function behind MCP `usage` and `GET /api/v1/usage`.

shipped production is serving it deploy aafe9dc

opened this

Opening Usage from the palette with no repository now draws three lines above the existing content. Each line comes from readForgeUsage, the function behind MCP usage and GET /api/v1/usage.

The lines look like this:

  • Today: $3.25 over 2 runs
  • Last 24 h: $3.25 over 2 runs
  • Headroom: work 5h 0% (each subscription's windows in percent, or no limit named / no window yet when the provider hasn't said)

The per-repository Usage screen is unchanged. The change is in src/tui/screens/usage.ts, in a new forgeSpendLines function. The data is read once when the screen opens.

Tests: test/tui-usage-forge.test.ts covers both cases. It renders the screen for a caller with two repositories, a subscription, spend and a noted limit, and asserts the three lines. It also asserts that Usage of a repository has none of them. I checked that the first test fails with the source change stashed. The existing Usage tests and palette-roster.test.ts pass, as do bun scripts/gate.ts and tsc --noEmit.

Not run: scripts/fast.ts reported 268 test files for this diff, about 22 minutes. I did not run all of them. Instead I ran the Usage, palette-roster and other TUI tests that open Usage or the palette, which gave 160 passes and the 3 palette-roster failures I then fixed by reverting the gate change below.

Left out:

  • Gate: I left the palette entry's gate as it is, so only a site admin sees Usage. Opening it to every signed-in user changed the pinned roster in test/palette-roster.test.ts for members and agents, and the issue didn't ask for that. Non-admins can still read the same numbers on the separate "Forge spend" screen. src/tui/forge.ts is untouched.
  • Narrow terminals: I did not add any special handling for narrow terminals. Long headroom lines are truncated.

Closes #8308

commented

Opening Usage from the palette with no repository now draws three lines above the existing content. Each line comes from readForgeUsage, the function behind MCP usage and GET /api/v1/usage.

The lines look like this:

  • Today: $3.25 over 2 runs
  • Last 24 h: $3.25 over 2 runs
  • Headroom: work 5h 0% (each subscription's windows in percent, or no limit named / no window yet when the provider hasn't said)

The per-repository Usage screen is unchanged. The change is in src/tui/screens/usage.ts, in a new forgeSpendLines function. The data is read once when the screen opens.

Tests: test/tui-usage-forge.test.ts covers both cases. It renders the screen for a caller with two repositories, a subscription, spend and a noted limit, and asserts the three lines. It also asserts that Usage of a repository has none of them. I checked that the first test fails with the source change stashed. The existing Usage tests and palette-roster.test.ts pass, as do bun scripts/gate.ts and tsc --noEmit.

Not run: scripts/fast.ts reported 268 test files for this diff, about 22 minutes. I did not run all of them. Instead I ran the Usage, palette-roster and other TUI tests that open Usage or the palette, which gave 160 passes and the 3 palette-roster failures I then fixed by reverting the gate change below.

Left out:

  • Gate: I left the palette entry's gate as it is, so only a site admin sees Usage. Opening it to every signed-in user changed the pinned roster in test/palette-roster.test.ts for members and agents, and the issue didn't ask for that. Non-admins can still read the same numbers on the separate "Forge spend" screen. src/tui/forge.ts is untouched.
  • Narrow terminals: I did not add any special handling for narrow terminals. Long headroom lines are truncated.
Changes requested — before the latest push

The three lines are correct and read from readForgeUsage (the same function as MCP usage), and the test fails without the change. Three things to fix in one round:

  1. FIRST: reachability. The Usage palette entry is still admin-only, so a member or agent never reaches these lines, and the 'done means reachable' bar is not met for them. The issue lists src/tui/forge.ts, and readForgeUsage already narrows to what the caller can see, so open the entry to signed-in users and update the pinned roster in test/palette-roster.test.ts. Without that, the ruling must come from a person, not from the builder skipping the failing roster test. Note that USAGE_ADMIN_ONLY still has to show for the route list; draw the spend block above it for everyone. Following AGENTS.md, the entry lives where it says.
  2. No docs/features/<name>.md how-to. Add one that says where the lines are (':' then Usage) and what they mean. Keep README.md untouched.
  3. Tests: add a case for a non-admin signed-in user (sees only the spend of repositories they can see, not the admin's) and a guest (no lines). Right now only the admin path is proven, and the gating is the point of this door.

Smaller: with a long headroom list the line is truncated, so the later subscriptions vanish in a narrow terminal. Wrap to extra lines or put one subscription per line so none is silently lost.

commented

All three of juniper's requests and the narrow-terminal point are done and pushed. The Usage, palette-roster and Returns test files pass (16 tests) and tsc is clean. I did not run the full suite or scripts/fast.ts (it named 268 of 1855 files, over the 5-minute budget). gate.ts printed nothing, so I take it as clean.

What changed

  • Reachability: The Usage palette entry (src/tui/forge.ts) is now offered to every signed-in user, member and agent included, and the spend block draws above the route list. The route list is still admin-only; everyone else sees USAGE_ADMIN_ONLY under the spend. A signed-out visitor is not offered the entry.
  • Palette hint: The hint changed to "the forge's spend and headroom; an admin also sees every route". I updated test/palette-roster.test.ts for the admin agent and the member, and test/tui-usage.test.ts now expects those two to see the spend and not the route count.
  • Narrow terminals: forgeSpendLines now puts each subscription's headroom on its own line, with Headroom: on the first and the rest indented. A line that is itself wider than the terminal is still truncated.
  • How-to: docs/features/forge-usage-terminal.md says where the lines are (: then Usage) and what they mean. README.md is untouched.
  • Tests, in test/tui-usage-forge.test.ts:

- Member: bob is not a repository writer, so bob sees Today: $0.00 over 0 runs, not alice's $3.25, and no route list. - Guest: the palette offers no Usage and nothing draws Today:. - Line layout: a unit test checks that three subscriptions give three lines.

Left out

  • Member with spend: bob can't create a repository on this test forge (not_member), so the member case shows the gating as zero spend, not a smaller non-zero figure.
  • Wrapping: I did not wrap a single over-wide subscription line.

Try it: SSH to the app terminal, press :, type Usage and press enter, as admin, as a member, and signed out.

Approved

Earlier asks, all met: (1) Usage is now offered to every signed-in person and agent (src/tui/forge.ts gate is session.user !== undefined), a guest is not offered it, and the route list stays the admin gate, with the admin-only wording for everyone else. (2) Headroom is one subscription per line, so a narrow terminal truncates one line and never drops later ones. (3) The how-to is docs/features/forge-usage-terminal.md and README is untouched. The roster pins and tui-usage tests were updated to match, and there is a guest test, a member test and a layout test. No new dependency, no dead code.

Two things I would do next, both non-blocking:

  • Non-blocking: the member test asserts only that the route count is absent. Also assert that USAGE_ADMIN_ONLY is drawn, so the person is told why the list is missing.
  • Non-blocking: the spend is read once when the screen opens and never refreshes. Re-read it when the screen is focused again, or on the existing returns window keys, so a long-open terminal does not show stale dollars. The layout test also casts with as never; a small typed fixture would be better.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs