session-orchestrator 3.16.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 (762) hide show
  1. package/.claude-plugin/marketplace.json +29 -0
  2. package/.claude-plugin/plugin.json +18 -0
  3. package/.codex-plugin/agents/explorer.toml +14 -0
  4. package/.codex-plugin/agents/session-reviewer.toml +23 -0
  5. package/.codex-plugin/agents/wave-worker.toml +15 -0
  6. package/.codex-plugin/config.toml +20 -0
  7. package/.codex-plugin/plugin.json +37 -0
  8. package/.cursor/rules/000-session-orchestrator.mdc +73 -0
  9. package/.cursor/rules/010-session-workflow.mdc +170 -0
  10. package/.cursor/rules/020-quality-gates.mdc +128 -0
  11. package/.cursor/rules/030-wave-execution.mdc +216 -0
  12. package/.cursor/rules/040-discovery.mdc +242 -0
  13. package/.cursor/rules/050-plan.mdc +235 -0
  14. package/.cursor/rules/060-evolve.mdc +232 -0
  15. package/.cursor/rules/070-gitlab-ops.mdc +246 -0
  16. package/.cursor/rules/080-ecosystem-health.mdc +145 -0
  17. package/.mcp.json +8 -0
  18. package/CHANGELOG.md +1544 -0
  19. package/LICENSE +21 -0
  20. package/NOTICE +64 -0
  21. package/README.md +242 -0
  22. package/SECURITY.md +90 -0
  23. package/agents/AGENTS.md +136 -0
  24. package/agents/analyst.md +99 -0
  25. package/agents/architect-reviewer.md +93 -0
  26. package/agents/code-implementer.md +106 -0
  27. package/agents/db-specialist.md +104 -0
  28. package/agents/dialectic-deriver.md +139 -0
  29. package/agents/docs-writer.md +113 -0
  30. package/agents/eval-judge.md +146 -0
  31. package/agents/memory-proposal-collector.md +297 -0
  32. package/agents/qa-strategist.md +102 -0
  33. package/agents/schemas/analyst.schema.json +46 -0
  34. package/agents/schemas/architect-reviewer.schema.json +50 -0
  35. package/agents/schemas/code-implementer.schema.json +61 -0
  36. package/agents/schemas/db-specialist.schema.json +80 -0
  37. package/agents/schemas/docs-writer.schema.json +56 -0
  38. package/agents/schemas/persona-panel-sidecar.schema.json +245 -0
  39. package/agents/schemas/qa-strategist.schema.json +46 -0
  40. package/agents/schemas/security-reviewer.schema.json +86 -0
  41. package/agents/schemas/session-reviewer.schema.json +69 -0
  42. package/agents/schemas/test-writer.schema.json +69 -0
  43. package/agents/schemas/ui-developer.schema.json +90 -0
  44. package/agents/schemas/ux-evaluator.schema.json +51 -0
  45. package/agents/security-reviewer.md +236 -0
  46. package/agents/session-reviewer.md +201 -0
  47. package/agents/skill-applied-judge.md +122 -0
  48. package/agents/test-writer.md +123 -0
  49. package/agents/ui-developer.md +109 -0
  50. package/agents/ux-evaluator.md +161 -0
  51. package/assets/icon.svg +11 -0
  52. package/assets/og-card.png +0 -0
  53. package/assets/og-card.svg +47 -0
  54. package/commands/autopilot-multi.md +74 -0
  55. package/commands/autopilot.md +80 -0
  56. package/commands/bootstrap.md +56 -0
  57. package/commands/brainstorm.md +48 -0
  58. package/commands/close.md +24 -0
  59. package/commands/debug.md +36 -0
  60. package/commands/discovery.md +32 -0
  61. package/commands/dispatcher.md +59 -0
  62. package/commands/eval.md +28 -0
  63. package/commands/evolve.md +10 -0
  64. package/commands/go.md +41 -0
  65. package/commands/grill.md +45 -0
  66. package/commands/harness-audit.md +26 -0
  67. package/commands/memory-cleanup.md +25 -0
  68. package/commands/persona-panel.md +121 -0
  69. package/commands/plan.md +15 -0
  70. package/commands/portfolio.md +97 -0
  71. package/commands/reconcile.md +23 -0
  72. package/commands/repo-audit.md +24 -0
  73. package/commands/session.md +30 -0
  74. package/commands/spinout.md +15 -0
  75. package/commands/sunset-review.md +27 -0
  76. package/commands/templates-ack.md +96 -0
  77. package/commands/test.md +97 -0
  78. package/docs/README.md +105 -0
  79. package/docs/USER-GUIDE.md +1403 -0
  80. package/docs/ci-setup.md +81 -0
  81. package/docs/codex-setup.md +142 -0
  82. package/docs/components.md +74 -0
  83. package/docs/cursor-setup.md +104 -0
  84. package/docs/events-schema.md +81 -0
  85. package/docs/migration-v3.md +148 -0
  86. package/docs/owner-config-schema.md +154 -0
  87. package/docs/persona-panel.md +433 -0
  88. package/docs/pi-setup.md +115 -0
  89. package/docs/plugin-architecture-v3.md +296 -0
  90. package/docs/pm-skills-marketplace.md +114 -0
  91. package/docs/policy-cache-validation-2026-04-28.md +118 -0
  92. package/docs/rule-authoring.md +316 -0
  93. package/docs/session-config-reference.md +1439 -0
  94. package/docs/session-config-template.md +961 -0
  95. package/docs/vault-docs-architecture.md +297 -0
  96. package/hooks/_lib/lock-bootstrap.mjs +272 -0
  97. package/hooks/_lib/lock-reconcile.mjs +93 -0
  98. package/hooks/_lib/profile-gate.mjs +95 -0
  99. package/hooks/_lib/transcript-history.mjs +211 -0
  100. package/hooks/agent-teams-h3-test.sh +362 -0
  101. package/hooks/config-protection.mjs +0 -0
  102. package/hooks/cwd-change-restore.mjs +131 -0
  103. package/hooks/enforce-commands.mjs +179 -0
  104. package/hooks/enforce-scope.mjs +273 -0
  105. package/hooks/hooks-codex.json +60 -0
  106. package/hooks/hooks-cursor.json +15 -0
  107. package/hooks/hooks-pi.json +115 -0
  108. package/hooks/hooks.json +215 -0
  109. package/hooks/loop-guard.mjs +260 -0
  110. package/hooks/on-session-end.mjs +217 -0
  111. package/hooks/on-session-start.mjs +660 -0
  112. package/hooks/on-stop.mjs +294 -0
  113. package/hooks/operator-steer.mjs +64 -0
  114. package/hooks/post-edit-validate.mjs +225 -0
  115. package/hooks/post-subagent-discovery-validator.mjs +398 -0
  116. package/hooks/post-tool-batch-wave-signal.mjs +328 -0
  117. package/hooks/post-tool-failure-corrective-context.mjs +248 -0
  118. package/hooks/post-tooluse-frontend-slop.mjs +184 -0
  119. package/hooks/pre-bash-destructive-guard.mjs +515 -0
  120. package/hooks/pre-bash-memory-propose-audit.mjs +206 -0
  121. package/hooks/pre-bash-staging-fence.mjs +223 -0
  122. package/hooks/pre-bash-templates-first.mjs +404 -0
  123. package/hooks/run-node.sh +72 -0
  124. package/hooks/skill-invocation-telemetry.mjs +99 -0
  125. package/hooks/subagent-telemetry.mjs +249 -0
  126. package/hooks/wave-scope-commit-guard.mjs +191 -0
  127. package/monitors/monitors.json +14 -0
  128. package/output-styles/finding-report.md +48 -0
  129. package/output-styles/session-report.md +53 -0
  130. package/output-styles/wave-summary.md +38 -0
  131. package/package.json +94 -0
  132. package/pi/extensions/session-orchestrator.ts +25 -0
  133. package/pi/prompts/autopilot-multi.md +12 -0
  134. package/pi/prompts/autopilot.md +12 -0
  135. package/pi/prompts/bootstrap.md +12 -0
  136. package/pi/prompts/brainstorm.md +12 -0
  137. package/pi/prompts/close.md +11 -0
  138. package/pi/prompts/debug.md +12 -0
  139. package/pi/prompts/discovery.md +12 -0
  140. package/pi/prompts/dispatcher.md +12 -0
  141. package/pi/prompts/eval.md +12 -0
  142. package/pi/prompts/evolve.md +12 -0
  143. package/pi/prompts/go.md +12 -0
  144. package/pi/prompts/grill.md +12 -0
  145. package/pi/prompts/harness-audit.md +12 -0
  146. package/pi/prompts/memory-cleanup.md +12 -0
  147. package/pi/prompts/persona-panel.md +12 -0
  148. package/pi/prompts/plan.md +12 -0
  149. package/pi/prompts/portfolio.md +12 -0
  150. package/pi/prompts/reconcile.md +12 -0
  151. package/pi/prompts/repo-audit.md +12 -0
  152. package/pi/prompts/session.md +12 -0
  153. package/pi/prompts/spinout.md +12 -0
  154. package/pi/prompts/sunset-review.md +12 -0
  155. package/pi/prompts/templates-ack.md +12 -0
  156. package/pi/prompts/test.md +12 -0
  157. package/rules/_index.md +51 -0
  158. package/rules/always-on/commit-discipline.md +26 -0
  159. package/rules/always-on/npm-quality-gates.md +26 -0
  160. package/rules/always-on/parallel-sessions.md +43 -0
  161. package/rules/opt-in-domain/prompt-caching.md +270 -0
  162. package/rules/opt-in-stack/backend-data.md +188 -0
  163. package/rules/opt-in-stack/backend.md +390 -0
  164. package/rules/opt-in-stack/frontend.md +98 -0
  165. package/rules/opt-in-stack/security-web.md +194 -0
  166. package/rules/opt-in-stack/swift.md +65 -0
  167. package/scripts/archive-closed-prds.mjs +416 -0
  168. package/scripts/autopilot-multi.mjs +802 -0
  169. package/scripts/autopilot.mjs +383 -0
  170. package/scripts/backfill-abandoned-sessions.mjs +265 -0
  171. package/scripts/backfill-learnings-expires.mjs +196 -0
  172. package/scripts/backfill-learnings.mjs +203 -0
  173. package/scripts/backfill-sessions.mjs +282 -0
  174. package/scripts/check-doc-consistency.sh +279 -0
  175. package/scripts/check-package-manager.mjs +445 -0
  176. package/scripts/ci/assert-vitest-green.mjs +267 -0
  177. package/scripts/codex-install.mjs +435 -0
  178. package/scripts/compute-grounding-injection.sh +186 -0
  179. package/scripts/cursor-install.mjs +113 -0
  180. package/scripts/dialectic-deriver.mjs +573 -0
  181. package/scripts/emit-event.mjs +160 -0
  182. package/scripts/emit-session.mjs +212 -0
  183. package/scripts/eval-session.mjs +262 -0
  184. package/scripts/export-hw-learnings.mjs +437 -0
  185. package/scripts/gc-stale-worktrees.mjs +666 -0
  186. package/scripts/generate-pi-prompts.mjs +127 -0
  187. package/scripts/harness-audit.mjs +287 -0
  188. package/scripts/lib/agent-frontmatter.mjs +266 -0
  189. package/scripts/lib/agent-output-schema.mjs +166 -0
  190. package/scripts/lib/agent-status.mjs +303 -0
  191. package/scripts/lib/ajv-loader.mjs +34 -0
  192. package/scripts/lib/auto-dialectic.mjs +382 -0
  193. package/scripts/lib/auto-dream.mjs +471 -0
  194. package/scripts/lib/autonomy/suitability.mjs +212 -0
  195. package/scripts/lib/autopilot/dep-graph.mjs +417 -0
  196. package/scripts/lib/autopilot/durable-telemetry.mjs +121 -0
  197. package/scripts/lib/autopilot/flags.mjs +104 -0
  198. package/scripts/lib/autopilot/kill-switches.mjs +174 -0
  199. package/scripts/lib/autopilot/loop.mjs +320 -0
  200. package/scripts/lib/autopilot/mr-draft.mjs +520 -0
  201. package/scripts/lib/autopilot/multi-killswitch.mjs +184 -0
  202. package/scripts/lib/autopilot/recent-runs.mjs +106 -0
  203. package/scripts/lib/autopilot/stall-sampler.mjs +97 -0
  204. package/scripts/lib/autopilot/telemetry.mjs +224 -0
  205. package/scripts/lib/autopilot/worktree-pipeline.mjs +605 -0
  206. package/scripts/lib/autopilot-telemetry.mjs +11 -0
  207. package/scripts/lib/autopilot.mjs +39 -0
  208. package/scripts/lib/backlog-scan.mjs +179 -0
  209. package/scripts/lib/bootstrap-lock-freshness.mjs +260 -0
  210. package/scripts/lib/bootstrap-lock-refresh.mjs +186 -0
  211. package/scripts/lib/build-live-signals.mjs +150 -0
  212. package/scripts/lib/ci-status-banner.mjs +425 -0
  213. package/scripts/lib/claude-md-budget-lint.mjs +246 -0
  214. package/scripts/lib/cli-flags.mjs +158 -0
  215. package/scripts/lib/codex/plugin-contract.mjs +610 -0
  216. package/scripts/lib/cold-start-detector.mjs +240 -0
  217. package/scripts/lib/command-blocker.mjs +458 -0
  218. package/scripts/lib/common.mjs +333 -0
  219. package/scripts/lib/config/auto-dream.mjs +77 -0
  220. package/scripts/lib/config/block-header.mjs +94 -0
  221. package/scripts/lib/config/broken-window.mjs +114 -0
  222. package/scripts/lib/config/coercers.mjs +248 -0
  223. package/scripts/lib/config/cold-start.mjs +92 -0
  224. package/scripts/lib/config/config-protection.mjs +120 -0
  225. package/scripts/lib/config/cross-repo.mjs +104 -0
  226. package/scripts/lib/config/custom-phases.mjs +213 -0
  227. package/scripts/lib/config/dialectic.mjs +92 -0
  228. package/scripts/lib/config/discovery-validator.mjs +75 -0
  229. package/scripts/lib/config/dispatcher-autonomy-capture.mjs +240 -0
  230. package/scripts/lib/config/dispatcher-autonomy.mjs +152 -0
  231. package/scripts/lib/config/docs-orchestrator.mjs +90 -0
  232. package/scripts/lib/config/docs-staleness.mjs +96 -0
  233. package/scripts/lib/config/drift-check.mjs +155 -0
  234. package/scripts/lib/config/eval.mjs +130 -0
  235. package/scripts/lib/config/events-rotation.mjs +74 -0
  236. package/scripts/lib/config/evolve.mjs +308 -0
  237. package/scripts/lib/config/frontend-slop-hook.mjs +104 -0
  238. package/scripts/lib/config/gitlab-portfolio.mjs +150 -0
  239. package/scripts/lib/config/handover-gate.mjs +106 -0
  240. package/scripts/lib/config/host-paths.mjs +76 -0
  241. package/scripts/lib/config/io.mjs +54 -0
  242. package/scripts/lib/config/loop-guard.mjs +117 -0
  243. package/scripts/lib/config/memory.mjs +150 -0
  244. package/scripts/lib/config/persona-gate-wave.mjs +258 -0
  245. package/scripts/lib/config/reconcile.mjs +205 -0
  246. package/scripts/lib/config/section-extractor.mjs +100 -0
  247. package/scripts/lib/config/skill-evolution.mjs +112 -0
  248. package/scripts/lib/config/slopcheck.mjs +99 -0
  249. package/scripts/lib/config/state-md-lock.mjs +83 -0
  250. package/scripts/lib/config/templates-first.mjs +94 -0
  251. package/scripts/lib/config/test.mjs +113 -0
  252. package/scripts/lib/config/vault-integration.mjs +201 -0
  253. package/scripts/lib/config/vault-mirror-quality.mjs +99 -0
  254. package/scripts/lib/config/vault-staleness.mjs +84 -0
  255. package/scripts/lib/config/vault-sync.mjs +96 -0
  256. package/scripts/lib/config/verification-auto-fix.mjs +84 -0
  257. package/scripts/lib/config/wave-reviewers.mjs +133 -0
  258. package/scripts/lib/config-schema.mjs +345 -0
  259. package/scripts/lib/config.mjs +474 -0
  260. package/scripts/lib/convergence-monitor.mjs +389 -0
  261. package/scripts/lib/coordinator-snapshot.mjs +371 -0
  262. package/scripts/lib/crypto-digest-utils.mjs +91 -0
  263. package/scripts/lib/discovery/helpers.mjs +127 -0
  264. package/scripts/lib/discovery/triage-state.mjs +279 -0
  265. package/scripts/lib/dispatcher/cli.mjs +257 -0
  266. package/scripts/lib/dispatcher/enumerate.mjs +243 -0
  267. package/scripts/lib/dispatcher/rank.mjs +363 -0
  268. package/scripts/lib/ecosystem-health.mjs +224 -0
  269. package/scripts/lib/ecosystem-wizard/ci-detector.mjs +18 -0
  270. package/scripts/lib/ecosystem-wizard/config-parser.mjs +54 -0
  271. package/scripts/lib/ecosystem-wizard/config-writer.mjs +287 -0
  272. package/scripts/lib/ecosystem-wizard/package-manager-detector.mjs +42 -0
  273. package/scripts/lib/ecosystem-wizard/wizard-prompt.mjs +246 -0
  274. package/scripts/lib/ecosystem-wizard.mjs +48 -0
  275. package/scripts/lib/env-check.mjs +89 -0
  276. package/scripts/lib/eval/engine.mjs +605 -0
  277. package/scripts/lib/eval/judge.mjs +433 -0
  278. package/scripts/lib/eval/report.mjs +367 -0
  279. package/scripts/lib/eval/schema.mjs +618 -0
  280. package/scripts/lib/eval/session-resolve.mjs +137 -0
  281. package/scripts/lib/eval/sink.mjs +77 -0
  282. package/scripts/lib/events-rotation.mjs +86 -0
  283. package/scripts/lib/events-schema.mjs +81 -0
  284. package/scripts/lib/events.mjs +80 -0
  285. package/scripts/lib/evolve/autonomy-verdict.mjs +461 -0
  286. package/scripts/lib/evolve/autopilot-effectiveness.mjs +293 -0
  287. package/scripts/lib/exclusivity-matrix.mjs +68 -0
  288. package/scripts/lib/fetch-baseline.mjs +311 -0
  289. package/scripts/lib/file-lock.mjs +512 -0
  290. package/scripts/lib/frontend-detect/detect.mjs +138 -0
  291. package/scripts/lib/frontend-detect/rules.mjs +295 -0
  292. package/scripts/lib/frontmatter-guard.mjs +241 -0
  293. package/scripts/lib/gates/echo-stub-detect.mjs +39 -0
  294. package/scripts/lib/gates/gate-baseline.mjs +42 -0
  295. package/scripts/lib/gates/gate-full.mjs +85 -0
  296. package/scripts/lib/gates/gate-helpers.mjs +231 -0
  297. package/scripts/lib/gates/gate-incremental.mjs +76 -0
  298. package/scripts/lib/gates/gate-per-file.mjs +55 -0
  299. package/scripts/lib/gitlab-ops/stale-mr-sweep.mjs +447 -0
  300. package/scripts/lib/gitlab-portfolio/aggregator.mjs +383 -0
  301. package/scripts/lib/gitlab-portfolio/cli.mjs +428 -0
  302. package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +289 -0
  303. package/scripts/lib/gitlab-portfolio/vcs-detect.mjs +182 -0
  304. package/scripts/lib/handover-gate.mjs +222 -0
  305. package/scripts/lib/hardening.mjs +43 -0
  306. package/scripts/lib/hardware-pattern-detector.mjs +238 -0
  307. package/scripts/lib/harness-audit/categories/category1.mjs +123 -0
  308. package/scripts/lib/harness-audit/categories/category2.mjs +145 -0
  309. package/scripts/lib/harness-audit/categories/category3.mjs +143 -0
  310. package/scripts/lib/harness-audit/categories/category4.mjs +202 -0
  311. package/scripts/lib/harness-audit/categories/category5.mjs +152 -0
  312. package/scripts/lib/harness-audit/categories/category6.mjs +211 -0
  313. package/scripts/lib/harness-audit/categories/category7.mjs +125 -0
  314. package/scripts/lib/harness-audit/categories/category8.mjs +328 -0
  315. package/scripts/lib/harness-audit/categories/category9.mjs +294 -0
  316. package/scripts/lib/harness-audit/categories/helpers.mjs +165 -0
  317. package/scripts/lib/harness-audit/categories.mjs +19 -0
  318. package/scripts/lib/historical-guard.mjs +15 -0
  319. package/scripts/lib/host-identity.mjs +262 -0
  320. package/scripts/lib/instruction-budget-guard.mjs +332 -0
  321. package/scripts/lib/io.mjs +304 -0
  322. package/scripts/lib/issue-close-strip-labels.mjs +161 -0
  323. package/scripts/lib/language-mappers/README.md +57 -0
  324. package/scripts/lib/language-mappers/index.mjs +165 -0
  325. package/scripts/lib/language-mappers/markdown.mjs +149 -0
  326. package/scripts/lib/language-mappers/python.mjs +249 -0
  327. package/scripts/lib/language-mappers/swift.mjs +201 -0
  328. package/scripts/lib/language-mappers/typescript.mjs +433 -0
  329. package/scripts/lib/learnings/expiry-sweep.mjs +164 -0
  330. package/scripts/lib/learnings/filters.mjs +43 -0
  331. package/scripts/lib/learnings/io.mjs +255 -0
  332. package/scripts/lib/learnings/schema.mjs +518 -0
  333. package/scripts/lib/learnings/surface.mjs +207 -0
  334. package/scripts/lib/learnings.mjs +42 -0
  335. package/scripts/lib/lock-reaper.mjs +648 -0
  336. package/scripts/lib/locks/index.mjs +31 -0
  337. package/scripts/lib/locks/lock-body.mjs +62 -0
  338. package/scripts/lib/locks/staging-fence-lock.mjs +267 -0
  339. package/scripts/lib/locks/state-md-lock.mjs +351 -0
  340. package/scripts/lib/loop-readiness-banner.mjs +144 -0
  341. package/scripts/lib/memory-banner.mjs +478 -0
  342. package/scripts/lib/memory-cleanup/worktree-sweep.mjs +108 -0
  343. package/scripts/lib/memory-cleanup-stamp.mjs +56 -0
  344. package/scripts/lib/memory-paths.mjs +31 -0
  345. package/scripts/lib/memory-proposals/collector.mjs +334 -0
  346. package/scripts/lib/memory-proposals/schema.mjs +289 -0
  347. package/scripts/lib/memory-proposals/sink.mjs +507 -0
  348. package/scripts/lib/memory-proposals/store.mjs +441 -0
  349. package/scripts/lib/mission-status-schema.mjs +114 -0
  350. package/scripts/lib/mode-selector/alternatives.mjs +64 -0
  351. package/scripts/lib/mode-selector/constants.mjs +29 -0
  352. package/scripts/lib/mode-selector/context-pressure.mjs +157 -0
  353. package/scripts/lib/mode-selector/rationale.mjs +55 -0
  354. package/scripts/lib/mode-selector/scoring.mjs +221 -0
  355. package/scripts/lib/mode-selector-accuracy.mjs +121 -0
  356. package/scripts/lib/mode-selector.mjs +160 -0
  357. package/scripts/lib/multi-provider-build/providers.mjs +64 -0
  358. package/scripts/lib/multi-provider-build/templating.mjs +130 -0
  359. package/scripts/lib/named-baseline-resolver.mjs +233 -0
  360. package/scripts/lib/named-vault-resolver.mjs +433 -0
  361. package/scripts/lib/owner-config/coerce.mjs +29 -0
  362. package/scripts/lib/owner-config/constants.mjs +21 -0
  363. package/scripts/lib/owner-config/defaults.mjs +50 -0
  364. package/scripts/lib/owner-config/error.mjs +19 -0
  365. package/scripts/lib/owner-config/index.mjs +13 -0
  366. package/scripts/lib/owner-config/merge.mjs +52 -0
  367. package/scripts/lib/owner-config/validate.mjs +259 -0
  368. package/scripts/lib/owner-config-banner.mjs +126 -0
  369. package/scripts/lib/owner-config-loader.mjs +159 -0
  370. package/scripts/lib/owner-config.example.yaml +72 -0
  371. package/scripts/lib/owner-config.mjs +28 -0
  372. package/scripts/lib/owner-interview.mjs +243 -0
  373. package/scripts/lib/owner-yaml.mjs +571 -0
  374. package/scripts/lib/package-manager.mjs +160 -0
  375. package/scripts/lib/path-utils.mjs +217 -0
  376. package/scripts/lib/peer-cards/merger.mjs +310 -0
  377. package/scripts/lib/peer-cards/reader.mjs +125 -0
  378. package/scripts/lib/peer-cards/schema.mjs +230 -0
  379. package/scripts/lib/peer-cards/staleness-banner.mjs +86 -0
  380. package/scripts/lib/peer-cards/writer.mjs +138 -0
  381. package/scripts/lib/peer-discovery.mjs +200 -0
  382. package/scripts/lib/persona-panel/catalog-loader.mjs +577 -0
  383. package/scripts/lib/persona-panel/consolidator.mjs +370 -0
  384. package/scripts/lib/persona-panel/persona-runner.mjs +375 -0
  385. package/scripts/lib/persona-panel/threshold.mjs +130 -0
  386. package/scripts/lib/pi-hook-bridge.mjs +328 -0
  387. package/scripts/lib/platform.mjs +266 -0
  388. package/scripts/lib/playwright-driver/runner.mjs +297 -0
  389. package/scripts/lib/plugin-root.mjs +210 -0
  390. package/scripts/lib/pre-dispatch-check.mjs +126 -0
  391. package/scripts/lib/product-repo-detect.mjs +121 -0
  392. package/scripts/lib/profiles/registry.mjs +176 -0
  393. package/scripts/lib/profiles/schema.mjs +209 -0
  394. package/scripts/lib/qg-command-drift-banner.mjs +88 -0
  395. package/scripts/lib/quality-gate/diagnostics.mjs +92 -0
  396. package/scripts/lib/quality-gate.mjs +536 -0
  397. package/scripts/lib/quality-gates-cache.mjs +228 -0
  398. package/scripts/lib/quality-gates-policy.mjs +95 -0
  399. package/scripts/lib/recommendations-v0.mjs +156 -0
  400. package/scripts/lib/reconcile/eligibility.mjs +203 -0
  401. package/scripts/lib/reconcile/emitter.mjs +244 -0
  402. package/scripts/lib/reconcile/engine.mjs +412 -0
  403. package/scripts/lib/reconcile/idempotency.mjs +239 -0
  404. package/scripts/lib/reconcile/renderer.mjs +211 -0
  405. package/scripts/lib/reconcile/writer.mjs +293 -0
  406. package/scripts/lib/reconcile-nudge-banner.mjs +284 -0
  407. package/scripts/lib/resource-probe/evaluate.mjs +190 -0
  408. package/scripts/lib/resource-probe/parsers.mjs +181 -0
  409. package/scripts/lib/resource-probe/probe-platform.mjs +300 -0
  410. package/scripts/lib/resource-probe.mjs +95 -0
  411. package/scripts/lib/rule-loader.mjs +552 -0
  412. package/scripts/lib/rules-sync.mjs +439 -0
  413. package/scripts/lib/scope-gate.mjs +496 -0
  414. package/scripts/lib/session-close-backfill.mjs +539 -0
  415. package/scripts/lib/session-discovery.mjs +256 -0
  416. package/scripts/lib/session-end/phase-skip.mjs +357 -0
  417. package/scripts/lib/session-end/worktree-cleanup.mjs +112 -0
  418. package/scripts/lib/session-id.mjs +362 -0
  419. package/scripts/lib/session-lock.mjs +703 -0
  420. package/scripts/lib/session-registry.mjs +355 -0
  421. package/scripts/lib/session-schema/aliases.mjs +71 -0
  422. package/scripts/lib/session-schema/constants.mjs +115 -0
  423. package/scripts/lib/session-schema/normalizer.mjs +66 -0
  424. package/scripts/lib/session-schema/timestamps.mjs +64 -0
  425. package/scripts/lib/session-schema/validator.mjs +453 -0
  426. package/scripts/lib/session-schema.mjs +71 -0
  427. package/scripts/lib/session-token-rollup.mjs +137 -0
  428. package/scripts/lib/sessions-staleness-banner.mjs +247 -0
  429. package/scripts/lib/skill-evolution/blast-radius-classifier.mjs +114 -0
  430. package/scripts/lib/skill-evolution/candidate-intake.mjs +270 -0
  431. package/scripts/lib/skill-evolution/config-validation-gate.mjs +279 -0
  432. package/scripts/lib/skill-evolution/engine.mjs +719 -0
  433. package/scripts/lib/skill-evolution/idempotency.mjs +279 -0
  434. package/scripts/lib/skill-evolution/mr-opener.mjs +507 -0
  435. package/scripts/lib/skill-health/join.mjs +181 -0
  436. package/scripts/lib/skill-health/score.mjs +123 -0
  437. package/scripts/lib/skill-invocations-schema.mjs +214 -0
  438. package/scripts/lib/skill-judge.mjs +348 -0
  439. package/scripts/lib/skill-judgments-schema.mjs +264 -0
  440. package/scripts/lib/slopcheck.mjs +501 -0
  441. package/scripts/lib/soul-resolve.mjs +118 -0
  442. package/scripts/lib/spiral-carryover.mjs +495 -0
  443. package/scripts/lib/state-md/body-sections.mjs +851 -0
  444. package/scripts/lib/state-md/frontmatter-mutators.mjs +453 -0
  445. package/scripts/lib/state-md/mission-status.mjs +247 -0
  446. package/scripts/lib/state-md/recommendations.mjs +57 -0
  447. package/scripts/lib/state-md/yaml-parser.mjs +234 -0
  448. package/scripts/lib/state-md-peer-guard.mjs +232 -0
  449. package/scripts/lib/state-md.mjs +53 -0
  450. package/scripts/lib/subagents-schema.mjs +309 -0
  451. package/scripts/lib/sunset/walker.mjs +1192 -0
  452. package/scripts/lib/test-runner/artifact-paths.mjs +94 -0
  453. package/scripts/lib/test-runner/fingerprint.mjs +33 -0
  454. package/scripts/lib/test-runner/issue-reconcile.mjs +770 -0
  455. package/scripts/lib/tmux-layout/layouts.mjs +224 -0
  456. package/scripts/lib/tmux-layout/telemetry-stats.mjs +100 -0
  457. package/scripts/lib/tmux-layout/telemetry.mjs +88 -0
  458. package/scripts/lib/tmux-layout/tmux-shell.mjs +82 -0
  459. package/scripts/lib/tmux-layout/vcs-detector.mjs +88 -0
  460. package/scripts/lib/validate/check-agents.mjs +457 -0
  461. package/scripts/lib/validate/check-codex-plugin.mjs +37 -0
  462. package/scripts/lib/validate/check-commands.mjs +148 -0
  463. package/scripts/lib/validate/check-component-paths.mjs +112 -0
  464. package/scripts/lib/validate/check-dead-bridge.mjs +180 -0
  465. package/scripts/lib/validate/check-hooks-symmetry.mjs +258 -0
  466. package/scripts/lib/validate/check-json-files.mjs +116 -0
  467. package/scripts/lib/validate/check-owner-leakage.mjs +1011 -0
  468. package/scripts/lib/validate/check-path-utils-canary.mjs +175 -0
  469. package/scripts/lib/validate/check-peekaboo-driver-canary.mjs +201 -0
  470. package/scripts/lib/validate/check-pi-package.mjs +110 -0
  471. package/scripts/lib/validate/check-pi-prompts.mjs +43 -0
  472. package/scripts/lib/validate/check-playwright-mcp-canary.mjs +154 -0
  473. package/scripts/lib/validate/check-plugin-json.mjs +96 -0
  474. package/scripts/lib/validate/check-plugin-monitors.mjs +206 -0
  475. package/scripts/lib/validate/check-plugin-schema.mjs +137 -0
  476. package/scripts/lib/validate/check-rules.mjs +143 -0
  477. package/scripts/lib/validate/check-session-plan-routing.mjs +154 -0
  478. package/scripts/lib/validate/check-test-fixture-shapes.mjs +280 -0
  479. package/scripts/lib/validate/check-unicode-safety.mjs +533 -0
  480. package/scripts/lib/validate/confidential-names.mjs +169 -0
  481. package/scripts/lib/validate/dead-bridge-corpus.mjs +141 -0
  482. package/scripts/lib/validate/dead-bridge-detectors.mjs +568 -0
  483. package/scripts/lib/validate/tier-inference.mjs +100 -0
  484. package/scripts/lib/validate-vendored-rules.mjs +519 -0
  485. package/scripts/lib/vault-archive.mjs +404 -0
  486. package/scripts/lib/vault-backfill/glab.mjs +164 -0
  487. package/scripts/lib/vault-backfill/manifest.mjs +75 -0
  488. package/scripts/lib/vault-backfill/template.mjs +130 -0
  489. package/scripts/lib/vault-consolidate-fs.mjs +331 -0
  490. package/scripts/lib/vault-migration-rules.mjs +155 -0
  491. package/scripts/lib/vault-mirror/auto-commit.mjs +203 -0
  492. package/scripts/lib/vault-mirror/namespace.mjs +152 -0
  493. package/scripts/lib/vault-mirror/process.mjs +567 -0
  494. package/scripts/lib/vault-mirror/pseudonym-map.mjs +164 -0
  495. package/scripts/lib/vault-mirror/render-learnings.mjs +201 -0
  496. package/scripts/lib/vault-mirror/render-sessions.mjs +367 -0
  497. package/scripts/lib/vault-mirror/render.mjs +8 -0
  498. package/scripts/lib/vault-mirror/utils.mjs +217 -0
  499. package/scripts/lib/vault-relocation-rules.mjs +555 -0
  500. package/scripts/lib/vault-repo-backfill.mjs +235 -0
  501. package/scripts/lib/vault-staleness-banner.mjs +142 -0
  502. package/scripts/lib/vault-status/board-writer.mjs +769 -0
  503. package/scripts/lib/vault-status/narrative-mirror.mjs +544 -0
  504. package/scripts/lib/vault-sync-baseline.mjs +152 -0
  505. package/scripts/lib/wave-context.mjs +29 -0
  506. package/scripts/lib/wave-executor/pool.mjs +248 -0
  507. package/scripts/lib/wave-resource-gate.mjs +204 -0
  508. package/scripts/lib/wave-sizing.mjs +75 -0
  509. package/scripts/lib/webhook-url.mjs +105 -0
  510. package/scripts/lib/workspace.mjs +198 -0
  511. package/scripts/lib/worktree/constants.mjs +35 -0
  512. package/scripts/lib/worktree/index.mjs +17 -0
  513. package/scripts/lib/worktree/lifecycle.mjs +287 -0
  514. package/scripts/lib/worktree/listing.mjs +118 -0
  515. package/scripts/lib/worktree/meta.mjs +64 -0
  516. package/scripts/lib/worktree-freshness.mjs +313 -0
  517. package/scripts/lib/worktree.mjs +15 -0
  518. package/scripts/lifecycle-sim-v6.mjs +347 -0
  519. package/scripts/lock-reaper.mjs +185 -0
  520. package/scripts/mcp-server.sh +241 -0
  521. package/scripts/measure-policy-cache-effectiveness.mjs +427 -0
  522. package/scripts/memory-propose.mjs +464 -0
  523. package/scripts/migrate-cold-start-seed.mjs +404 -0
  524. package/scripts/migrate-learnings-jsonl.mjs +189 -0
  525. package/scripts/migrate-legacy-learnings.sh +61 -0
  526. package/scripts/migrate-sessions-jsonl.mjs +448 -0
  527. package/scripts/migrate-subagents-jsonl.mjs +196 -0
  528. package/scripts/migrate-vault-paths.mjs +796 -0
  529. package/scripts/parse-config.mjs +149 -0
  530. package/scripts/pi-install.mjs +117 -0
  531. package/scripts/print-applicable-rules.mjs +247 -0
  532. package/scripts/promote-vault-strict.mjs +496 -0
  533. package/scripts/relocate-vault-corpus.mjs +1178 -0
  534. package/scripts/run-migrate-v2-cross-repo.mjs +385 -0
  535. package/scripts/run-quality-gate.mjs +216 -0
  536. package/scripts/spikes/h3-agent-teams/preflight.sh +53 -0
  537. package/scripts/spikes/h3-agent-teams/run-h3.sh +112 -0
  538. package/scripts/spikes/h3-agent-teams/setup.sh +137 -0
  539. package/scripts/spikes/h3-agent-teams/toggle.sh +38 -0
  540. package/scripts/sweep-expired-learnings.mjs +135 -0
  541. package/scripts/sync-vault-schema.mjs +376 -0
  542. package/scripts/tests/fixtures/fetch-baseline/sample-rule.md +8 -0
  543. package/scripts/tmux-layout.mjs +245 -0
  544. package/scripts/token-audit.sh +191 -0
  545. package/scripts/typecheck.mjs +42 -0
  546. package/scripts/upload-social-preview.mjs +316 -0
  547. package/scripts/validate-config.mjs +46 -0
  548. package/scripts/validate-plugin-manifests.mjs +163 -0
  549. package/scripts/validate-plugin.mjs +264 -0
  550. package/scripts/validate-wave-scope.mjs +289 -0
  551. package/scripts/vault-backfill.mjs +404 -0
  552. package/scripts/vault-consolidate.mjs +596 -0
  553. package/scripts/vault-integration-watcher.mjs +394 -0
  554. package/scripts/vault-mirror.mjs +430 -0
  555. package/skills/_shared/bootstrap-gate.md +111 -0
  556. package/skills/_shared/config-reading.md +226 -0
  557. package/skills/_shared/instruction-file-resolution.md +79 -0
  558. package/skills/_shared/model-selection.md +64 -0
  559. package/skills/_shared/monitor-patterns.md +300 -0
  560. package/skills/_shared/parallel-aware-auq.md +121 -0
  561. package/skills/_shared/parallel-aware-preamble.md +185 -0
  562. package/skills/_shared/platform-tools.md +96 -0
  563. package/skills/_shared/state-ownership.md +221 -0
  564. package/skills/architecture/DEEPENING.md +37 -0
  565. package/skills/architecture/INTERFACE-DESIGN.md +44 -0
  566. package/skills/architecture/LANGUAGE.md +53 -0
  567. package/skills/architecture/SKILL.md +92 -0
  568. package/skills/autopilot/SKILL.md +419 -0
  569. package/skills/bootstrap/SKILL.md +592 -0
  570. package/skills/bootstrap/STATE.md.template +24 -0
  571. package/skills/bootstrap/_shared-template.md +243 -0
  572. package/skills/bootstrap/deep-template.md +659 -0
  573. package/skills/bootstrap/fast-template.md +251 -0
  574. package/skills/bootstrap/intensity-heuristic.md +80 -0
  575. package/skills/bootstrap/public-fallback.md +342 -0
  576. package/skills/bootstrap/standard-template.md +736 -0
  577. package/skills/bootstrap/templates/agents/project-code-review.md +18 -0
  578. package/skills/bootstrap/templates/agents/project-discovery.md +18 -0
  579. package/skills/bootstrap/templates/agents/project-quality-gate.md +18 -0
  580. package/skills/brainstorm/SKILL.md +268 -0
  581. package/skills/brainstorm/soul.md +49 -0
  582. package/skills/claude-md-drift-check/SKILL.md +186 -0
  583. package/skills/claude-md-drift-check/checker.mjs +1380 -0
  584. package/skills/claude-md-drift-check/checker.sh +37 -0
  585. package/skills/claude-md-drift-check/package.json +16 -0
  586. package/skills/convergence-monitoring/README.md +39 -0
  587. package/skills/convergence-monitoring/SIGNALS.md +246 -0
  588. package/skills/convergence-monitoring/SKILL.md +285 -0
  589. package/skills/daily/SKILL.md +222 -0
  590. package/skills/daily/generate.sh +92 -0
  591. package/skills/daily/templates/daily.md.tpl +36 -0
  592. package/skills/debug/SKILL.md +188 -0
  593. package/skills/debug/soul.md +35 -0
  594. package/skills/discovery/SKILL.md +567 -0
  595. package/skills/discovery/issue-templates.md +237 -0
  596. package/skills/discovery/probes/docs-staleness.mjs +195 -0
  597. package/skills/discovery/probes/frontend-slop.mjs +186 -0
  598. package/skills/discovery/probes/ssot-code-diff.mjs +310 -0
  599. package/skills/discovery/probes/supply-chain-slopcheck.mjs +440 -0
  600. package/skills/discovery/probes/vault-narrative-staleness.mjs +355 -0
  601. package/skills/discovery/probes/vault-staleness.mjs +272 -0
  602. package/skills/discovery/probes-arch.md +252 -0
  603. package/skills/discovery/probes-audit.md +95 -0
  604. package/skills/discovery/probes-code.md +329 -0
  605. package/skills/discovery/probes-docs.md +76 -0
  606. package/skills/discovery/probes-feature.md +150 -0
  607. package/skills/discovery/probes-infra.md +138 -0
  608. package/skills/discovery/probes-intro.md +25 -0
  609. package/skills/discovery/probes-session.md +495 -0
  610. package/skills/discovery/probes-supply-chain.md +94 -0
  611. package/skills/discovery/probes-ui.md +147 -0
  612. package/skills/discovery/probes-vault.md +64 -0
  613. package/skills/discovery/slop-patterns.md +115 -0
  614. package/skills/dispatcher/SKILL.md +173 -0
  615. package/skills/docs-orchestrator/SKILL.md +362 -0
  616. package/skills/docs-orchestrator/audience-mapping.md +140 -0
  617. package/skills/domain-model/ADR-FORMAT.md +47 -0
  618. package/skills/domain-model/CONTEXT-FORMAT.md +77 -0
  619. package/skills/domain-model/SKILL.md +85 -0
  620. package/skills/ecosystem-health/SKILL.md +119 -0
  621. package/skills/ecosystem-health/wizard.md +193 -0
  622. package/skills/eval/SKILL.md +293 -0
  623. package/skills/eval/rubric-v1.md +218 -0
  624. package/skills/evolve/SKILL.md +546 -0
  625. package/skills/frontmatter-guard/SKILL.md +126 -0
  626. package/skills/gitlab-ops/SKILL.md +368 -0
  627. package/skills/gitlab-portfolio/SKILL.md +196 -0
  628. package/skills/grill/SKILL.md +185 -0
  629. package/skills/grill/soul.md +55 -0
  630. package/skills/hook-development/SKILL.md +413 -0
  631. package/skills/mcp-builder/SKILL.md +260 -0
  632. package/skills/memory-cleanup/SKILL.md +310 -0
  633. package/skills/mode-selector/SKILL.md +226 -0
  634. package/skills/peekaboo-driver/SKILL.md +237 -0
  635. package/skills/peekaboo-driver/soul.md +32 -0
  636. package/skills/persona-panel/SKILL.md +365 -0
  637. package/skills/persona-panel/persona-format.md +205 -0
  638. package/skills/persona-panel/presets/designer-lens.md +87 -0
  639. package/skills/persona-panel/presets/engineer-lens.md +88 -0
  640. package/skills/persona-panel/presets/pm-lens.md +86 -0
  641. package/skills/plan/SKILL.md +496 -0
  642. package/skills/plan/mode-feature.md +141 -0
  643. package/skills/plan/mode-new.md +297 -0
  644. package/skills/plan/mode-retro.md +271 -0
  645. package/skills/plan/prd-feature-template.md +132 -0
  646. package/skills/plan/prd-full-template.md +151 -0
  647. package/skills/plan/prd-reviewer-prompt.md +103 -0
  648. package/skills/plan/retro-template.md +75 -0
  649. package/skills/plan/soul.md +62 -0
  650. package/skills/playwright-driver/SKILL.md +226 -0
  651. package/skills/playwright-driver/soul.md +30 -0
  652. package/skills/quality-gates/SKILL.md +212 -0
  653. package/skills/reconcile/SKILL.md +324 -0
  654. package/skills/repo-audit/SKILL.md +272 -0
  655. package/skills/session-end/SKILL.md +1044 -0
  656. package/skills/session-end/discovery-scan.md +37 -0
  657. package/skills/session-end/drift-operations.md +97 -0
  658. package/skills/session-end/learning-patterns.md +78 -0
  659. package/skills/session-end/metrics-collection.md +175 -0
  660. package/skills/session-end/phase-3-2-docs-verification.md +148 -0
  661. package/skills/session-end/phase-3-6-tail.md +344 -0
  662. package/skills/session-end/phase-3-7a-recommendations.md +86 -0
  663. package/skills/session-end/plan-verification.md +288 -0
  664. package/skills/session-end/session-metrics-write.md +223 -0
  665. package/skills/session-end/vault-operations.md +50 -0
  666. package/skills/session-end/verification-checklist.md +20 -0
  667. package/skills/session-plan/SKILL.md +554 -0
  668. package/skills/session-plan/wave-template.md +37 -0
  669. package/skills/session-start/SKILL.md +1043 -0
  670. package/skills/session-start/phase-2-5-docs-planning.md +119 -0
  671. package/skills/session-start/phase-4-5-resource-health.md +49 -0
  672. package/skills/session-start/phase-7-1-premise-check.md +47 -0
  673. package/skills/session-start/phase-7-5-mode-selector.md +237 -0
  674. package/skills/session-start/phase-8-5-express-path.md +61 -0
  675. package/skills/session-start/presentation-format.md +81 -0
  676. package/skills/session-start/soul.md +57 -0
  677. package/skills/skill-creator/SKILL.md +168 -0
  678. package/skills/spinout/SKILL.md +76 -0
  679. package/skills/sunset-review/SKILL.md +96 -0
  680. package/skills/test-runner/SKILL.md +362 -0
  681. package/skills/test-runner/rubric-v1.md +388 -0
  682. package/skills/test-runner/soul.md +46 -0
  683. package/skills/tmux-layout/SKILL.md +104 -0
  684. package/skills/ubiquitous-language/SKILL.md +97 -0
  685. package/skills/using-orchestrator/SKILL.md +144 -0
  686. package/skills/vault-mirror/SKILL.md +234 -0
  687. package/skills/vault-sync/SKILL.md +319 -0
  688. package/skills/vault-sync/package-lock.json +40 -0
  689. package/skills/vault-sync/package.json +11 -0
  690. package/skills/vault-sync/tests/fixtures/archive-test-vault/90-archive/bad-archived.md +8 -0
  691. package/skills/vault-sync/tests/fixtures/archive-test-vault/_meta/.gitkeep +0 -0
  692. package/skills/vault-sync/tests/fixtures/archive-test-vault/live-note.md +8 -0
  693. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/_meta/.gitkeep +0 -0
  694. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/bad-type.md +8 -0
  695. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/good-note.md +8 -0
  696. package/skills/vault-sync/tests/fixtures/clean-vault/.obsidian/config.md +8 -0
  697. package/skills/vault-sync/tests/fixtures/clean-vault/01-projects/foo/projects-baseline.md +10 -0
  698. package/skills/vault-sync/tests/fixtures/clean-vault/03-daily/daily-2026-04-13.md +8 -0
  699. package/skills/vault-sync/tests/fixtures/clean-vault/README.md +3 -0
  700. package/skills/vault-sync/tests/fixtures/clean-vault/hello-world.md +11 -0
  701. package/skills/vault-sync/tests/fixtures/dangling-link-vault/_meta/.gitkeep +0 -0
  702. package/skills/vault-sync/tests/fixtures/dangling-link-vault/has-dangling.md +9 -0
  703. package/skills/vault-sync/tests/fixtures/dangling-link-vault/real-target.md +8 -0
  704. package/skills/vault-sync/tests/fixtures/empty-vault/_meta/.gitkeep +0 -0
  705. package/skills/vault-sync/tests/fixtures/missing-field-vault/_meta/.gitkeep +0 -0
  706. package/skills/vault-sync/tests/fixtures/missing-field-vault/missing-id.md +7 -0
  707. package/skills/vault-sync/tests/fixtures/nested-tag-vault/03-daily/daily-2026-04-13.md +9 -0
  708. package/skills/vault-sync/tests/fixtures/nested-tag-vault/_meta/.gitkeep +0 -0
  709. package/skills/vault-sync/tests/fixtures/nested-tag-vault/nested-tags-note.md +11 -0
  710. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/README.md +3 -0
  711. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_MOC.md +3 -0
  712. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_meta/.gitkeep +0 -0
  713. package/skills/vault-sync/tests/fixtures/with-moc-vault/_MOC.md +11 -0
  714. package/skills/vault-sync/tests/fixtures/with-moc-vault/_meta/.gitkeep +0 -0
  715. package/skills/vault-sync/tests/fixtures/with-moc-vault/hello-world.md +11 -0
  716. package/skills/vault-sync/tests/schema-drift.test.mjs +133 -0
  717. package/skills/vault-sync/validator.mjs +658 -0
  718. package/skills/vault-sync/validator.sh +55 -0
  719. package/skills/wave-executor/SKILL.md +496 -0
  720. package/skills/wave-executor/circuit-breaker.md +169 -0
  721. package/skills/wave-executor/wave-loop.md +1043 -0
  722. package/skills/write-executable-plan/SKILL.md +237 -0
  723. package/skills/write-executable-plan/plan-template.md +154 -0
  724. package/templates/_minimal/CLAUDE.md.tmpl +41 -0
  725. package/templates/_minimal/README.md.tmpl +15 -0
  726. package/templates/_minimal/gitignore.tmpl +47 -0
  727. package/templates/_shared/harte-regeln.md +16 -0
  728. package/templates/_shared/loop.md +90 -0
  729. package/templates/_shared/rules/parallel-sessions.md +77 -0
  730. package/templates/nextjs-minimal/README.md +30 -0
  731. package/templates/nextjs-minimal/app/layout.tsx +18 -0
  732. package/templates/nextjs-minimal/app/page.tsx +7 -0
  733. package/templates/nextjs-minimal/eslint.config.mjs +16 -0
  734. package/templates/nextjs-minimal/next.config.mjs +4 -0
  735. package/templates/nextjs-minimal/package.json +27 -0
  736. package/templates/nextjs-minimal/tsconfig.json +23 -0
  737. package/templates/node-minimal/README.md +33 -0
  738. package/templates/node-minimal/eslint.config.mjs +10 -0
  739. package/templates/node-minimal/package.json +21 -0
  740. package/templates/node-minimal/src/index.ts +1 -0
  741. package/templates/node-minimal/tests/sanity.test.ts +5 -0
  742. package/templates/node-minimal/tsconfig.json +17 -0
  743. package/templates/personas/README.md +150 -0
  744. package/templates/personas/accounting-compliance.v1.md +120 -0
  745. package/templates/personas/accounting-tax-advisor.v1.md +116 -0
  746. package/templates/personas/buyer-p1-cto.v1.md +125 -0
  747. package/templates/personas/buyer-p2-kanzlei.v1.md +134 -0
  748. package/templates/personas/buyer-p3-build.v1.md +130 -0
  749. package/templates/personas/buyer-p4-tech-veto.v1.md +130 -0
  750. package/templates/personas/buyer-p5-solo.v1.md +132 -0
  751. package/templates/personas/buyer-p6-ld.v1.md +130 -0
  752. package/templates/personas/klima-ai-expert.v1.md +114 -0
  753. package/templates/personas/klima-physicist.v1.md +117 -0
  754. package/templates/python-uv/README.md +28 -0
  755. package/templates/python-uv/pyproject.toml +32 -0
  756. package/templates/python-uv/src/__PROJECT_NAME__/__init__.py +0 -0
  757. package/templates/python-uv/src/__PROJECT_NAME__/main.py +6 -0
  758. package/templates/python-uv/tests/test_sanity.py +2 -0
  759. package/templates/static-html/README.md +19 -0
  760. package/templates/static-html/index.html +15 -0
  761. package/templates/static-html/script.js +1 -0
  762. package/templates/static-html/styles.css +26 -0
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cwd-change-restore.mjs — CwdChanged hook handler.
4
+ *
5
+ * Hook event: CwdChanged (issue #342).
6
+ * Fires when the coordinator's working directory changes unexpectedly.
7
+ * Records the event in `.orchestrator/current-session.json` under the
8
+ * `cwd_changes` array so the coordinator and downstream skills can
9
+ * inspect recent directory changes without re-reading the full event log.
10
+ *
11
+ * Note: the actual CWD restoration is a harness-level concern; this
12
+ * handler is informational only. It mirrors the pattern used by
13
+ * post-tool-failure-corrective-context.mjs.
14
+ *
15
+ * Decision flow:
16
+ * 1. shouldRunHook gate — exit 0 immediately when the hook is disabled.
17
+ * 2. Read JSON payload from stdin: { previous_cwd, new_cwd }.
18
+ * 3. Build a compact record: { timestamp, previous_cwd, new_cwd }.
19
+ * 4. Atomic read-modify-write of .orchestrator/current-session.json:
20
+ * append to `cwd_changes` array (create if absent), keep last 20
21
+ * entries to bound file growth.
22
+ * 5. Output: nothing on stdout. Diagnostic errors to stderr only.
23
+ *
24
+ * Exit codes: 0 always (informational, never blocking).
25
+ */
26
+
27
+ import { readFile, writeFile, rename, mkdir } from 'node:fs/promises';
28
+ import path from 'node:path';
29
+
30
+ import { shouldRunHook } from './_lib/profile-gate.mjs';
31
+ // Exit 0 immediately when disabled via SO_HOOK_PROFILE / SO_DISABLED_HOOKS.
32
+ if (!shouldRunHook('cwd-change-restore')) process.exit(0);
33
+
34
+ import { SO_PROJECT_DIR } from '../scripts/lib/platform.mjs';
35
+
36
+ // ---------------------------------------------------------------------------
37
+ // Constants
38
+ // ---------------------------------------------------------------------------
39
+
40
+ /** Maximum number of cwd_change entries retained per session. */
41
+ const MAX_ENTRIES = 20;
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Helpers
45
+ // ---------------------------------------------------------------------------
46
+
47
+ /**
48
+ * Read stdin to EOF (best-effort). Returns parsed JSON or null on failure.
49
+ * Uses a 5 s timeout consistent with Claude Code hook contract.
50
+ *
51
+ * @returns {Promise<object|null>}
52
+ */
53
+ function readStdinJson() {
54
+ return new Promise((resolve) => {
55
+ if (process.stdin.readableEnded || process.stdin.closed) {
56
+ resolve(null);
57
+ return;
58
+ }
59
+ const chunks = [];
60
+ const timer = setTimeout(() => { resolve(null); }, 5_000);
61
+ process.stdin.setEncoding('utf8');
62
+ process.stdin.on('data', (c) => chunks.push(c));
63
+ process.stdin.on('end', () => {
64
+ clearTimeout(timer);
65
+ const raw = chunks.join('').trim();
66
+ if (!raw) { resolve(null); return; }
67
+ try { resolve(JSON.parse(raw)); } catch { resolve(null); }
68
+ });
69
+ process.stdin.on('error', () => { clearTimeout(timer); resolve(null); });
70
+ process.stdin.resume();
71
+ });
72
+ }
73
+
74
+ /**
75
+ * Atomic read-modify-write of a JSON file via temp + rename.
76
+ * Reads the existing file (or starts with `defaultValue` when absent),
77
+ * applies `mutate`, writes to a tmp file, then renames over the original.
78
+ * Atomic on POSIX (same-filesystem rename). Best-effort on Windows.
79
+ *
80
+ * @param {string} filePath
81
+ * @param {object} defaultValue — used when the file does not exist or is unparseable
82
+ * @param {function(object): object} mutate — synchronous pure transformer
83
+ */
84
+ async function atomicMutateJson(filePath, defaultValue, mutate) {
85
+ let current = defaultValue;
86
+ try {
87
+ const raw = await readFile(filePath, 'utf8');
88
+ current = JSON.parse(raw);
89
+ } catch {
90
+ // File absent or unparseable — start from defaultValue.
91
+ }
92
+
93
+ const updated = mutate(current);
94
+ const tmp = `${filePath}.tmp-cwd-${process.pid}-${Date.now()}`;
95
+ await mkdir(path.dirname(filePath), { recursive: true });
96
+ await writeFile(tmp, JSON.stringify(updated, null, 2) + '\n', 'utf8');
97
+ await rename(tmp, filePath);
98
+ }
99
+
100
+ // ---------------------------------------------------------------------------
101
+ // Main
102
+ // ---------------------------------------------------------------------------
103
+
104
+ async function main() {
105
+ const input = await readStdinJson();
106
+
107
+ const previousCwd =
108
+ typeof input?.previous_cwd === 'string' ? input.previous_cwd : null;
109
+ const newCwd =
110
+ typeof input?.new_cwd === 'string' ? input.new_cwd : null;
111
+
112
+ const record = {
113
+ timestamp: new Date().toISOString(),
114
+ previous_cwd: previousCwd,
115
+ new_cwd: newCwd,
116
+ };
117
+
118
+ const sessionFile = path.join(SO_PROJECT_DIR, '.orchestrator', 'current-session.json');
119
+
120
+ await atomicMutateJson(sessionFile, {}, (current) => {
121
+ const existing = Array.isArray(current.cwd_changes)
122
+ ? current.cwd_changes
123
+ : [];
124
+ // Append the new record and cap at MAX_ENTRIES (keep most-recent).
125
+ const updated = [...existing, record].slice(-MAX_ENTRIES);
126
+ return { ...current, cwd_changes: updated };
127
+ });
128
+ }
129
+
130
+ // Exit 0 always — informational hook must never block Claude.
131
+ main().catch(() => {}).finally(() => process.exit(0));
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * enforce-commands.mjs — PreToolUse hook: blocks dangerous Bash commands.
4
+ *
5
+ * Node.js port of hooks/enforce-commands.sh. Part of v3.0.0 migration
6
+ * (Epic #124, issue #138). ESM, Node 20+, no external dependencies beyond stdlib.
7
+ *
8
+ * Decision flow (8 gates, early-exit):
9
+ * G1 tool filter — only Bash tool is gated
10
+ * G2 command present + string
11
+ * G3 wave-scope.json exists
12
+ * G4 command-guard gate enabled
13
+ * G5 enforcement != "off"
14
+ * G6 blocked pattern match against .blockedCommands[], or
15
+ * fallback safety list when .blockedCommands is empty
16
+ * G7 strict → deny (exit 2); warn → stderr + allow (exit 0); otherwise allow
17
+ *
18
+ * SECURITY-REQ-01: try/catch on main(). emitDeny on any unhandled error —
19
+ * exit 2, never exit 1. Null-guard readStdin() return.
20
+ * SECURITY-REQ-07: FALLBACK_BLOCKED includes 'git push -f' and 'drop table'
21
+ * (short form + case variant gaps in the original Bash fallback list).
22
+ * SECURITY-REQ-08: scope file read exactly once per invocation.
23
+ */
24
+
25
+ import { shouldRunHook } from './_lib/profile-gate.mjs';
26
+ // #211: exit 0 immediately (silent allow) when this hook is disabled via profile/env
27
+ if (!shouldRunHook('enforce-commands')) process.exit(0);
28
+
29
+ import path from 'node:path';
30
+
31
+ import { readStdin, emitAllow, emitDeny, emitWarn } from '../scripts/lib/io.mjs';
32
+ import { resolveProjectDir } from '../scripts/lib/platform.mjs';
33
+ import {
34
+ findScopeFile,
35
+ commandMatchesBlocked,
36
+ suggestForCommandBlock,
37
+ extractBashWriteTargets,
38
+ pathMatchesPattern,
39
+ } from '../scripts/lib/hardening.mjs';
40
+ import { readJson } from '../scripts/lib/common.mjs';
41
+
42
+ // Fallback safety list — applied when scope.blockedCommands is empty.
43
+ // Keep in sync with hooks/enforce-commands.sh; v3 additions (#138, SECURITY-REQ-07)
44
+ // cover the short-form git push and the lowercase SQL variant the Bash version missed.
45
+ const FALLBACK_BLOCKED = [
46
+ 'rm -rf',
47
+ 'git push --force',
48
+ 'git push -f',
49
+ 'git reset --hard',
50
+ 'DROP TABLE',
51
+ 'drop table',
52
+ 'git checkout -- .',
53
+ ];
54
+
55
+ async function main() {
56
+ const input = await readStdin();
57
+ if (!input) return emitAllow();
58
+
59
+ // G1 — only Bash is gated
60
+ if (input.tool_name !== 'Bash') return emitAllow();
61
+
62
+ // G2 — command must be a non-empty string
63
+ const command = input?.tool_input?.command;
64
+ if (typeof command !== 'string' || command.length === 0) return emitAllow();
65
+
66
+ const projectRoot = resolveProjectDir();
67
+
68
+ // G3 — no scope file → allow
69
+ const scopePath = findScopeFile(projectRoot);
70
+ if (!scopePath) return emitAllow();
71
+
72
+ // SECURITY-REQ-08: read scope file exactly once; use the parsed object
73
+ // for all subsequent gate checks.
74
+ let scope;
75
+ try {
76
+ scope = await readJson(scopePath);
77
+ } catch {
78
+ scope = {};
79
+ }
80
+ const enforcement = scope.enforcement || 'strict';
81
+ const blockedCommands = Array.isArray(scope.blockedCommands)
82
+ ? scope.blockedCommands
83
+ : [];
84
+ const gateOn = scope?.gates?.['command-guard'] !== false;
85
+
86
+ // bash-write-guard (#800) — OPT-IN, WARN-ONLY, default OFF.
87
+ //
88
+ // INVERTED DEFAULT (deliberate divergence from the command-guard convention
89
+ // above, where a MISSING gates entry means ENABLED): this gate runs ONLY when
90
+ // `gates['bash-write-guard'] === true` is EXPLICITLY set. Conservative shell-
91
+ // write parsing carries a real false-positive risk (quoting, `>$VAR`, process
92
+ // substitution, pipes), so it stays off unless a wave opts in. It never denies
93
+ // and never changes the exit path — it only writes advisory stderr lines — so
94
+ // it is safe to run before the command-guard gate/enforcement early-returns.
95
+ // Skipped under enforcement:off (nothing is enforced there). See #800.
96
+ if (enforcement !== 'off' && scope?.gates?.['bash-write-guard'] === true) {
97
+ runBashWriteGuard(command, scope, projectRoot);
98
+ }
99
+
100
+ // G4 — gate disabled → allow
101
+ if (!gateOn) return emitAllow();
102
+ // G5 — enforcement "off" → allow
103
+ if (enforcement === 'off') return emitAllow();
104
+
105
+ // G6 — determine which list to check
106
+ const useFallback = blockedCommands.length === 0;
107
+ const patternsToCheck = useFallback ? FALLBACK_BLOCKED : blockedCommands;
108
+
109
+ for (const pattern of patternsToCheck) {
110
+ if (commandMatchesBlocked(command, pattern)) {
111
+ const prefix = useFallback
112
+ ? 'Blocked by fallback safety list'
113
+ : 'Blocked command';
114
+ const reason = `${prefix}: '${pattern}' found in command`;
115
+ const suggestion = suggestForCommandBlock(pattern);
116
+ if (enforcement === 'strict') {
117
+ return emitDeny(reason, suggestion);
118
+ }
119
+ return emitWarn(`${reason} — ${suggestion}`);
120
+ }
121
+ }
122
+
123
+ // G7 — no match → allow
124
+ return emitAllow();
125
+ }
126
+
127
+ /**
128
+ * bash-write-guard (#800) — advisory, side-effecting stderr warner.
129
+ *
130
+ * Extracts likely Bash write targets from `command`, relativises each against the
131
+ * project root where possible, and WARNS (stderr only) for every target that is
132
+ * NOT covered by the wave's allowedPaths. NEVER denies, NEVER changes the exit
133
+ * code — v1 is warn-only by design (#800). No event infra is pulled in: this hook
134
+ * has no emitEvent import, so warnings are plain stderr lines per the #800 contract.
135
+ *
136
+ * @param {string} command — raw Bash command string
137
+ * @param {object} scope — parsed wave-scope.json
138
+ * @param {string} projectRoot — absolute project root
139
+ */
140
+ function runBashWriteGuard(command, scope, projectRoot) {
141
+ const allowedPaths = Array.isArray(scope.allowedPaths) ? scope.allowedPaths : [];
142
+ const targets = extractBashWriteTargets(command);
143
+ for (const target of targets) {
144
+ if (!targetInWaveScope(target, allowedPaths, projectRoot)) {
145
+ process.stderr.write(`bash-write-guard: ${target} outside wave scope (warn-only, #800)\n`);
146
+ }
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Is a write target covered by the wave's allowedPaths? Reuses the same
152
+ * `pathMatchesPattern` matcher the enforce-scope path gate uses (no bespoke
153
+ * matching). Absolute targets inside the project root are relativised first;
154
+ * both the relative and raw forms are tried so an in-scope target never warns.
155
+ *
156
+ * @param {string} target — verbatim write target from extractBashWriteTargets
157
+ * @param {string[]} allowedPaths — wave allowedPaths union
158
+ * @param {string} projectRoot — absolute project root
159
+ * @returns {boolean}
160
+ */
161
+ function targetInWaveScope(target, allowedPaths, projectRoot) {
162
+ if (!Array.isArray(allowedPaths) || allowedPaths.length === 0) return false;
163
+ let rel = target;
164
+ if (path.isAbsolute(target)) {
165
+ const fromRoot = path.relative(projectRoot, target);
166
+ if (fromRoot && !fromRoot.startsWith('..') && !path.isAbsolute(fromRoot)) {
167
+ rel = fromRoot;
168
+ }
169
+ }
170
+ const norm = rel.split(path.sep).join('/').replace(/^\.\//, '');
171
+ return allowedPaths.some(
172
+ (p) => pathMatchesPattern(norm, p) || pathMatchesPattern(target, p),
173
+ );
174
+ }
175
+
176
+ // SECURITY-REQ-01 (F-03): top-level try/catch — never let exit 1 leak.
177
+ main().catch((e) => {
178
+ emitDeny('Internal hook error — request blocked for safety', `${e?.message || e}`);
179
+ });
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * enforce-scope.mjs — PreToolUse hook: block Edit/Write/MultiEdit outside allowed wave paths.
4
+ *
5
+ * Replaces enforce-scope.sh (87-line Bash). Part of v3.0.0 Windows-native migration.
6
+ * Issue: github.com/Kanevry/session-orchestrator/issues/137
7
+ *
8
+ * Decision flow (8 gates + one pre-gate, early-exit):
9
+ * G1 tool filter — only Edit/Write/MultiEdit are gated
10
+ * G2 file_path present + string
11
+ * G3 wave-scope.json exists
12
+ * G4 path-guard gate enabled
13
+ * G5 enforcement != "off"
14
+ * G5b (#792) allowlist-first: an EXPLICIT absolute allowedPaths entry that
15
+ * matches the fully realpath-resolved candidate → allow, BEFORE G6.
16
+ * Runs before G6 so a deliberate out-of-repo grant (e.g. a vault path)
17
+ * is reachable at all — G6 would otherwise deny every out-of-repo path
18
+ * without ever consulting allowedPaths. See matchesAbsoluteAllowlist.
19
+ * G6 resolved path inside project root
20
+ * G7 relative path matches an allowedPaths pattern
21
+ * G8 (all passed) → allow
22
+ *
23
+ * Exit codes: 0 = allow 2 = deny
24
+ *
25
+ * SECURITY notes (inline refs):
26
+ * REQ-01 top-level try/catch → emitDeny on unexpected error (fail-closed)
27
+ * REQ-03 realpath(dirname) to resolve symlinks; ENOENT → fall back to path.resolve
28
+ * REQ-04 relativeFromRoot() === null → deny as outside-root
29
+ * REQ-05 normalize path separators to "/" before pathMatchesPattern (Windows compat)
30
+ * REQ-06 relative file_path resolved against projectRoot, not process.cwd()
31
+ * REQ-08 wave-scope.json read once; parsed object passed to all gate checks
32
+ * REQ-09 (#792) G5b out-of-repo carveout is structurally safe: RELATIVE
33
+ * allowedPaths entries can NEVER match an out-of-repo path (the
34
+ * isAbsolute filter drops them), so `**` / `../**` cannot be used to
35
+ * escape the repo; only entries that are themselves absolute match,
36
+ * and only against their own literal (canonical/realpath) subtree.
37
+ * Empty absolute set → the pre-gate is inert (byte-identical to the
38
+ * pre-#792 behaviour).
39
+ *
40
+ * Coordinator carveout (#245): a short, explicit list of harness-owned files
41
+ * bypasses Gate 7 (allowedPaths glob) — specifically STATE.md across all platform
42
+ * state dirs and the wave-scope.json manifest itself. Coordinators write these
43
+ * between waves as part of the harness protocol; subjecting them to per-wave
44
+ * allowedPaths would force every wave plan to re-list harness infrastructure.
45
+ * Project-root containment (Gate 6) and enforcement-off (Gate 5) still apply.
46
+ * No wildcards — exact string match only.
47
+ */
48
+
49
+ import path from 'node:path';
50
+ import { promises as fs } from 'node:fs';
51
+
52
+ import { shouldRunHook } from './_lib/profile-gate.mjs';
53
+ // #211: exit 0 immediately (silent allow) when this hook is disabled via profile/env
54
+ if (!shouldRunHook('enforce-scope')) process.exit(0);
55
+
56
+ import { readStdin, emitAllow, emitDeny, emitWarn } from '../scripts/lib/io.mjs';
57
+ import { isPathInside, relativeFromRoot } from '../scripts/lib/path-utils.mjs';
58
+ import { resolveProjectDir } from '../scripts/lib/platform.mjs';
59
+ import {
60
+ findScopeFile,
61
+ pathMatchesPattern,
62
+ suggestForScopeViolation,
63
+ } from '../scripts/lib/hardening.mjs';
64
+ import { readJson } from '../scripts/lib/common.mjs';
65
+
66
+ async function main() {
67
+ // SECURITY-REQ-01: null-guard empty stdin — treat as allow (no input = not a real hook call)
68
+ const input = await readStdin();
69
+ if (!input) return emitAllow();
70
+
71
+ const toolName = input.tool_name;
72
+ const filePath = input?.tool_input?.file_path;
73
+
74
+ // Gate 1: only Edit, Write, and MultiEdit are path-gated
75
+ if (toolName !== 'Edit' && toolName !== 'Write' && toolName !== 'MultiEdit') return emitAllow();
76
+
77
+ // Gate 2: file_path must be a non-empty string
78
+ if (!filePath || typeof filePath !== 'string') return emitAllow();
79
+
80
+ const projectRootRaw = resolveProjectDir();
81
+
82
+ // Resolve symlinks in the project root itself so that realpath(file) comparisons
83
+ // are consistent. On macOS /tmp → /private/tmp; mismatches would cause false denials.
84
+ let projectRoot;
85
+ try {
86
+ projectRoot = await fs.realpath(projectRootRaw);
87
+ } catch {
88
+ projectRoot = projectRootRaw;
89
+ }
90
+
91
+ // Gate 3: no wave-scope.json → nothing to enforce
92
+ const scopePath = findScopeFile(projectRoot);
93
+ if (!scopePath) return emitAllow();
94
+
95
+ // SECURITY-REQ-08: read scope file once; pass parsed object to all subsequent checks
96
+ let scope;
97
+ try {
98
+ scope = await readJson(scopePath);
99
+ } catch {
100
+ scope = {};
101
+ }
102
+
103
+ const enforcement = scope.enforcement ?? 'strict';
104
+ const allowedPaths = Array.isArray(scope.allowedPaths) ? scope.allowedPaths : [];
105
+ const gatesEnabled = scope.gates?.['path-guard'] !== false;
106
+
107
+ // Gate 4: path-guard gate explicitly disabled
108
+ if (!gatesEnabled) return emitAllow();
109
+
110
+ // Gate 5: enforcement is turned off
111
+ if (enforcement === 'off') return emitAllow();
112
+
113
+ // SECURITY-REQ-06: resolve relative file_path against projectRoot, not process.cwd()
114
+ const absPathInput = path.isAbsolute(filePath)
115
+ ? filePath
116
+ : path.resolve(projectRoot, filePath);
117
+
118
+ // SECURITY-REQ-03: resolve symlinks to prevent symlink-escape.
119
+ // Strategy:
120
+ // 1. Try fs.realpath on the file itself — follows symlinks (blocks `src/evil → /etc/passwd`).
121
+ // 2. On ENOENT (file doesn't exist yet — common for Write), walk up to the
122
+ // nearest existing ancestor, realpath it, then re-attach the non-existent
123
+ // suffix. Keeps projectRoot and resolvedPath in the same canonical namespace
124
+ // (e.g. both under /private/tmp on macOS).
125
+ // 3. Any non-ENOENT fs error → fail-closed.
126
+ let resolvedPath;
127
+ try {
128
+ resolvedPath = await fs.realpath(absPathInput);
129
+ } catch (err) {
130
+ if (err?.code !== 'ENOENT') {
131
+ return emitDeny(
132
+ 'Scope check failed — unable to resolve file path',
133
+ `Internal: ${err?.code ?? 'unknown'}`,
134
+ );
135
+ }
136
+ // File doesn't exist yet — walk up to nearest existing ancestor.
137
+ try {
138
+ const segments = [path.basename(absPathInput)];
139
+ let ancestor = path.dirname(absPathInput);
140
+ while (true) {
141
+ try {
142
+ const realAncestor = await fs.realpath(ancestor);
143
+ segments.reverse();
144
+ resolvedPath = path.join(realAncestor, ...segments);
145
+ break;
146
+ } catch (e) {
147
+ if (e?.code !== 'ENOENT') throw e;
148
+ const parent = path.dirname(ancestor);
149
+ if (parent === ancestor) {
150
+ // Hit filesystem root (should not occur for paths under projectRoot).
151
+ resolvedPath = absPathInput;
152
+ break;
153
+ }
154
+ segments.push(path.basename(ancestor));
155
+ ancestor = parent;
156
+ }
157
+ }
158
+ } catch (e) {
159
+ return emitDeny(
160
+ 'Scope check failed — unable to resolve file path',
161
+ `Internal: ${e?.code ?? 'unknown'}`,
162
+ );
163
+ }
164
+ }
165
+
166
+ // Gate 5b (#792): allowlist-first for explicit absolute (out-of-repo) grants.
167
+ // An EXPLICIT absolute allowedPaths entry (e.g. a coordinator-granted vault
168
+ // path) is structurally unreachable under Gate 6, which denies every
169
+ // out-of-repo path before allowedPaths is ever consulted. Honour such grants
170
+ // here — matching ONLY absolute entries against the fully realpath-resolved
171
+ // candidate, so relative entries can never be used to escape the repo (REQ-09).
172
+ if (matchesAbsoluteAllowlist(resolvedPath, allowedPaths)) return emitAllow();
173
+
174
+ // Gate 6: path must be inside the project root
175
+ if (!isPathInside(resolvedPath, projectRoot)) {
176
+ const reason = `Scope violation: path outside project root`;
177
+ const suggestion = suggestForScopeViolation(filePath, allowedPaths.join(', '));
178
+ return enforcement === 'strict'
179
+ ? emitDeny(reason, suggestion)
180
+ : emitWarn(`${reason} — ${suggestion}`);
181
+ }
182
+
183
+ // Compute the relative path from project root to the resolved file path
184
+ const relPath = relativeFromRoot(projectRoot, resolvedPath);
185
+
186
+ // SECURITY-REQ-04: null return means outside root — deny rather than pass null to pathMatchesPattern
187
+ if (relPath === null) {
188
+ const reason = `Scope violation: '${filePath}' outside project root`;
189
+ const suggestion = suggestForScopeViolation(filePath, allowedPaths.join(', '));
190
+ return enforcement === 'strict'
191
+ ? emitDeny(reason, suggestion)
192
+ : emitWarn(`${reason} — ${suggestion}`);
193
+ }
194
+
195
+ // SECURITY-REQ-05: normalize Windows path separators to '/' before glob matching
196
+ const normalizedRel = relPath.split(path.sep).join('/');
197
+
198
+ // Coordinator carveout (#245): exact-path allowlist for harness-owned files.
199
+ // STATE.md and wave-scope.json are written by the coordinator between waves;
200
+ // per-wave allowedPaths lists should not need to enumerate harness infrastructure.
201
+ if (isCoordinatorCarveout(normalizedRel, projectRoot, scopePath)) {
202
+ return emitAllow();
203
+ }
204
+
205
+ // Gate 7: check normalised relative path against each allowedPaths pattern
206
+ const matched = allowedPaths.some((pattern) => pathMatchesPattern(normalizedRel, pattern));
207
+
208
+ if (!matched) {
209
+ const reason = `Scope violation: '${normalizedRel}' not in allowed paths [${allowedPaths.join(', ')}]`;
210
+ const suggestion = suggestForScopeViolation(normalizedRel, allowedPaths.join(', '));
211
+ return enforcement === 'strict'
212
+ ? emitDeny(reason, suggestion)
213
+ : emitWarn(`${reason} — ${suggestion}`);
214
+ }
215
+
216
+ // Gate 8 / all gates passed → allow
217
+ return emitAllow();
218
+ }
219
+
220
+ const COORDINATOR_CARVEOUT_PATHS = Object.freeze([
221
+ '.claude/STATE.md',
222
+ '.codex/STATE.md',
223
+ '.cursor/STATE.md',
224
+ '.pi/STATE.md',
225
+ ]);
226
+
227
+ /**
228
+ * Returns true if the given project-relative, forward-slash-normalized path is
229
+ * one of the harness-owned files the coordinator writes between waves.
230
+ *
231
+ * Matches STATE.md across all platform state dirs and the wave-scope.json the
232
+ * hook just read (its exact, resolved relative path — no wildcard). Exact
233
+ * string comparison only; any glob semantics belong in Gate 7.
234
+ */
235
+ function isCoordinatorCarveout(normalizedRel, projectRoot, scopePath) {
236
+ if (COORDINATOR_CARVEOUT_PATHS.includes(normalizedRel)) return true;
237
+ const scopeRel = relativeFromRoot(projectRoot, scopePath);
238
+ if (scopeRel === null) return false;
239
+ return scopeRel.split(path.sep).join('/') === normalizedRel;
240
+ }
241
+
242
+ /**
243
+ * #792: Honour EXPLICIT absolute allowedPaths entries that point OUTSIDE the repo
244
+ * (a deliberate coordinator grant, e.g. "/Users/x/Projects/vault/**").
245
+ * Such entries are structurally unreachable under the default relative-only
246
+ * matcher because Gate 6 denies out-of-repo paths first, and Gate 7 only ever
247
+ * matches the ROOT-RELATIVE candidate (an absolute pattern can never match it).
248
+ *
249
+ * SECURITY (REQ-09): matches ONLY entries that are themselves absolute, against
250
+ * the fully realpath-resolved candidate — so RELATIVE entries (`**`, `../**`)
251
+ * can NEVER be used to escape the repo. When no absolute entry exists the helper
252
+ * returns false and the caller falls through to Gate 6 unchanged (inert pre-gate).
253
+ * An absolute entry matches only its own literal (canonical/realpath) subtree;
254
+ * the operator is responsible for supplying a canonical absolute path.
255
+ *
256
+ * @param {string} resolvedPath — fully realpath-resolved candidate (absolute)
257
+ * @param {string[]} allowedPaths — raw allowedPaths array from wave-scope.json
258
+ * @returns {boolean}
259
+ */
260
+ function matchesAbsoluteAllowlist(resolvedPath, allowedPaths) {
261
+ const abs = allowedPaths.filter((p) => typeof p === 'string' && path.isAbsolute(p));
262
+ if (abs.length === 0) return false;
263
+ const normalizedAbs = resolvedPath.split(path.sep).join('/');
264
+ return abs.some((pat) => pathMatchesPattern(normalizedAbs, pat.split(path.sep).join('/')));
265
+ }
266
+
267
+ // SECURITY-REQ-01 (fail-closed): any unhandled rejection → structured deny, never bare exit 1
268
+ main().catch((e) => {
269
+ emitDeny(
270
+ 'Internal hook error — request blocked for safety',
271
+ `${e?.message ?? String(e)}`,
272
+ );
273
+ });
@@ -0,0 +1,60 @@
1
+ {
2
+ "description": "Synchronous Codex hooks for payload-compatible Session Orchestrator handlers.",
3
+ "hooks": {
4
+ "SessionStart": [
5
+ {
6
+ "matcher": "startup|resume|clear|compact",
7
+ "hooks": [
8
+ {
9
+ "type": "command",
10
+ "command": "echo '🎯 Session Orchestrator v3.16.0 — /session [housekeeping|feature|deep] | /plan [new|feature|retro] | /discovery [scope] | /evolve [analyze|review|list]'",
11
+ "async": false
12
+ },
13
+ {
14
+ "type": "command",
15
+ "command": "SO_PLATFORM=codex CODEX_PLUGIN_ROOT=\"${PLUGIN_ROOT}\" sh \"${PLUGIN_ROOT}/hooks/run-node.sh\" \"${PLUGIN_ROOT}/hooks/on-session-start.mjs\"",
16
+ "timeout": 5
17
+ }
18
+ ]
19
+ }
20
+ ],
21
+ "PreToolUse": [],
22
+ "PostToolUse": [
23
+ {
24
+ "matcher": "*",
25
+ "hooks": [
26
+ {
27
+ "type": "command",
28
+ "command": "SO_PLATFORM=codex CODEX_PLUGIN_ROOT=\"${PLUGIN_ROOT}\" sh \"${PLUGIN_ROOT}/hooks/run-node.sh\" \"${PLUGIN_ROOT}/hooks/loop-guard.mjs\"",
29
+ "timeout": 5
30
+ }
31
+ ]
32
+ }
33
+ ],
34
+ "SubagentStart": [],
35
+ "SubagentStop": [
36
+ {
37
+ "matcher": "",
38
+ "hooks": [
39
+ {
40
+ "type": "command",
41
+ "command": "SO_PLATFORM=codex CODEX_PLUGIN_ROOT=\"${PLUGIN_ROOT}\" sh \"${PLUGIN_ROOT}/hooks/run-node.sh\" \"${PLUGIN_ROOT}/hooks/on-stop.mjs\"",
42
+ "timeout": 5
43
+ }
44
+ ]
45
+ }
46
+ ],
47
+ "Stop": [
48
+ {
49
+ "matcher": "",
50
+ "hooks": [
51
+ {
52
+ "type": "command",
53
+ "command": "SO_PLATFORM=codex CODEX_PLUGIN_ROOT=\"${PLUGIN_ROOT}\" sh \"${PLUGIN_ROOT}/hooks/run-node.sh\" \"${PLUGIN_ROOT}/hooks/on-stop.mjs\"",
54
+ "timeout": 5
55
+ }
56
+ ]
57
+ }
58
+ ]
59
+ }
60
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "_comment": "Cursor IDE hook mapping reference. Configure hooks in Cursor Settings > Hooks.",
3
+ "_note": "Cursor hooks fire at different lifecycle points than Claude Code. See docs/cursor-setup.md for details.",
4
+ "_limitation": "SessionStart greeting (session-start skill) is NOT available on Cursor. Cursor has no conversation-start lifecycle event equivalent to Claude Code's UserPromptSubmit hook. Session initialisation must be triggered manually.",
5
+ "hooks": {
6
+ "afterFileEdit": {
7
+ "script": "hooks/enforce-scope.mjs",
8
+ "note": "Post-hoc scope warning — Cursor fires AFTER the edit (not before). Cannot prevent out-of-scope edits, only warn."
9
+ },
10
+ "beforeShellExecution": {
11
+ "script": "hooks/enforce-commands.mjs",
12
+ "note": "Blocks dangerous commands before shell execution. Direct equivalent of Claude Code's PreToolUse Bash hook."
13
+ }
14
+ }
15
+ }