ruvnet-brain 4.5.3 → 4.5.5

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 (56) hide show
  1. package/README.md +2 -2
  2. package/bin/install.mjs +148 -31
  3. package/config/model-router/catalog.template.json +126 -52
  4. package/config/model-router/policy.default.mjs +94 -75
  5. package/config/model-router/qualification-contract.json +124 -0
  6. package/config/model-router/routing-eval-cases.json +275 -0
  7. package/config/model-router/routing-policy.template.json +76 -0
  8. package/config/model-router/weekly-analyst-instruction.md +60 -0
  9. package/data/model-catalog.json +44 -49
  10. package/package.json +3 -1
  11. package/plugin/.claude-plugin/plugin.json +1 -1
  12. package/plugin/.codex-plugin/plugin.json +1 -1
  13. package/plugin/hooks/codex-hooks.json +40 -3
  14. package/plugin/hooks/hook-contracts.json +218 -19
  15. package/plugin/hooks/hooks.json +51 -2
  16. package/plugin/scripts/agentdb-recall.mjs +101 -30
  17. package/plugin/scripts/codex-hook-adapter.mjs +18 -9
  18. package/plugin/scripts/continuity-hook-policy.mjs +9 -0
  19. package/plugin/scripts/continuity-journal.mjs +33 -33
  20. package/plugin/scripts/ground-ruvnet.sh +5 -5
  21. package/plugin/scripts/hook-shim.mjs +4 -30
  22. package/plugin/scripts/project-capture-queue.mjs +333 -0
  23. package/plugin/scripts/project-progression-contract.mjs +1 -1
  24. package/plugin/scripts/project-progression-hook.mjs +3 -3
  25. package/plugin/scripts/project-progression-producer.mjs +53 -28
  26. package/plugin/scripts/project-progression-session-start.mjs +44 -4
  27. package/plugin/scripts/project-progression-store.mjs +14 -0
  28. package/plugin/scripts/project-transition-hook.mjs +204 -0
  29. package/plugin/scripts/session-snapshot-hook.mjs +44 -272
  30. package/plugin/scripts/session-start-budget.mjs +2 -2
  31. package/plugin/scripts/turn-outcome-capture.mjs +125 -47
  32. package/plugin/scripts/turn-transport-journal.mjs +106 -0
  33. package/scripts/codex-hook-trust-reconcile.mjs +247 -0
  34. package/scripts/codex-routed.sh +3 -36
  35. package/scripts/goldie-weekly.sh +8 -64
  36. package/scripts/metaharness-router.mjs +7 -1
  37. package/scripts/model-analyst-sandbox.mjs +54 -0
  38. package/scripts/model-currency-evidence.mjs +139 -0
  39. package/scripts/model-currency.mjs +230 -0
  40. package/scripts/model-native-catalog.mjs +111 -0
  41. package/scripts/model-native-qualification.mjs +251 -0
  42. package/scripts/model-router-agent-hook.mjs +136 -0
  43. package/scripts/model-router-dispatch.mjs +161 -0
  44. package/scripts/model-router-engine.mjs +155 -104
  45. package/scripts/model-routing-eval.mjs +108 -0
  46. package/scripts/model-routing-gateway.mjs +420 -0
  47. package/scripts/model-routing-launchers.mjs +174 -0
  48. package/scripts/model-routing-policy-promotion.mjs +203 -0
  49. package/scripts/model-weekly-analyst.mjs +299 -0
  50. package/scripts/model-weekly-assessment.mjs +91 -0
  51. package/scripts/model-weekly-cycle.mjs +183 -0
  52. package/scripts/model-weekly-qualification.mjs +362 -0
  53. package/scripts/native-subscription-usage.mjs +57 -0
  54. package/scripts/release-qualification-contract.mjs +54 -0
  55. package/scripts/security-guidance-codex-compat.mjs +142 -0
  56. package/scripts/user-model-prompt-hook.mjs +69 -0
