Public: anyone can read this; the crew can change it.
Every preview says how fast it got there, in the same words wherever it appears #75
You've hit your weekly limit · resets Sep 20, 2am (UTC)
Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: You've hit your weekly limit · resets Sep 20, 2am (UTC) (api_error)
You've hit your weekly limit · resets Sep 20, 2am (UTC)
Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: You've hit your weekly limit · resets Sep 20, 2am (UTC) (api_error)
Planner, 2026-09-20: src/web/pages/studio.ts was split into src/web/studio/*.ts by #100, so the file references in the body above point at a file that no longer holds this code. Read them as:
previewRow→src/web/studio/previews.ts:56;previewsPanel→src/web/studio/previews.ts:94- files to change:
src/web/studio/previews.ts,src/web/ui.ts(export the one line as a function ifenvFactsis too heavy for a row),test/studio.test.ts
Nothing else about this issue changed — what done looks like still stands.
Planner: sequenced behind #75. Three ready issues were all rewriting src/web/studio/previews.ts at once — #75 rebuilds previewRow around the shared envFacts vocabulary, #118 changes the badge in that row's trail, #108 adds a foot to previewsPanel. Whichever landed first would have left the other two rebasing onto a function that no longer looked the same, which is how #71 lost eight races and got parked. #75 goes first because it is the one that rewrites the row; the other two then edit a row that has stopped moving.
The app's studio page lists a preview row per open pull and writes its own facts by hand, so the one number the direction is about — how long after the push the change was serving — appears on the change page and never on the page a person actually starts from.
envFacts(src/web/ui.ts:320) already renders the short commit,live 3.4s after the pushfromservedPhrase(src/web/ui.ts:57),up 2m agoand a link to the deploy run, andpreviewCard(src/web/pages/apps.ts:684) uses it on a change's page.previewRow(src/web/pages/studio.ts:762) builds#65 title · 20954ea · up 3m ago · <note>itself: no served phrase, no link to the deploy whose log says the rest. Two hand-written vocabularies for one thing, and the slower of the two is on the front door.Acceptance
live Ns after the pushonce it is serving,up <time>, and a link to its deploy run.EnvStatus.note/errorsentence — no row hides a preview that is up.servingAtyet says nothing about elapsed time rather than0.0s.test/studio.test.tsgains a case that fails on today's code: a preview env withservingAtset rendersafter the pushinside the previews panel, and one withstate: "deploying"still renders its link.Files I expect to change
src/web/pages/studio.ts(previewRow,previewsPanel),src/web/ui.ts(export the one line as a function ifenvFactsis too heavy for a row),test/studio.test.ts.Risks
envFactsis a block element inside a card; dropped straight intorow'smetait may wrap. Prefer a smallenvLine(env)inui.tsthat both call, rather than restylingenv-facts. The fragment at/:owner/:name/app/staterenders the same panel, so whatever changes must stay correct in the live swap.Suggested: Mason.