devrites 7.3.1 → 7.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +19 -3
  3. package/bin/devrites.mjs +31 -5
  4. package/docs/engine/commands.md +35 -3
  5. package/docs/release.md +5 -2
  6. package/engine/Makefile +2 -2
  7. package/engine/internal/acceptance/newfinal_origins.go +39 -0
  8. package/engine/internal/acceptance/preconditions.go +17 -11
  9. package/engine/internal/acceptance/transcript.go +23 -4
  10. package/engine/internal/gate/gate.go +8 -6
  11. package/engine/internal/gate/readiness_binding.go +50 -21
  12. package/engine/internal/install/apply.go +36 -21
  13. package/engine/internal/install/binary.go +67 -9
  14. package/engine/internal/install/install.go +63 -21
  15. package/engine/internal/install/manifest.go +4 -5
  16. package/engine/internal/install/merge.go +89 -33
  17. package/engine/internal/install/preflight.go +60 -19
  18. package/engine/internal/install/uninstall.go +19 -9
  19. package/engine/internal/install/update.go +0 -4
  20. package/engine/internal/lib/claims.go +170 -4
  21. package/engine/internal/lib/claims_holder.go +13 -16
  22. package/engine/internal/lib/closeout.go +52 -28
  23. package/engine/internal/lib/context_io.go +88 -4
  24. package/engine/internal/lib/continuation.go +111 -24
  25. package/engine/internal/lib/dispatch.go +157 -24
  26. package/engine/internal/lib/final_prerequisites.go +137 -0
  27. package/engine/internal/lib/manifest_union.go +62 -25
  28. package/engine/internal/lib/next.go +10 -10
  29. package/engine/internal/lib/packet.go +32 -8
  30. package/engine/internal/lib/packet_integrity.go +194 -2
  31. package/engine/internal/lib/resolve.go +128 -142
  32. package/engine/internal/lib/treebaseline.go +0 -1
  33. package/engine/internal/markdowntext/markdowntext.go +110 -31
  34. package/engine/internal/overhaul/records/check.go +45 -5
  35. package/engine/internal/overhaul/records/consistency.go +34 -8
  36. package/engine/internal/overhaul/records/run.go +55 -11
  37. package/engine/internal/parallel/landing.go +17 -0
  38. package/engine/internal/state/acceptance.go +35 -5
  39. package/engine/internal/state/feature.go +3 -2
  40. package/engine/internal/state/observation.go +1 -1
  41. package/engine/internal/state/write.go +20 -44
  42. package/engine/internal/workflow/commands.go +25 -3
  43. package/engine/main.go +19 -0
  44. package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +41 -39
  45. package/pack/.claude/skills/overhaul/SKILL.md +8 -4
  46. package/pack/.claude/skills/overhaul/references/lifecycle.md +13 -6
  47. package/pack/.claude/skills/overhaul/references/orchestration.md +32 -21
  48. package/pack/.claude/skills/overhaul/references/records.md +23 -8
  49. package/pack/.claude/skills/overhaul/references/scope-and-safety.md +7 -2
  50. package/pack/.claude/skills/overhaul/references/scoring.md +7 -0
  51. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +17 -17
  52. package/pack/.claude/skills/rite-clarify/SKILL.md +25 -25
  53. package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +41 -39
  54. package/pack/generated/claude/skills/overhaul/SKILL.md +8 -4
  55. package/pack/generated/claude/skills/overhaul/references/lifecycle.md +13 -6
  56. package/pack/generated/claude/skills/overhaul/references/orchestration.md +32 -21
  57. package/pack/generated/claude/skills/overhaul/references/records.md +23 -8
  58. package/pack/generated/claude/skills/overhaul/references/scope-and-safety.md +7 -2
  59. package/pack/generated/claude/skills/overhaul/references/scoring.md +7 -0
  60. package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +17 -17
  61. package/pack/generated/claude/skills/rite-clarify/SKILL.md +25 -25
  62. package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +41 -39
  63. package/pack/generated/codex/skills/overhaul/SKILL.md +8 -4
  64. package/pack/generated/codex/skills/overhaul/references/lifecycle.md +13 -6
  65. package/pack/generated/codex/skills/overhaul/references/orchestration.md +32 -21
  66. package/pack/generated/codex/skills/overhaul/references/records.md +23 -8
  67. package/pack/generated/codex/skills/overhaul/references/scope-and-safety.md +7 -2
  68. package/pack/generated/codex/skills/overhaul/references/scoring.md +7 -0
  69. package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +17 -17
  70. package/pack/generated/codex/skills/rite-clarify/SKILL.md +25 -25
  71. package/pack/generated/devin/skills/devrites-lib/reference/parallel-dispatch.md +41 -39
  72. package/pack/generated/devin/skills/overhaul/SKILL.md +8 -4
  73. package/pack/generated/devin/skills/overhaul/references/lifecycle.md +13 -6
  74. package/pack/generated/devin/skills/overhaul/references/orchestration.md +32 -21
  75. package/pack/generated/devin/skills/overhaul/references/records.md +23 -8
  76. package/pack/generated/devin/skills/overhaul/references/scope-and-safety.md +7 -2
  77. package/pack/generated/devin/skills/overhaul/references/scoring.md +7 -0
  78. package/pack/generated/devin/skills/rite-build/reference/wright-dispatch.md +17 -17
  79. package/pack/generated/devin/skills/rite-clarify/SKILL.md +25 -25
  80. package/pack/generated/dsh/runtime/cordis.patch.yml +28 -14
  81. package/pack/generated/dsh/skills/devrites-lib/reference/parallel-dispatch.md +41 -39
  82. package/pack/generated/dsh/skills/overhaul/SKILL.md +8 -4
  83. package/pack/generated/dsh/skills/overhaul/references/lifecycle.md +13 -6
  84. package/pack/generated/dsh/skills/overhaul/references/orchestration.md +32 -21
  85. package/pack/generated/dsh/skills/overhaul/references/records.md +23 -8
  86. package/pack/generated/dsh/skills/overhaul/references/scope-and-safety.md +7 -2
  87. package/pack/generated/dsh/skills/overhaul/references/scoring.md +6 -0
  88. package/pack/generated/dsh/skills/rite-build/reference/wright-dispatch.md +17 -17
  89. package/pack/generated/dsh/skills/rite-clarify/SKILL.md +25 -25
  90. package/pack/generated/omp/skills/devrites-lib/reference/parallel-dispatch.md +41 -39
  91. package/pack/generated/omp/skills/overhaul/SKILL.md +8 -4
  92. package/pack/generated/omp/skills/overhaul/references/lifecycle.md +13 -6
  93. package/pack/generated/omp/skills/overhaul/references/orchestration.md +32 -21
  94. package/pack/generated/omp/skills/overhaul/references/records.md +23 -8
  95. package/pack/generated/omp/skills/overhaul/references/scope-and-safety.md +7 -2
  96. package/pack/generated/omp/skills/overhaul/references/scoring.md +7 -0
  97. package/pack/generated/omp/skills/rite-build/reference/wright-dispatch.md +17 -17
  98. package/pack/generated/omp/skills/rite-clarify/SKILL.md +25 -25
  99. package/pack/generated/pi/skills/devrites-lib/reference/parallel-dispatch.md +41 -39
  100. package/pack/generated/pi/skills/overhaul/SKILL.md +8 -4
  101. package/pack/generated/pi/skills/overhaul/references/lifecycle.md +13 -6
  102. package/pack/generated/pi/skills/overhaul/references/orchestration.md +32 -21
  103. package/pack/generated/pi/skills/overhaul/references/records.md +23 -8
  104. package/pack/generated/pi/skills/overhaul/references/scope-and-safety.md +7 -2
  105. package/pack/generated/pi/skills/overhaul/references/scoring.md +7 -0
  106. package/pack/generated/pi/skills/rite-build/reference/wright-dispatch.md +17 -17
  107. package/pack/generated/pi/skills/rite-clarify/SKILL.md +25 -25
  108. package/package.json +1 -1
  109. package/scripts/dsh-generate.py +1 -1
  110. package/scripts/install-lib.sh +29 -0
  111. package/uninstall.sh +1 -0
