session-orchestrator 3.21.0 → 3.23.0

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 (345) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.cursor/commands/autopilot-multi.md +14 -0
  5. package/.cursor/commands/autopilot.md +14 -0
  6. package/.cursor/commands/bootstrap.md +14 -0
  7. package/.cursor/commands/brainstorm.md +14 -0
  8. package/.cursor/commands/close.md +13 -0
  9. package/.cursor/commands/contract-version-bump.md +14 -0
  10. package/.cursor/commands/debug.md +14 -0
  11. package/.cursor/commands/discovery.md +14 -0
  12. package/.cursor/commands/dispatcher.md +14 -0
  13. package/.cursor/commands/eli5.md +14 -0
  14. package/.cursor/commands/eval.md +14 -0
  15. package/.cursor/commands/evolve.md +14 -0
  16. package/.cursor/commands/go.md +14 -0
  17. package/.cursor/commands/grill.md +14 -0
  18. package/.cursor/commands/harness-audit.md +13 -0
  19. package/.cursor/commands/journey-audit.md +14 -0
  20. package/.cursor/commands/memory-cleanup.md +14 -0
  21. package/.cursor/commands/persona-panel.md +14 -0
  22. package/.cursor/commands/plan.md +14 -0
  23. package/.cursor/commands/portfolio.md +14 -0
  24. package/.cursor/commands/reconcile.md +14 -0
  25. package/.cursor/commands/release.md +14 -0
  26. package/.cursor/commands/repo-audit.md +13 -0
  27. package/.cursor/commands/session.md +14 -0
  28. package/.cursor/commands/spinout.md +14 -0
  29. package/.cursor/commands/sunset-review.md +14 -0
  30. package/.cursor/commands/templates-ack.md +14 -0
  31. package/.cursor/commands/test.md +14 -0
  32. package/.cursor/hooks.json +60 -0
  33. package/.cursor/rules/000-session-orchestrator.mdc +11 -2
  34. package/.cursor/rules/010-session-workflow.mdc +9 -1
  35. package/.cursor/rules/020-quality-gates.mdc +1 -1
  36. package/.cursor/rules/030-wave-execution.mdc +1 -1
  37. package/.cursor/rules/040-discovery.mdc +6 -6
  38. package/.cursor/rules/050-plan.mdc +10 -10
  39. package/.cursor/rules/070-gitlab-ops.mdc +73 -57
  40. package/.cursor/rules/080-ecosystem-health.mdc +7 -7
  41. package/.cursor/skills/architecture/SKILL.md +13 -0
  42. package/.cursor/skills/autopilot/SKILL.md +12 -0
  43. package/.cursor/skills/bootstrap/SKILL.md +12 -0
  44. package/.cursor/skills/brainstorm/SKILL.md +13 -0
  45. package/.cursor/skills/claude-md-drift-check/SKILL.md +13 -0
  46. package/.cursor/skills/contract-version-bump/SKILL.md +12 -0
  47. package/.cursor/skills/convergence-monitoring/SKILL.md +12 -0
  48. package/.cursor/skills/daily/SKILL.md +12 -0
  49. package/.cursor/skills/debug/SKILL.md +13 -0
  50. package/.cursor/skills/discovery/SKILL.md +13 -0
  51. package/.cursor/skills/dispatcher/SKILL.md +13 -0
  52. package/.cursor/skills/docs-orchestrator/SKILL.md +13 -0
  53. package/.cursor/skills/domain-model/SKILL.md +13 -0
  54. package/.cursor/skills/ecosystem-health/SKILL.md +13 -0
  55. package/.cursor/skills/eli5/SKILL.md +13 -0
  56. package/.cursor/skills/eval/SKILL.md +12 -0
  57. package/.cursor/skills/evolve/SKILL.md +13 -0
  58. package/.cursor/skills/frontmatter-guard/SKILL.md +13 -0
  59. package/.cursor/skills/gitlab-ops/SKILL.md +13 -0
  60. package/.cursor/skills/gitlab-portfolio/SKILL.md +13 -0
  61. package/.cursor/skills/grill/SKILL.md +13 -0
  62. package/.cursor/skills/hook-development/SKILL.md +13 -0
  63. package/.cursor/skills/journey-audit/SKILL.md +13 -0
  64. package/.cursor/skills/mcp-builder/SKILL.md +13 -0
  65. package/.cursor/skills/memory-cleanup/SKILL.md +12 -0
  66. package/.cursor/skills/mode-selector/SKILL.md +13 -0
  67. package/.cursor/skills/npm-publish/SKILL.md +12 -0
  68. package/.cursor/skills/peekaboo-driver/SKILL.md +13 -0
  69. package/.cursor/skills/persona-panel/SKILL.md +12 -0
  70. package/.cursor/skills/plan/SKILL.md +13 -0
  71. package/.cursor/skills/playwright-driver/SKILL.md +13 -0
  72. package/.cursor/skills/quality-gates/SKILL.md +13 -0
  73. package/.cursor/skills/reconcile/SKILL.md +12 -0
  74. package/.cursor/skills/repo-audit/SKILL.md +13 -0
  75. package/.cursor/skills/session-end/SKILL.md +13 -0
  76. package/.cursor/skills/session-plan/SKILL.md +13 -0
  77. package/.cursor/skills/session-start/SKILL.md +13 -0
  78. package/.cursor/skills/skill-creator/SKILL.md +13 -0
  79. package/.cursor/skills/spinout/SKILL.md +12 -0
  80. package/.cursor/skills/sunset-review/SKILL.md +13 -0
  81. package/.cursor/skills/test-runner/SKILL.md +13 -0
  82. package/.cursor/skills/tmux-layout/SKILL.md +13 -0
  83. package/.cursor/skills/ubiquitous-language/SKILL.md +13 -0
  84. package/.cursor/skills/using-orchestrator/SKILL.md +13 -0
  85. package/.cursor/skills/vault-mirror/SKILL.md +13 -0
  86. package/.cursor/skills/vault-sync/SKILL.md +13 -0
  87. package/.cursor/skills/wave-executor/SKILL.md +13 -0
  88. package/.cursor/skills/write-executable-plan/SKILL.md +13 -0
  89. package/.mcp.json +4 -1
  90. package/CHANGELOG.md +269 -0
  91. package/README.md +18 -15
  92. package/agents/AGENTS.md +23 -4
  93. package/agents/code-implementer.md +2 -1
  94. package/agents/db-specialist.md +2 -1
  95. package/agents/docs-writer.md +3 -1
  96. package/agents/eval-judge.md +1 -1
  97. package/agents/memory-proposal-collector.md +6 -4
  98. package/agents/session-reviewer.md +7 -1
  99. package/agents/test-writer.md +2 -1
  100. package/agents/ui-developer.md +2 -1
  101. package/commands/bootstrap.md +2 -2
  102. package/commands/close.md +3 -1
  103. package/commands/eli5.md +33 -0
  104. package/commands/go.md +1 -1
  105. package/commands/journey-audit.md +43 -0
  106. package/commands/release.md +5 -3
  107. package/commands/test.md +2 -2
  108. package/docs/USER-GUIDE.md +2 -2
  109. package/docs/ci-setup.md +14 -0
  110. package/docs/codex-setup.md +64 -0
  111. package/docs/components.md +7 -6
  112. package/docs/cursor-setup.md +26 -47
  113. package/docs/events-schema.md +76 -4
  114. package/docs/github-mirror-protection.md +197 -0
  115. package/docs/pi-setup.md +2 -0
  116. package/docs/rule-authoring.md +3 -1
  117. package/docs/scope-collision-guard.md +52 -5
  118. package/docs/session-config-reference.md +57 -12
  119. package/docs/session-config-template.md +4 -3
  120. package/docs/telemetry.md +22 -0
  121. package/hooks/_lib/lock-bootstrap.mjs +26 -16
  122. package/hooks/_lib/vcs-create-matcher.mjs +397 -38
  123. package/hooks/enforce-scope.mjs +64 -0
  124. package/hooks/hooks-codex.json +1 -1
  125. package/hooks/hooks-cursor.json +201 -20
  126. package/hooks/hooks-pi.json +1 -1
  127. package/hooks/hooks.json +12 -2
  128. package/hooks/on-session-end.mjs +237 -104
  129. package/hooks/on-session-start.mjs +404 -110
  130. package/hooks/on-stop.mjs +48 -9
  131. package/hooks/post-subagent-discovery-validator.mjs +34 -3
  132. package/hooks/post-tool-batch-wave-signal.mjs +11 -2
  133. package/hooks/pre-auq-clarity.mjs +787 -0
  134. package/hooks/pre-bash-issue-budget.mjs +133 -21
  135. package/hooks/pre-bash-sessions-ledger-guard.mjs +159 -0
  136. package/hooks/pre-bash-staging-fence.mjs +4 -0
  137. package/hooks/pre-task-scope-disjoint.mjs +368 -35
  138. package/hooks/skill-invocation-telemetry.mjs +21 -10
  139. package/monitors/monitors.json +6 -0
  140. package/package.json +3 -1
  141. package/pi/prompts/eli5.md +12 -0
  142. package/pi/prompts/journey-audit.md +12 -0
  143. package/rules/_index.md +9 -1
  144. package/rules/always-on/ask-via-tool.md +62 -0
  145. package/rules/always-on/bash-harness-pitfalls.md +168 -0
  146. package/rules/always-on/build-value.md +47 -0
  147. package/rules/always-on/cross-session-messaging.md +59 -0
  148. package/rules/always-on/loop-and-monitor.md +221 -0
  149. package/rules/always-on/parallel-sessions.md +142 -12
  150. package/rules/always-on/receiving-review.md +108 -0
  151. package/rules/always-on/test-value.md +40 -0
  152. package/rules/always-on/verification-before-completion.md +77 -0
  153. package/scripts/archive-closed-prds.mjs +258 -18
  154. package/scripts/auq-audit.mjs +825 -0
  155. package/scripts/autopilot.mjs +12 -8
  156. package/scripts/backfill-evidence-digest.mjs +376 -0
  157. package/scripts/cursor-install.mjs +89 -48
  158. package/scripts/export-hw-learnings.mjs +143 -2
  159. package/scripts/express-path.mjs +299 -0
  160. package/scripts/generate-cursor-adapter.mjs +253 -0
  161. package/scripts/github-protection-audit.mjs +358 -0
  162. package/scripts/lib/auq/clarity.mjs +1314 -0
  163. package/scripts/lib/auq/parse.mjs +1006 -0
  164. package/scripts/lib/auq/schema.mjs +1457 -0
  165. package/scripts/lib/autopilot/worktree-pipeline.mjs +240 -16
  166. package/scripts/lib/build-live-signals.mjs +24 -5
  167. package/scripts/lib/ci-status-banner.mjs +221 -68
  168. package/scripts/lib/command-blocker.mjs +70 -0
  169. package/scripts/lib/config/dispatcher-autonomy-capture.mjs +32 -9
  170. package/scripts/lib/config/reconcile.mjs +79 -4
  171. package/scripts/lib/config/section-extractor.mjs +235 -36
  172. package/scripts/lib/config/vault-integration.mjs +12 -1
  173. package/scripts/lib/config-schema.mjs +9 -1
  174. package/scripts/lib/config.mjs +57 -6
  175. package/scripts/lib/convergence-monitor.mjs +13 -2
  176. package/scripts/lib/cursor-hook-bridge.mjs +443 -0
  177. package/scripts/lib/dispatcher/cli.mjs +2 -2
  178. package/scripts/lib/dispatcher/rank.mjs +4 -7
  179. package/scripts/lib/express-path.mjs +327 -0
  180. package/scripts/lib/file-lock.mjs +22 -4
  181. package/scripts/lib/gates/gate-full.mjs +84 -11
  182. package/scripts/lib/gates/gate-helpers.mjs +93 -21
  183. package/scripts/lib/git-config-drift.mjs +134 -5
  184. package/scripts/lib/host-identity.mjs +247 -2
  185. package/scripts/lib/instruction-budget-guard.mjs +31 -1
  186. package/scripts/lib/io.mjs +239 -0
  187. package/scripts/lib/issue-budget.mjs +284 -31
  188. package/scripts/lib/learnings/io.mjs +55 -10
  189. package/scripts/lib/learnings/schema.mjs +95 -28
  190. package/scripts/lib/lock-reaper.mjs +7 -1
  191. package/scripts/lib/locks/staging-fence-lock.mjs +5 -1
  192. package/scripts/lib/locks/state-md-lock.mjs +8 -1
  193. package/scripts/lib/memory-banner.mjs +5 -2
  194. package/scripts/lib/memory-paths.mjs +15 -6
  195. package/scripts/lib/mode-selector/scoring.mjs +53 -6
  196. package/scripts/lib/owner-interview.mjs +78 -32
  197. package/scripts/lib/peer-discovery.mjs +73 -22
  198. package/scripts/lib/platform.mjs +72 -9
  199. package/scripts/lib/plugin-root.mjs +143 -19
  200. package/scripts/lib/project-hygiene.mjs +104 -4
  201. package/scripts/lib/quality-gate.mjs +271 -13
  202. package/scripts/lib/reconcile/emitter.mjs +87 -19
  203. package/scripts/lib/reconcile/engine.mjs +281 -13
  204. package/scripts/lib/reconcile/idempotency.mjs +102 -1
  205. package/scripts/lib/reconcile/renderer.mjs +165 -7
  206. package/scripts/lib/reconcile/sanitize.mjs +40 -17
  207. package/scripts/lib/reconcile/writer.mjs +415 -84
  208. package/scripts/lib/resource-probe/evaluate.mjs +330 -149
  209. package/scripts/lib/resource-probe/probe-platform.mjs +35 -0
  210. package/scripts/lib/resource-probe.mjs +18 -2
  211. package/scripts/lib/rule-loader.mjs +37 -2
  212. package/scripts/lib/rules-sync.mjs +51 -8
  213. package/scripts/lib/scope-gate.mjs +90 -0
  214. package/scripts/lib/session-close-backfill.mjs +369 -28
  215. package/scripts/lib/session-discovery.mjs +13 -3
  216. package/scripts/lib/session-end/phase-skip.mjs +37 -4
  217. package/scripts/lib/session-end/worktree-cleanup.mjs +154 -7
  218. package/scripts/lib/session-id.mjs +30 -14
  219. package/scripts/lib/session-identity/own-session.mjs +159 -0
  220. package/scripts/lib/session-lock.mjs +85 -30
  221. package/scripts/lib/session-schema/normalizer.mjs +70 -3
  222. package/scripts/lib/session-schema/validator.mjs +40 -0
  223. package/scripts/lib/session-start-probes.mjs +608 -0
  224. package/scripts/lib/session-transition.mjs +277 -0
  225. package/scripts/lib/sessions-staleness-banner.mjs +124 -57
  226. package/scripts/lib/spiral-carryover.mjs +111 -9
  227. package/scripts/lib/state-md/frontmatter-mutators.mjs +41 -8
  228. package/scripts/lib/state-md/mission-status.mjs +467 -72
  229. package/scripts/lib/state-md/yaml-parser.mjs +145 -16
  230. package/scripts/lib/state-md.mjs +12 -2
  231. package/scripts/lib/telemetry/sync.mjs +46 -8
  232. package/scripts/lib/validate/check-agents.mjs +66 -0
  233. package/scripts/lib/validate/check-auq-clarity.mjs +274 -0
  234. package/scripts/lib/validate/check-cursor-adapter.mjs +102 -0
  235. package/scripts/lib/validate/check-dead-bridge.mjs +24 -2
  236. package/scripts/lib/validate/check-doc-cli-commands.mjs +16 -32
  237. package/scripts/lib/validate/check-hooks-symmetry.mjs +59 -63
  238. package/scripts/lib/validate/check-playwright-mcp-canary.mjs +13 -22
  239. package/scripts/lib/validate/check-plugin-monitors.mjs +10 -4
  240. package/scripts/lib/validate/check-rules.mjs +153 -9
  241. package/scripts/lib/validate/check-test-value-bans.mjs +165 -17
  242. package/scripts/lib/validate/check-unwired-features.mjs +340 -32
  243. package/scripts/lib/validate/repo-files.mjs +275 -0
  244. package/scripts/lib/validate-vendored-rules.mjs +229 -7
  245. package/scripts/lib/vault-backfill/glab.mjs +91 -58
  246. package/scripts/lib/vault-backfill/manifest.mjs +28 -8
  247. package/scripts/lib/vault-mirror/process.mjs +99 -43
  248. package/scripts/lib/vault-mirror/telemetry.mjs +210 -0
  249. package/scripts/lib/vault-staleness-banner.mjs +76 -6
  250. package/scripts/lib/vault-status/board-writer.mjs +211 -10
  251. package/scripts/lib/vault-status/narrative-mirror.mjs +188 -8
  252. package/scripts/lib/vcs-repo-spec.mjs +182 -13
  253. package/scripts/lib/wave-executor/foreign-dispatch.mjs +832 -0
  254. package/scripts/lib/wave-resource-gate.mjs +67 -73
  255. package/scripts/lib/wave-transcript-tail.mjs +869 -0
  256. package/scripts/materialize-wave-scope.mjs +478 -0
  257. package/scripts/mcp-server.sh +11 -2
  258. package/scripts/parse-config.mjs +65 -0
  259. package/scripts/release.mjs +443 -122
  260. package/scripts/run-quality-gate.mjs +14 -0
  261. package/scripts/token-audit.sh +9 -2
  262. package/scripts/validate-plugin.mjs +6 -0
  263. package/scripts/validate-wave-scope.mjs +73 -1
  264. package/scripts/vault-backfill.mjs +32 -5
  265. package/scripts/vault-mirror.mjs +203 -34
  266. package/skills/_shared/monitor-patterns.md +31 -5
  267. package/skills/_shared/parallel-aware-auq.md +31 -25
  268. package/skills/_shared/parallel-aware-preamble.md +35 -4
  269. package/skills/_shared/platform-tools.md +11 -5
  270. package/skills/_shared/state-ownership.md +61 -8
  271. package/skills/autopilot/SKILL.md +5 -1
  272. package/skills/bootstrap/SKILL.md +5 -4
  273. package/skills/bootstrap/_shared-template.md +18 -10
  274. package/skills/bootstrap/deep-template.md +10 -6
  275. package/skills/bootstrap/fast-template.md +15 -8
  276. package/skills/bootstrap/standard-template.md +10 -6
  277. package/skills/brainstorm/SKILL.md +18 -18
  278. package/skills/brainstorm/soul.md +12 -0
  279. package/skills/claude-md-drift-check/checker.mjs +39 -11
  280. package/skills/discovery/SKILL.md +28 -24
  281. package/skills/dispatcher/SKILL.md +1 -1
  282. package/skills/eli5/SKILL.md +43 -0
  283. package/skills/evolve/SKILL.md +8 -9
  284. package/skills/gitlab-ops/SKILL.md +30 -26
  285. package/skills/grill/SKILL.md +6 -6
  286. package/skills/grill/soul.md +16 -0
  287. package/skills/journey-audit/SKILL.md +269 -0
  288. package/skills/memory-cleanup/SKILL.md +2 -2
  289. package/skills/npm-publish/SKILL.md +4 -4
  290. package/skills/peekaboo-driver/SKILL.md +18 -6
  291. package/skills/persona-panel/SKILL.md +1 -1
  292. package/skills/plan/SKILL.md +18 -16
  293. package/skills/plan/mode-feature.md +1 -1
  294. package/skills/plan/mode-new.md +35 -23
  295. package/skills/plan/soul.md +12 -0
  296. package/skills/reconcile/SKILL.md +44 -4
  297. package/skills/session-end/SKILL.md +70 -24
  298. package/skills/session-end/metrics-collection.md +7 -4
  299. package/skills/session-end/phase-3-6-tail.md +48 -5
  300. package/skills/session-end/phase-3-7a-recommendations.md +16 -2
  301. package/skills/session-plan/SKILL.md +6 -1
  302. package/skills/session-plan/wave-template.md +1 -0
  303. package/skills/session-start/SKILL.md +96 -48
  304. package/skills/session-start/phase-2-5-docs-planning.md +8 -8
  305. package/skills/session-start/phase-4-5-resource-health.md +82 -19
  306. package/skills/session-start/phase-7-5-mode-selector.md +15 -3
  307. package/skills/session-start/phase-8-5-express-path.md +77 -12
  308. package/skills/session-start/soul.md +110 -0
  309. package/skills/test-runner/SKILL.md +2 -2
  310. package/skills/using-orchestrator/SKILL.md +1 -1
  311. package/skills/vault-sync/validator.mjs +31 -0
  312. package/skills/wave-executor/SKILL.md +4 -2
  313. package/skills/wave-executor/circuit-breaker.md +34 -9
  314. package/skills/wave-executor/wave-loop.md +129 -24
  315. package/skills/write-executable-plan/SKILL.md +6 -6
  316. package/templates/_shared/journey-manifest.md +110 -0
  317. package/scripts/tests/fixtures/fetch-baseline/sample-rule.md +0 -8
  318. package/skills/vault-sync/tests/fixtures/archive-test-vault/90-archive/bad-archived.md +0 -8
  319. package/skills/vault-sync/tests/fixtures/archive-test-vault/_meta/.gitkeep +0 -0
  320. package/skills/vault-sync/tests/fixtures/archive-test-vault/live-note.md +0 -8
  321. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/_meta/.gitkeep +0 -0
  322. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/bad-type.md +0 -8
  323. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/good-note.md +0 -8
  324. package/skills/vault-sync/tests/fixtures/clean-vault/.obsidian/config.md +0 -8
  325. package/skills/vault-sync/tests/fixtures/clean-vault/01-projects/foo/projects-baseline.md +0 -10
  326. package/skills/vault-sync/tests/fixtures/clean-vault/03-daily/daily-2026-04-13.md +0 -8
  327. package/skills/vault-sync/tests/fixtures/clean-vault/README.md +0 -3
  328. package/skills/vault-sync/tests/fixtures/clean-vault/hello-world.md +0 -11
  329. package/skills/vault-sync/tests/fixtures/dangling-link-vault/_meta/.gitkeep +0 -0
  330. package/skills/vault-sync/tests/fixtures/dangling-link-vault/has-dangling.md +0 -9
  331. package/skills/vault-sync/tests/fixtures/dangling-link-vault/real-target.md +0 -8
  332. package/skills/vault-sync/tests/fixtures/empty-vault/_meta/.gitkeep +0 -0
  333. package/skills/vault-sync/tests/fixtures/missing-field-vault/_meta/.gitkeep +0 -0
  334. package/skills/vault-sync/tests/fixtures/missing-field-vault/missing-id.md +0 -7
  335. package/skills/vault-sync/tests/fixtures/nested-tag-vault/03-daily/daily-2026-04-13.md +0 -9
  336. package/skills/vault-sync/tests/fixtures/nested-tag-vault/_meta/.gitkeep +0 -0
  337. package/skills/vault-sync/tests/fixtures/nested-tag-vault/nested-tags-note.md +0 -11
  338. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/README.md +0 -3
  339. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_MOC.md +0 -3
  340. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_meta/.gitkeep +0 -0
  341. package/skills/vault-sync/tests/fixtures/with-moc-vault/_MOC.md +0 -11
  342. package/skills/vault-sync/tests/fixtures/with-moc-vault/_meta/.gitkeep +0 -0
  343. package/skills/vault-sync/tests/fixtures/with-moc-vault/hello-world.md +0 -11
  344. package/skills/vault-sync/tests/schema-drift.test.mjs +0 -133
  345. package/templates/_shared/rules/parallel-sessions.md +0 -77