@@ -1,6 +1,6 @@
1
1
  {
2
- "_note": "The legacy automatic gate collection remains retired. What is permitted is the continuity plane below and nothing else: SessionStart restores the canonical project checkpoint; UserPromptSubmit runs the single unprompted-speech chokepoint; Stop may nudge one explicitly authorized project-scoped objective AND capture a project snapshot; PreCompact and SessionEnd capture a project snapshot. Version 3 of this file permitted exactly two handlers, which was not a safety property but a contradiction: it demanded a restore while forbidding any event that could WRITE the journal the restore reads, so the canonical store held zero progression rows. Adding to this list is still a deliberate act that must pass `npm run hooks:check`; what changed is that the shape can now express the plane that actually works. Amended 2026-09-11 (Stuart): the continuity-only charter had retired the ONLY enforcement of ADR-0012 — never write rUv-product code the brain has not seen — and the failure it exists to prevent recurred the day it was measured absent. The plane now also carries three grounding registrations: ground-ruvnet (UserPromptSubmit, grounding injection — a second owner of that event, scoped by ADR-040 §Amendment 2026-09-11 to directives rather than speech), decision-gate’s write route (PreToolUse, the one refuser, ADR-067), and grounding-stamp (PostToolUse on a successful search_ruvnet, the receipt that opens the write gate). Amended 2026-09-12: the 2026-09-11 claim that Codex PreToolUse/PostToolUse delivery had never been observed was measured with a prompt that never invoked a tool (`codex exec \"reply OK\"`), so it was an untested path, not a failing one. Re-measured with prompts that actually call a tool (a real apply_patch write, a real MCP search_ruvnet call against this repo's own server): both events FIRED on codex-cli 0.154.0 with real payloads. decision-gate's write route and grounding-stamp are now dual-host (see _codexCapture and contracts below); the bash route (exec_command) remains Claude-only — today's measurement did not exercise it. Also amended 2026-09-12: added grounding-turn-mark (UserPromptSubmit) and grounding-turn-gate (Stop), the \"answered without searching\" pair — ground-ruvnet's Gate 1 directive is advisory, so nothing previously checked whether the model complied before the turn ended. grounding-turn-mark records that Gate 1 fired for a turn; grounding-turn-gate forces continuation at Stop if grounding-stamp's own evidence shows no search_ruvnet call happened since. Both dual-host from the start (the Stop-block contract is already proven on Codex via continuation-gate). Added capacity-aware-parallel-work at UserPromptSubmit on both measured hosts: it is context-only, resource-bounded, and requires the coordinator to check actual tool/runtime slots; it does not spawn or claim workers. Amended 2026-09-30 (ADR-0030 decision point #1, no new registration): grounding-turn-mark also arms a turn when the prompt asks a capability/feasibility/architecture question about any tool or platform, and grounding-turn-gate then requires every capability claim in the final answer to be bound to a relevant STRONG source read this turn after the last weak one (a WebFetch body is a small model's summary: weak); on Claude it reads the transcript instead of stamp mtimes, which removed the measured 'no search recorded' false alarms. ADR-0030 #2/#3 run in shadow only.",
3
- "_version": 8,
2
+ "_note": "The legacy automatic gate collection remains retired. What is permitted is the continuity plane below and nothing else: SessionStart restores the canonical project checkpoint; UserPromptSubmit runs the single unprompted-speech chokepoint; Stop may nudge one explicitly authorized project-scoped objective AND capture a project snapshot; PreCompact and SessionEnd capture a project snapshot. Version 3 of this file permitted exactly two handlers, which was not a safety property but a contradiction: it demanded a restore while forbidding any event that could WRITE the journal the restore reads, so the canonical store held zero progression rows. Adding to this list is still a deliberate act that must pass `npm run hooks:check`; what changed is that the shape can now express the plane that actually works. Amended 2026-09-11 (Stuart): the continuity-only charter had retired the ONLY enforcement of ADR-0012 \u2014 never write rUv-product code the brain has not seen \u2014 and the failure it exists to prevent recurred the day it was measured absent. The plane now also carries three grounding registrations: ground-ruvnet (UserPromptSubmit, grounding injection \u2014 a second owner of that event, scoped by ADR-040 \u00a7Amendment 2026-09-11 to directives rather than speech), decision-gate\u2019s write route (PreToolUse, the one refuser, ADR-067), and grounding-stamp (PostToolUse on a successful search_ruvnet, the receipt that opens the write gate). Amended 2026-09-12: the 2026-09-11 claim that Codex PreToolUse/PostToolUse delivery had never been observed was measured with a prompt that never invoked a tool (`codex exec \"reply OK\"`), so it was an untested path, not a failing one. Re-measured with prompts that actually call a tool (a real apply_patch write, a real MCP search_ruvnet call against this repo's own server): both events FIRED on codex-cli 0.154.0 with real payloads. decision-gate's write route and grounding-stamp are now dual-host (see _codexCapture and contracts below); the bash route (exec_command) remains Claude-only \u2014 today's measurement did not exercise it. Also amended 2026-09-12: added grounding-turn-mark (UserPromptSubmit) and grounding-turn-gate (Stop), the \"answered without searching\" pair \u2014 ground-ruvnet's Gate 1 directive is advisory, so nothing previously checked whether the model complied before the turn ended. grounding-turn-mark records that Gate 1 fired for a turn; grounding-turn-gate forces continuation at Stop if grounding-stamp's own evidence shows no search_ruvnet call happened since. Both dual-host from the start (the Stop-block contract is already proven on Codex via continuation-gate). Added capacity-aware-parallel-work at UserPromptSubmit on both measured hosts: it is context-only, resource-bounded, and requires the coordinator to check actual tool/runtime slots; it does not spawn or claim workers. Amended 2026-09-30 (ADR-0030 decision point #1, no new registration): grounding-turn-mark also arms a turn when the prompt asks a capability/feasibility/architecture question about any tool or platform, and grounding-turn-gate then requires every capability claim in the final answer to be bound to a relevant STRONG source read this turn after the last weak one (a WebFetch body is a small model's summary: weak); on Claude it reads the transcript instead of stamp mtimes, which removed the measured 'no search recorded' false alarms. ADR-0030 #2/#3 run in shadow only. Amendment 2026-10-03: normalized prompt/tool/failure/child observations are automatic; startup replays before restoring. Queued and unavailable evidence remain distinct from exact committed readback. Native Grok prompt recall is unsupported.",
3
+ "_version": 9,
4
4
  "_eventOwners": [
5
5
  {
6
6
  "event": "SessionStart",
@@ -10,7 +10,7 @@
10
10
  "claude",
11
11
  "codex"
12
12
  ],
13
- "responsibility": "Restore the newest coherent committed checkpoint. Reads only; ADR-073 §5 forbids replaying the outbox here because replay is a write and a write costs more than this boundary's whole budget."
13
+ "responsibility": "Replay consent-eligible pending canonical memory within the shared startup budget, then restore only verified coherent state; disclose pending or unavailable rather than silently treating an older checkpoint as latest."
14
14
  },
15
15
  {
16
16
  "event": "UserPromptSubmit",
@@ -30,7 +30,7 @@
30
30
  "claude",
31
31
  "codex"
32
32
  ],
33
- "responsibility": "May request one continuation for one explicitly authorized, project-scoped objective read from the user's own work ledger (ADR-043). Never a refusal, never a second task store. Amended 2026-09-30 (ADR-074 class `completion`, no new registration): the same Stop body also requests ONE correction when the final answer claims work is done without a verification command run after the last state change this turn (Claude transcript), a named check, and a NOT-verified disclosure — on Codex, whose rollout format is not parsed, only the answer-side half is enforced and the transcript half is reported UNKNOWN. It also records first-person promises from the final answer into the SAME per-project ledger (Claude only; capped; closed only by a later evidence-passing completion claim, never by --done) and requests continuation on them under the same loop guards and cooldown."
33
+ "responsibility": "May request one continuation for one explicitly authorized, project-scoped objective read from the user's own work ledger (ADR-043). Never a refusal, never a second task store. Amended 2026-09-30 (ADR-074 class `completion`, no new registration): the same Stop body also requests ONE correction when the final answer claims work is done without a verification command run after the last state change this turn (Claude transcript), a named check, and a NOT-verified disclosure \u2014 on Codex, whose rollout format is not parsed, only the answer-side half is enforced and the transcript half is reported UNKNOWN. It also records first-person promises from the final answer into the SAME per-project ledger (Claude only; capped; closed only by a later evidence-passing completion claim, never by --done) and requests continuation on them under the same loop guards and cooldown."
34
34
  },
