@azure-id/orc 1.7.1 → 1.8.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 (63) hide show
  1. package/CHANGELOG.md +3869 -3381
  2. package/README-id.md +942 -844
  3. package/README.md +882 -788
  4. package/bin/build-agents.js +43 -27
  5. package/bin/cli.js +45460 -44169
  6. package/bin/graph-extract.js +3216 -0
  7. package/bin/graph-gain.js +404 -0
  8. package/bin/graph-map.js +232 -0
  9. package/bin/graph-notes.js +229 -0
  10. package/bin/graph-query.js +1770 -0
  11. package/bin/graph-resolve.js +255 -0
  12. package/bin/graph-shard.js +325 -0
  13. package/bin/graph-signals.js +277 -0
  14. package/bin/graph.js +658 -0
  15. package/bin/verify-contracts.js +4809 -4553
  16. package/bin/verify-package.js +640 -616
  17. package/bin/webui/api.js +1425 -1414
  18. package/bin/webui/fixtures/index.js +584 -576
  19. package/bin/webui/fixtures/knowledge.js +356 -291
  20. package/bin/webui/fixtures/stats.js +107 -104
  21. package/bin/webui/i18n/en/knowledge.json +182 -151
  22. package/bin/webui/i18n/en/overview.json +101 -100
  23. package/bin/webui/i18n/id/knowledge.json +182 -151
  24. package/bin/webui/i18n/id/overview.json +101 -100
  25. package/bin/webui/js/panels/knowledge.js +1130 -1006
  26. package/bin/webui/js/panels/overview.js +492 -488
  27. package/package.json +39 -39
  28. package/templates/agents/MODEL-MAPPING.md +163 -158
  29. package/templates/agents/orc-executor-haiku-4-5.md +128 -121
  30. package/templates/agents/orc-executor-opus-4-7-high.md +129 -122
  31. package/templates/agents/orc-executor-opus-4-7-med.md +129 -122
  32. package/templates/agents/orc-executor-opus-4-8-high.md +129 -122
  33. package/templates/agents/orc-executor-opus-5-high.md +129 -122
  34. package/templates/agents/orc-executor-opus-5-low.md +129 -122
  35. package/templates/agents/orc-executor-opus-5-med.md +129 -122
  36. package/templates/agents/orc-executor-sonnet-4-6-high.md +129 -122
  37. package/templates/agents/orc-executor-sonnet-4-6-med.md +129 -122
  38. package/templates/agents/orc-executor-sonnet-5-high.md +129 -122
  39. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +89 -0
  40. package/templates/hooks/README.md +454 -396
  41. package/templates/hooks/orc-graph-hook.js +471 -0
  42. package/templates/hooks/orc-statusline-render.js +922 -921
  43. package/templates/hooks/orc-statusline.js +1596 -1545
  44. package/templates/skills/_shared/README.md +4 -0
  45. package/templates/skills/_shared/code-graph.md +348 -0
  46. package/templates/skills/_shared/opus5-only.md +4 -0
  47. package/templates/skills/_shared/phases/execution.md +168 -147
  48. package/templates/skills/_shared/phases/planning.md +149 -135
  49. package/templates/skills/_shared/phases/preflight.md +132 -118
  50. package/templates/skills/_shared/phases/review.md +63 -53
  51. package/templates/skills/_shared/phases/ship.md +100 -88
  52. package/templates/skills/_shared/phases/trace.md +8 -0
  53. package/templates/skills/_shared/phases/wiki-consult.md +194 -189
  54. package/templates/skills/_shared/read-ladder.md +132 -102
  55. package/templates/skills/_shared/return-validation.md +259 -250
  56. package/templates/skills/orc/SKILL.md +255 -254
  57. package/templates/skills/orc-analyze/SKILL.md +13 -13
  58. package/templates/skills/orc-diy/references/flow-schema.md +101 -100
  59. package/templates/skills/orc-fast/SKILL.md +236 -229
  60. package/templates/skills/orc-mini/SKILL.md +267 -259
  61. package/templates/skills/orc-quick/SKILL.md +378 -361
  62. package/templates/skills/orc-quick/references/dispatch-gate.md +6 -0
  63. package/templates/skills/orc-wiki/references/staleness.md +294 -288
