← all pages

The factory running · 01

Triage, and the morning report

Delegate a Backlog ticket and Symphony triages it within the minute, attempting the one thing that reveals what the ticket actually needs: writing the ticket out in full. The human wakes up to a one-glance board report, not a pile.

Draft-first, not score-first

Most triage classifies a ticket as written: read it, guess its size, guess its risk, file it. Ours classifies by drafting. The session always attempts the complete ticket — what to build from the user's side, the evidence a human will accept, the plan and the facts it rests on, the blockers — and the route falls out of where the draft fails. Entanglement between decisions only shows up when you try to write their option lists; scoring never finds it.

The claim is verified first: the bug reproduced, or the behaviour confirmed absent, so the ticket is triaged as understood rather than as written. Then every open question is classified by who holds the answer:

The discipline: a question answerable from documentation that reaches a human is a triage bug — the maintainer's attention was spent to save the agent a lookup.

Has this been asked before?

Before drafting, the session searches the tracker for the ticket's concept and not its wording — the glossary term, the synonyms the glossary avoids, the area of code — across every state, closed ones included, and reads the decision records for the area. Where it looked goes in the comment. What it finds can end the triage in one of three places, and they are deliberately three rather than one, so a later search can tell a deliberate no from a never-was:

What the search findsHow the ticket closes
An open ticket asking for the same thingDuplicate of the survivor. The older ticket wins; anything only the newer one said moves onto it as a comment. The survivor is triaged only when asked.
The ask was declined on purpose, on a ticket or in a decision record's rejected alternativesNot the session's call. It routes needs-decision with one card — the earlier no and its reason, A) still no, B) reconsider. "Still no" marks this ticket a duplicate of the declined one; "reconsider" resumes the draft with the old reason cited as a fact.
A closed ticket already did it, or found it invalidDone or Canceled, with the evidence in the closing comment.

Not Planned is the record of what the project chose not to do. One ticket per declined ask, the reason in its closing comment written to outlive the moment — what was asked, why not, and what would change the answer — and later tickets asking the same thing marked duplicates of it, so one ticket accretes the whole history of the ask. "Too busy" is a deferral, not a decline; that ticket stays open and untriaged.

Four routes, rendered as columns

A route is a claim about what the ticket waits for — never about what anyone is currently doing to it. On Redkale's board each route is a state, so the board itself shows what every ticket awaits; no route is ever a label. Untriaged work sits in Backlog.

RouteThe ticket waits forWhere it lands
ready-for-agentNothing. An AFK session can start from the ticket as drafted.Todo, delegation kept — implementation follows unattended
ready-for-humanHuman execution. The draft is complete, but a step of it needs a credential, account or device the unattended runner does not hold.Todo, handed back — delegation removed, creator tagged
needs-decisionOne reply. Every open blank fits a card the maintainer can answer from their phone.Needs Decision, with the card
needs-grillingA session. The open questions are entangled or open-form; the agenda seeds the grilling.Needs Grilling, with the agenda

Where a route lands, and which transition it performs, is the tracker's business and not the skill's. When the runner needs none of the human-only steps to build the thing, that step is split into a ticket of its own so the build still runs unattended.

Delegating in Backlog is consent for the whole ride: a ticket that triages clean proceeds through implementation to Human Review, where the evidence contract is the gate. Otherwise the ticket advances past its route only on a reply, a session, or an explicit directive — and resuming is one drag: answer the card or hold the session, then move it to Backlog (re-triage reads the reply) or straight to Todo. Ties break toward grilling: a wrongly-carded ticket gets built confidently wrong, which costs more than a session.

The closed-form test

A blank in the draft qualifies for a decision card only if all four hold. Fail any one and the ticket goes to grilling instead:

01Enumerable.You can list 2–4 options and would execute any of them verbatim, happily. Prose options for a visual question fail this; a variants prototype makes them pass.
02Independent.The answer leaves every other blank's options unchanged.
03Few.At most two blanks on the ticket. More is a conversation wearing a form's clothes.
04Recoverable.A wrong pick is cheap to reverse. Schema migrations, public API shapes, pricing go to grilling even as a single clean question — the point is stress-testing the reasoning, not picking.

Prototypes, during triage

A visual blank — "which direction should this UI take" — can never be honestly enumerated in prose. So the triage session builds a throwaway variants prototype on the spot: one self-contained HTML file, two to four distinct directions behind a control bar. The blank becomes genuinely closed-form, and the decision card links the prototype as its options. Behavioural tangles get a clickable logic walkthrough attached to the grilling agenda as session material. Both are disposable by construction: zero setup, state in memory, dead once the verdict is recorded — and yes, the unattended run builds them too: the prototype exists precisely because nobody with taste is present, so taste can be exercised later in one reply.

Where the words go

The draft — and later the spec that supersedes it — lives in the effort's artefact: one HTML page per effort, created lazily the first time there is something long-form to write, and linked from the ticket. The ticket description stays its author's; the comment stays a glance, with only the decision card or the grilling agenda inline, because those are written to be answered from a phone. Every comment the session posts opens with "Generated by AI during triage." — a stranger reading the tracker always knows which voice is speaking.

The morning report

Every weekday morning at 07:30 London time, a scheduler on an always-on machine fires one script. It is read-only: one query over the full board, one Slack message — one line per ticket with its link, grouped by what it awaits (Awaiting you / In flight / Backlog, untriaged), with tickets quiet for three days flagged. It launches no sessions and writes nothing to the tracker, so it photographs outcomes rather than promising them. Reply in the thread with an answer for a ticket and the team agent does the drag for you: your reply lands on the ticket, the ticket returns to Backlog, and the triage lane reads it.

The principle underneath: runners launch sessions, reporters read state. The report and the triage that feeds it share no machinery — which is why the report can never claim something happened that didn't.