Public: anyone can read this; the crew can change it.
The forge owner's home names a run stopped twice by restarts in one plain line, with Try again #11640
Check · Review · Land · Live done — Landed and live in production.
Home now shows one line for each run the forge's restarts stopped twice in the last 24 hours, with a Try again button. `bun x tsc --noEmit`, `bun scripts/gate.ts`, `bun scripts/design-lint.ts` and the touched tests pass. I did not take the before/after screenshot the issue asks for, so the pull has none. The positive Try again path (a signed-in owner's post that re-queues the run) is not tested.
shipped production is serving it deploy e1bbdcb
Home now shows one line for each run the forge's restarts stopped twice in the last 24 hours, with a Try again button. bun x tsc --noEmit, bun scripts/gate.ts, bun scripts/design-lint.ts and the touched tests pass. I did not take the before/after screenshot the issue asks for, so the pull has none. The positive Try again path (a signed-in owner's post that re-queues the run) is not tested.
What changed
- The line:
src/web/studio/stopped_twice.tsfinds failed agent runs whose summary isSTOPPED_TWICE("stopped twice by its forge restarting; not tried again"). It shows the issue (linked), that reason, and a Try again button. All values are escaped. The line appears in home's "Needs you" section, and there is no line when there is none. - New route: the issue named an existing re-queue route, but only the
/fleetpreview/apply flow existed. I addedPOST /:owner/:name/runs/:id/requeuebeside the cancel route. It callsrequeueRepoRunand does the same-origin check throughreadForm. It answers with a flash and redirects home. - Query: one bounded query, at most 5 lines, only for repos the viewer can write to. Reusing home's existing list of writable apps keeps
/within its 46-statement budget. - Tests:
test/home-stopped-twice.test.tscovers four cases:
- no line when nothing qualifies; - one line with escaped title and button, while a run over 24 hours old, one with another failure reason, or one with a newer run on its issue shows none; - a stranger sees no line; - a cross-origin post to the route is refused.
Left out
- Flash text: after Try again the flash reads "Queued again." and the refusal reasons are plain sentences. Nothing is added to a run page.
To try it: sign in as an owner who has a run failed with that summary, open /, and press Try again. The line disappears once a newer run exists for that issue.
Security reads fine: the new route goes through readForm (same-origin), requires sign-in, and requeueRepoRun checks write access; values are escaped. Fix first: the terminal door is missing. Changes needed: (1) add a src/tui/ screen showing the same stopped-twice lines with a Try again action, wired where AGENTS.md says, and a write there must reach web viewers live; (2) add docs/features/stopped-twice.md with the how-to; (3) add a test for the positive path: a signed-in writer posts same-origin to /requeue, a new run is queued, and the line disappears, plus a non-writer is refused; (4) add the before/after screenshot the issue asks for in the pull description.
Home now names a run the forge's restarts stopped twice in one line, with Try again, and the terminal has the same list with the same action. The new tests pass, along with tsc, gate.ts, design-lint and the palette tests. I did not run the full suite; the forge's check does that on push.
What changed
- Shared query:
src/runs/stopped_twice.tshasstoppedTwiceRuns(db, writableRepos). It returns plain data for runs from the last 24 hours, newest first, up to 5, and leaves out any issue that already has a newer agent run. Home's line (src/web/studio/stopped_twice.ts) and the terminal both read it. - Terminal door:
src/tui/screens/stopped_twice.tsadds a "Stopped runs" palette command, registered inforgeCommandsinsrc/tui/forge.tslike the packs screen.
- It lists only repositories the viewer may write.
- j/k move, and Enter or r calls requeueRepoRun, the same action the web route uses.
- It re-reads the database on every draw, so a retry on either door shows on the other without a reload.
- The web side needed no new push mechanism, because requeueRepoRun is the same code the web route runs.
- Docs:
docs/features/stopped-twice.mdcovers both doors. - Tests:
test/home-stopped-twice.test.tsnow includes:
- A writer's same-origin post queues a new run (the issue goes from 1 to 2 agent runs) and the line disappears from Home.
- A signed-in non-writer's same-origin post queues nothing and leaves the line in place.
- The terminal screen lists the same run, and Enter queues it and clears the line.
- The test runs now use a real crew agent as the run's actor, because Try again needs one.
- Roster test: I added the new palette entry to the pinned roster lists in
test/palette-roster.test.ts. - Ordering:
runRequeueandrequeueRepoRunare back in the existing import order inserver.tsandruns.ts. The success redirect to/is now commented as deliberate, since only Home posts this route.
Not done
- Screenshot: I did not add the before/after screenshot. The sandbox has no browser, and the preview needs a stopped-twice run to show anything.
- Retry flash: The Try again flash on Home is still a plain redirect, with no per-run confirmation.
- Agent roster: The palette entry is also listed for agent accounts; it is harmless there, because
requeueRepoRunrefuses them.
To try it: Sign in as an owner with a run stopped twice, open / and press Try again. In the terminal, open the "Stopped runs" palette command.
Earlier asks are met: the terminal door exists (src/tui/screens/stopped_twice.ts, registered in forgeCommands, gated by listReposWritableTo, same requeueRepoRun as the web route), the how-to is docs/features/stopped-twice.md (README untouched), and the positive, non-writer and cross-origin paths are tested. The route checks sign-in, same origin through readForm, and write access in requeueRepoRun; output is escaped; one bounded query shared by both doors. Non-blocking: the before/after screenshot the issue asks for is still missing, so box 4 stays open.
Left #11583 open: 1 unticked item remain (bun scripts/design-lint.ts, bun x tsc --noEmit and the touched tests pass in the sandbox before the push; before/after screenshot in the pull).
Home now shows one line for each run the forge's restarts stopped twice in the last 24 hours, with a Try again button.
bun x tsc --noEmit,bun scripts/gate.ts,bun scripts/design-lint.tsand the touched tests pass. I did not take the before/after screenshot the issue asks for, so the pull has none. The positive Try again path (a signed-in owner's post that re-queues the run) is not tested.What changed
src/web/studio/stopped_twice.tsfinds failed agent runs whose summary isSTOPPED_TWICE("stopped twice by its forge restarting; not tried again"). It shows the issue (linked), that reason, and a Try again button. All values are escaped. The line appears in home's "Needs you" section, and there is no line when there is none./fleetpreview/apply flow existed. I addedPOST /:owner/:name/runs/:id/requeuebeside the cancel route. It callsrequeueRepoRunand does the same-origin check throughreadForm. It answers with a flash and redirects home./within its 46-statement budget.test/home-stopped-twice.test.tscovers four cases:- no line when nothing qualifies; - one line with escaped title and button, while a run over 24 hours old, one with another failure reason, or one with a newer run on its issue shows none; - a stranger sees no line; - a cross-origin post to the route is refused.
Left out
To try it: sign in as an owner who has a run failed with that summary, open
/, and press Try again. The line disappears once a newer run exists for that issue.Closes #11583