@azure-id/orc 1.9.2 → 2.0.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 (172) hide show
  1. package/CHANGELOG.md +321 -0
  2. package/README-id.md +21 -36
  3. package/README.md +25 -36
  4. package/bin/build-agents.js +117 -20
  5. package/bin/cli.js +725 -29
  6. package/bin/gotcha-import.js +1081 -0
  7. package/bin/gotcha.js +1286 -0
  8. package/bin/graph-query.js +1 -1
  9. package/bin/graph.js +717 -717
  10. package/bin/habit.js +1453 -0
  11. package/bin/mockrun-catalog.js +281 -276
  12. package/bin/run-undo.js +398 -0
  13. package/bin/trace-write.js +657 -0
  14. package/bin/verify-contracts.js +525 -79
  15. package/bin/verify-package.js +51 -4
  16. package/bin/webui/api.js +26 -0
  17. package/bin/webui/app.html +239 -232
  18. package/bin/webui/css/00-tokens.css +110 -92
  19. package/bin/webui/css/04-motion.css +87 -0
  20. package/bin/webui/css/06-responsive.css +203 -178
  21. package/bin/webui/css/panels/behaviour.css +205 -0
  22. package/bin/webui/fixtures/behaviour.js +532 -0
  23. package/bin/webui/fixtures/index.js +34 -0
  24. package/bin/webui/fixtures/knowledge.js +7 -1
  25. package/bin/webui/fixtures/stats.js +16 -0
  26. package/bin/webui/i18n/en/behaviour.json +143 -0
  27. package/bin/webui/i18n/en/nav.json +25 -24
  28. package/bin/webui/i18n/en/tour.json +37 -35
  29. package/bin/webui/i18n/id/behaviour.json +143 -0
  30. package/bin/webui/i18n/id/nav.json +25 -24
  31. package/bin/webui/i18n/id/tour.json +37 -35
  32. package/bin/webui/js/01-i18n.js +155 -154
  33. package/bin/webui/js/90-tour.js +498 -494
  34. package/bin/webui/js/91-shortcuts.js +126 -126
  35. package/bin/webui/js/99-boot.js +121 -118
  36. package/bin/webui/js/panels/behaviour.js +1022 -0
  37. package/mock-run/INDEX.md +109 -107
  38. package/mock-run/gotcha-import.md +118 -0
  39. package/mock-run/habits.md +129 -0
  40. package/mock-run/orc-quick.md +6 -1
  41. package/package.json +1 -1
  42. package/templates/agents/MODEL-MAPPING.md +7 -7
  43. package/templates/agents/orc-advisor-opus-5-xhigh.md +1 -7
  44. package/templates/agents/orc-analyze-mini-opus-5-med.md +1 -6
  45. package/templates/agents/orc-analyze-mini-sonnet-5-high.md +1 -4
  46. package/templates/agents/orc-claude-writer-opus-4-8-high.md +48 -53
  47. package/templates/agents/orc-claude-writer-opus-5-med.md +1 -8
  48. package/templates/agents/orc-context-combiner-opus-5-high.md +1 -11
  49. package/templates/agents/orc-executor-haiku-4-5.md +14 -6
  50. package/templates/agents/orc-executor-opus-4-7-high.md +14 -6
  51. package/templates/agents/orc-executor-opus-4-7-med.md +14 -6
  52. package/templates/agents/orc-executor-opus-4-8-high.md +14 -6
  53. package/templates/agents/orc-executor-opus-5-high.md +14 -6
  54. package/templates/agents/orc-executor-opus-5-low.md +14 -6
  55. package/templates/agents/orc-executor-opus-5-med.md +14 -6
  56. package/templates/agents/orc-executor-sonnet-4-6-high.md +14 -6
  57. package/templates/agents/orc-executor-sonnet-4-6-med.md +14 -6
  58. package/templates/agents/orc-executor-sonnet-5-high.md +14 -6
  59. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +1 -10
  60. package/templates/agents/orc-judge-opus-5-xhigh.md +5 -9
  61. package/templates/agents/orc-learn-writer-opus-5-low.md +1 -7
  62. package/templates/agents/orc-pattern-codifier-opus-5-med.md +1 -8
  63. package/templates/agents/orc-pattern-codifier-sonnet-5-high.md +58 -63
  64. package/templates/agents/orc-planner-mini-opus-5-med.md +1 -4
  65. package/templates/agents/orc-planner-mini-sonnet-5-high.md +1 -2
  66. package/templates/agents/orc-planner-opus-5-med.md +1 -4
  67. package/templates/agents/orc-recon-opus-5-low.md +1 -8
  68. package/templates/agents/orc-recon-sonnet-4-6-med.md +1 -8
  69. package/templates/agents/orc-retro-opus-5-med.md +6 -8
  70. package/templates/agents/orc-retro-sonnet-5-high.md +6 -7
  71. package/templates/agents/orc-reviewer-opus-5-med.md +52 -16
  72. package/templates/agents/orc-scout-opus-5-low.md +1 -6
  73. package/templates/agents/orc-scout-sonnet-4-6-high.md +35 -39
  74. package/templates/agents/orc-system-analyst-opus-5-high.md +1 -6
  75. package/templates/agents/orc-test-author-opus-5-med.md +4 -5
  76. package/templates/agents/orc-trace-writer-haiku-4-5.md +3 -7
  77. package/templates/agents/orc-verifier-opus-5-med.md +16 -8
  78. package/templates/agents/orc-wiki-scanner-opus-4-8-high.md +74 -79
  79. package/templates/agents/orc-wiki-scanner-opus-5-med.md +1 -8
  80. package/templates/agents/orc-wiki-scanner-sonnet-5-high.md +97 -106
  81. package/templates/commands/orc-analyze.md +13 -21
  82. package/templates/commands/orc-fast.md +10 -15
  83. package/templates/commands/orc-poly.md +12 -21
  84. package/templates/commands/orc-pr-driver.md +11 -30
  85. package/templates/commands/orc-pr-setup.md +10 -31
  86. package/templates/commands/orc-route.md +11 -41
  87. package/templates/commands/orc-test.md +5 -60
  88. package/templates/hooks/README.md +34 -0
  89. package/templates/hooks/orc-session-hook.js +264 -0
  90. package/templates/hooks/orc-statusline.js +3 -1
  91. package/templates/skills/_shared/README.md +9 -0
  92. package/templates/skills/_shared/code-graph.md +47 -55
  93. package/templates/skills/_shared/config-precedence.md +3 -1
  94. package/templates/skills/_shared/extra-dispatch.md +73 -88
  95. package/templates/skills/_shared/gotchas.md +228 -177
  96. package/templates/skills/_shared/habits.md +101 -0
  97. package/templates/skills/_shared/lane-contract.md +84 -0
  98. package/templates/skills/_shared/phases/README.md +142 -83
  99. package/templates/skills/_shared/phases/analyst-gates.md +10 -21
  100. package/templates/skills/_shared/phases/execution.md +8 -14
  101. package/templates/skills/_shared/phases/house-rules.md +27 -32
  102. package/templates/skills/_shared/phases/intake.md +127 -133
  103. package/templates/skills/_shared/phases/mock-example.md +46 -56
  104. package/templates/skills/_shared/phases/plan-handoff.md +91 -97
  105. package/templates/skills/_shared/phases/planning.md +7 -17
  106. package/templates/skills/_shared/phases/preflight.md +19 -42
  107. package/templates/skills/_shared/phases/review.md +23 -27
  108. package/templates/skills/_shared/phases/rules.md +18 -42
  109. package/templates/skills/_shared/phases/scoring.md +55 -65
  110. package/templates/skills/_shared/phases/security-checklist.md +46 -50
  111. package/templates/skills/_shared/phases/security.md +45 -55
  112. package/templates/skills/_shared/phases/ship.md +6 -15
  113. package/templates/skills/_shared/phases/stop-resume.md +2 -5
  114. package/templates/skills/_shared/phases/summary.md +73 -48
  115. package/templates/skills/_shared/phases/testgen.md +41 -51
  116. package/templates/skills/_shared/phases/trace-verbs.md +433 -0
  117. package/templates/skills/_shared/phases/trace.md +136 -367
  118. package/templates/skills/_shared/phases/verify.md +62 -70
  119. package/templates/skills/_shared/phases/wave-grouping.md +128 -133
  120. package/templates/skills/_shared/phases/wiki-consult.md +10 -6
  121. package/templates/skills/_shared/read-ladder.md +2 -55
  122. package/templates/skills/_shared/return-validation.md +17 -70
  123. package/templates/skills/_shared/review-slice.md +79 -0
  124. package/templates/skills/_shared/smoke-gate.md +46 -28
  125. package/templates/skills/context-combiner/SKILL.md +15 -44
  126. package/templates/skills/orc/SKILL.md +34 -62
  127. package/templates/skills/orc/references/pattern-gate.md +89 -89
  128. package/templates/skills/orc/references/phases/intake.md +41 -47
  129. package/templates/skills/orc/references/phases/integration.md +13 -19
  130. package/templates/skills/orc/references/preflight-report.md +8 -9
  131. package/templates/skills/orc/references/ultra-mode.md +8 -6
  132. package/templates/skills/orc/subskills/orc-execution/SKILL.md +27 -73
  133. package/templates/skills/orc/subskills/orc-execution/core.md +12 -99
  134. package/templates/skills/orc/subskills/orc-execution/subagent.md +14 -13
  135. package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +11 -52
  136. package/templates/skills/orc/subskills/orc-review-verify/core.md +52 -135
  137. package/templates/skills/orc/subskills/orc-review-verify/subagent.md +7 -7
  138. package/templates/skills/orc/subskills/orc-testgen/SKILL.md +11 -22
  139. package/templates/skills/orc/subskills/orc-testgen/core.md +20 -59
  140. package/templates/skills/orc/subskills/orc-testgen/subagent.md +7 -7
  141. package/templates/skills/orc-advisor/SKILL.md +56 -60
  142. package/templates/skills/orc-analyze/SKILL.md +30 -66
  143. package/templates/skills/orc-analyze/schemas/report-audit.md +2 -1
  144. package/templates/skills/orc-analyze/schemas/report-prose.md +2 -1
  145. package/templates/skills/orc-analyze-mini/SKILL.md +35 -70
  146. package/templates/skills/orc-diy/README.md +31 -0
  147. package/templates/skills/orc-diy/SKILL.md +23 -74
  148. package/templates/skills/orc-diy/references/blocks/pattern.md +18 -18
  149. package/templates/skills/orc-fast/SKILL.md +44 -72
  150. package/templates/skills/orc-judge/SKILL.md +77 -82
  151. package/templates/skills/orc-mini/SKILL.md +61 -109
  152. package/templates/skills/orc-pattern/SKILL.md +27 -48
  153. package/templates/skills/orc-poly/SKILL.md +32 -61
  154. package/templates/skills/orc-pr-driver/SKILL.md +25 -51
  155. package/templates/skills/orc-pr-driver/references/green-gate.md +113 -105
  156. package/templates/skills/orc-pr-setup/SKILL.md +20 -45
  157. package/templates/skills/orc-quick/README.md +43 -2
  158. package/templates/skills/orc-quick/SKILL.md +76 -107
  159. package/templates/skills/orc-quick/references/dispatch-gate.md +16 -5
  160. package/templates/skills/orc-quick/references/gh-mode.md +48 -1
  161. package/templates/skills/orc-quick/references/look.md +3 -1
  162. package/templates/skills/orc-retro/SKILL.md +19 -18
  163. package/templates/skills/orc-retro/examples/retro-mock.md +1 -1
  164. package/templates/skills/orc-route/SKILL.md +25 -45
  165. package/templates/skills/orc-test/SKILL.md +16 -37
  166. package/templates/skills/orc-verify/SKILL.md +14 -32
  167. package/templates/skills/orc-wait/SKILL.md +156 -163
  168. package/templates/skills/orc-wiki/references/phases/phase-0.md +1 -6
  169. package/templates/skills/orc-wiki/references/phases/phase-1.md +1 -6
  170. package/templates/skills/orc-wiki/references/phases/phase-2.md +1 -6
  171. package/templates/skills/orc-wiki/references/phases/phase-3.md +1 -6
  172. package/templates/skills/orc-wiki/references/phases/phase-3c.md +1 -6
