0025 — The flow runs without a human: green merges itself, the fixer merges, and the driver assigns

The headline, in his words

"I'm expected to do nothing throughout the driver flow."

That sentence is the acceptance test for everything below. Any design whose normal path stops and asks him has failed it. The exception is about 5% — a genuinely important decision — and the explicit instruction is that we DO NOT BUILD AROUND THAT 5%. A queue of parked questions is now a design failure, not a healthy backlog; two were parked when this was written (smith-decision-b89238852, b89235012), and under this posture that is the defect, not the process.

The decisions

1. Auto-merge. Every PR, every repo. Nothing holds for a human.

When CI is green and the cloud reviewer says 🟢, it merges. No Slack ask, no days-long wait, no human ✅ path.

2. The fixer has full authority, and its scope is the RED

"It could merge a PR and everything. It could do anything it needs to do just to make sure that everything is clean."

3. The driver is a COORDINATOR. It orchestrates; it does not act.

"I would give it a dock. The dock is gonna have items… the driver is just gonna say, okay, these action items, I'm gonna go ahead and give them to sub-agents… four sub-agents can tackle four things if they don't overlap. But if they do overlap, maybe the driver is gonna say, okay, we're gonna go one at a time… The driver is really driving the orchestration. They're not driving the actions. They're driving the setup with the sub-agents. They're really like a coordinator."

4. Work is ASSIGNED, never self-claimed — .claims becomes .assigned

This is a MODEL change, not a rename, and it is why the word moves at all. claimed = the driver helps itself off the board. assigned = it works what it is given. Today's driver drifted its own goal to "whatever 14 merged PRs prove" while the board sat at 48%; a driver that cannot pick its own work is the fix. The word carries the model, so the word changes.

There are two assignment levels and one word, deliberately:

⚠️ Collision, accepted with eyes open. assign is 983 hits in propflowai's domain layer — assignedVendorCompanyId (534), assignment (301), assignee (20) — vendors assigned to work orders. This is weaker than the lease collision ADR-0023 refused: that one collided THREE ways inside the harness itself, in the same prose. This one is cross-repo and cross-language (agent-smith Python vs propflowai TypeScript), no shared symbol table. THE RULE TO CARRY: assigned in the harness always means ACTION ITEMS, never vendors. If harness prose ever says "assigned" about a vendor, it is wrong.