35
35
  {
36
36
  "event": "Stop",
@@ -40,7 +40,7 @@
40
40
  "claude",
41
41
  "codex"
42
42
  ],
43
- "responsibility": "Append one project snapshot to the canonical store and commit any outbox debt a previously interrupted session left behind. Also records the turn's outcome (final assistant text, files changed, command descriptions — never user text) to AgentDB namespace `turns`, in the project store when it exists or the machine-wide store outside the repository; SessionEnd/PreCompact distill those records (ruflo ADR-174)."
43
+ "responsibility": "Persist redacted turn outcomes through the fsynced canonical-project journal; queued is not recorded. No global fallback. Exact-key content readback commits transport; terminal boundaries also distill eligible records."
44
44
  },
45
45
  {
46
46
  "event": "PreCompact",
@@ -49,7 +49,7 @@
49
49
  "hosts": [
50
50
  "claude"
51
51
  ],
52
- "responsibility": "The boundary at which context is about to be lost — capture before it is."
52
+ "responsibility": "The boundary at which context is about to be lost \u2014 capture before it is."
53
53
  },
54
54
  {
55
55
  "event": "SessionEnd",
@@ -59,7 +59,7 @@
59
59
  "claude",
60
60
  "codex"
61
61
  ],
62
- "responsibility": "The boundary at which the session is about to be gone — capture before it is."
62
+ "responsibility": "The boundary at which the session is about to be gone \u2014 capture before it is."
63
63
  },
64
64
  {
65
65
  "event": "UserPromptSubmit",
@@ -69,7 +69,7 @@
69
69
  "claude",
70
70
  "codex"
71
71
  ],
72
- "responsibility": "Injects a grounding directive into the model’s context when the prompt names the rUv stack, reaches for a classical default, or asks to build: call search_ruvnet before you assert. Not speech — emits no advocacy, promotion, lesson or alarm and reads no dial; silenced by the brain switch (ADR-054); scoped by ADR-040 §Amendment 2026-09-11."
72
+ "responsibility": "Injects a grounding directive into the model\u2019s context when the prompt names the rUv stack, reaches for a classical default, or asks to build: call search_ruvnet before you assert. Not speech \u2014 emits no advocacy, promotion, lesson or alarm and reads no dial; silenced by the brain switch (ADR-054); scoped by ADR-040 \u00a7Amendment 2026-09-11."
73
73
  },
74
74
  {
75
75
  "event": "UserPromptSubmit",
@@ -79,7 +79,7 @@
79
79
  "claude",
80
80
  "codex"
81
81
  ],
82
- "responsibility": "For clearly substantial, independently splittable work, adds context-only guidance based on bounded memory-pressure, swap, compression, and normalized-load signals. It never creates workers, claims they are running, or overrides the coordinator’s live agent-tool/runtime cap; unknown capacity recommends serial execution."
82
+ "responsibility": "For clearly substantial, independently splittable work, adds context-only guidance based on bounded memory-pressure, swap, compression, and normalized-load signals. It never creates workers, claims they are running, or overrides the coordinator\u2019s live agent-tool/runtime cap; unknown capacity recommends serial execution."
83
83
  },