@@ -0,0 +1,433 @@
1
+ # Phase reference — Trace verbs (id: `trace-verbs`)
2
+
3
+ > **Library file, read ON DEMAND** — only for a verb not in `orc lane phases <lane> --json` → `trace_grammar`, or for a verb's detail. Data: `TRACE_VERBS` in `bin/cli.js`; `npm run verify` fails when they disagree or a phase lists an unknown verb.
4
+
5
+ <!-- orc:layer core -->
6
+
7
+ ## Verb set (CLOSED — never invent new verbs)
8
+
9
+ "Emitted by" now reads **orc → writer** for the narrated verbs: the orchestrator
10
+ supplies the fact in a packet, the writer writes the line. `SPAWN`, `RETURN` and
11
+ `PHASE-EDGE` stay hook-owned and need no cooperation at all. ` · ` separates the
12
+ sub-forms of one verb. "Owner" is the file that holds the detail; a verb whose
13
+ owner is this file has its detail in "Verb detail" below.
14
+
15
+ | Verb | Emitted by | Meaning | Owner |
16
+ |------|-----------|---------|-------|
17
+ | `PHASE <name> start\|end` | orc → writer | phase transition | `_shared/phases/trace.md` |
18
+ | `PHASE-EDGE <role-family> :: first=<agent>` | hook | deterministic phase inference: a SPAWN whose role family differs from the previous one opens an edge | `hooks/orc-trace.js` |
19
+ | `CONFIG <key=value …>` | orc → writer | Phase 1 — the resolved config values this run will consume, ALWAYS with opus5_only | `_shared/phases/trace-verbs.md` |
20
+ | `WIKI-CONSULT <fresh\|aging\|stale\|absent\|empty> :: docs=<list\|none>` | orc → writer | project wiki consulted for grounding, with its staleness tier | `_shared/phases/wiki-consult.md` |
21
+ | `CROSSLINK <cached\|configured-no-cache\|none> :: boundaries=<n> peers=<names> · CROSSLINK inject task=<id> :: <boundary>` | orc → writer | cross-repo peer-knowledge state at the consult point; `inject` when a slice receives a linked contract | `_shared/phases/wiki-consult.md` |
22
+ | `GRAPH-CONSULT <fresh\|updated\|built\|drifted\|none\|off> :: files=<n> symbols=<n>[ density=<n>[ thin=1]] · GRAPH-CONSULT card task=<id> :: targets=<…>` | orc → writer | the code graph's preflight state, copied VERBATIM from the CLI `trace` field | `_shared/code-graph.md` |
23
+ | `GRAPH-UPDATE <state> :: parsed=<n> reused=<n> deleted=<n> gen=<n> route=<n> ms=<n>` | orc → writer | one graph update, the `trace` field of `orc graph update --json`, verbatim | `_shared/phases/trace-verbs.md` |
24
+ | `GRAPH-MAP <repo\|focused> :: files=<shown>/<total> [focus=<a,b>] gen=<n>` | orc → writer | ONE line at the start of planning, the `trace` field of `orc graph map --json`, verbatim | `_shared/phases/trace-verbs.md` |
25
+ | `GRAPH-CHANGES <found\|none> :: symbols=<n> high=<n> medium=<n> low=<n> gen=<n>` | orc → writer | one line at review, the `trace` field of `orc graph changes --json`, verbatim | `_shared/phases/trace-verbs.md` |
26
+ | `GRAPH-COMPLEXITY <mini-ok\|recommend-orc> :: files=<n> callers=<n> caller_files=<n> maybe=<n> tests=<n> risk=<n> cochange=<n> gen=<n>` | orc → writer | one line per /orc-mini run, the `trace` field of the `--complexity` impact call, verbatim | `_shared/phases/trace-verbs.md` |
27
+ | `GRAPH-COCHANGE <found\|none> :: rows=<n> commits=<n>` | orc → writer | one line per planning batch, for the file that produced the widest answer | `_shared/phases/trace-verbs.md` |
28
+ | `GRAPH-HINT injected=<n> subagent_start=<n> read_notes=<n> updates=<n>` | orc → writer | ONE line per phase close, the graph hook's counters; omitted when the counter file does not exist | `_shared/phases/trace-verbs.md` |
29
+ | `GRAPH-GAIN paid=<n> low=<n> high=<n> calls=<n>` | orc → writer | ONE line per run at ship; `paid` is exact, `low`/`high` are an estimate never collapsed into one number | `_shared/phases/trace-verbs.md` |
30
+ | `GRAPH-NOTES <applied\|below-min\|none\|deferred\|off\|skipped> :: <detail>` | orc → writer | one notes batch; `applied` copies the noter's one-line return verbatim | `_shared/phases/trace-verbs.md` |
31
+ | `SPAWN <agent>` | hook | an agent dispatch was observed (skeleton) | `hooks/orc-trace.js` |
32
+ | `RETURN <agent> :: <desc> dur=<m>m<s>s [model=<id>]` | hook | a subagent finished (skeleton) — not an orchestrator obligation; the model check is VERIFY | `hooks/orc-trace.js` |
33
+ | `DISPATCH <agent> :: <task> expect=<model>/<effort>[ via=extra:<profile>]` | orc → writer | orchestrator dispatched a named agent (the claim) | `_shared/phases/trace-verbs.md` |
34
+ | `SCORE task=<id> score=<n> band=<range> model=<m> facets=<compact-vector>[ via=extra:<profile>] :: <reason>` | orc → writer | scoring decision (tunes the rubric); a fix cycle emits `task=fix-<n>` | `_shared/phases/scoring.md` |
35
+ | `VERIFY <task> actual=<model>/<effort> ✅ MATCH · VERIFY <task> actual=<model>/<effort> ⛔ DOWNGRADE expected=<m>/<e>` | orc → writer | claimed-vs-actual model check; surface a downgrade to the user, not just the trace | `_shared/return-validation.md` |
36
+ | `ASK <qid> :: offered=<o1\|o2\|…> rec=<o\|none> chose=<o\|other> by=<user\|ledger\|learned\|config\|default> [pre=<o>] [ctx=<k=v,…>]` | orc → writer | one answered decision point — what `orc habit` learns from; the free text of an `other` answer is never stored | `_shared/phases/trace-verbs.md` |
37
+ | `QUESTION count=<n> :: <topic>` | subagent→orc → writer | stopped to ask the user | `_shared/phases/trace-verbs.md` |
38
+ | `CONTEXT-GAP :: <what was already known>` | subagent→orc → writer | asked/re-derived something already in context | `_shared/phases/trace-verbs.md` |
39
+ | `REPLAN wave=<n> :: <reason>` | orc → writer | re-planned after a conflict/failure | `_shared/phases/trace-verbs.md` |
40
+ | `GATE <grounding\|coverage\|graph\|evidence\|derivation\|facet\|schema\|judgment\|wave-boundary\|budget\|stack-gate\|stack-certainty\|layer-green> pass\|bounce\|escalate :: <detail>` | orc → writer | exit-gate result; `escalate` is judgment-only; bounce detail lists the misses | `_shared/phases/trace-verbs.md` |
41
+ | `ADVISE :: brief=<path> questions=<n>` | orc → writer | ultra Phase U0 — advisor brief received, clarification round relayed | `orc/references/ultra-mode.md` |
42
+ | `JUDGE <analysis\|plan\|implementation> <verdict> round=<n> blocking=<n> advisory=<n> downgraded=<n>` | orc → writer | ultra judgment verdict | `orc/references/ultra-mode.md` |
43
+ | `OUTCOME task=<id> score=<n> band=<range> model=<m> retries=<n> requeues=<n> needs_context=<n> unmet=<n>` | orc → writer | task closed — links the scoring band to what it actually took | `_shared/phases/execution.md` |
44
+ | `FINDING p0=<n> p1=<n> p2=<n> p3=<n>[ pre=<n> suppressed=<n> folded=<n>]` | reviewer→orc → writer | review outcome (P0–P3 severity ladder); the tail counts the after-filter's buckets | `_shared/phases/review.md` |
45
+ | `FINDING-OUTCOME addressed=<n> disputed=<n> wontfix=<n> open=<n> pre=<n> suppressed=<n> :: <cat>:<addressed>/<total>,…` | orc → writer | ONE line at review close — what became of each finding; `orc gotcha quality` reads it | `_shared/phases/trace-verbs.md` |
46
+ | `VERDICT pass\|fail :: <detail>` | verifier→orc → writer | verification outcome | `_shared/phases/verify.md` |
47
+ | `DRIFT loop=<n> :: <user description, compressed>` | orc → writer | mock-example drift-recovery loop opened (hard cap 2 loops) | `_shared/drift-recovery.md` |
48
+ | `TDD-RED task=<id> iter=<n> :: <failing tests>` | executor→orc → writer | TDD repair-loop iteration — the plan's acceptance tests still red | `_shared/phases/trace-verbs.md` |
49
+ | `TDD-GREEN task=<id> iter=<n>` | executor→orc → writer | the task's TDD acceptance tests pass | `_shared/phases/trace-verbs.md` |
50
+ | `REPRO red\|green :: <cmd> exit=<n> · REPRO none :: <reason>` | executor→orc → writer | a DEFECT task's reproduction: RED before the fix, GREEN after | `_shared/return-validation.md` |
51
+ | `NOTE :: <decisions>` | writer | the packet's `decisions` field — the WHY layer; one line, only when non-empty | `agents/orc-trace-writer-haiku-4-5.md` |
52
+ | `STATS lane=<l> slug=<s> dispatches=<n> waves=<n> tasks=<n> bands=<h:n,m:n,l:n> downgrades=<n> duration_ms=<n>` | orc → writer | ONE summary line per run, in the FINISH packet, immediately BEFORE the FINISH line | `_shared/phases/trace-verbs.md` |
53
+ | `PACT <state> :: <ids> · PACT inject task=<id> :: <PACT-id> · PACT recheck pass\|fail :: <ids>` | orc → writer | invariant-ledger state at the Phase-1 probe, a promise injected into a task, the Phase-6 recheck | `orc-pact/references/gate.md` |
54
+ | `BOUNDARY <EXECUTE\|ESCALATE\|REFUSE\|unknown> task=<id> :: <area> · BOUNDARY lift task=<id> :: <area>` | orc → writer | per-task boundary verdict; an uncarded area is `unknown`, never REFUSE | `orc-boundary/references/gate.md` |
55
+ | `CHALLENGE iter=<n> findings=P0:<n>/P1:<n>/P2:<n> coverage=<n>% verdict=PASS\|FAIL · CHALLENGE accept\|rebut :: <id> · CHALLENGE regoal\|retemplate :: v<n>` | orc → writer | one line per completed /orc-challenge iteration — `orc challenge record`'s `trace_line`, verbatim | `orc-challenge/SKILL.md` |
56
+ | `EXTRA <profile>/<model> engine=<api\|claude-shim\|cli> task=<id> band=[lo,hi) tok=in/cw/cr/out outcome=<done\|partial\|failed\|fallback> dur=<m>m<s>s · EXTRA fallback task=<id> :: <reason> → <agent> · EXTRA substitution task=<id> :: requested=<m> reported=<m> · EXTRA reroute task=<id> :: <providers> · EXTRA resume task=<id> attempt=<n> :: from=<reason> attribution=<verdict> target=<extra:profile\|agent> files_preexisting=<n> · EXTRA orphan task=<id> :: attempt=<n> lease-expired files_changed=<n> state=<state> · EXTRA demote run=<slug> :: profile=<p> reason=<consecutive-stall\|stale-live-attempt\|manual> n=<k> → <ladder>` | orc → writer | one line per FOREIGN dispatch — `orc extra dispatch`'s `trace_line`, verbatim | `_shared/extra-dispatch.md` |
57
+ | `FINISH :: <detail>` | orc → writer | run ended — mandatory, even on an abort | `_shared/phases/trace.md` |
58
+
59
+ `SPAWN`/`RETURN`/`PHASE-EDGE` come from the hook automatically. Every other verb
60
+ reaches the file through a packet — you never append lines by hand.
61
+
62
+ ## Verb detail
63
+
64
+ - **`PHASE-EDGE`.** ORC agent names encode their role, so when a SPAWN's role
65
+ family differs from the previous SPAWN's, the hook segments the run itself.
66
+ Families: `recon → recon` (v1.9.0 — /orc-quick's read-only half; a question
67
+ answered for a person is not an analysis), `analyst|scout → analysis`,
68
+ `planner → planning`, `executor → execution`, `reviewer → review`,
69
+ `verifier → verify`, `test-author → testgen`, `advisor|judge → ultra-gate`
70
+ (the trace writer never opens an edge). Zero model dependence: even a run
71
+ where every writer dispatch was forgotten still reads planning → execution →
72
+ review → verify, and `/orc-retro` computes NARRATION COVERAGE from edges with
73
+ vs without a writer `SPAWN` between them.
74
+ - **`CONFIG`.** ALWAYS carries `opus5_only` — it selects the executor table AND
75
+ every fixed role, so retro can segment outcomes by dispatch mode. Runtime
76
+ proof that the run honored the config; `/orc-retro` audits it against behavior.
77
+ - **`ASK`.** One line per answered decision point. `qid` is a row of
78
+ `orc habit points --json`; a qid the registry does not know is dropped and
79
+ `orc habit doctor` counts it. `offered`, `rec`, `chose` and `pre` are option
80
+ ids, never free text: an answer typed in words is `chose=other`, and the words
81
+ are never stored. `by` says how the answer came: `user` typed it, `ledger` said
82
+ it up front in the request, `learned` took what an accepted habit pre-selected,
83
+ `config` or `default` answered without showing the question (not a choice, so
84
+ not counted). `ctx` carries only what the lane knows (`branch`, `kind`, `size`,
85
+ `risk`). `orc habit` reads these lines; it never applies a habit without a yes.
86
+ - **`WIKI-CONSULT`.** Full/mini at planning; fast at slice-build. `docs=` is the
87
+ pages pulled/handed to the executor (comma list) or `none`. It records whether
88
+ the run grounded in the wiki and whether it was stale (grounding + staleness
89
+ for later audit).
90
+ - **`CROSSLINK`.** `cached` = peer cache present; `configured-no-cache` =
91
+ crosslink configured but the cache is not built. It records whether peer
92
+ contracts were injected this run. Full orc consumes only the pre-built
93
+ crosslink cache — it never reads peer source live (mechanism in
94
+ `wiki-consult.md`).
95
+ - **`GRAPH-CONSULT`.** Copied VERBATIM from the `trace` field of
96
+ `orc graph status --heal --json --brief` (`code-graph.md` §4). `density=` is
97
+ the named symbols per file, and `thin=1` means most files hold none, so most
98
+ questions asked of the graph will not find one (v1.9.1). A `GATE` line that
99
+ describes the graph in other words does not replace it. The `card` form is the
100
+ `trace` of `orc graph ctx --json`, with `task=` added, when a slice receives
101
+ cards.
102
+ - **`GRAPH-UPDATE`.** One graph update at a wave close, a green smoke gate, a
103
+ code-writing `/orc-quick` request, or ship. The graph HOOK writes its own
104
+ `GRAPH-UPDATE … :: by=hook …` lines directly; never copy one of those, it is
105
+ already in the file.
106
+ - **`GRAPH-MAP`.** Also at a `/orc-quick` Q1 look that had no file to name.
107
+ `files=` is how many the budget SHOWED over how many the repository has, so a
108
+ short map can be told from a small repository. `focused` means `--focus`
109
+ re-ranked the repository around what the request named. RANK is a hint about
110
+ where to look first and the trace never says more than that.
111
+ - **`GRAPH-CHANGES`.** `high` counts symbols that are exported, have three or
112
+ more callers and NO test reaching them.
113
+ - **`GRAPH-COMPLEXITY`.** The `trace` field of
114
+ `orc graph impact … --complexity --json`. The CLI computes the verdict from the
115
+ four thresholds in `bin/graph-signals.js`; `maybe` is reported and never trips
116
+ one. Mini's own `GATE complexity :: <the line>` is separate: it records what
117
+ the USER chose after the offer.
118
+ - **`GRAPH-COCHANGE`.** Not per file — the `trace` field of
119
+ `orc graph cochange --json` for the file that produced the widest answer.
120
+ - **`GRAPH-HINT`.** Not one per hint — the counters `orc-graph-hook.js` keeps in
121
+ `<log_dir>/<run>.graph-hook.json`. Omitted when the file does not exist (the
122
+ hook is off, or it never had anything to say).
123
+ - **`GRAPH-GAIN`.** The `trace` field of `orc graph gain --run <trace name>
124
+ --json`, verbatim. `paid` is exact (the tokens the graph put in); `low`/`high`
125
+ are an ESTIMATE of the retrieval it kept out. Omitted when the ledger is empty
126
+ or the graph is off.
127
+ - **`GRAPH-NOTES`.** The `trace` field of `orc graph notes pending --json` when
128
+ it exited 3 or 5; `skipped` under the Opus-5-only mode.
129
+ - **`RETURN`.** The hook attributes the RETURN to the finishing agent from the
130
+ SubagentStop payload (`~<agent>` = approximate FIFO match on older Claude Code
131
+ that omits `agent_type`; `~agent :: unattributed` = ≥2 agents in flight, so it
132
+ deliberately claimed NO pending record rather than starve the right one),
133
+ echoes the SPAWN's desc + wall-clock duration, and appends `model=<id>` when
134
+ the return's `actual_model` is visible in the last message. A duplicate stop
135
+ for an agent whose record was already consumed is DROPPED, never written as a
136
+ desc-less RETURN. Still hook-written skeleton — NOT an orchestrator
137
+ obligation; the authoritative model check is the `VERIFY` line.
138
+ - **`DISPATCH`.** **A FOREIGN dispatch appends `via=extra:<profile>`** and its
139
+ `expect=` names the profile's model rather than a Claude tier — additive, the
140
+ way `/orc-doc`'s `sections=` was. A foreign worker is not a Claude subagent, so
141
+ the hook emits NO `SPAWN` and NO `RETURN` for it (P7, the `/orc-quick`
142
+ ad-hoc-recon precedent): this line and `EXTRA` are the whole record, which is
143
+ why neither is optional. **The `/orc-doc` lane's tail NAMES ITS SECTIONS**
144
+ (v0.49.2) — `doc write sections=03-scope,04-risks part=sections/03-scope.md`,
145
+ `doc check sections=03-goals`, `doc digest source=<path>` — which is the only
146
+ thing that makes `orc doc cost`'s per-section attribution honest rather than a
147
+ guess. It is additive: the tail was already captured whole.
148
+ - **`SCORE`.** **A task the resolver sent foreign appends `via=extra:<profile>`**,
149
+ and `model=` is the foreign model id — so `/orc-retro` can segment a band's
150
+ outcomes by WHO ran it. `facets=` is the planner-emitted vector
151
+ (breadth·novelty·logic·test·fan·unc·risk) the score was computed from —
152
+ `/orc-retro` reads it to recalibrate the formula. Fix-cycle dispatches emit
153
+ `SCORE task=fix-<n> …` the same way.
154
+ - **`VERIFY`.** The COMPARISON stays the orchestrator's obligation — surface a
155
+ downgrade to the user, not just the trace.
156
+ - **`GATE`.** `facet` is the plan's facet-vocabulary check
157
+ (`effort-and-mode.md`); `schema` is the plan-handoff schema check; `judgment`
158
+ is ultra (`escalate` is judgment-only); `budget` is the Phase-1
159
+ `run_budget_dispatches` forecast gate — `pass` or the `stop` that blocks
160
+ wave 1, emitted only when the key is > 0; `stack-gate` is the Phase 8
161
+ stacked-PR threshold + handoff; `stack-certainty` is a stacked-PR seam
162
+ decision; `layer-green` is one layer's green-gate ladder. The shared-band
163
+ SIBLING-CONSISTENCY determination is NOT a gate name — carry it in the
164
+ packet's `decisions`, never as an invented verb. Bounce detail lists the
165
+ misses (feeds `/orc-retro` gate-bounce rates).
166
+ - **`OUTCOME`.** Feeds `/orc-retro` calibration.
167
+ - **`FINDING-OUTCOME`.** At review close: `/orc` Phase 7, `/orc-mini` after the
168
+ risk option, `/orc-quick` after the review offer. The counts are PROGRAMMATIC
169
+ (`_shared/gotchas.md` §10): the flagged lines changed before ship = addressed;
170
+ the user said "not a problem here" = disputed; declined with no reason = wontfix.
171
+ `pre` and `suppressed` copy the after-filter's buckets; they never gate. The
172
+ `FINDING` tail `pre= suppressed= folded=` is additive (the `sections=` precedent).
173
+ - **`DRIFT`.** `PHASE mock-example`; canonical `_shared/drift-recovery.md`.
174
+ - **`TDD-RED` / `TDD-GREEN`.** Cap `tdd_loop_max`; a paired TDD task's red proof
175
+ also emits iter=0. `TDD-GREEN` is the non-exempt definition-of-done.
176
+ - **`REPRO`.** `_shared/return-validation.md` §5d. TWO lines per reproduced
177
+ defect, in this order: the `before` run must be RED and the `after` run GREEN,
178
+ or the return was malformed. `REPRO none :: <reason>` when no reproduction
179
+ could be written — an honest answer, never a missing line. A reproduction is
180
+ NOT a plan-time acceptance test, so it never reuses `TDD-RED`/`TDD-GREEN`:
181
+ `/orc-retro` counts "we proved the bug first" apart from "we drove the plan's
182
+ acceptance tests".
183
+ - **`NOTE`.** Scoring rationale, user answers verbatim, what was rejected. One
184
+ line per packet, only when `decisions` is non-empty.
185
+ - **`PACT`.** At the Phase-1 probe (`pact_gate`); `inject` when a
186
+ DRIFTED/BROKEN promise is appended to a task's `constraints[]`; `recheck` at
187
+ Phase 6. Records whether last month's decisions constrained this month's plan.
188
+ - **`BOUNDARY`.** `lift` when `boundary_gate: block` removes ONE task from a
189
+ wave (the wave still runs). `/orc-retro` reads these to answer the question
190
+ the lane exists for: how much work did we stop attempting, and was that right.
191
+ - **`CHALLENGE`.** **Copy `orc challenge record`'s `trace_line` verbatim** — the
192
+ CLI assembles it so the lane never composes a second wording for the same
193
+ number. `accept`/`rebut` when an escape valve is used; `regoal|retemplate` on a
194
+ re-freeze. `/orc-retro` reads the sequence to answer whether a cycle converged
195
+ or stalled.
196
+ - **`EXTRA`.** A slice that executed on a non-Claude worker
197
+ (`_shared/extra-dispatch.md`). **Copy `orc extra dispatch`'s `trace_line`
198
+ verbatim** — the CLI assembles it, exactly as `orc challenge record` does, so
199
+ the lane never composes a second wording for the same numbers. The sub-forms:
200
+ `fallback` when a failed foreign dispatch re-dispatches to Claude (P6);
201
+ `substitution` / `reroute` when the endpoint answered with a different model,
202
+ or the same model served by a different company; `resume` (v0.54.0) when a
203
+ dispatch CONTINUES a position an earlier attempt left on disk; `orphan` when
204
+ preflight reports a dispatch that never reported back; `demote` (v1.0.0) when
205
+ this run DROPS a foreign profile to the bottom of the ladder after two
206
+ consecutive stalls, a stale live attempt, or `orc extra demote`.
207
+ - **A demotion that leaves no line cannot be counted** either — copy
208
+ `orc extra demotion`’s `trace_line` VERBATIM and emit it before the next
209
+ dispatch, beside the mandatory announce line. A demotion is RUN state: it
210
+ never writes the config and it is never promoted back on its own.
211
+ - **A resume that leaves no line cannot be counted** — neither
212
+ `orc extra stats` nor `/orc-retro` can then learn whether resuming works, or
213
+ which providers ignore the resume preamble. `EXTRA resume` rides in the
214
+ resumed dispatch's own `trace_extras[]`; `EXTRA orphan` is the LANE's to
215
+ emit after it reports, the same ownership rule as `EXTRA fallback`.
216
+ - **`tok=none` is a real value** and the ONLY correct one when the worker
217
+ reported no counts (engine `cli` often does not): `tok=0/0/0/0` would tell
218
+ `/orc-budget` the run was free, while a measured zero — engine `api`'s `cw`,
219
+ always — is a different fact.
220
+ - **On a lane with no score `band=` carries `slot:<slot>`** (v0.55.0 —
221
+ `slot:doc-writer`, `slot:wiki-scanner-light`): the field NAME is unchanged,
222
+ so this parser, the eight-field dedupe and the ` :: ` tolerance are
223
+ untouched, and `orc extra stats` gives each POSITION its own row for free.
224
+ - This is the verb `/orc-retro` reads to answer the only question that
225
+ matters: is the cheap model actually cheaper once you count the repairs.
226
+
227
+ ## `STATS` — what `orc stats` reads
228
+
229
+ `orc stats` reads the tail of each file and nothing more: one line per file,
230
+ never a parse of the whole trace. Omit a field you genuinely do not have (a lane
231
+ with no waves omits `waves=`); never guess one. Every trace-owning lane emits
232
+ it, not just `orc`.
233
+
234
+ - **A run with no `FINISH` is counted as unfinished, permanently.** That is
235
+ correct behaviour and it is why `FINISH` is mandatory even on an abort.
236
+ - **A trace older than v0.42.0 has no `STATS` line.** `orc stats` falls back to
237
+ counting `DISPATCH` lines — orchestrator-written and present in every lane
238
+ (including `/orc-quick`, whose ad-hoc recon emits no `SPAWN`/`RETURN`). Old
239
+ traces still count, with less detail. Never back-fill a `STATS` line into an
240
+ old trace: the numbers would be invented, and the trace is append-only.
241
+
242
+ **Skeleton caveat (read every retro metric with it):** the hook only sees a NEW
243
+ dispatch. CONTINUING an already-running agent fires no PreToolUse/SubagentStop
244
+ pair, so a lane driven by continuing one agent produces fewer `SPAWN`/`RETURN`
245
+ lines than it did real work. The skeleton is a FLOOR on dispatch volume, never a
246
+ census — narration coverage computed from it reads low, not wrong.
247
+
248
+
249
+ ## Protocol detail — the WHY behind `trace.md`
250
+
251
+ `trace.md` carries the rules a run applies at every phase close. This section
252
+ keeps the reasons and the per-lane detail behind them, for a reader who needs it.
253
+
254
+ Purpose: capture the flow of a run — phases, spawns, the model that actually
255
+ answered, scoring decisions, user questions, review/verify outcomes — so the
256
+ skills can be improved from real traces. This is NOT the decision log
257
+ (`run/…md`, agent knowledge, deleted on success). The trace is a separate,
258
+ **persistent** artifact and the two never mix.
259
+
260
+ There is no gate. Behavior-trace logging is PERMANENT — every run traces. The
261
+ `orc-trace.js` hook is the deterministic guarantee: on the first ORC-agent
262
+ dispatch it bootstraps `log_dir` + the run pointer itself, so a `.txt` is created
263
+ for every run even if the orchestrator never writes a rich marker. Only
264
+ `log_dir` (default `.claude/orc/logs`) is configurable.
265
+
266
+ ### Narration
267
+
268
+ - **The pen (v2.0.0).** `orc trace write --packet -` reads the packet on stdin
269
+ and writes the `.txt` lines AND the `.jsonl` rows from it, in the writer's
270
+ formats — the two halves agree by construction. An unknown verb, a missing or
271
+ "now" `ts`, or a parse error exits 2 and writes NOTHING; a missing `.current`
272
+ on a later packet exits 3. Only on exit ≠ 0 does the lane dispatch
273
+ `orc-trace-writer-haiku-4-5` with the SAME packet (the fallback).
274
+ - **Pairing rule (the anti-forget mechanism).** The write for phase N is issued
275
+ **in the same tool block as phase N+1's first dispatch** — logging
276
+ piggybacks on the very action the model reliably performs. A phase with no next
277
+ dispatch (FINISH, an abort, a pure-question phase) writes SOLO, before
278
+ printing that phase's user-facing output.
279
+ - **First write is solo** — before the planner/analyst goes out. It carries
280
+ `run_meta` and performs the rename repair (below) while nothing else is in
281
+ flight.
282
+ - **Last write (run end).** The FINISH packet (final report summary, ship
283
+ state, verdict totals) is written BEFORE you delete `.current`.
284
+
285
+ A fallback writer's own `SPAWN`/`RETURN` are logged like any `orc*` agent.
286
+ `/orc-retro` audits narration coverage from the narrated (non-`hook`) lines
287
+ stamped inside each `PHASE-EDGE` interval, or a writer SPAWN there.
288
+
289
+ ### Phase packet
290
+
291
+ - The packet is built from the phase's **actual working state as the phase
292
+ closes** — never reconstructed later from memory.
293
+ - `ts` is each event's REAL time. The writer stamps nothing itself: the block is
294
+ a faithful late append of events that happened seconds ago, not an end-of-run
295
+ summary. Retro sorts by stamp, not by file order.
296
+ - Subagent-returned markers (`QUESTION`, `FINDING`, `VERDICT`, a return's
297
+ `actual_model`) are folded into the NEXT packet, never written directly.
298
+ - `VERIFY` stays an orchestrator OBLIGATION — you compare claimed vs actual and
299
+ surface any ⛔ DOWNGRADE to the user in chat; only the LINE travels by packet.
300
+ - The writer NEVER invents: an absent field is omitted, never guessed.
301
+
302
+ ### Packet units per lane (full detail)
303
+
304
+ | Tier | Lanes | Packets |
305
+ |------|-------|---------|
306
+ | Build lanes | `orc` (incl. ultra), `orc-mini`, `orc-fast` | per phase — full orc ≈ 7–9 (ultra adds U0 + judge packets); orc-mini batches to 3 (intake+plan, execution, ship); orc-fast to 2 (preflight+dispatch, gate+ship) |
307
+ | Multi-dispatch | `orc-wiki`, `orc-pr-driver` (lane `prdriver`) | orc-wiki: one per scan-batch boundary (the points that already run the registration sync / offer the pause) + the end-of-run packet. orc-pr-driver: one per LAYER boundary (each layer's green gate closes) + the end-of-run packet |
308
+ | Composed | `orc-diy` | one packet per ENABLED phase group, **minimum 2** — the flow shape is user-composed, so the count is too (the compiled flow carries this block automatically) |
309
+ | Iterative | `orc-quick`, `orc-challenge` (lane `challenge`), `orc-doc` (lane `doc`), `orc-test` (lane `test`) | **one packet per completed numbered entry** + the end-of-run `FINISH` packet — the lane loops on user requests, so the count follows entries, not phases. For `orc-challenge` the unit is one completed ITERATION (C2→C8), and the packet goes out at the stop; on a PASS it is the `FINISH` packet. **Several trace files for one cycle is CORRECT** — several sessions ran, and `orc stats` counts several. For `orc-doc` the unit is one completed WAVE, and the packet is the LAST step of the stop sequence. For `orc-test` the unit is one completed CYCLE (T2→T9), and the packet goes out at the stop |
310
+ | Single-dispatch | `orc-claude`, `orc-plan`, `orc-analyze` + `orc-analyze-mini` (both lane token `analyze`), `orc-pattern`, `orc-verify`, `orc-learn`, `orc-poly`, `orc-pr-setup` (lane `prsetup`), `orc-grill`, `orc-route`, `orc-brainstorm` (lane `brainstorm`), `orc-pact` (lane `pact`), `orc-boundary` (lane `boundary`), `orc-handoff` (lane `handoff`), `orc-budget` (lane `budget`), `orc-aftermath` (lane `aftermath`), `orc-export` (lane `export`) | **exactly ONE mandatory end-of-run packet** |
311
+
312
+ **`context-combiner` is NOT a lane — it is a PHASE inside the analyze run.** It
313
+ has no slash command and no entry point of its own: `orc-analyze` Phase F
314
+ dispatches it while `.current` still points at that run's `run-analyze-…` file.
315
+ So it never writes a pointer, never touches a trace file, and never emits its own
316
+ `FINISH`; its `DISPATCH`/`RETURN`, its Phase D challenge verdicts and its
317
+ conservation-gate result all fold into **orc-analyze's** end-of-run packet. The
318
+ hook agrees — `context-combiner` maps to its own `PHASE-EDGE` role family
319
+ (`combine`), which segments the phase *within* that trace. Listing it as a lane
320
+ (as this table did before v0.42.0) declared a run nothing could ever open.
321
+
322
+ **The single-packet obligation is defined HERE, once** (every trace-owning lane
323
+ already loads this reference) — micro-lane spines keep only their existing trace
324
+ pointer. That packet is dispatched SOLO after the lane's main return validates
325
+ and BEFORE `.current` is deleted; it carries `run_meta` (so the rename repair
326
+ works there too) plus the lane's whole event list: intake decisions, the user's
327
+ answers, `DISPATCH`/`VERIFY`, gate/verdict lines, `FINISH`. One Haiku call per
328
+ run buys the WHY layer for every lane. Haiku cost is noise against any run's
329
+ executor spend.
330
+
331
+ `/orc-retro` is the ONE exception: it mines traces and writes none (its hard
332
+ rule 4). The hook enforces this — `orc-retro-*` dispatches never bootstrap a
333
+ trace and never emit `SPAWN`/`RETURN`.
334
+
335
+ ### Files & lifecycle
336
+
337
+ - Folder: `log_dir` (default `.claude/orc/logs/`). Persistent — **never deleted**
338
+ (deliberate opposite of the decision log). Top level holds the run `.txt` plus
339
+ its sidecars (`.pending.json`, `.jsonl`); generated reports live in
340
+ subfolders (`retro/`).
341
+ - One file per run: **`run-<lane>-<slug>-<DDMMYY>-<HHMMSS>.txt`**, append-only.
342
+ - `lane` — the trace-owning skill's short name: one value of the
343
+ `run_meta.lane` enum in `trace.md`. That enum is the ONE list — the lane
344
+ vocabulary `orc stats` and `/orc-retro` count against. Every value there is
345
+ a lane some entry point actually opens — keep it that way. `ultra` = an
346
+ /orc-ultra run, the ONLY lane the orc spine can emit besides `orc`. No other
347
+ value is legal: a lane no entry point opens is a lane every counting tool
348
+ reports as permanently zero.
349
+ - `slug` — kebab-cased short user context from the intent (`[a-z0-9-]`, ≤32
350
+ chars, filesystem-safe, no trailing hyphen) — same derivation as the
351
+ run-folder slug.
352
+ - `HHMMSS` — so two same-day runs never collide.
353
+ - e.g. `run-orc-cas-multi-exchange-withdrawal-240726-002352.txt`.
354
+ - The name is DATA: `/orc-retro` aggregates per lane straight from it, without
355
+ parsing content.
356
+ - **Why the pointer and the file are made together.** A pointer naming a file
357
+ that does not exist yet is indistinguishable from a dangling one by content
358
+ alone. That used to split a run across two files (a generic bootstrap holding
359
+ the hook skeleton + a rich file holding every narrated line, each looking
360
+ correct alone). The `orc-trace.js` hook reads the pointer to know which file
361
+ to append to, and since v0.34.2 it also honors a POINTER whose mtime is fresh
362
+ even when the file is not there yet — the two fixes are independent on purpose.
363
+ - **Why a resumed lane re-writes the pointer.** Otherwise every line it writes
364
+ after the return goes nowhere: the v0.34.2 split-run signature, reached by a
365
+ different road. Two traces for a suspend is CORRECT — two lanes ran, and
366
+ `orc stats` counts two.
367
+ - **The hook bootstrap.** When no usable pointer exists as the first ORC-agent
368
+ dispatch fires, the hook creates the folder + a generic
369
+ `run-<DDMMYY>-<HHMMSS>.txt` and points at it. The FIRST writer dispatch
370
+ repairs that — a MOVE, decided against disk (the writer's contract). Non-ORC
371
+ Tasks never trace — the hook only bootstraps for agent names starting with `orc`.
372
+
373
+ ### Write cadence
374
+
375
+ The trace is a **running record**, not an end-of-run report. Each phase's packet
376
+ goes out AT that phase's close — coupled to the next phase's first dispatch:
377
+
378
+ | Moment | Packet carries |
379
+ |--------|----------------|
380
+ | a phase closes | that phase's events + the decisions behind them |
381
+ | dispatching an agent | the `DISPATCH` line (folded into the closing phase's packet) |
382
+ | a return validates | its `VERIFY` + any subagent-returned marker |
383
+ | a task closes | its `OUTCOME` |
384
+ | review/verify verdict | `FINDING` / `VERDICT` |
385
+ | run end | `FINISH` — dispatched SOLO and returned before `.current` is deleted |
386
+
387
+ About the self-check in `trace.md`:
388
+ The failure this prevents is a fully-executed run behind a one-line trace. If a
389
+ phase went by without its packet, write it NOW with the events' real
390
+ timestamps rather than skipping them — a late block with true stamps is a late
391
+ record; a block stamped "now" is a FALSE one. Batching everything at `FINISH` is
392
+ the classic failure: by then the run's context is compacted and the detail is gone.
393
+
394
+ ### Model source of truth — the claimed-vs-actual check
395
+
396
+ A hook cannot read a subagent's model id (it lives only in the subagent's system
397
+ prompt). So each dispatched agent returns two fields (see each agent's return
398
+ contract):
399
+
400
+ - `actual_model` — **quoted verbatim** from the agent's injected system-prompt
401
+ model-id line ("The exact model ID is …"). Never a guess; `unknown` if absent.
402
+ - `actual_effort` — the value of `$CLAUDE_EFFORT` (env var, read via Bash).
403
+
404
+ For each spawn the orchestrator:
405
+ 1. Derives the **expected** `(model, effort)` from the dispatched agent NAME via
406
+ the `config.md` score→model table / `MODEL-MAPPING.md`.
407
+ 2. Compares against the returned `actual_*` and puts a `VERIFY` line in the next
408
+ packet — `✅ MATCH` or `⛔ DOWNGRADE`. A downgrade (the harness capped a high
409
+ pin to the main-session tier) is surfaced to the user, not just logged.
410
+
411
+ ### Announce-on-spawn
412
+
413
+ When dispatching, announce the model to the user, derived from the agent NAME
414
+ (e.g. "Spawning orc-executor-opus-5-low → claude-opus-5-5 / low"). Derive it
415
+ from the name — do NOT pass the coarse `sonnet|opus|haiku` dispatch arg, which
416
+ cannot express 4-7 vs 4-8 and would override the frontmatter pin.
417
+
418
+ ### Compaction safety
419
+
420
+ The checkpoint carries `logging_enabled` + `trace_path`. On resume, re-read them
421
+ and continue dispatching packets against the same file. The hook backbone keeps
422
+ emitting `SPAWN`/`RETURN`/`PHASE-EDGE` regardless of orchestrator memory, so a
423
+ compacted run is never blind — at worst it loses the WHY layer for one phase.
424
+ `/orc-ultra` is the `orc` skill with `ultra_mode: true`; its packets are just
425
+ orc's plus the U0/judge ones.
426
+
427
+ ### Write discipline
428
+
429
+ - Append-only; one whole block per append (never edit prior lines).
430
+ - The trace records behavior faithfully — including the ugly bits (over-asking,
431
+ downgrades, failed waves). That honesty is the whole value.
432
+
433
+ <!-- /orc:layer -->