@@ -99,26 +99,26 @@ Same-worktree multi-writer / root-emulated worktrees stay forbidden.
99
99
 
100
100
  ## Run
101
101
 
102
- Same-worktree (non-isolated) dispatch claims before writing: the `dispatch open`
103
- below adds `--claim-session <id>`, one `--claim <path>` per task path, and
104
- `--claim-ttl <minutes>` sized to the write; it runs the
105
- `claim check --session <id> <task-paths>` test, and a live foreign holder fails the
106
- open with no wave and no claim and stops the dispatch, per
107
- [`agents.md`](../../devrites-lib/reference/standards/agents.md). `.devrites/**`
108
- is never a task path; see [Workflow Artifact admission](../../devrites-lib/reference/standards/workflow-artifacts.md).
102
+ Before same-tree writing, `dispatch open` adds `--claim-session <id>`,
103
+ `--claim <path>` per task path, and `--claim-ttl <minutes>` sized to the write.
104
+ It runs `claim check --session <id> <task-paths>`. Live foreign or abandoned
105
+ unreleased/nonterminal claims (even same-session/expired) refuse without a wave
106
+ or new claim, per [`agents.md`](../../devrites-lib/reference/standards/agents.md).
107
+ `.devrites/**` is never a task path; see [Workflow Artifact admission](../../devrites-lib/reference/standards/workflow-artifacts.md).
109
108
  Render the contract with `devrites-engine packet <slug> --wave <wave> --phase build
110
109
  --role slice-wright --slice <SLICE-ID> [--checks <G-ID,...>] [--focus <file>]` (it
111
110
  writes the linted same-worktree `packets/<wave>.contract.md`; a native-worktree pilot
112
- writes its own contract with `Isolation`, `worktree_base`, and subject) and hand the wright that text verbatim. Reviewers read
113
- that file, so `--focus` rows state each defect to fix with its anchor, never a reviewer's verdict,
114
- count, or pass status ("code review is no-findings" voids the next review). Ask the host
115
- for the exact writer in fresh context; a repair round on the same slice whose
116
- returned wright the host can still continue goes to that wright on its existing
117
- handle instead, so it does not re-read the slice from scratch. Wait, and track it
118
- through the launch barrier — `devrites-engine dispatch <slug> open --phase build --wave
119
- <slice-id> --role slice-wright --slice <SLICE-ID> --contract <file>` (it refuses a
111
+ writes its own contract with `Isolation`, `worktree_base`, and subject). Give it
112
+ verbatim. Reviewers read it: `--focus` names defect + anchor, never a prior
113
+ verdict, count, or pass claim. Ask the exact writer in fresh context; a repair
114
+ may continue the returned wright's existing handle if the host supports it,
115
+ avoiding a reread. Track the launch barrier — `devrites-engine dispatch <slug> open --phase build --wave
116
+ <wave-id> --role slice-wright --slice <SLICE-ID> --contract <file>` (it refuses a
120
117
  contract that forbids writer-safe checks or names none), then `start` with the host handle
121
- (the last start seals the wave) and `return` on completion (auto-records dispatch/return metrics). Every 5 wright
118
+ (the last start seals the wave) and `return --wave <wave-id> --role slice-wright
119
+ --handle <id>` on completion (auto-records dispatch/return metrics). Every wave ID
120
+ is single-use: use a fresh ID for each repair or retry, even after abandonment;
121
+ the earlier wave keeps its handles, history, and any unreleased claim. Every 5 wright
122
122
  rounds on one slice, `open` blocks for a reslice review. First re-admit each
123
123
  finding still driving rounds under the Proportionality rule of
124
124
  [agents.md § Result admission](../../devrites-lib/reference/standards/agents.md#result-admission): one without a broken anchor or a reachable trigger becomes a
@@ -129,7 +129,7 @@ open findings move to the new slice owning their paths), or record
129
129
  `## <DRIFT-ID> — <SLICE-ID> reslice review` with why no smaller split exists and
130
130
  a spec trace of the slice's obligations (hardening no AC/INV/PROH requires moves to
131
131
  a sibling slice dependents do not need, still gated before Seal), and
132
- reopen with `--reslice-review <DRIFT-ID>`. Same-worktree stays one writer.
132
+ open a fresh wave with `--reslice-review <DRIFT-ID>`. Same-worktree stays one writer.
133
133
  Never run two writers in one worktree, mix isolated and same-worktree writers,
134
134
  or substitute a generic agent. Sanctioned parallel dispatch uses one exact
135
135
  wright per worktree, source-local `slice-wright.<SLICE-ID>` roles and starts
