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,112 @@
1
+ #!/usr/bin/env node
2
+ // check-component-paths.mjs — Validate plugin component path fields resolve to real locations.
3
+ // Covers: commands, agents, hooks, mcpServers path resolution from plugin.json.
4
+ // Usage: check-component-paths.mjs <plugin-root>
5
+ // Outputs lines of the form " PASS: ..." / " FAIL: ..."
6
+ // Exit 0 = all checks passed; exit 1 = at least one failure.
7
+
8
+ import { readFileSync, existsSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+
11
+ const [, , pluginRoot] = process.argv;
12
+
13
+ if (!pluginRoot) {
14
+ console.error('Usage: check-component-paths.mjs <plugin-root>');
15
+ process.exit(1);
16
+ }
17
+
18
+ const PLUGIN_JSON = join(pluginRoot, '.claude-plugin', 'plugin.json');
19
+
20
+ let passed = 0;
21
+ let failed = 0;
22
+
23
+ function pass(msg) {
24
+ console.log(` PASS: ${msg}`);
25
+ passed++;
26
+ }
27
+
28
+ function fail(msg) {
29
+ console.log(` FAIL: ${msg}`);
30
+ failed++;
31
+ }
32
+
33
+ // ============================================================================
34
+ // Check 4: Component path fields resolve to real files/directories
35
+ // ============================================================================
36
+ console.log('--- Check 4: component paths ---');
37
+
38
+ // Load plugin.json — required for all checks below
39
+ let json;
40
+ try {
41
+ json = JSON.parse(readFileSync(PLUGIN_JSON, 'utf8'));
42
+ } catch {
43
+ fail(`plugin.json not found or invalid JSON at ${PLUGIN_JSON}`);
44
+ console.log('');
45
+ console.log(`Results: ${passed} passed, ${failed} failed`);
46
+ process.exit(1);
47
+ }
48
+
49
+ // Conventional auto-discovery locations (relative to plugin root)
50
+ const CONVENTIONAL = {
51
+ commands: 'commands',
52
+ agents: 'agents',
53
+ hooks: 'hooks/hooks.json',
54
+ mcpServers: '.mcp.json',
55
+ };
56
+
57
+ /**
58
+ * Strip a leading "./" from a path string.
59
+ * @param {string} p
60
+ * @returns {string}
61
+ */
62
+ function stripLeadingDotSlash(p) {
63
+ return p.replace(/^\.\//, '');
64
+ }
65
+
66
+ /**
67
+ * Check that a component path field either resolves to a real path or
68
+ * falls back to a conventional location.
69
+ *
70
+ * @param {string} field - JSON field name (e.g. "commands")
71
+ * @param {string} conventional - Conventional relative path under pluginRoot
72
+ * @param {boolean} optional - If true, missing conventional path is a PASS
73
+ */
74
+ function checkComponentPath(field, conventional, optional = false) {
75
+ const relPath = json[field] || '';
76
+
77
+ if (!relPath) {
78
+ // No explicit value — try conventional auto-discovery
79
+ const absPath = join(pluginRoot, conventional);
80
+ if (existsSync(absPath)) {
81
+ pass(`${field} auto-discovered at: ./${conventional}`);
82
+ } else if (optional) {
83
+ pass(`${field} not found at conventional location (optional, skipped)`);
84
+ } else {
85
+ fail(`${field} not found at conventional location: ./${conventional}`);
86
+ }
87
+ return;
88
+ }
89
+
90
+ // Explicit value — must start with "./"
91
+ if (!relPath.startsWith('./')) {
92
+ fail(`${field} path does not start with ./: ${relPath}`);
93
+ return;
94
+ }
95
+
96
+ const absPath = join(pluginRoot, stripLeadingDotSlash(relPath));
97
+ if (existsSync(absPath)) {
98
+ pass(`${field} resolves to: ${relPath}`);
99
+ } else {
100
+ fail(`${field} path does not exist: ${relPath} (resolved to ${absPath})`);
101
+ }
102
+ }
103
+
104
+ checkComponentPath('commands', CONVENTIONAL.commands);
105
+ checkComponentPath('agents', CONVENTIONAL.agents);
106
+ checkComponentPath('hooks', CONVENTIONAL.hooks);
107
+ checkComponentPath('mcpServers', CONVENTIONAL.mcpServers, true);
108
+
109
+ console.log('');
110
+ console.log(`Results: ${passed} passed, ${failed} failed`);
111
+
112
+ process.exit(failed > 0 ? 1 : 0);
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env node
2
+ // check-dead-bridge.mjs — Dead-bridge validator (dangling refs + bridge balance).
3
+ //
4
+ // Issue #671. Generalises the #618 baseline-fetch-bridge guard
5
+ // (check-baseline-fetch-bridge.mjs) into a corpus-driven dead-bridge detector:
6
+ // a "bridge" is a documented hand-off between two surfaces (a guard naming a
7
+ // file, a doc pointer to a script, a Phase reference to a skill, …). A bridge
8
+ // is DEAD when one end dangles — the referenced file/symbol no longer exists,
9
+ // or the two ends of a documented pair are unbalanced.
10
+ //
11
+ // This module is the CLI ORCHESTRATOR. It owns the real-fs IO (RepoContext),
12
+ // drives the FROZEN-contract detectors, prints PASS/FAIL lines, and sets the
13
+ // exit code. The detection logic and the corpus of known bridges live in the
14
+ // two sibling modules imported below.
15
+ //
16
+ // Usage: check-dead-bridge.mjs <plugin-root>
17
+ // Outputs lines of the form " PASS: ..." / " FAIL: ...".
18
+ // Exit 0 = all bridges intact; 1 = at least one dead bridge; 2 = tool error
19
+ // (a detector reported a `*-tool-error` rule — e.g. an unreadable surface).
20
+ //
21
+ // Import-safety: importing `runCheckDeadBridge` MUST NOT trigger any execution
22
+ // or process.exit — the isMain guard at the bottom is the only side-effecting
23
+ // path. The Quality wave imports runCheckDeadBridge directly for unit tests.
24
+
25
+ import { pathToFileURL } from 'node:url';
26
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
27
+ import path from 'node:path';
28
+ import { DETECTORS } from './dead-bridge-detectors.mjs';
29
+ import * as corpus from './dead-bridge-corpus.mjs';
30
+
31
+ const DEFAULT_EXTS = ['.mjs', '.md'];
32
+
33
+ /**
34
+ * Recursively collect absolute paths under `absDir` whose extension is in
35
+ * `exts`. Returns [] when `absDir` is missing or not a directory. Defensive:
36
+ * an unreadable sub-directory is skipped rather than throwing, so a single bad
37
+ * entry never aborts the whole walk (tool-error surfacing is the detectors'
38
+ * job, via readText/exists on a specific surface).
39
+ *
40
+ * @param {string} absDir
41
+ * @param {string[] | null} exts null/undefined → match every file
42
+ * @returns {string[]}
43
+ */
44
+ function walk(absDir, exts) {
45
+ /** @type {string[]} */
46
+ const out = [];
47
+ let entries;
48
+ try {
49
+ if (!existsSync(absDir) || !statSync(absDir).isDirectory()) return out;
50
+ entries = readdirSync(absDir, { withFileTypes: true });
51
+ } catch {
52
+ return out;
53
+ }
54
+ for (const ent of entries) {
55
+ const full = path.join(absDir, ent.name);
56
+ let isDir;
57
+ let isFile;
58
+ try {
59
+ // Dirent gives the type directly; fall back to statSync for symlinks etc.
60
+ isDir = ent.isDirectory();
61
+ isFile = ent.isFile();
62
+ if (!isDir && !isFile && ent.isSymbolicLink()) {
63
+ const st = statSync(full);
64
+ isDir = st.isDirectory();
65
+ isFile = st.isFile();
66
+ }
67
+ } catch {
68
+ continue;
69
+ }
70
+ if (isDir) {
71
+ out.push(...walk(full, exts));
72
+ } else if (isFile) {
73
+ if (!exts || exts.includes(path.extname(full))) out.push(full);
74
+ }
75
+ }
76
+ return out;
77
+ }
78
+
79
+ /**
80
+ * Build the RepoContext handed to every detector. All IO is real node:fs and
81
+ * lives ONLY here — detectors are pure functions of (ctx, corpus).
82
+ *
83
+ * @param {string} pluginRoot
84
+ * @returns {{
85
+ * pluginRoot: string,
86
+ * listMdFiles: (absDir: string) => string[],
87
+ * listFiles: (absDir: string, exts?: string[]) => string[],
88
+ * readText: (absPath: string) => string,
89
+ * exists: (absPath: string) => boolean,
90
+ * }}
91
+ */
92
+ export function buildRepoContext(pluginRoot) {
93
+ return {
94
+ pluginRoot,
95
+ listMdFiles: (absDir) => walk(absDir, ['.md']),
96
+ listFiles: (absDir, exts = DEFAULT_EXTS) => walk(absDir, exts),
97
+ readText: (absPath) => readFileSync(absPath, 'utf8'),
98
+ exists: (absPath) => existsSync(absPath),
99
+ };
100
+ }
101
+
102
+ /**
103
+ * Relativize an absolute path against the plugin root for human-readable
104
+ * output. Falls back to the raw path when it lies outside the root.
105
+ *
106
+ * @param {string} root
107
+ * @param {string} abs
108
+ * @returns {string}
109
+ */
110
+ function relativize(root, abs) {
111
+ return path.relative(root, abs);
112
+ }
113
+
114
+ /**
115
+ * Run the dead-bridge validator against a plugin root. Drives every frozen
116
+ * detector, prints a PASS line per clean detector and a FAIL line per finding,
117
+ * then a Results summary. Returns the process exit code.
118
+ *
119
+ * @param {string} pluginRoot
120
+ * @returns {number} 0 = all bridges intact; 1 = dead bridge(s); 2 = tool error.
121
+ */
122
+ export function runCheckDeadBridge(pluginRoot) {
123
+ const ctx = buildRepoContext(pluginRoot);
124
+
125
+ console.log('--- Check: dead-bridge validator (dangling refs + bridge balance) ---');
126
+
127
+ // Run every detector, collecting findings tagged by their producing detector.
128
+ /** @type {Array<{ rule: string, severity: string, file: string, line: number, message: string }>} */
129
+ const findings = [];
130
+ /** @type {Set<string>} */
131
+ const detectorsWithFindings = new Set();
132
+ /** @type {string[]} */
133
+ const allDetectorIds = [];
134
+ let toolError = false;
135
+
136
+ for (const { id, fn } of DETECTORS) {
137
+ allDetectorIds.push(id);
138
+ const out = fn(ctx, corpus) || [];
139
+ for (const f of out) {
140
+ findings.push(f);
141
+ detectorsWithFindings.add(id);
142
+ if (typeof f.rule === 'string' && f.rule.endsWith('-tool-error')) toolError = true;
143
+ }
144
+ }
145
+
146
+ // PASS line per detector that produced zero findings; FAIL line per finding.
147
+ // Detectors are processed in DETECTORS order; PASS lines are emitted first so
148
+ // the clean surfaces read before the failures (mirrors check-rules.mjs flow).
149
+ for (const id of allDetectorIds) {
150
+ if (!detectorsWithFindings.has(id)) {
151
+ console.log(` PASS: ${id} — no dead bridges detected`);
152
+ }
153
+ }
154
+
155
+ for (const f of findings) {
156
+ const loc = f.file ? `${relativize(pluginRoot, f.file)}:${f.line} — ` : '';
157
+ console.log(` FAIL: ${loc}${f.message}`);
158
+ }
159
+
160
+ const passed = allDetectorIds.length - detectorsWithFindings.size;
161
+ const failed = findings.length;
162
+
163
+ console.log('');
164
+ console.log(`Results: ${passed} passed, ${failed} failed`);
165
+
166
+ if (toolError) return 2;
167
+ return failed > 0 ? 1 : 0;
168
+ }
169
+
170
+ // CLI entry — only when executed directly, never on import (keeps the exports
171
+ // safe to import from tests without triggering process.exit).
172
+ const isMain = import.meta.url === pathToFileURL(process.argv[1] || '').href;
173
+ if (isMain) {
174
+ const pluginRoot = process.argv[2];
175
+ if (!pluginRoot) {
176
+ console.error('Usage: check-dead-bridge.mjs <plugin-root>');
177
+ process.exit(2);
178
+ }
179
+ process.exit(runCheckDeadBridge(pluginRoot));
180
+ }
@@ -0,0 +1,258 @@
1
+ #!/usr/bin/env node
2
+ // scripts/lib/validate/check-hooks-symmetry.mjs
3
+ // Verify event-key + handler-file symmetry across hooks/{hooks,hooks-codex,hooks-cursor,hooks-pi}.json
4
+ // Exit 0 = all checks pass, 1 = any check fails
5
+ // Stdout: ' PASS: ...' / ' FAIL: ...' lines + 'Results: N passed, M failed'
6
+
7
+ import { readFileSync, existsSync, readdirSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+
10
+ const PLUGIN_ROOT = process.argv[2];
11
+ if (!PLUGIN_ROOT) {
12
+ console.error('Usage: check-hooks-symmetry.mjs <plugin-root>');
13
+ process.exit(1);
14
+ }
15
+
16
+ const HOOKS_DIR = join(PLUGIN_ROOT, 'hooks');
17
+
18
+ // Documented asymmetries — events expected to be missing from specific configs.
19
+ // Anything NOT in this list that's asymmetric → FAIL (drift).
20
+ const DOCUMENTED_ASYMMETRIES = {
21
+ // Events from hooks.json/hooks-codex.json that are intentionally absent in hooks-cursor.json
22
+ cursorMissingFromMain: ['SessionStart', 'SessionEnd', 'PostToolUse', 'PostToolUseFailure', 'PostToolBatch', 'Stop', 'SubagentStart', 'SubagentStop', 'CwdChanged', 'PreToolUse'],
23
+ // Events unique to hooks-cursor.json (Cursor IDE-specific)
24
+ cursorOnly: ['afterFileEdit', 'beforeShellExecution'],
25
+ // Claude/Codex events with no Pi-native v1 mapping yet.
26
+ piMissingFromMain: ['PostToolUseFailure', 'PostToolBatch', 'SubagentStart', 'SubagentStop', 'CwdChanged'],
27
+ // Pi-native extension events that map onto Claude/Codex hook events.
28
+ piEventMap: {
29
+ session_start: 'SessionStart',
30
+ session_shutdown: 'SessionEnd',
31
+ tool_call: 'PreToolUse',
32
+ tool_result: 'PostToolUse',
33
+ agent_end: 'Stop',
34
+ },
35
+ };
36
+
37
+ const REQUIRED_CODEX_EVENTS = [
38
+ 'SessionStart',
39
+ 'PreToolUse',
40
+ 'PostToolUse',
41
+ 'SubagentStart',
42
+ 'SubagentStop',
43
+ 'Stop',
44
+ ];
45
+ const FORBIDDEN_CODEX_EVENTS = [
46
+ 'SessionEnd',
47
+ 'PostToolUseFailure',
48
+ 'PostToolBatch',
49
+ 'CwdChanged',
50
+ ];
51
+
52
+ const REQUIRED_PI_TOOL_HANDLERS = {
53
+ bash: ['pre-bash-destructive-guard.mjs', 'enforce-commands.mjs'],
54
+ edit: ['enforce-scope.mjs', 'config-protection.mjs'],
55
+ write: ['enforce-scope.mjs', 'config-protection.mjs'],
56
+ };
57
+
58
+ let passed = 0;
59
+ let failed = 0;
60
+
61
+ function pass(msg) { console.log(` PASS: ${msg}`); passed++; }
62
+ function fail(msg) { console.log(` FAIL: ${msg}`); failed++; }
63
+
64
+ // Step 1: Load JSON files — required files exit on error; cursor is optional (returns undefined)
65
+ function loadJson(filePath, required = true) {
66
+ if (!required && !existsSync(filePath)) return undefined;
67
+ try {
68
+ return JSON.parse(readFileSync(filePath, 'utf8'));
69
+ } catch (e) {
70
+ fail(`${filePath.split('/').pop()}: ${e.message}`);
71
+ process.exit(1);
72
+ }
73
+ }
74
+
75
+ const packageJson = loadJson(join(PLUGIN_ROOT, 'package.json'), false);
76
+ const piPackageRequired = Boolean(packageJson?.pi);
77
+ const claudeJson = loadJson(join(HOOKS_DIR, 'hooks.json'));
78
+ const codexJson = loadJson(join(HOOKS_DIR, 'hooks-codex.json'));
79
+ const cursorJson = loadJson(join(HOOKS_DIR, 'hooks-cursor.json'), false);
80
+ const piJson = loadJson(join(HOOKS_DIR, 'hooks-pi.json'), piPackageRequired);
81
+
82
+ // Step 2: Extract event keys
83
+ const claudeEvents = new Set(Object.keys(claudeJson.hooks || {}));
84
+ const codexEvents = new Set(Object.keys(codexJson.hooks || {}));
85
+ const cursorEvents = cursorJson ? new Set(Object.keys(cursorJson.hooks || {})) : new Set();
86
+ const piEvents = piJson ? new Set(Object.keys(piJson.hooks || {})) : new Set();
87
+
88
+ // Step 3: Codex exposes a deliberate subset of the broader Claude event surface.
89
+ console.log('--- Check 1: hooks-codex.json required/forbidden event surface ---');
90
+ const missingRequiredCodex = REQUIRED_CODEX_EVENTS.filter((event) => !codexEvents.has(event));
91
+ if (missingRequiredCodex.length === 0) {
92
+ pass(`required Codex event subset is present (${REQUIRED_CODEX_EVENTS.join(', ')})`);
93
+ } else {
94
+ fail(`hooks-codex.json missing required events: ${missingRequiredCodex.join(', ')}`);
95
+ }
96
+
97
+ const forbiddenCodex = FORBIDDEN_CODEX_EVENTS.filter((event) => codexEvents.has(event));
98
+ if (forbiddenCodex.length === 0) {
99
+ pass('hooks-codex.json excludes all forbidden Claude-only events');
100
+ } else {
101
+ fail(`hooks-codex.json has forbidden unsupported events: ${forbiddenCodex.join(', ')}`);
102
+ }
103
+
104
+ // Step 4: cursor asymmetries must be documented
105
+ console.log('');
106
+ console.log('--- Check 2: hooks-cursor.json documented asymmetries ---');
107
+ if (cursorJson) {
108
+ const cursorMissing = [...claudeEvents].filter((e) => !cursorEvents.has(e));
109
+ const undocumentedMissing = cursorMissing.filter((e) => !DOCUMENTED_ASYMMETRIES.cursorMissingFromMain.includes(e));
110
+ if (undocumentedMissing.length === 0) {
111
+ pass(`hooks-cursor.json missing events are all documented (${cursorMissing.length} events: ${cursorMissing.join(', ')})`);
112
+ } else {
113
+ fail(`hooks-cursor.json missing UNDOCUMENTED events: ${undocumentedMissing.join(', ')}`);
114
+ }
115
+
116
+ const cursorExtra = [...cursorEvents].filter((e) => !claudeEvents.has(e));
117
+ const undocumentedExtra = cursorExtra.filter((e) => !DOCUMENTED_ASYMMETRIES.cursorOnly.includes(e));
118
+ if (undocumentedExtra.length === 0) {
119
+ pass(`hooks-cursor.json cursor-only events are all documented (${cursorExtra.length} events: ${cursorExtra.join(', ')})`);
120
+ } else {
121
+ fail(`hooks-cursor.json has UNDOCUMENTED extra events: ${undocumentedExtra.join(', ')}`);
122
+ }
123
+ } else {
124
+ pass(`hooks-cursor.json absent (optional config)`);
125
+ }
126
+
127
+ // Step 5: pi native-event mappings must cover all non-documented main events
128
+ console.log('');
129
+ console.log('--- Check 3: hooks-pi.json documented mappings ---');
130
+ if (piJson) {
131
+ const piCoveredMainEvents = new Set();
132
+ for (const [piEvent, mainEvent] of Object.entries(DOCUMENTED_ASYMMETRIES.piEventMap)) {
133
+ if (piEvents.has(piEvent)) piCoveredMainEvents.add(mainEvent);
134
+ }
135
+
136
+ const piMissing = [...claudeEvents].filter((e) =>
137
+ !piCoveredMainEvents.has(e) && !DOCUMENTED_ASYMMETRIES.piMissingFromMain.includes(e));
138
+ if (piMissing.length === 0) {
139
+ pass(`hooks-pi.json covers mapped main events; missing events are documented (${DOCUMENTED_ASYMMETRIES.piMissingFromMain.join(', ')})`);
140
+ } else {
141
+ fail(`hooks-pi.json missing UNDOCUMENTED main-event mappings: ${piMissing.join(', ')}`);
142
+ }
143
+
144
+ const knownPiEvents = new Set(Object.keys(DOCUMENTED_ASYMMETRIES.piEventMap));
145
+ const piExtra = [...piEvents].filter((e) => !knownPiEvents.has(e));
146
+ if (piExtra.length === 0) {
147
+ pass(`hooks-pi.json pi-native events are all mapped (${piEvents.size} events)`);
148
+ } else {
149
+ fail(`hooks-pi.json has UNDOCUMENTED pi-native events: ${piExtra.join(', ')}`);
150
+ }
151
+
152
+ const missingToolHandlers = requiredPiToolHandlerGaps(piJson);
153
+ if (missingToolHandlers.length === 0) {
154
+ pass('hooks-pi.json wires required tool_call handlers for bash, edit, and write');
155
+ } else {
156
+ fail(`hooks-pi.json missing required tool_call handlers: ${missingToolHandlers.join('; ')}`);
157
+ }
158
+ } else {
159
+ pass(`hooks-pi.json absent (optional config)`);
160
+ }
161
+
162
+ // Step 6: Extract handler-file refs from each config
163
+ // Handles two shapes:
164
+ // Claude/Codex: hooks[event] = Array<{ hooks: Array<{ command: "node \"$CLAUDE_PLUGIN_ROOT/hooks/foo.mjs\"" }> }>
165
+ // Cursor: hooks[event] = { script: "hooks/foo.mjs" }
166
+ function extractHandlers(json) {
167
+ const handlers = new Set();
168
+ for (const event of Object.values(json.hooks || {})) {
169
+ const matchers = Array.isArray(event) ? event : [event];
170
+ for (const m of matchers) {
171
+ // Cursor shape: script field at matcher level
172
+ if (typeof m.script === 'string') {
173
+ const scriptMatch = m.script.match(/(?:hooks\/)([\w/-]+\.mjs)/);
174
+ if (scriptMatch) handlers.add(scriptMatch[1]);
175
+ }
176
+ // Claude/Codex shape: nested hooks array with command field
177
+ const hookList = m.hooks || [];
178
+ for (const h of hookList) {
179
+ const cmd = h.command || h.script || '';
180
+ const match = cmd.match(/(?:hooks\/|\$\{?CLAUDE_PLUGIN_ROOT\}?\/hooks\/|\$\{?CODEX_PLUGIN_ROOT\}?\/hooks\/|\$\{?PI_PLUGIN_ROOT\}?\/hooks\/)([\w/-]+\.mjs)/);
181
+ if (match) handlers.add(match[1]);
182
+ }
183
+ }
184
+ }
185
+ return handlers;
186
+ }
187
+
188
+ function matcherMatches(matcher, target) {
189
+ if (!matcher || matcher === '*') return true;
190
+ return matcher.split('|').map((p) => p.trim().toLowerCase()).includes(target);
191
+ }
192
+
193
+ function handlersForPiTool(json, toolName) {
194
+ const handlers = new Set();
195
+ const entries = Array.isArray(json.hooks?.tool_call) ? json.hooks.tool_call : [];
196
+ for (const entry of entries) {
197
+ const matcher = typeof entry.matcher === 'string' ? entry.matcher.toLowerCase() : '';
198
+ if (!matcherMatches(matcher, toolName)) continue;
199
+ for (const hook of Array.isArray(entry.hooks) ? entry.hooks : []) {
200
+ const cmd = hook.command || hook.script || '';
201
+ const match = cmd.match(/(?:hooks\/|\$\{?PI_PLUGIN_ROOT\}?\/hooks\/)([\w/-]+\.mjs)/);
202
+ if (match) handlers.add(match[1]);
203
+ }
204
+ }
205
+ return handlers;
206
+ }
207
+
208
+ function requiredPiToolHandlerGaps(json) {
209
+ const gaps = [];
210
+ for (const [toolName, requiredHandlers] of Object.entries(REQUIRED_PI_TOOL_HANDLERS)) {
211
+ const handlers = handlersForPiTool(json, toolName);
212
+ for (const required of requiredHandlers) {
213
+ if (!handlers.has(required)) gaps.push(`${toolName} → ${required}`);
214
+ }
215
+ }
216
+ return gaps;
217
+ }
218
+ const claudeHandlers = extractHandlers(claudeJson);
219
+ const codexHandlers = extractHandlers(codexJson);
220
+ const cursorHandlers = cursorJson ? extractHandlers(cursorJson) : new Set();
221
+ const piHandlers = piJson ? extractHandlers(piJson) : new Set();
222
+ const allHandlers = new Set([...claudeHandlers, ...codexHandlers, ...cursorHandlers, ...piHandlers]);
223
+
224
+ // Step 7: Verify each handler file exists on disk (skip _lib/* — those are library modules)
225
+ console.log('');
226
+ console.log('--- Check 4: handler files exist on disk ---');
227
+ const missing = [];
228
+ for (const h of allHandlers) {
229
+ if (h.startsWith('_lib/')) continue; // library modules, not hook handlers
230
+ if (!existsSync(join(HOOKS_DIR, h))) {
231
+ missing.push(h);
232
+ }
233
+ }
234
+ if (missing.length === 0) {
235
+ pass(`all ${allHandlers.size} handler files exist on disk`);
236
+ } else {
237
+ fail(`handler files referenced but missing: ${missing.join(', ')}`);
238
+ }
239
+
240
+ // Step 8: Reverse — find .mjs files in hooks/ that are NOT referenced anywhere (potential dead code)
241
+ // (informational only — not a fail; ship as PASS noting count, with a stretch-goal output)
242
+ console.log('');
243
+ console.log('--- Check 5: no orphan .mjs files in hooks/ ---');
244
+ let dirEntries = [];
245
+ try { dirEntries = readdirSync(HOOKS_DIR); } catch { /* empty */ }
246
+ const onDisk = dirEntries.filter((f) => f.endsWith('.mjs'));
247
+ const unreferenced = onDisk.filter((f) => !allHandlers.has(f));
248
+ if (unreferenced.length === 0) {
249
+ pass(`no orphan .mjs files in hooks/ (${onDisk.length} files all referenced)`);
250
+ } else {
251
+ // INFO not FAIL — orphans are tolerated for now (e.g., _lib/ modules)
252
+ pass(`hooks/ has ${unreferenced.length} unreferenced .mjs files (allowed; they may be library helpers): ${unreferenced.join(', ')}`);
253
+ }
254
+
255
+ // Final
256
+ console.log('');
257
+ console.log(`Results: ${passed} passed, ${failed} failed`);
258
+ process.exit(failed > 0 ? 1 : 0);
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ // check-json-files.mjs — Validate hooks and mcpServers JSON file contents.
3
+ // Usage: check-json-files.mjs <plugin-root>
4
+ // Outputs lines of the form " PASS: ..." / " FAIL: ..."
5
+ // Exit 0 = all checks passed; exit 1 = at least one failure.
6
+
7
+ import { readFileSync, existsSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+
10
+ const [, , pluginRoot] = process.argv;
11
+
12
+ if (!pluginRoot) {
13
+ console.error('Usage: check-json-files.mjs <plugin-root>');
14
+ process.exit(1);
15
+ }
16
+
17
+ const PLUGIN_JSON = join(pluginRoot, '.claude-plugin', 'plugin.json');
18
+ const CONVENTIONAL_HOOKS = 'hooks/hooks.json';
19
+
20
+ let passed = 0;
21
+ let failed = 0;
22
+
23
+ function pass(msg) {
24
+ console.log(` PASS: ${msg}`);
25
+ passed++;
26
+ }
27
+
28
+ function fail(msg) {
29
+ console.log(` FAIL: ${msg}`);
30
+ failed++;
31
+ }
32
+
33
+ function isValidJson(filePath) {
34
+ try {
35
+ JSON.parse(readFileSync(filePath, 'utf8'));
36
+ return true;
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+
42
+ // Read plugin.json to resolve configured paths
43
+ let pluginData = {};
44
+ if (existsSync(PLUGIN_JSON)) {
45
+ try {
46
+ pluginData = JSON.parse(readFileSync(PLUGIN_JSON, 'utf8'));
47
+ } catch {
48
+ // plugin.json invalid — proceed with empty data; path checks will use auto-discovery
49
+ }
50
+ }
51
+
52
+ // ============================================================================
53
+ // Check 5: hooks file is valid JSON (if it's a .json file)
54
+ // ============================================================================
55
+ console.log('--- Check 5: hooks JSON validity ---');
56
+
57
+ const hooksPath = pluginData.hooks ?? '';
58
+ if (hooksPath && hooksPath.endsWith('.json')) {
59
+ const hooksAbs = join(pluginRoot, hooksPath.replace(/^\.\//, ''));
60
+ if (existsSync(hooksAbs)) {
61
+ if (isValidJson(hooksAbs)) {
62
+ pass('hooks file is valid JSON');
63
+ } else {
64
+ fail(`hooks file is not valid JSON: ${hooksPath}`);
65
+ }
66
+ } else {
67
+ fail('hooks file not found (already reported above)');
68
+ }
69
+ } else {
70
+ const hooksAbs = join(pluginRoot, CONVENTIONAL_HOOKS);
71
+ if (existsSync(hooksAbs)) {
72
+ if (isValidJson(hooksAbs)) {
73
+ pass(`hooks file is valid JSON (auto-discovered at ./${CONVENTIONAL_HOOKS})`);
74
+ } else {
75
+ fail(`hooks file is not valid JSON: ./${CONVENTIONAL_HOOKS}`);
76
+ }
77
+ } else {
78
+ pass('hooks is not a JSON file or not specified (skipped)');
79
+ }
80
+ }
81
+
82
+ // ============================================================================
83
+ // Check 5b: mcpServers file is valid JSON (if specified)
84
+ // ============================================================================
85
+ console.log('');
86
+ console.log('--- Check 5b: mcpServers JSON validity ---');
87
+
88
+ const mcpPath = pluginData.mcpServers ?? '';
89
+ if (mcpPath && mcpPath.endsWith('.json')) {
90
+ const mcpAbs = join(pluginRoot, mcpPath.replace(/^\.\//, ''));
91
+ if (existsSync(mcpAbs)) {
92
+ if (isValidJson(mcpAbs)) {
93
+ pass('mcpServers file is valid JSON');
94
+ } else {
95
+ fail(`mcpServers file is not valid JSON: ${mcpPath}`);
96
+ }
97
+ } else {
98
+ fail('mcpServers file not found (already reported above)');
99
+ }
100
+ } else {
101
+ const mcpAbs = join(pluginRoot, '.mcp.json');
102
+ if (existsSync(mcpAbs)) {
103
+ if (isValidJson(mcpAbs)) {
104
+ pass('mcpServers file is valid JSON (auto-discovered at ./.mcp.json)');
105
+ } else {
106
+ fail('mcpServers file is not valid JSON: ./.mcp.json');
107
+ }
108
+ } else {
109
+ pass('mcpServers not found at conventional location (optional, skipped)');
110
+ }
111
+ }
112
+
113
+ console.log('');
114
+ console.log(`Results: ${passed} passed, ${failed} failed`);
115
+
116
+ process.exit(failed > 0 ? 1 : 0);