✓ landed 2026-08-12

Landed — one call, six nodes, three backends

reckon crew dispatch ran six nodes across two external harnesses and the calling harness, with no change to the calling instruction and no harness named anywhere an agent reads. All eleven declared measures banked: one node definition reached the same 36-key routing result on two backends; three commits landed scoped clean; a worker's unprompted four-field NEEDS-HELP: report was answered and resumed in the same session, which restated its prior measurements without re-running anything; budget read utilisation 1.02% on one backend and an explicit unknown on the other. 1,598 tests pass, 103 of them new. Two live defects were found and fixed; one constructed measurement did not fire and is recorded as a negative result. Full record: landed evidence (commits a927c9c, 8a44624, 0ae4167, d3a7617, 2224770).

§1 — Why this exists

Reckon can coordinate a sprint but cannot dispatch a worker that is not an in-process subagent of the orchestrator's own harness. This plan adds that path, and does so through a single dispatch instruction that names no harness, model, effort level or sandbox flag. The agent states what it wants; reckon resolves how. Per-backend flag translation is compiled code the agent never reads, which is what makes drift between execution paths structurally impossible to express.

The seam design, the single permitted branch and the verified per-backend matrix are recorded in Agent Fleet Orchestration §2–§3. Read that before implementing.

✓ landed §2 — The task-definition contract

Landed as crew.validate_node plus a pre-dispatch checklist in the skill. A live rejection named five failing properties at exit 2; 18 tests cover the seven, including the three the measure names. Independently verifiable gained a real test on implementation — the manifest path must be absolute, because a relative one resolves against the worker's own worktree and makes a delivered node look silent. Contract text now lives in references/worker-protocol.md; the table below is the design record. § contract

This is the highest-value deliverable in the sprint, because a worker that thrashes is almost always executing a malformed task. The contract makes well-formedness checkable before dispatch, so the escape hatch handles only the genuine residual.

A node is dispatchable only when all seven hold:

PropertyTest
Single goal The goal states one deliverable. If it joins two with "and", it is two nodes.
Fully specified Every input is already in the live plan or in the node's fences. Nothing requires the worker to infer intent.
Demonstrable Done-when is a measure that emits evidence — a named test, a recorded command output, a numeric result against a stated bound. A subjective adjective ("clean", "robust", "better") fails this test.
Closed No decision from outside the node is needed. A required-but-unlocked decision means the node is not ready; a decision node precedes it.
Scoped Exclusive write paths are enumerated, and nothing outside them is needed. No concurrent node shares a path.
Bounded The work fits the resolved time budget. If it cannot, split it — a budget is not a target to overrun.
Independently verifiable The orchestrator can audit completion from the manifest, git show --stat and the gate evidence, without reading the implementation.

Implement this as an explicit pre-dispatch checklist in the skill and as a validation in reckon crew dispatch that refuses a node missing a goal, a measurable done-when, or a write scope. A node that fails is reshaped or split — never dispatched with the hope that the worker will work it out.

✓ landed §3 — Deliverables

