0012 — The Smith review runs itself every morning, and a merge refuses under a person
- Status: Proposed (flips to Accepted with the first morning that records a checkpoint) ⚠️ PARTIALLY SUPERSEDED 2026-09-12 by ADR-0025: the Can count Rung 5 clause below —
shippedderived only from a merged PR AND aprod_evidencepermalink, a merged-but-untested fix not counting — is retired AS A GATE. The bar is now a PR that addresses the point plus the sub-agent's own completion naming that PR; prod evidence survives as the stronger grade a sub-agent is encouraged to reach, and as the record of why the distinction was drawn. Everything else here stands, includingmerge_guard, which is a restart interlock and not an approval gate. (Appended toStatuson purpose: this adds NO line, so every line-number citation into this file stays true.) ⚠️ AMENDED 2026-10-19 — ON A TRACKER BOARD, MERGED COUNTS AS DONE. The Can count Rung 5 clause's last surviving sense, that a merged-but-untested fix "does not count", is reversed for the count: Gera decided that merged and shipped are both done, and every tracker's hero number is now (shipped + merged) / live (propflow-docs3d6026b65,a796a3891,3e5efccff). The STATUS is still derived, and still two:bin/refresh-trackertellsmergedfromshippedexactly as before, and a merged row with noprod_evidencekeeps one line saying so in its expand. See Amendment 2026-10-19 at the foot. (Appended toStatuson purpose: this adds NO line, so every line-number citation into this file stays true.) - Date: 2026-09-07
- Deciders: Gera, in the 2026-09-07 review read-back — "it should run daily
in the morning queue, and also drive itself to merge" — and the session that
built it (agent-smith PR
smith/daily-self-review). Written at decision time because ADR-0004 says a decision that changes how systems relate is not done until it is; this one changes how the review relates to the morning queue, to the worker, and to every other conversation Smith is having.
What changes
Until today the smith-review skill — the day's pass over everything Smith
said and did, ending in fixes — ran only when a human typed /smith-review.
Its own preamble calls it "the inventory that a future autonomous self-repair
engine will run." Three things become true at once:
- The review is a scheduled pipeline.
MorningQueueWorkflow's last step,smith-review, runsagent_smith.self_review run, which reads the checkpoint store for the window (since the last checkpoint; a day if there is none), refuses to run twice in a day, posts the brief as a#agent-smiththread and starts a durableSmithTaskWorkflowcarrying it. The brain runs the skill inside that container, onMODEL_HIGH, and closes it withsmith-task verdict— Rung 6's receipt, not a merge. - The review may merge its own PRs. That is the instruction. Rung 0 (never under an agent still pushing) and Rungs 1–6 (merged-verified, deployed, tooling re-run, live test, proved in prod in the channel, checkpoint) still bind; what is gone is the human deciding the moment.
- A merge that would restart the worker refuses while a person is mid-turn
with Smith. New:
live_runs(everyclaude -pturn registers itself by pid while it runs) andmerge_guard(refuses a merge into a restart repo while a human-facing turn is live). It is consulted at BOTH merge sites — the brain's owngh pr mergethrough the command-gate hook, and the human-✅ approval path'smerge_pr_activity— and it fails CLOSED when it cannot see the registry.
Why a task container and not a turn, and why not a new scheduler
A brain turn has a two-hour wall and no memory of why it started once it ends.
The review opens PRs, waits on CI, merges, restarts the very worker it runs
on, and must then come back and prove each fix in prod. SmithTaskWorkflow is
the structure agent-smith already has for "a task that outlives a turn": it
restates goal and acceptance on every wake, re-wakes the brain when the
thread's PR evidence changes phase, and closes DONE only on a receipt. Its
workflow id is derived from the goal, and the goal names the date — so a
second dispatch the same morning collides into "already driving" instead of a
second review. No scheduler was invented: the step is a NightJobSpec run
through the same run_night_job_activity every nightly job uses.
How it relates to the ladder
- ADR-0002 — agent↔agent is SendMessage, tmux is hosting. Nothing here
attaches to a pane. The container wakes turns through
dispatcher.dispatch, the door a Slack message takes; fixes fan out as the brain's own subagents. - ADR-0003 — rungs integrate by signals, never calls. The queue does not await the review; it dispatches and reads back nothing. What the review produces are files other rungs read: the dispatch log (this system's ignition), the checkpoint store's mtime (its end), and the tracker's JSON block on docs.propflowai.co (its answer). The merge guard is likewise a file read — a marker per running turn — not a call into the worker.
- ADR-0009 — a signal must fail when the system fails. The dispatch-log pattern is written ONLY on a real dispatch (a skip or a failed launch writes a different word); the checkpoint mtime moves ONLY when Rung 6 records. A green pair means "the queue started a review and a review reached its end", and nothing more — the N/M on the page is the verdict.
- ADR-0010 — a finished session leaves by its own exit. The live-run
marker is removed in the runner's
finally, and a marker whose pid is gone is stale, reported, and never counted: the guard never becomes a reason to kill anything, and a dead worker cannot pin every merge shut.
What the guard means for the graceful drain (agent-smith #422)
#422 (merged 2026-09-07) makes the worker drain in-flight activities on
SIGTERM instead of killing them — deploys relaunch within ~4s of a merge via
SIGTERM+wait, not kickstart -k. That makes a restart survivable; this makes the review not the thing
that asked for one while a person is waiting. They are two lines, not one:
the drain protects a turn from a restart that happens; the guard stops a
Smith-initiated merge from scheduling that restart under a person in the
first place. Gera's phrasing — "the drain makes it safe, not polite" — is
the reason both exist.
What the first morning can and cannot do
- Can: dispatch, run the sweep and triage, write rows, open PRs, merge its own green PRs when no person is mid-turn, record the checkpoint, refresh the tracker, post N/M. Every one of these is a tool the brain already has.
- Can count Rung 5: propflow-docs #47 (
p6-merged-is-not-shipped) is live, sobin/refresh-trackerderivesshippedonly from a merged PR AND aprod_evidencepermalink — the permalink the brief tells the brain to post in the thread and put on the row. A merged-but-untested fix rendersmerged · untestedand does not count. A fix the brain cannot trigger on demand is carried UNVERIFIED rather than closed. - Cannot see: a human joining the review's OWN thread. The guard excludes the asking turn by workflow id, and a human message coalesced into a running turn keeps that turn's machine sender. It never hides a stranger's turn; it can fail to notice a colleague in this one. Named here rather than papered.
Consequences
The catalog gains smith-daily-review, proposed, with the two signals
above; it flips to active after the first morning whose thread carries a
checkpoint. The review's #agent-smith receipt becomes a daily thread, and
the phase doc's hero number is expected to go DOWN on mornings the sweep
finds more than it fixes — which the skill's §0 says is the count getting
more honest, not the work regressing.
Amendment 2026-10-19 — on a tracker board, merged counts as done
What changed. Gera, 2026-10-19: "for status it should just say like
shipped, merged and in flight, because when it says not proven etc it
overrides the item", and "as long as we've shipped it we can call it done,
and that should be the case also for the template." So a merged row is done.
The Can count Rung 5 clause above said a merged-but-untested fix renders
merged · untested and "does not count"; on every tracker board it now
counts. ADR-0025's
supersession table had already retired that clause as a GATE ("under
decision 6 those 114 are done"); the hero kept counting shipped only until
this change, so the board read lower than the doctrine. This amendment closes
that gap; ADR-0025's row needs no edit.
What shipped (propflow-docs, all 2026-10-19):
3d6026b65: the hero is (shipped + merged) / live, equal to the two tiles beside it, and the bars count the same way. The merged pill and tile read one word, "Merged"; the· partial/· assembled/· commit evidencetags leave the status cell (still in the DOM and in the expanded detail). Template,new-tracker,ARTIFACT-STYLE.md§ Trackers and therefresh-trackerheader carry the rule.a796a3891:bin/restamp-done-counts.mjsrestamped the renderer of every tracker page (111), with each page's data block checked byte-identical.3e5efccff: the last doctrine lines that still described the old hero.
What did not change.
- The status is still derived, and there are still two of it.
bin/refresh-trackertellsmergedfromshippedexactly as propflow-docs #47 made it:shippedneeds a merged PR AND aprod_evidencepermalink. A merged row with noprod_evidencekeeps one small line in its expand saying so. "Done" is the union; the two states are not merged into one. - The strict figure survives.
board-countand the finisher'sprovenstill count shipped only, so the gap between "done" and "proven in prod" is still one read away. Prod evidence remains the stronger grade a sub-agent is encouraged to reach, as the 2026-09-12 note above already said. - A fix the brain cannot trigger on demand is still carried UNVERIFIED in the review's own thread. This amendment changes what a tracker COUNTS, not what the review is allowed to call verified.
Consequence for this ADR's own prediction. Consequences expected the hero
to go DOWN on mornings the sweep finds more than it fixes. That still holds,
but a merge now moves the hero on the day it lands, not on the day prod
evidence arrives, so the number rises sooner and the merged-versus-shipped gap
is read from the tiles and board-count, not from the hero.