session-orchestrator 5.12.0 → 5.13.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 (385) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +4 -1
  3. package/.codex-plugin/agents/explorer.toml +1 -1
  4. package/.codex-plugin/agents/session-reviewer.toml +2 -2
  5. package/.codex-plugin/agents/wave-worker.toml +1 -1
  6. package/.codex-plugin/plugin.json +1 -1
  7. package/.cursor-plugin/plugin.json +1 -1
  8. package/.orchestrator/policy/blocked-commands.json +8 -0
  9. package/.orchestrator/policy/public-export.json +30 -0
  10. package/CHANGELOG.md +162 -4
  11. package/README.md +126 -127
  12. package/agents/analyst.md +7 -2
  13. package/agents/architect-reviewer.md +7 -2
  14. package/agents/code-implementer.md +4 -2
  15. package/agents/db-specialist.md +9 -2
  16. package/agents/dialectic-deriver.md +9 -3
  17. package/agents/docs-writer.md +7 -2
  18. package/agents/eval-judge.md +7 -1
  19. package/agents/qa-strategist.md +7 -2
  20. package/agents/security-reviewer.md +9 -2
  21. package/agents/session-reviewer.md +18 -2
  22. package/agents/skill-applied-judge.md +7 -1
  23. package/agents/test-writer.md +9 -2
  24. package/agents/ui-developer.md +9 -2
  25. package/agents/ux-evaluator.md +6 -1
  26. package/commands/session.md +1 -1
  27. package/commands/templates-ack.md +89 -18
  28. package/docs/agent-authoring.md +30 -11
  29. package/docs/ci-setup.md +38 -2
  30. package/docs/codex-setup.md +33 -9
  31. package/docs/components.md +13 -2
  32. package/docs/cursor-setup.md +3 -3
  33. package/docs/events-schema.md +5 -4
  34. package/docs/evidence-candidates.md +63 -0
  35. package/docs/fleet-checkin-audit.md +7 -4
  36. package/docs/github-mirror-protection.md +150 -3
  37. package/docs/install.md +90 -17
  38. package/docs/instruction-delivery.md +1 -1
  39. package/docs/migration-v4.md +2 -2
  40. package/docs/mods.md +118 -0
  41. package/docs/owner-config-schema.md +1 -0
  42. package/docs/plugin-architecture-v3.md +1 -1
  43. package/docs/pm-skills-marketplace.md +4 -3
  44. package/docs/rule-authoring.md +24 -13
  45. package/docs/scope-collision-guard.md +2 -1
  46. package/docs/session-config-reference.md +49 -15
  47. package/docs/session-config-template.md +30 -22
  48. package/docs/sessions-ledger-repair.md +137 -0
  49. package/docs/vault-docs-architecture.md +1 -1
  50. package/hooks/_lib/hook-import-set.json +406 -73
  51. package/hooks/_lib/hook-root.mjs +301 -0
  52. package/hooks/_lib/lock-bootstrap.mjs +434 -4
  53. package/hooks/_lib/orchestrator-ignore.mjs +3 -0
  54. package/hooks/_lib/subagent-transcript.mjs +2 -2
  55. package/hooks/_lib/vcs-create-matcher.mjs +13 -17
  56. package/hooks/cwd-change-restore.mjs +5 -1
  57. package/hooks/enforce-commands.mjs +4 -3
  58. package/hooks/enforce-scope.mjs +11 -1
  59. package/hooks/hooks-codex.json +48 -2
  60. package/hooks/hooks.json +31 -31
  61. package/hooks/on-session-end.mjs +38 -15
  62. package/hooks/on-session-start.mjs +139 -49
  63. package/hooks/on-stop.mjs +11 -6
  64. package/hooks/post-bash-issue-budget-refund.mjs +6 -1
  65. package/hooks/post-bash-write-verify.mjs +8 -4
  66. package/hooks/post-edit-validate.mjs +45 -52
  67. package/hooks/post-subagent-discovery-validator.mjs +2 -2
  68. package/hooks/post-tool-batch-wave-signal.mjs +8 -4
  69. package/hooks/post-tool-failure-corrective-context.mjs +5 -1
  70. package/hooks/pre-bash-destructive-guard.mjs +220 -8
  71. package/hooks/pre-bash-issue-budget.mjs +6 -1
  72. package/hooks/pre-bash-sessions-ledger-guard.mjs +691 -123
  73. package/hooks/pre-bash-staging-fence.mjs +258 -14
  74. package/hooks/pre-bash-templates-first.mjs +28 -27
  75. package/hooks/run-node.sh +1 -1
  76. package/hooks/skill-invocation-telemetry.mjs +15 -8
  77. package/hooks/subagent-telemetry.mjs +77 -14
  78. package/hooks/wave-scope-commit-guard.mjs +143 -14
  79. package/mods/so-hud/.claude-plugin/plugin.json +11 -0
  80. package/mods/so-hud/README.md +57 -0
  81. package/mods/so-hud/hooks/beacon-io.mjs +101 -0
  82. package/mods/so-hud/hooks/heredoc-scan.ts +394 -0
  83. package/mods/so-hud/hooks/hooks.json +1 -0
  84. package/mods/so-hud/hooks/logic.ts +182 -0
  85. package/mods/so-hud/hooks/register.tsx +670 -0
  86. package/mods/so-hud/hooks/rules.ts +2998 -0
  87. package/mods/so-hud/tsconfig.json +8 -0
  88. package/mods/so-hud/types/index.d.ts +36 -0
  89. package/package.json +4 -2
  90. package/rules/_index.md +1 -1
  91. package/rules/always-on/ask-via-tool.md +1 -1
  92. package/rules/always-on/loop-and-monitor.md +17 -194
  93. package/rules/always-on/parallel-sessions.md +3 -1
  94. package/rules/opt-in-stack/backend-data.md +1 -1
  95. package/rules/opt-in-stack/backend.md +1 -1
  96. package/rules/opt-in-stack/security-web.md +5 -1
  97. package/scripts/agent-usage-census.mjs +79 -0
  98. package/scripts/apply-session-learnings.mjs +34 -6
  99. package/scripts/archive-closed-prds.mjs +21 -5
  100. package/scripts/autopilot.mjs +11 -5
  101. package/scripts/backfill-abandoned-sessions.mjs +13 -3
  102. package/scripts/backfill-evidence-digest.mjs +2 -1
  103. package/scripts/backfill-learnings-from-vault.mjs +61 -6
  104. package/scripts/backfill-sessions.mjs +16 -2
  105. package/scripts/check-package-manager.mjs +26 -8
  106. package/scripts/check-sessions-integrity.mjs +4 -1
  107. package/scripts/ci/assert-vitest-green.mjs +3 -0
  108. package/scripts/ci/windows-smoke.mjs +201 -0
  109. package/scripts/close-precheck.mjs +55 -0
  110. package/scripts/dialectic-deriver.mjs +20 -12
  111. package/scripts/emit-event.mjs +2 -2
  112. package/scripts/emit-session.mjs +239 -20
  113. package/scripts/eval-session.mjs +17 -3
  114. package/scripts/export-hw-learnings.mjs +29 -2
  115. package/scripts/fleet-checkin-audit.mjs +8 -4
  116. package/scripts/fleet-checkin.mjs +39 -27
  117. package/scripts/gc-stale-worktrees.mjs +6 -1
  118. package/scripts/github-export.mjs +128 -0
  119. package/scripts/github-protection-audit.mjs +3 -1
  120. package/scripts/handover-queue-check.mjs +209 -0
  121. package/scripts/harness-audit.mjs +6 -4
  122. package/scripts/lib/agent-frontmatter.mjs +57 -10
  123. package/scripts/lib/agent-status.mjs +125 -7
  124. package/scripts/lib/agent-usage-census.mjs +394 -0
  125. package/scripts/lib/auto-dialectic.mjs +17 -10
  126. package/scripts/lib/auto-dream.mjs +22 -14
  127. package/scripts/lib/autopilot/loop.mjs +3 -1
  128. package/scripts/lib/autopilot/recent-runs.mjs +4 -2
  129. package/scripts/lib/autopilot/stall-sampler.mjs +2 -1
  130. package/scripts/lib/autopilot/telemetry.mjs +5 -1
  131. package/scripts/lib/autopilot/worktree-pipeline.mjs +5 -5
  132. package/scripts/lib/baseline-archetypes.mjs +10 -2
  133. package/scripts/lib/blocked-commands-policy.mjs +4 -3
  134. package/scripts/lib/build-live-signals.mjs +13 -9
  135. package/scripts/lib/ci-status-banner.mjs +329 -24
  136. package/scripts/lib/codex/plugin-contract.mjs +8 -0
  137. package/scripts/lib/cold-start-detector.mjs +5 -2
  138. package/scripts/lib/command-blocker.mjs +603 -43
  139. package/scripts/lib/common.mjs +3 -2
  140. package/scripts/lib/config/cross-repo.mjs +74 -7
  141. package/scripts/lib/config/host-paths.mjs +6 -2
  142. package/scripts/lib/config/section-extractor.mjs +65 -11
  143. package/scripts/lib/config/template-keys.mjs +153 -0
  144. package/scripts/lib/config/vault-integration.mjs +1 -0
  145. package/scripts/lib/config.mjs +2 -2
  146. package/scripts/lib/coordinator-snapshot.mjs +1 -1
  147. package/scripts/lib/discovery/triage-state.mjs +2 -1
  148. package/scripts/lib/dispatcher/rank.mjs +5 -7
  149. package/scripts/lib/ecosystem-health.mjs +2 -2
  150. package/scripts/lib/eval/engine.mjs +3 -2
  151. package/scripts/lib/eval/session-resolve.mjs +6 -2
  152. package/scripts/lib/eval/sink.mjs +4 -3
  153. package/scripts/lib/events-retention-banner.mjs +3 -2
  154. package/scripts/lib/events-schema.mjs +10 -0
  155. package/scripts/lib/events.mjs +23 -12
  156. package/scripts/lib/evolve/autonomy-verdict.mjs +4 -9
  157. package/scripts/lib/evolve/autopilot-effectiveness.mjs +8 -18
  158. package/scripts/lib/fleet-protocol.mjs +4 -0
  159. package/scripts/lib/gates/gate-full.mjs +172 -11
  160. package/scripts/lib/gates/gate-helpers.mjs +236 -23
  161. package/scripts/lib/git-config-drift.mjs +141 -7
  162. package/scripts/lib/github-export.mjs +447 -0
  163. package/scripts/lib/gitlab-portfolio/cli.mjs +16 -5
  164. package/scripts/lib/handover-queue-marks.mjs +159 -0
  165. package/scripts/lib/hardware-pattern-detector.mjs +103 -13
  166. package/scripts/lib/harness-audit/categories/category1.mjs +16 -4
  167. package/scripts/lib/harness-audit/categories/category4.mjs +11 -8
  168. package/scripts/lib/harness-audit/categories/category6.mjs +25 -5
  169. package/scripts/lib/harness-audit/categories/category9.mjs +10 -4
  170. package/scripts/lib/host-identity.mjs +9 -5
  171. package/scripts/lib/http-request.mjs +64 -0
  172. package/scripts/lib/instruction-budget-guard.mjs +30 -22
  173. package/scripts/lib/io.mjs +6 -3
  174. package/scripts/lib/issue-budget-reconcile.mjs +3 -2
  175. package/scripts/lib/issue-budget.mjs +36 -7
  176. package/scripts/lib/learnings/evidence-candidates.mjs +154 -0
  177. package/scripts/lib/learnings/expiry-sweep.mjs +99 -7
  178. package/scripts/lib/learnings/io.mjs +289 -15
  179. package/scripts/lib/learnings/select.mjs +53 -4
  180. package/scripts/lib/learnings/store-role.mjs +209 -0
  181. package/scripts/lib/learnings/surface.mjs +46 -7
  182. package/scripts/lib/ledger-path.mjs +113 -0
  183. package/scripts/lib/maintenance-due-banner.mjs +63 -12
  184. package/scripts/lib/memory-banner.mjs +5 -6
  185. package/scripts/lib/memory-proposals/collector.mjs +5 -2
  186. package/scripts/lib/memory-proposals/sink.mjs +7 -4
  187. package/scripts/lib/memory-proposals/store.mjs +22 -5
  188. package/scripts/lib/mode-selector-accuracy.mjs +2 -1
  189. package/scripts/lib/no-follow-open.mjs +57 -0
  190. package/scripts/lib/orphan-reaper/reaper-audit.mjs +4 -2
  191. package/scripts/lib/own-lock-root.mjs +95 -0
  192. package/scripts/lib/owner-interview.mjs +2 -1
  193. package/scripts/lib/owner-yaml.mjs +70 -7
  194. package/scripts/lib/platform.mjs +161 -9
  195. package/scripts/lib/plugin-update-banner.mjs +15 -11
  196. package/scripts/lib/pre-push-local-partial.mjs +117 -0
  197. package/scripts/lib/pre-push-remote-gate.mjs +151 -25
  198. package/scripts/lib/process-group.mjs +270 -34
  199. package/scripts/lib/project-hygiene.mjs +28 -0
  200. package/scripts/lib/quality-gate.mjs +33 -9
  201. package/scripts/lib/reconcile/backlog.mjs +29 -15
  202. package/scripts/lib/reconcile/engine.mjs +26 -2
  203. package/scripts/lib/reconcile/idempotency.mjs +65 -3
  204. package/scripts/lib/reconcile/rule-expiry-sweep.mjs +53 -12
  205. package/scripts/lib/reconcile/verdict-ledger.mjs +224 -0
  206. package/scripts/lib/reconcile-nudge-banner.mjs +40 -6
  207. package/scripts/lib/resource-probe/evaluate.mjs +32 -9
  208. package/scripts/lib/resource-probe/probe-platform.mjs +3 -1
  209. package/scripts/lib/rule-loader.mjs +20 -10
  210. package/scripts/lib/scope-baseline.mjs +123 -8
  211. package/scripts/lib/scope-echo.mjs +5 -2
  212. package/scripts/lib/scope-gate.mjs +55 -20
  213. package/scripts/lib/session-close-backfill.mjs +75 -7
  214. package/scripts/lib/session-end/close-precheck.mjs +151 -0
  215. package/scripts/lib/session-end/phase-skip.mjs +8 -7
  216. package/scripts/lib/session-end/tail-runner.mjs +7 -2
  217. package/scripts/lib/session-id.mjs +9 -1
  218. package/scripts/lib/session-identity/own-session.mjs +63 -0
  219. package/scripts/lib/session-lock.mjs +114 -0
  220. package/scripts/lib/session-record-repair.mjs +245 -35
  221. package/scripts/lib/session-registry.mjs +72 -9
  222. package/scripts/lib/session-schema/constants.mjs +9 -0
  223. package/scripts/lib/session-schema/filters.mjs +56 -1
  224. package/scripts/lib/session-schema/validator.mjs +15 -5
  225. package/scripts/lib/session-start-probes.mjs +149 -22
  226. package/scripts/lib/session-token-rollup.mjs +2 -1
  227. package/scripts/lib/session-work-trees.mjs +166 -0
  228. package/scripts/lib/sessions-canonical.mjs +61 -3
  229. package/scripts/lib/sessions-integrity-banner.mjs +17 -39
  230. package/scripts/lib/sessions-staleness-banner.mjs +8 -5
  231. package/scripts/lib/sh-quote.mjs +1 -0
  232. package/scripts/lib/skill-evidence-window.mjs +5 -1
  233. package/scripts/lib/skill-health/join.mjs +10 -9
  234. package/scripts/lib/skill-invocations-schema.mjs +13 -0
  235. package/scripts/lib/skill-judgments-schema.mjs +6 -2
  236. package/scripts/lib/snapshot-probe.mjs +414 -0
  237. package/scripts/lib/so-hud/collect.mjs +49 -5
  238. package/scripts/lib/so-hud/runtime.mjs +15 -4
  239. package/scripts/lib/spiral-carryover.mjs +8 -1
  240. package/scripts/lib/state-md/frontmatter-mutators.mjs +266 -8
  241. package/scripts/lib/state-md/idle-reset.mjs +14 -5
  242. package/scripts/lib/state-md/mission-status.mjs +5 -1
  243. package/scripts/lib/state-md-peer-guard.mjs +2 -0
  244. package/scripts/lib/state-md.mjs +31 -8
  245. package/scripts/lib/sunset/walker.mjs +4 -3
  246. package/scripts/lib/telemetry/consent.mjs +4 -2
  247. package/scripts/lib/telemetry/queue.mjs +3 -3
  248. package/scripts/lib/telemetry/sync.mjs +45 -9
  249. package/scripts/lib/test-runner/artifact-paths.mjs +10 -2
  250. package/scripts/lib/tmux-layout/layouts.mjs +20 -3
  251. package/scripts/lib/ux-grill/paths.mjs +5 -1
  252. package/scripts/lib/validate/check-agents.mjs +37 -6
  253. package/scripts/lib/validate/check-component-paths.mjs +25 -1
  254. package/scripts/lib/validate/check-guard-requires-parity.mjs +3 -3
  255. package/scripts/lib/validate/check-hooks-symmetry.mjs +53 -32
  256. package/scripts/lib/validate/check-json-files.mjs +3 -1
  257. package/scripts/lib/validate/check-learning-provenance.mjs +3 -2
  258. package/scripts/lib/validate/check-learnings-shell-writes.mjs +10 -4
  259. package/scripts/lib/validate/check-metrics-ledger-root.mjs +234 -0
  260. package/scripts/lib/validate/check-owner-leakage.mjs +159 -11
  261. package/scripts/lib/validate/check-test-posix-shell.mjs +246 -0
  262. package/scripts/lib/validate/check-unwired-features.mjs +4 -2
  263. package/scripts/lib/validate/check-vcs-repo-flag-positional.mjs +58 -0
  264. package/scripts/lib/validate/check-vcs-repo-flag.mjs +259 -73
  265. package/scripts/lib/validate/check-workflow-continue-on-error.mjs +63 -0
  266. package/scripts/lib/validate/confidential-names.mjs +3 -1
  267. package/scripts/lib/vault-mirror/migrate-ids.mjs +321 -0
  268. package/scripts/lib/vault-mirror/namespace.mjs +19 -7
  269. package/scripts/lib/vault-mirror/process.mjs +56 -27
  270. package/scripts/lib/vault-mirror/prune.mjs +5 -2
  271. package/scripts/lib/vault-mirror/render-learnings.mjs +3 -3
  272. package/scripts/lib/vault-mirror/render-sessions.mjs +36 -53
  273. package/scripts/lib/vault-mirror/retention.mjs +2 -2
  274. package/scripts/lib/vault-mirror/utils.mjs +79 -0
  275. package/scripts/lib/vault-staleness-banner.mjs +4 -7
  276. package/scripts/lib/vault-status/board-writer.mjs +2 -1
  277. package/scripts/lib/vault-status/narrative-mirror.mjs +66 -7
  278. package/scripts/lib/wave-executor/foreign-dispatch.mjs +20 -0
  279. package/scripts/lib/win-process-tree.mjs +137 -0
  280. package/scripts/lib/workspace.mjs +1 -1
  281. package/scripts/lib/worktree/constants.mjs +1 -1
  282. package/scripts/lib/worktree/lifecycle.mjs +1 -1
  283. package/scripts/lib/worktree/listing.mjs +1 -1
  284. package/scripts/lib/zx.mjs +50 -0
  285. package/scripts/mcp-server.mjs +16 -7
  286. package/scripts/mcp-server.sh +13 -83
  287. package/scripts/measure-policy-cache-effectiveness.mjs +7 -5
  288. package/scripts/memory-propose.mjs +10 -3
  289. package/scripts/migrate-cold-start-seed.mjs +7 -0
  290. package/scripts/migrate-legacy-learnings.sh +22 -0
  291. package/scripts/migrate-sessions-jsonl.mjs +16 -2
  292. package/scripts/migrate-vault-paths.mjs +29 -13
  293. package/scripts/parse-config.mjs +71 -14
  294. package/scripts/print-learnings-index.mjs +25 -2
  295. package/scripts/release-session-lock.mjs +94 -7
  296. package/scripts/release.mjs +451 -24
  297. package/scripts/relocate-vault-corpus.mjs +11 -7
  298. package/scripts/repair-invalid-sessions.mjs +68 -3
  299. package/scripts/resolve-session-invocation.mjs +10 -17
  300. package/scripts/run-migrate-v2-cross-repo.mjs +56 -1
  301. package/scripts/run-quality-gate.mjs +33 -7
  302. package/scripts/self-update.mjs +56 -7
  303. package/scripts/session-commit-files.mjs +133 -0
  304. package/scripts/site-numbers.mjs +52 -9
  305. package/scripts/snapshot-probe.mjs +156 -0
  306. package/scripts/so-hud.mjs +29 -6
  307. package/scripts/state-md-idle-reset.mjs +2 -1
  308. package/scripts/sweep-expired-learnings.mjs +54 -6
  309. package/scripts/sweep-expired-rules.mjs +4 -1
  310. package/scripts/validate-plugin.mjs +22 -0
  311. package/scripts/vault-integration-watcher.mjs +54 -6
  312. package/scripts/vault-mirror.mjs +9 -0
  313. package/skills/_shared/fleet-protocol.md +142 -1
  314. package/skills/_shared/instruction-file-resolution.md +1 -1
  315. package/skills/_shared/monitor-patterns.md +44 -25
  316. package/skills/_shared/platform-tools.md +7 -0
  317. package/skills/_shared/state-ownership.md +3 -2
  318. package/skills/architecture/references/domain-model.md +1 -1
  319. package/skills/bootstrap/SKILL.md +3 -1
  320. package/skills/bootstrap/_shared-template.md +4 -4
  321. package/skills/bootstrap/fast-template.md +1 -1
  322. package/skills/bootstrap/private-contract.md +1 -1
  323. package/skills/bootstrap/references/bootstrap-retroactive-flow.md +17 -9
  324. package/skills/bootstrap/templates/agents/project-code-review.md +5 -1
  325. package/skills/bootstrap/templates/agents/project-discovery.md +5 -1
  326. package/skills/bootstrap/templates/agents/project-quality-gate.md +5 -1
  327. package/skills/claude-md-drift-check/SKILL.md +3 -3
  328. package/skills/claude-md-drift-check/checker.mjs +61 -101
  329. package/skills/close/SKILL.md +20 -7
  330. package/skills/discovery/probes/docs-staleness.mjs +7 -5
  331. package/skills/discovery/probes/frontend-slop.mjs +7 -3
  332. package/skills/discovery/probes/ssot-code-diff.mjs +5 -3
  333. package/skills/discovery/probes/supply-chain-slopcheck.mjs +10 -8
  334. package/skills/discovery/probes/vault-narrative-staleness.mjs +30 -10
  335. package/skills/discovery/probes/vault-staleness.mjs +5 -3
  336. package/skills/discovery/probes-session.md +3 -0
  337. package/skills/discovery/probes-vault.md +2 -0
  338. package/skills/dispatcher/SKILL.md +1 -1
  339. package/skills/eval/SKILL.md +3 -1
  340. package/skills/evolve/SKILL.md +2 -0
  341. package/skills/evolve/references/evolve-analyze-mode.md +3 -3
  342. package/skills/evolve/references/evolve-dialectic-mode.md +1 -1
  343. package/skills/gitlab-ops/SKILL.md +7 -6
  344. package/skills/gitlab-portfolio/SKILL.md +2 -2
  345. package/skills/go/SKILL.md +13 -1
  346. package/skills/npm-publish/SKILL.md +5 -2
  347. package/skills/plan/SKILL.md +23 -10
  348. package/skills/plan/mode-feature.md +13 -8
  349. package/skills/plan/mode-new.md +6 -14
  350. package/skills/plan/prd-feature-template.md +19 -0
  351. package/skills/plan/prd-full-template.md +12 -5
  352. package/skills/plan/prd-premortem-panel.md +48 -0
  353. package/skills/plan/prd-reviewer-prompt.md +11 -3
  354. package/skills/plan/soul.md +1 -1
  355. package/skills/portfolio/SKILL.md +5 -6
  356. package/skills/quality-gates/SKILL.md +2 -4
  357. package/skills/reconcile/SKILL.md +27 -4
  358. package/skills/release/SKILL.md +16 -8
  359. package/skills/session-end/SKILL.md +94 -11
  360. package/skills/session-end/phase-3-2-docs-verification.md +1 -0
  361. package/skills/session-end/phase-3-6-tail.md +11 -7
  362. package/skills/session-end/phase-3-7a-recommendations.md +9 -2
  363. package/skills/session-end/plan-verification.md +16 -1
  364. package/skills/session-end/references/phase-3-documentation-updates.md +14 -12
  365. package/skills/session-end/references/phase-5-issue-cleanup.md +1 -1
  366. package/skills/session-end/references/session-summary-template.md +4 -0
  367. package/skills/session-end/session-metrics-write.md +7 -4
  368. package/skills/session-plan/SKILL.md +5 -3
  369. package/skills/session-start/SKILL.md +9 -3
  370. package/skills/session-start/phase-4-5-resource-health.md +11 -5
  371. package/skills/session-start/phase-8-5-express-path.md +4 -3
  372. package/skills/session-start/references/phase-1-2-session-lock.md +7 -5
  373. package/skills/session-start/references/phase-1-5-session-continuity.md +2 -2
  374. package/skills/session-start/references/phase-1-7-vault-status-board.md +1 -1
  375. package/skills/session-start/references/phase-4-ssot-environment-check.md +3 -2
  376. package/skills/tmux-layout/SKILL.md +2 -2
  377. package/skills/vault-sync/validator.mjs +3 -2
  378. package/skills/wave-executor/SKILL.md +5 -4
  379. package/skills/wave-executor/references/wave-executor-state-init.md +3 -3
  380. package/skills/wave-executor/references/wave-loop-dispatch.md +11 -5
  381. package/skills/wave-executor/references/wave-loop-review.md +13 -5
  382. package/skills/wave-executor/references/wave-loop-scope-manifest.md +1 -1
  383. package/assets/og-card.png +0 -0
  384. package/assets/og-card.svg +0 -47
  385. package/assets/wave-lifecycle.svg +0 -98
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  name: session-reviewer
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
- model: inherit
3
+ description: 'Use this agent between waves or at session end to verify work quality against the session plan, or ad hoc to review a named diff, branch or MR without any plan (verdict ship / ship nach Fix / FIX_REQUIRED). Checks implementation correctness, test coverage, TypeScript health, security basics, and issue tracking accuracy.'
4
+ model: opus
5
+ effort: medium
5
6
  color: pink