@@ -59,34 +59,34 @@ dispatch uses
59
59
  remains.
60
60
  5. **Write the verdict.** Write `Decision coverage: CLEAR` only after re-reading all inputs and confirming
61
61
  every material row has current evidence and an owner. Normal flow sets `phase=clarify` and
62
- `next_action=/rite-temper`. A low-stakes spec — the significance trigger temper itself
63
- skips (rite-temper step 1) — sets `next_action=/rite-define` instead. A contract-neutral later-phase return uses
64
- the native restore below; changed behavior or acceptance routes to
65
- `/rite-plan repair` instead. Stop without starting the next phase.
62
+ `next_action=/rite-temper`, or `/rite-define` for low-stakes specs temper skips.
63
+ Later-phase entries follow the ownership protocol below. Return inline verdicts
64
+ to the controlling caller; otherwise stop before starting the next phase.
66
65
 
67
66
  ## Native clarify cursor protocol
68
67
 
69
- The controlling root edits only cursor rows in `state.md`; it must preserve unrelated Markdown and the file's existing table/bullet presentation.
70
-
71
- - **Normal entry from Spec:** set `phase=clarify`, `status=running`, and
72
- `next_action=/rite-clarify <slug>`; omit both return fields.
73
- - **Already in Clarify:** no-op. Do not overwrite an existing valid return
74
- cursor.
75
- - **Later-phase entry:** only `temper`, `define`, `plan`, `vet`, `build`,
76
- `converge`, `prove`, `polish`, `review`, `seal`, or `ship` may return. First
77
- copy the current `phase` and non-empty `next_action` to `return_phase` and
78
- `return_next_action`; then set `phase=clarify`, `status=running`, and
79
- `next_action=/rite-clarify <slug>`. Missing/unknown cursor values fail closed
80
- before any write.
81
- - **Contract-neutral restore:** after a fresh `Decision coverage: CLEAR`, require
82
- `phase=clarify`, both return fields, a recognized later `return_phase`, and a
83
- non-empty `return_next_action`. Restore those values to `phase` and
84
- `next_action`, set `status=running`, and remove both return fields in the same
85
- rewrite. Re-read the cursor and confirm the return rows are absent.
86
- - **Contract changed:** do not restore the saved cursor. Record drift and route
87
- through `/rite-plan repair`, which owns the changed plan and next action.
88
-
89
- Never normalize or rewrite the rest of `state.md` while applying this protocol.
68
+ Edit only cursor rows; preserve unrelated Markdown and table/bullet presentation.
69
+
70
+ - **Validate before writes:** require no return fields or a complete pair:
71
+ recognized later `return_phase`, non-empty `return_next_action`. Invalid/half
72
+ pairs fail closed. Later phases: `temper`, `define`, `plan`, `vet`, `build`,
73
+ `converge`, `prove`, `polish`, `review`, `seal`, `ship`.
74
+ - **Spec entry:** set `phase=clarify`, `status=running`,
75
+ `next_action=/rite-clarify <slug>`; omit return fields.
76
+ - **Caller-owned pair:** pair with `phase!=clarify` requires a native
77
+ controlling caller; otherwise stop for ownership recovery. Run bounded Clarify
78
+ inline, preserve all cursor rows, and return its verdict to caller.
79
+ Contract changes require Plan repair and Vet before outer resume.
80
+ - **Clarify-owned pair:** standalone later-phase entry without a pair saves current
81
+ phase/non-empty next action as the pair, then sets `phase=clarify`,
82
+ `status=running`, `next_action=/rite-clarify <slug>`. Missing/unknown values
83
+ fail closed. `phase=clarify` resumes without writes; its pair belongs to
84
+ standalone Clarify, not a nested caller.
85
+ - **Restore:** after fresh `CLEAR`, only the owner restores its pair.
86
+ Contract-neutral standalone Clarify restores phase/next action, sets
87
+ `status=running`, atomically unsets both return fields, and re-reads to verify.
88
+ Contract changes retain the pair through Plan repair and Vet; only its owner
89
+ consumes it after readiness. Preserve caller pairs.
90
90
 
91
91
  ## Output
92
92
 
@@ -55,28 +55,27 @@ If the candidate diff has no matching surfaces, record
55
55
  The `agents` dispatch contract needs no flag: `--role` auto-fires it
56
56
  (`auto=[agents]` in the output). The command prints `unselected=[...]`; an
57
57
  omitted applicable trigger is a gap, not a shortcut.