84
84
  {
85
85
  "event": "PreToolUse",
@@ -109,7 +109,7 @@
109
109
  "claude",
110
110
  "codex"
111
111
  ],
112
- "responsibility": "Records that ground-ruvnet's Gate 1 (the same regex, proven byte-identical by test) matched this turn's prompt, so grounding-turn-gate has something to check at Stop — Stop's own payload carries no prompt text. Amended 2026-09-30: also arms when the prompt asks a capability/feasibility/architecture question about any tool or platform, recording the subjects it named; a marker not yet consumed is merged without moving its mtime (a queued mid-turn prompt re-dating it was a measured false-alarm cause). Writes only a marker file under ~/.cache/ruvnet-brain/grounding-turn/; never blocks, never speaks to the model."
112
+ "responsibility": "Records that ground-ruvnet's Gate 1 (the same regex, proven byte-identical by test) matched this turn's prompt, so grounding-turn-gate has something to check at Stop \u2014 Stop's own payload carries no prompt text. Amended 2026-09-30: also arms when the prompt asks a capability/feasibility/architecture question about any tool or platform, recording the subjects it named; a marker not yet consumed is merged without moving its mtime (a queued mid-turn prompt re-dating it was a measured false-alarm cause). Writes only a marker file under ~/.cache/ruvnet-brain/grounding-turn/; never blocks, never speaks to the model."
113
113
  },
114
114
  {
115
115
  "event": "Stop",
@@ -119,7 +119,56 @@
119
119
  "claude",
120
120
  "codex"
121
121
  ],
122
- "responsibility": "The 'answered without searching' gate (2026-09-12): if grounding-turn-mark's marker shows Gate 1 fired this turn and grounding-stamp's own stamp evidence shows no search_ruvnet call happened since, forces continuation via the same hookSpecificOutput.additionalContext contract continuation-gate already uses on both hosts. A separate registration from continuation-gate — see grounding-turn-gate.mjs's header for why folding it into that file's ledger/cooldown semantics would corrupt them rather than extend them. Consumes its marker unconditionally so a stale one can never pressure an unrelated later turn. Amended 2026-09-30 (ADR-0030 #1): on Claude, 'was search_ruvnet called' is read from the transcript, and on an armed turn each capability claim in the final answer must be bound to a relevant strong source read this turn after the last weak one, else ONE correction naming the claim and what was read; on Codex (rollout not parsed) only rUv-term claims are judged, from stamps, and the rest are UNKNOWN. Gates #2/#3 are shadow-logged, never delivered."
122
+ "responsibility": "The 'answered without searching' gate (2026-09-12): if grounding-turn-mark's marker shows Gate 1 fired this turn and grounding-stamp's own stamp evidence shows no search_ruvnet call happened since, forces continuation via the same hookSpecificOutput.additionalContext contract continuation-gate already uses on both hosts. A separate registration from continuation-gate \u2014 see grounding-turn-gate.mjs's header for why folding it into that file's ledger/cooldown semantics would corrupt them rather than extend them. Consumes its marker unconditionally so a stale one can never pressure an unrelated later turn. Amended 2026-09-30 (ADR-0030 #1): on Claude, 'was search_ruvnet called' is read from the transcript, and on an armed turn each capability claim in the final answer must be bound to a relevant strong source read this turn after the last weak one, else ONE correction naming the claim and what was read; on Codex (rollout not parsed) only rUv-term claims are judged, from stamps, and the rest are UNKNOWN. Gates #2/#3 are shadow-logged, never delivered."
123
+ },
124
+ {
125
+ "event": "UserPromptSubmit",
126
+ "owner": "session-snapshot",
127
+ "class": "normalized continuity observation",
128
+ "hosts": [
129
+ "claude",
130
+ "codex"
131
+ ],
132
+ "responsibility": "Capture bounded redacted observable intent or outcome through the canonical progression bridge; retain pending/failed status and do not infer success from pre-tool intent."
133
+ },
134
+ {
135
+ "event": "PreToolUse",
136
+ "owner": "session-snapshot",
137
+ "class": "normalized continuity observation",
138
+ "hosts": [
139
+ "claude",
140
+ "codex"
141
+ ],
142
+ "responsibility": "Capture bounded redacted observable intent or outcome through the canonical progression bridge; retain pending/failed status and do not infer success from pre-tool intent."
143
+ },
144
+ {
145
+ "event": "PostToolUse",
146
+ "owner": "session-snapshot",
147
+ "class": "normalized continuity observation",
148
+ "hosts": [
149
+ "claude",
150
+ "codex"
151
+ ],
152
+ "responsibility": "Capture bounded redacted observable intent or outcome through the canonical progression bridge; retain pending/failed status and do not infer success from pre-tool intent."
153
+ },
154
+ {
155
+ "event": "PostToolUseFailure",
156
+ "owner": "session-snapshot",
157
+ "class": "normalized continuity observation",
158
+ "hosts": [
159
+ "claude"
160
+ ],
161
+ "responsibility": "Capture bounded redacted observable intent or outcome through the canonical progression bridge; retain pending/failed status and do not infer success from pre-tool intent."
162
+ },
163
+ {
164
+ "event": "SubagentStop",
165
+ "owner": "session-snapshot",
166
+ "class": "normalized continuity observation",
167
+ "hosts": [
168
+ "claude",
169
+ "codex"
170
+ ],
171
+ "responsibility": "Capture bounded redacted observable intent or outcome through the canonical progression bridge; retain pending/failed status and do not infer success from pre-tool intent."
123
172
  }
