assay  ·  who may say what, and when

Lifecycle

How a brief moves from idea to done — and why the most important rule is that the implementer stops before the finish line.


The five steps

todo → in-progress → implemented → verified → done
Table The five states — meaning and owner
StateMeaningWho
todo Authored, unclaimed, dependencies known. On the board, in Next-up if eligible. Author
in-progress A session owns it and is implementing. Moved from the queue to active work. Implementer
implemented The implementer finished and filled the Evidence section with their own run. Implementers STOP here. Implementer
verified A non-implementer re-ran the Verify table on merged main and filled Evidence (dated, with runner). Independent verifier
done Verified and carries the recorded review verdict. For human-gated briefs, a review entry naming a human is required. Verifier + reviewer

Why implemented is not done

An implementer verifying their own work is assaying their own metal. In multi-agent work this is not a philosophical concern — it is the primary failure mode. Every agent asked whether its task is done will say yes. A verifier drawn from the same fleet shares correlated failure modes with the implementer.

The lifecycle rule — implementers stop at implemented, a non-implementer advances to verified — makes self-grading structurally impossible. That extra step is friction, and the friction is the feature. It does not make the system uncorruptible, but it makes the corruption visible: a brief sitting at implemented with no verifier dispatched is a queue item, not a hidden assumption.

A sequence of states is only half of a separation of powers; the other half is assigning each transition to somebody who cannot also perform the one before it. That assignment is the desk model — five standing roles, each defined by what it may not do. See Desk roles.


Evidence and review

Verified and Reviewed cells take dated, attributed entries (2026-07-08 model-verifier, human:alex), never a bare checkmark. An undated tick is unattributable and unauditable. A dated, attributed entry works like a hallmark: it records who struck it and when.

The two checks are distinct:

  • Verify table proves function: "does it work?" Re-running the brief's Verify commands on merged mainline.
  • Review proves quality: "is it well-built?" A code, structure, and security pass. Neither substitutes for the other.

Not every entry in those cells may come from a model. Attribution carries a risk-keyed floor: a brief with any risk answer set, or a human gate, will not pass lint at verified or done with an economy-tier runner recorded against it — and for the highest-risk work the floor is a named human rather than a stronger model. Which class of actor may sign which gate is set out on Model tiering.


The execution witness

There is a gap in everything above, and it is worth naming before describing what closes part of it. An Evidence section is prose written by the session that ran the checks. It asserts that the commands were run and what they returned. Nothing in that assertion is distinguishable from a session that ran nothing and wrote a plausible table.

So the toolkit can run the Verify table itself. It executes each row's command in a fresh subshell at the repository root and appends one witness row per Verify row:

| # | Command        | Result    | Output              | Date       | Runner                    |
| 1 | `go test ./...` | pass exit=0 | sha256:6f1a0b3c9d22 | 2026-08-13 | human:alex @ b988d175ab12 |

Three things about that row matter more than its shape. The result is three-state: a row can pass, fail, or come back could-not-run — a command that was not found, an unsubstituted placeholder, a timeout. Could-not-run is recorded as itself, never folded into either of the other two, because a check that did not execute reporting the same thing as a check that passed is the failure mode the whole discipline is built against. The output is hashed, so a claim about what a command printed is pinned to something reproducible rather than to a summary. And the runner and commit are recorded together, so the row says what was run, against what, by whom.

A closed brief whose Evidence claims the rows were run but carries no witness draws a notice on the board. It is deliberately a notice rather than a failure: a brief closed before the mechanism existed cannot have a witness, and hand-writing witnesses into closed briefs to clear the flag would manufacture exactly the evidence the witness exists to replace.


STATUS.md: the single-writer rule

STATUS.md at the repo root is generated from the stream READMEs and registers — never hand-edited. It has exactly one writer: main's CI, which regenerates and commits it on every push that touches a source.

  • Branches never commit STATUS.md. PR CI runs --lint mode only and blocks any PR whose diff touches STATUS.md.
  • One writer eliminates the conflict class entirely. A generated file committed on branches turns every concurrent PR into a merge conflict.
  • Regenerate locally freely; never commit on a branch. On a merge conflict, take either side and rerun the generator — never hand-merge a generated file.

Next-up: the cross-stream queue

The generator computes a Next-up batch so a session does not default to "the next brief in my stream" — the rabbit-hole reflex the system exists to prevent. Next-up weighs:

  • Priority + staleness — higher-priority and aged streams rise.
  • A 2-per-stream cap — no single stream floods the batch.
  • Findings exclusion — a brief with an unresolved finding against it is held out.

A known defect: the staleness score rewards neglect regardless of why a stream aged. A value/effort term is a candidate knob — the board is a heuristic scheduler, not an oracle.