58
- 3. Enforce the launch barrier through the engine, not prose. Open the wave
59
- (`devrites-engine dispatch <slug> open --phase <p> --wave <w> --role <r>...`;
60
- a reviewer, auditor, or test-analyst wave adds `--packet <file>`, any one of the
61
- wave's rendered `packets/<w>.<role>.md` (hand each agent its own file unedited), and `open` refuses one that seeds a gate result, outcome,
62
- count, or "already passed" claim; a Build reviewer wave adds `--slice <SLICE-ID>`
63
- so its findings key on that slice; at Review and Seal it also needs the packet to
64
- name the frozen candidate diff and the manifest to cover every checkpointed path;
65
- a same-tree writer wave adds `--claim-session <id> --claim <path>...` per
66
- [`wright-dispatch.md`](skill://rite-build/reference/wright-dispatch.md#run)), launch every native agent nonblocking through the host's own agent
67
- tool (never a shell-launched host CLI such as `omp -p` or `claude -p`: that is a
68
- dispatch bridge, its PID handle dies with the session, and its return is a `gap`),
69
- record each returned host handle
70
- (`dispatch ... start --wave <w> --role <r> --handle <id>`) — the last start
71
- seals the wave (an explicit `seal` is a no-op), which makes a
72
- serial launch-then-wait pattern impossible to record. Record each completion
73
- with `dispatch ... return`; a reviewer adds `--result <file>` holding its return verbatim (the engine stores it as `packets/<wave>-<role>.return.md`, derives the outcome from its head, and records its `Finding:` keys; a file already at that path is kept), or `--outcome <findings|no-findings|gap>` when the host cannot hand the return over as a file; `return` refuses before seal. `dispatch status`
74
- exits nonzero while the wave is open, sealed, or abandoned. `start`/`return`
75
- auto-record the dispatch/return metrics events — no separate ledger call. If
76
- an opened wave cannot obtain every handle or reach `seal`, run
77
- `devrites-engine dispatch <slug> abandon --wave <w> --reason <reason>` (with
78
- `--release` on a host-confirmed stop or refused launch) before
79
- recording the gap; never leave an open wave to block a retry.
58
+ 3. Open a single-use wave; every retry needs a fresh ID:
59
+ `devrites-engine dispatch <slug> open --phase <p> --wave <w> --role <r>...`.
60
+ Reviewer/auditor/test-analyst waves add `--packet <file>` naming any rendered
61
+ `packets/<w>.<role>.md`; give each agent its own packet unedited. `open` rejects
62
+ seeded gate results, outcomes, counts, or pass claims. Build reviewers add
63
+ `--slice <SLICE-ID>`; Review/Seal packets bind the frozen diff and a manifest
64
+ covering every checkpointed path. Same-tree writers add `--claim-session <id>
65
+ --claim <path>...` per [`wright-dispatch.md`](skill://rite-build/reference/wright-dispatch.md#run).
66
+ Launch all native agents nonblocking through the host tool before waiting.
67
+ Never shell-launch host CLIs (`omp -p`, `claude -p`): that bridge's handle dies
68
+ with the session and its return is a gap. Record every host handle with
69
+ `dispatch ... start --wave <w> --role <r> --handle <id>`; the last seals the wave
70
+ (explicit `seal` then does nothing). Return only after seal, with the recorded
71
+ handle: `dispatch ... return --wave <w> --role <r> --handle <id>`.
72
+ Reviewers add `--result <file>`: retain it verbatim at
73
+ `packets/<wave>-<role>.return.md` (keep an existing file), derive outcome and
74
+ `Finding:` keys. If the host cannot provide a file, use explicit
75
+ `--outcome findings|no-findings|gap`. Status is nonzero for open/sealed/abandoned
76
+ waves; start/return record metrics. If handles/seal cannot be obtained,
77
+ `dispatch ... abandon --wave <w> --reason <reason>` before recording the gap;
78
+ add `--release` only after host-confirmed stop/refused launch.
80
79
  4. Ask for each exact named agent in fresh context; omit native syntax and
81
80
  `agent_type`/`task_name`/`fork_turns` from the instruction.
82
81
  5. Every dispatch reaches a terminal classification before reconciliation:
@@ -144,32 +143,35 @@ the client renames a field its mocked test still passes, and the verdict reads c
144
143
 
145
144
  ## Cancellation and terminal reconciliation
146
145
 
147
- Cancellation acknowledgement means the host accepted a request, not that the
148
- child stopped. A transport timeout likewise leaves execution unknown. Keep the
149
- child's handle, path/resource ownership and capacity reservation until the
150
- native host confirms a terminal state and returned work has been reconciled.
151
- Query or wait on that handle; do not replace the child, release its slot, or
152
- reuse its resources while it may still run. If terminal state cannot be
153
- established, record a gap and retain ownership; for a child launched by an earlier
154
- session, the claim proof below settles it. A result classification alone
155
- does not prove host termination.
146
+ Cancellation acknowledgement or timeout leaves execution unknown. Keep handles,
147
+ path/resource ownership, and capacity until the native host confirms termination
148
+ and returned work is reconciled. Query/wait; never replace children, release slots,
149
+ or reuse resources prematurely. If unproven, record a gap and retain ownership;
150
+ earlier-session claim proof follows. Outcome classification alone proves no death.
156
151
 
157
152
  On resume (compaction or a new session), run `devrites-engine dispatch <slug>
158
153
  status`, `parallel status`, and `claim list` before any dispatch. A read-only
159
154
  wave whose handles this session cannot query: `abandon` it, record each unreturned
160
- role `gap`, and re-dispatch fresh on the current digest; its late returns are
161
- `stale`. A writer keeps its claim and lease — no relaunch on those paths until the
162
- claim is released or its holder is proven terminal. For an unqueryable writer,
163
- `claim list` showing its claim `dead` (the engine proved the holding session
164
- exited on this host), or `claim list --all --session <id>` showing it `released`
165
- (bare `list` only counts released rows), is that proof: `abandon` the wave, record the
166
- role `gap`, claim the paths, and re-dispatch without waiting on the launching
167
- session. `live` or `expired` stays held. A wright that never returned an
155
+ role `gap`, and re-dispatch under a fresh wave ID on the current digest; its late
156
+ returns are `stale`. A writer retains claim/lease: no relaunch under a fresh wave,
157
+ same session, or expired TTL until release or proven termination. For an
158
+ unqueryable writer, `claim list` `dead` proves its holding session exited on this
159
+ host; `claim list --all --session <id>` shows `released` (bare `list` counts it).
160
+ After that proof, `dispatch <slug> abandon --wave <w> --release --reason <reason>`
161
+ stamps `terminal_at` even without a claim, not a return. Record `gap`, reclaim
162
+ paths, and re-dispatch. `live`/`expired` stays held; cancellation acknowledgement,
163
+ timeout, ordinary abandonment, or replacement cannot prove writer death.
164
+ A wright that never returned an
168
165
  admitted result leaves unadmitted bytes: task-path changes since its pre-dispatch
169
166
  `git diff --name-only` baseline are never cited as built nor discarded, and are
170
167
  named in the re-dispatch contract; changes outside task paths stop for the human
171
168
  (Converge side: [`rite-converge`](skill://rite-converge/SKILL.md)).
172
169
 
170
+ Finalization settles every launched role, including proof/custom/writer roles.
171
+ Abandoned proof/reviewer replacement needs a newer settled account, same canonical
172
+ phase/role/exact unordered slice set, and distinct handle. Writer termination
173
+ admits no bytes and bypasses no candidate, admission, review or proof gate.
174
+
173
175
  ## Scale limits
174
176
 
175
177
  The role table bounds rosters. Use up to ten concurrent read-only reviewers,
@@ -143,10 +143,14 @@ deployment, or anything the user did not start with this command.
143
143
  reconfirmation otherwise), the re-hashed plan digest, the task closure, the current
144
144
  plan revision, no later stop, and for PR or branch scope a checked-out `HEAD` equal
145
145
  to the pinned head. Record it in `approval.json`.
146
- 2. Execute the approved DAG with [`overhaul-implementer`](.omp/agents/overhaul-implementer.md): one
147
- writer per path, independent frontend and backend tasks concurrently, TDD per
148
- [`references/repair-and-measurement.md`](references/repair-and-measurement.md).
149
- Admit patches only when observed changed paths equal the contract.
146
+ 2. Execute the approved DAG with [`overhaul-implementer`](.omp/agents/overhaul-implementer.md)
147
+ and TDD per [`references/repair-and-measurement.md`](references/repair-and-measurement.md).
148
+ Serialize shared-repository target writes, even for independent frontend/backend
149
+ tasks: whole-repository before-capture → target writer stops → full delta →
150
+ receipt admission, then start the next writer. Preserve one owner per physical
151
+ task path; admit only observed changes within the approved contract. Read-only
152
+ reviews and verification may overlap on immutable inputs when resources permit
153
+ ([observation windows](references/orchestration.md#single-writer-budgets-and-cancellation)).
150
154
  3. Verify each fix independently (`repair-verify`), test the assembled candidate,
151
155
  remeasure approved targets, rescore, publish, and follow the convergence table in
152
156
  [`references/lifecycle.md`](references/lifecycle.md) — continuing automatically
@@ -142,9 +142,13 @@ dispatched in task-ID order; a failed or blocked task keeps its dependents block
142
142
  Order correctness and security work before dependent performance or refactor work; keep dependency migrations separate from unrelated optimizations so gains stay
143
143
  attributable; give each shared physical file, generated source, lockfile or
144
144
  interface one write owner with explicit ordering; let a shared-contract change land
145
- only with evidence from both consumers. Independent frontend and backend tasks may
146
- run concurrently. A task like "improve architecture", "optimize queries" or "add
147
- tests" with no concrete failing case and acceptance evidence is not approvable.
145
+ only with evidence from both consumers. Serialize target-mutating attempts on one
146
+ repository, including independent frontend/backend tasks: whole-repository
147
+ before-capture → target writer stops → full delta → receipt admission, then dispatch
148
+ the next writer. Read-only reviews and verification may overlap on immutable inputs
149
+ when resources permit ([observation windows](orchestration.md#single-writer-budgets-and-cancellation)).
150
+ A task like "improve architecture", "optimize queries" or "add tests" with no concrete
151
+ failing case and acceptance evidence is not approvable.
148
152
  Each task names the oracle its kind requires
149
153
  ([`repair-and-measurement.md`](repair-and-measurement.md#oracles-by-finding-kind)).
150
154
  Rejected and deferred findings stay visible and keep failing their controls.
@@ -211,9 +215,12 @@ Dispatch only the deficient areas and their dependencies: frontend deficits to t
211
215
  frontend engineer plus relevant craft, performance, security or proof specialists;
212
216
  backend deficits to the backend engineer plus data, concurrency, security or proof
213
217
  specialists; boundary deficits to both producer and consumer owners. When both sides
214
- have deficits, dispatch them concurrently. When one side alone is affected, do not
215
- spawn an idle other-side repair to manufacture overlap; reuse unaffected evidence
216
- only after a recorded freshness check. Final cross-lane checks stay mandatory.
218
+ have deficits, dispatch independent read-only investigation and verification
219
+ concurrently on immutable inputs where resources permit; queue shared-repository
220
+ target writes through the exclusive capture → writer stop → delta → admission
221
+ windows above. When one side alone is affected, do not spawn an idle other-side
222
+ repair to manufacture overlap; reuse unaffected evidence only after a recorded
223
+ freshness check. Final cross-lane checks stay mandatory.
217
224
 
218
225
  Each new assignment carries the previous attempt's actual evidence, current deficit
219
226
  IDs, a falsifiable hypothesis or the exact missing observation, why the next action
@@ -83,10 +83,13 @@ file's body as its instructions; record that fallback in `run.json` capabilities
83
83
  ## Concurrent waves
84
84
 
85
85
  Use a bounded pool: at most 6 active read-only workers (reviewers, verifiers,
86
- critics) unless the user or host sets another limit; writers stay one per path. The limit counts nested and tool-launched model agents; workers never
87
- delegate further. A timed-out, cancelled-but-unconfirmed or `unknown` worker keeps
88
- its slot until it reaches a verified terminal state. Test runners, browsers and compilers obey a separate recorded
89
- CPU/memory/process budget.
86
+ critics) unless the user or host sets another limit. Target-mutating writer attempts
87
+ on one repository run serially, including their complete observation and admission
88
+ windows; path-disjoint tasks do not isolate a shared repository. The limit counts
89
+ nested and tool-launched model agents; workers never delegate further. A timed-out,
90
+ cancelled-but-unconfirmed or `unknown` worker keeps its slot until it reaches a
91
+ verified terminal state. Test runners, browsers and compilers obey a separate
92
+ recorded CPU/memory/process budget.
90
93
 
91
94
  After the short shared snapshot and component-map preflight:
92
95
 
@@ -104,19 +107,22 @@ After the short shared snapshot and component-map preflight:
104
107
  Launch the gap wave a critic names as soon as it names it, alongside that wave's
105
108
  verifiers, instead of waiting for them; every wave still runs, and reconciliation
106
109
  still waits until every attempt is terminal.
107
- 5. Synchronize only at snapshot establishment, shared-contract decisions, final
108
- reconciliation, approval, combined-candidate verification and completion. A
109
- question blocking one lane never stalls unrelated work in another.
110
+ 5. Read-only waves synchronize only at snapshot establishment, shared-contract
111
+ decisions, final reconciliation, approval, combined-candidate verification and
112
+ completion. A question blocking one lane never stalls unrelated read-only work
113
+ in another. Shared-repository target writes use the exclusive windows below.
110
114
 
111
115
  Record in `dispatch.json`, per attempt: wave, role, lane, profiles, snapshot,
112
116
  `dispatched_at` (coordinator clock), and the worker's own `started_at` and
113
117
  `finished_at`. Concurrency is proven only by overlapping worker intervals for the
114
118
  frontend and backend attempts of one wave. Never invent timestamps or claim
115
- parallelism the receipts do not show. Parallel writes additionally need approved,
116
- path-independent tasks; contracts, schemas, lockfiles, generators and shared
117
- components impose real ordering. Benchmarks sharing CPU, browser, database, network
118
- or caches run in exclusive measurement windows (see
119
- [`repair-and-measurement.md`](repair-and-measurement.md#measurement-windows)).
119
+ parallelism the receipts do not show. Read-only review and verification may overlap
120
+ on immutable inputs when their resources permit. Approved, path-independent tasks
121
+ still serialize target mutation on a shared repository: whole-repository deltas
122
+ cannot attribute overlapping writes to individual attempts. Contracts, schemas,
123
+ lockfiles, generators and shared components impose further ordering. Benchmarks
124
+ sharing CPU, browser, database, network or caches run in exclusive measurement
125
+ windows (see [`repair-and-measurement.md`](repair-and-measurement.md#measurement-windows)).
120
126
 
121
127
  ## Dispatch packets
122
128
 
@@ -239,15 +245,20 @@ Reconcile only after every attempt of the wave is terminal:
239
245
  ## Single writer, budgets and cancellation
240
246
 
241
247
  - One active writer per physical target path, including symlink and case aliases;
242
- the validator enforces this over `dispatch.json`. This is a coordination rule, not
243
- an operating-system lock; the coordinator also compares fingerprints before and
244
- after every writer.
245
- - Before admitting a patch, check its expected input hashes and the observed changed
246
- paths against the task's exact allowed paths. Observe them per attempt: run
247
- `devrites-engine overhaul snapshot state <repo> <before.json>` just before dispatch and
248
- `devrites-engine overhaul snapshot delta <before.json> <repo>` after it, and pass that output to
249
- `devrites-engine overhaul admit receipt --observed`. Never derive them from `git status`, which
250
- also lists the user's own edits. Extra paths are rejected, never merged later.
248
+ the validator reserves each live writer's complete approved task scope, not a
249
+ narrower `write_paths` claim. This is a coordination rule, not an operating-system
250
+ lock or permission to overlap target writes on one repository.
251
+ - Serialize the shared repository's entire target-mutating attempt window: capture
252
+ `devrites-engine overhaul snapshot state <repo> <before.json>` immediately before
253
+ dispatch, wait for the writer to stop, capture
254
+ `devrites-engine overhaul snapshot delta <before.json> <repo>`, and finish receipt
255
+ admission before the next target writer starts. The delta reports the whole
256
+ repository, including concurrent user edits; retain every observed path and reject
257
+ changes outside the task's exact allowed paths. Never filter sibling paths or
258
+ derive observations from `git status`. Path-disjoint writes still share this
259
+ observation resource. Read-only workers may overlap on immutable inputs where
260
+ resource use permits; checks that mutate the target repository also need this
261
+ exclusive window.
251
262
  - Use only providers and models the user approved; record the actual selection and
252
263
  any fallback. Independence means a separate context and evidence, not a
253
264
  different paid model. Never escalate to an unapproved provider to raise a score.
@@ -70,8 +70,8 @@ and every admission and settlement is recorded before the run leaves `RUNNING`
70
70
  revision as a new file under `revisions/`; never rewrite an existing one.
71
71
  3. Render views into the staged generation with `devrites-engine overhaul render`.
72
72
  4. `devrites-engine overhaul records publish <run>` validates the staged generation
73
- against the previous one, writes `manifest.json` (SHA-256 of every generation file
74
- and every revision), renames the directory, then replaces `CURRENT` last.
73
+ against the previous one, writes `manifest.json` (SHA-256 of every generation file,
74
+ revision and admitted receipt), renames the directory, then replaces `CURRENT` last.
75
75
  5. Any reader runs `validate <run>` first. A mismatch between `CURRENT`, the manifest
76
76
  and file bytes is a mixed generation: stop applying and republish.
77
77
 
@@ -79,6 +79,16 @@ A crash leaves an incomplete `g<N+1>.tmp` or a complete `g<N+1>` not yet current
79
79
  `validate` reports both, `stage` refuses until you inspect it, and the previous
80
80
  generation stays intact. One atomic rename is not a transaction; readers verify
81
81
  digests.
82
+
83
+ Publishing first seals each admitted receipt's exact bytes in `manifest.receipts`.
84
+ Later generations retain those digests and each settled task/attempt's original
85
+ receipt path, even when the attempt leaves the dispatch ledger. Receipt changes
86
+ invalidate both `validate` and the next `publish`; a caller's new path or digest
87
+ cannot replace settled authority. Preserve the original receipt and record new work
88
+ as a new attempt. A manifest without receipt bindings is not trusted.
89
+ `admit receipt` remains read-only: settlement is recorded in the stage and sealed by
90
+ `publish`, not by changing the current generation during admission.
91
+
82
92
  Give run files restrictive permissions, redact secrets before storing evidence, and
83
93
  never store credentials, tokens or private keys.
84
94
 
@@ -122,20 +132,23 @@ for needs-validation, evidence for decided findings, `verified_by` naming an adm
122
132
  verifier attempt, repository-relative locations (external ones are labels, never
123
133
  host paths); `revisions.plan.file` equal to `revisions/plan-r<rev>.json`, required
124
134
  once approvals or writers exist; plan digest pins; known, acyclic dependencies;
125
- allowed paths that are exact files inside the repository (no `*` or `?`, no
135
+ non-empty arrays of allowed paths that are exact files inside the repository (no `*` or `?`, no
126
136
  directories, no `.git` component or run-area path in any letter case or through a
127
137
  symlink, no symlink or traversal escape); a separate verifier role;
128
138
  approval and `accept-degradation` events with quote and trusted channel, approvals
129
139
  matching the plan digest, closure and current revision, none active after a later
130
- stop; a scorecard only with `revisions.rubric` and the same verdict as `run.json`;
140
+ stop; a scorecard only with `revisions.rubric`, the same verdict as `run.json`, and
141
+ `inputs` digests matching the exact selected rubric, results and gates bytes;
131
142
  `READY_FOR_USER_REVIEW` only with a scorecard whose verdict is `MEETS_TARGETS`, and
132
143
  `COMPLETED_WITH_APPROVED_DEGRADATION` only with `MEETS_TARGETS_WITH_APPROVED_DEGRADATION`,
133
144
  each listing every audit gate (plus every repair gate outside assessment-only runs) as
134
145
  `PASS` or `NOT_APPLICABLE` (`G-CONCURRENCY` may be `WAIVED_OPERATIONAL` for the degraded outcome);
135
146
  no approval or writer in an assessment-only run; unchanged `run_id`, `repo_root`,
136
147
  `mode` and `assessment_only`; writers authorized for their task; one live writer
137
- per path (case-folded, symlink-resolved); every attempt `admitted`, `rejected` or
138
- `cancelled` once the outcome leaves `RUNNING` (`timed-out` and `unknown` are not settled); one outcome per approved task at the end;
148
+ per authoritative task path (case-folded, symlink-resolved), reserving the whole
149
+ approved `allowed_paths` scope even when `write_paths` is omitted or narrower;
150
+ every attempt `admitted`, `rejected` or `cancelled` once the outcome leaves `RUNNING`
151
+ (`timed-out` and `unknown` are not settled); one outcome per approved task at the end;
139
152
  a coverage denominator that never shrinks; append-only cycles, findings history and
140
153
  approval events; immutable revisions; view stamps; manifest integrity; stale stages
141
154
  and interrupted publishes. Across records: every finding's `domain` is a score key;
@@ -146,8 +159,10 @@ inside the run; coverage ranges use the seven coverage states; a scorecard's
146
159
  `G-NO-CRITICAL-HIGH` PASS needs no open critical or high finding,
147
160
  `G-NO-OPEN-SERIOUS-LEAD` PASS no open lead with critical or high potential impact,
148
161
  and `G-COVERAGE` PASS a non-empty matrix with no blocked cell, every applicable cell
149
- closed by an admitted, non-gap receipt whose `domains_checked` lists its domain, and every range of
150
- every eligible file reviewed or excluded.
162
+ closed by an admitted, non-gap receipt whose `domains_checked` lists its domain and
163
+ whose lane matches the cell, with receipt schema, run, task, attempt, role, lane and
164
+ snapshot matching the admitted dispatch identity; every range of every eligible file
165
+ reviewed or excluded.
151
166
 
152
167
  Receipt admission and quote anchoring live in `devrites-engine overhaul admit`
153
168
  ([`orchestration.md`](orchestration.md#admission-tool)).
@@ -201,8 +201,13 @@ read-only (`GIT_OPTIONAL_LOCKS=0`, `diff.autoRefreshIndex=false`, no external di
201
201
  drivers or textconv, fixed `a/` `b/` prefixes), never stashes, never commits and
202
202
  leaves `.git/index` byte-identical; it refuses an index with unmerged entries.
203
203
  Submodules and nested repositories are recorded as boundaries, never read. The plan
204
- pins the baseline manifest digest, so approval binds it. Use `state` before and
205
- `delta` after each writer attempt to observe exactly the paths that attempt changed.
204
+ pins the baseline manifest digest, so approval binds it. Per-attempt `state`/`delta`
205
+ observe whole-repository changes, not writer attribution. Serialize each shared-root
206
+ target-mutating writer from its before-capture through stopping, after-capture and
207
+ receipt admission before starting another writer, even for disjoint task paths.
208
+ Preserve the full delta, including user changes; changes outside the approved task
209
+ scope reject admission rather than being filtered out. Read-only review and
210
+ verification may overlap on immutable inputs when their resources permit.
206
211
 
207
212
  Re-fingerprint before each edit and after each check. When user edits touch an
208
213
  assigned path or its decisive assumptions (`verify` reports changes outside
@@ -259,3 +259,10 @@ written. `G-THRESHOLDS` and `G-MANDATORY` are computed; `validate` rejects a
259
259
  scorecard whose `G-NO-CRITICAL-HIGH`, `G-NO-OPEN-SERIOUS-LEAD` or `G-COVERAGE` PASS
260
260
  contradicts `findings.json` or `coverage.json`, and a control recorded PASS while a
261
261
  linked finding is still open ([`records.md`](records.md#enforced-versus-review-only)).
262
+ `publish` and `validate` bind `scorecard.json.inputs.{rubric_sha256,results_sha256,gates_sha256}`
263
+ to the exact file bytes read by the calculator: `run.json.revisions.rubric.file`,
264
+ the selected generation's `results-candidate.json` when present (otherwise
265
+ `results-baseline.json`), and that generation's `gates.json`. Calculate from those
266
+ paths before publication. Missing or mismatched inputs reject the generation;
267
+ records never recalculate a card or replace its digests to make it current.
268
+
@@ -99,26 +99,26 @@ Same-worktree multi-writer / root-emulated worktrees stay forbidden.
99
99
 
100
100
  ## Run
101
101
 
102
- Same-worktree (non-isolated) dispatch claims before writing: the `dispatch open`
103
- below adds `--claim-session <id>`, one `--claim <path>` per task path, and
104
- `--claim-ttl <minutes>` sized to the write; it runs the
105
- `claim check --session <id> <task-paths>` test, and a live foreign holder fails the
106
- open with no wave and no claim and stops the dispatch, per
107
- [`agents.md`](skill://devrites-lib/reference/standards/agents.md). `.devrites/**`
108
- is never a task path; see [Workflow Artifact admission](skill://devrites-lib/reference/standards/workflow-artifacts.md).
102
+ Before same-tree writing, `dispatch open` adds `--claim-session <id>`,
103
+ `--claim <path>` per task path, and `--claim-ttl <minutes>` sized to the write.
104
+ It runs `claim check --session <id> <task-paths>`. Live foreign or abandoned
105
+ unreleased/nonterminal claims (even same-session/expired) refuse without a wave
106
+ or new claim, per [`agents.md`](skill://devrites-lib/reference/standards/agents.md).
107
+ `.devrites/**` is never a task path; see [Workflow Artifact admission](skill://devrites-lib/reference/standards/workflow-artifacts.md).
109
108
  Render the contract with `devrites-engine packet <slug> --wave <wave> --phase build
110
109
  --role slice-wright --slice <SLICE-ID> [--checks <G-ID,...>] [--focus <file>]` (it
111
110
  writes the linted same-worktree `packets/<wave>.contract.md`; a native-worktree pilot
112
- writes its own contract with `Isolation`, `worktree_base`, and subject) and hand the wright that text verbatim. Reviewers read
113
- that file, so `--focus` rows state each defect to fix with its anchor, never a reviewer's verdict,
114
- count, or pass status ("code review is no-findings" voids the next review). Ask the host
115
- for the exact writer in fresh context; a repair round on the same slice whose
116
- returned wright the host can still continue goes to that wright on its existing
117
- handle instead, so it does not re-read the slice from scratch. Wait, and track it
118
- through the launch barrier — `devrites-engine dispatch <slug> open --phase build --wave
119
- <slice-id> --role slice-wright --slice <SLICE-ID> --contract <file>` (it refuses a
111
+ writes its own contract with `Isolation`, `worktree_base`, and subject). Give it
112
+ verbatim. Reviewers read it: `--focus` names defect + anchor, never a prior
113
+ verdict, count, or pass claim. Ask the exact writer in fresh context; a repair
114
+ may continue the returned wright's existing handle if the host supports it,
115
+ avoiding a reread. Track the launch barrier — `devrites-engine dispatch <slug> open --phase build --wave
116
+ <wave-id> --role slice-wright --slice <SLICE-ID> --contract <file>` (it refuses a
120
117
  contract that forbids writer-safe checks or names none), then `start` with the host handle
121
- (the last start seals the wave) and `return` on completion (auto-records dispatch/return metrics). Every 5 wright
118
+ (the last start seals the wave) and `return --wave <wave-id> --role slice-wright
119
+ --handle <id>` on completion (auto-records dispatch/return metrics). Every wave ID
120
+ is single-use: use a fresh ID for each repair or retry, even after abandonment;
121
+ the earlier wave keeps its handles, history, and any unreleased claim. Every 5 wright
122
122
  rounds on one slice, `open` blocks for a reslice review. First re-admit each
123
123
  finding still driving rounds under the Proportionality rule of
124
124
  [agents.md § Result admission](skill://devrites-lib/reference/standards/agents.md#result-admission): one without a broken anchor or a reachable trigger becomes a
@@ -129,7 +129,7 @@ open findings move to the new slice owning their paths), or record
129
129
  `## <DRIFT-ID> — <SLICE-ID> reslice review` with why no smaller split exists and
130
130
  a spec trace of the slice's obligations (hardening no AC/INV/PROH requires moves to
131
131
  a sibling slice dependents do not need, still gated before Seal), and
132
- reopen with `--reslice-review <DRIFT-ID>`. Same-worktree stays one writer.
132
+ open a fresh wave with `--reslice-review <DRIFT-ID>`. Same-worktree stays one writer.
133
133
  Never run two writers in one worktree, mix isolated and same-worktree writers,
134
134
  or substitute a generic agent. Sanctioned parallel dispatch uses one exact
135
135
  wright per worktree, source-local `slice-wright.<SLICE-ID>` roles and starts
@@ -59,34 +59,34 @@ dispatch uses
59
59
  remains.
60
60
  5. **Write the verdict.** Write `Decision coverage: CLEAR` only after re-reading all inputs and confirming
61
61
  every material row has current evidence and an owner. Normal flow sets `phase=clarify` and
62
- `next_action=/rite-temper`. A low-stakes spec — the significance trigger temper itself
63
- skips (rite-temper step 1) — sets `next_action=/rite-define` instead. A contract-neutral later-phase return uses
64
- the native restore below; changed behavior or acceptance routes to
65
- `/rite-plan repair` instead. Stop without starting the next phase.
62
+ `next_action=/rite-temper`, or `/rite-define` for low-stakes specs temper skips.
63
+ Later-phase entries follow the ownership protocol below. Return inline verdicts
64
+ to the controlling caller; otherwise stop before starting the next phase.
66
65
 
67
66
  ## Native clarify cursor protocol
68
67
 
69
- The controlling root edits only cursor rows in `state.md`; it must preserve unrelated Markdown and the file's existing table/bullet presentation.
70
-
71
- - **Normal entry from Spec:** set `phase=clarify`, `status=running`, and
72
- `next_action=/rite-clarify <slug>`; omit both return fields.
73
- - **Already in Clarify:** no-op. Do not overwrite an existing valid return
74
- cursor.
75
- - **Later-phase entry:** only `temper`, `define`, `plan`, `vet`, `build`,
76
- `converge`, `prove`, `polish`, `review`, `seal`, or `ship` may return. First
77
- copy the current `phase` and non-empty `next_action` to `return_phase` and
78
- `return_next_action`; then set `phase=clarify`, `status=running`, and
79
- `next_action=/rite-clarify <slug>`. Missing/unknown cursor values fail closed
80
- before any write.
81
- - **Contract-neutral restore:** after a fresh `Decision coverage: CLEAR`, require
82
- `phase=clarify`, both return fields, a recognized later `return_phase`, and a
83
- non-empty `return_next_action`. Restore those values to `phase` and
84
- `next_action`, set `status=running`, and remove both return fields in the same
85
- rewrite. Re-read the cursor and confirm the return rows are absent.
86
- - **Contract changed:** do not restore the saved cursor. Record drift and route
87
- through `/rite-plan repair`, which owns the changed plan and next action.
88
-
89
- Never normalize or rewrite the rest of `state.md` while applying this protocol.
68
+ Edit only cursor rows; preserve unrelated Markdown and table/bullet presentation.
69
+
70
+ - **Validate before writes:** require no return fields or a complete pair:
71
+ recognized later `return_phase`, non-empty `return_next_action`. Invalid/half
72
+ pairs fail closed. Later phases: `temper`, `define`, `plan`, `vet`, `build`,
73
+ `converge`, `prove`, `polish`, `review`, `seal`, `ship`.
74
+ - **Spec entry:** set `phase=clarify`, `status=running`,
75
+ `next_action=/rite-clarify <slug>`; omit return fields.
76
+ - **Caller-owned pair:** pair with `phase!=clarify` requires a native
77
+ controlling caller; otherwise stop for ownership recovery. Run bounded Clarify
78
+ inline, preserve all cursor rows, and return its verdict to caller.
79
+ Contract changes require Plan repair and Vet before outer resume.
80
+ - **Clarify-owned pair:** standalone later-phase entry without a pair saves current
81
+ phase/non-empty next action as the pair, then sets `phase=clarify`,
82
+ `status=running`, `next_action=/rite-clarify <slug>`. Missing/unknown values
83
+ fail closed. `phase=clarify` resumes without writes; its pair belongs to
84
+ standalone Clarify, not a nested caller.
85
+ - **Restore:** after fresh `CLEAR`, only the owner restores its pair.
86
+ Contract-neutral standalone Clarify restores phase/next action, sets
87
+ `status=running`, atomically unsets both return fields, and re-reads to verify.
88
+ Contract changes retain the pair through Plan repair and Vet; only its owner
89
+ consumes it after readiness. Preserve caller pairs.
90
90
 
91
91
  ## Output
92
92