@@ -1,250 +1,259 @@
1
- # Return validation (every lane, every subagent return)
2
-
3
- Canonical procedure for validating a spawned agent's return. Every ORC lane
4
- (full, mini, fast, wiki, diy) runs this on EVERY return; a malformed return is
5
- a failure (requeue/re-dispatch with reason — lane sets the retry cap).
6
-
7
- ## 0. Is the previous attempt still ALIVE? (v1.2.0) — BEFORE anything else
8
-
9
- > **`a lane that re-dispatches over a live attempt` has broken this contract.**
10
-
11
- **A Task error does not kill the agent behind it.** Claude Code's tool call can
12
- fail, time out, or be cut off mid-turn while the subagent it started keeps
13
- running — and keeps writing files. Every rule below this line ends in
14
- "re-dispatch", and every one of them silently assumed a failed call meant a dead
15
- agent. It does not.
16
-
17
- What that costs, measured: one graded `/orc-quick` entry put THREE
18
- `orc-executor-opus-5-low` agents on the SAME task — 50m19s, 115m22s and
19
- 100m53s, **266 minutes of Opus 5 for one authorised dispatch**, all editing the
20
- same files, inside a 2h04m window. The second was dispatched 4m19s after the
21
- first, while the first was still working. The hook had recorded all three; no
22
- lane had ever read that record.
23
-
24
- ### The rule
25
-
26
- Before ANY re-dispatch, requeue or repair round — and before the first dispatch
27
- of a resumed run — run:
28
-
29
- ```
30
- orc run inflight --json # 0 clear · 1 in-flight · 2 unknown
31
- ```
32
-
33
- | exit | meaning | what the lane does |
34
- |---|---|---|
35
- | 0 | provably nothing in flight | dispatch |
36
- | 1 | ≥1 dispatch has not returned | **REFUSE. Name the agent, the task and its age.** Ask the user. |
37
- | 2 | cannot prove either way | **REFUSE by default.** Say why, and let the USER decide. |
38
-
39
- **Exit 2 refuses, and that is deliberate.** Everywhere else in ORC an absent
40
- reading is treated as absent and never blocks — `orc usage check` exit 2 never
41
- stops a run, an UNCHECKABLE pact never raises the exit code. This is the one
42
- place the default inverts, because the two outcomes are not symmetrical: a
43
- wrongly-refused dispatch costs one question, and a wrongly-issued one costs a
44
- second Opus agent for an hour. Refusing on `unknown` is the cheap error.
45
-
46
- ### An interrupted turn is UNKNOWN, never FAILED
47
-
48
- A usage limit, an API error, a dropped connection or a `Ctrl+C` between a
49
- dispatch and its return says **nothing** about the agent. Treat it as §0 exit 2
50
- and ask. A lane that classifies an interruption as a failure re-dispatches into
51
- a live agent, gets interrupted again sooner because it is now paying twice, and
52
- the loop tightens on itself — which is exactly how the 266-minute entry
53
- happened.
54
-
55
- ### What refusing looks like
56
-
57
- ```
58
- ⛔ 1 dispatch is still in flight — not re-dispatching.
59
-
60
- orc-executor-opus-5-low started 4m ago
61
- "Fix approval flow defects"
62
-
63
- A Task error does not kill the agent behind it. It may still be writing.
64
- 1. wait for it 2. dispatch anyway (2 agents on one task) 3. stop
65
- ```
66
-
67
- Option 2 must always be offered and never be the default: the user is allowed
68
- to overrule this, and an unreadable sidecar must never trap a run.
69
-
70
- ### The evidence, and its one honest limit
71
-
72
- `orc run inflight` reads the pending sidecar that `orc-trace.js` writes on every
73
- `SPAWN`, cross-checked against the trace's own SPAWN/RETURN balance. It reports
74
- `unknown` — never `clear` — when the sidecar is missing, unreadable, or holds
75
- only records older than six hours, and when the sidecar and the trace disagree.
76
- **Unknown is not zero.**
77
-
78
- It cannot see an **ad-hoc** dispatch (`/orc-quick` recon, model+effort rather
79
- than a pinned `orc-*` agent): the hook writes no `SPAWN` for one, so no record
80
- exists. Those are read-only and short, so the exposure is small — but the limit
81
- is stated rather than papered over, and a lane must not report `clear` as proof
82
- that an ad-hoc read is finished.
83
-
84
- ## 1. Contract shape
85
-
86
- The return must carry every field its agent contract names. Missing or extra
87
- shape = malformed. Never repair a return yourself; re-dispatch.
88
-
89
- ## 2. Claimed-vs-actual model (tier-downgrade check)
90
-
91
- Every return carries:
92
-
93
- - `actual_model` — quoted VERBATIM from the agent's system-prompt model-id
94
- line, never inferred (`unknown` when no such line exists)
95
- - `actual_effort` — the agent's `$CLAUDE_EFFORT` value
96
-
97
- Compare both against what the dispatch expected (the agent NAME encodes it).
98
- Append the `VERIFY` trace line with the comparison; any mismatch is surfaced
99
- to the user as a ⛔ DOWNGRADE — never silently accepted. (A subagent can't
100
- exceed the MAIN session's tier, so a downgrade usually means the main session
101
- is on the wrong model.)
102
-
103
- ## 2b. A FOREIGN return — the SUBSTITUTION check (v0.50.0)
104
-
105
- A foreign worker (`orc extra dispatch`, `_shared/extra-dispatch.md`) is not a
106
- Claude subagent. It has no injected system-prompt model-id line, so **it cannot
107
- carry `actual_model`** — and §2 must not be faked for it. A foreign return that
108
- claimed an `actual_model` would be claiming evidence that does not exist.
109
-
110
- It carries instead, and every one of these is quoted from the wire rather than
111
- assumed:
112
-
113
- - `engine` (`api` | `claude-shim` | `cli`), `provider`, `profile`
114
- - `model_requested` — what the route row asked for
115
- - **`model_reported`** — the `model` field the endpoint echoed back
116
- - `usage` — the four token kinds, never blended, **or `null`**
117
-
118
- **`model_reported != model_requested` is ⛔ SUBSTITUTION**, surfaced to the user
119
- exactly as ⛔ DOWNGRADE is today and never silently accepted. It is the only
120
- defence against an aggregator quietly serving something else. `unknown` is a
121
- valid, honest value and is reported as `unknown` — **never as a match**.
122
-
123
- **A clean model check is not a clean answer.** An aggregator's *provider-level*
124
- fallback is on by default and it PRESERVES the model id, so the substitution
125
- check reads clean while the code went to a different company. Engine `api`
126
- records the response's `provider` echo and reports **⚠ REROUTE**; the other two
127
- engines cannot see it at all, and their `served_by_note` says so. An absent
128
- measurement is never a pass.
129
-
130
- **`usage: null` is not four zeros.** A worker that reported no token counts
131
- (engine `cli` frequently) returns `null` plus a note. `{0,0,0,0}` would tell
132
- `/orc-budget` the run was free. Engine `api`'s `cache_write: 0` is the opposite
133
- case — a real measurement — so the two must never be normalised together.
134
-
135
- **The fence is per-engine, and the return says which one it had.** Engine `api`
136
- ENFORCES `declared_files`; engines `claude-shim` and `cli` ASK. A return
137
- carrying `fence: {declared_files: false}` means the list was an instruction, not
138
- a rule — treat §6 below as the only real check, and say so to the user rather
139
- than reporting a constraint that was never applied.
140
-
141
- **A RESUMED foreign dispatch owes three more fields** (v0.54.0). The dispatch
142
- return sets `resume_expected: true`, so the obligation is never inferred:
143
-
144
- - **`resume_state`** — `continued` · `restarted` · `no-op`. Absent on a slice
145
- with no `resumed_from` is correct; **absent on a resume slice is MALFORMED.**
146
- A return claiming `restarted` while `preexisting[]` was non-empty is a
147
- FINDING, not a failure — it is how `/orc-retro` learns which providers ignore
148
- a resume preamble, so surface it rather than treating it as a bad return.
149
- - **`preexisting_read[]`** — which pre-existing files the worker actually
150
- opened. Quoted like `wiki_used`: **what it did, never what the dispatcher
151
- assumed.** An EMPTY list on a resume whose `preexisting[]` was not empty is an
152
- honest and informative return — it says the worker ignored the preamble — and
153
- it must be surfaced, never dropped.
154
- - **`journal_fidelity`** — relayed from the dispatch return (`per-turn` |
155
- `streamed-opaque`), so a validator never reports `streamed-opaque` evidence as
156
- if it had per-turn tool attribution.
157
-
158
- Everything else in this file applies to a foreign return unchanged: the
159
- honest-status rules, the pattern attestation, the TDD attestation, the wiki
160
- attestation, and above all **§6, the worktree delta** — which is engine-blind
161
- because it reads the worktree rather than the return, and is therefore what
162
- makes a foreign executor safe at all.
163
-
164
- ## 3. Honest-status rules (executor returns)
165
-
166
- - `status=done` on a stack with a runnable build/test REQUIRES `evidence`
167
- {command, exit_code, tail} quoted VERBATIM; a missing block or a false
168
- `no_runner_detected` is malformed.
169
- - `done` with a non-empty `unmet[]` is `partial` — treat it as such.
170
-
171
- ## 4. Pattern attestation (when a `pattern` was injected)
172
-
173
- A task that received a `pattern` slice must return `invariants_checked: true`
174
- plus the matching `pattern_version`; false/absent on a pattern task is
175
- malformed.
176
-
177
- ## 5. TDD attestation (when a `tdd_spec` was injected — v0.33.0)
178
-
179
- A task whose slice carried a `tdd_spec` must return `tdd_state: green|red` —
180
- `green` only with the passing run quoted in `evidence`; `status=done` with
181
- `tdd_state: red` (or an absent field) is malformed. `red` is an HONEST return:
182
- the lane runs its repair loop up to `tdd_loop_max`, then STOPS with the red
183
- report — never re-dispatch past the cap.
184
-
185
- ## 5b. Wiki attestation (when wiki content or page pointers were injected — v0.41.0)
186
-
187
- A task whose slice carried wiki material must return **`wiki_used`** — the doc
188
- paths it ACTUALLY read, or `none`. Quoted like `actual_model`: what the agent
189
- did, never what the dispatcher assumed.
190
-
191
- `none` is a valid and INFORMATIVE return, not a failure: it says the pages were
192
- not useful or were ignored. Record it and surface it — a wiki whose pages are
193
- shipped into every slice and read by nobody is the failure mode this field
194
- exists to make visible, and it is invisible if `none` is quietly dropped. Absent
195
- on a slice that carried wiki material is malformed. Not required otherwise.
196
-
197
- ## 5c. Rules attestation (when the anti-slop card was injected — v1.7.0)
198
-
199
- A slice assembled by `orc rules slice` (`phases/rules.md`) must return three
200
- fields. All three may be empty; **absent is malformed**, because an empty array
201
- and a missing one are the difference between "nothing applied" and "nobody
202
- looked".
203
-
204
- | Field | What it holds | Empty means |
205
- |---|---|---|
206
- | `rules_applied[]` | the rule ids the agent acted on | it changed nothing for this task |
207
- | `rules_conflicts[]` | two rules that disagree, each named by id or quote | none collided |
208
- | `rules_overridden[]` | an ORC id a project rule replaced | the project replaced none |
209
-
210
- **A `rules_conflicts[]` entry is a GAP, never a resolution.** Relay it through
211
- the lane's own gap channel and let the user decide. An agent that quietly picks
212
- a winner has made a standing decision for the project in a slice nobody will
213
- read again.
214
-
215
- `rules_overridden[]` is cross-checked against the `overrides` the CLI already
216
- computed. The agent may return MORE than the CLI counted — the CLI only counts
217
- ids a user NAMED, and the agent is the only reader that can spot an unnamed
218
- contradiction — but an id the CLI listed and the return omits means the card was
219
- not read.
220
-
221
- A rule the slice could not honour because this lane structurally cannot do it
222
- comes back as `unsupported_request`, relayed as a gap. **Never a guessed
223
- compromise.**
224
-
225
- ## 6. Worktree delta (post-wave, every lane that dispatches executors)
226
-
227
- Compare `git status --short` before and after each dispatch. A path that
228
- appears, disappears, or **reverts** and is absent from that task's
229
- `declared_files` is a slice violation regardless of what the return said —
230
- including a file that became LESS modified, which is how a destructive `git`
231
- command inside a slice disguises itself as a clean tree. `actual_files` is a
232
- CLAIM; the worktree is the EVIDENCE. An unexplained delta gates the wave: name
233
- it, attribute it, and get a decision before closing.
234
-
235
- **On a RESUMED task the "before" side of the delta is the JOURNAL BASELINE**
236
- (`orc extra reconcile`, `_shared/extra-dispatch.md`), not the state at the top of
237
- this wave. A file the previous attempt created is already in the tree and is
238
- **not** an unexplained delta — it is explained, by the journal, by name. Without
239
- that the first resumed wave trips its own gate on the work it just recovered.
240
-
241
- ## 7. Gotcha capture (repair loops only — v0.40.0)
242
-
243
- A return that closes a repair loop (`tdd_state` went red → green, a drift
244
- round resolved, a reviewer P0/P1 was fixed in-run) carries
245
- `gotcha_recorded` — either the entry body (`trigger`, `symptom`, `cause`,
246
- `fix`, `scope`) or `none` with a one-line reason. Absent on a repair-closing
247
- return is malformed. It is NOT required on a return that never repaired
248
- anything, and a loop that hit its cap and STOPPED must return `none` — an
249
- unsolved failure is not a gotcha. The agent RETURNS the body; the
250
- orchestrator writes the file. See `gotchas.md`.
1
+ # Return validation (every lane, every subagent return)
2
+
3
+ Canonical procedure for validating a spawned agent's return. Every ORC lane
4
+ (full, mini, fast, wiki, diy) runs this on EVERY return; a malformed return is
5
+ a failure (requeue/re-dispatch with reason — lane sets the retry cap).
6
+
7
+ ## 0. Is the previous attempt still ALIVE? (v1.2.0) — BEFORE anything else
8
+
9
+ > **`a lane that re-dispatches over a live attempt` has broken this contract.**
10
+
11
+ **A Task error does not kill the agent behind it.** Claude Code's tool call can
12
+ fail, time out, or be cut off mid-turn while the subagent it started keeps
13
+ running — and keeps writing files. Every rule below this line ends in
14
+ "re-dispatch", and every one of them silently assumed a failed call meant a dead
15
+ agent. It does not.
16
+
17
+ What that costs, measured: one graded `/orc-quick` entry put THREE
18
+ `orc-executor-opus-5-low` agents on the SAME task — 50m19s, 115m22s and
19
+ 100m53s, **266 minutes of Opus 5 for one authorised dispatch**, all editing the
20
+ same files, inside a 2h04m window. The second was dispatched 4m19s after the
21
+ first, while the first was still working. The hook had recorded all three; no
22
+ lane had ever read that record.
23
+
24
+ ### The rule
25
+
26
+ Before ANY re-dispatch, requeue or repair round — and before the first dispatch
27
+ of a resumed run — run:
28
+
29
+ ```
30
+ orc run inflight --json # 0 clear · 1 in-flight · 2 unknown
31
+ ```
32
+
33
+ | exit | meaning | what the lane does |
34
+ |---|---|---|
35
+ | 0 | provably nothing in flight | dispatch |
36
+ | 1 | ≥1 dispatch has not returned | **REFUSE. Name the agent, the task and its age.** Ask the user. |
37
+ | 2 | cannot prove either way | **REFUSE by default.** Say why, and let the USER decide. |
38
+
39
+ **Exit 2 refuses, and that is deliberate.** Everywhere else in ORC an absent
40
+ reading is treated as absent and never blocks — `orc usage check` exit 2 never
41
+ stops a run, an UNCHECKABLE pact never raises the exit code. This is the one
42
+ place the default inverts, because the two outcomes are not symmetrical: a
43
+ wrongly-refused dispatch costs one question, and a wrongly-issued one costs a
44
+ second Opus agent for an hour. Refusing on `unknown` is the cheap error.
45
+
46
+ ### An interrupted turn is UNKNOWN, never FAILED
47
+
48
+ A usage limit, an API error, a dropped connection or a `Ctrl+C` between a
49
+ dispatch and its return says **nothing** about the agent. Treat it as §0 exit 2
50
+ and ask. A lane that classifies an interruption as a failure re-dispatches into
51
+ a live agent, gets interrupted again sooner because it is now paying twice, and
52
+ the loop tightens on itself — which is exactly how the 266-minute entry
53
+ happened.
54
+
55
+ ### What refusing looks like
56
+
57
+ ```
58
+ ⛔ 1 dispatch is still in flight — not re-dispatching.
59
+
60
+ orc-executor-opus-5-low started 4m ago
61
+ "Fix approval flow defects"
62
+
63
+ A Task error does not kill the agent behind it. It may still be writing.
64
+ 1. wait for it 2. dispatch anyway (2 agents on one task) 3. stop
65
+ ```
66
+
67
+ Option 2 must always be offered and never be the default: the user is allowed
68
+ to overrule this, and an unreadable sidecar must never trap a run.
69
+
70
+ ### The evidence, and its one honest limit
71
+
72
+ `orc run inflight` reads the pending sidecar that `orc-trace.js` writes on every
73
+ `SPAWN`, cross-checked against the trace's own SPAWN/RETURN balance. It reports
74
+ `unknown` — never `clear` — when the sidecar is missing, unreadable, or holds
75
+ only records older than six hours, and when the sidecar and the trace disagree.
76
+ **Unknown is not zero.**
77
+
78
+ It cannot see an **ad-hoc** dispatch (`/orc-quick` recon, model+effort rather
79
+ than a pinned `orc-*` agent): the hook writes no `SPAWN` for one, so no record
80
+ exists. Those are read-only and short, so the exposure is small — but the limit
81
+ is stated rather than papered over, and a lane must not report `clear` as proof
82
+ that an ad-hoc read is finished.
83
+
84
+ ## 1. Contract shape
85
+
86
+ The return must carry every field its agent contract names. Missing or extra
87
+ shape = malformed. Never repair a return yourself; re-dispatch.
88
+
89
+ ## 2. Claimed-vs-actual model (tier-downgrade check)
90
+
91
+ Every return carries:
92
+
93
+ - `actual_model` — quoted VERBATIM from the agent's system-prompt model-id
94
+ line, never inferred (`unknown` when no such line exists)
95
+ - `actual_effort` — the agent's `$CLAUDE_EFFORT` value
96
+
97
+ Compare both against what the dispatch expected (the agent NAME encodes it).
98
+ Append the `VERIFY` trace line with the comparison; any mismatch is surfaced
99
+ to the user as a ⛔ DOWNGRADE — never silently accepted. (A subagent can't
100
+ exceed the MAIN session's tier, so a downgrade usually means the main session
101
+ is on the wrong model.)
102
+
103
+ ## 2b. A FOREIGN return — the SUBSTITUTION check (v0.50.0)
104
+
105
+ A foreign worker (`orc extra dispatch`, `_shared/extra-dispatch.md`) is not a
106
+ Claude subagent. It has no injected system-prompt model-id line, so **it cannot
107
+ carry `actual_model`** — and §2 must not be faked for it. A foreign return that
108
+ claimed an `actual_model` would be claiming evidence that does not exist.
109
+
110
+ It carries instead, and every one of these is quoted from the wire rather than
111
+ assumed:
112
+
113
+ - `engine` (`api` | `claude-shim` | `cli`), `provider`, `profile`
114
+ - `model_requested` — what the route row asked for
115
+ - **`model_reported`** — the `model` field the endpoint echoed back
116
+ - `usage` — the four token kinds, never blended, **or `null`**
117
+
118
+ **`model_reported != model_requested` is ⛔ SUBSTITUTION**, surfaced to the user
119
+ exactly as ⛔ DOWNGRADE is today and never silently accepted. It is the only
120
+ defence against an aggregator quietly serving something else. `unknown` is a
121
+ valid, honest value and is reported as `unknown` — **never as a match**.
122
+
123
+ **A clean model check is not a clean answer.** An aggregator's *provider-level*
124
+ fallback is on by default and it PRESERVES the model id, so the substitution
125
+ check reads clean while the code went to a different company. Engine `api`
126
+ records the response's `provider` echo and reports **⚠ REROUTE**; the other two
127
+ engines cannot see it at all, and their `served_by_note` says so. An absent
128
+ measurement is never a pass.
129
+
130
+ **`usage: null` is not four zeros.** A worker that reported no token counts
131
+ (engine `cli` frequently) returns `null` plus a note. `{0,0,0,0}` would tell
132
+ `/orc-budget` the run was free. Engine `api`'s `cache_write: 0` is the opposite
133
+ case — a real measurement — so the two must never be normalised together.
134
+
135
+ **The fence is per-engine, and the return says which one it had.** Engine `api`
136
+ ENFORCES `declared_files`; engines `claude-shim` and `cli` ASK. A return
137
+ carrying `fence: {declared_files: false}` means the list was an instruction, not
138
+ a rule — treat §6 below as the only real check, and say so to the user rather
139
+ than reporting a constraint that was never applied.
140
+
141
+ **A RESUMED foreign dispatch owes three more fields** (v0.54.0). The dispatch
142
+ return sets `resume_expected: true`, so the obligation is never inferred:
143
+
144
+ - **`resume_state`** — `continued` · `restarted` · `no-op`. Absent on a slice
145
+ with no `resumed_from` is correct; **absent on a resume slice is MALFORMED.**
146
+ A return claiming `restarted` while `preexisting[]` was non-empty is a
147
+ FINDING, not a failure — it is how `/orc-retro` learns which providers ignore
148
+ a resume preamble, so surface it rather than treating it as a bad return.
149
+ - **`preexisting_read[]`** — which pre-existing files the worker actually
150
+ opened. Quoted like `wiki_used`: **what it did, never what the dispatcher
151
+ assumed.** An EMPTY list on a resume whose `preexisting[]` was not empty is an
152
+ honest and informative return — it says the worker ignored the preamble — and
153
+ it must be surfaced, never dropped.
154
+ - **`journal_fidelity`** — relayed from the dispatch return (`per-turn` |
155
+ `streamed-opaque`), so a validator never reports `streamed-opaque` evidence as
156
+ if it had per-turn tool attribution.
157
+
158
+ Everything else in this file applies to a foreign return unchanged: the
159
+ honest-status rules, the pattern attestation, the TDD attestation, the wiki
160
+ attestation, and above all **§6, the worktree delta** — which is engine-blind
161
+ because it reads the worktree rather than the return, and is therefore what
162
+ makes a foreign executor safe at all.
163
+
164
+ ## 3. Honest-status rules (executor returns)
165
+
166
+ - `status=done` on a stack with a runnable build/test REQUIRES `evidence`
167
+ {command, exit_code, tail} quoted VERBATIM; a missing block or a false
168
+ `no_runner_detected` is malformed.
169
+ - `done` with a non-empty `unmet[]` is `partial` — treat it as such.
170
+
171
+ ## 4. Pattern attestation (when a `pattern` was injected)
172
+
173
+ A task that received a `pattern` slice must return `invariants_checked: true`
174
+ plus the matching `pattern_version`; false/absent on a pattern task is
175
+ malformed.
176
+
177
+ ## 5. TDD attestation (when a `tdd_spec` was injected — v0.33.0)
178
+
179
+ A task whose slice carried a `tdd_spec` must return `tdd_state: green|red` —
180
+ `green` only with the passing run quoted in `evidence`; `status=done` with
181
+ `tdd_state: red` (or an absent field) is malformed. `red` is an HONEST return:
182
+ the lane runs its repair loop up to `tdd_loop_max`, then STOPS with the red
183
+ report — never re-dispatch past the cap.
184
+
185
+ ## 5b. Wiki attestation (when wiki content or page pointers were injected — v0.41.0)
186
+
187
+ A task whose slice carried wiki material must return **`wiki_used`** — the doc
188
+ paths it ACTUALLY read, or `none`. Quoted like `actual_model`: what the agent
189
+ did, never what the dispatcher assumed.
190
+
191
+ `none` is a valid and INFORMATIVE return, not a failure: it says the pages were
192
+ not useful or were ignored. Record it and surface it — a wiki whose pages are
193
+ shipped into every slice and read by nobody is the failure mode this field
194
+ exists to make visible, and it is invisible if `none` is quietly dropped. Absent
195
+ on a slice that carried wiki material is malformed. Not required otherwise.
196
+
197
+ ## 5b.1 Graph attestation (when code-graph cards were injected — v1.8.0)
198
+
199
+ A task whose slice carried `orc graph ctx` cards must return **`graph_used`** —
200
+ `{targets, generation}`: the card targets it ACTUALLY used (or `none`), and the `generation`
201
+ the cards carried. The same honesty rule as `wiki_used`: `none` is informative (the cards did
202
+ not help), absent is malformed, and a lane never drops it. A `generation` lower than the one
203
+ `orc graph status` reports now means the agent acted on an OLD index — record it, do not
204
+ re-run the task for it alone. Canonical: `code-graph.md`.
205
+
206
+ ## 5c. Rules attestation (when the anti-slop card was injected — v1.7.0)
207
+
208
+ A slice assembled by `orc rules slice` (`phases/rules.md`) must return three
209
+ fields. All three may be empty; **absent is malformed**, because an empty array
210
+ and a missing one are the difference between "nothing applied" and "nobody
211
+ looked".
212
+
213
+ | Field | What it holds | Empty means |
214
+ |---|---|---|
215
+ | `rules_applied[]` | the rule ids the agent acted on | it changed nothing for this task |
216
+ | `rules_conflicts[]` | two rules that disagree, each named by id or quote | none collided |
217
+ | `rules_overridden[]` | an ORC id a project rule replaced | the project replaced none |
218
+
219
+ **A `rules_conflicts[]` entry is a GAP, never a resolution.** Relay it through
220
+ the lane's own gap channel and let the user decide. An agent that quietly picks
221
+ a winner has made a standing decision for the project in a slice nobody will
222
+ read again.
223
+
224
+ `rules_overridden[]` is cross-checked against the `overrides` the CLI already
225
+ computed. The agent may return MORE than the CLI counted — the CLI only counts
226
+ ids a user NAMED, and the agent is the only reader that can spot an unnamed
227
+ contradiction — but an id the CLI listed and the return omits means the card was
228
+ not read.
229
+
230
+ A rule the slice could not honour because this lane structurally cannot do it
231
+ comes back as `unsupported_request`, relayed as a gap. **Never a guessed
232
+ compromise.**
233
+
234
+ ## 6. Worktree delta (post-wave, every lane that dispatches executors)
235
+
236
+ Compare `git status --short` before and after each dispatch. A path that
237
+ appears, disappears, or **reverts** and is absent from that task's
238
+ `declared_files` is a slice violation regardless of what the return said —
239
+ including a file that became LESS modified, which is how a destructive `git`
240
+ command inside a slice disguises itself as a clean tree. `actual_files` is a
241
+ CLAIM; the worktree is the EVIDENCE. An unexplained delta gates the wave: name
242
+ it, attribute it, and get a decision before closing.
243
+
244
+ **On a RESUMED task the "before" side of the delta is the JOURNAL BASELINE**
245
+ (`orc extra reconcile`, `_shared/extra-dispatch.md`), not the state at the top of
246
+ this wave. A file the previous attempt created is already in the tree and is
247
+ **not** an unexplained delta — it is explained, by the journal, by name. Without
248
+ that the first resumed wave trips its own gate on the work it just recovered.
249
+
250
+ ## 7. Gotcha capture (repair loops only — v0.40.0)
251
+
252
+ A return that closes a repair loop (`tdd_state` went red → green, a drift
253
+ round resolved, a reviewer P0/P1 was fixed in-run) carries
254
+ `gotcha_recorded` — either the entry body (`trigger`, `symptom`, `cause`,
255
+ `fix`, `scope`) or `none` with a one-line reason. Absent on a repair-closing
256
+ return is malformed. It is NOT required on a return that never repaired
257
+ anything, and a loop that hit its cap and STOPPED must return `none` — an
258
+ unsolved failure is not a gotcha. The agent RETURNS the body; the
259
+ orchestrator writes the file. See `gotchas.md`.