6
7
  tools: Read, Grep, Glob, Bash, SendMessage
7
8
  sandbox-tier: read-only
@@ -12,6 +13,15 @@ output-schema: schemas/session-reviewer.schema.json
12
13
 
13
14
  You are a quality gate agent. Your job is to verify work quality — NOT to implement or fix anything.
14
15
 
16
+ ## Ad-hoc Mode (no wave plan)
17
+
18
+ When your prompt names a diff, branch, commit range or MR but no wave plan or session plan, review that change on its own. Do NOT look for, create or ask for a plan, STATE.md or wave artefacts; their absence is not a finding and not an obstacle.
19
+
20
+ - **Scope:** the named change only (`git diff <base>...<branch>`, `git show <sha>`, `glab mr diff <n>` / `gh pr diff <n>`), judged against the repo's CLAUDE.md/AGENTS.md and `.claude/rules/`. Read-only: you never check out, commit or push.
21
+ - **Findings:** only those you can back with a concrete scenario (input or state → wrong result) and a `file:line`. Rank them **HOCH / MITTEL / NIEDRIG**, at most ~12, each with its RCR-007 class. Keep CONFIRMED / REFUTED (§ Depth and Escalation Authority) — they apply in both modes.
22
+ - **Verdict**, exactly one: `ship` (no finding needs a fix before merge) · `ship nach Fix` (only MITTEL/NIEDRIG findings with a local, named fix; no second review needed) · `FIX_REQUIRED` (any HOCH, or a fix that needs another review).
23
+ - **Output:** the findings list, CONFIRMED, REFUTED and the verdict replace the wave-shaped report below. Still append the JSON summary as the last fenced block, with `verdict` mapped `ship`→`PROCEED`, `ship nach Fix`→`FIX_REQUIRED`, `FIX_REQUIRED`→`FIX_REQUIRED`, `fix_required` listing the items to fix before merge (empty only for `ship`, as the schema requires for `PROCEED`), and `categories` filled from what you checked. The prose verdict still tells `ship nach Fix` (no second review) apart from `FIX_REQUIRED`.
24
+
15
25
  ## Review Checklist
