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,328 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * post-tool-batch-wave-signal.mjs — PostToolBatch hook.
4
+ *
5
+ * Hook event: PostToolBatch (issue #342).
6
+ * Fires after a batch of tool invocations completes within a single wave
7
+ * turn. Writes a deterministic `last_batch` signal into
8
+ * `.orchestrator/current-session.json` so skills and the coordinator can
9
+ * observe batch-resolution boundaries without parsing the full event log.
10
+ *
11
+ * Also refreshes the session-lock heartbeat (Epic #583, W3-P3 wiring of
12
+ * W2-I3 OQ2). The PostToolBatch event fires on a much more frequent cadence
13
+ * than session-start / inter-wave / session-end, which keeps the heartbeat
14
+ * within the TTL window even during long-running waves. The call is
15
+ * try/catch-wrapped — a heartbeat-refresh failure must never block the
16
+ * coordinator at a tool-batch boundary.
17
+ *
18
+ * Decision flow:
19
+ * 1. shouldRunHook gate — exit 0 immediately when the hook is disabled.
20
+ * 2. Read JSON payload from stdin:
21
+ * { batch_id, batch_size, batch_completed_at, agent_id?, parent_session_id? }
22
+ * 3. Atomic read-modify-write of .orchestrator/current-session.json:
23
+ * set `last_batch` to
24
+ * { batch_id, batch_size, completed_at, agent_id?, parent_session_id? }
25
+ * (always overwrites — last batch wins, one record per session file).
26
+ * 4. Best-effort: refresh session.lock `last_heartbeat` via updateHeartbeat()
27
+ * using the session_id read back from current-session.json (or stdin).
28
+ * 5. Output: nothing on stdout. Diagnostic errors to stderr only.
29
+ *
30
+ * Exit codes: 0 always (informational, never blocking).
31
+ *
32
+ * hooks.json wiring is managed separately (W3-C4 scope).
33
+ */
34
+
35
+ import { readFile, writeFile, rename, mkdir } from 'node:fs/promises';
36
+ import path from 'node:path';
37
+
38
+ import { shouldRunHook } from './_lib/profile-gate.mjs';
39
+ // Exit 0 immediately when disabled via SO_HOOK_PROFILE / SO_DISABLED_HOOKS.
40
+ if (!shouldRunHook('post-tool-batch-wave-signal')) process.exit(0);
41
+
42
+ import { SO_PROJECT_DIR } from '../scripts/lib/platform.mjs';
43
+ import { emitEvent } from '../scripts/lib/events.mjs';
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Helpers
47
+ // ---------------------------------------------------------------------------
48
+
49
+ /**
50
+ * Read stdin to EOF (best-effort). Returns parsed JSON or null on failure.
51
+ * Uses a 5 s timeout consistent with Claude Code hook contract.
52
+ *
53
+ * @returns {Promise<object|null>}
54
+ */
55
+ function readStdinJson() {
56
+ return new Promise((resolve) => {
57
+ if (process.stdin.readableEnded || process.stdin.closed) {
58
+ resolve(null);
59
+ return;
60
+ }
61
+ const chunks = [];
62
+ const timer = setTimeout(() => { resolve(null); }, 5_000);
63
+ process.stdin.setEncoding('utf8');
64
+ process.stdin.on('data', (c) => chunks.push(c));
65
+ process.stdin.on('end', () => {
66
+ clearTimeout(timer);
67
+ const raw = chunks.join('').trim();
68
+ if (!raw) { resolve(null); return; }
69
+ try { resolve(JSON.parse(raw)); } catch { resolve(null); }
70
+ });
71
+ process.stdin.on('error', () => { clearTimeout(timer); resolve(null); });
72
+ process.stdin.resume();
73
+ });
74
+ }
75
+
76
+ /**
77
+ * Atomic read-modify-write of a JSON file via temp + rename.
78
+ * Reads the existing file (or starts with `defaultValue` when absent),
79
+ * applies `mutate`, writes to a tmp file, then renames over the original.
80
+ * Atomic on POSIX (same-filesystem rename). Best-effort on Windows.
81
+ *
82
+ * @param {string} filePath
83
+ * @param {object} defaultValue — used when the file does not exist or is unparseable
84
+ * @param {function(object): object} mutate — synchronous pure transformer
85
+ */
86
+ async function atomicMutateJson(filePath, defaultValue, mutate) {
87
+ let current = defaultValue;
88
+ try {
89
+ const raw = await readFile(filePath, 'utf8');
90
+ current = JSON.parse(raw);
91
+ } catch {
92
+ // File absent or unparseable — start from defaultValue.
93
+ }
94
+
95
+ const updated = mutate(current);
96
+ const tmp = `${filePath}.tmp-ptb-${process.pid}-${Date.now()}`;
97
+ await mkdir(path.dirname(filePath), { recursive: true });
98
+ await writeFile(tmp, JSON.stringify(updated, null, 2) + '\n', 'utf8');
99
+ await rename(tmp, filePath);
100
+ }
101
+
102
+ /**
103
+ * Resolve the session-id for the heartbeat refresh.
104
+ * Precedence:
105
+ * 1. stdin payload `session_id` / `sessionId` field (Claude Code contract).
106
+ * 2. parent_session_id from stdin (sub-agent batches).
107
+ * 3. `.orchestrator/current-session.json` (`session_id` written by
108
+ * on-session-start.mjs).
109
+ * Returns null when no id can be resolved.
110
+ *
111
+ * @param {object|null} input Parsed stdin payload (may be null).
112
+ * @param {string} sessionFile Absolute path to current-session.json.
113
+ * @returns {Promise<string|null>}
114
+ */
115
+ async function resolveSessionIdForHeartbeat(input, sessionFile) {
116
+ if (input) {
117
+ if (typeof input.session_id === 'string' && input.session_id.length > 0) {
118
+ return input.session_id;
119
+ }
120
+ if (typeof input.sessionId === 'string' && input.sessionId.length > 0) {
121
+ return input.sessionId;
122
+ }
123
+ if (typeof input.parent_session_id === 'string' && input.parent_session_id.length > 0) {
124
+ return input.parent_session_id;
125
+ }
126
+ }
127
+ try {
128
+ const raw = await readFile(sessionFile, 'utf8');
129
+ const parsed = JSON.parse(raw);
130
+ if (typeof parsed.session_id === 'string' && parsed.session_id.length > 0) {
131
+ return parsed.session_id;
132
+ }
133
+ } catch { /* missing or unparseable is fine */ }
134
+ return null;
135
+ }
136
+
137
+ /**
138
+ * Resolve the current wave number from .claude/wave-scope.json `.wave`.
139
+ * Returns 0 when the file is absent or unparseable, mirroring the
140
+ * pre-bash-memory-propose-audit.mjs G5 precedent ("wave defaults to 0 when
141
+ * wave-scope.json absent"). The file is deleted mid-session at Quality phase
142
+ * transitions and final cleanup, so absence is an expected, non-error state.
143
+ *
144
+ * @param {string} projectDir
145
+ * @returns {Promise<number>}
146
+ */
147
+ async function resolveWaveNumber(projectDir) {
148
+ const waveFile = path.join(projectDir, '.claude', 'wave-scope.json');
149
+ try {
150
+ const raw = await readFile(waveFile, 'utf8');
151
+ const data = JSON.parse(raw);
152
+ const wave = data?.wave;
153
+ return typeof wave === 'number' ? wave : 0;
154
+ } catch {
155
+ // Absent or unparseable — treat as 0 (no active wave).
156
+ return 0;
157
+ }
158
+ }
159
+
160
+ // ---------------------------------------------------------------------------
161
+ // Main
162
+ // ---------------------------------------------------------------------------
163
+
164
+ async function main() {
165
+ const input = await readStdinJson();
166
+
167
+ // Extract fields from the hook payload.
168
+ const batchId = typeof input?.batch_id === 'string' ? input.batch_id : null;
169
+ const batchSize =
170
+ typeof input?.batch_size === 'number' ? input.batch_size : null;
171
+ const completedAt =
172
+ typeof input?.batch_completed_at === 'string'
173
+ ? input.batch_completed_at
174
+ : new Date().toISOString();
175
+ const agentId =
176
+ typeof input?.agent_id === 'string' ? input.agent_id : undefined;
177
+ const parentSessionId =
178
+ typeof input?.parent_session_id === 'string'
179
+ ? input.parent_session_id
180
+ : undefined;
181
+ // wave_signal is set by the orchestrator when a wave completes.
182
+ const waveSignal =
183
+ typeof input?.wave_signal === 'string' ? input.wave_signal : null;
184
+ const nextWaveRole =
185
+ typeof input?.next_wave_role === 'string' ? input.next_wave_role : null;
186
+ const waveNumber =
187
+ typeof input?.wave_number === 'number' ? input.wave_number : null;
188
+
189
+ // Build the last_batch signal. Only include optional fields when present
190
+ // to keep the session file lean.
191
+ const lastBatch = {
192
+ batch_id: batchId,
193
+ batch_size: batchSize,
194
+ completed_at: completedAt,
195
+ ...(agentId !== undefined ? { agent_id: agentId } : {}),
196
+ ...(parentSessionId !== undefined ? { parent_session_id: parentSessionId } : {}),
197
+ ...(waveSignal !== null ? { wave_signal: waveSignal } : {}),
198
+ };
199
+
200
+ const sessionFile = path.join(SO_PROJECT_DIR, '.orchestrator', 'current-session.json');
201
+
202
+ await atomicMutateJson(sessionFile, {}, (current) => ({
203
+ ...current,
204
+ last_batch: lastBatch,
205
+ }));
206
+
207
+ // ----------------------------------------------------------------------
208
+ // Heartbeat refresh (Epic #583 W3-P3, wires W2-I3 OQ2).
209
+ // ----------------------------------------------------------------------
210
+ // The session.lock liveness rule is heartbeat-based (Epic #583, W2-I3):
211
+ // (now - last_heartbeat) < ttl_hours
212
+ // The default TTL is 4h; PostToolBatch fires far more often than that,
213
+ // so refreshing here keeps every active session perpetually live to
214
+ // discoverActiveSessions() while a coordinator is making tool calls.
215
+ // Resolve the session-id from stdin first, falling back to the just-
216
+ // written current-session.json so the refresh stays decoupled from the
217
+ // hook payload shape. Wrapped in try/catch — same defence-in-depth
218
+ // posture as the rest of this hook (must NEVER block).
219
+ try {
220
+ const sessionId = await resolveSessionIdForHeartbeat(input, sessionFile);
221
+ if (typeof sessionId === 'string' && sessionId.length > 0) {
222
+ const { updateHeartbeat } = await import('../scripts/lib/session-lock.mjs');
223
+ updateHeartbeat({ repoRoot: SO_PROJECT_DIR, sessionId });
224
+ }
225
+ } catch { /* best effort — hook must remain non-blocking */ }
226
+
227
+ // Emit wave-lifecycle events via the canonical stream when the orchestrator
228
+ // populates wave_signal ('wave-start' | 'wave-complete'). Mechanical seam —
229
+ // see docs/events-schema.md. Best-effort; never blocks the hook.
230
+ //
231
+ // Live path today: the `wave_signal === null` branch below provides the
232
+ // mechanical wave-lifecycle fallback (#612). It fires live by diffing
233
+ // `.claude/wave-scope.json` `.wave` against the persisted `last_wave` — no
234
+ // payload injection required. This explicit-signal branch remains as the
235
+ // preferred path for whenever the harness DOES inject `wave_signal` into the
236
+ // batch payload (it takes precedence over the fallback when present).
237
+ if (waveSignal === 'wave-start' || waveSignal === 'wave-complete') {
238
+ try {
239
+ await emitEvent(
240
+ waveSignal === 'wave-start'
241
+ ? 'orchestrator.wave.started'
242
+ : 'orchestrator.wave.completed',
243
+ {
244
+ ...(waveNumber !== null ? { wave_number: waveNumber } : {}),
245
+ ...(nextWaveRole !== null ? { next_wave_role: nextWaveRole } : {}),
246
+ ...(batchId !== null ? { batch_id: batchId } : {}),
247
+ ...(batchSize !== null ? { batch_size: batchSize } : {}),
248
+ },
249
+ );
250
+ } catch { /* best-effort — hook must remain non-blocking */ }
251
+ } else if (waveSignal === null) {
252
+ // ------------------------------------------------------------------
253
+ // Mechanical wave-lifecycle fallback (#612, Option b).
254
+ // ------------------------------------------------------------------
255
+ // When the harness does NOT inject an explicit wave_signal (the common
256
+ // case today — nothing populates it), detect wave boundaries from the
257
+ // coordinator-written .claude/wave-scope.json `.wave` number, diffed
258
+ // against `last_wave` persisted in current-session.json. The explicit
259
+ // path above takes precedence — this branch only runs when wave_signal
260
+ // is absent (backward-compatible).
261
+ //
262
+ // Only a STRICT INCREASE (wave > last_wave AND wave > 0) is a real wave
263
+ // boundary. wave-scope.json is deleted mid-session at Quality phase
264
+ // transitions and final cleanup, so resolveWaveNumber() returns 0 in
265
+ // those windows — a drop to 0 (or any non-increase) is NOT a wave change
266
+ // and is ignored, preventing spurious emissions on every batch.
267
+ //
268
+ // Final-wave limitation: the LAST wave never receives a `completed` event
269
+ // here because there is no N+1 transition to trigger it. The coordinator
270
+ // emits the final orchestrator.wave.completed at session close.
271
+ try {
272
+ const wave = await resolveWaveNumber(SO_PROJECT_DIR);
273
+ if (wave > 0) {
274
+ // Read last_wave from the just-written session file (after the
275
+ // last_batch RMW above, so we observe the latest persisted value).
276
+ let lastWave = 0;
277
+ try {
278
+ const raw = await readFile(sessionFile, 'utf8');
279
+ const parsed = JSON.parse(raw);
280
+ if (typeof parsed.last_wave === 'number') lastWave = parsed.last_wave;
281
+ } catch { /* absent/unparseable → lastWave stays 0 */ }
282
+
283
+ if (wave > lastWave) {
284
+ // Close the prior wave first (only when there was one).
285
+ if (lastWave > 0) {
286
+ await emitEvent('orchestrator.wave.completed', {
287
+ wave_number: lastWave,
288
+ ...(batchId !== null ? { batch_id: batchId } : {}),
289
+ ...(batchSize !== null ? { batch_size: batchSize } : {}),
290
+ });
291
+ }
292
+ // Open the new wave.
293
+ await emitEvent('orchestrator.wave.started', {
294
+ wave_number: wave,
295
+ ...(nextWaveRole !== null ? { next_wave_role: nextWaveRole } : {}),
296
+ ...(batchId !== null ? { batch_id: batchId } : {}),
297
+ ...(batchSize !== null ? { batch_size: batchSize } : {}),
298
+ });
299
+ // Persist the high-water mark so the next batch does not re-emit.
300
+ await atomicMutateJson(sessionFile, {}, (current) => ({
301
+ ...current,
302
+ last_wave: wave,
303
+ }));
304
+ }
305
+ }
306
+ } catch { /* best-effort — hook must remain non-blocking */ }
307
+ }
308
+
309
+ // If a wave-complete signal is present, surface it as additionalContext so
310
+ // Claude sees the state change at the next turn boundary.
311
+ // PostToolBatch hookSpecificOutput shape per CC docs:
312
+ // { hookSpecificOutput: { hookEventName: "PostToolBatch", additionalContext: "<string>" } }
313
+ if (waveSignal === 'wave-complete') {
314
+ const waveLabel = waveNumber !== null ? `Wave ${waveNumber}` : 'Wave';
315
+ const nextRole = nextWaveRole ?? 'unknown';
316
+ const context = `${waveLabel} complete. Next agent role: ${nextRole}. ` +
317
+ `Batch ${batchId ?? 'n/a'} (${batchSize ?? 'n/a'} tools) resolved at ${completedAt}.`;
318
+ process.stdout.write(JSON.stringify({
319
+ hookSpecificOutput: {
320
+ hookEventName: 'PostToolBatch',
321
+ additionalContext: context,
322
+ },
323
+ }));
324
+ }
325
+ }
326
+
327
+ // Exit 0 always — informational hook must never block Claude.
328
+ main().catch(() => {}).finally(() => process.exit(0));
@@ -0,0 +1,248 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * post-tool-failure-corrective-context.mjs — PostToolUseFailure hook.
4
+ *
5
+ * Hook event: PostToolUseFailure (issue #342).
6
+ * Fires after a tool invocation exits with a non-zero status or produces an
7
+ * error payload. Appends a structured corrective-context note to the
8
+ * `corrective_context` array in `.orchestrator/current-session.json` so the
9
+ * coordinator and downstream skills can inspect recent tool failures without
10
+ * re-reading the full event log.
11
+ *
12
+ * Decision flow:
13
+ * 1. shouldRunHook gate — exit 0 immediately when the hook is disabled.
14
+ * 2. Read JSON payload from stdin: { tool_name, tool_input, error, exit_code }.
15
+ * 3. Build a compact note: { timestamp, tool_name, error_summary, exit_code }.
16
+ * error_summary is capped at 256 chars to keep the session file lean.
17
+ * 4. Atomic read-modify-write of .orchestrator/current-session.json:
18
+ * append to `corrective_context` array (create if absent), keep last 20
19
+ * entries to bound file growth.
20
+ * 5. Write to stderr only (stdout must remain clean — hook is informational).
21
+ *
22
+ * Exit codes: 0 always (informational, never blocking).
23
+ *
24
+ * hooks.json wiring is managed separately (W3-C4 scope).
25
+ */
26
+
27
+ import { readFile, writeFile, mkdir, rename } 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('post-tool-failure-corrective-context')) process.exit(0);
33
+
34
+ import { SO_PROJECT_DIR } from '../scripts/lib/platform.mjs';
35
+
36
+ // ---------------------------------------------------------------------------
37
+ // Constants
38
+ // ---------------------------------------------------------------------------
39
+
40
+ /** Maximum number of corrective context entries retained per session. */
41
+ const MAX_ENTRIES = 20;
42
+
43
+ /** Maximum length of error_summary field (chars). */
44
+ const MAX_ERROR_SUMMARY_CHARS = 256;
45
+
46
+ // ---------------------------------------------------------------------------
47
+ // Helpers
48
+ // ---------------------------------------------------------------------------
49
+
50
+ /**
51
+ * Read stdin to EOF (best-effort). Returns parsed JSON or null on failure.
52
+ * Uses a 5 s timeout consistent with Claude Code hook contract.
53
+ *
54
+ * @returns {Promise<object|null>}
55
+ */
56
+ function readStdinJson() {
57
+ return new Promise((resolve) => {
58
+ if (process.stdin.readableEnded || process.stdin.closed) {
59
+ resolve(null);
60
+ return;
61
+ }
62
+ const chunks = [];
63
+ const timer = setTimeout(() => { resolve(null); }, 5_000);
64
+ process.stdin.setEncoding('utf8');
65
+ process.stdin.on('data', (c) => chunks.push(c));
66
+ process.stdin.on('end', () => {
67
+ clearTimeout(timer);
68
+ const raw = chunks.join('').trim();
69
+ if (!raw) { resolve(null); return; }
70
+ try { resolve(JSON.parse(raw)); } catch { resolve(null); }
71
+ });
72
+ process.stdin.on('error', () => { clearTimeout(timer); resolve(null); });
73
+ process.stdin.resume();
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Atomic read-modify-write of a JSON file.
79
+ * Reads the existing file (or starts with `defaultValue` when absent),
80
+ * applies `mutate`, writes to a tmp file, renames over the original.
81
+ *
82
+ * @param {string} filePath
83
+ * @param {object} defaultValue — used when the file does not exist
84
+ * @param {function(object): object} mutate — pure transformer
85
+ */
86
+ async function atomicMutateJson(filePath, defaultValue, mutate) {
87
+ let current = defaultValue;
88
+ try {
89
+ const raw = await readFile(filePath, 'utf8');
90
+ current = JSON.parse(raw);
91
+ } catch {
92
+ // File absent or unparseable — start from defaultValue.
93
+ }
94
+
95
+ const updated = mutate(current);
96
+ const tmp = `${filePath}.tmp-ptf-${process.pid}-${Date.now()}`;
97
+ await mkdir(path.dirname(filePath), { recursive: true });
98
+ await writeFile(tmp, JSON.stringify(updated, null, 2) + '\n', 'utf8');
99
+
100
+ // Rename is atomic on POSIX (same-filesystem). On Windows this is best-effort
101
+ // via the fs.rename syscall (may fail if target is locked — swallowed by
102
+ // the catch in main()).
103
+ await rename(tmp, filePath);
104
+ }
105
+
106
+ // ---------------------------------------------------------------------------
107
+ // Main
108
+ // ---------------------------------------------------------------------------
109
+
110
+ /**
111
+ * Derive a short cause-hint and suggestion based on the tool name and
112
+ * error text. All strings are kept short to stay within the ~500-char
113
+ * additionalContext budget.
114
+ *
115
+ * @param {string|null} toolName
116
+ * @param {string|null} errorSummary
117
+ * @returns {{ cause: string, suggestion: string }}
118
+ */
119
+ function deriveHints(toolName, errorSummary) {
120
+ const err = (errorSummary ?? '').toLowerCase();
121
+
122
+ if (toolName === 'Bash') {
123
+ if (err.includes('permission denied') || err.includes('eacces')) {
124
+ return {
125
+ cause: 'insufficient file permissions',
126
+ suggestion: 'check file mode with `ls -la` and adjust with `chmod` if needed',
127
+ };
128
+ }
129
+ if (err.includes('command not found') || err.includes('enoent')) {
130
+ return {
131
+ cause: 'command or binary not on PATH',
132
+ suggestion: 'verify the binary is installed and `which <cmd>` resolves it',
133
+ };
134
+ }
135
+ if (err.includes('timeout') || err.includes('timed out')) {
136
+ return {
137
+ cause: 'command exceeded time limit',
138
+ suggestion: 'increase the timeout parameter or break the command into smaller steps',
139
+ };
140
+ }
141
+ return {
142
+ cause: 'shell command exited non-zero',
143
+ suggestion: 'inspect the error output above, fix the root cause, and retry',
144
+ };
145
+ }
146
+
147
+ if (toolName === 'Edit' || toolName === 'Write') {
148
+ if (err.includes('no such file') || err.includes('enoent')) {
149
+ return {
150
+ cause: 'target file or parent directory does not exist',
151
+ suggestion: 'create the missing directory with `mkdir -p` before writing',
152
+ };
153
+ }
154
+ if (err.includes('old_string not found') || err.includes('not unique')) {
155
+ return {
156
+ cause: 'old_string did not match any text in the file',
157
+ suggestion: 're-read the file to confirm the exact text, then retry with a wider context window',
158
+ };
159
+ }
160
+ return {
161
+ cause: 'file edit failed',
162
+ suggestion: 're-read the file to verify its current state, then retry',
163
+ };
164
+ }
165
+
166
+ if (toolName === 'Read') {
167
+ return {
168
+ cause: 'file could not be read (missing or unreadable)',
169
+ suggestion: 'verify the path exists and is accessible before retrying',
170
+ };
171
+ }
172
+
173
+ if (toolName === 'Glob' || toolName === 'Grep') {
174
+ return {
175
+ cause: 'search returned an error (bad pattern or missing directory)',
176
+ suggestion: 'check the pattern syntax and confirm the search root exists',
177
+ };
178
+ }
179
+
180
+ // Fallback for unknown tools.
181
+ return {
182
+ cause: 'tool invocation failed',
183
+ suggestion: 'check the error details above and retry with corrected parameters',
184
+ };
185
+ }
186
+
187
+ async function main() {
188
+ const input = await readStdinJson();
189
+
190
+ // Extract fields from the hook payload. All optional — missing fields are
191
+ // represented as null in the stored note.
192
+ const toolName = typeof input?.tool_name === 'string' ? input.tool_name : null;
193
+ const exitCode = typeof input?.exit_code === 'number' ? input.exit_code : null;
194
+
195
+ const rawError =
196
+ typeof input?.error === 'string'
197
+ ? input.error
198
+ : (input?.error !== null && input?.error !== undefined ? String(input.error) : null);
199
+
200
+ const errorSummary = rawError !== null
201
+ ? rawError.slice(0, MAX_ERROR_SUMMARY_CHARS)
202
+ : null;
203
+
204
+ const note = {
205
+ timestamp: new Date().toISOString(),
206
+ tool_name: toolName,
207
+ error_summary: errorSummary,
208
+ exit_code: exitCode,
209
+ };
210
+
211
+ const sessionFile = path.join(SO_PROJECT_DIR, '.orchestrator', 'current-session.json');
212
+
213
+ await atomicMutateJson(sessionFile, {}, (current) => {
214
+ const existing = Array.isArray(current.corrective_context)
215
+ ? current.corrective_context
216
+ : [];
217
+ // Append the new note and cap at MAX_ENTRIES (keep most-recent).
218
+ const updated = [...existing, note].slice(-MAX_ENTRIES);
219
+ return { ...current, corrective_context: updated };
220
+ });
221
+
222
+ // Surface corrective context to Claude via additionalContext on the next turn.
223
+ // PostToolUseFailure hookSpecificOutput shape per CC docs:
224
+ // { hookSpecificOutput: { hookEventName: "PostToolUseFailure", additionalContext: "<string>" } }
225
+ // Keep the message under ~500 chars so it stays readable.
226
+ const { cause, suggestion } = deriveHints(toolName, errorSummary);
227
+ const toolLabel = toolName ?? 'unknown tool';
228
+ const exitLabel = exitCode !== null ? ` (exit ${exitCode})` : '';
229
+ // Strip control chars (newlines, ANSI escapes) before forwarding to additionalContext —
230
+ // SEC-016 (Log Injection): tool errors may contain attacker-controlled bytes.
231
+ const safeSummary = errorSummary
232
+ ? errorSummary.replace(/[\r\n]/g, ' ').split('').join(' ').slice(0, 120)
233
+ : '';
234
+ const summaryLabel = safeSummary ? ` Error: ${safeSummary}` : '';
235
+ const additionalContext =
236
+ `Tool failure: ${toolLabel}${exitLabel}.${summaryLabel} ` +
237
+ `Common cause: ${cause}. Try: ${suggestion}.`;
238
+
239
+ process.stdout.write(JSON.stringify({
240
+ hookSpecificOutput: {
241
+ hookEventName: 'PostToolUseFailure',
242
+ additionalContext: additionalContext.slice(0, 500),
243
+ },
244
+ }));
245
+ }
246
+
247
+ // Exit 0 always — informational hook must never block Claude.
248
+ main().catch(() => {}).finally(() => process.exit(0));