Public: anyone can read this; the crew can change it.
Split src/web/pages/studio.ts into modules named for one concept each #100
Check · Review · Land · Live done — Landed and live in production.
`src/web/pages/studio.ts` (2,757 lines) is now `src/web/studio/`, one module named for the one thing it owns: `words` (the vocabulary and its badge — `pullWord`/`runWord`, still the one place a word is decided), `leans` (the decider's lean, asked off the request path), `asks` (the card, the row, the panel, the bulk table), `previews` (production's head card, every open pull's preview, and the frag…
shipped production is serving it deploy 2fa0c24
web/pages/studio.ts was 2,757 lines and every studio issue added to it. It is now web/studio/, one module named for the one thing it owns: words (the vocabulary and its badge), leans (the decider's lean, asked off the request path), asks, previews, home, app, change, tell, run, lists, actions and style. The move is pure — every line is in the new files verbatim, bar an avatarOf wrapper the eight call sites no longer need, four unused imports, and the CSS, now joined from named parts and byte-for-byte equal to the string it was. pages/studio.ts stays a thin re-export of the six handles the tests import, so the tests that prove no byte of HTML changed were untouched by the change that moved it.
The merge with main is the piece to look at: main (#99) added the studio head card's Terminal line inside appPanels in the old pages/studio.ts, and this branch had moved that whole function to web/studio/previews.ts. Both sides meant the same thing, so both are kept — terminalLine(terminalFor(...)), the writer-only when and the host key beside it, applied verbatim to appPanels where it now lives. Nothing else conflicted, and no test was changed to make it pass.
To try it: the studio app page (/:owner/:name in studio mode) draws the same head card, previews list and Terminal line as before. bun x tsc --noEmit is clean and the check's test set is 246 pass / 6 fail here — those six (apps, apps-adversarial, web, pulls, cross-repo-pull) fail identically on a clean origin/main worktree in this sandbox, which cannot authenticate a git push over http; test/studio.test.ts and test/studio-words.test.ts, including #99's two new terminal tests, are 50 pass / 0 fail.
🤖 Generated with Claude Code
src/web/pages/studio.ts(2,757 lines) is nowsrc/web/studio/, one module named for the one thing it owns:words(the vocabulary and its badge —pullWord/runWord, still the one place a word is decided),leans(the decider's lean, asked off the request path),asks(the card, the row, the panel, the bulk table),previews(production's head card, every open pull's preview, and the fragment a deploy event refreshes),home,app,change,tell(with thetellWordthe lists read),run(the transcript, and the Stop a live run has),lists,actions(every POST the studio makes) andstyle(the page sheet).It is a pure move. Every line of the old file is in the new ones verbatim, bar three things worth checking: the
avatarOfwrapper is gone (it wasreturn avatar(username); its eight call sites callavatardirectly), four imports nothing used are gone, and the CSS is now joined from named parts instudio/style.ts—bulkCssstill derived from the same table the bulk route enforces — which I compared against the old string at runtime and it is byte-for-byte equal. No markup was touched, no class renamed, no rule deleted. The proof is thattest/studio.test.ts,test/studio-words.test.ts,test/decide.test.tsandtest/ledger.test.tsare untouched and green (109 tests with the rest of the crew suites), andbun x tsc --noEmitis clean;pages/studio.tsstays as a 13-line re-export of exactly the six handles those tests import, so nothing intest/had to move for the code to. Every other importer —repo,pull,pulls,issues,runs,site,http/server— now points at the module it needs;board.tsneeded nothing, itsDecisioncomes fromcore/decisions.ts.What I chose not to do: the sheet still carries the first studio's dead rules (
.studio,.studio-main,.studio-preview*,.studio-live*,.studio-list*,.studio-who,.studio-rail*,.studio-crew*— nothing in the directory draws any of them). Deleting them changes what is served, which this issue rules out; they are labelled as stale instyle.tsand are worth their own issue. The parts also stay assembled in one file rather than living in the page modules, because moving them there would either flip the served order or make the pages and the sheet import each other.To try it:
bun run src/main.ts, then the studio home, an app, a change, a tell and a run —/,/:owner/:name,/:owner/:name/pulls/:n,/:owner/:name/issues/:n,/:owner/:name/runs/:id— should be indistinguishable frommain, including the asks panel's bulk bar with scripts off. In my sandbox six tests inapps,apps-adversarial,web,pullsandcross-repo-pullfail ongit push: auth required; they fail identically on an unmodifiedHEADworktree here, so they are the sandbox, not this change.🤖 Generated with Claude Code
Closes #63