124
173
  ],
125
174
  "_notInThisPlane": [
@@ -127,7 +176,7 @@
127
176
  "id": "decision-gate (bash route)",
128
177
  "class": "consequential-action authorization",
129
178
  "adr": "ADR-067",
130
- "reachability": "The bash sub-event (protect-state, identifier-preflight, spend-guard, degradation-watch, hijack-ruvnet, design-wall) stays reachable through hook-shim.mjs by explicit invocation and is not registered: the 2026-09-11 mandate was the WRITE path (ADR-0012), and no host has proven PreToolUse delivery for Bash under the plane’s measured-not-assumed rule. The write route IS in the plane — see contracts."
179
+ "reachability": "The bash sub-event (protect-state, identifier-preflight, spend-guard, degradation-watch, hijack-ruvnet, design-wall) stays reachable through hook-shim.mjs by explicit invocation and is not registered: the 2026-09-11 mandate was the WRITE path (ADR-0012), and no host has proven PreToolUse delivery for Bash under the plane\u2019s measured-not-assumed rule. The write route IS in the plane \u2014 see contracts."
131
180
  },
132
181
  {
133
182
  "id": "execution-policy",
@@ -140,13 +189,13 @@
140
189
  "state": "partial",
141
190
  "measuredOn": "2026-09-12",
142
191
  "host": "codex-cli 0.154.0",
143
- "method": "2026-09-11: a probe hook was registered in a temporary CODEX_HOME on all twelve event names the installed binary declares, and a real `codex exec \"reply OK\"` was run against it — a prompt that never invokes a tool. 2026-09-12: re-probed with prompts that DO invoke a tool — a real apply_patch write, and a real MCP call to this repo's own plugin/mcp/server.mjs registered as `search_ruvnet` in the probe's CODEX_HOME config.toml.",
192
+ "method": "2026-09-11: a probe hook was registered in a temporary CODEX_HOME on all twelve event names the installed binary declares, and a real `codex exec \"reply OK\"` was run against it \u2014 a prompt that never invokes a tool. 2026-09-12: re-probed with prompts that DO invoke a tool \u2014 a real apply_patch write, and a real MCP call to this repo's own plugin/mcp/server.mjs registered as `search_ruvnet` in the probe's CODEX_HOME config.toml.",
144
193
  "fired": [
145
194
  "SessionStart",
146
195
  "UserPromptSubmit",
147
196
  "SessionEnd",
148
197
  "PreToolUse (apply_patch write; tool_input.command carried the raw patch)",
149
- "PostToolUse (apply_patch write; tool_response = \"Exit code: 0 … Success. Updated the following files: A <path>\")",
198
+ "PostToolUse (apply_patch write; tool_response = \"Exit code: 0 \u2026 Success. Updated the following files: A <path>\")",
150
199
  "PreToolUse (MCP search_ruvnet; tool_name mcp__ruvnet_brain__search_ruvnet, tool_input.query preserved verbatim)",
151
200
  "PostToolUse (MCP search_ruvnet; tool_response.content[0].text carried the \"Searched N RuvNet repos\" banner)"
152
201
  ],
@@ -154,7 +203,7 @@
154
203
  "Stop": "The 2026-09-11 probe turn never completed, so run_turn_stop_hooks had no completion to fire on. The binary declares the event and StopCommandOutputWire, so this is not-proven rather than unsupported. Stop keeps only the pre-existing continuation gate; no capture handler was added to an event whose delivery has not been seen.",
155
204
  "PreCompact": "A one-line turn never approaches a compaction threshold. The binary declares PreCompact and PreCompactCommandOutputWire. No capture handler registered."
156
205
  },
157
- "consequence": "Codex captures at SessionEnd only; Stop/PreCompact remain unproven and unregistered as above (unchanged by this measurement). PreToolUse/PostToolUse are now proven for a write (apply_patch) and an MCP tool call (search_ruvnet) specifically, and decision-gate's write route plus grounding-stamp are registered on Codex accordingly (see contracts below). Bash-class tool calls (exec_command) were not exercised by this measurement and remain unregistered — extending on unexercised evidence would repeat the exact mistake this record corrects. Amended 2026-09-29: session-snapshot is registered on Codex Stop so each Codex turn's outcome is recorded (SessionEnd carries no last_assistant_message). Stop delivery is still NOT live-observed; the registration rests on codex-cli 0.158.0's declared stop.command.input schema and fails open."
206
+ "consequence": "Codex captures at SessionEnd only; Stop/PreCompact remain unproven and unregistered as above (unchanged by this measurement). PreToolUse/PostToolUse are now proven for a write (apply_patch) and an MCP tool call (search_ruvnet) specifically, and decision-gate's write route plus grounding-stamp are registered on Codex accordingly (see contracts below). Bash-class tool calls (exec_command) were not exercised by this measurement and remain unregistered \u2014 extending on unexercised evidence would repeat the exact mistake this record corrects. Amended 2026-09-29: session-snapshot is registered on Codex Stop so each Codex turn's outcome is recorded (SessionEnd carries no last_assistant_message). Stop delivery is still NOT live-observed; the registration rests on codex-cli 0.158.0's declared stop.command.input schema and fails open."
158
207
  },
