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,658 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * validator.mjs — Meta-Vault frontmatter + wiki-link validator (Phase 1).
4
+ *
5
+ * Reads every `.md` file under VAULT_DIR, parses YAML frontmatter, validates
6
+ * against the canonical vaultFrontmatterSchema, and checks wiki-link targets
7
+ * resolve inside the vault. Emits a machine-readable JSON report to stdout and
8
+ * exits 0 on clean vault (warnings allowed), 1 on validation errors, 0 when
9
+ * there is no vault to validate.
10
+ *
11
+ * ── Schema drift ────────────────────────────────────────────────────────────
12
+ * The Zod schema below is auto-vendored from the canonical source:
13
+ * projects-baseline/packages/zod-schemas/src/vault-frontmatter.ts
14
+ * This skill is intentionally self-contained (no workspace dependency on the
15
+ * shared monorepo package), so the schema is vendored here via the managed
16
+ * sync script: scripts/sync-vault-schema.mjs
17
+ *
18
+ * To update after a canonical change, run:
19
+ * node scripts/sync-vault-schema.mjs --write
20
+ * then commit the resulting validator.mjs diff.
21
+ *
22
+ * The schema block below is fenced by a pair of sentinel comments managed by
23
+ * sync-vault-schema.mjs. DO NOT edit between them by hand — any manual edit
24
+ * will be overwritten on the next --write run and will cause --check to report
25
+ * drift.
26
+ *
27
+ * Drift is gated by tests/schema-drift.test.mjs (5 scenarios: idempotency,
28
+ * --check clean, --check drift, missing canonical, sentinel presence) and
29
+ * by the GitLab CI pipeline which runs --check mode against a freshly-cloned
30
+ * canonical to catch any out-of-band edits.
31
+ *
32
+ * 2026-04-13: tagPathRegex added for Obsidian nested-tag support (e.g. meta/schema).
33
+ *
34
+ * 2026-05-23 (#503, I5): `peer-card` appended to vaultNoteTypeSchema via the
35
+ * vendored-edit + sync-script-baseline-update path. Upstream canonical
36
+ * (projects-baseline/packages/zod-schemas/src/vault-frontmatter.ts) is
37
+ * behind until #503 lands there; until then, `sync-vault-schema.mjs --check`
38
+ * will report drift in CI. Tracked as upstream-sync-debt in the #503 PRD.
39
+ * When upstream catches up, re-run `node scripts/sync-vault-schema.mjs --write`
40
+ * to confirm idempotency.
41
+ *
42
+ * 2026-07-02 (#725, D2): `'source-repo': z.string().optional()` appended to
43
+ * vaultFrontmatterSchema (same vendored-ahead pattern as #503). vault-mirror
44
+ * now emits `source-repo` in generated learning notes for cross-repo
45
+ * attribution (scripts/lib/vault-mirror/render-learnings.mjs). The field is
46
+ * OPTIONAL — pre-existing notes without it stay valid, and `.passthrough()`
47
+ * already accepted the key; the explicit declaration adds string-type
48
+ * enforcement. Upstream canonical is behind until #725 lands there, so
49
+ * `sync-vault-schema.mjs --check` reports drift in CI (upstream-sync-debt).
50
+ * Re-run `--write` once upstream catches up to confirm idempotency.
51
+ *
52
+ * 2026-07-03 (#738, I2): `board` appended to vaultNoteTypeSchema so the
53
+ * generated `01-projects/_active-sessions.md` board validates as a
54
+ * first-class vault note. Upstream canonical sync remains out of scope for
55
+ * this worker because the baseline repo is intentionally dirty.
56
+ * ────────────────────────────────────────────────────────────────────────────
57
+ */
58
+
59
+ import { readdirSync, readFileSync, statSync, existsSync } from 'node:fs';
60
+ import { join, relative, resolve, dirname, basename } from 'node:path';
61
+ import { fileURLToPath } from 'node:url';
62
+ import { z } from 'zod';
63
+ import YAML from 'yaml';
64
+ import { resolveInstructionFile } from '../../scripts/lib/common.mjs';
65
+ import {
66
+ computeSchemaHash,
67
+ writeBaseline,
68
+ readBaseline,
69
+ diffBaseline,
70
+ } from '../../scripts/lib/vault-sync-baseline.mjs';
71
+
72
+ // ── Inline vendored schema (mirrors projects-baseline vault-frontmatter.ts) ──
73
+ // ── BEGIN GENERATED SCHEMA (sync-vault-schema.mjs) — do not edit between sentinels ──
74
+ const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
75
+
76
+ const tagPathRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*(?:\/[a-z0-9]+(?:-[a-z0-9]+)*)*$/;
77
+
78
+ const isoDateRegex =
79
+ /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})?)?$/;
80
+
81
+ const vaultNoteTypeSchema = z.enum([
82
+ 'note',
83
+ 'daily',
84
+ 'project',
85
+ 'person',
86
+ 'reference',
87
+ 'idea',
88
+ 'learning',
89
+ 'session',
90
+ 'peer-card',
91
+ 'board',
92
+ ]);
93
+
94
+ const vaultNoteStatusSchema = z.enum([
95
+ 'draft',
96
+ 'active',
97
+ 'verified',
98
+ 'archived',
99
+ 'production',
100
+ 'mvp',
101
+ 'idea',
102
+ ]);
103
+
104
+ const vaultFrontmatterSchema = z
105
+ .object({
106
+ id: z
107
+ .string()
108
+ .regex(slugRegex, 'Ungueltige id (kebab-case slug format required)')
109
+ .min(2)
110
+ .max(128),
111
+ type: vaultNoteTypeSchema,
112
+ created: z.string().regex(isoDateRegex, 'Ungueltiges Datum (ISO 8601 required)'),
113
+ updated: z.string().regex(isoDateRegex, 'Ungueltiges Datum (ISO 8601 required)'),
114
+ title: z.string().min(1).max(200).optional(),
115
+ tags: z
116
+ .array(
117
+ z
118
+ .string()
119
+ .regex(tagPathRegex, 'Ungueltiger tag (kebab-case segments joined by / — e.g. meta/schema)')
120
+ .min(1)
121
+ .max(64),
122
+ )
123
+ .optional(),
124
+ status: vaultNoteStatusSchema.optional(),
125
+ expires: z
126
+ .string()
127
+ .regex(isoDateRegex, 'Ungueltiges Datum (ISO 8601 required)')
128
+ .optional(),
129
+ source: z.string().optional(),
130
+ sources: z.array(z.string()).optional(),
131
+ aliases: z.array(z.string().min(1).max(200)).optional(),
132
+ 'source-repo': z.string().optional(),
133
+ })
134
+ .passthrough();
135
+ // ── END GENERATED SCHEMA ──
136
+
137
+ // ── Schema hash (module-scope cached) ───────────────────────────────────────
138
+ // Extract the vendored schema text between the BEGIN/END sentinels in this
139
+ // file's own source and compute a stable 8-char SHA-256 prefix. Used by
140
+ // --mode=baseline (to stamp snapshots) and --mode=diff (to detect schema drift
141
+ // between a stored baseline and the current validator revision).
142
+ const _schemaHash = (() => {
143
+ try {
144
+ const selfPath = fileURLToPath(import.meta.url);
145
+ const src = readFileSync(selfPath, 'utf8');
146
+ const begin = '── BEGIN GENERATED SCHEMA';
147
+ const end = '── END GENERATED SCHEMA ──';
148
+ const beginIdx = src.indexOf(begin);
149
+ const endIdx = src.indexOf(end);
150
+ if (beginIdx === -1 || endIdx === -1 || endIdx <= beginIdx) return 'unknown';
151
+ const schemaBlock = src.slice(beginIdx, endIdx + end.length);
152
+ return computeSchemaHash(schemaBlock);
153
+ } catch {
154
+ return 'unknown';
155
+ }
156
+ })();
157
+
158
+ // ── CLI args ────────────────────────────────────────────────────────────────
159
+ const args = process.argv.slice(2);
160
+ const checkExpires = args.includes('--check-expires');
161
+
162
+ // Parse --mode <hard|warn|off|baseline|diff|full> (default: hard)
163
+ // hard — legacy alias; identical to full enforcement
164
+ // full — enforce: exit 1 on errors
165
+ // warn — report but exit 0
166
+ // off — skip entirely
167
+ // baseline — write snapshot then exit 0
168
+ // diff — compare against snapshot, emit JSON diff
169
+ // Parse --exclude <glob> (repeatable)
170
+ let mode = 'hard';
171
+ const excludePatterns = [];
172
+
173
+ // ── Unconditional config-loaded excludes (issue #329) ──────────────────────
174
+ // Read `vault-sync.exclude` from <VAULT_DIR>/CLAUDE.md (or AGENTS.md) BEFORE
175
+ // parsing argv so that bare invocations (no caller, no --exclude flags) still
176
+ // honour the project's configured exclusion list. CLI --exclude flags below
177
+ // are additive — they extend (do not replace) the config-loaded list.
178
+ //
179
+ // Resolution order for the directory:
180
+ // 1. process.env.VAULT_DIR (absolute or relative to cwd)
181
+ // 2. process.cwd() fallback
182
+ //
183
+ // Wrapped in try/catch: missing CLAUDE.md, missing module, or parse error all
184
+ // degrade silently to "no config excludes" — the validator must continue to
185
+ // work on repos that have no project-instruction file.
186
+ try {
187
+ const configDir = process.env.VAULT_DIR ? resolve(process.env.VAULT_DIR) : process.cwd();
188
+ const instr = resolveInstructionFile(configDir);
189
+ if (instr && existsSync(instr.path)) {
190
+ const content = readFileSync(instr.path, 'utf8');
191
+ const { _parseVaultSync } = await import('../../scripts/lib/config/vault-sync.mjs');
192
+ const parsed = _parseVaultSync(content);
193
+ if (Array.isArray(parsed.exclude)) {
194
+ for (const pat of parsed.exclude) {
195
+ if (typeof pat === 'string' && pat.length > 0) excludePatterns.push(pat);
196
+ }
197
+ }
198
+ }
199
+ } catch {
200
+ // Silent fallback: validator must work without CLAUDE.md / config parser.
201
+ }
202
+
203
+ for (let i = 0; i < args.length; i++) {
204
+ const a = args[i];
205
+ if (a === '--mode') {
206
+ const v = args[i + 1];
207
+ if (v === 'hard' || v === 'warn' || v === 'off' || v === 'baseline' || v === 'diff' || v === 'full') {
208
+ mode = v;
209
+ } else {
210
+ process.stderr.write(
211
+ `validator.mjs: invalid --mode value "${v}" (expected hard|warn|off|baseline|diff|full)\n`,
212
+ );
213
+ process.exit(2);
214
+ }
215
+ i++;
216
+ } else if (a.startsWith('--mode=')) {
217
+ const v = a.slice('--mode='.length);
218
+ if (v === 'hard' || v === 'warn' || v === 'off' || v === 'baseline' || v === 'diff' || v === 'full') {
219
+ mode = v;
220
+ } else {
221
+ process.stderr.write(
222
+ `validator.mjs: invalid --mode value "${v}" (expected hard|warn|off|baseline|diff|full)\n`,
223
+ );
224
+ process.exit(2);
225
+ }
226
+ } else if (a === '--exclude') {
227
+ if (args[i + 1]) {
228
+ excludePatterns.push(args[i + 1]);
229
+ i++;
230
+ }
231
+ } else if (a.startsWith('--exclude=')) {
232
+ excludePatterns.push(a.slice('--exclude='.length));
233
+ }
234
+ }
235
+
236
+ // ── Tiny fnmatch-style glob matcher ─────────────────────────────────────────
237
+ // Supports:
238
+ // ** — any number of path segments (zero or more)
239
+ // * — any characters except `/`
240
+ // ? — any single character except `/`
241
+ // literal path separators and characters otherwise
242
+ // Operates on POSIX-style forward-slash relative paths.
243
+ function globToRegExp(glob) {
244
+ // Normalise input
245
+ const g = glob.replace(/\\/g, '/');
246
+ let re = '^';
247
+ for (let i = 0; i < g.length; i++) {
248
+ const c = g[i];
249
+ if (c === '*') {
250
+ if (g[i + 1] === '*') {
251
+ // `**` — match across path segments
252
+ // Also swallow a following `/` so that `**/foo` matches `foo` at root.
253
+ const nextSlash = g[i + 2] === '/';
254
+ re += '(?:.*?)';
255
+ if (nextSlash) i += 2;
256
+ else i += 1;
257
+ } else {
258
+ re += '[^/]*';
259
+ }
260
+ } else if (c === '?') {
261
+ re += '[^/]';
262
+ } else if ('.+^$(){}|[]\\'.includes(c)) {
263
+ re += '\\' + c;
264
+ } else {
265
+ re += c;
266
+ }
267
+ }
268
+ re += '$';
269
+ return new RegExp(re);
270
+ }
271
+
272
+ const excludeRegexes = excludePatterns.map((p) => globToRegExp(p));
273
+
274
+ function isExcluded(relPath) {
275
+ const p = relPath.replace(/\\/g, '/');
276
+ for (const re of excludeRegexes) {
277
+ if (re.test(p)) return true;
278
+ }
279
+ return false;
280
+ }
281
+
282
+ // ── Vault marker detection ──────────────────────────────────────────────────
283
+ // Returns true if dir contains at least one recognized vault marker:
284
+ // 1. _meta/ directory
285
+ // 2. CLAUDE.md or AGENTS.md (alias — see skills/_shared/instruction-file-resolution.md)
286
+ // containing both "## Session Config" and "vault-sync:". The instruction
287
+ // file is resolved via resolveInstructionFile() so CLAUDE.md wins ties and
288
+ // AGENTS.md is accepted on Codex CLI repos.
289
+ // 3. .obsidian/ directory
290
+ function isVaultDir(dir) {
291
+ if (existsSync(join(dir, '_meta')) && statSync(join(dir, '_meta')).isDirectory()) return true;
292
+ if (existsSync(join(dir, '.obsidian')) && statSync(join(dir, '.obsidian')).isDirectory()) return true;
293
+ const instr = resolveInstructionFile(dir);
294
+ if (instr) {
295
+ try {
296
+ const content = readFileSync(instr.path, 'utf8');
297
+ if (content.includes('## Session Config') && content.includes('vault-sync:')) return true;
298
+ } catch {
299
+ // unreadable instruction file — not a vault marker
300
+ }
301
+ }
302
+ return false;
303
+ }
304
+
305
+ // ── Resolve vault dir ───────────────────────────────────────────────────────
306
+ let vaultDir;
307
+ if (process.env.VAULT_DIR) {
308
+ vaultDir = resolve(process.env.VAULT_DIR);
309
+ // Only warn when the directory exists but lacks vault markers.
310
+ // Non-existent dirs are handled further down by the existsSync guard (status: skipped).
311
+ if (existsSync(vaultDir) && statSync(vaultDir).isDirectory() && !isVaultDir(vaultDir)) {
312
+ process.stderr.write(
313
+ 'vault-sync: warning: VAULT_DIR set but directory lacks vault markers (_meta/, CLAUDE.md or AGENTS.md with vault-sync, or .obsidian/)\n',
314
+ );
315
+ }
316
+ } else {
317
+ const cwd = process.cwd();
318
+ if (isVaultDir(cwd)) {
319
+ vaultDir = resolve(cwd);
320
+ } else {
321
+ process.stderr.write(
322
+ [
323
+ 'vault-sync: error: VAULT_DIR is not set and the current working directory does not look like a Meta-Vault.',
324
+ '',
325
+ 'Expected one of the following in cwd:',
326
+ ' - _meta/ directory',
327
+ " - CLAUDE.md (or AGENTS.md on Codex CLI) with a '## Session Config' and 'vault-sync:' block",
328
+ ' - .obsidian/ directory',
329
+ '',
330
+ 'Fix: set VAULT_DIR to the vault root, or cd into the vault before running.',
331
+ '',
332
+ ].join('\n'),
333
+ );
334
+ process.exit(2);
335
+ }
336
+ }
337
+
338
+ const EXCLUDED_DIRS = new Set([
339
+ 'node_modules',
340
+ '.git',
341
+ '.obsidian',
342
+ '90-archive',
343
+ ]);
344
+
345
+ function emit(obj) {
346
+ process.stdout.write(JSON.stringify(obj) + '\n');
347
+ }
348
+
349
+ // Mode off → no-op (useful for onboarding / emergency bypass).
350
+ if (mode === 'off') {
351
+ emit({
352
+ status: 'skipped-mode-off',
353
+ mode,
354
+ vault_dir: vaultDir,
355
+ files_checked: 0,
356
+ excluded_count: 0,
357
+ files_skipped_no_frontmatter: 0,
358
+ errors: [],
359
+ warnings: [],
360
+ });
361
+ process.exit(0);
362
+ }
363
+
364
+ // No vault to check → skipped.
365
+ if (!existsSync(vaultDir) || !statSync(vaultDir).isDirectory()) {
366
+ emit({ status: 'skipped', reason: 'no vault', mode, vault_dir: vaultDir });
367
+ process.exit(0);
368
+ }
369
+
370
+ // ── Crawl .md files ─────────────────────────────────────────────────────────
371
+ function walk(dir, out) {
372
+ let entries;
373
+ try {
374
+ entries = readdirSync(dir, { withFileTypes: true });
375
+ } catch {
376
+ return;
377
+ }
378
+ for (const e of entries) {
379
+ if (e.name.startsWith('.') && e.name !== '.') {
380
+ // always skip dot-dirs/files except allow top-level
381
+ if (e.isDirectory() && EXCLUDED_DIRS.has(e.name)) continue;
382
+ if (e.isDirectory()) continue;
383
+ // skip hidden files
384
+ continue;
385
+ }
386
+ if (e.isDirectory()) {
387
+ if (EXCLUDED_DIRS.has(e.name)) continue;
388
+ walk(join(dir, e.name), out);
389
+ } else if (e.isFile() && e.name.endsWith('.md')) {
390
+ out.push(join(dir, e.name));
391
+ }
392
+ }
393
+ }
394
+
395
+ const mdFiles = [];
396
+ walk(vaultDir, mdFiles);
397
+
398
+ if (mdFiles.length === 0) {
399
+ emit({ status: 'skipped', reason: 'no vault', mode, vault_dir: vaultDir });
400
+ process.exit(0);
401
+ }
402
+
403
+ // ── Parse frontmatter ───────────────────────────────────────────────────────
404
+ const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
405
+
406
+ function parseFrontmatter(raw) {
407
+ const m = raw.match(FRONTMATTER_RE);
408
+ if (!m) return { hasFrontmatter: false };
409
+ const yamlBlock = m[1];
410
+ try {
411
+ const data = YAML.parse(yamlBlock);
412
+ return { hasFrontmatter: true, data: data ?? {}, raw: yamlBlock };
413
+ } catch (err) {
414
+ return { hasFrontmatter: true, parseError: err.message || String(err) };
415
+ }
416
+ }
417
+
418
+ // ── Build link index (filename -> path) ─────────────────────────────────────
419
+ const fileIndex = new Map(); // basename-without-ext -> [absolute paths]
420
+ for (const f of mdFiles) {
421
+ const key = basename(f, '.md');
422
+ if (!fileIndex.has(key)) fileIndex.set(key, []);
423
+ fileIndex.get(key).push(f);
424
+ }
425
+
426
+ // ── Wiki-link regex — captures link body for target parsing ─────────────────
427
+ const WIKILINK_RE = /\[\[([^\]]+)\]\]/g;
428
+
429
+ function findAliasSeparatorIndex(linkBody) {
430
+ for (let i = 0; i < linkBody.length; i++) {
431
+ if (linkBody[i] === '\\' && linkBody[i + 1] === '|') return i;
432
+ if (linkBody[i] === '|') return i;
433
+ }
434
+ return -1;
435
+ }
436
+
437
+ function extractWikiLinkTarget(linkBody) {
438
+ const aliasIndex = findAliasSeparatorIndex(linkBody);
439
+ const targetWithAnchor = aliasIndex === -1 ? linkBody : linkBody.slice(0, aliasIndex);
440
+ return targetWithAnchor.split('#', 1)[0].trim();
441
+ }
442
+
443
+ function extractWikiLinks(content) {
444
+ const targets = new Set();
445
+ let m;
446
+ while ((m = WIKILINK_RE.exec(content)) !== null) {
447
+ const target = extractWikiLinkTarget(m[1]);
448
+ if (target.length > 0) targets.add(target);
449
+ }
450
+ return [...targets];
451
+ }
452
+
453
+ function resolveWikiLink(target, sourceFile) {
454
+ // Target may be a bare name ("my-note") or a path ("01-projects/foo/_overview").
455
+ // Try exact path first (relative to vault), then basename lookup.
456
+ const candidate1 = resolve(vaultDir, target.endsWith('.md') ? target : target + '.md');
457
+ if (existsSync(candidate1)) return true;
458
+
459
+ // Try relative to source file's directory
460
+ const candidate2 = resolve(
461
+ dirname(sourceFile),
462
+ target.endsWith('.md') ? target : target + '.md',
463
+ );
464
+ if (existsSync(candidate2)) return true;
465
+
466
+ // Try basename lookup anywhere in index
467
+ const key = basename(target, '.md');
468
+ if (fileIndex.has(key)) return true;
469
+
470
+ return false;
471
+ }
472
+
473
+ // ── Validate each file ──────────────────────────────────────────────────────
474
+ const errors = [];
475
+ const warnings = [];
476
+ let filesChecked = 0;
477
+ let filesSkippedNoFrontmatter = 0;
478
+ let excludedCount = 0;
479
+
480
+ const todayIso = new Date().toISOString().slice(0, 10);
481
+
482
+ for (const file of mdFiles) {
483
+ const rel = relative(vaultDir, file);
484
+ if (isExcluded(rel)) {
485
+ excludedCount++;
486
+ continue;
487
+ }
488
+ let raw;
489
+ try {
490
+ raw = readFileSync(file, 'utf8');
491
+ } catch (err) {
492
+ errors.push({
493
+ file: rel,
494
+ path: '',
495
+ message: `Cannot read file: ${err.message || err}`,
496
+ });
497
+ continue;
498
+ }
499
+
500
+ const fm = parseFrontmatter(raw);
501
+
502
+ if (!fm.hasFrontmatter) {
503
+ filesSkippedNoFrontmatter++;
504
+ continue;
505
+ }
506
+
507
+ filesChecked++;
508
+
509
+ if (fm.parseError) {
510
+ errors.push({
511
+ file: rel,
512
+ path: 'frontmatter',
513
+ message: `YAML parse error: ${fm.parseError}`,
514
+ });
515
+ continue;
516
+ }
517
+
518
+ const parsed = vaultFrontmatterSchema.safeParse(fm.data);
519
+ if (!parsed.success) {
520
+ for (const issue of parsed.error.issues) {
521
+ errors.push({
522
+ file: rel,
523
+ path: issue.path.join('.'),
524
+ message: issue.message,
525
+ });
526
+ }
527
+ // Even if frontmatter is invalid, still check wiki-links to surface all problems.
528
+ }
529
+
530
+ // Wiki-link check
531
+ const body = raw.slice(raw.match(FRONTMATTER_RE)?.[0].length || 0);
532
+ const links = extractWikiLinks(body);
533
+ for (const target of links) {
534
+ if (!resolveWikiLink(target, file)) {
535
+ warnings.push({
536
+ file: rel,
537
+ type: 'dangling-wiki-link',
538
+ message: `Wiki-link target not found in vault: [[${target}]]`,
539
+ });
540
+ }
541
+ }
542
+
543
+ // Expires check (opt-in)
544
+ if (checkExpires && parsed.success && parsed.data.expires) {
545
+ if (parsed.data.expires < todayIso) {
546
+ warnings.push({
547
+ file: rel,
548
+ type: 'expired',
549
+ message: `Note expired on ${parsed.data.expires} (today is ${todayIso})`,
550
+ });
551
+ }
552
+ }
553
+ }
554
+
555
+ const hasErrors = errors.length > 0;
556
+
557
+ // ── mode=baseline ─────────────────────────────────────────────────────────
558
+ // Serialize current errors + warnings as a snapshot, then exit 0.
559
+ if (mode === 'baseline') {
560
+ const baselinePath = join(vaultDir, '.orchestrator', 'metrics', 'vault-sync-baseline.json');
561
+ writeBaseline(baselinePath, {
562
+ errors,
563
+ warnings,
564
+ schemaHash: _schemaHash,
565
+ isoTimestamp: new Date().toISOString(),
566
+ vaultDir,
567
+ });
568
+ process.stderr.write(
569
+ `WRITE: baseline -> ${baselinePath} (${errors.length} errors, ${warnings.length} warnings)\n`,
570
+ );
571
+ process.exit(0);
572
+ }
573
+
574
+ // ── mode=diff ─────────────────────────────────────────────────────────────
575
+ // Read a prior baseline, compute set-differences, emit JSON diff to stdout.
576
+ if (mode === 'diff') {
577
+ const baselinePath = join(vaultDir, '.orchestrator', 'metrics', 'vault-sync-baseline.json');
578
+ const baseline = readBaseline(baselinePath);
579
+
580
+ if (!baseline) {
581
+ // No baseline file at all — fall back to full enforcement.
582
+ process.stderr.write(
583
+ `WARN: no baseline found at ${baselinePath} — falling back to full enforcement. Run --mode=baseline to create a snapshot.\n`,
584
+ );
585
+ const statusFull = hasErrors ? 'invalid' : 'ok';
586
+ emit({
587
+ status: statusFull,
588
+ mode: 'diff-fallback-full',
589
+ vault_dir: vaultDir,
590
+ files_checked: filesChecked,
591
+ excluded_count: excludedCount,
592
+ files_skipped_no_frontmatter: filesSkippedNoFrontmatter,
593
+ errors,
594
+ warnings,
595
+ });
596
+ process.exit(hasErrors ? 1 : 0);
597
+ }
598
+
599
+ if (baseline.schemaHash !== _schemaHash) {
600
+ process.stderr.write(
601
+ `WARN: baseline outdated (hash=${baseline.schemaHash}, current=${_schemaHash}) — please re-snapshot via --mode=baseline\n`,
602
+ );
603
+ // Schema drift — fall back to full enforcement.
604
+ const statusFull = hasErrors ? 'invalid' : 'ok';
605
+ emit({
606
+ status: statusFull,
607
+ mode: 'diff-fallback-full',
608
+ vault_dir: vaultDir,
609
+ files_checked: filesChecked,
610
+ excluded_count: excludedCount,
611
+ files_skipped_no_frontmatter: filesSkippedNoFrontmatter,
612
+ errors,
613
+ warnings,
614
+ });
615
+ process.exit(hasErrors ? 1 : 0);
616
+ }
617
+
618
+ const errorDiff = diffBaseline({ baselineErrors: baseline.errors, currentErrors: errors });
619
+ const warningDiff = diffBaseline({ baselineErrors: baseline.warnings, currentErrors: warnings });
620
+
621
+ emit({
622
+ new_errors: errorDiff.newErrors,
623
+ resolved_errors: errorDiff.resolvedErrors,
624
+ new_warnings: warningDiff.newErrors,
625
+ resolved_warnings: warningDiff.resolvedErrors,
626
+ baseline_count: errorDiff.baselineCount,
627
+ current_count: errorDiff.currentCount,
628
+ schema_hash: _schemaHash,
629
+ vault_dir: vaultDir,
630
+ files_checked: filesChecked,
631
+ excluded_count: excludedCount,
632
+ files_skipped_no_frontmatter: filesSkippedNoFrontmatter,
633
+ });
634
+
635
+ process.stderr.write(
636
+ `baseline=${errorDiff.baselineCount} current=${errorDiff.currentCount} new=${errorDiff.newErrors.length} resolved=${errorDiff.resolvedErrors.length}\n`,
637
+ );
638
+
639
+ process.exit(errorDiff.newErrors.length === 0 ? 0 : 1);
640
+ }
641
+
642
+ // ── mode=full | hard | warn ───────────────────────────────────────────────
643
+ // 'full' and 'hard' are identical (hard is the legacy alias).
644
+ // In warn mode, errors are reported but the status is "ok" for exit-code purposes.
645
+ // The errors array is still populated so the caller can surface them as warnings.
646
+ const status = hasErrors ? (mode === 'warn' ? 'ok' : 'invalid') : 'ok';
647
+ emit({
648
+ status,
649
+ mode,
650
+ vault_dir: vaultDir,
651
+ files_checked: filesChecked,
652
+ excluded_count: excludedCount,
653
+ files_skipped_no_frontmatter: filesSkippedNoFrontmatter,
654
+ errors,
655
+ warnings,
656
+ });
657
+
658
+ process.exit(hasErrors && (mode === 'hard' || mode === 'full') ? 1 : 0);