Follow-on to #205. That ticket gives the supervisor a reader over generic platform records. This one makes the coding domain write enough into those records for the reader to see it — the other half of "the domain writes into a generic record; the supervisor reads platform records."
No supervision-side change is needed for any of this, which is the evidence the boundary is right.
A. A human-driven coding session is invisible
Starting a session from the Coding tab writes only coding_sessions. It creates no board card and no loop run, so a Lead cannot answer "is anyone working in the API repo right now" — the most common case, and half of what the hardcoded Overseer assembles per repo (routes/coding.ts:1122-1131).
Fix: lib/coding-board.ts (new, pure, mirroring lib/delegation.ts) emits a generic record —
codingSessionTaskRecord({sessionId, repoName, engine, status, now}) → id csess-${sessionId}, type coding.session, title Coding: ${repoName}. Precedent three lines away: routes/coding.ts:760 already writes an engine.signin card via mirrorRuntimeTask.
No column declaration needed — coder-repo declares no boardColumns, so defaultBoardColumns(["coding"]) already maps running→"Running" and completed→"Done".
The trap, and the reason this ticket exists separately. A session leaves active in four places, and only one is the end route:
routes/coding.ts:1336 — endSessionlib/coding-store.ts:403 — inside reconcileOrphanedSessions, the reapersuspendSessionsFromOtherNodes (routes/instances.ts:328) — suspends rather than endsCodingSessionWorkflow's finally — raw UPDATE coding_sessions, not via endSession
Writing the card at create and clearing it only at (1) strands a permanently "running" card on three paths — the exact failure mode this whole feature exists to remove, and the same shape as the two stranded-row bugs already memorialised in coding-session.ts:122 and :158.
Recommended: make endSession the single choke point (have the workflow call it instead of raw SQL) and mirror the card from createSession + endSession. mirrorRuntimeTask upserts on id, so re-writes are idempotent.
Note this also puts a live session on the Repo Coder's own board for the human. Confirmed wanted — a live session is exactly what belongs on a work board.
B. The Pilot never reports mid-run progress
AgentLoopWorkflow calls recordIteration per iteration (workflows/agent-loop.ts:144). CodingSessionWorkflow does not, so check_delegation and subordinate_status both report iteration: 0 for a run that has taken a dozen steps — the supervisor's only progress signal, permanently reading zero.
Fix: hoist let pilotSteps = 0 above closeDelegation, increment on the "action" branch of the existing onEvent dep, and call recordIteration when loopRunId is set. runCodingLoop already emits exactly one "action" per step (lib/coding-loop.ts:118), so no extra durable steps.
Compute the increment outsidestep.do — a retried step re-runs its body, and ++ inside would double-count.
A second bug rides on this.CodingSessionWorkflow runs runCodingLoop in up to 12 rounds, and runCodingLoop restarts its step counter at 0 each round. So today's terminal recordIteration(env, runId, outcome.steps) records the last round's count, not the cumulative one — it understates even at the end. Fix with Math.max(pilotSteps, outcome.steps ?? 0).
Follow-on to #205. That ticket gives the supervisor a reader over generic platform records. This one makes the coding domain write enough into those records for the reader to see it — the other half of "the domain writes into a generic record; the supervisor reads platform records."
No supervision-side change is needed for any of this, which is the evidence the boundary is right.
A. A human-driven coding session is invisible
Starting a session from the Coding tab writes only
coding_sessions. It creates no board card and no loop run, so a Lead cannot answer "is anyone working in the API repo right now" — the most common case, and half of what the hardcoded Overseer assembles per repo (routes/coding.ts:1122-1131).Fix:
lib/coding-board.ts(new, pure, mirroringlib/delegation.ts) emits a generic record —codingSessionTaskRecord({sessionId, repoName, engine, status, now})→ idcsess-${sessionId}, typecoding.session, titleCoding: ${repoName}. Precedent three lines away:routes/coding.ts:760already writes anengine.signincard viamirrorRuntimeTask.No column declaration needed —
coder-repodeclares noboardColumns, sodefaultBoardColumns(["coding"])already mapsrunning→"Running" andcompleted→"Done".The trap, and the reason this ticket exists separately. A session leaves
activein four places, and only one is the end route:routes/coding.ts:1336—endSessionlib/coding-store.ts:403— insidereconcileOrphanedSessions, the reapersuspendSessionsFromOtherNodes(routes/instances.ts:328) — suspends rather than endsCodingSessionWorkflow'sfinally— rawUPDATE coding_sessions, not viaendSessionWriting the card at create and clearing it only at (1) strands a permanently "running" card on three paths — the exact failure mode this whole feature exists to remove, and the same shape as the two stranded-row bugs already memorialised in
coding-session.ts:122and:158.Recommended: make
endSessionthe single choke point (have the workflow call it instead of raw SQL) and mirror the card fromcreateSession+endSession.mirrorRuntimeTaskupserts on id, so re-writes are idempotent.Note this also puts a live session on the Repo Coder's own board for the human. Confirmed wanted — a live session is exactly what belongs on a work board.
B. The Pilot never reports mid-run progress
AgentLoopWorkflowcallsrecordIterationper iteration (workflows/agent-loop.ts:144).CodingSessionWorkflowdoes not, socheck_delegationandsubordinate_statusboth reportiteration: 0for a run that has taken a dozen steps — the supervisor's only progress signal, permanently reading zero.Fix: hoist
let pilotSteps = 0abovecloseDelegation, increment on the"action"branch of the existingonEventdep, and callrecordIterationwhenloopRunIdis set.runCodingLoopalready emits exactly one"action"per step (lib/coding-loop.ts:118), so no extra durable steps.Compute the increment outside
step.do— a retried step re-runs its body, and++inside would double-count.A second bug rides on this.
CodingSessionWorkflowrunsrunCodingLoopin up to 12 rounds, andrunCodingLooprestarts itsstepcounter at 0 each round. So today's terminalrecordIteration(env, runId, outcome.steps)records the last round's count, not the cumulative one — it understates even at the end. Fix withMath.max(pilotSteps, outcome.steps ?? 0).