159
208
  "contracts": [
160
209
  {
@@ -167,7 +216,7 @@
167
216
  "mode": "advisory",
168
217
  "offBehavior": "partial",
169
218
  "matcher": "startup|resume|clear|compact|fork",
170
- "timeout": 5
219
+ "timeout": 8
171
220
  },
172
221
  {
173
222
  "id": "unprompted-speech",
@@ -299,6 +348,65 @@
299
348
  "offBehavior": "silence",
300
349
  "matcher": "*",
301
350
  "timeout": 10
351
+ },
352
+ {
353
+ "id": "session-snapshot",
354
+ "event": "UserPromptSubmit",
355
+ "hosts": [
356
+ "claude",
357
+ "codex"
358
+ ],
359
+ "mode": "advisory",
360
+ "offBehavior": "run",
361
+ "matcher": "*",
362
+ "timeout": 10
363
+ },
364
+ {
365
+ "id": "session-snapshot",
366
+ "event": "PreToolUse",
367
+ "hosts": [
368
+ "claude",
369
+ "codex"
370
+ ],
371
+ "mode": "advisory",
372
+ "offBehavior": "run",
373
+ "matcher": "*",
374
+ "timeout": 10
375
+ },
376
+ {
377
+ "id": "session-snapshot",
378
+ "event": "PostToolUse",
379
+ "hosts": [
380
+ "claude",
381
+ "codex"
382
+ ],
383
+ "mode": "advisory",
384
+ "offBehavior": "run",
385
+ "matcher": "*",
386
+ "timeout": 10
387
+ },
388
+ {
389
+ "id": "session-snapshot",
390
+ "event": "PostToolUseFailure",
391
+ "hosts": [
392
+ "claude"
393
+ ],
394
+ "mode": "advisory",
395
+ "offBehavior": "run",
396
+ "matcher": "*",
397
+ "timeout": 10
398
+ },
399
+ {
400
+ "id": "session-snapshot",
401
+ "event": "SubagentStop",
402
+ "hosts": [
403
+ "claude",
404
+ "codex"
405
+ ],
406
+ "mode": "advisory",
407
+ "offBehavior": "run",
408
+ "matcher": "*",
409
+ "timeout": 10
302
410
  }
303
411
  ],
304
412
  "matcherAllowlist": [
@@ -341,15 +449,106 @@
341
449
  "layer": "plugin",
342
450
  "event": "PreToolUse",
343
451
  "matcher": "^(Write|Edit|MultiEdit|NotebookEdit|apply_patch)$",
344
- "reason": "The write-class tools, anchored — the exact matcher ADR-067 shipped and hook-registry-lint’s matcher-semantics test models. Claude Code matchers are searches, so the anchors are load-bearing. apply_patch (Codex's raw write-tool name) was added 2026-09-12 after a real apply_patch call was measured to fire this event live on codex-cli 0.154.0 — a dead branch on Claude, which never names a tool apply_patch.",
345
- "retiredBy": "not retired — registered 2026-09-11 (ADR-0012 / ADR-067, Stuart mandate); extended to Codex 2026-09-12"
452
+ "reason": "The write-class tools, anchored \u2014 the exact matcher ADR-067 shipped and hook-registry-lint\u2019s matcher-semantics test models. Claude Code matchers are searches, so the anchors are load-bearing. apply_patch (Codex's raw write-tool name) was added 2026-09-12 after a real apply_patch call was measured to fire this event live on codex-cli 0.154.0 \u2014 a dead branch on Claude, which never names a tool apply_patch.",
453
+ "retiredBy": "not retired \u2014 registered 2026-09-11 (ADR-0012 / ADR-067, Stuart mandate); extended to Codex 2026-09-12"
346
454
  },