package/CHANGELOG.md CHANGED
@@ -7,6 +7,275 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.23.0] - 2026-08-28
11
+
12
+ Two commits today (1 `feat`, 1 `fix`; 64 files, +4,971/−184) close Waves 3 and 4 of the
13
+ resumed session, plus eight items carried forward from Wave 2 (`36aa605`, 2026-08-26,
14
+ never previously changelogged). No `BREAKING CHANGE:` footer and no `!` subject. The
15
+ pattern repeats across both waves: a guard, sanitizer, or census that already existed but
16
+ checked the wrong population or stopped short of the surface it needed to reach — a parity
17
+ guard sampling five rule files by name instead of reading the directory, a sanitizer whose
18
+ findings never reached stderr, a byte-count drifting 338 lines from the line it cited, a
19
+ tracked directory hiding an untracked hook beside it.
20
+
21
+ One `feat` commit (session-2, `30940cb`, 2026-08-28; 39 files, +2,475/−405) closes Wave 2
22
+ with three GitHub-mirror fixes and a session-identity cluster at the process boundary. No
23
+ `BREAKING CHANGE:` footer and no `!` subject. The through-line: identifiers the platforms
24
+ mint (UUIDv7, semantic session ids) were rejected or dropped by readers built for UUIDv4
25
+ only — every resume looked foreign — and call sites that needed a repo root passed
26
+ `undefined` instead, so fail-open paths ran on every invocation.
27
+
28
+ ### Added
29
+
30
+ - **Eight core rules ship as sanitized copies, with a report-only leak scanner (#1098).**
31
+ `rules/always-on/` holds sanitized copies of `ask-via-tool`, `build-value`,
32
+ `loop-and-monitor` and five more; `scanVendoringLeaks()` now reaches stderr as one line
33
+ per finding in both CLIs, folded into `validate-vendored-rules` with a rule-ID census.
34
+ - **Session Config fails loud on an unparsable line (#1097).** `collectUnparsableLines`
35
+ gates warn/strict via one `htmlCommentSkipper` shared by extractor and classifier — a
36
+ commented-out `enforcement: strict` had been reading as live config.
37
+ - **A read-only protection-audit CLI, with a runbook naming the order (#1079).** States
38
+ the required sequence; never flips a setting itself.
39
+ - **The scope guard now emits `orchestrator.wave_dispatch.scope_checked` (#1092).** Closes
40
+ the ledger half that never recorded a signal-free ALLOW.
41
+ - **`/journey-audit` — a user-facing product audit as a repeatable skill (#1161).** Skill,
42
+ command and manifest template; skill/command counts measured at 48/28.
43
+ - **A Cursor `.mdc` parity guard that reads the directory, not a fixed list (#1093).**
44
+ Catches bare `PID=`/`${VAR}` IDs a name-sampling guard had missed; `priority::` swept
45
+ across all 5 files.
46
+ - **The old root now formally leaves before the new one claims it, wired at all four
47
+ promotion sites (#1069).** `scripts/lib/session-transition.mjs` → `leaveSourceRoot()`:
48
+ `deregisterSelf()` → lock-release (reusing `on-session-end`'s ownership rules) →
49
+ `orchestrator.session.root_left` (carries `source_root_hash`/`source_root_basename`,
50
+ never an absolute path — the payload also travels over the optional webhook). Review
51
+ found the Phase-1.2.1 promotion site had been missing the call; it is now wired at
52
+ session-start Phase 0.5, Phase 1.2.1, and both `parallel-aware-*` docs. A real
53
+ `git worktree` two-root integration test goes phantom-peer red → green.
54
+
55
+ ### Fixed
56
+
57
+ - **Six onboarding contradictions + a `cursor-install` TARGET guard (#1078).** First
58
+ production diff authored by a foreign model (composer-2.5) under mandatory Claude review.
59
+ - **Amber is now a documented normal state (#1062).** `docs/ci-setup.md` names it instead
60
+ of leaving it an unexplained CI color.
61
+ - **A tracked directory no longer hides an untracked hook beside it (#1158).**
62
+ `hooksPathIsTracked` now requires a GIT-tracked file directly under `core.hooksPath`.
63
+ - **`probe-stale` collapses to one vocabulary term (#1159).** A record older than 7 days
64
+ is `probe-stale`, severity `warn`, never a live finding; the registry remap is gone.
65
+ - **The scope-cap saw operators, not shell keywords (#1145).** `splitSegments` now splits
66
+ on keywords too, so `for t in a b c; do glab issue create; done` no longer slips a
67
+ compound-statement head past the cap.
68
+ - **A missing `.claude/rules/` was misdiagnosed as a loop (#1132).** `err.code` now
69
+ separates silent `ENOENT`/`ENOTDIR` from loud `EACCES`; the repeat was caller fan-out.
70
+ - **Two probes measured the wrong population (#1143/#1148).** One counted a whole file and
71
+ cited a line that had already drifted 338 lines from the finding; both scanners read the
72
+ filesystem instead of the git index, censoring 5 gitignored files as documentation.
73
+ - **Generated rules now self-verify offline (#1101).** Each carries a sha256 seal over its
74
+ own Evidence block instead of a learning-key into a gitignored file; 23 rules sealed,
75
+ fresh-clone warnings 23 → 0.
76
+ - **`reconcile.targets` had zero consumers (#1099).** Now wired through with a closed enum,
77
+ visible rejection of unknowns, and per-target path confinement.
78
+ - **Orphaned wave-scope files survived re-materialization (#1103).** Reconciled by
79
+ ownership proof now, never a blind directory wipe — two parallel sessions can share one
80
+ wave-N directory (PSA-003).
81
+ - **Two rival vendoring paths wrote the same rule file (#1060).** `rules/` is now sole SSOT
82
+ for PSA-001..007; `templates/_shared/rules/` is deleted.
83
+ - **`parseSessionId` accepted only UUIDv4; Codex mints v7 (#66/#1091).**
84
+ `scripts/lib/session-id.mjs` now accepts RFC-9562 v1–8 (`UUID_RE`, additive `version`
85
+ field — see `### Removed` below for the alias this superseded). Every SessionStart had
86
+ minted a fresh v4; a
87
+ resumed/compacted thread read its own lock as a foreign session. `hooks/on-stop.mjs` and
88
+ `hooks/on-session-end.mjs` now apply the writer's acceptance rule, closing a lock-leak via
89
+ non-UUID stdin ids.
90
+ - **phase-3-7a called `updateFrontmatterFieldsOnDisk(undefined, …)` (#65/#1036).**
91
+ `skills/session-end/phase-3-7a-recommendations.md` requires a repo root; every `/close`
92
+ took the fail-open path — 0 of 5 recommendation fields were ever written. The snippet now
93
+ binds `repoRoot` via `git rev-parse --show-toplevel`; the catch logs the cause.
94
+ - **Codex MCP launch resolved to `/scripts/mcp-server.sh` from non-git cwd (#64).** Codex
95
+ copies a marketplace plugin to
96
+ `~/.codex/plugins/cache/<marketplace>/session-orchestrator/<version>/` and starts the MCP
97
+ child with no plugin-root env var. `.mcp.json` and `scripts/lib/plugin-root.mjs` gained a
98
+ plugin-cache scan tier (name-matched `package.json`, newest by mtime). Codex snapshots
99
+ `.mcp.json` at install time — existing installs need a reinstall.
100
+ - **`scoring.mjs` read a flat `completion_rate` 0 of 281 records carry (#1071).** The value
101
+ lives under `effectiveness`, so the high-completion bonus was unreachable.
102
+ `resolveMemoryDir`/`buildLiveSignals` now take an explicit `repoRoot` instead of
103
+ `process.cwd()`.
104
+ - **mission-status recovery aborted on the first non-canonical body line (#1104).**
105
+ `scripts/lib/state-md/mission-status.mjs` now skips per line, reports skipped lines
106
+ (`recoverFrontmatterMissionStatusDetailed`). `setMissionStatus` refuses ids outside the
107
+ grammar with a stderr WARN from the on-disk wrapper.
108
+ - **`enterWorktree` failed with `already used by worktree` when the source branch was
109
+ checked out (#1067).** `scripts/lib/autopilot/worktree-pipeline.mjs` now creates
110
+ `so/<sessionId>` from that branch and returns `branch`/`promotedFrom`.
111
+ - **Phase 4a auto-promoted-worktree cleanup was dead under the #1069 process boundary.**
112
+ Since the promoted worktree runs as a brand-new session with its own id,
113
+ `detectAutoPromotedWorktree()`'s basename match against the CURRENT session id could
114
+ never fire post-#1069. `enterWorktree()` now writes `.orchestrator/promoted-from.json`
115
+ (source-root hash + basename, source session id, branch) at creation time;
116
+ `detectAutoPromotedWorktree()` tries this marker FIRST (`source: 'marker'`), falling back
117
+ to the legacy basename match (`source: 'basename'`) for pre-marker worktrees.
118
+ `isWorktreeClean()` discounts exactly the marker's own untracked line so the marker never
119
+ reads as dirty by itself. Re-promoting onto an existing `so/<sessionId>` branch now reuses
120
+ it (`reusedBranch: true`) or reports a typed refusal, instead of failing outright. See
121
+ ADR-0013.
122
+ - **`.mcp.json`'s bash bootstrap had silently drifted from `resolvePluginRoot()`'s tier
123
+ order.** The shell mirror now matches the same five env tiers in the same order, tests
124
+ `package.json`'s `name` field via `node -e JSON.parse(...)` instead of a substring `grep`
125
+ (which had matched `session-orchestrator-fork`), and ties the newest-by-mtime cache scan
126
+ to the same strict `-nt` comparison as the JS side. Two drift tests pin JS and shell
127
+ staying in sync.
128
+ - **`ci-status-banner.mjs` escaped control bytes in the JSON preview but not in the
129
+ parse-error message.** `JSON.stringify()` alone is not enough — V8 quotes the raw
130
+ offending input inside `SyntaxError.message`, carrying control bytes straight to the
131
+ terminal. `escapeControlBytes()` now covers both the preview AND `err.message`;
132
+ `parseCliJson()` also gained a shape-gate against `null`/`[]`/a bare `"ok"` string, all of
133
+ which parse as valid JSON but are not the object/array shape callers expect.
134
+ - **A refused mission-status write warned on only 1 of 5 call paths.**
135
+ `setMissionStatusDetailed()` now reports the refusal reason (e.g. `id-grammar`) to every
136
+ caller, and the on-disk wrapper emits the stderr WARN on all 5 paths instead of the one it
137
+ happened to cover before.
138
+ - **`check-unwired-features` exempted itself from its own edge census via its allowlist
139
+ string, hiding a real orphan behind it.** The `SELF_REL` self-reference correctly
140
+ contributes zero edges by design, but the same code path was masking that
141
+ `scripts/lib/webhook-url.mjs` has zero callers repo-wide — genuinely unreachable, not a
142
+ false positive. Follow-up issue pending to wire it in or remove it.
143
+ - **Three load-sensitive tests hardened with margin instead of being disabled.**
144
+ `tests/scripts/validate-plugin.test.mjs`'s child-process timeout moved from 30s to 120s (a
145
+ killed child returns `status: null`, which had read as a different failure than a real
146
+ one) plus a matching `hookTimeout` bump, and two further spawn-timeout assertions gained
147
+ the same discriminating margin between contention and a genuine failure.
148
+
149
+ ### Changed
150
+
151
+ - **Host-registry census counts `semantic_session_id` (#1066).** `hooks/on-session-start.mjs`
152
+ falls back to `session_id` only when it is itself semantic. Before, only UUIDs were
153
+ projected — the n-increment discards them — so the registry contributed nothing to
154
+ numbering.
155
+ - **Session end events carry `semantic_session_id`; backfill event + supersede (#1068).**
156
+ `orchestrator.session.ended` / `.stopped` carry `semantic_session_id` (omitted when
157
+ unknown). A new `orchestrator.session.backfill_completed` event records each backfill outcome. A
158
+ completed record may now supersede an `abandoned` stub (append-only, `supersedes` marker).
159
+ Readers preferring the newest record are a follow-up.
160
+ - **`.semgrep.yml` regains two taint-mode rules (#1129).** `json-parse-untrusted-input` and
161
+ `prototype-pollution-object-assign` aimed at this repo's real trust boundary (hook stdin,
162
+ child-process stdout); 27 rules total. `unsafe-llm-output-rendering` stays excluded with a
163
+ measured reason (no DOM code).
164
+
165
+ ### Removed
166
+
167
+ - **`UUID_V4_RE` removed** from `scripts/lib/session-id.mjs` — deprecated alias of
168
+ `UUID_RE` with zero importers repo-wide (measured @ 7daa3d2; hits in
169
+ `tests/telemetry/anon-id.test.mjs` and `server/ingest/validate.mjs` are unrelated local
170
+ constants of the same name). Use `UUID_RE`, any RFC 9562 version 1–8.
171
+
172
+ ### Notes
173
+
174
+ Two of this session's diffs were authored by foreign models under the #1150 adapter —
175
+ #1078 by composer-2.5, #1093 by grok-4.6 — each passing mandatory Claude review before
176
+ landing. First production use of the foreign-dispatch path.
177
+
178
+ ## [3.22.0] - 2026-08-22
179
+
180
+ Twenty commits (12 `fix`, 5 `docs`, 2 `feat`, 1 `chore`; 150 files, +17,312/−2,575), no
181
+ `BREAKING CHANGE:` footer and no `!` subject. One strand runs through all of it:
182
+ **an instrument that reported confidently and measured the wrong quantity.** Not a
183
+ threshold set too tight, not a rule too strict — the wrong quantity, reported with the
184
+ same certainty as the right one. The host-resource warning fired on **99.0% of 1,477
185
+ measured session starts** and nobody could falsify it, because the two fields it was
186
+ computed from were never persisted. A hygiene probe announced "37 files (11 MB)" while
187
+ sizing the entire directory instead of the 37 — factor ~18 — and proposed deleting
188
+ version-controlled source files, because it never asked git. And the questions this tool
189
+ puts to its operator had never been measured at all: **21 of 72 passed** on first
190
+ measurement, and the single dominant cause was a 12-codepoint header limit that silently
191
+ truncated 30 of them.
192
+
193
+ ### Added
194
+
195
+ - **The operator's questions are now measured before he reads them (#1107).** `scripts/auq-audit.mjs`
196
+ scores every `AskUserQuestion` block and every prose fallback list against eight criteria
197
+ (K1–K8) plus two hard hurdles, all thresholds sourced from one registry — no hard-coded
198
+ number in the scorer. The census found **three populations, not one**: 40 Claude Code blocks,
199
+ 10 Codex prose lists, and 17 that every prior count had missed (9 `.cursor/rules/*.mdc` with
200
+ 10 choice blocks, plus 6 runtime questions inside `.mjs`). Baseline **21 of 72 (29%)**, after
201
+ the pass **72 of 72**. The dominant cause was structural: `header` caps at 12 codepoints and
202
+ the tool truncates silently — **26 of 42 headers exceeded it**, and one NFD-composed header
203
+ measured 12 visible characters as 14, destroying the question. Population A — the operator's
204
+ own path — ran 62% failing against 0% for the Codex and Cursor forms, which carry no header
205
+ at all.
206
+ - **A guard on the guard (#1122 groundwork).** The `AskUserQuestion` PreToolUse hook denies only
207
+ the two hard hurdles and reports the rest to stderr; `check-auq-clarity` is wired into
208
+ `validate-plugin` and blocks on H1/H2 with a measured 0% false-positive rate. Its own wiring is
209
+ proven by fake regression, not asserted.
210
+ - **`/eli5`** — say the last answer again in plain words, same facts, in the order the operator
211
+ needs them.
212
+
213
+ ### Fixed
214
+
215
+ - **The warning that fired on 99.0% of all session starts (#1089).** Measured over **1,477
216
+ `orchestrator.session.started` events across 18 repos**: `ram_free_gb < 2` fired on 84.0%,
217
+ `claude_processes >= 5` on 93.6%, any of the three on **99.0%** — against 4,884 stop events
218
+ with zero OOM markers. Three independent measurement errors, no threshold among them.
219
+ (a) `os.freemem()` on Darwin reports only `Pages free` — median **0.4 GB** on hosts with
220
+ 24–128 GB — so memory is now judged on `memory_pressure_pct_free` and a better signal
221
+ *replaces* a worse one rather than suppressing it. (b) `concurrent-sessions-warn` is
222
+ denominated in sessions and was compared against a process count; measured ratio **6.0:1**.
223
+ Same threshold, right denominator: 93.6% → **4.2%**. (c) One noisy axis could cap a wave;
224
+ now two independent soft signals must agree. The verdict had reached `sessions.jsonl` for
225
+ **15 of 1,734 sessions (0.9%)**, which is why the false alarm survived four months while six
226
+ repos independently wrote it into their learnings store — one at confidence **1.0**.
227
+ Codified as `.claude/rules/host-resources.md` (HR-101..106).
228
+ - **A standing condition is not a second opinion (#1089 follow-up).** The first live run of the
229
+ rebuilt verdict returned `warn | cap 2 | soft: ["cpu","zombies"]`. Zombie processes are idle
230
+ by definition — they cannot cause the load they are paired with — and are always present
231
+ (6, 13 and 9 in three readings minutes apart). They report; they never count toward the
232
+ two-signal rule.
233
+ - **A probe that sized the wrong set and never asked git.** `checkStaleArtifacts` computed its
234
+ byte figure over the whole of `.orchestrator/` instead of the aged subset it names —
235
+ the 37 files weighed **0.68 MB against 11 MB reported**. Independently, it consulted git
236
+ nowhere and therefore proposed pruning seven tracked, runtime-read source files, among them
237
+ the policy file `pre-bash-templates-first.mjs` reads and the two steering documents
238
+ session-start loads. The git exclusion is fail-**silent**, not fail-open: falling back to
239
+ "nothing is tracked" *is* the defect it closes.
240
+ - **Only the raw session ID releases a lock (#1085).** One session carried three identities —
241
+ STATE.md said `session-2`, the lock said `session-3`, issue-budget counted against a third
242
+ UUID — and `findPeers` reported the session's own presence as a foreign peer. The semantic
243
+ ID is now attribution metadata only; a release requires exact raw-ID equality, and a
244
+ semantic hint resolves to a raw ID only against a verified local binding. The companion fix
245
+ to issue-budget removed a data-loss path in which an identity-less invocation wrote its
246
+ fresh state into the shared counter and erased a live session's parked overflow.
247
+ - **The npm receipt is the boundary — and a `throw` lay behind it (#1088).** `publish()` threw
248
+ *after* a successful `npm publish`, during a 12-second registry-propagation poll: published,
249
+ not tagged, not pushed, reported as "failed, retryable". Propagation now returns a typed
250
+ outcome, each post-receipt step gets exactly one attempt, and everything else is collected as
251
+ `post-publish-reconciliation`. Leak detection decides on an extracted path rather than a regex
252
+ over `npm notice` prose (`contest` ≠ `tests`), and `ensureGithubRelease` became tri-state so
253
+ an auth or network answer no longer reads as "no release exists".
254
+ - **`--silent` leaked into the children, and the gate discarded its own diagnosis (a4f93cf).**
255
+ - **The empty sidecar path skipped the collision gate with exit 0 (#1083).** A coordinator that
256
+ wrote only the aggregate form of the two-shape scope declaration ran **six waves and ~27
257
+ dispatches with zero `FILE-SCOPE` injection** — and the absence looked identical to a clean
258
+ run. `scripts/materialize-wave-scope.mjs` is now the canonical writer of both shapes.
259
+ - **The GitLab target comes from the explicit path (#1065).** `glab repo view --output json`
260
+ materialised a full project response to read one field; on 2026-08-17 that response carried a
261
+ runner registration credential into a tool transcript. Project identity is now
262
+ `(host, URL-encoded namespace/project)` with traversal and double-encoding rejection, and the
263
+ same minimisation reached the vault-backfill path.
264
+ - **The restore froze after its first run (#state-md).** Also: a `gitleaks` allowlist that grew
265
+ by one proper name per incident now matches on a word boundary instead.
266
+ - **Four count claims where the checker could only see two (#docs-parity).** `docs/components.md`
267
+ claimed 46 skills and 26 commands against 47 and 27 on disk. The drift checker reported two —
268
+ its patterns are `^##`-anchored — while a census of the same two surfaces in the same file
269
+ found four; the two inside the Mermaid diagram were already self-contradictory before the fix.
270
+
271
+ ### Notes
272
+
273
+ `.claude/rules/host-resources.md` is new and always-on. `.claude/rules/bash-harness-pitfalls.md`
274
+ gained no rule text this line, but two measurement traps were recorded against it in the
275
+ learnings store: `rg -rn` is not `grep -rn` (`-r` is `--replace` and silently substitutes every
276
+ match), and zsh does not word-split an unquoted variable, so a multi-path `git log -- $paths`
277
+ reports zero matches with exit 0 — both produce a plausible wrong number without erroring.
278
+
10
279
  ## [3.21.0] - 2026-08-19
11
280
 
12
281
  Twenty-one commits (12 `fix`, 4 `feat`, 4 `docs`, 1 `chore`; 209 files, +28,906/−2,893), no
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Session Orchestrator
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
- [![Version](https://img.shields.io/badge/version-3.21.0-blue.svg)](CHANGELOG.md)
4
+ [![Version](https://img.shields.io/badge/version-3.23.0-blue.svg)](CHANGELOG.md)
5
5
  [![npm](https://img.shields.io/npm/v/session-orchestrator.svg)](https://www.npmjs.com/package/session-orchestrator)
6
6
  [![Tests](https://img.shields.io/badge/tests-12%2C000%2B-brightgreen.svg)](docs/telemetry/telemetry-claims.md)
7
7
 
@@ -52,6 +52,8 @@ That is the whole loop. `/plan` and `/evolve` extend it (see [Lifecycle](#lifecy
52
52
 
53
53
  ## Quick Start
54
54
 
55
+ Run `/bootstrap` in your project repo first — it writes `.orchestrator/bootstrap.lock`, which session-start requires before `/session` will run.
56
+
55
57
  Add a `## Session Config` section to your project's `CLAUDE.md` (Claude Code and Cursor IDE) or `AGENTS.md` (Codex CLI and Pi) — see [instruction-file-resolution](skills/_shared/instruction-file-resolution.md) for which file each platform reads. The smallest valid config is seven fields:
56
58
 
57
59
  ```yaml
@@ -70,8 +72,8 @@ Everything else is opt-in. See [`docs/session-config-template.md`](docs/session-
70
72
 
71
73
  ## What you get
72
74
 
73
- - **45 skills** for the session lifecycle (start, plan, execute, close, evolve), discovery, vault sync, MCP authoring, debugging, brainstorming, plan grilling, persona panels, cross-repo dispatch, learning→rule reconciliation, session-process eval, audits, and more
74
- - **24 slash commands** (`/session`, `/go`, `/close`, `/discovery`, `/plan`, `/grill`, `/evolve`, `/autopilot`, `/dispatcher`, `/reconcile`, `/eval`, `/test`, `/debug`, …)
75
+ - **48 skills** for the session lifecycle (start, plan, execute, close, evolve), discovery, vault sync, MCP authoring, debugging, brainstorming, plan grilling, persona panels, cross-repo dispatch, learning→rule reconciliation, session-process eval, audits, and more
76
+ - **28 slash commands** (`/session`, `/go`, `/close`, `/discovery`, `/plan`, `/grill`, `/evolve`, `/autopilot`, `/dispatcher`, `/reconcile`, `/eval`, `/test`, `/debug`, …)
75
77
  - **15 typed subagents** (code-implementer, test-writer, security-reviewer, session-reviewer, qa-strategist, architect-reviewer, …)
76
78
  - **10 hook event types** enforcing scope, blocking destructive commands, gating templates-first, capturing telemetry — full on Claude Code; experimental, post-hoc, or bridged on the other platforms ([Platform support](#platform-support))
77
79
  - **10,000+ vitest tests** run on every commit ([telemetry methodology](docs/telemetry/telemetry-claims.md))
@@ -127,22 +129,23 @@ The system is markdown-driven config plus a thin Node runtime — skills, comman
127
129
  - **Five typed waves, not one big batch.** Discovery first, so implementers start with shared context. Impl-Core before Impl-Polish, so architecture lands before integrations. Quality runs a *simplification pass* on AI-generated code **before** tests are written — otherwise tests pin the AI patterns into place.
128
130
  - **Inter-wave reviews, not just end-of-session.** Catching regressions between waves — not only at the end — stops a bad pattern from propagating into later work; the confidence floor filters speculative criticism so only high-signal findings reach you.
129
131
  - **State persists across crashes.** `STATE.md` records wave progress and deviations; the next `/session` offers to resume from the last completed wave.
130
- - **Hooks enforce, not just warn.** A pre-Bash guard blocks destructive shell commands, and pre-Edit scope enforcement blocks writes outside an agent's allowed paths — in main sessions and subagent waves alike (specifics in [Safety](#safety)). This hard enforcement is full on Claude Code; it degrades to experimental / post-hoc / bridged on Codex CLI, Cursor IDE, and Pi (see [Platform support](#platform-support)).
132
+ - **Hooks enforce, not just warn.** A pre-Bash guard blocks destructive shell commands, and pre-Edit scope enforcement blocks writes outside an agent's allowed paths — in main sessions and subagent waves alike (specifics in [Safety](#safety)). This hard enforcement is full on Claude Code; Cursor and Pi reach it through payload bridges; Codex is still pending a real `apply_patch` adapter (see [Platform support](#platform-support)).
131
133
  - **Cross-session learning is opt-in and inspectable.** Every session writes a record; after 5+ sessions `/evolve analyze` extracts confidence-scored patterns you can read and prune. Nothing is hidden.
132
134
  - **VCS dual support, no lock-in.** Auto-detects GitLab or GitHub from your remote and drives the full lifecycle for both.
133
135
 
134
- ## Recent highlights (v3.21.0)
136
+ ## Recent highlights (v3.23.0)
135
137
 
136
- Every release is additive and backward-compatible. Highlights of the v3.21.0 line:
138
+ Every release is additive and backward-compatible. Highlights of the v3.23.0 line: the first shaped by three external bug reports on the public mirror (Kanevry#64, #65, #66), all three reproduced, fixed and live-verified:
137
139
 
138
- - **The site that proves its own numbers (#1043–#1046)** the live page had served v3.19.0 against v3.20.0 in the repo for six days, all five legal paths were 404, and the `Measured` block the honesty argument of the whole page — carried five wrong numbers. It is now generated: `scripts/site-numbers.mjs` reads **13 metrics** from the repo into `data-metric` spans, and its very first run caught three real errors, one of them the coordinator's own (`skills: page says 47, repo says 46`) and one a contract defect that would have shipped `vv3.20.0` at the next release. Deploy config moved from a dashboard into a versioned `vercel.json`. Rendered height fell to **52.4%** of the old page (10,350 → 5,428px), and mobile navigation previously `display:none` with no hamburger — exists.
139
- - **The documented Claude Code install path was guaranteed broken** — `claude plugin dir` is not a subcommand; it exits 1, the fallback path does not exist, `cd` fails, `npm install` never runs, and every hook afterwards cannot find `zx`. Measured on Claude Code 2.1.235. That is the cause behind external issues #62/#63, whose reporters described the symptom and **all four issues opened by people outside this repo are install or environment failures, not one a feature request**. The replacement was extracted from the shipped HTML, entity-decoded and executed verbatim.
140
- - **The scope guard shipped the instructions for its own disarmament (#1057)** — the stale-manifest denial ended on ``remove it with `rm -f <path>` ``, and that string travels in `permissionDecisionReason` into the context of the agent just denied. `rm -f` is not blocked (14 rules, only `rm-rf-destructive` bites), and with the manifest gone both allowedPaths **and** project-root containment fall. A parallel session in the same working copy received this suggestion for the live manifest of this one, and declined on an indicator rather than on knowledge.
141
- - **Two dead instruments, found by measuring rather than reading** — the v2 vault renderer's branch condition was **structurally false from its first commit** and matched **0 of 253** session records; the obvious fix would have been worse than the bug, because `agents` is polymorphic (210× a number, 14× an array over 599 wave objects) and a naive `??` would have written `[object Object]` into the vault. And `scanBacklog` read 50 of 89 open issues while reporting the window nowhere: `critical 0, high 10, stale 0` where the truth was `1 / 18 / 5`.
142
- - **Cross-session messaging is wired (Epic #1048, waves 1–2)** — a new always-on rule with CSM-001..005, and a peer-inform branch hung **below** the sibling check in the PSA decision tree so it can mask neither that branch nor the PSA-002 pause. The moat was never "peer sessions cannot talk to each other" — they demonstrably can — it is that they share one working copy, and what crosses the channel is information, never isolation.
143
- - **Guards that were green without biting** the owner-leakage scanner did not read `.html` at all; admitting the class immediately found a live `U+00AD` breaking a word visibly on a legally required page. `harness-audit` category 6 awarded **2/2** outside a git repository. Six consecutive CI pipelines were red because a test depended on untracked ledger files: locally 23/23, on CI `23 tests | 23 skipped`. Each is now closed by a mechanism, and the review panel found further holes inside the fixes themselves including one fail-open state inside the fix that was closing fail-open.
140
+ - **Codex CLI mints UUIDv7 session ids; every reader accepted only v4 (#66 / #1091)** each SessionStart minted a fresh v4, so a resumed or compacted thread read its own lock as a foreign session. `parseSessionId` now accepts RFC 9562 versions 1–8 and the stop/end hooks apply the writer's rule, so one id owns the lock from start through release. The `UUID_V4_RE` alias is gone: zero importers, and a name that said v4 while matching v1–8.
141
+ - **Every `/close` wrote 0 of 5 recommendation fields (#65 / #1036)** — the documented Phase 3.7a call passed `undefined` where a repo root is required, and the fail-open catch hid it on every run. The snippet binds the root; the catch now names the cause. A second defect found while verifying the fix: backticks in a comment inside a `node -e "…"` string made bash execute `undefined` on each close.
142
+ - **Codex copies a marketplace plugin and starts the MCP child with no plugin-root variable (#64)** — measured: the copy lives under `~/.codex/plugins/cache/<marketplace>/session-orchestrator/<version>/`, and from a non-git cwd the launcher resolved to `/scripts/mcp-server.sh`. `.mcp.json` and `plugin-root.mjs` gained a cache-scan tier with a name-matched `package.json`, and `.mcp.json` now mirrors the module's tier order under two drift tests. Existing installs need a reinstall Codex snapshots `.mcp.json` at install time.
143
+ - **Worktree-Auto-Promotion is a process boundary, not a live migration (#1069, ADR-0013)** — the source session deregisters and releases its lock before the new worktree's session acquires (`leaveSourceRoot()`), which removes the phantom peer that stayed visible for up to 60 minutes. Because the new session's id never equals the worktree suffix, Phase 4a cleanup keys on a promotion marker written at creation time; the review panel found that key dead before any user did.
144
+ - **The host registry contributed nothing to session numbering (#1066)** — the census projected only raw UUIDs, which the n-increment discards. It now counts `semantic_session_id`, so two sessions on one host cannot mint the same label. The semantic id stays a best-effort label; ownership remains the raw id plus owner proof.
145
+ - **The mode selector scored a field no record carries (#1071)** `completion_rate` sits under `effectiveness` in all 281 ledger records; the flat read was always `undefined`, so the high-completion bonus was unreachable and the fixtures pinned a shape production never writes. Fixed with a nested-first read and a divisor test for the 99 records that carry no rate at all.
146
+ - **Semgrep regained two rules a path filter had dropped (#1129)** — re-aimed at this repo's real trust boundary (hook stdin, child-process stdout), taint-mode; the first true positives were three unguarded `JSON.parse` calls on `glab`/`gh` output in the CI banner. A proposed spread-sink was refused with a measurement: object spread cannot pollute a prototype.
144
147
 
145
- Previous line (v3.20.0): the memory pipeline 233 sessions of learnings that reached no agent (#1014), agent-authored text neutralised at the render point (#1015), and a learning store made durable after 11 of 13 provenance pointers resolved to nothing (#1017).
148
+ Previous line (v3.22.0): instruments that confidently measured the wrong quantity the 99%-firing resource warning, the AUQ audit, and the lock-release identity split.
146
149
 
147
150
  Full version history: [CHANGELOG.md](CHANGELOG.md).
148
151
 
@@ -165,10 +168,10 @@ The design goal is engineering quality: every wave exits verified, every unfinis
165
168
 
166
169
  | Feature | Claude Code | Codex CLI | Cursor IDE | Pi |
167
170
  |---|---|---|---|---|
168
- | All 24 commands | Native slash commands | Native plugin commands | Rules-based (.mdc) | Prompt templates |
171
+ | All 28 commands | Native slash commands | Native plugin commands | Native `.cursor/commands` slash commands | Prompt templates |
169
172
  | Parallel agents | Agent tool | Multi-agent roles | Sequential only | Sequential (parallel planned) |
170
173
  | Session persistence | `.claude/STATE.md` | `.codex/STATE.md` | `.cursor/STATE.md` | `.pi/STATE.md` |
171
- | Scope enforcement | PreToolUse hooks | Unavailable — pending a real `apply_patch` adapter | `afterFileEdit` (post-hoc) | `tool_call` bridge |
174
+ | Scope enforcement | PreToolUse hooks | Unavailable — pending a real `apply_patch` adapter | `preToolUse` + `beforeShellExecution` via cursor-hook-bridge; `afterFileEdit` post-hoc | `tool_call` bridge |
172
175
  | AskUserQuestion | Native tool | Numbered-list fallback | Numbered-list fallback | Numbered-list fallback |
173
176
  | Quality gates | Full | Full | Full | Full |
174
177
 
package/agents/AGENTS.md CHANGED
@@ -73,7 +73,7 @@ tools: Read, Grep, Glob, Bash # comma-separated string OR JSON array (bo
73
73
  **Body conventions** (from Anthropic's `plugins/plugin-dev/agents/*` reference set):
74
74
  - Sections: `**Your Core Responsibilities:**` → `**[X] Process:**` → `**Quality Standards:**` → `**Output Format:**` → `**Edge Cases:**`.
75
75
  - Length: 500–3000 words is the recommended range. Below 500 reads as under-specified; above 3000 reads as bloated.
76
- - Read-only reviewer agents: tools `Read, Grep, Glob, Bash` (no Edit/Write). Implementer agents: `Read, Edit, Write, Glob, Grep, Bash`.
76
+ - Read-only reviewer agents: tools `Read, Grep, Glob, Bash` (no Edit/Write). Implementer agents: `Read, Edit, Write, Glob, Grep, Bash`. Agents on the escalation allowlist append `SendMessage` to either baseline — see § Escalation Channel (#1051) for the six that do and why the rest do not.
77
77
 
78
78
  ## Model Selection & Cost Routing (#768)
79
79
 
@@ -95,6 +95,25 @@ Every agent definition with `repo-write` sandbox-tier (i.e. `Edit`/`Write` prese
95
95
 
96
96
  This is deliberately more explicit than a bare "Do NOT commit" — the git index and stash are SHARED resources across concurrently-dispatched sibling agents in the same wave, and `git stash`/`git add`/`git mv`/`git rm` are index-mutating even when scoped to the agent's own files. `docs-writer.md` had NO git-write restriction at all until #724 closed the gap (its `repo-write` siblings at least carried a bare "Do NOT commit" line) — when adding a new repo-write agent, copy the ban line verbatim rather than re-deriving a weaker phrasing so this gap does not recur. See `.claude/rules/parallel-sessions.md` § PSA-007 for the full rationale and fleet evidence.
97
97
 
98
+ ## Escalation Channel (#1051)
99
+
100
+ Six agents opt into `SendMessage` so a wave-blocking obstacle can reach the coordinator **while the wave is still running**, instead of surfacing only in the final report after the wave has ended. The allowlist is exactly:
101
+
102
+ `code-implementer` · `db-specialist` · `ui-developer` · `test-writer` · `docs-writer` · `session-reviewer`
103
+
104
+ **The Nicht-Liste is deliberate, not an oversight.** `analyst`, `qa-strategist`, `architect-reviewer`, `security-reviewer`, `ux-evaluator`, `eval-judge`, `skill-applied-judge` and `dialectic-deriver` do NOT get the tool. Their output is a judgment over a whole corpus — a finding at minute three is provisional, and the analysis is complete only at the end. An early message from one of them would carry an unfinished verdict the coordinator cannot act on without re-reading the final report anyway, so the channel would add interrupts without adding information. The six above are different: each one can hit a state where its *task* becomes unfulfillable (the file it must edit does not exist, the migration target is missing, the diff under review is absent) — an obstacle, not a verdict.
105
+
106
+ **The contract every escalation-enabled agent carries** (see `.claude/rules/cross-session-messaging.md` CSM-001/004/005):
107
+
108
+ - **One message, upward only.** Exactly ONE `SendMessage` to `main` per obstacle. Never to a sibling agent — agents send upward, they cannot discover sideways.
109
+ - **Never wait for a reply.** Silence is neither refusal nor consent (CSM-004); the agent keeps working in its scope or ends `blocked`.
110
+ - **Degrade silently.** Where `SendMessage` is unavailable (disabled telemetry, non-Anthropic provider, native Windows — CSM-005), the obstacle goes in the final report instead. No code path may assume delivery happened.
111
+ - **Payload:** agent role, declared file scope, the obstacle. The send is noted in the agent's own report so the operator can see the hand-off.
112
+
113
+ **Mandate for new agents** — same shape as the git-write ban convention above: when adding a repo-write agent that belongs on this allowlist, copy the escalation block verbatim from `code-implementer.md` (adjusting only the role name) rather than re-deriving a weaker phrasing. A paraphrase that drops "never wait for a reply" or "upward only" re-opens exactly the failure modes CSM-004 and CSM-001 exist to close.
114
+
115
+ `SendMessage` does NOT lift an agent out of `read-only`: it is in `READ_ONLY_TOOLS` (`scripts/lib/validate/tier-inference.mjs`, #1049), so `session-reviewer` keeps `sandbox-tier: read-only` and every `sandbox-tier` in this directory is unchanged by the opt-in.
116
+
98
117
  ## Color Allocation Strategy (#443)
99
118
 
100
119
  `color` is an **operator side-channel**, not a cosmetic field. In a `/tmux-layout` or multi-pane session, the per-agent color lets the operator tell co-running agents apart at a glance. With only a 9-color palette (`blue | cyan | green | yellow | purple | orange | pink | red | magenta`) and more than 9 agents in this directory, some colors are **deliberately shared** — but never carelessly.
@@ -124,12 +143,12 @@ Agents MAY declare their sandbox permission tier. Valid values:
124
143
 
125
144
  | Value | Meaning | Typical tools |
126
145
  |---|---|---|
127
- | `read-only` | observes only; no file writes, no network | `Read, Grep, Glob, Bash` |
128
- | `repo-write` | may create or modify files | `Read, Edit, Write, Glob, Grep, Bash` |
146
+ | `read-only` | observes only; no file writes, no network | `Read, Grep, Glob, Bash` (+ `Skill`, `SendMessage`, `ListAgents`) |
147
+ | `repo-write` | may create or modify files | `Read, Edit, Write, Glob, Grep, Bash` (+ `Skill`, `SendMessage`, `ListAgents`) |
129
148
  | `network-allowed` | may make outbound network calls (future) | — |
130
149
  | `dangerous` | may run destructive shell commands (future) | — |
131
150
 
132
- Inference rule (backward-compat): agents without `sandbox-tier:` infer their tier from tools — `Edit` or `Write` present → `repo-write`; only `Read/Grep/Glob/Bash/Skill` → `read-only`. The validator emits **WARN**, not FAIL, when the field is absent, so existing agents continue to work during migration. Bash appears in all tiers — fine-grained Bash control is handled by `hooks/pre-bash-destructive-guard.mjs`, not by tier.
151
+ Inference rule (backward-compat): agents without `sandbox-tier:` infer their tier from tools — `Edit` or `Write` present → `repo-write`; only `Read/Grep/Glob/Bash/Skill/SendMessage/ListAgents` → `read-only`. `SendMessage` and `ListAgents` are pure agent↔coordinator communication surfaces with no filesystem write path, so they do not lift an agent out of `read-only` (`scripts/lib/validate/tier-inference.mjs` `READ_ONLY_TOOLS`, #1049) — that is what lets `session-reviewer` opt into the escalation channel while staying `read-only`. The validator emits **WARN**, not FAIL, when the field is absent, so existing agents continue to work during migration. Bash appears in all tiers — fine-grained Bash control is handled by `hooks/pre-bash-destructive-guard.mjs`, not by tier.
133
152
 
134
153
  Example:
135
154
 
@@ -3,7 +3,7 @@ name: code-implementer
3
3
  description: 'Use this agent for feature implementation, API development, refactoring, and general code changes. Handles backend logic, API routes, service layers, and cross-cutting concerns. <example>Context: Wave plan assigns a new API endpoint implementation. user: "Implement CRUD API for invoices" assistant: "I''ll dispatch the code-implementer agent to build the invoice API endpoints." <commentary>Feature implementation with multiple files is the code-implementer''s core strength.</commentary></example> <example>Context: Refactoring task in an implementation wave. user: "Extract shared validation logic into a utility module" assistant: "I''ll use the code-implementer to extract and refactor the validation logic." <commentary>Cross-file refactoring requires systematic reading, extraction, and verification.</commentary></example>'
4
4
  model: inherit
5
5
  color: green
6
- tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*)
6
+ tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*), SendMessage
7
7
  sandbox-tier: repo-write
8
8
  output-schema: schemas/code-implementer.schema.json
9
9
  ---
@@ -37,6 +37,7 @@ You are a focused implementation agent. You write production code, refactor exis
37
37
  - Do NOT add standalone or narrative documentation (README, CLAUDE.md, guides), and never write docs for code that does not exist yet — those surfaces are owned by docs-writer. Inline code-surface docs ARE yours: comments where logic is non-obvious, plus JSDoc/TSDoc on public functions you author (per `.claude/rules/development.md` § Documentation).
38
38
  - Do NOT introduce new runtime dependencies without explicit instruction. If a new dependency seems necessary, pause and report rather than installing.
39
39
  - Do NOT run ANY git write operation (`git add`, `git commit`, `git stash`, `git mv`, `git rm`, `git push`, `git reset`) — the git index and stash are shared session resources (PSA-007); the coordinator handles ALL VCS operations.
40
+ - **Escalation channel (#1051, opt-in):** If you hit a WAVE-BLOCKING obstacle — one that makes your task unfulfillable, not a question you could answer by reading more code — send exactly ONE `SendMessage` to `main` carrying your agent role (`code-implementer`), your declared file scope, and the obstacle. Then keep working in your scope or end with `Status: blocked`. NEVER wait for a reply (CSM-004); never message a sibling agent (CSM-001 — upward only). Where `SendMessage` is unavailable, report the obstacle in your final report instead (CSM-005). Note the send in Blockers / Notes.
40
41
  - Do NOT touch unrelated files in the same directory just because they share a folder.
41
42
  - Before creating a NEW file, grep for existing files with a similar basename/purpose (`git ls-files | grep -i <basename>`) — if one exists, prefer extending it over creating a "cousin" duplicate (#730.3).
42
43
  - Do NOT use destructive operations (`rm -rf`, `git reset --hard`, `git clean`). Stick to Edit/Write — the git-write ban above (PSA-007) already covers `git reset`/`git clean`'s VCS-specific forms.
@@ -3,7 +3,7 @@ name: db-specialist
3
3
  description: 'Use this agent for database work — schema design, migrations, queries, indexes, and database functions. Handles SQL, ORMs, and database architecture decisions. <example>Context: New feature requires database schema changes. user: "Create the migration for the invoice tables with proper indexes" assistant: "I''ll dispatch the db-specialist agent to design the schema and create the migration." <commentary>Schema design requires understanding normalization, indexing, and the existing data model.</commentary></example> <example>Context: Performance issue with database queries. user: "Optimize the slow invoice listing query" assistant: "I''ll use the db-specialist to analyze and optimize the query with proper indexing." <commentary>Query optimization requires understanding execution plans, indexes, and data access patterns.</commentary></example>'
4
4
  model: inherit
5
5
  color: purple
6
- tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*)
6
+ tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*), SendMessage
7
7
  sandbox-tier: repo-write
8
8
  output-schema: schemas/db-specialist.schema.json
9
9
  ---
@@ -36,6 +36,7 @@ You are a focused database agent. You design schemas, write migrations, optimize
36
36
  - Do NOT modify application code — only database-related files (`migrations/`, `schema.sql`, `prisma/`, RPC function definitions).
37
37
  - Do NOT run `DROP TABLE`, `TRUNCATE`, or `DELETE` without explicit user instruction.
38
38
  - Do NOT run ANY git write operation (`git add`, `git commit`, `git stash`, `git mv`, `git rm`, `git push`, `git reset`) — the git index and stash are shared session resources (PSA-007); the coordinator handles ALL VCS operations.
39
+ - **Escalation channel (#1051, opt-in):** If you hit a WAVE-BLOCKING obstacle — one that makes your task unfulfillable, not a question you could answer by reading more code — send exactly ONE `SendMessage` to `main` carrying your agent role (`db-specialist`), your declared file scope, and the obstacle. Then keep working in your scope or end with `Status: blocked`. NEVER wait for a reply (CSM-004); never message a sibling agent (CSM-001 — upward only). Where `SendMessage` is unavailable, report the obstacle in your final report instead (CSM-005). Note the send in Blockers / Notes.
39
40
 
40
41
  ## Quality Standards
41
42
 
@@ -3,7 +3,7 @@ name: docs-writer
3
3
  description: 'Use this agent when documentation needs to be generated or updated as part of a session — user-facing READMEs, dev-focused CLAUDE.md sections, or vault narratives (context.md, decisions.md, people.md). <example>Context: a feature session added a new CLI flag. user: "Update the README with the new --no-vault flag." assistant: "I''ll dispatch the docs-writer agent to scan the diff and update README plus the Dev CLAUDE.md section if warranted." <commentary>Scope touches user-facing docs — docs-writer decides audience split and cites the diff.</commentary></example>'
4
4
  model: inherit
5
5
  color: cyan
6
- tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*)
6
+ tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*), SendMessage
7
7
  sandbox-tier: repo-write
8
8
  output-schema: schemas/docs-writer.schema.json
9
9
  ---
@@ -52,6 +52,8 @@ General rule: edit only files explicitly listed in the session scope passed at d
52
52
 
53
53
  Do NOT run ANY git write operation (`git add`, `git commit`, `git stash`, `git mv`, `git rm`, `git push`, `git reset`) — the git index and stash are shared session resources (PSA-007); the coordinator handles ALL VCS operations.
54
54
 
55
+ **Escalation channel (#1051, opt-in):** If you hit a WAVE-BLOCKING obstacle — one that makes your task unfulfillable, not a question you could answer by reading more code — send exactly ONE `SendMessage` to `main` carrying your agent role (`docs-writer`), your declared file scope, and the obstacle. Then keep working in your scope or end with `Status: blocked`. NEVER wait for a reply (CSM-004); never message a sibling agent (CSM-001 — upward only). Where `SendMessage` is unavailable, report the obstacle in your final report instead (CSM-005). Note the send in Blockers / Notes.
56
+
55
57
  ## Output Format
56
58
 
57
59
  Report back in this shape:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: eval-judge
3
- description: Use this agent during the /eval Skill Phase 3 (Epic #803, issue #810) to judge — from a session-eval record's dimension evidence, kpis, and session_id — the record's instruction-adherence and report-quality per rubric-v1.md's Judge Dimensions section. Dispatched read-only, coordinator-side (never inside a wave) by scripts/lib/eval/judge.mjs::runEvalJudge with a bounded per-call budget. RETURNS one fenced json block of two advisory judge dimensions (instruction-adherence, report-quality); the coordinator merges them via mergeJudgeDimensions() and appends the record via appendEvalRecord(). Read-only by contract — never writes files. Advisory-only and always uncalibrated — never blended into the deterministic tally or any global score. <example>Context: /eval Phase 3 with eval.judge: haiku. user "Judge whether this session-eval record shows instruction adherence and honest report quality." assistant "Dispatching eval-judge to read the record slice and emit advisory instruction-adherence/report-quality judgments." <commentary>The judge overlays a cheap advisory signal onto the five deterministic dimensions — never a global score, never a gate.</commentary></example>
3
+ description: "Use this agent during the /eval Skill Phase 3 (Epic #803, issue #810) to judge — from a session-eval record's dimension evidence, kpis, and session_id — the record's instruction-adherence and report-quality per rubric-v1.md's Judge Dimensions section. Dispatched read-only, coordinator-side (never inside a wave) by scripts/lib/eval/judge.mjs::runEvalJudge with a bounded per-call budget. RETURNS one fenced json block of two advisory judge dimensions (instruction-adherence, report-quality); the coordinator merges them via mergeJudgeDimensions() and appends the record via appendEvalRecord(). Read-only by contract — never writes files. Advisory-only and always uncalibrated — never blended into the deterministic tally or any global score. <example>Context: /eval Phase 3 with eval.judge: haiku. user \"Judge whether this session-eval record shows instruction adherence and honest report quality.\" assistant \"Dispatching eval-judge to read the record slice and emit advisory instruction-adherence/report-quality judgments.\" <commentary>The judge overlays a cheap advisory signal onto the five deterministic dimensions — never a global score, never a gate.</commentary></example>"
4
4
  model: haiku
5
5
  color: cyan
6
6
  tools: Read, Grep, Glob
@@ -135,8 +135,8 @@ and `{{options}}` at render time.
135
135
  ```
136
136
  AskUserQuestion({
137
137
  questions: [{
138
- header: "Memory — Confirm Proposals (Batch {{N}} of {{M}})",
139
- question: "Select the learnings you want to store permanently. Unselected proposals will be archived as declined.",
138
+ header: "Memory",
139
+ question: "Batch {{N}} of {{M}} — which learnings should be stored permanently? Unselected ones are archived as declined.",
140
140
  options: [
141
141
  // one entry per proposal in this batch — see label format below
142
142
  { label: "{{label}}", description: "{{description}}" },
@@ -147,12 +147,14 @@ AskUserQuestion({
147
147
  })
148
148
  ```
149
149
 
150
- **When there is only one batch** (`M === 1`), omit the batch suffix:
150
+ **When there is only one batch** (`M === 1`), omit the batch prefix from the question:
151
151
 
152
152
  ```
153
- header: "Memory Confirm Proposals"
153
+ question: "Which learnings should be stored permanently? Unselected ones are archived as declined."
154
154
  ```
155
155
 
156
+ `header` stays `"Memory"` in both cases: the field is cut off after 12 characters, so anything longer never reaches the operator.
157
+
156
158
  ### Option label format
157
159
 
158
160
  Locked by D3 (Wave 1 decision):
@@ -3,7 +3,7 @@ name: session-reviewer
3
3
  description: 'Use this agent between waves or at session end to verify work quality against the session plan. Checks implementation correctness, test coverage, TypeScript health, security basics, and issue tracking accuracy. <example>Context: Impl-Core wave is complete, coordinator needs quality check before Impl-Polish. user: "Impl-Core wave done, review before continuing" assistant: "I''ll dispatch the session-reviewer to verify Impl-Core outputs." <commentary>Inter-wave quality gate ensures issues are caught early, not at session end.</commentary></example> <example>Context: Session end, verifying all work before committing. user: "/close" assistant: "Running session-reviewer to verify all session work before committing." <commentary>Final quality gate before any code is committed.</commentary></example>'
4
4
  model: inherit
5
5
  color: pink
6
- tools: Read, Grep, Glob, Bash
6
+ tools: Read, Grep, Glob, Bash, SendMessage
7
7
  sandbox-tier: read-only
8
8
  output-schema: schemas/session-reviewer.schema.json
9
9
  ---
@@ -164,6 +164,12 @@ The same standard binds your own conduct: a defect in your OWN review process
164
164
 
165
165
  Evidence for both halves (2026-08-14 quality panel, 18 findings / 2 HIGH): each of the three reviewers refuted at least one coordinator claim. The architect's 10-entry CONFIRMED list and the QA strategist's 12-entry REFUTED list produced no findings at all, yet two REFUTED entries closed gaps the coordinator had explicitly suspected — re-work the next wave would otherwise have repeated. The security reviewer reproduced a HIGH that no test and no gate had surfaced (self-review and a green gate are not review), and disclosed a defect in his own probe with its full cleanup. A fix-agent refused a coordinator-specified `needleCount > 0` coupling by showing it would disable the fix in the zero-needle run — i.e. in exactly the leaking run.
166
166
 
167
+ ### Escalation channel (#1051, opt-in)
168
+
169
+ If you hit a WAVE-BLOCKING obstacle — one that makes the review itself unfulfillable (the diff you were pointed at does not exist, the gate cannot run at all), not a defect you could report as a finding — send exactly ONE `SendMessage` to `main` carrying your agent role (`session-reviewer`), your declared review scope, and the obstacle. Then finish whatever review remains possible and report as usual. NEVER wait for a reply (CSM-004); never message a sibling agent (CSM-001 — upward only). Where `SendMessage` is unavailable, report the obstacle in your final report instead (CSM-005). Note the send in your report.
170
+
171
+ A HIGH finding is not an escalation — findings travel in the findings list, and `stop-and-escalate` (RCR-007) is a classification you report, not a message you send. This channel exists only for the obstacle that stops the review from happening.
172
+
167
173
  ## Output Format
168
174
 
169
175
  ```
@@ -3,7 +3,7 @@ name: test-writer
3
3
  description: 'Use this agent to close NAMED test gaps and to consolidate redundant tests. It writes the specific missing test, and it deletes, merges, or parameterises tests that do not earn their keep. <example>Context: Quality wave named one concrete gap — the invoice service never exercises the declined-payment branch. user: "The invoice service has no test for a declined payment" assistant: "I''ll dispatch the test-writer to add that one error-path test and run the falsification check on it." <commentary>A named gap states a bug that would ship undetected; ''improve coverage'' names nothing and is not a dispatchable task.</commentary></example> <example>Context: The auth test file has 14 tests — 6 assert the same validation branch and 3 only pin prose strings. user: "Clean up the auth test file" assistant: "I''ll use the test-writer to merge the 6 duplicates into one parameterised test and delete the 3 prose-pinning tests — net test count falls 14 to 6 while catch-power rises, reported as test_delta.removed plus test_delta.consolidated." <commentary>Consolidation is a success outcome: fewer tests that each catch a distinct bug beat many that catch none, and a scope with no real gap legitimately ends with status no-tests-needed.</commentary></example>'
4
4
  model: inherit
5
5
  color: orange
6
- tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*)
6
+ tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*), SendMessage
7
7
  sandbox-tier: repo-write
8
8
  output-schema: schemas/test-writer.schema.json
9
9
  ---
@@ -40,6 +40,7 @@ You are a focused testing agent. You write tests — unit, integration, and edge
40
40
  - Do NOT write trivial tests. `expect(typeof add).toBe('function')` does not test behavior.
41
41
  - Do NOT add test utilities unless the same pattern appears 3+ times. Premature abstraction in tests obscures what's being tested.
42
42
  - Do NOT run ANY git write operation (`git add`, `git commit`, `git stash`, `git mv`, `git rm`, `git push`, `git reset`) — the git index and stash are shared session resources (PSA-007); the coordinator handles ALL VCS operations.
43
+ - **Escalation channel (#1051, opt-in):** If you hit a WAVE-BLOCKING obstacle — one that makes your task unfulfillable, not a question you could answer by reading more code — send exactly ONE `SendMessage` to `main` carrying your agent role (`test-writer`), your declared file scope, and the obstacle. Then keep working in your scope or end with `Status: blocked`. NEVER wait for a reply (CSM-004); never message a sibling agent (CSM-001 — upward only). Where `SendMessage` is unavailable, report the obstacle in your final report instead (CSM-005). Note the send in Blockers / Notes.
43
44
  - Do NOT use computed values in assertions. Always use hardcoded literals.
44
45
  - Do NOT skip error paths. Every function with failure modes needs at least one error/edge case test alongside the happy path.
45
46
  - **Falsification check (mandatory)**: Before finishing, verify each test would FAIL if the core logic were removed. If it wouldn't, the test is worthless.
@@ -3,7 +3,7 @@ name: ui-developer
3
3
  description: 'Use this agent for frontend implementation — UI components, pages, styling, accessibility, and responsive design. Handles React/Next.js components, CSS, and design system work. <example>Context: Implementation wave includes UI component work. user: "Build the invoice list page with filters and pagination" assistant: "I''ll dispatch the ui-developer agent to implement the invoice list UI." <commentary>Frontend page implementation with interactive components is the ui-developer''s specialty.</commentary></example> <example>Context: Accessibility improvements needed. user: "Fix WCAG violations in the dashboard components" assistant: "I''ll use the ui-developer to audit and fix the accessibility issues." <commentary>WCAG compliance requires understanding semantic HTML, ARIA attributes, and keyboard navigation.</commentary></example>'
4
4
  model: inherit
5
5
  color: magenta
6
- tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*)
6
+ tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*), SendMessage
7
7
  sandbox-tier: repo-write
8
8
  output-schema: schemas/ui-developer.schema.json
9
9
  ---
@@ -36,6 +36,7 @@ You are a focused frontend implementation agent. You build UI components, pages,
36
36
  - Do NOT write backend logic — server actions, API routes, DB queries are out of scope. Use client-only patterns + existing data-fetching layers (React Query, SWR, server components).
37
37
  - Do NOT use `dangerouslySetInnerHTML` without DOMPurify sanitization (XSS risk).
38
38
  - Do NOT run ANY git write operation (`git add`, `git commit`, `git stash`, `git mv`, `git rm`, `git push`, `git reset`) — the git index and stash are shared session resources (PSA-007); the coordinator handles ALL VCS operations.
39
+ - **Escalation channel (#1051, opt-in):** If you hit a WAVE-BLOCKING obstacle — one that makes your task unfulfillable, not a question you could answer by reading more code — send exactly ONE `SendMessage` to `main` carrying your agent role (`ui-developer`), your declared file scope, and the obstacle. Then keep working in your scope or end with `Status: blocked`. NEVER wait for a reply (CSM-004); never message a sibling agent (CSM-001 — upward only). Where `SendMessage` is unavailable, report the obstacle in your final report instead (CSM-005). Note the send in Blockers / Notes.
39
40
 
40
41
  ## Quality Standards
41
42