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,457 @@
1
+ #!/usr/bin/env node
2
+ // check-agents.mjs — Validate agent .md files have valid YAML frontmatter.
3
+ // Usage: check-agents.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, readdirSync, existsSync } from 'node:fs';
8
+ import { join, resolve, dirname } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { ALLOWED_MODEL_ALIASES, MODEL_ID_RE } from '../agent-frontmatter.mjs';
11
+
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+
14
+ // Lazy-loaded from tier-inference.mjs on first use in Check 8.
15
+ let _tierModule = null;
16
+ async function getTierModule() {
17
+ if (!_tierModule) {
18
+ _tierModule = await import(join(__dirname, 'tier-inference.mjs'));
19
+ }
20
+ return _tierModule;
21
+ }
22
+
23
+ const [, , pluginRoot] = process.argv;
24
+
25
+ if (!pluginRoot) {
26
+ console.error('Usage: check-agents.mjs <plugin-root>');
27
+ process.exit(1);
28
+ }
29
+
30
+ const PLUGIN_JSON = join(pluginRoot, '.claude-plugin', 'plugin.json');
31
+ const CONVENTIONAL_AGENTS = 'agents';
32
+
33
+ // Nested instruction files (CLAUDE.md / AGENTS.md) may live in agents/ as
34
+ // per-directory authoring conventions (Anthropic large-codebase layered-doc
35
+ // pattern). They are NOT agent definitions and must be excluded from
36
+ // frontmatter / output-schema / sandbox-tier validation.
37
+ const INSTRUCTION_FILENAMES = new Set(['AGENTS.md', 'CLAUDE.md']);
38
+ const isAgentDefFile = (f) => f.endsWith('.md') && !INSTRUCTION_FILENAMES.has(f);
39
+
40
+ let passed = 0;
41
+ let failed = 0;
42
+
43
+ function pass(msg) {
44
+ console.log(` PASS: ${msg}`);
45
+ passed++;
46
+ }
47
+
48
+ function warn(msg) {
49
+ console.log(` WARN: ${msg}`);
50
+ }
51
+
52
+ function fail(msg) {
53
+ console.log(` FAIL: ${msg}`);
54
+ failed++;
55
+ }
56
+
57
+ /**
58
+ * Extract YAML frontmatter content (between first --- and second ---).
59
+ * Returns null if no valid frontmatter block found.
60
+ */
61
+ function extractFrontmatter(content) {
62
+ const m = content.match(/^---\n([\s\S]*?)\n---/);
63
+ return m ? m[1] : null;
64
+ }
65
+
66
+ /**
67
+ * Get a scalar field value from frontmatter text.
68
+ * Returns null if field not present.
69
+ */
70
+ function getField(fm, name) {
71
+ const m = fm.match(new RegExp(`^${name}:\\s*(.+)$`, 'm'));
72
+ return m ? m[1].trim() : null;
73
+ }
74
+
75
+ /**
76
+ * Check whether a field key is present in frontmatter (even with empty/block value).
77
+ */
78
+ function hasField(fm, name) {
79
+ return new RegExp(`^${name}:`, 'm').test(fm);
80
+ }
81
+
82
+ /**
83
+ * Parse the tools field value into an array of tool name strings.
84
+ * Handles comma-separated strings ("Read, Edit, Write") and JSON arrays.
85
+ * Returns [] if toolsVal is null/empty or unparseable.
86
+ */
87
+ function parseToolsValue(toolsVal) {
88
+ if (!toolsVal) return [];
89
+ const v = toolsVal.trim();
90
+ if (v.startsWith('[')) {
91
+ try {
92
+ const arr = JSON.parse(v);
93
+ return Array.isArray(arr) ? arr.filter((t) => typeof t === 'string') : [];
94
+ } catch {
95
+ return [];
96
+ }
97
+ }
98
+ // Comma-separated string: split on comma, strip whitespace.
99
+ return v.split(',').map((t) => t.trim()).filter(Boolean);
100
+ }
101
+
102
+ // ============================================================================
103
+ // Check 6: Agent .md files have valid YAML frontmatter
104
+ // ============================================================================
105
+ console.log('--- Check 6: agent frontmatter ---');
106
+
107
+ // Resolve agents directory from plugin.json or fall back to conventional location.
108
+ let agentsDir;
109
+ if (existsSync(PLUGIN_JSON)) {
110
+ let pluginData = {};
111
+ try {
112
+ pluginData = JSON.parse(readFileSync(PLUGIN_JSON, 'utf8'));
113
+ } catch {
114
+ // ignore parse errors — fall back to conventional
115
+ }
116
+ const agentsPath = pluginData.agents;
117
+ if (agentsPath) {
118
+ // Strip leading ./ if present, then join to plugin root
119
+ agentsDir = join(pluginRoot, agentsPath.replace(/^\.\//, ''));
120
+ }
121
+ }
122
+ if (!agentsDir) {
123
+ agentsDir = join(pluginRoot, CONVENTIONAL_AGENTS);
124
+ }
125
+
126
+ if (!existsSync(agentsDir)) {
127
+ const agentsPath = (() => {
128
+ try {
129
+ return JSON.parse(readFileSync(PLUGIN_JSON, 'utf8')).agents;
130
+ } catch {
131
+ return null;
132
+ }
133
+ })();
134
+ if (agentsPath) {
135
+ fail(`agents path is not a directory: ${agentsPath}`);
136
+ } else {
137
+ fail(`agents directory not found at conventional location: ./${CONVENTIONAL_AGENTS}`);
138
+ }
139
+ console.log('');
140
+ console.log(`Results: ${passed} passed, ${failed} failed`);
141
+ process.exit(failed > 0 ? 1 : 0);
142
+ }
143
+
144
+ const mdFiles = readdirSync(agentsDir).filter(isAgentDefFile);
145
+
146
+ if (mdFiles.length === 0) {
147
+ fail('agents directory is empty (no .md files)');
148
+ } else {
149
+ for (const agentFile of mdFiles) {
150
+ const agentName = agentFile;
151
+ const filePath = join(agentsDir, agentFile);
152
+ const content = readFileSync(filePath, 'utf8');
153
+
154
+ const frontmatter = extractFrontmatter(content);
155
+
156
+ if (!frontmatter) {
157
+ fail(`${agentName}: missing YAML frontmatter`);
158
+ continue;
159
+ }
160
+
161
+ // ------------------------------------------------------------------
162
+ // Required fields check
163
+ // ------------------------------------------------------------------
164
+ const REQUIRED_FIELDS = ['name', 'description', 'model', 'color'];
165
+ const missingFields = REQUIRED_FIELDS.filter((f) => !hasField(frontmatter, f));
166
+
167
+ if (missingFields.length === 0) {
168
+ pass(`${agentName}: all required frontmatter fields present`);
169
+ } else {
170
+ fail(`${agentName}: missing frontmatter fields: ${missingFields.join(' ')}`);
171
+ }
172
+
173
+ // ------------------------------------------------------------------
174
+ // Format validation (only when fields are present)
175
+ // ------------------------------------------------------------------
176
+
177
+ // description: must be an inline value, not a YAML block scalar (> or |)
178
+ if (hasField(frontmatter, 'description')) {
179
+ const descVal = getField(frontmatter, 'description');
180
+ if (descVal === null || /^[>|]/.test(descVal)) {
181
+ const got = descVal ?? '';
182
+ fail(`${agentName}: description must be an inline string, not a YAML block scalar (got: '${got}')`);
183
+ }
184
+ }
185
+
186
+ // model: alias (inherit|sonnet|opus|haiku|fable) OR full model ID
187
+ // (claude-{opus|sonnet|haiku|fable}-N[-N][-YYYYMMDD]).
188
+ // Validated against the SSOT exports from agent-frontmatter.mjs (#768) —
189
+ // do not re-declare the alias set or the model-ID regex here.
190
+ // Per https://code.claude.com/docs/en/sub-agents — the canonical doc accepts both.
191
+ if (hasField(frontmatter, 'model')) {
192
+ const modelVal = getField(frontmatter, 'model');
193
+ if (modelVal === null || (!ALLOWED_MODEL_ALIASES.has(modelVal) && !MODEL_ID_RE.test(modelVal))) {
194
+ const got = modelVal ?? '';
195
+ const aliasList = [...ALLOWED_MODEL_ALIASES].join('|');
196
+ fail(`${agentName}: model must be ${aliasList} or a full model ID like 'claude-opus-4-7' or 'claude-sonnet-5' (got: '${got}')`);
197
+ }
198
+ }
199
+
200
+ // color: canonical Anthropic palette (red|blue|green|yellow|purple|orange|pink|cyan) plus magenta from plugin-dev SKILL.md.
201
+ // Source: https://code.claude.com/docs/en/sub-agents § Supported frontmatter fields.
202
+ if (hasField(frontmatter, 'color')) {
203
+ const colorVal = getField(frontmatter, 'color');
204
+ const colorRe = /^(blue|cyan|green|yellow|magenta|red|purple|orange|pink)$/;
205
+ if (colorVal === null || !colorRe.test(colorVal)) {
206
+ const got = colorVal ?? '';
207
+ fail(`${agentName}: color must be one of blue|cyan|green|yellow|magenta|red|purple|orange|pink (got: '${got}')`);
208
+ }
209
+ }
210
+
211
+ // tools: optional. Accepts BOTH forms per Anthropic canonical:
212
+ // 1. Comma-separated string: `tools: Read, Grep, Glob`
213
+ // 2. JSON array: `tools: ["Read", "Grep", "Glob"]`
214
+ // Anthropic's own reference agents (plugins/plugin-dev/agents/*) use array form.
215
+ // Reject only YAML block scalars (`>` or `|`) and malformed arrays (e.g. trailing comma, non-string elements).
216
+ if (hasField(frontmatter, 'tools')) {
217
+ const toolsVal = getField(frontmatter, 'tools');
218
+ if (toolsVal !== null && /^[>|]/.test(toolsVal)) {
219
+ fail(`${agentName}: tools must be a comma-separated string or JSON array, not a YAML block scalar (got: '${toolsVal}')`);
220
+ } else if (toolsVal !== null && /^\[/.test(toolsVal)) {
221
+ // JSON-array form — parse and validate each element is a string
222
+ let parsed;
223
+ try {
224
+ parsed = JSON.parse(toolsVal);
225
+ } catch {
226
+ fail(`${agentName}: tools is a malformed JSON array (got: '${toolsVal}')`);
227
+ parsed = null;
228
+ }
229
+ if (parsed !== null) {
230
+ if (!Array.isArray(parsed)) {
231
+ fail(`${agentName}: tools must be an array when using JSON form (got: '${toolsVal}')`);
232
+ } else if (!parsed.every((t) => typeof t === 'string')) {
233
+ fail(`${agentName}: tools array must contain only string elements (got: '${toolsVal}')`);
234
+ }
235
+ }
236
+ }
237
+ }
238
+ }
239
+ }
240
+
241
+ // ============================================================================
242
+ // Check 7: output-schema field (issue #417) + standalone sidecar schemas (#457).
243
+ // (a) When an agent's frontmatter declares `output-schema:`, the referenced
244
+ // JSON schema file must exist, parse as JSON, and compile under AJV 2020.
245
+ // (b) Any `agents/schemas/*.schema.json` file not referenced by an agent
246
+ // (e.g. persona-panel-sidecar.schema.json) is validated as a standalone
247
+ // schema: must parse + compile under AJV 2020.
248
+ // Catches broken schemas at plugin-distribution time rather than runtime.
249
+ // ============================================================================
250
+ console.log('');
251
+ console.log('--- Check 7: agent output-schema files ---');
252
+
253
+ if (existsSync(agentsDir)) {
254
+ const schemaFiles = readdirSync(agentsDir).filter(isAgentDefFile);
255
+ // Collect agents with output-schema declarations.
256
+ const declared = [];
257
+ for (const agentFile of schemaFiles) {
258
+ const filePath = join(agentsDir, agentFile);
259
+ const content = readFileSync(filePath, 'utf8');
260
+ const fm = extractFrontmatter(content);
261
+ if (!fm) continue;
262
+ if (!hasField(fm, 'output-schema')) continue;
263
+ const schemaRel = getField(fm, 'output-schema');
264
+ if (!schemaRel) continue;
265
+ declared.push({ agentFile, schemaRel });
266
+ }
267
+
268
+ // Track every schema file referenced via output-schema so the standalone walk
269
+ // below does not double-validate them.
270
+ const referencedSchemaPaths = new Set();
271
+ for (const { schemaRel } of declared) {
272
+ referencedSchemaPaths.add(resolve(agentsDir, schemaRel));
273
+ }
274
+
275
+ // Enumerate standalone schemas: any agents/schemas/*.schema.json file not
276
+ // referenced by an agent frontmatter (sidecar / panel / non-agent schemas).
277
+ const standaloneSchemas = [];
278
+ const schemasDir = join(agentsDir, 'schemas');
279
+ if (existsSync(schemasDir)) {
280
+ const allSchemaFiles = readdirSync(schemasDir).filter((f) => f.endsWith('.schema.json'));
281
+ for (const schemaFile of allSchemaFiles) {
282
+ const absPath = resolve(schemasDir, schemaFile);
283
+ if (referencedSchemaPaths.has(absPath)) continue;
284
+ standaloneSchemas.push({ schemaFile, absPath });
285
+ }
286
+ }
287
+
288
+ if (declared.length === 0 && standaloneSchemas.length === 0) {
289
+ // No agents declare output-schema yet and no standalone schemas exist — skip silently.
290
+ } else {
291
+ // Lazy-load shared AJV 2020 instance (W3-Q2 MED-004 fold-in).
292
+ let ajvInstance = null;
293
+ try {
294
+ const { getAjv2020 } = await import('../ajv-loader.mjs');
295
+ ajvInstance = await getAjv2020({ allErrors: true, strict: false });
296
+ } catch (err) {
297
+ fail(`output-schema check: could not load ajv-loader — ${err.message}`);
298
+ }
299
+
300
+ if (ajvInstance) {
301
+ // (a) Agent-referenced schemas
302
+ for (const { agentFile, schemaRel } of declared) {
303
+ // Resolve schema path relative to agentsDir (e.g. "schemas/code-implementer.schema.json").
304
+ const schemaPath = resolve(agentsDir, schemaRel);
305
+ if (!existsSync(schemaPath)) {
306
+ fail(`${agentFile}: output-schema file not found: ${schemaRel}`);
307
+ continue;
308
+ }
309
+ let raw;
310
+ try {
311
+ raw = readFileSync(schemaPath, 'utf8');
312
+ } catch (err) {
313
+ fail(`${agentFile}: output-schema read error: ${err.message}`);
314
+ continue;
315
+ }
316
+ let schema;
317
+ try {
318
+ schema = JSON.parse(raw);
319
+ } catch (err) {
320
+ fail(`${agentFile}: output-schema parse error: ${err.message}`);
321
+ continue;
322
+ }
323
+ try {
324
+ ajvInstance.compile(schema);
325
+ pass(`${agentFile}: output-schema validates`);
326
+ } catch (err) {
327
+ fail(`${agentFile}: output-schema error: ${err.message}`);
328
+ }
329
+ }
330
+
331
+ // (b) Standalone schemas (#457: sidecar / panel / non-agent-named).
332
+ for (const { schemaFile, absPath } of standaloneSchemas) {
333
+ let raw;
334
+ try {
335
+ raw = readFileSync(absPath, 'utf8');
336
+ } catch (err) {
337
+ fail(`${schemaFile}: standalone schema read error: ${err.message}`);
338
+ continue;
339
+ }
340
+ let schema;
341
+ try {
342
+ schema = JSON.parse(raw);
343
+ } catch (err) {
344
+ fail(`${schemaFile}: standalone schema parse error: ${err.message}`);
345
+ continue;
346
+ }
347
+ try {
348
+ ajvInstance.compile(schema);
349
+ pass(`agents/schemas/${schemaFile}: Draft 2020-12 compiles OK (standalone)`);
350
+ } catch (err) {
351
+ fail(`${schemaFile}: standalone schema compile error: ${err.message}`);
352
+ }
353
+ }
354
+ }
355
+ }
356
+ }
357
+
358
+ // ============================================================================
359
+ // Check 8: sandbox-tier field (issue #418) — when present, value must be in
360
+ // TIER_ENUM and must be consistent with the agent's tools list.
361
+ // When absent, emit WARN with the inferred tier (not FAIL — backward-compat).
362
+ // ============================================================================
363
+ console.log('');
364
+ console.log('--- Check 8: agent sandbox-tier ---');
365
+
366
+ if (existsSync(agentsDir)) {
367
+ const { TIER_ENUM, inferTierFromTools, validateTierConsistency } = await getTierModule();
368
+
369
+ const allMdFiles = readdirSync(agentsDir).filter(isAgentDefFile);
370
+ for (const agentFile of allMdFiles) {
371
+ const filePath = join(agentsDir, agentFile);
372
+ const content = readFileSync(filePath, 'utf8');
373
+ const fm = extractFrontmatter(content);
374
+ if (!fm) continue; // already caught by Check 6
375
+
376
+ const toolsVal = getField(fm, 'tools');
377
+ const toolsArray = parseToolsValue(toolsVal);
378
+ const inferred = inferTierFromTools(toolsArray);
379
+
380
+ if (!hasField(fm, 'sandbox-tier')) {
381
+ warn(`${agentFile}: sandbox-tier missing — inferred=${inferred}`);
382
+ continue;
383
+ }
384
+
385
+ const declared = getField(fm, 'sandbox-tier');
386
+ if (!declared) {
387
+ fail(`${agentFile}: sandbox-tier field is empty`);
388
+ continue;
389
+ }
390
+
391
+ if (!TIER_ENUM.includes(declared)) {
392
+ fail(`${agentFile}: sandbox-tier "${declared}" is not valid; must be one of: ${TIER_ENUM.join(', ')}`);
393
+ continue;
394
+ }
395
+
396
+ const consistency = validateTierConsistency({ declared, inferred, tools: toolsArray });
397
+ if (!consistency.ok) {
398
+ fail(`${agentFile}: sandbox-tier mismatch — ${consistency.error}`);
399
+ continue;
400
+ }
401
+
402
+ pass(`${agentFile}: sandbox-tier OK (${declared})`);
403
+ }
404
+ }
405
+
406
+ // ============================================================================
407
+ // Check 9: color-collision aggregation (issue #443).
408
+ // The 9-color palette is an operator side-channel (distinguishes co-running
409
+ // agents at a glance). With more than 9 agents, colors are deliberately
410
+ // shared — but two DISPATCHABLE agents sharing a color is a likely
411
+ // same-wave collision and surfaces as a WARN (not FAIL: deliberate
412
+ // cross-phase shares are legitimate — see agents/AGENTS.md § Color
413
+ // Allocation Strategy).
414
+ // Non-dispatchable reference docs (description contains "NOT a dispatchable"
415
+ // or "Reference documentation") are excluded from the aggregation: they
416
+ // never dispatch as a subagent, so their color can never collide on screen.
417
+ // ============================================================================
418
+ console.log('');
419
+ console.log('--- Check 9: agent color collisions ---');
420
+
421
+ if (existsSync(agentsDir)) {
422
+ const colorMap = new Map(); // color -> [agentFile, ...]
423
+ const colorMdFiles = readdirSync(agentsDir).filter(isAgentDefFile);
424
+ for (const agentFile of colorMdFiles) {
425
+ const filePath = join(agentsDir, agentFile);
426
+ const content = readFileSync(filePath, 'utf8');
427
+ const fm = extractFrontmatter(content);
428
+ if (!fm) continue; // already caught by Check 6
429
+
430
+ const description = getField(fm, 'description') ?? '';
431
+ const isNonDispatchable =
432
+ /NOT a dispatchable/i.test(description) || /Reference documentation/i.test(description);
433
+ if (isNonDispatchable) continue;
434
+
435
+ const colorVal = getField(fm, 'color');
436
+ if (!colorVal) continue; // missing/invalid color already caught by Check 6
437
+
438
+ if (!colorMap.has(colorVal)) colorMap.set(colorVal, []);
439
+ colorMap.get(colorVal).push(agentFile);
440
+ }
441
+
442
+ let collisions = 0;
443
+ for (const [color, names] of colorMap) {
444
+ if (names.length > 1) {
445
+ collisions++;
446
+ warn(`color collision: ${color} shared by dispatchable agents ${names.sort().join(', ')} — confirm they never co-run in one wave (agents/AGENTS.md § Color Allocation Strategy)`);
447
+ }
448
+ }
449
+ if (collisions === 0) {
450
+ pass('no color collisions among dispatchable agents');
451
+ }
452
+ }
453
+
454
+ console.log('');
455
+ console.log(`Results: ${passed} passed, ${failed} failed`);
456
+
457
+ process.exit(failed > 0 ? 1 : 0);
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFileSync } from 'node:fs';
4
+ import { resolve } from 'node:path';
5
+ import { validateCodexPluginContract } from '../codex/plugin-contract.mjs';
6
+
7
+ const pluginRoot = process.argv[2];
8
+ if (!pluginRoot) {
9
+ console.error('Usage: check-codex-plugin.mjs <plugin-root>');
10
+ process.exit(1);
11
+ }
12
+
13
+ console.log('--- Check: canonical Codex plugin contract ---');
14
+
15
+ let expectedBaseVersion;
16
+ try {
17
+ const packageJson = JSON.parse(readFileSync(resolve(pluginRoot, 'package.json'), 'utf8'));
18
+ expectedBaseVersion = packageJson.version;
19
+ } catch (error) {
20
+ console.log(` FAIL: cannot read package.json version: ${error.message}`);
21
+ console.log('');
22
+ console.log('Results: 0 passed, 1 failed');
23
+ process.exit(1);
24
+ }
25
+
26
+ const verdict = validateCodexPluginContract({ pluginRoot, expectedBaseVersion });
27
+ if (verdict.ok) {
28
+ console.log(' PASS: .codex-plugin/plugin.json and hooks/hooks-codex.json satisfy the Codex contract');
29
+ } else {
30
+ for (const error of verdict.errors) {
31
+ console.log(` FAIL: [${error.rule}] ${error.path}: ${error.message}`);
32
+ }
33
+ }
34
+
35
+ console.log('');
36
+ console.log(`Results: ${verdict.ok ? 1 : 0} passed, ${verdict.errors.length} failed`);
37
+ process.exit(verdict.ok ? 0 : 1);
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ // check-commands.mjs — Validate that the commands directory contains .md files.
3
+ // Usage: check-commands.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 { existsSync, readdirSync, readFileSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ import yaml from 'js-yaml';
10
+
11
+ const [, , pluginRoot] = process.argv;
12
+
13
+ if (!pluginRoot) {
14
+ console.error('Usage: check-commands.mjs <plugin-root>');
15
+ process.exit(1);
16
+ }
17
+
18
+ const PLUGIN_JSON_PATH = join(pluginRoot, '.claude-plugin', 'plugin.json');
19
+ const CONVENTIONAL_COMMANDS = 'commands';
20
+
21
+ let passed = 0;
22
+ let failed = 0;
23
+
24
+ function pass(msg) {
25
+ console.log(` PASS: ${msg}`);
26
+ passed++;
27
+ }
28
+
29
+ function fail(msg) {
30
+ console.log(` FAIL: ${msg}`);
31
+ failed++;
32
+ }
33
+
34
+ /**
35
+ * Extract the YAML block at the beginning of a command file.
36
+ *
37
+ * @param {string} content
38
+ * @returns {{ ok: true, yamlText: string } | { ok: false, diagnostic: string }}
39
+ */
40
+ function extractInitialFrontmatter(content) {
41
+ const lines = content.split(/\r?\n/);
42
+ if (lines[0] !== '---') {
43
+ return { ok: false, diagnostic: 'missing YAML frontmatter opening delimiter' };
44
+ }
45
+
46
+ const closingDelimiter = lines.indexOf('---', 1);
47
+ if (closingDelimiter === -1) {
48
+ return { ok: false, diagnostic: 'missing YAML frontmatter closing delimiter' };
49
+ }
50
+
51
+ return { ok: true, yamlText: lines.slice(1, closingDelimiter).join('\n') };
52
+ }
53
+
54
+ /**
55
+ * Parse and validate the frontmatter contract for one command file.
56
+ *
57
+ * @param {string} commandsDir
58
+ * @param {string} filename
59
+ */
60
+ function validateCommandFrontmatter(commandsDir, filename) {
61
+ const content = readFileSync(join(commandsDir, filename), 'utf8');
62
+ const extracted = extractInitialFrontmatter(content);
63
+ if (!extracted.ok) {
64
+ fail(`${filename}: ${extracted.diagnostic}`);
65
+ return;
66
+ }
67
+
68
+ let frontmatter;
69
+ try {
70
+ frontmatter = yaml.load(extracted.yamlText, { schema: yaml.CORE_SCHEMA });
71
+ } catch (error) {
72
+ const reason = error?.reason ?? error?.message ?? String(error);
73
+ const location = error?.mark
74
+ ? ` at line ${error.mark.line + 1}, column ${error.mark.column + 1}`
75
+ : '';
76
+ fail(`${filename}: invalid YAML frontmatter: ${reason}${location}`);
77
+ return;
78
+ }
79
+
80
+ if (frontmatter === null || typeof frontmatter !== 'object' || Array.isArray(frontmatter)) {
81
+ fail(`${filename}: YAML frontmatter must be a non-null mapping/object`);
82
+ return;
83
+ }
84
+
85
+ if (
86
+ Object.hasOwn(frontmatter, 'argument-hint') &&
87
+ typeof frontmatter['argument-hint'] !== 'string'
88
+ ) {
89
+ fail(`${filename}: argument-hint must be a string`);
90
+ }
91
+ }
92
+
93
+ // ============================================================================
94
+ // Check 7: Command .md files exist
95
+ // ============================================================================
96
+ console.log('--- Check 7: command files ---');
97
+
98
+ // Read optional commands path from plugin.json
99
+ let commandsPath = '';
100
+ if (existsSync(PLUGIN_JSON_PATH)) {
101
+ try {
102
+ const json = JSON.parse(readFileSync(PLUGIN_JSON_PATH, 'utf8'));
103
+ if (json.commands && typeof json.commands === 'string') {
104
+ commandsPath = json.commands;
105
+ }
106
+ } catch {
107
+ // Malformed plugin.json — fall back to conventional location
108
+ }
109
+ }
110
+
111
+ // Resolve the commands directory
112
+ let commandsDir;
113
+ if (commandsPath) {
114
+ // Strip leading "./" to allow join to work correctly
115
+ commandsDir = join(pluginRoot, commandsPath.replace(/^\.\//, ''));
116
+ } else {
117
+ commandsDir = join(pluginRoot, CONVENTIONAL_COMMANDS);
118
+ }
119
+
120
+ if (existsSync(commandsDir)) {
121
+ let entries;
122
+ try {
123
+ entries = readdirSync(commandsDir);
124
+ } catch {
125
+ entries = [];
126
+ }
127
+ const mdFiles = entries.filter((f) => f.endsWith('.md')).sort();
128
+
129
+ if (mdFiles.length > 0) {
130
+ pass(`commands directory contains ${mdFiles.length} .md files`);
131
+ for (const filename of mdFiles) {
132
+ validateCommandFrontmatter(commandsDir, filename);
133
+ }
134
+ } else {
135
+ fail('commands directory is empty (no .md files)');
136
+ }
137
+ } else {
138
+ if (commandsPath) {
139
+ fail(`commands path is not a directory: ${commandsPath}`);
140
+ } else {
141
+ fail(`commands directory not found at conventional location: ./${CONVENTIONAL_COMMANDS}`);
142
+ }
143
+ }
144
+
145
+ console.log('');
146
+ console.log(`Results: ${passed} passed, ${failed} failed`);
147
+
148
+ process.exit(failed > 0 ? 1 : 0);