347
455
  {
348
456
  "layer": "plugin",
349
457
  "event": "PostToolUse",
350
458
  "matcher": "^(?:.*__)?search_ruvnet$",
351
459
  "reason": "The grounding tool with or without an MCP server prefix (mcp__plugin_ruvnet-brain_ruvnet-brain__search_ruvnet, or Codex's mcp__ruvnet_brain__search_ruvnet, measured live 2026-09-12). Only a successful search may mint a stamp; the body checks the result banner.",
352
- "retiredBy": "not retired — registered 2026-09-11 (ADR-0012); Codex host proven reachable 2026-09-12, matcher unchanged"
460
+ "retiredBy": "not retired \u2014 registered 2026-09-11 (ADR-0012); Codex host proven reachable 2026-09-12, matcher unchanged"
461
+ },
462
+ {
463
+ "layer": "plugin",
464
+ "event": "PreToolUse",
465
+ "matcher": "*",
466
+ "reason": "Observe normalized lifecycle transitions independently of the write-refusal and grounding matchers; the body enforces canonical identity, consent and bounded non-authoritative semantic observations.",
467
+ "retiredBy": "not retired - owner automatic AgentDB mandate 2026-10-03"
468
+ },
469
+ {
470
+ "layer": "plugin",
471
+ "event": "PostToolUse",
472
+ "matcher": "*",
473
+ "reason": "Observe normalized lifecycle transitions independently of the write-refusal and grounding matchers; the body enforces canonical identity, consent and bounded non-authoritative semantic observations.",
474
+ "retiredBy": "not retired - owner automatic AgentDB mandate 2026-10-03"
475
+ },
476
+ {
477
+ "layer": "plugin",
478
+ "event": "PostToolUseFailure",
479
+ "matcher": "*",
480
+ "reason": "Observe normalized lifecycle transitions independently of the write-refusal and grounding matchers; the body enforces canonical identity, consent and bounded non-authoritative semantic observations.",
481
+ "retiredBy": "not retired - owner automatic AgentDB mandate 2026-10-03"
482
+ },
483
+ {
484
+ "layer": "plugin",
485
+ "event": "SubagentStop",
486
+ "matcher": "*",
487
+ "reason": "Observe normalized lifecycle transitions independently of the write-refusal and grounding matchers; the body enforces canonical identity, consent and bounded non-authoritative semantic observations.",
488
+ "retiredBy": "not retired - owner automatic AgentDB mandate 2026-10-03"
489
+ },
490
+ {
491
+ "layer": "codex",
492
+ "event": "PreToolUse",
493
+ "matcher": "*",
494
+ "reason": "Canonical observation owner sees tool transitions before normalization; bounded body selects substantive observations. The independent anchored decision and grounding matchers remain unchanged.",
495
+ "retiredBy": "not retired - automatic memory mandate 2026-10-03"
496
+ },
497
+ {
498
+ "layer": "codex",
499
+ "event": "PostToolUse",
500
+ "matcher": "*",
501
+ "reason": "Canonical observation owner sees tool transitions before normalization; bounded body selects substantive observations. The independent anchored decision and grounding matchers remain unchanged.",
502
+ "retiredBy": "not retired - automatic memory mandate 2026-10-03"
503
+ },
504
+ {
505
+ "layer": "codex",
506
+ "event": "SessionStart",
507
+ "matcher": "startup|resume|clear|compact|fork",
508
+ "reason": "Explicit supported Codex lifecycle registration, corresponding to the host-filtered continuity policy; its enforcing handler and live registration are checked independently.",
509
+ "retiredBy": "not retired - canonical continuity host parity"
510
+ },
511
+ {
512
+ "layer": "codex",
513
+ "event": "Stop",
514
+ "matcher": "*",
515
+ "reason": "Explicit supported Codex lifecycle registration, corresponding to the host-filtered continuity policy; its enforcing handler and live registration are checked independently.",
516
+ "retiredBy": "not retired - canonical continuity host parity"
517
+ },
518
+ {
519
+ "layer": "codex",
520
+ "event": "PreToolUse",
521
+ "matcher": "^(Write|Edit|MultiEdit|NotebookEdit|apply_patch)$",
522
+ "reason": "Explicit supported Codex lifecycle registration, corresponding to the host-filtered continuity policy; its enforcing handler and live registration are checked independently.",
523
+ "retiredBy": "not retired - canonical continuity host parity"
524
+ },
525
+ {
526
+ "layer": "codex",
527
+ "event": "PostToolUse",
528
+ "matcher": "^(?:.*__)?search_ruvnet$",
529
+ "reason": "Explicit supported Codex lifecycle registration, corresponding to the host-filtered continuity policy; its enforcing handler and live registration are checked independently.",
530
+ "retiredBy": "not retired - canonical continuity host parity"
531
+ },
532
+ {
533
+ "layer": "codex",
534
+ "event": "UserPromptSubmit",
535
+ "matcher": "*",
536
+ "reason": "Explicit supported Codex lifecycle registration, corresponding to the host-filtered continuity policy; its enforcing handler and live registration are checked independently.",
537
+ "retiredBy": "not retired - canonical continuity host parity"
538
+ },
539
+ {
540
+ "layer": "codex",
541
+ "event": "SessionEnd",
542
+ "matcher": "*",
543
+ "reason": "Explicit supported Codex lifecycle registration, corresponding to the host-filtered continuity policy; its enforcing handler and live registration are checked independently.",
544
+ "retiredBy": "not retired - canonical continuity host parity"
545
+ },
546
+ {
547
+ "layer": "codex",
548
+ "event": "SubagentStop",
549
+ "matcher": "*",
550
+ "reason": "Explicit supported Codex lifecycle registration, corresponding to the host-filtered continuity policy; its enforcing handler and live registration are checked independently.",
551
+ "retiredBy": "not retired - canonical continuity host parity"
353
552
  }
354
553
  ]