16
26
 
17
27
  > **Verification standard**: When verifying inter-wave checkpoint completion, apply `.claude/rules/verification-before-completion.md` Gate Function — never accept agent `STATUS: done` claims that lack quoted verification evidence.
@@ -246,3 +256,9 @@ Verdict variants (concrete examples per scenario):
246
256
  - `fix_required`: array of strings describing items that must be addressed before proceeding
247
257
  - Wrap in a fenced code block tagged `json` so consuming skills can extract via regex
248
258
  - The coordinator's `validateAgentOutput()` parses the LAST fenced ```json block; place it at the end of your response
259
+
260
+ ## Examples
261
+
262
+ <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>
263
+
264
+ <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>
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  name: skill-applied-judge
3
- description: 'Use this agent at session-end Phase 3.6.6 (#645 L3) to judge — from the session transcript evidence (excerpts) — whether each selected skill was actually APPLIED and whether its work COMPLETED. Dispatched read-only by scripts/lib/skill-judge.mjs::runSkillJudge as Haiku with a bounded per-call budget. RETURNS one fenced json block of advisory per-skill judgments; the coordinator writes them. Read-only by contract — never writes files. Advisory-only — output never gates any action. <example>Context: session-end Phase 3.6.6 with skill-evolution.judge: true. user "Judge whether the skills this session selected were actually applied." assistant "Dispatching skill-applied-judge to read the transcript evidence and emit advisory applied/completed judgments for each selected skill." <commentary>The judge produces a cheap advisory signal feeding the L3 skill-judgments sidecar — never an auto-action gate.</commentary></example>'
3
+ description: 'Use this agent at session-end Phase 3.6.6 (#645 L3) to judge — from the session transcript evidence (excerpts) — whether each selected skill was actually APPLIED and whether its work COMPLETED. Dispatched read-only by scripts/lib/skill-judge.mjs::runSkillJudge as Haiku with a bounded per-call budget. RETURNS one fenced json block of advisory per-skill judgments; the coordinator writes them. Read-only by contract — never writes files. Advisory-only — output never gates any action.'
4
4
  model: haiku
