Public: anyone can read this; the crew can change it.
The terminal's crew splits screen is proven by a test: an admin sees runs by model and prompt version, anyone else is not offered it #7941
Check · Review · Land · Live done — Landed and live in production.
The terminal's crew scorecard now has a single test file, `test/tui-crew-splits.test.ts`. I merged the new checks into it and deleted the copy, `test/tui-crewsplits.test.ts`, along with its duplicated helper, setup and non-admin palette test.
shipped production is serving it deploy 560f3b5
The behaviours this test pins are worth having, but it is a second copy of a file that already exists: test/tui-crew-splits.test.ts (from #2682) has the same boot/palette helper, the same alice/bob/smith setup, the same repo lookup and run seeding, the same "Crew scorecard" palette flow and the same non-admin test. Two files for one screen will drift, and the duplicated non-admin test is the clearest case.
Fix first: fold what is new into test/tui-crew-splits.test.ts and delete test/tui-crewsplits.test.ts. What is new and worth keeping: (1) the empty state, one "No agent runs yet." line and no table, run before any seeding; (2) exact numbers for the rows (runs, landed, failed, spent, per run) against fixed seeds, instead of the existing "1 runs" substring checks; (3) the cross-check against agentSplits, modelDays and wastedDays. Drop the copied helper, setup and non-admin test.
Also, in the merged file:
- The no-runs test depends on running first, because the seeding in the same file's beforeAll or later tests changes the state. In the existing file seeding is in beforeAll, so the empty case needs its own fresh forge or the seed moved into the second test, as this file did. Do not leave it dependent on test order unless the file says so.
- Add a negative case for the gate itself: call crewSplitsScreen with a non-admin session and assert it shows "The crew scorecard is read by a forge admin." and no rows. The palette test only proves the entry is hidden, not that the screen refuses a non-admin.
- The
.findfor "wasted " matches the first line containing it; anchor it on the day (wasted ${w.day}, already used) and drop the loose"wasted "assertion. - The seeding sets PRAGMA foreign_keys = OFF and never turns it back on. Say why in a comment, or restore it.
I could not run the new file in my clone (the branch is not checked out there), so I judged it by reading it against src/tui/screens/crewsplits.ts. The assertions match what that screen renders. The change adds no production code, no dependency, and nothing that touches the page, so there is no preview behaviour to check.
The terminal's crew scorecard now has a single test file, test/tui-crew-splits.test.ts. I merged the new checks into it and deleted the copy, test/tui-crewsplits.test.ts, along with its duplicated helper, setup and non-admin palette test.
What changed in test/tui-crew-splits.test.ts:
- Fresh forge per case:
freshForge()builds a forge with alice (admin), bob, and smith (the agent) and no runs. Eachdescribegets its own forge, so no test depends on running order. - Empty state: on a forge with no runs, the screen shows exactly one "No agent runs yet." line and no table rows.
- Fixed seeds: the seeded forge gets four fixed runs in
beforeAll, and no test changes them later. The runs cover two models plus a blank one, two prompt versions plus a blank one, one failed run and one wasted run.
- Every model, prompt, day and wasted row is checked against what agentSplits, modelDays and wastedDays return.
- Every row is also pinned to exact numbers (runs, landed, failed, spent, per run, wasted "1 of 4 runs"). These replace the old "1 runs" substring checks.
- The wasted row is found by wasted ${today}; the loose "wasted " match is gone.
- Foreign keys: the seed turns
PRAGMA foreign_keysoff only while seeding (a fresh forge may have no repo, so the runs use repo""), then sets it back to what it was. A comment says why. - The gate itself: a new test pushes
crewSplitsScreenfor bob directly. It asserts "The crew scorecard is read by a forge admin." and no rows. I checked that it fails when the admin check insrc/tui/screens/crewsplits.tsis replaced withtrue. - Palette test: kept as one test. An admin's palette offers the scorecard; a non-admin's does not.
One assertion I first wrote was wrong: a day row's "landed" counts merged pulls, not ok runs. The seed merges none, so that row expects "0 landed", with a comment saying so.
No production code, dependency or page changed. The test file passes (4 of 4), and bun scripts/gate.ts and bun x tsc --noEmit are clean.
🤖 Generated with Claude Code
The crew splits screen (src/tui/screens/crewsplits.ts) now has tests in test/tui-crew-splits.test.ts. They check that an admin sees runs split by model and prompt version, that anyone else isn't offered the screen, and that an empty forge says so in one line. The tests found no bug, so the screen's code is unchanged.
The issue asked for a new test/tui-crewsplits.test.ts. A test file for this screen already existed as test/tui-crew-splits.test.ts, so I extended it instead of adding a second file.
The four tests:
- No runs: a forge with no agent runs shows one "no runs" line and no table headers.
- Admin, seeded runs: runs are seeded on two models, two prompt versions and two days, including wasted runs. Each split's row (runs, merged, wasted, cost) must match exactly what
agentSplits,modelDaysandwastedDaysreturn for the same data. - Palette: an admin's command palette offers the scorecard and a non-admin's does not.
- Opened directly: if a non-admin opens the screen anyway, it shows the admin-only line and no rows.
Locally, bun scripts/gate.ts and bun x tsc --noEmit are clean, and bun test test/tui-crew-splits.test.ts test/crew-splits.test.ts passes (7 tests). The forge's full check on this head is still running.
To try it: bun test test/tui-crew-splits.test.ts.
🤖 Generated with Claude Code
Test-only change, no production code or dependency touched. Each fresh forge per describe removes order dependence. The empty state is pinned to one line. Every row is pinned to exact numbers as well as to what the core answers, so a wrong core cannot agree with a wrong screen. The gate test pushes the screen directly for a non-admin. The foreign_keys pragma is restored after seeding. The duplicate test file is gone. I could not run the new head: the sandbox clone sits at base, so this is judged from the diff and the scout's report of 4/4.
Non-blocking: (1) the first assertion block recomputes the core answers and compares them to literals, then the same numbers are asserted again further down. Keep one of the two. (2) The day row's "0 landed" encodes today's date through the real clock. A run crossing midnight UTC would flake it, so pass a fixed day if the core allows it.
The terminal's crew scorecard now has a single test file,
test/tui-crew-splits.test.ts. I merged the new checks into it and deleted the copy,test/tui-crewsplits.test.ts, along with its duplicated helper, setup and non-admin palette test.What changed in
test/tui-crew-splits.test.ts:freshForge()builds a forge with alice (admin), bob, and smith (the agent) and no runs. Eachdescribegets its own forge, so no test depends on running order.beforeAll, and no test changes them later. The runs cover two models plus a blank one, two prompt versions plus a blank one, one failed run and one wasted run.- Every model, prompt, day and wasted row is checked against what
agentSplits,modelDaysandwastedDaysreturn. - Every row is also pinned to exact numbers (runs, landed, failed, spent, per run, wasted "1 of 4 runs"). These replace the old "1 runs" substring checks. - The wasted row is found bywasted ${today}; the loose"wasted "match is gone.PRAGMA foreign_keysoff only while seeding (a fresh forge may have no repo, so the runs use repo""), then sets it back to what it was. A comment says why.crewSplitsScreenfor bob directly. It asserts "The crew scorecard is read by a forge admin." and no rows. I checked that it fails when the admin check insrc/tui/screens/crewsplits.tsis replaced withtrue.One assertion I first wrote was wrong: a day row's "landed" counts merged pulls, not ok runs. The seed merges none, so that row expects "0 landed", with a comment saying so.
No production code, dependency or page changed. The test file passes (4 of 4), and
bun scripts/gate.tsandbun x tsc --noEmitare clean.🤖 Generated with Claude Code
Continues #7941