355
554
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "RuvNet Brain lifecycle plane. The broad legacy routing, learning, and release interceptors remain retired. What is automatic is exactly: SessionStart restores the canonical project checkpoint; UserPromptSubmit runs the single unprompted-speech chokepoint, ground-ruvnet grounding injection, and a capacity-aware context hint for clearly large independent work. The capacity hook uses bounded CPU/memory-pressure evidence, never starts agents, and tells the coordinator to check live tools and clamp to the runtime cap; it is not user-facing speech. ground-ruvnet remains a directive to the model, not speech — ADR-040 §Amendment 2026-09-11. PreToolUse runs decision-gate's write route, the ONE process that may refuse a Write/Edit/MultiEdit/NotebookEdit/apply_patch (ADR-067, composing ground-before-write per ADR-0012); PostToolUse on a successful search_ruvnet mints the grounding stamp that opens that gate. grounding-turn-mark (UserPromptSubmit) records that the grounding directive fired this turn, and grounding-turn-gate (Stop) forces continuation if the final answer asserts a rUv capability and no search_ruvnet call was recorded since. Stop also runs the ledger-scoped continuation handler and captures a project snapshot; PreCompact and SessionEnd capture a project snapshot. Every capture is bounded and fails open; only decision-gate may block on exit code, and it fails open on its own errors — the Stop stdout envelopes are advisory at the shim boundary but keep the agent working.",
2
+ "description": "RuvNet Brain lifecycle plane. The broad legacy routing, learning, and release interceptors remain retired. What is automatic is exactly: SessionStart restores the canonical project checkpoint; UserPromptSubmit runs the single unprompted-speech chokepoint, ground-ruvnet grounding injection, and a capacity-aware context hint for clearly large independent work. The capacity hook uses bounded CPU/memory-pressure evidence, never starts agents, and tells the coordinator to check live tools and clamp to the runtime cap; it is not user-facing speech. ground-ruvnet remains a directive to the model, not speech \u2014 ADR-040 \u00a7Amendment 2026-09-11. PreToolUse runs decision-gate's write route, the ONE process that may refuse a Write/Edit/MultiEdit/NotebookEdit/apply_patch (ADR-067, composing ground-before-write per ADR-0012); PostToolUse on a successful search_ruvnet mints the grounding stamp that opens that gate. grounding-turn-mark (UserPromptSubmit) records that the grounding directive fired this turn, and grounding-turn-gate (Stop) forces continuation if the final answer asserts a rUv capability and no search_ruvnet call was recorded since. Stop also runs the ledger-scoped continuation handler and captures a project snapshot; PreCompact and SessionEnd capture a project snapshot. Every capture is bounded and fails open; only decision-gate may block on exit code, and it fails open on its own errors \u2014 the Stop stdout envelopes are advisory at the shim boundary but keep the agent working. Automatic normalized project observations are captured at prompt, pre-tool, post-tool and child completion; Claude also observes PostToolUseFailure. Pending and degraded memory are disclosed; this does not establish synchronous ADR-073 conformance or native Grok recall. SessionStart has an 8-second measured replay/restore envelope.",
3
3
  "hooks": {
4
4
  "SessionStart": [
5
5
  {
@@ -8,7 +8,7 @@
8
8
  {
9
9
  "type": "command",
10
10
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" session-start || true",
11
- "timeout": 5
11
+ "timeout": 8
12
12
  }
13
13
  ]
14
14
  }
@@ -17,6 +17,11 @@
17
17
  {
18
18
  "matcher": "*",
19
19
  "hooks": [
20
+ {
21
+ "type": "command",
22
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" session-snapshot UserPromptSubmit || true",
23
+ "timeout": 10
24
+ },
20
25
  {
21
26
  "type": "command",
22
27
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" unprompted-speech UserPromptSubmit",
@@ -41,6 +46,16 @@
41
46
  }
42
47
  ],
43
48
  "PreToolUse": [
49
+ {
50
+ "matcher": "*",
51
+ "hooks": [
52
+ {
53
+ "type": "command",
54
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" session-snapshot PreToolUse || true",
55
+ "timeout": 10
56
+ }
57
+ ]
58
+ },
44
59
  {
45
60
  "matcher": "^(Write|Edit|MultiEdit|NotebookEdit|apply_patch)$",
46
61
  "hooks": [
@@ -53,6 +68,16 @@
53
68
  }
54
69
  ],
55
70
  "PostToolUse": [
71
+ {
72
+ "matcher": "*",
73
+ "hooks": [
74
+ {
75
+ "type": "command",
76
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" session-snapshot PostToolUse || true",
77
+ "timeout": 10
78
+ }
79
+ ]
80
+ },
56
81
  {
57
82
  "matcher": "^(?:.*__)?search_ruvnet$",
58
83
  "hooks": [
@@ -109,6 +134,30 @@
109
134
  }
110
135
  ]
111
136
  }
137
+ ],
138
+ "SubagentStop": [
139
+ {
140
+ "matcher": "*",
141
+ "hooks": [
142
+ {
143
+ "type": "command",
144
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" session-snapshot SubagentStop || true",
145
+ "timeout": 10
146
+ }
147
+ ]
148
+ }
149
+ ],
150
+ "PostToolUseFailure": [
151
+ {
152
+ "matcher": "*",
153
+ "hooks": [
154
+ {
155
+ "type": "command",
156
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-shim.mjs\" session-snapshot PostToolUseFailure || true",
157
+ "timeout": 10
158
+ }
159
+ ]
160
+ }
112
161
  ]
113
162
  }
114
163
  }