5
+ effort: medium
6
+ omitClaudeMd: true
5
7
  color: cyan
6
8
  tools: Read, Grep, Glob
7
9
  sandbox-tier: read-only
@@ -135,3 +137,7 @@ Rules:
135
137
  - `scripts/lib/skill-judgments-schema.mjs` — the schema the coordinator validates against
136
138
  - `skills/session-end/SKILL.md` § Phase 3.6.6 — the dispatch + write site
137
139
  - Issue #645 (OpenSpace A, epic #643) — original spec and L3 acceptance criteria
140
+
141
+ ## Examples
142
+
143
+ <example>Context: session-end Phase 3.6.6 with skill-evolution.judge: true. user "Judge whether the skills this session selected were actually applied." assistant "Dispatching skill-applied-judge to read the transcript evidence and emit advisory applied/completed judgments for each selected skill." <commentary>The judge produces a cheap advisory signal feeding the L3 skill-judgments sidecar — never an auto-action gate.</commentary></example>
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  name: test-writer
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
- model: inherit
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.'
4
+ model: sonnet
5
+ effort: medium
5
6
  color: orange
6
7
  tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*), SendMessage
7
8
  sandbox-tier: repo-write
@@ -141,3 +142,9 @@ Required: `status`, `task_id`, `files_changed`, `blockers`. Optional: `verdict`,
141
142
  - **Coverage threshold conflict**: Adding tests for a low-priority module pushes coverage down (because new lines exposed). → That's expected; do not skip writing tests just to game the coverage metric. Coverage measures untested code, not test quality.
142
143
  - **Property-based vs example-based**: Function has clear invariants (e.g., parser inverts serializer). → Consider property-based tests (`fast-check`, `Hypothesis`) alongside examples. Use sparingly — only when invariants are stronger than examples.
143
144
  - **Snapshot tests**: Output is large structured data (rendered HTML, AST). → Snapshots are acceptable when the project uses them, but always pair with at least one explicit assertion on key fields — pure snapshot tests rot quickly.
145
+
146
+ ## Examples
147
+
148
+ <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>
149
+
150
+ <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>
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  name: ui-developer
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
- model: inherit
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.'
4
+ model: opus
5
+ effort: medium
5
6
  color: magenta
6
7
  tools: Read, Edit, Write, Glob, Grep, Bash, Skill(session-orchestrator:*), SendMessage
7
8
  sandbox-tier: repo-write
@@ -108,3 +109,9 @@ Required: `status`, `task_id`, `files_changed`, `blockers`. Optional: `verdict`.
108
109
  - **Mobile-first conflict**: Design mockup is desktop-only with no mobile spec. → Implement mobile-first with reasonable defaults (single column, stacked filters), flag the desktop-only spec in Notes for design clarification.
109
110
  - **Animation request**: Task asks for "smooth transitions" without specifics. → Use the project's existing motion tokens (typically `transition: 200ms ease`) and flag for design review if heavier animation is needed.
110
111
  - **JS-disabled fallback**: Server-rendered page must work without JS. → Confirm with the wave plan; if unspecified, use progressive enhancement (form posts work, JS adds client-side validation on top).
112
+
113
+ ## Examples
114
+
115
+ <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>
116
+
117
+ <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>
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  name: ux-evaluator
3
- description: 'Use this agent for read-only UX evaluation of test-runner driver artifacts (Playwright AX-tree snapshots, screenshots, console output). Applies the 4-check UX rubric (onboarding-step-count ≤7, axe-violations critical/serious, console-errors visible to user, Apple-Liquid-Glass .glassEffect() conformance on SwiftUI 26+) and emits structured findings JSON with stable fingerprints. <example>Context: test-runner has just produced .orchestrator/metrics/test-runs/12345-1715688000123/ax-snapshots/. user: "Evaluate UX of the dashboard flow against rubric-v1." assistant: "I''ll dispatch ux-evaluator to read the AX-tree snapshots and emit findings.json per skills/test-runner/rubric-v1.md." <commentary>ux-evaluator is the only agent that translates driver-captured artifacts into reconcilable findings; it never invokes drivers itself.</commentary></example>'
3
+ description: 'Use this agent for read-only UX evaluation of test-runner driver artifacts (Playwright AX-tree snapshots, screenshots, console output). Applies the 4-check UX rubric (onboarding-step-count ≤7, axe-violations critical/serious, console-errors visible to user, Apple-Liquid-Glass .glassEffect() conformance on SwiftUI 26+) and emits structured findings JSON with stable fingerprints.'
4
4
  model: opus
5
+ effort: medium
5
6
  color: blue
6
7
  tools: Read, Grep, Glob, Bash
7
8
  sandbox-tier: read-only
@@ -159,3 +160,7 @@ After the human-readable stdout summary, append a fenced ```json block matching
159
160
  ```
160
161
 
161
162
  Required: `verdict` (enum PROCEED|PROCEED_WITH_FOLLOWUPS|FIX_REQUIRED|BLOCKED), `run_id`, `rubric_version`, `checks_applied`, `findings_count`, `findings_path`. Optional: `severity_counts`. The coordinator's `validateAgentOutput()` parses the LAST fenced ```json block; place it at the end of your response.
163
+
164
+ ## Examples
165
+
166
+ <example>Context: test-runner has just produced .orchestrator/metrics/test-runs/12345-1715688000123/ax-snapshots/. user: "Evaluate UX of the dashboard flow against rubric-v1." assistant: "I'll dispatch ux-evaluator to read the AX-tree snapshots and emit findings.json per skills/test-runner/rubric-v1.md." <commentary>ux-evaluator is the only agent that translates driver-captured artifacts into reconcilable findings; it never invokes drivers itself.</commentary></example>
@@ -17,7 +17,7 @@ You are beginning a new development session. The complete text following `/sessi
17
17
 
18
18
  **Explicit execution requests:** Ordinary housekeeping uses the coordinator-direct maintenance shape returned by `scripts/session-shape.mjs`. If the user explicitly requests parallel subagents or waves in the context, carry that request into the session plan as an override for this run, following [User-authorized housekeeping execution deviation](../skills/session-plan/SKILL.md#user-authorized-housekeeping-execution-deviation). Retain `session-type: housekeeping`, keep the resolver's default shape distinct from the actual plan, and preserve global Session Config and the user's model settings. The planning and execution skills apply this exception before their housekeeping shortcuts; the request does not implicitly authorize unrelated external actions.
19
19
 
20
- ### Argument alias: `ultradeep` (PRD `docs/prd/2026-09-06-ultradeep-session-profile.md`)
20
+ ### Argument alias: `ultradeep` (spec: internal session-profile PRD, 2026-09-06)
21
21
 
22
22
  `/session ultradeep` is an alias, NOT a fourth `session_type`. Resolve it to TWO STATE.md frontmatter values and then continue exactly as a `deep` session would:
23
23
 
@@ -5,7 +5,7 @@ argument-hint: "[optional-reason]"
5
5
 
6
6
  # Templates Acknowledgement
7
7
 
8
- Write a session-scoped acknowledgement entry to `.orchestrator/runtime/templates-acknowledged.json`. Once written, the `pre-bash-templates-first` hook (G6) will allow `gh`/`glab` create operations for the rest of the current session without requiring a prior template Read.
8
+ Write a session-scoped acknowledgement entry to `.orchestrator/runtime/templates-acknowledged.json` (inside a linked git worktree: the main checkout's `.orchestrator/runtime/`, where the hook reads it). Once written, the `pre-bash-templates-first` hook (G6) will allow `gh`/`glab` create operations for the rest of the current session without requiring a prior template Read.
9
9
 
10
10
  **Use this only when:**
11
11
  - You have already reviewed the relevant template externally (e.g. copy-paste workflow), OR
@@ -15,28 +15,76 @@ Write a session-scoped acknowledgement entry to `.orchestrator/runtime/templates
15
15
 
16
16
  Run the following node snippet to write the acknowledgement:
17
17
 