All eight landed: reckon/_backends.py (translation, keyed to a backend's command, verified against four event streams recorded from live runs), reckon crew dispatch/attach — plus observe, resume, list and stop, without which the measures are unreachable — references/worker-protocol.md, the structured escape hatch, the four-axis reflex with a validator that refuses a non-quantitative completion, continuation at three altitudes, budget capture with an explicit unknown state, and the skill upgrade with the gate-fence rule authored solely here. § dispatch, § divergences

The launch matrix as code. reckon/_backends.py translates a resolved flight config plus a node into a concrete invocation for each backend: argument construction, session-id capture from the backend's machine-readable stream, resume form, terminal-event recognition, and final-message retrieval. Unit-tested per backend against recorded event fixtures, with no live process required.

The uniform CLI primitive. reckon crew dispatch --project P --plan L --section S --role R --node N and reckon crew attach --run R --task T. Dispatch validates the node against §2, resolves flight config, creates the detached worktree through the existing fleet script, composes the fenced prompt, and then branches once on launch: kind — spawning the process and returning a run id for a cli backend, or returning a dispatch directive for an in-harness backend which the agent binds back with attach. Atomic: it performs the whole operation or none of it. JSON on stdout.

The harness-agnostic worker contract. skills/reckon-ship/references/worker-protocol.md owns the task-definition contract, the four fences, the compact manifest shape, and the escape hatch — everything true of a worker regardless of backend. Having one home for these is what stops them drifting between backends. The fence set is scope, time, evidence and delivery; delivery is a fence rather than a convention because a background worker can complete its work and end its turn without delivering a report, at which point the node looks failed when it is not.

The escape hatch. A worker stops and emits a report opening with NEEDS-HELP: and four required fields: tried: the attempt and its observable result, options: two or three concrete paths, leaning: which and why, cost-if-wrong: what must be redone. Named triggers: the same command failed twice with different fixes attempted; a decision the plan does not settle is required; the necessary change exceeds the write scope; the gate's evidence cannot be produced with the available tools or data; or the budget is spent with the gate still closed. The orchestrator answers by default, escalates only scope trade-offs and irreversible choices, and resumes the same session — which is why session reuse is load-bearing rather than an optimisation.

The summary reflex. Four axes — what, why, how, when — emitted at dispatch, at completion, and when micro-planning the next step, one line each, at most two lines per axis, restating nothing the plan already says. The binding discipline is that at completion, why carries the gate evidence, which forces every wave report to be quantitative and makes a wave that cannot state its evidence visibly incomplete rather than plausibly done. Specified with worked examples in Agent Fleet Orchestration §8.

Continuation wiring at every level. Work must never end without naming what comes next, and the chain has to close at three altitudes rather than one. A worker returns candidate follow-ons in its manifest — work it discovered but was fenced out of — which the orchestrator either folds into the current wave or writes as a plan followup; today a worker's out-of-scope discovery has nowhere to go but prose. A plan landing resolves its driving followup and appends the next one-line invocation, or records that the chain closes; this rule exists but is enforced only by discipline, so make it a validated condition of the writeback. A sprint close reports the sprints it feeds, derived from the dependency graph — the downstream sprints whose items this sprint's plans unblock — which does not exist at all today. Enforce all three: a session ending with neither a next invocation nor an explicit no-followup outcome is a failure, at every altitude.

Record whatever budget signal the backend emits. The two CLI backends are asymmetric here and the design must not pretend otherwise. One emits a structured rate-limit event carrying utilisation, reset time and a threshold status — enough to reason about headroom. The other emits per-turn token usage but no headroom at all, and offers no query command for it. So capture what is emitted into the run record, expose it as a budget block that may legitimately read unknown, and never infer exhaustion from absence. Acting on that signal is the subject of budget-aware-dispatch; this plan only ensures the data is captured from the first dispatch onward, so the later work has history to reason over.

The skill upgrade — and this plan owns SKILL.md outright. reckon-ship/SKILL.md gains the pre-dispatch checklist, the one dispatch instruction, the summary reflex and the gate-fence rule that a wave does not open through a closed gate. It gains no backend-specific text. references/worker-backends.md is added as maintainer documentation of what _backends.py does internally — it is not agent-facing, and the ownership test is that a sentence in it which does not turn on process, session or observation mechanics is misfiled.

The gate-fence rule is authored here and nowhere else. Gates are not yet structured state, so enforcement at this stage means the orchestrator reads the plan's declared evidence-gate table and refuses to open the next wave until its measure has produced evidence. derived-gate-state later swaps that enforcement from reading prose to reading computed state; it must not re-author the rule, and no concurrent node may write this file until this plan's changes are integrated. Saying so explicitly is the point — two plans claiming one rule is how a worker rewrites a peer's text believing it owns it.

✓ landed §4 — Evidence gates

Eleven of eleven banked, with one exemption stated rather than glossed: the routing-leakage grep returns three hits, all in a documented legacy-tier reader that never selects a worker, and the property is now guarded by a test so it cannot decay. Two limits found while running it are recorded for the work downstream: one backend's restrained tier blocks all writes including the manifest, and configured concurrency is not yet enforced by dispatch. § gates

Measures to demonstrate, not thresholds to tune around. The sprint closes on the first row; the rest must all bank before the sprint is done.

End-to-end dispatch

One real node dispatched through reckon crew dispatch lands a commit in a detached worktree with its manifest on disk, verified by git show --stat showing only assigned paths. Record the run id, commit SHA and manifest path.

Evidence

Uniformity

The same node definition dispatches successfully against at least two backends with no change to the calling instruction — only flight config differs. Both invocations recorded.

Evidence

Task contract enforced

Tests proving dispatch refuses a node with two goals, a subjective done-when, and a missing write scope; each rejection names the failing property.

Evidence

Escape hatch round-trip

A worker deliberately driven to a NEEDS-HELP: report, all four fields present, answered by the orchestrator and resumed in the same session, with the resumed turn demonstrably retaining prior context.

Evidence

Durable delivery

A recorded case where the manifest file exists on disk; the recovery ladder is followed in order and redispatch is not the first response to an idle signal.

Evidence

In-harness branch

native dispatch returns a directive carrying worktree, manifest path and resolved fences, and reckon crew attach binds a real harness task to it.

Evidence

Both summaries

Verbatim dispatch and completion summaries captured, four axes each, with the completion WHY carrying a quantitative gate measure.

Evidence

Continuation closes at three altitudes

Tests proving each: a worker manifest carrying a candidate follow-on reaches a plan followup; a plan writeback without a next invocation or an explicit no-followup outcome is refused; a sprint close reports its downstream sprints derived from the graph. A recorded end-to-end trace shows the chain intact from worker to sprint.

Evidence

Budget signal captured

A run record from each CLI backend, one carrying parsed utilisation and reset time, the other legitimately reading unknown. A test proves absence is never read as exhaustion.

Evidence

No routing leakage

A grep over skills/ and reckon/ excluding _backends.py and test fixtures returns no concrete model identifier or provider name.

Evidence

Suite and validators green

Full reckon suite passes; both skill validators pass; new-test count recorded.

Evidence
✓ landed 2026-08-12

§6 — A worker must be able to read the plan it is sent to read

Dispatch resolves the base to a commit, compares the working plan's bytes against that commit's blob and verifies the named section by authored id or heading — all before a worktree exists. It refuses at exit 4 with error=plan-unavailable, beside 2 for a malformed node and 3 for a budget hold, so a caller branches without parsing prose. Demonstrated on the live failure rather than a fixture: with the plan genuinely dirty, a dispatch naming it returned "differs from base 'HEAD'; commit the plan before dispatching" and created 0 worktrees. It then blocked this session twice more, correctly both times. 5 new tests, suite green at 1,680 (commit c558f47).

A dispatch cuts a detached worktree from a base ref and then tells the worker its first act is to read the live plan at the named section. Those two facts do not compose: the worktree holds the committed plan, so any edit still sitting in the orchestrator's working tree is invisible to the worker. The node names a section that, from where the worker stands, does not exist.

The failure is quiet in the worst way. The node is well-formed — it passes all seven properties, because well-formedness is judged against the node, never against what its worktree can show. Nothing warns. The worker either burns its budget hunting a missing section or, worse, finds an older revision of it and implements the previous intent faithfully.

Observed 2026-08-12 while dispatching against a section written minutes earlier: caught thirty-seven seconds in, by chance, only because the worktree was opened to check. The cost was one stopped run and one removed worktree; unnoticed it would have been a wasted budget and a plausible-looking wrong result.

Dispatch refuses before it creates anything. The plan the node names must be readable at the base ref, must contain the named section there, and must not differ from the orchestrator's working copy. Any of those failing is a refusal that names the file and says to commit — checked before the worktree exists, so a refused dispatch leaves nothing to unwind.

No override accompanies this. The remedy is one commit, the rule is cheap to satisfy, and an escape hatch here would be taken exactly in the hurry that produces the bug.

MeasureRequired evidence
An uncommitted plan is refused A dispatch whose plan differs between the working tree and the base ref is refused with no worktree created and no run record written, and the message names the file and the remedy.
A missing section is refused A dispatch naming a section absent from the plan at the base ref is refused the same way, rather than being discovered by the worker.
A clean plan is unaffected A dispatch whose plan and section are present and committed proceeds exactly as before; the existing dispatch tests pass unchanged.
The refusal is branchable The caller can distinguish this refusal from a malformed node and from a budget hold without parsing prose, and the command surface documents which code it is.
Suite green Full reckon suite passes; new-test count recorded.
✓ landed 2026-08-12

§7 — The contract must not refuse a well-formed node

A conjunction bounds two deliverables only when a task action follows it, and a listed term preceded by a hyphen no longer fails demonstrability; then and ; stay explicit separators. All 3 conjoined-noun goals refused in one wave now pass while the genuine two-deliverable goal from that same wave is still refused. Re-checked against this session's own three refusals: 2 were false positives and now pass, 1 was a true positive and still refuses — a bare vague adjective, which is the case the check exists for. 2 new tests, suite green at 1,701 (commit a2aef3e).

Two properties reject nodes that satisfy them, and both failures share a shape: a pattern matching a surface feature of the wording rather than the thing the property is about.

Single-goal matches any " and ". A goal naming one deliverable through a conjoined noun phrase — "round-trip a section from parse and serialisation", "derived age and a staleness verdict", "sprint order and incompleteness" — is refused as two nodes. Three of three nodes in one wave were refused this way, each reworded to remove a conjunction that was never a second deliverable. The distinction that matters is between a conjunction joining two verb phrases and one joining a noun phrase.

Demonstrable matches a subjective term inside a compound. The check tests a word boundary, and a hyphen is one, so machine-readable, human-readable and any compound ending in a listed adjective are rejected as opinions. Observed twice today, once while dispatching the guard in §6 itself: a done-when naming a machine-readable exit code was refused for resting on the term "readable".

The direction of the error is what makes these worth fixing. Both checks exist to stop a worker being sent an unmeasurable goal; here they block the most precise available wording and push the coordinator toward vaguer text. And both were survivable only because a human noticed — a refused dispatch is silent about whether the refusal was correct.

The checks are worth keeping: the same pass correctly caught a genuine two-deliverable goal and a time budget overrunning its fence. The defect is precision, not existence, so the measure is a test carrying both the correctly-refused and the wrongly-refused wording from the waves that produced them.

MeasureRequired evidence
A conjoined noun phrase passes The three real goals refused in one wave pass, while a genuine two-deliverable goal from the same wave is still refused, in one test.
A hyphenated compound passes machine-readable in a done-when passes while a bare subjective adjective is still refused, in one test.
Suite green Full reckon suite passes; new-test count recorded.
✓ landed 2026-08-12

§8 — A property that checks exclusivity must not sound like it checks sufficiency

A dry run now returns the write paths it resolved, so a coordinator sees what it actually fenced before committing a wave to it, and the worker protocol states plainly that scoped checks exclusivity and does not prove the named paths can carry the goal. 2 new tests (commit 7952c4c). The worker reported blocked rather than claiming complete, because the full suite was red on arrival from a concurrent commit deriving plan dispatchability — its own two measures passed throughout, and the suite came back green at 1,711 once that peer landed its fix. The run is recorded with gate not-run: the measure was unevaluable against this node, which is not the same as failed.

A node can satisfy all seven properties and still be unbuildable. Scoped verifies that write paths are enumerated and shared with no concurrent node; nothing verifies that those paths can carry the goal. Observed today: a node fenced to two files passed validation and blocked on arrival, because the behaviour it had to change lived in two further files — exactly one of the two required surfaces was reachable, so the assertion the node existed to make could not truthfully be made.

The escape hatch handled it as designed: the worker audited the call graph, changed nothing, and named both missing files. The cost was still a full dispatch cycle, and the fault was the coordinator's — the fence came from a symbol search rather than from the callers of the thing being changed.

A property that sounds like it guarantees buildability while checking only exclusivity is worse than one that states its own limit. So the cheap half is to report the resolved write scope back from a dry run, letting a coordinator see what it actually fenced before committing a wave to it; and the honest half is to say plainly, in the contract, what scoped does and does not check.

MeasureRequired evidence
A dry run reports the scope it resolved The dry-run payload carries the resolved write paths, shown by a test reading them back.
The property states its own limit The contract says scoped checks exclusivity and not sufficiency, in the skill and in the worker protocol, asserted by a contract test.
Suite green Full reckon suite passes; new-test count recorded.
✓ landed 2026-08-12

§9 — A followup id must identify exactly one followup

Append refuses a duplicate id across followups, questions, research and comments, naming the existing entry and leaving the version unmoved; a resolve whose id has no open entry returns an error instead of reporting success; and resolve skips a closed duplicate to reach the open match. Validated non-mutatingly against this plan's own live HTML — 2 matching entries, 1 open before and 0 open after — then the stuck record was closed for real. 4 new tests, suite green at 1,703 (commit 6b043e3).

Two sessions independently minted f-uwd-003 against this plan, and the store accepted both. The consequence is not cosmetic: resolve targets by id, so it matched the same article twice and reported success both times while leaving the second followup open. A write that cannot address a record it claims to have written is worse than one that fails, because nothing surfaces the miss — it was caught only by reading the state back and counting.

The neighbouring ledger already refuses this exact shape: append_run rejects a second record for a run id, on the grounds that a double promotion double-counts the very measurements a later reader depends on. A collection whose entries are addressed by id owes the same guarantee, and followups are addressed by id on every resolve.

Two halves, and the second is what makes the first safe to rely on. Append refuses a duplicate id, naming the existing entry, so the collision is a visible error at the moment it is created rather than a silent one later. And a resolve that matches no open entry says so instead of reporting success, which is the failure that hid this one.

The stuck record on this plan is the test case: its content is already folded into §7, and it cannot be closed through any sanctioned write path today — the prose tool correctly refuses to edit structured state, and the state tool cannot reach past the first match.

MeasureRequired evidence
A duplicate id is refused on append Appending a followup whose id already exists raises, naming the existing entry, in a test; the same holds for the other id-addressed collections.
A resolve that matches nothing says so Resolving an id with no open entry reports a failure rather than success, in a test that would have caught the duplicate-id miss.
The stuck record closes The second f-uwd-003 on this plan is resolvable and resolved, shown by an open-followup count of zero.
Suite green Full reckon suite passes; new-test count recorded.
✓ landed 2026-08-12

§10 — The continuation check must fire on a landing, not on a resolve

An active plan below full implementation now carries its own continuation, so an ordinary mid-run resolve passes; at 1.0 a final resolve with no chain answer still refuses, new terminal landings without one still refuse, and plans already recorded as shipped stay writable. The gate that mattered is met directly: the same resolve driven through the ops path and the HTTP patch path returns [true, true], and both persist zero open followups — the two doors that disagreed now answer alike. 5 new tests over 6 cases, suite green at 1,717 (commit ac93488). Reported blocked on a stale base: the 3 roadmap failures it saw had already been fixed on main by a concurrent session before it finished.

The rule that work must not end without naming what comes next is enforced on two write paths, and they disagree. The ops path treats a batch that resolves a followup or sets a terminal status as a landing; the HTTP patch path keys on terminal status alone. The same resolve is therefore refused through one door and accepted through the other — which is exactly the drift the shared definition was introduced to prevent, and the module says so in its own words: one definition exists "so the ops writer and the HTTP patch writer cannot disagree". They share the definition of a continuation. They do not share the trigger.

Resolving a followup is not a landing. A plan left active, below full implementation, with a section dispatched and in flight, has manifestly not ended — yet the refusal reads "plan landing leaves no continuation". An error that misdescribes what happened is worse than no error, because the reader satisfies the string instead of the intent.

And the cheapest way past a false fire corrodes the signal it protects. The outcome text only has to contain "no followup" to pass, so a check firing on ordinary mid-run resolves trains its users to write that phrase into outcomes that are not final. Every false fire devalues the marker for the one case it exists to catch. This was met live: the phrase had to be worded carefully into a genuinely non-final outcome to get a true statement past the check.

Once same-plan follow-on work is folded into sections rather than deferred as followups, zero open followups becomes the normal state of a healthy active plan. A check keyed to that condition fires on the common case and stays quiet on the rare one.

Fix the definition, not the trigger. Narrowing the ops trigger to terminal status would lose a real protection: a session that resolves its driving followup, leaves the plan active and ends naming nothing is the failure this was built for. Instead let a plan that is manifestly still in progress — non-terminal status below full implementation — count as carrying its own continuation. A final resolve on a plan with nothing left still refuses; both fields are already structured state, so nothing has to parse the HTML for a rendering convention that would rot; and the reconciliation lands in the shared definition, which is where the module already says the single truth belongs.

MeasureRequired evidence
Both write paths agree One test drives the same resolve through the ops path and the HTTP patch path and asserts the same verdict from each.
A mid-run resolve passes Resolving a followup on an active plan below full implementation succeeds and leaves no open followup, reproducing the case met on this plan today.
The real failure still refuses A batch setting a terminal status with no open followup and no chain-closed outcome is still refused, and so is a final resolve that leaves nothing naming what comes next.
History stays editable The existing rule that only a new landing owes an answer is preserved, so plans already recorded as shipped without a followup remain writable.
Suite green Full reckon suite passes; new-test count recorded.

§5 — Constraints

Worker prompts carry fences and a pointer to the live plan. They never copy plan context, decisions, research or done-when prose — a copied brief becomes a second source of truth that drifts between workers and sessions.

The worktree dispatch contract already in references/sprint-orchestration.md §6 remains binding and is not restated: no branch creation or switching, no stash, rebase, clean or hard reset, explicit path staging only, no shared plan-state edits, conventional commit subject and body, no AI attribution, no plan or sprint identifiers in commit messages.

Workers default to the full-access tier bounded by their detached worktree. A node whose only write is its own manifest may be dropped to a read-only tier as a runtime choice; that is routing, not a policy change.

§ Decisions

One execution skill, or a sibling skill for external-harness teams?

A sibling skill was designed first and rejected during review as a drift risk.

Classifying the intended additions showed only two of six were harness-specific — launch mechanics and session reuse. The other four would have been duplicated subsystems. The durable rule: split a skill when the process differs, never when only the substrate differs. Adding a thin entry point later costs a small file; un-forking two drifted skills is a real merge.

What tier do workers run at inside their worktree?

A workspace-write sandbox is inherited by child processes and breaks test runners, builds and anything spawning subprocesses — workers must be able to run the verification their gates demand. The detached worktree bounds blast radius instead. The reviewed tier remains available per-node for work that does not build.

Should dispatch be an MCP tool or a CLI command?

Dispatch must spawn a background process the agent then yields on, which an MCP tool cannot usefully do. Keeping reads on MCP also holds that surface at five tools, consistent with reckon's ongoing tool-count collapse.

§ Followups

Build the uniform dispatch path and the worker contract

Land the backend translation module, the atomic dispatch and attach primitives, the task-definition contract with pre-dispatch validation, the structured escape hatch, the four-axis summary reflex, and the skill upgrade. Close on a real node dispatched end to end through the uniform call.

/reckon-ship uniform-worker-dispatch

Landed — commits a927c9c, 8a44624, 0ae4167, d3a7617, 2224770. Six nodes dispatched through one call across two external harnesses and the calling harness; all 11 gates banked. One node definition reached the same 36-key routing result on two backends; an unprompted four-field NEEDS-HELP report was answered and resumed in the same session, which restated its measurements without re-running; budget read utilisation 1.02% on one backend and explicit unknown on the other. 1,598 tests pass (103 new). Two live defects found and fixed: the resume invocation was rejected on argument order, and a dead process with an empty log misread as starting.

Promote live run pointers into the committed run ledger

Dispatch now writes a transient live pointer per run and observation folds the stream, manifest presence and budget signal back into it, but nothing promotes a finished run into durable committed history. Two limits surfaced while running the wave and belong to this work or its neighbours: one backend's restrained tier blocks all writes including the manifest, so a read-only node has no delivery channel; and configured per-backend concurrency is resolved but not enforced by dispatch, so the cap is currently advice to the caller.

/reckon-ship crew-run-ledger

Foreign-owner: the promotion work it names landed in crew-run-ledger, which is shipped at 1.0 — live pointers now promote into the repository's committed ledger with recovery for an interrupted orchestrator. Closed here rather than left open against a plan that no longer owns it.

Stop the single-goal check rejecting a conjoined noun phrase

The single-goal property matches any " and " in the goal, so it refuses goals that name one deliverable: round-trip a section from parse and serialisation, derived age and a staleness verdict, sprint order and incompleteness. Three of three nodes in one wave were refused on this, each reworded to remove a conjunction that was never a second deliverable.

The check is worth keeping - the same pass correctly caught a genuine two-deliverable goal and a time budget overrunning its fence in the same wave. The defect is precision, not existence. Distinguish a conjunction joining two verb phrases (two deliverables) from one joining a noun phrase (one deliverable), and measure it with a test carrying both the refused-correctly and refused-wrongly goals from that wave.

/reckon-ship uniform-worker-dispatch

Folded into §7 as its second measure, and closed only once §9 made it reachable: resolve now skips a closed duplicate to reach the open match, so the record that reported success twice while leaving this one open is addressable. Measured on the merged code — two of the three wordings this session was refused on now pass, and the third was a true positive that still refuses, because "correctly" standing alone really is the vague adjective the check exists to catch.

The subjective-term check fires inside hyphenated compounds

The demonstrable property rejects a done-when containing a subjective adjective, matched on a word boundary. A hyphen is a word boundary, so machine-readable, human-readable and any compound ending in a listed term are rejected as opinions. Observed 2026-08-12 dispatching the section-6 guard itself: a done-when naming a machine-readable exit code was refused for resting on the subjective term 'readable', and the node had to be reworded rather than fixed.

The cost is small but the direction is wrong: the check exists to stop a worker being sent an unmeasurable goal, and here it blocks the most precise available wording. Narrow the match so a compound whose head is not the listed adjective passes, and keep a test for both the true positive and this false one.

/reckon-ship uniform-worker-dispatch

Folded into §7 as its second measure and closable only once §9 shipped, since resolve now skips a closed duplicate to reach the open match. Closed through the merged code in-process: the long-running MCP server still held the pre-merge store, so its resolve reported success while changing nothing — the silent-success failure §9 exists to remove, met once more on the way out. done — no followup: every remaining item on this plan is a section (§8 is dispatched and in flight), which is the folding rule working as intended rather than a chain that stops.

Scoped checks that paths are exclusive, never that they are sufficient

A node can satisfy all seven properties and still be unbuildable. The scoped property verifies that write paths are enumerated and shared with no concurrent node; nothing checks whether those paths can actually carry the goal. Observed today: a node routing gate state into the blocking derivation was fenced to reckon/lifecycle.py and reckon/roadmap.py, passed validation, and blocked on arrival - read_plan builds its blocking rows in mcp_views._blocking for typed reads and serve._derive_lifecycle for discovery reads, so exactly one of the two required surfaces was reachable and the two-direction assertion could not truthfully be made.

The escape hatch caught it cleanly, which is the intended division of labour: the worker audited the call graph, changed nothing, and named both missing files and functions. But the cost is a full dispatch cycle, and the fault was the coordinator's - the fence was inferred from a symbol search rather than from the callers of the thing being changed.

Two directions, and the first is cheap. Have --dry-run report the write scope back as a resolved list so a coordinator sees what it actually fenced before committing a wave to it. Then consider whether a sufficiency hint is possible at all: the paths naming a symbol the goal mentions, or the callers of a function in scope, would have surfaced both missing files here. If it cannot be checked, say so in the contract - a property that sounds like it guarantees buildability while checking only exclusivity is worse than one that states its own limit.

/reckon-ship uniform-worker-dispatch

Folded into §8. The finding is sharper than a missing check: a property that sounds like it guarantees buildability while verifying only exclusivity is worse than one that states its limit, so the section requires both the cheap fix (a dry run reporting the scope it resolved) and the honest one (the contract saying what scoped does not check).

Plan closed — done, no followup. Five sections landed in one run (§6 worktree-visibility guard, §7 contract precision, §8 scope sufficiency, §9 followup id integrity, §10 continuation trigger), every one of them work that surfaced during the run rather than being deferred out of it. Four followups were drained to zero: one closed against the plan that had since shipped its work, three folded into sections. Suite 1,717 green. Two workers reported blocked rather than claiming complete, both times against a suite made red by a concurrent session; the escape hatch and the ownership rule between them cost nothing and hid nothing.