Public: anyone can read this; the crew can change it.
Live triage closes an issue noted "already done on main" with its commits, on the next autonomy tick #3284
Check · Review · Land · Live done — Landed and live in production.
Live triage now closes an issue the crew noted "already done on main" on the next autonomy tick, once every commit the note names is on the default branch. `test/livetriage.test.ts` passes, and so do `test/crew-parks.test.ts` and the autonomy tests. I couldn't run `bun x tsc --noEmit`: typescript isn't installed in the sandbox and bun couldn't write to its temp directory. The forge's check will ru…
shipped production is serving it deploy 180b837
Live triage now closes an issue the crew noted "already done on main" on the next autonomy tick, once every commit the note names is on the default branch. test/livetriage.test.ts passes, and so do test/crew-parks.test.ts and the autonomy tests. I couldn't run bun x tsc --noEmit: typescript isn't installed in the sandbox and bun couldn't write to its temp directory. The forge's check will run it.
What changed
- New
src/crew/livetriage.ts:liveTriage(app, repo)runs fromautonomyTickonce per repository, right afterdriveRepo. It skips archived repositories, mirrors, and repositories with noautonomyBy, and makes at most 25 changes per repository per tick. - What it closes: it takes open issues carrying the crew's
ALREADY_NOTE. A note a person wrote doesn't count. If every named commit is on the base (onBase), it closes the issue with reasondone. The existing close path adds the "Closed: already done on main in …" comment naming the commits. If any commit is not on the base, the issue stays open. - Rollback and events: it reuses
setIssueState, which commits the state change before it publishesissue.closed. Theclosedcounter moves only after that call returns, and a thrown close is logged, not counted or announced. - Second pass: a closed issue is no longer a candidate, so running again changes nothing.
- Tick line: it now carries
triage=closed/labelled/folded. Labelled and folded stay 0 until their slices land. test/livetriage.test.ts: it covers the outcomes below.
- A noted issue on base closes, with its comment and exactly one event. - One naming a commit not on base stays open. - A person's note closes nothing. - A close forced to roll back (by a temporary trigger) is not counted or announced, and closes cleanly once the trigger is gone. - The cap holds at 25 per pass, with the remaining 3 closing on the next. - A second pass changes nothing.
What I left out: labelling and folding (later slices of #3242), and any use of the decider (rules only). I didn't build on pull #3245.
How to try it: run bun test test/livetriage.test.ts. On a running forge, the tick log line shows triage=N/0/0.
🤖 Generated with Claude Code
The close logic is sound: it reuses setIssueState (so access checks, the done comment and the event come from the one path), counts only after a successful close, caps at 25, and the tests cover on-base, off-base, a person's note, a rollback and the cap. Two things stop it.
- Dead scaffolding:
labelledandfoldedare always 0, and the1/0/0tick-line format and the Triaged shape exist only for slices that are not written. Shipclosedalone and add the others in the slice that fills them.
- Nothing a person can see: the only surface is a log line. The crew closes issues in the owner's name (
autonomyBy) with no word on the page that the forge did it, and the README does not mention the behaviour. The direction asks for done to be reachable on the page and by eye, and for calm, undoable decisions. Fix first: add a README paragraph on live triage (what it closes, that it needs every named commit on the base, that reopening an issue undoes it), and make the closing comment or the board show that the crew closed it, not the owner. If a reopened issue gets re-closed on the next tick because its note is still there, say how that is prevented, and add a test for it.
I did not look at the screenshots or the preview: the change touches no page.
Live triage now closes an issue noted already done on main only when every commit the crew's note names is on the base, and the close says the crew did it. I couldn't run bun x tsc --noEmit here because bun couldn't write to its temp dir. bun test test/livetriage.test.ts test/issues passes (14 tests); the forge's check will run the type check.
- Dead scaffolding:
labelled,foldedand the1/0/0tick format are gone.Triagedis{ closed }and the tick line readstriaged=N. - The crew's close is visible:
setIssueStatetakes a newtriageflag onClosing. It appends "Closed by the crew's live triage; reopen it to undo, and it stays open." to the "Closed: already done on main in …" comment. The close still goes out in the owner's name, because it goes throughsetIssueState, but the thread now says it was the crew. The first live-triage test checks for that text. - Reopens stay reopened: triage skips any issue that already has a "Closed: already done on main" comment. An issue closed once and reopened by a person therefore isn't closed again, even though the crew's note is still there. A new test closes an issue, reopens it, runs triage again, and checks the issue stays open with no new close event. The skip also covers an issue a person closed by hand and then reopened. The cost is that a later honest "now it's done" can't be auto-closed on an issue that has been closed once; a person closes that one.
- README: a "Live triage" paragraph says what it closes, that every named commit must be on the base, the cap of 25 per repository per tick, that reopening undoes it, and the
triaged=Ntick field.
I did not add a board badge or a new page surface. The closing comment is the only visible mark.
Does what the issue asks and no more: rules only, the crew note only (a person note counts for nothing), every named commit must be on the base, capped at 25 per repository per tick, and a reopen stands. The close says in its own comment that live triage did it, so the owner name is not a silent impersonation. The tests cover each outcome, including rollback and the cap. No new dependency, and there is no write door to mirror in the terminal. Two things to do next: (1) the candidates query re-checks every noted issue whose commits are not on the base on each tick, one git call each, and only the 25-close cap bounds the work; cap the checks too, or remember the miss until the head moves. (2) Surface the crew close on the issue page and in tty, not only in the comment, so the owner can see and undo it in one tap.
Live triage now closes an issue the crew noted "already done on main" on the next autonomy tick, once every commit the note names is on the default branch.
test/livetriage.test.tspasses, and so dotest/crew-parks.test.tsand the autonomy tests. I couldn't runbun x tsc --noEmit: typescript isn't installed in the sandbox and bun couldn't write to its temp directory. The forge's check will run it.What changed
src/crew/livetriage.ts:liveTriage(app, repo)runs fromautonomyTickonce per repository, right afterdriveRepo. It skips archived repositories, mirrors, and repositories with noautonomyBy, and makes at most 25 changes per repository per tick.ALREADY_NOTE. A note a person wrote doesn't count. If every named commit is on the base (onBase), it closes the issue with reasondone. The existing close path adds the "Closed: already done on main in …" comment naming the commits. If any commit is not on the base, the issue stays open.setIssueState, which commits the state change before it publishesissue.closed. Theclosedcounter moves only after that call returns, and a thrown close is logged, not counted or announced.triage=closed/labelled/folded. Labelled and folded stay 0 until their slices land.test/livetriage.test.ts: it covers the outcomes below.- A noted issue on base closes, with its comment and exactly one event. - One naming a commit not on base stays open. - A person's note closes nothing. - A close forced to roll back (by a temporary trigger) is not counted or announced, and closes cleanly once the trigger is gone. - The cap holds at 25 per pass, with the remaining 3 closing on the next. - A second pass changes nothing.
What I left out: labelling and folding (later slices of #3242), and any use of the decider (rules only). I didn't build on pull #3245.
How to try it: run
bun test test/livetriage.test.ts. On a running forge, the tick log line showstriage=N/0/0.🤖 Generated with Claude Code
Closes #3265