Words tested and rejected, so nobody re-derives them: lease (a product entity

5. /driver mints a FRESH workflow, and it starts from a SETUP TABLE

6. DONE is a PR that addresses the point, and the SUB-AGENT self-certifies

"If there's a PR then the sub-agent can mark complete… if the sub-agent wants to validate on prod they're encouraged to but not required to because in some cases we probably can't."

7. The decider answers ~95%, and the test is IN PLAN + REVERSIBLE

8. Specialist housing: SEVEN activities, ONE agent

Astra's written test (receipt f71df4d01): bounded contract → Temporal ACTIVITY; investigative ownership → AGENT. Cross-rung integration by SIGNALS, never activity calls (ADR-0003).

housing specialists
activity decider · nudger · cleaner · optimizer · finisher · slacker · updater
agent fixer

⚠️ updater moved, and Astra's own rule is what moved it. Astra made updater an AGENT because "updater requires judgment" — full vs partial closure. Gera has now removed that judgment: "the updater should be just focused on passing information into the docs… it should be self-determined." The sub-agent decides; the updater only writes it down. With the judgment gone the updater has a bounded contract, so under Astra's own test it is an activity. The record is kept this way round on purpose: the test survived, the answer changed.

Liveness must not lie. It must never report a working specialist as never-run — specialists.json says everRun:false for nudge and fable-decide while fable-decide has 336 receipts — and must never silently drop an unknown name: a well-formed optimizer2 line is dropped at specialists-snapshot:50. Both are ADR-0009 failures: a signal that reports healthy-but-blind is worse than one that fails.

9. Names — final, and cheap because everything was stopped first

mechanism old new
a driver session driving one task to a criterion OperatorTaskWorkflow + DriverTaskWorkflow DriverWorkflow
the action items a driver has been given .claims .assigned
one execution per job, however many doors it arrives through SmithWorkClaimWorkflow SingleRunnerWorkflow
drives one PR to merge SmithPrDriveWorkflow PrDriveWorkflow (now merges)
a PR approval held for a human SmithApprovalWorkflow DELETED — the human wait is removed and the machine gate folds into PrDriveWorkflow
a parked human decision SmithDecisionBlockWorkflow AnswerWaitWorkflow
a pane stuck on a dialog nobody is answering SmithPromptResponderWorkflow StuckPaneWorkflow
per-item generation authority SmithRowLeaseWorkflow PENDING Fable — Astra: keep it, a RETRY is a second writer even with one driver

Drop the Smith prefix throughout. It named the HOST, not the user, and was already inconsistent — 10 prefixed types, 4 unprefixed, one namespace.

Why this is a rename in place and not an additive cutover. ADR-0021 §5 requires an additive cutover for any workflow rename: register the new type alongside the old, keep the old registered until a live query returns zero running executions. That rule exists only to protect running executionsworker.py says it plainly: the legacy type must stay registered for as long as one execution still carries it in its history, because a worker missing that name fails the workflow task RETRYABLY, so nothing surfaces to anyone. Stop everything first and the constraint disappears, which is why the reset is sequenced stop-then-rename rather than the other way round: zero running executions means rename in place and delete the old names outright — no dual registration, no drain period, no migration to maintain.

⚠️ THE CONDITION, NOT A DATE — and this ADR does not claim it has been met. ADR-0021 decision 5 says the old name retires "only when a live query returns zero running executions of that type — not on a guess, and not on a date", and that rule survives here unchanged. PLAN.md records 72 running executions at ~14:40 on 2026-09-12 and the intent to end them; the rename lands when the query below reads 0, and not before.

temporal workflow count --query "ExecutionStatus = 'Running'"

Written as a command because a retirement condition nobody can execute is a fact somebody has to remember.

What this supersedes — precisely, and nothing more

Per DESIGN.md §8 and ADR-0023 decision 6: ADRs are not rewritten. Each entry below is marked superseded on its own Status or Date line, appending no line, so every line-number citation into those files stays true — PR #141's precedent.

record clause superseded what stands
ADR-0012 "Can count Rung 5"shipped derived only from a merged PR AND a prod_evidence permalink; a merged-but-untested fix does not count. Decision 6 above replaces the gate. Everything else: the scheduled pipeline, the review merging its own PRs, and the merge_guard. See the open question below — the guard is a restart interlock, not an approval gate, and is NOT deleted here.
ADR-0021 §5's additive cutover target DriverTaskWorkflow, and its retirement query. Decision 9 renames in place to DriverWorkflow because zero executions are running. Decisions 1, 2, 3, 4, 6, 7 and the 2026-09-11 amendment. The role is still the Driver; /operator is still a live door; the product's operator still does not move.
ADR-0023 Decision 4's "the harness does not say lease for a work claim — it says CLAIM", for the DRIVER'S work items only. Decision 4 above makes those .assigned. Decisions 1, 2, 3, 5, 6, 7 and 8. The yielding rule, "action item", the row_lease split, and the interface lags are untouched — and SmithRowLeaseWorkflow is still PENDING, now on Fable.
propflow-docs CLAUDE.md §A tracker is GENERATED, ARTIFACT-STYLE.md §Trackers, and bin/refresh-tracker (propflow-docs #47, p6-merged-is-not-shipped, 2026-09-10) "Merged is not shipped" as a GATE. That rule is why the board reads 27 shipped against 114 merged-but-never-exercised; under decision 6 those 114 are done. The standard is superseded, NOT deleted. It stays as the record of why the distinction was drawn, and prod_evidence stays as the STRONGER grade a sub-agent is encouraged to reach. The prod_evidence key itself is an interface (ADR-0023 §6) and does not move.

Not superseded, and reinforced: ADR-0003 (the fixer announces by a shared-surface write, never N messages), ADR-0004 (this ADR exists because of it), ADR-0009 (the liveness lies above are failures under it), ADR-0015 (one owner per red — decision 2 lets that owner finish, it does not add a second), ADR-0019 (the mechanism that has to carry the 95%).

Open, and named rather than papered over

  1. ADR-0012's merge_guard versus decision 1. The guard refuses a merge that would restart the worker while a person is mid-turn with Smith. It is not an approval gate and decision 1 does not name it, so it is left standing here — but "every PR merges on green" and "some merges wait on a live human turn" are two sentences that will be read together by someone. This needs an explicit ruling, not an inference.
  2. scripts/backfill-vendor-identity-claims.ts carries a written prohibition in its own header"A HUMAN RUNS --mode=apply, NEVER AN AGENT." It predates this posture and has not been reconciled with it. Under decision 7's test it plausibly survives (customer data, irreversible → human), but do not treat the new posture as having silently overridden a rule written into code about customer data. Decide it explicitly.
  3. Two ADRs are numbered 0014 and two are numbered 0024. Both 0024s are cited by SYSTEMS.md under the same label. Renumbering would break every existing citation, so this is recorded, not fixed.

Consequences