18
+ The acknowledgement requires proof from the nearest ancestor whose process name
19
+ (basename of `comm`) is `claude`: its `~/.claude/sessions/<pid>.json` must supply a valid `sessionId`.
20
+ Only parent PID and process name are measured, with at most 64 processes and no
21
+ cycles. Nonempty native environment IDs must agree with that invocation.
22
+ Missing process/session evidence refuses the acknowledgement, including on
23
+ harnesses without a Claude ancestor. Shared
24
+ `.orchestrator/current-session.json` state is never used as identity. This guards against accidental acknowledgement
25
+ for a parent session from a nested harness; it is not a security boundary against
26
+ a hostile child (which could write the file directly). A Claude started as a
27
+ plain `node` script has no `claude` ancestor and is refused. Run this
28
+ from the target project with the harness's plugin-root environment set (or from
29
+ the session-orchestrator repository itself).
30
+ The hook accepts this acknowledgement only when its invocation supplies a valid,
31
+ unambiguous `session_id` or `sessionId`; inherited environment IDs cannot grant
32
+ an acknowledgement bypass when that invocation ID is missing.
33
+
18
34
  ```bash
19
35
  node --input-type=module -e "
20
- import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync } from 'node:fs';
36
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync, statSync } from 'node:fs';
21
37
  import { join, dirname } from 'node:path';
22
38
  import { randomBytes } from 'node:crypto';
39
+ import { pathToFileURL } from 'node:url';
23
40
 
24
41
  const cwd = process.cwd();
25
- const sessionFile = join(cwd, '.orchestrator', 'current-session.json');
26
- const ackFile = join(cwd, '.orchestrator', 'runtime', 'templates-acknowledged.json');
27
42
  const reason = process.argv[1] ?? '';
28
43
  const userId = process.env.USER ?? process.env.USERNAME ?? '';
29
44
 
30
- // Resolve session_id
31
- let sessionId = null;
32
- if (existsSync(sessionFile)) {
45
+ // Bootstrap from the same root precedence as the plugin resolver. The cwd
46
+ // fallback is restricted to the plugin repository, never an arbitrary project.
47
+ const roots = [
48
+ ['claude', 'CLAUDE_PLUGIN_ROOT'], ['codex', 'CODEX_PLUGIN_ROOT'],
49
+ ['cursor', 'CURSOR_RULES_DIR'], ['pi', 'PI_PLUGIN_ROOT'],
50
+ ];
51
+ const platform = (process.env.SO_PLATFORM ?? '').trim();
52
+ const ordered = [...roots.filter(([p]) => p === platform), ...roots.filter(([p]) => p !== platform)];
53
+ let pluginRoot = null;
54
+ for (const name of ['PLUGIN_ROOT', ...ordered.map(([, name]) => name)]) {
55
+ const candidate = (process.env[name] ?? '').trim();
56
+ if (!candidate) continue;
57
+ try { if (statSync(candidate).isDirectory()) { pluginRoot = candidate; break; } } catch { /* try next root */ }
58
+ }
59
+ if (!pluginRoot) {
33
60
  try {
34
- const raw = JSON.parse(readFileSync(sessionFile, 'utf8'));
35
- sessionId = raw.session_id ?? raw.sessionId ?? null;
36
- } catch { /* ignore */ }
61
+ if (JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf8')).name === 'session-orchestrator') pluginRoot = cwd;
62
+ } catch { /* no plugin-root evidence */ }
63
+ }
64
+ if (!pluginRoot) {
65
+ process.stderr.write('⚠ templates-ack: plugin root unavailable — ack not written\n');
66
+ process.exit(1);
67
+ }
68
+ // The ack file is runtime state: in a linked worktree it lives in the MAIN
69
+ // checkout, the same root the pre-bash-templates-first hook reads (#1729).
70
+ let ackFile = null;
71
+ try {
72
+ const { resolveEventsLedgerRoot } = await import(pathToFileURL(join(pluginRoot, 'scripts/lib/platform.mjs')).href);
73
+ ackFile = join(resolveEventsLedgerRoot(cwd), '.orchestrator', 'runtime', 'templates-acknowledged.json');
74
+ } catch {
75
+ process.stderr.write('⚠ templates-ack: root resolver unavailable — ack not written\n');
76
+ process.exit(1);
77
+ }
78
+ let sessionId = null;
79
+ try {
80
+ const { readInvocationSessionId } = await import(pathToFileURL(join(pluginRoot, 'scripts/lib/session-identity/own-session.mjs')).href);
81
+ sessionId = readInvocationSessionId();
82
+ } catch {
83
+ process.stderr.write('⚠ templates-ack: process-local identity helper unavailable — ack not written\n');
84
+ process.exit(1);
37
85
  }
38
86
  if (!sessionId) {
39
- process.stderr.write('⚠ templates-ack: could not read session_id from .orchestrator/current-session.json — ack not written\n');
87
+ process.stderr.write('⚠ templates-ack: session id does not come from this invocation — ack not written\n');
40
88
  process.exit(1);
41
89
  }
42
90
 
@@ -67,15 +115,38 @@ if (reason) process.stdout.write(' Reason: ' + reason + '\n');
67
115
 
68
116
  ## Verification
69
117
 
70
- After writing, confirm the entry exists:
118
+ After writing, confirm the entry exists. The check resolves the same root as
119
+ the writer (main checkout for a linked worktree); the `Written:` line above
120
+ names the same file.
71
121
 
72
122
  ```bash
73
- node -e "
74
- const f = require('fs');
75
- const p = '.orchestrator/runtime/templates-acknowledged.json';
76
- if (!f.existsSync(p)) { console.log('NOT FOUND'); process.exit(1); }
77
- const d = JSON.parse(f.readFileSync(p, 'utf8'));
78
- console.log(JSON.stringify(d, null, 2));
123
+ node --input-type=module -e "
124
+ import { existsSync, readFileSync, statSync } from 'node:fs';
125
+ import { join } from 'node:path';
126
+ import { pathToFileURL } from 'node:url';
127
+ const cwd = process.cwd();
128
+ // Same plugin-root lookup as the writer: an env root first, the cwd only
129
+ // when it IS the plugin repository, never an arbitrary project.
130
+ let pluginRoot = null;
131
+ for (const name of ['PLUGIN_ROOT', 'CLAUDE_PLUGIN_ROOT', 'CODEX_PLUGIN_ROOT', 'CURSOR_RULES_DIR', 'PI_PLUGIN_ROOT']) {
132
+ const candidate = (process.env[name] ?? '').trim();
133
+ if (!candidate) continue;
134
+ try { if (statSync(candidate).isDirectory()) { pluginRoot = candidate; break; } } catch { /* try next root */ }
135
+ }
136
+ if (!pluginRoot) {
137
+ try {
138
+ if (JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf8')).name === 'session-orchestrator') pluginRoot = cwd;
139
+ } catch { /* no plugin-root evidence */ }
140
+ }
141
+ if (!pluginRoot) { console.log('plugin root unavailable'); process.exit(1); }
142
+ let root;
143
+ try {
144
+ const { resolveEventsLedgerRoot } = await import(pathToFileURL(join(pluginRoot, 'scripts/lib/platform.mjs')).href);
145
+ root = resolveEventsLedgerRoot(cwd);
146
+ } catch { console.log('root resolver unavailable'); process.exit(1); }
147
+ const p = join(root, '.orchestrator', 'runtime', 'templates-acknowledged.json');
148
+ if (!existsSync(p)) { console.log('NOT FOUND: ' + p); process.exit(1); }
149
+ console.log(JSON.stringify(JSON.parse(readFileSync(p, 'utf8')), null, 2));
79
150
  "
80
151
  ```
81
152
 
@@ -48,8 +48,9 @@ Agent files live in `agents/` as Markdown with YAML frontmatter. Required fields
48
48
  ```yaml
49
49
  ---
50
50
  name: kebab-case-name # 3-50 chars, lowercase + hyphens only
51
- description: Use this agent when [conditions]. <example>Context: ... user: "..." assistant: "..." <commentary>Why this agent is appropriate</commentary></example>
52
- model: inherit # inherit | sonnet | opus | haiku | fable — OR full ID like claude-opus-5-5, claude-sonnet-4-6, claude-haiku-4-5-20251001, claude-sonnet-5, claude-fable-5
51
+ description: Use this agent when [conditions]. # single-line routing sentence; <example> blocks go in the body § Examples
52
+ model: opus # inherit | sonnet | opus | haiku | fable — OR full ID like claude-opus-5-5, claude-sonnet-4-6, claude-haiku-4-5-20251001, claude-sonnet-5, claude-fable-5
53
+ effort: medium # low | medium | high | xhigh | max — REQUIRED whenever model is not inherit (#1614)
53
54
  color: blue # blue | cyan | green | yellow | purple | orange | pink | red | magenta
54
55
  tools: Read, Grep, Glob, Bash # comma-separated string OR JSON array (both accepted; we prefer comma-string for consistency)
55
56
  ---
@@ -59,8 +60,9 @@ tools: Read, Grep, Glob, Bash # comma-separated string OR JSON array (bo
59
60
 
60
61
  **Required vs optional:**
61
62
  - Runtime canonical doc: only `name` + `description` are required.
62
- - Our validator (defensive for plugin-distribution): all four of `name + description + model + color` required; `tools` optional.
63
- - `description` MUST be a single-line inline string, NOT a YAML block scalar (`>` or `|`). Put `<example>` blocks inline.
63
+ - Our validator (defensive for plugin-distribution): all four of `name + description + model + color` required; `effort` required as soon as `model` is not `inherit`; `tools` optional.
64
+ - `omitClaudeMd: true|false` (optional, #1616) drops CLAUDE.md from the agent's start context. Set only on narrow judges that read nothing but the records they are handed (`eval-judge`, `skill-applied-judge`, `dialectic-deriver`); reviewers and implementers keep it because they check against the rules.
65
+ - `description` MUST be a single-line inline string, NOT a YAML block scalar (`>` or `|`). It carries only the routing sentence(s) — the text the dispatcher matches on. `<example>…</example>` blocks (with `<commentary>`) do NOT go inline in the description: they live in a `## Examples` section at the end of the body, one block per paragraph (#887, #1157).
64
66
  - `tools` accepts BOTH comma-separated string (`Read, Edit, Write`) and JSON array (`["Read", "Edit", "Write"]`). Anthropic's own reference agents use array form; we use string form for consistency.
65
67
 
66
68
  **Body conventions** (from Anthropic's `plugins/plugin-dev/agents/*` reference set):
@@ -68,15 +70,25 @@ tools: Read, Grep, Glob, Bash # comma-separated string OR JSON array (bo
68
70
  - Length: 500–3000 words is the recommended range. Below 500 reads as under-specified; above 3000 reads as bloated.
69
71
  - 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.
70
72
 
71
- ## Model Selection & Cost Routing (#768)
73
+ ## Model Selection & Cost Routing (#768, #1614)
72
74
 
73
- `model:` is not just a compatibility field — it is a cost/quality dial per agent. Pick deliberately, don't default to `sonnet` everywhere.
75
+ Every agent pins `model:` AND `effort:` explicitly. `inherit` was the default until 2026-10-14 and cost the catalog its users: under a Fable lead, an inheriting agent ran on the most expensive model at the session's effort, and the fleet moved to private opus/medium agents (census in #1614: plugin share of dispatches fell from 61 % in the week of 15 September to 6 % in the week of 8 October).
74
76
 
75
- - **`haiku`** — cheap, fast, advisory/judge roles where the task is narrow classification or a single yes/no verdict, not open-ended reasoning. Precedent: `dialectic-deriver`, `skill-applied-judge`. Pin `haiku` when the agent's whole job is "read a short input, emit a structured verdict."
76
- - **`sonnet`** — an explicit cost cap, NOT a default. Pin it only when an agent must stay on the workhorse tier even in an Opus session, and state the reason inline. A bare `sonnet` on a working agent silently overrides the operator's session model — the failure mode that moved the implementation and review catalog to `inherit`.
77
- - **`inherit`** — **the default for the working catalog.** Lets the coordinator/session's active model tier flow through, so the agent runs at whatever tier the operator picked (an Opus session gives its implementers AND its reviewers Opus-quality judgment). Use it for implementation, test-writing, and review agents alike — `code-implementer`, `test-writer`, `security-reviewer`, `session-reviewer`, `db-specialist`, `ui-developer`, and the read-only analysis agents. Diverge only for a named cost/quality reason.
78
- - **`opus`** — reserve for agents whose task genuinely needs the strongest available reasoning (e.g. `ux-evaluator`) and where the cost is justified because the agent runs rarely (dispatched solo, not fanned out across a wave).
79
- - **Full model-ID pinning** (`claude-opus-5-5`, `claude-sonnet-5`, `claude-fable-5-20260101`, …) — only when the agent has a demonstrated dependency on a SPECIFIC model version, e.g. a reproducibility requirement that needs a dated snapshot, or a known behavioral regression on newer models for this agent's exact prompt. Pinning trades away automatic model-family upgrades — document the reason inline as a frontmatter comment when you do this.
77
+ | Role | model | effort | Agents |
78
+ |---|---|---|---|
79
+ | Implementation and review | `opus` | `medium` | `code-implementer`, `db-specialist`, `ui-developer`, `session-reviewer`, `security-reviewer`, `architect-reviewer` |
80
+ | Tests, docs, analysis | `sonnet` | `medium` | `test-writer`, `docs-writer`, `qa-strategist`, `analyst` |
81
+ | Narrow judges | `haiku` | `medium` | `eval-judge`, `skill-applied-judge`, `dialectic-deriver` |
82
+ | Rare solo evaluator | `opus` | `medium` | `ux-evaluator` (judges screenshots and AX trees against a rubric, dispatched alone, not fanned out) |
83
+
84
+ - **`effort` is required whenever `model` is not `inherit`** (validated by `checkAgentEffort` in `scripts/lib/agent-frontmatter.mjs`). The per-model default differs: Sonnet 5.5 defaults to `high`, Opus 5.5 to `medium`, so a Sonnet agent without `effort` thinks longer than an Opus one. `medium` follows the owner's standing instruction (2026-09-30); raise it only for a named reason in the agent.
85
+ - **`haiku`** — narrow classification or a single structured verdict over a short input. Whether read-only analysis roles move to Haiku is an open owner decision (#1614); do not switch them until it is made.
86
+ - **`sonnet`** — work that needs judgment but not the strongest reasoning: test gaps, docs, PRD and coverage analysis.
87
+ - **`opus`** — code changes and reviews, where a missed defect costs more than the tokens.
88
+ - **`inherit`** — only with a reason written into the agent (e.g. the agent must follow whatever model the operator chose). It also inherits the session's effort.
89
+ - **Full model-ID pinning** (`claude-opus-5-5`, `claude-sonnet-5`, `claude-fable-5-20260101`, …) — only for a demonstrated dependency on one model version (a reproducibility snapshot, a known regression on newer models). Document the reason inline as a frontmatter comment.
90
+
91
+ Whether `effort` from a **plugin** agent's frontmatter takes effect is not stated in the upstream docs; the #1614 acceptance smoke checks it per role. If it does not, the dispatcher passes `effort` as a dispatch parameter (Claude Code v2.1.292+).
80
92
 
81
93
  **Resolution order** (highest precedence first): `CLAUDE_CODE_SUBAGENT_MODEL` environment variable → the invocation-time model parameter (if the dispatcher passes one explicitly) → the agent's own frontmatter `model:` value. An agent's `model:` is therefore a default, not a guarantee — a session or environment override can supersede it.
82
94
 
@@ -90,6 +102,13 @@ Every agent definition with `repo-write` sandbox-tier (i.e. `Edit`/`Write` prese
90
102
 
91
103
  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.
92
104
 
105
+ **Sole exception — worktree mode (#1614).** Only `code-implementer` may stage its own files one by one and commit, and only when its prompt carries a line `WORKTREE-MODE: <absolute path> <branch>` that matches `git rev-parse --show-toplevel` and `git branch --show-current`; otherwise the ban applies unchanged. Coordinator duty: never grant the coordinator's own worktree, never put two agents in one worktree. The wave-executor never sets the line. A linked worktree has its own index, so the index race this ban prevents does not exist there. The commit hook briefly adds an entry to the shared stash via lint-staged; the agent itself never runs `git stash`. Push, merge, `git reset`, `git stash` and `git clean` stay banned. The exception lives in the agent's own Rules section, next to the unchanged ban line, so Check 10 still finds the ban. The detector `psa007-git-write` (`scripts/lib/wave-transcript-tail.mjs`) still reports every commit inside a wave; that is correct, because wave prompts never carry `WORKTREE-MODE`.
106
+
107
+ ## Waiting, Forks and Start Cost (#1615, #1616)
108
+
109
+ - **Waiting longer than 5 minutes does not belong in a subagent.** A subagent's prompt cache lives 5 minutes, so every longer wait (pipeline, remote run, rerun) rebuilds its whole context on the next turn (#1615 measured 250 M rewritten tokens in 14 days). The agent reports its intermediate state and ends; the coordinator waits with Monitor and then continues it with `SendMessage` (or dispatches a fresh one).
110
+ - **Fork or subagent.** A short task that needs the current conversation goes to a fork: it inherits system prompt, tools and history and reads the parent session's cache, so it does not pay the 60–80k token start context again. A task with its own file scope, worktree or model goes to a subagent. The wave-executor stays on subagents, because it needs scope boundaries.
111
+
93
112
  ## Escalation Channel (#1051)
94
113
 
95
114
  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:
package/docs/ci-setup.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  > **Maintainer-internal.** This document describes the maintainer's private CI mirror setup. It is not required for using the plugin.
4
4
 
5
+ GitHub's Linux/macOS test matrix is supplemented by two non-blocking Windows jobs on `windows-latest` (#1612): `test-windows-smoke` runs lint, typecheck and `scripts/ci/windows-smoke.mjs` (the product contract for Claude Code on Windows; it moves into `gate` after 10 green main runs), and `test-windows-suite` runs the full suite for information while the test-portability backlog is open. The fresh SessionStart smoke needs npm-registry access and reports unavailable network as unmeasurable.
6
+
5
7
  ## schema-drift-check job
6
8
 
7
9
  The `schema-drift-check` job compares the vendored `vault-frontmatter` schema
@@ -633,8 +635,42 @@ The router tries eligible aliases in configuration order, checking each with
633
635
  `offload doctor -H <alias> --brief --no-probe`. The alias selects a gate execution
634
636
  host; it is independent of the Git remote being pushed to. With no eligible
635
637
  host, no `offload` executable, or unavailable remote readiness/transport, the
636
- hook runs the same local full gate. A classified transport failure can first
637
- try the next configured host.
638
+ hook falls back locally. A classified transport failure can first try the next
639
+ configured host.
640
+
641
+ The local fallback depends on the push target (#1642):
642
+
643
+ - **A branch other than `main` on `origin`** (by remote name or its exact push
644
+ URL) takes the local **partial** gate, `scripts/lib/pre-push-local-partial.mjs`.
645
+ It computes the files changed since the merge-base with origin's default
646
+ branch and runs `node --check` and ESLint on the changed source files, plus
647
+ `vitest related --run` for all changed files. A red check blocks the push. The
648
+ full suite then runs in the MR pipeline on the pushed head SHA.
649
+ - **Everything else** (any push that includes `main` or a tag — every pushed ref counts, not only the first — the GitHub mirror, a push
650
+ by URL to another host, a hand invocation without a remote) runs the full
651
+ gate locally. No MR pipeline stands between those pushes and their result.
652
+ - The partial gate exits 10 and hands over to the full local gate when there is
653
+ no merge-base, when a source file was deleted or renamed, when `package.json`, `package-lock.json`, `vitest.config.*` or
654
+ `eslint.config.*` changed, or when `eslint`/`vitest` is missing from
655
+ `node_modules` (fail-closed). Its ledger event is
656
+ `orchestrator.quality_gate.{passed,failed}` with `variant: 'local-partial'`.
657
+ - Ceiling: `vitest related` follows the import graph. A test that reaches a
658
+ changed file only by spawning it (hooks, `.husky/`, CLIs) or by reading it
659
+ from disk (policy JSON, Markdown, fixtures; edited or deleted) is not
660
+ selected locally, and the MR pipeline catches that class. Only a deleted or
661
+ renamed source file (`.mjs`/`.cjs`/`.js`) falls back to the full gate (#1643).
662
+
663
+ `SO_GATE_HOSTS` overrides the host order for one push without a config commit:
664
+ `SO_GATE_HOSTS=hostA,hostB git push` tries exactly those aliases, in that order,
665
+ instead of the configured `remote-hosts` list (whitespace-only counts as unset).
666
+ Every alias must have a regular file `<alias>.env` in offload's host registry
667
+ (`${OFFLOAD_CONFIG_DIR:-$HOME/.config/remote-offload}/hosts/`, the same rule
668
+ `offload -H` uses) and match `^[A-Za-z0-9._-]+$`. An unknown or invalid alias,
669
+ or an override none of whose hosts can run the gate (not ready, transport
670
+ failure, no `offload`), blocks the push with exit 2 and does **not** fall back
671
+ to the local gate. The router logs the chosen host and its source (`config`,
672
+ `override`, or `fallback` to local) on stderr, and the remote gate's ledger
673
+ event carries `host` and `host_source`.
638
674
 
639
675
  On the remote checkout, the command checks out the pushed SHA again, verifies
640
676
  `HEAD` and a clean source tree, and runs `npm run --silent quality-gate`.
@@ -11,7 +11,7 @@ Guide for using Session Orchestrator with OpenAI Codex through Codex's public pl
11
11
 
12
12
  ## Installation
13
13
 
14
- **Recommended:** the short remote form (`codex plugin marketplace add <owner>/<repo>`) needs no local clone — see "Short-Form Marketplace Add" below. The steps below are the maintainer/local-clone path used by `scripts/codex-install.mjs`.
14
+ Two paths. The clone below is the complete install: it puts the runtime dependencies next to the plugin. The short remote form (`codex plugin marketplace add <owner>/<repo>`) needs no clone and takes two commands, but the installed plugin has no `node_modules`, so part of the plugin falls back or stops until you run `npm install` there — see "Short-Form Marketplace Add" below.
15
15
 
16
16
  Clone the repository, install its runtime dependencies, and run the installer from the plugin root:
17
17
 
@@ -34,7 +34,7 @@ A marketplace on the working checkout copies all of it into the Codex plugin cac
34
34
 
35
35
  It operates only through public Codex plugin commands; hook trust remains untouched.
36
36
 
37
- ### Short-Form Marketplace Add (Recommended — Verified 2026-09-04, codex-cli 0.144.4)
37
+ ### Short-Form Marketplace Add (Verified 2026-09-04, codex-cli 0.144.4; dependencies measured 2026-10-21, codex-cli 0.160.1)
38
38
 
39
39
  `codex plugin marketplace add --help` documents a short remote form:
40
40
 
@@ -42,7 +42,7 @@ It operates only through public Codex plugin commands; hook trust remains untouc
42
42
  codex plugin marketplace add owner/repo --ref main
43
43
  ```
44
44
 
45
- This is the recommended install path — no local clone needed. Confirmed end-to-end on codex-cli **0.144.4** (2026-09-04), against this repo's unchanged flat layout (`.codex-plugin/plugin.json` + `.claude-plugin/marketplace.json` at repo root, no `plugins/<name>/`):
45
+ This is the shortest install path — no local clone needed. Confirmed end-to-end on codex-cli **0.144.4** (2026-09-04), against this repo's unchanged flat layout (`.codex-plugin/plugin.json` + `.claude-plugin/marketplace.json` at repo root, no `plugins/<name>/`):
46
46
 
47
47
  ```
48
48
  $ codex plugin add session-orchestrator@kanevry --json
@@ -53,6 +53,13 @@ $ echo $?
53
53
 
54
54
  `codex plugin list --available --json --marketplace kanevry` confirms `installed: true, enabled: true` for the same layout — no `plugins/<name>/` restructuring was needed.
55
55
 
56
+ **No runtime dependencies on this path (measured 2026-10-21, codex-cli 0.160.1, isolated `CODEX_HOME`).** `marketplace add` and `plugin add` both exit 0, but the installed path (`~/.codex/plugins/cache/kanevry/session-orchestrator/<version>`) has no `node_modules`. The SessionStart hook, the Bash guards and `scripts/parse-config.mjs` still run (the destructive-command guard's `git stash` check falls back to a warning, because it needs `zx`). Everything else that needs a runtime dependency (`zx`, `zod`, `js-yaml`, `ajv`, `remark`, …) either falls back or stops:
57
+
58
+ - `owner.yaml` loads `js-yaml` lazily: when the file exists, owner preferences fall back to defaults and the process prints `WARN owner-yaml: 'js-yaml' is not installed … Run 'npm install' in the plugin directory`.
59
+ - Scripts that import a dependency at the top stop with `ERR_MODULE_NOT_FOUND` and no warning: the worktree helpers (`zx`), the learnings index (`zod`), the persona panel and the PRD archive (`js-yaml`), among others (18 files import `js-yaml` that way).
60
+
61
+ To restore them, run `npm install --omit=dev --ignore-scripts` in the `installedPath` that `codex plugin add --json` prints, and again after every update, because each version gets a new cache directory. The clone path above avoids this.
62
+
56
63
  **Historical note:** on codex-cli 0.141.0 (2026-08-28), the identical `plugin add` command failed against this same layout with `Error: plugin session-orchestrator was not found in marketplace kanevry`; upgrading to 0.144.4+ resolves it.
57
64
 
58
65
  ### Switching Marketplace Sources
@@ -160,9 +167,10 @@ $ strings -a "$(npm root -g)/@openai/codex/node_modules/@openai/codex-darwin-arm
160
167
  | Event | 0.144.4 | Wired here |
161
168
  |---|---|---|
162
169
  | `SessionStart` | yes | yes — banner + `on-session-start.mjs` |
163
- | `PostToolUse` | yes | yes — `loop-guard.mjs` |
170
+ | `PostToolUse` | yes | yes — `loop-guard.mjs`; `Bash`: `post-bash-write-verify.mjs` (warn-only, #1691) |
164
171
  | `SubagentStop`, `Stop` | yes | yes — `on-stop.mjs` |
165
- | `PreToolUse`, `SubagentStart` | yes | declared, **empty** (see below) |
172
+ | `PreToolUse` | yes | yes — `Bash`: destructive guard, staging fence, memory-propose audit, sessions-ledger guard, issue budget, `enforce-commands.mjs` (#1691); `pre-bash-templates-first.mjs` and the Edit/Write guards stay unwired (see below) |
173
+ | `SubagentStart` | yes | declared, **empty** |
166
174
  | `UserPromptSubmit`, `PermissionRequest`, `PreCompact`, `PostCompact` | yes | no — this repo has no handler for them |
167
175
  | `SessionEnd`, `Interrupt` | **no — event does not exist** | n/a |
168
176
  | `PostToolUseFailure`, `PostToolBatch`, `CwdChanged` | no — Claude-only | n/a |
@@ -171,26 +179,42 @@ $ strings -a "$(npm root -g)/@openai/codex/node_modules/@openai/codex-darwin-arm
171
179
 
172
180
  For the day `SessionEnd` does land: upstream caps it (and `Interrupt`) at a **1 s default / 3 s maximum** timeout, where every other event gets 600 s. `hooks/on-session-end.mjs` measures ~221 ms median, so it fits — but only just, and only while it stays that fast.
173
181
 
174
- ### Why our PreToolUse guards stay unwired — the reason, corrected
182
+ ### Which PreToolUse guards run on Codex — the reason, corrected
175
183
 
176
184
  Earlier revisions of this page said the handlers were unwired because "no Codex bridge delivers `tool_name`". **That was measuring the wrong thing** — it grepped our own adapter code rather than the Codex payload contract. There is no bridge because none is needed:
177
185
 
178
186
  - `pre-tool-use.command.input` REQUIRES `tool_name` and `tool_input`, alongside `cwd`, `hook_event_name`, `model`, `permission_mode`, `session_id`, `tool_use_id`, `transcript_path`, `turn_id`.
179
187
  - The deny envelope is `hookSpecificOutput.{hookEventName, permissionDecision, permissionDecisionReason}` — byte-identical to what `emitDeny()` already writes, and Codex enforces exactly that shape (its own error text: *"PreToolUse hook returned permissionDecision:deny without a non-empty permissionDecisionReason"*). Codex additionally rejects `permissionDecision: "allow"` and `"ask"`; our allow path is a bare `exit 0` with no stdout, so it is compatible.
180
188
 
181
- The real blocker is the **tool-name vocabulary**. Codex has no `Bash`, `Edit`, `Write` or `MultiEdit` tool — `strings -a <codex> | grep -c '"Bash"'` returns `0`; its tools are `shell`, `exec_command`, `unified_exec`, `apply_patch`, `update_plan`, `view_image`. Every PreToolUse guard in `hooks/` opens with an equality gate on a Claude tool name and returns `emitAllow()` otherwise, so wiring `pre-bash-destructive-guard.mjs` or `enforce-scope.mjs` today produces a hook that runs, matches nothing, and allows everything — **false enforcement, which is worse than a registered gap** (#919-P2 class).
189
+ Until 2026-10-20 this page named the **tool-name vocabulary** as the real blocker: Codex's model-facing tools are `shell`, `exec_command`, `unified_exec`, `apply_patch`, `update_plan`, `view_image`, and `strings -a <codex> | grep -c '"Bash"'` returned `0` (codex-cli 0.144.4). **For the shell tool that is refuted** (#1669, measured 2026-10-20 on codex-cli 0.160.1 with a logging PreToolUse hook under `codex exec`): a shell call reaches the hook as `"tool_name":"Bash"` with `"tool_input":{"command":"<string>"}`, and `matcher: "Bash"` fires. Codex maps its shell tool to the Claude name at the hook boundary, so the Bash guards need no tool-name map. The allow-only `pre-bash-staging-fence.mjs` is wired on that basis. For the Edit/Write matchers (`apply_patch`) the vocabulary question is still unmeasured.
190
+
191
+ **Codex honours a deny** (#1691, measured 2026-10-20 on codex-cli 0.160.1). `codex exec` with `pre-bash-destructive-guard.mjs` as the only PreToolUse hook and the prompt `printf x > CLAUDE.md` logged `Command blocked by PreToolUse hook: Destructive command blocked: '> CLAUDE.md' (rule: redirect-truncate-protected)`, and `CLAUDE.md` stayed unchanged. The control run with `hooks.PreToolUse=[]` ran the command and the file became `x`. The measured payload carries `session_id`, `turn_id`, `cwd` (the session workdir, which is also the hook's process cwd), `tool_name: "Bash"`, `tool_input.command` and `transcript_path: null`; PostToolUse adds `tool_response: ""`. A real Codex session exports no `CLAUDE_*` variables.
192
+
193
+ Each Bash hook was then fed that payload and wired only where it enforces on it:
194
+
195
+ | Hook | On Codex | Why |
196
+ |---|---|---|
197
+ | `pre-bash-destructive-guard.mjs` | wired | denies `> CLAUDE.md` |
198
+ | `pre-bash-sessions-ledger-guard.mjs` | wired | denies a direct write to `.orchestrator/metrics/sessions.jsonl` |
199
+ | `pre-bash-issue-budget.mjs` | wired | with a cap of 1 the second `glab issue create` is denied and parked |
200
+ | `enforce-commands.mjs` | wired | applies `blockedCommands` from `.codex/wave-scope.json` |
201
+ | `pre-bash-memory-propose-audit.mjs` | wired | appends its audit event (observe-only by design) |
202
+ | `post-bash-write-verify.mjs` (PostToolUse) | wired | reports a write outside `allowedPaths` (warn-only by design) |
203
+ | `pre-bash-templates-first.mjs` | **not wired** | it can only deny there: the template-Read proof needs `transcript_path`, which Codex sends as `null`, and `/templates-ack` needs a `claude` parent process |
204
+ | `post-bash-issue-budget-refund.mjs` | n/a | runs on `PostToolUseFailure`, which Codex does not have; a failed create keeps its budget slot |
182
205
 
183
- Consequence to state plainly: **PSA-003 (destructive-command guard) and the file-scope guard are behavioural only on Codex today.** The repair is a tool-name map (`shell`/`exec_command`/`unified_exec` → `Bash`) for the Bash guards, plus an `apply_patch` payload adapter for the Edit/Write matchers specifically. Only the second half needs the adapter.
206
+ What this still leaves open: **the file-scope guard is behavioural only on Codex today**, because the Edit/Write guards need an `apply_patch` payload adapter. `tests/hooks/codex-bash-guards-wiring.test.mjs` runs every registered Bash command on the measured payload.
184
207
 
185
208
  These per-event gaps are tracked as documented asymmetries in `scripts/lib/validate/check-hooks-symmetry.mjs` (Check 6, `handlerAsymmetries`) — an UNDOCUMENTED one-platform-only handler fails validation.
186
209
 
187
- An empty `PreToolUse` or `SubagentStart` array means the event belongs to the validated Codex surface but currently has no payload-compatible handler. It does not mean installation or hook trust failed.
210
+ An empty `SubagentStart` array means the event belongs to the validated Codex surface but currently has no payload-compatible handler. It does not mean installation or hook trust failed.
188
211
 
189
212
  ## Usage
190
213
 
191
214
  After installation or refresh, start a fresh task. In the desktop composer, open the skill picker, search for `go` or `close`, and select the matching **Session Orchestrator** entry. In Codex CLI or the IDE extension, use `/skills` or mention the namespaced skill directly in your prompt. [OpenAI skill invocation](https://learn.chatgpt.com/docs/build-skills)
192
215
 
193
216
  ```text
217
+ $session-orchestrator:bootstrap # once per repository, before the first session
194
218
  $session-orchestrator:session # start with the deep default
195
219
  $session-orchestrator:session housekeeping # maintenance session
196
220
  $session-orchestrator:session deep # explicit deep session
@@ -57,7 +57,7 @@ Codex uses the curated six-event project subset `SessionStart`, `PreToolUse`, `P
57
57
 
58
58
  - **Output Styles (3):** `session-report`, `wave-summary`, `finding-report`.
59
59
  - **Policy & rules:** `.orchestrator/policy/blocked-commands.json` (destructive-command rules); `.claude/rules/parallel-sessions.md` (PSA-001..PSA-004).
60
- - **Destructive-command guard.** On Claude Code, the active `hooks/pre-bash-destructive-guard.mjs` applies `.orchestrator/policy/blocked-commands.json` in the main session and in subagent waves. The policy has 12 blocking rules (`git reset --hard`, `rm -rf`, `git push --force`, deletion of `.orchestrator/metrics/**`, and more) and 4 warning rules. Cursor and Pi use event bridges with documented limits; Codex does not enforce this guard. Scope `enforcement: warn` or `off` does not change the separate destructive-command policy — see [Platform support](../README.md#platform-support). Where the hook is active, bypass it per session only for intentional maintenance by setting `allow-destructive-ops: true` in Session Config. The rule source of truth is [`.claude/rules/parallel-sessions.md`](https://github.com/Kanevry/session-orchestrator/blob/main/.claude/rules/parallel-sessions.md) (PSA-003), vendored to consumer repos via `/bootstrap`.
60
+ - **Destructive-command guard.** On Claude Code, the active `hooks/pre-bash-destructive-guard.mjs` applies `.orchestrator/policy/blocked-commands.json` in the main session and in subagent waves. The policy has 13 blocking rules (`git reset --hard`, `rm -rf`, `git push --force`, deletion of `.orchestrator/metrics/**`, and more) and 4 warning rules. Cursor and Pi use event bridges with documented limits; On Codex the same hook runs as a `PreToolUse` Bash hook, and Codex honours its deny (measured 2026-10-20, codex-cli 0.160.1, #1691). Scope `enforcement: warn` or `off` does not change the separate destructive-command policy — see [Platform support](../README.md#platform-support). Where the hook is active, bypass it per session only for intentional maintenance by setting `allow-destructive-ops: true` in Session Config. The rule source of truth is [`.claude/rules/parallel-sessions.md`](https://github.com/Kanevry/session-orchestrator/blob/main/.claude/rules/parallel-sessions.md) (PSA-003), vendored to consumer repos via `/bootstrap`.
61
61
  - **Import probe.** `hooks/post-edit-import-probe.mjs` (PostToolUse on `Edit`/`Write`/`MultiEdit`) guards the other direction: a hook-reachable helper saved in a broken intermediate state makes *every* Bash/Edit/Write call fail with an internal hook error, host-wide, for every session sharing the working copy. Right after such a file is saved the probe runs ESLint `no-undef` on it (plus a child-process `import()` for `scripts/lib/**`) and reports the blast radius; it never blocks and always exits 0. It only fires for files listed in the committed allowlist [`hooks/_lib/hook-import-set.json`](../hooks/_lib/hook-import-set.json), regenerated by `node scripts/generate-hook-import-set.mjs`. Kill switch: `SO_DISABLED_HOOKS=post-edit-import-probe`.
62
62
  - **Process-group kill + orphan reaper.** Both quality-gate paths spawn their commands `detached: true`, so the whole process GROUP is killed on timeout (SIGTERM → grace → SIGKILL, exit 124) instead of only the shell — the shell's own children used to be reparented to PID 1 and keep running. Every gate process this repo starts is recorded in `.orchestrator/runtime/gate-processes.jsonl`; `hooks/post-tool-batch-wave-signal.mjs` and `hooks/on-stop.mjs` trigger a throttled, detached orphan scan that reaps only what that register claims. Ships inert (`reaper.enabled: false`, `reaper.mode: report`) until its firing rate is measured — rule [`.claude/rules/host-resources.md`](../.claude/rules/host-resources.md) § HR-107, rationale [ADR-0015](adr/0015-process-group-kill-and-orphan-reaper.md), audit trail `.orchestrator/metrics/reaper-audit.jsonl`.
63
63
  - **ADR-0016 Cross-session messaging.** Adopt for the live cross-session axis (CSM-001..005), Spike for Remote Control (#1056, closed negative); anchors "entries vs messages" — files hold state, messages are hints — rationale [ADR-0016](adr/0016-cross-session-messaging.md).
@@ -72,13 +72,24 @@ Codex uses the curated six-event project subset `SessionStart`, `PreToolUse`, `P
72
72
 
73
73
  `scripts/harness-audit.mjs` runs **9 deterministic categories / 38 checks** over a repo and emits `.orchestrator/metrics/audit.jsonl`. Category 8 ("Large-Codebase Readiness") operationalises Anthropic's [Claude Code large-codebase best-practices](https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start) checklist — layered `CLAUDE.md` (or `AGENTS.md`), codebase-map presence, LSP/code-intelligence wiring, scoped test/lint commands, `permissions.deny`, and root-file leanness — as scored signals you can run on yourself and on consumer repos. Category 9 ("Skill-Health Surfacing") surfaces the #648 per-skill health pipeline — telemetry hygiene, scorer wiring, and an advisory-only verdict tally that never affects points; non-adoption always scores full points. These checks are intentionally orthogonal to repo-audit's baseline-compliance pass/fail; both surfaces ship.
74
74
 
75
+ ## Design choices
76
+
77
+ - **The wave order is deliberate.** Discovery runs first so every implementer starts from the same picture of the code. Impl-Core runs before Impl-Polish so the structure exists before anything integrates against it. The Quality wave simplifies generated code *before* tests are written; write the tests first and they assert whatever the model produced, so changing it later means rewriting the tests too.
78
+ - **Checks run after each implementation wave, not only at the end.** A mistake caught after wave 2 costs one wave. The same mistake found at `/close` has already been copied into every wave after it. Findings below the configured confidence threshold are not shown to you.
79
+ - **A crash does not lose the session.** `STATE.md` records which wave finished and what deviated from the plan. The next `/session` offers to continue from the last completed wave.
80
+ - **Two sessions in one working copy is treated as a real risk.** Two people, or two of your own sessions, in the same checkout share one git index, one filesystem and one `STATE.md`, and neither can see the other's uncommitted work. A heartbeat session lock, per-agent file-scope manifests, and the rules in [`.claude/rules/parallel-sessions.md`](../.claude/rules/parallel-sessions.md) exist for exactly that case.
81
+ - **Guards run where the harness supports them, and the [platform table](../README.md#platform-support) says where they do not.** The destructive-command policy (13 rules block, 4 warn) runs as a real hook on Claude Code and Codex and as a bridge on Cursor and Pi; file-scope enforcement is a hook on Claude Code, a bridge on Cursor and Pi, and instructions only on Codex (see [Other surfaces](#other-surfaces)).
82
+ - **What it learns is opt-in and readable.** Every session appends a record. After 5 or more sessions, `/evolve analyze` proposes patterns with a confidence score; you read them and delete the ones you disagree with. Nothing is applied without you.
83
+ - **GitLab and GitHub, both fully.** It detects which one your remote points at and drives issues and merge or pull requests for either.
84
+ - **No build step.** Skills, commands and agents are Markdown with YAML frontmatter; the code that dispatches, validates and records runs in `scripts/lib/*.mjs` and `hooks/*.mjs`. When a session does something you did not expect, you can open the file that decided it.
85
+
75
86
  ## Comparisons
76
87
 
77
88
  Moved here from the README so that a claim about another project can carry its measurement next to it. Every row below names when and how it was measured; rows that could not be measured were **removed rather than softened** — an unverifiable comparison row is worse than none.
78
89
 
79
90
  ### vs. `open-gsd/gsd-core`
80
91
 
81
- Surface counts measured 2026-09-06 by this repo's 360° ecosystem probe (`docs/audits/2026-09-06-360-audit/w1/d11-github-overlap.md`); session-orchestrator's own counts measured the same day with the commands listed in the [README](../README.md#what-you-get).
92
+ Surface counts measured 2026-09-06 by this repo's 360° ecosystem probe (GitHub-overlap report of the 2026-09-06 360° audit; audit reports stay in the private GitLab repository and are not part of the public mirror); session-orchestrator's own counts measured the same day with the commands listed in the [README](../README.md#what-you-get).
82
93
 
83
94
  | Axis | session-orchestrator | `open-gsd/gsd-core` |
84
95
  |---|---|---|