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,99 @@
1
+ import { matchBlockHeader } from './block-header.mjs';
2
+
3
+ /**
4
+ * slopcheck.mjs — Parser for the top-level `slopcheck:` YAML block
5
+ * (PRD gsd Pattern Adoption Quick-Wins — Pattern 2 / issues #517, #520).
6
+ *
7
+ * Drives the opt-in package-legitimacy gate that defends against LLM-
8
+ * hallucinated npm/pip/cargo package names ("slopsquatting"). Plugged into
9
+ * /plan PRD generation and /discovery supply-chain probes.
10
+ *
11
+ * Returns `{ enabled, sources }`.
12
+ * Tolerant parser: malformed values silently fall back to defaults.
13
+ *
14
+ * Consumers:
15
+ * - `scripts/lib/slopcheck.mjs` (classifyPackages())
16
+ * - `skills/discovery/probes/supply-chain-slopcheck.mjs` (discovery probe)
17
+ */
18
+
19
+ const ALLOWED_SOURCES = new Set(['plan', 'discovery']);
20
+ const DEFAULT_SOURCES = ['plan', 'discovery'];
21
+
22
+ /**
23
+ * Parse the top-level `slopcheck:` YAML block from markdown content.
24
+ * Independent of the `## Session Config` section boundary.
25
+ *
26
+ * Defaults:
27
+ * enabled: false (opt-in)
28
+ * sources: ['plan', 'discovery']
29
+ *
30
+ * @param {string} content — full file contents
31
+ * @returns {{ enabled: boolean, sources: string[] }}
32
+ */
33
+ export function _parseSlopcheck(content) {
34
+ const defaults = {
35
+ enabled: false,
36
+ sources: [...DEFAULT_SOURCES],
37
+ };
38
+
39
+ const lines = content.split(/\r?\n/);
40
+ let inBlock = false;
41
+ const blockLines = [];
42
+
43
+ for (const rawLine of lines) {
44
+ const line = rawLine.replace(/\r$/, '');
45
+ if (!inBlock) {
46
+ if (matchBlockHeader(line, 'slopcheck')) inBlock = true;
47
+ continue;
48
+ }
49
+ if (line.length > 0 && !/^\s/.test(line)) break;
50
+ blockLines.push(line);
51
+ }
52
+
53
+ if (blockLines.length === 0) return defaults;
54
+
55
+ let scEnabled = false;
56
+ let scSources = [...DEFAULT_SOURCES];
57
+
58
+ for (const rawLine of blockLines) {
59
+ const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
60
+ if (!clean.trim()) continue;
61
+
62
+ const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
63
+ if (!kvMatch) continue;
64
+
65
+ const k = kvMatch[1];
66
+ let v = kvMatch[2].trim();
67
+ if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
68
+ else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
69
+
70
+ switch (k) {
71
+ case 'enabled':
72
+ // Default is false → only flip to true on explicit "true"
73
+ scEnabled = v.toLowerCase() === 'true';
74
+ break;
75
+ case 'sources': {
76
+ // Accept inline array notation: [] or [a, b, c]
77
+ const stripped = v.replace(/^\s*\[/, '').replace(/\]\s*$/, '').trim();
78
+ if (stripped === '') {
79
+ scSources = [];
80
+ } else {
81
+ const items = stripped
82
+ .split(',')
83
+ .map((s) => s.trim())
84
+ .filter((s) => s.length > 0)
85
+ .filter((s) => ALLOWED_SOURCES.has(s));
86
+ // Only override the default when the parsed list is non-empty after filtering;
87
+ // a malformed list silently falls back to defaults.
88
+ if (items.length > 0) scSources = items;
89
+ }
90
+ break;
91
+ }
92
+ }
93
+ }
94
+
95
+ return {
96
+ enabled: scEnabled,
97
+ sources: scSources,
98
+ };
99
+ }
@@ -0,0 +1,83 @@
1
+ import { matchBlockHeader } from './block-header.mjs';
2
+
3
+ /**
4
+ * state-md-lock.mjs — Parser for the top-level `state-md-lock:` YAML block
5
+ * (PRD gsd Pattern Adoption Quick-Wins — Pattern 1 / issues #517, #518).
6
+ *
7
+ * Drives the mechanical STATE.md write lock that prevents race conditions
8
+ * between parallel worker sessions writing the same STATE.md.
9
+ *
10
+ * Returns `{ enabled, "timeout-ms" }`.
11
+ * Tolerant parser: malformed values silently fall back to defaults.
12
+ *
13
+ * Consumer: `scripts/lib/session-lock.mjs` (Agent A — adds withStateMdLock()).
14
+ */
15
+
16
+ /**
17
+ * Parse the top-level `state-md-lock:` YAML block from markdown content.
18
+ * Independent of the `## Session Config` section boundary.
19
+ *
20
+ * Defaults:
21
+ * enabled: true
22
+ * timeout-ms: 10000 (integer ≥ 0)
23
+ *
24
+ * @param {string} content — full file contents
25
+ * @returns {{ enabled: boolean, "timeout-ms": number }}
26
+ */
27
+ export function _parseStateMdLock(content) {
28
+ const defaults = {
29
+ enabled: true,
30
+ 'timeout-ms': 10000,
31
+ };
32
+
33
+ const lines = content.split(/\r?\n/);
34
+ let inBlock = false;
35
+ const blockLines = [];
36
+
37
+ for (const rawLine of lines) {
38
+ const line = rawLine.replace(/\r$/, '');
39
+ if (!inBlock) {
40
+ if (matchBlockHeader(line, 'state-md-lock')) inBlock = true;
41
+ continue;
42
+ }
43
+ if (line.length > 0 && !/^\s/.test(line)) break;
44
+ blockLines.push(line);
45
+ }
46
+
47
+ if (blockLines.length === 0) return defaults;
48
+
49
+ let smlEnabled = true;
50
+ let smlTimeoutMs = 10000;
51
+
52
+ for (const rawLine of blockLines) {
53
+ const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
54
+ if (!clean.trim()) continue;
55
+
56
+ const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
57
+ if (!kvMatch) continue;
58
+
59
+ const k = kvMatch[1];
60
+ let v = kvMatch[2].trim();
61
+ if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
62
+ else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
63
+
64
+ switch (k) {
65
+ case 'enabled':
66
+ // Default is true → only flip to false on explicit "false"
67
+ smlEnabled = v.toLowerCase() !== 'false';
68
+ break;
69
+ case 'timeout-ms': {
70
+ if (/^\d+$/.test(v)) {
71
+ const n = parseInt(v, 10);
72
+ if (n >= 0) smlTimeoutMs = n;
73
+ }
74
+ break;
75
+ }
76
+ }
77
+ }
78
+
79
+ return {
80
+ enabled: smlEnabled,
81
+ 'timeout-ms': smlTimeoutMs,
82
+ };
83
+ }
@@ -0,0 +1,94 @@
1
+ import { matchBlockHeader } from './block-header.mjs';
2
+
3
+ /**
4
+ * templates-first.mjs — Parser for the top-level `templates-first:` YAML block
5
+ * (PRD gsd Pattern Adoption Quick-Wins — Pattern 3 / issues #517, #519).
6
+ *
7
+ * Drives the pre-bash hook that blocks `gh|glab pr|mr|issue create` calls
8
+ * unless the matching repo template (.github/PULL_REQUEST_TEMPLATE,
9
+ * .gitlab/merge_request_templates/*, …) was Read in the current session.
10
+ *
11
+ * Returns `{ enabled, hosts }`.
12
+ * Tolerant parser: malformed values silently fall back to defaults.
13
+ *
14
+ * Consumer: `hooks/pre-bash-templates-first.mjs` (Wave 2).
15
+ */
16
+
17
+ const ALLOWED_HOSTS = new Set(['github', 'gitlab']);
18
+ const DEFAULT_HOSTS = ['github', 'gitlab'];
19
+
20
+ /**
21
+ * Parse the top-level `templates-first:` YAML block from markdown content.
22
+ * Independent of the `## Session Config` section boundary.
23
+ *
24
+ * Defaults:
25
+ * enabled: true
26
+ * hosts: ['github', 'gitlab']
27
+ *
28
+ * @param {string} content — full file contents
29
+ * @returns {{ enabled: boolean, hosts: string[] }}
30
+ */
31
+ export function _parseTemplatesFirst(content) {
32
+ const defaults = {
33
+ enabled: true,
34
+ hosts: [...DEFAULT_HOSTS],
35
+ };
36
+
37
+ const lines = content.split(/\r?\n/);
38
+ let inBlock = false;
39
+ const blockLines = [];
40
+
41
+ for (const rawLine of lines) {
42
+ const line = rawLine.replace(/\r$/, '');
43
+ if (!inBlock) {
44
+ if (matchBlockHeader(line, 'templates-first')) inBlock = true;
45
+ continue;
46
+ }
47
+ if (line.length > 0 && !/^\s/.test(line)) break;
48
+ blockLines.push(line);
49
+ }
50
+
51
+ if (blockLines.length === 0) return defaults;
52
+
53
+ let tfEnabled = true;
54
+ let tfHosts = [...DEFAULT_HOSTS];
55
+
56
+ for (const rawLine of blockLines) {
57
+ const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
58
+ if (!clean.trim()) continue;
59
+
60
+ const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
61
+ if (!kvMatch) continue;
62
+
63
+ const k = kvMatch[1];
64
+ let v = kvMatch[2].trim();
65
+ if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
66
+ else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
67
+
68
+ switch (k) {
69
+ case 'enabled':
70
+ // Default is true → only flip to false on explicit "false"
71
+ tfEnabled = v.toLowerCase() !== 'false';
72
+ break;
73
+ case 'hosts': {
74
+ const stripped = v.replace(/^\s*\[/, '').replace(/\]\s*$/, '').trim();
75
+ if (stripped === '') {
76
+ tfHosts = [];
77
+ } else {
78
+ const items = stripped
79
+ .split(',')
80
+ .map((s) => s.trim())
81
+ .filter((s) => s.length > 0)
82
+ .filter((s) => ALLOWED_HOSTS.has(s));
83
+ if (items.length > 0) tfHosts = items;
84
+ }
85
+ break;
86
+ }
87
+ }
88
+ }
89
+
90
+ return {
91
+ enabled: tfEnabled,
92
+ hosts: tfHosts,
93
+ };
94
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * test.mjs — Parser for the top-level `test:` YAML block.
3
+ *
4
+ * Mirrors the docs-orchestrator / events-rotation block-parser pattern.
5
+ * Promoted from the inline _parseTestBlock in scripts/parse-config.mjs
6
+ * as part of the /test epic (#378) Track B wiring.
7
+ */
8
+
9
+ import { validatePathInsideProject } from '../path-utils.mjs';
10
+ import { matchBlockHeader } from './block-header.mjs';
11
+
12
+ /**
13
+ * Parse the top-level `test:` YAML block from markdown content.
14
+ * Returns defaults when the block is absent.
15
+ * @param {string} content — full CLAUDE.md / AGENTS.md content
16
+ * @returns {{enabled: boolean, "default-profile": string, "profiles-path": string, mode: string, "retention-days": number}}
17
+ * `profiles-path` is stored as an absolute path (realpath-resolved when the target exists,
18
+ * lexically-resolved via `path.resolve(cwd, v)` when the target does not exist yet) —
19
+ * defeats post-validation symlink-swap TOCTOU (#405, deep-4 deep-5).
20
+ */
21
+ export function _parseTest(content) {
22
+ const defaults = {
23
+ enabled: false,
24
+ 'default-profile': 'smoke',
25
+ 'profiles-path': '.orchestrator/policy/test-profiles.json',
26
+ mode: 'warn',
27
+ 'retention-days': 30,
28
+ };
29
+
30
+ const lines = content.split(/\r?\n/);
31
+ let inBlock = false;
32
+ const blockLines = [];
33
+
34
+ for (const rawLine of lines) {
35
+ const line = rawLine.replace(/\r$/, '');
36
+ if (!inBlock) {
37
+ // Match top-level `test:` key (not indented, no inline value after colon)
38
+ if (matchBlockHeader(line, 'test')) {
39
+ inBlock = true;
40
+ }
41
+ continue;
42
+ }
43
+ // Any non-empty, non-indented line closes the block
44
+ if (line.length > 0 && !/^\s/.test(line)) break;
45
+ blockLines.push(line);
46
+ }
47
+
48
+ if (blockLines.length === 0) return defaults;
49
+
50
+ let tcEnabled = false;
51
+ let tcDefaultProfile = 'smoke';
52
+ let tcProfilesPath = '.orchestrator/policy/test-profiles.json';
53
+ let tcMode = 'warn';
54
+ let tcRetentionDays = 30;
55
+
56
+ const validModes = new Set(['warn', 'strict', 'off']);
57
+
58
+ for (const rawLine of blockLines) {
59
+ // Strip inline YAML comments and trailing whitespace
60
+ const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
61
+ if (!clean.trim()) continue;
62
+
63
+ const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
64
+ if (!kvMatch) continue;
65
+
66
+ const k = kvMatch[1];
67
+ let v = kvMatch[2].trim();
68
+ // Strip surrounding quotes
69
+ if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
70
+ else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
71
+
72
+ switch (k) {
73
+ case 'enabled':
74
+ tcEnabled = v.toLowerCase() === 'true';
75
+ break;
76
+ case 'default-profile':
77
+ if (v) tcDefaultProfile = v;
78
+ break;
79
+ case 'profiles-path':
80
+ if (v) {
81
+ // SEC-IR-LOW-2 + SEC-Q2-LOW-1 + #402 + #405:
82
+ // Delegate two-phase path-traversal + symlink-escape guard to the shared helper.
83
+ // Store the resolved path (not raw v) to defeat TOCTOU symlink-swap attacks (#405).
84
+ const projectRoot = process.cwd();
85
+ const result = validatePathInsideProject(v, projectRoot);
86
+ if (result.ok) {
87
+ // Store resolved path, not raw v, to defeat TOCTOU symlink-swap (#405)
88
+ tcProfilesPath = result.realPath || result.lexicalPath;
89
+ }
90
+ // Silent skip on failure — matches the lenient pattern of other case branches
91
+ }
92
+ break;
93
+ case 'mode':
94
+ if (validModes.has(v.toLowerCase())) tcMode = v.toLowerCase();
95
+ break;
96
+ case 'retention-days': {
97
+ if (/^\d+$/.test(v)) {
98
+ const n = parseInt(v, 10);
99
+ if (n >= 0) tcRetentionDays = n;
100
+ }
101
+ break;
102
+ }
103
+ }
104
+ }
105
+
106
+ return {
107
+ enabled: tcEnabled,
108
+ 'default-profile': tcDefaultProfile,
109
+ 'profiles-path': tcProfilesPath,
110
+ mode: tcMode,
111
+ 'retention-days': tcRetentionDays,
112
+ };
113
+ }
@@ -0,0 +1,201 @@
1
+ /**
2
+ * vault-integration.mjs — Parsers for vault-integration and resource-thresholds
3
+ * sub-keys.
4
+ *
5
+ * `_parseVaultIntegration(content)` reads its block scoped from the raw markdown
6
+ * content (cold-start.mjs style), matching the pattern used by every other
7
+ * block-scoped parser in `scripts/lib/config/`. Pre-#593 this parser took a
8
+ * flat KV map shared with all other blocks — a name-collision time bomb
9
+ * because `enabled:` is also used by 15+ other blocks (`docs-orchestrator`,
10
+ * `vault-staleness`, `slopcheck`, etc.). The last `enabled:` line in the file
11
+ * silently overwrote `vault-integration.enabled: true`.
12
+ *
13
+ * `_parseResourceThresholds(kv)` is unchanged: its sub-keys
14
+ * (`ram-free-min-gb`, `ram-free-critical-gb`, `cpu-load-max-pct`,
15
+ * `concurrent-sessions-warn`, `ssh-no-docker`) are unique across all blocks,
16
+ * so a shared KV map has no collision risk.
17
+ *
18
+ * Issue #497 inline-object form is preserved on the content-based path —
19
+ * a `vault-integration: { ... }` line takes precedence over a same-named
20
+ * block form when both are present.
21
+ */
22
+
23
+ import { _coerceBoolean, _coerceInteger } from './coercers.mjs';
24
+ import { matchBlockHeader } from './block-header.mjs';
25
+
26
+ // ---------------------------------------------------------------------------
27
+ // vault-integration
28
+ // ---------------------------------------------------------------------------
29
+
30
+ const MODE_ALLOWED = ['warn', 'strict', 'off'];
31
+
32
+ /**
33
+ * Parse the top-level `vault-integration:` YAML block (or inline-object literal)
34
+ * from the markdown content. Independent of the `## Session Config` section
35
+ * boundary so a baseline using either CLAUDE.md / AGENTS.md baseline-list-item form
36
+ * (`- vault-integration: { ... }`) or block form is handled identically.
37
+ *
38
+ * Supports two source shapes:
39
+ * 1. Inline object literal on a single line (issue #497):
40
+ * `vault-integration: { enabled: true, vault-dir: ~/Projects/vault, mode: warn }`
41
+ * (with or without a leading `- ` list-item dash)
42
+ * 2. Block form with indented sub-keys (default):
43
+ * ```
44
+ * vault-integration:
45
+ * enabled: true
46
+ * vault-dir: ~/Projects/vault
47
+ * mode: warn
48
+ * ```
49
+ *
50
+ * The inline form takes precedence when both are present.
51
+ *
52
+ * Accepted forms: the bold-bullet markdown rendering of either shape above —
53
+ * `- **vault-integration:** { ... }` or a `- **vault-integration:**` header
54
+ * followed by an indented block — is also accepted (#823). The optional `**`
55
+ * is stripped only immediately around the `key:` token at line start; the
56
+ * value portion (including any literal `**` inside it) is untouched.
57
+ *
58
+ * Defaults:
59
+ * enabled: false
60
+ * vault-dir: null
61
+ * mode: "warn" (invalid values silently fall back to "warn")
62
+ * vault-name: null (absent = downstream callers use deriveRepo() default)
63
+ *
64
+ * @param {string} content — full file contents
65
+ * @returns {{enabled: boolean, "vault-dir": string|null, mode: string, "vault-name": string|null}}
66
+ */
67
+ export function _parseVaultIntegration(content) {
68
+ const defaults = { enabled: false, 'vault-dir': null, mode: 'warn', 'vault-name': null };
69
+ if (typeof content !== 'string' || content === '') return defaults;
70
+
71
+ const lines = content.split(/\r?\n/);
72
+
73
+ // Pass 1: inline-object form. Matches `vault-integration: { ... }` with or
74
+ // without a leading `- ` (baseline list-item form per #497).
75
+ for (const rawLine of lines) {
76
+ const line = rawLine.replace(/\r$/, '');
77
+ const inlineMatch = line.match(/^(?:-\s+)?(?:\*\*)?vault-integration:(?:\*\*)?\s*(\{[^}]*\})\s*(?:#.*)?$/);
78
+ if (inlineMatch) {
79
+ return _parseInlineObject(inlineMatch[1]);
80
+ }
81
+ }
82
+
83
+ // Pass 2: block form. Find `^vault-integration:\s*$` (header-only line) and
84
+ // accumulate indented continuation lines until a non-indented line breaks
85
+ // out of the block.
86
+ let inBlock = false;
87
+ const blockLines = [];
88
+ for (const rawLine of lines) {
89
+ const line = rawLine.replace(/\r$/, '');
90
+ if (!inBlock) {
91
+ if (matchBlockHeader(line, 'vault-integration')) inBlock = true;
92
+ continue;
93
+ }
94
+ if (line.length > 0 && !/^\s/.test(line)) break;
95
+ blockLines.push(line);
96
+ }
97
+ if (blockLines.length === 0) return defaults;
98
+
99
+ let enabled = false;
100
+ let vaultDir = null;
101
+ let mode = 'warn';
102
+ let vaultName = null;
103
+
104
+ for (const rawLine of blockLines) {
105
+ const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
106
+ if (!clean.trim()) continue;
107
+
108
+ // Only first-level sub-keys (single indent). Skip deeper nested keys like
109
+ // `gitlab-groups:` list items (handled as a no-op — they aren't in this
110
+ // parser's return shape).
111
+ const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)$/);
112
+ if (!kvMatch) continue;
113
+
114
+ const k = kvMatch[1];
115
+ let v = kvMatch[2].trim();
116
+ if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
117
+ else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
118
+
119
+ switch (k) {
120
+ case 'enabled':
121
+ // Strict booleans only. Anything other than "true"/"false" stays at default (false).
122
+ if (v.toLowerCase() === 'true') enabled = true;
123
+ else if (v.toLowerCase() === 'false') enabled = false;
124
+ break;
125
+ case 'vault-dir':
126
+ if (v === '' || v === 'none' || v === 'null') vaultDir = null;
127
+ else vaultDir = v;
128
+ break;
129
+ case 'mode':
130
+ if (MODE_ALLOWED.includes(v.toLowerCase())) mode = v.toLowerCase();
131
+ else mode = 'warn'; // silent fallback (parity with pre-#593 behaviour)
132
+ break;
133
+ case 'vault-name':
134
+ if (v === '' || v === 'none' || v === 'null') vaultName = null;
135
+ else vaultName = v;
136
+ break;
137
+ }
138
+ }
139
+
140
+ return { enabled, 'vault-dir': vaultDir, mode, 'vault-name': vaultName };
141
+ }
142
+
143
+ /**
144
+ * Parse an inline YAML object literal `{ key: val, key: val }` into the
145
+ * vault-integration return shape. Supports unquoted values including `~/` paths.
146
+ *
147
+ * @param {string} raw — full literal including braces
148
+ * @returns {{enabled: boolean, "vault-dir": string|null, mode: string}}
149
+ */
150
+ function _parseInlineObject(raw) {
151
+ const stripped = raw.replace(/^\s*\{/, '').replace(/\}\s*$/, '').trim();
152
+ const kv = new Map();
153
+ if (stripped !== '') {
154
+ for (const pair of stripped.split(',')) {
155
+ const colonIdx = pair.indexOf(':');
156
+ if (colonIdx === -1) continue;
157
+ const k = pair.slice(0, colonIdx).trim();
158
+ const v = pair.slice(colonIdx + 1).trim();
159
+ if (k) kv.set(k, v);
160
+ }
161
+ }
162
+
163
+ const enabledRaw = kv.get('enabled');
164
+ const enabled = enabledRaw === 'true' ? true : false;
165
+ const vaultDirRaw = kv.get('vault-dir');
166
+ const vaultDir =
167
+ vaultDirRaw === undefined || vaultDirRaw === '' || vaultDirRaw === 'none' || vaultDirRaw === 'null'
168
+ ? null
169
+ : vaultDirRaw;
170
+ const modeRaw = kv.get('mode') ?? 'warn';
171
+ const mode = MODE_ALLOWED.includes(modeRaw.toLowerCase()) ? modeRaw.toLowerCase() : 'warn';
172
+ const vaultNameRaw = kv.get('vault-name');
173
+ const vaultName =
174
+ vaultNameRaw === undefined || vaultNameRaw === '' || vaultNameRaw === 'none' || vaultNameRaw === 'null'
175
+ ? null
176
+ : vaultNameRaw;
177
+ return { enabled, 'vault-dir': vaultDir, mode, 'vault-name': vaultName };
178
+ }
179
+
180
+ // ---------------------------------------------------------------------------
181
+ // resource-thresholds
182
+ // ---------------------------------------------------------------------------
183
+
184
+ // Sub-key names are deliberately unique across all blocks (no collision with
185
+ // vault-integration / vault-sync / others) because they are flattened into the
186
+ // same KV map by the Session Config parser. See the A5 note in parse-config.sh.
187
+
188
+ /**
189
+ * Extract resource-thresholds sub-keys from the Session Config KV map.
190
+ * @param {Map<string, string>} kv
191
+ * @returns {{[key: string]: number|boolean}}
192
+ */
193
+ export function _parseResourceThresholds(kv) {
194
+ return {
195
+ 'ram-free-min-gb': _coerceInteger(kv, 'ram-free-min-gb', 4),
196
+ 'ram-free-critical-gb': _coerceInteger(kv, 'ram-free-critical-gb', 2),
197
+ 'cpu-load-max-pct': _coerceInteger(kv, 'cpu-load-max-pct', 80),
198
+ 'concurrent-sessions-warn': _coerceInteger(kv, 'concurrent-sessions-warn', 5),
199
+ 'ssh-no-docker': _coerceBoolean(kv, 'ssh-no-docker', true),
200
+ };
201
+ }
@@ -0,0 +1,99 @@
1
+ import { matchBlockHeader } from './block-header.mjs';
2
+
3
+ /**
4
+ * vault-mirror-quality.mjs — Parser for the top-level `vault-mirror:` YAML block,
5
+ * extracting the nested `quality:` sub-block (PRD F1.2 / issue #504).
6
+ *
7
+ * Returns the consumer-facing shape `{ quality: { "min-narrative-chars": int, "min-confidence": float } }`.
8
+ * Tolerant parser: malformed values silently fall back to defaults.
9
+ *
10
+ * Consumer: `scripts/vault-mirror.mjs` (I4's code).
11
+ */
12
+
13
+ /**
14
+ * Parse the top-level `vault-mirror:` YAML block from markdown content, extracting
15
+ * the nested `quality:` sub-block. Independent of the `## Session Config` section
16
+ * boundary (mirrors `_parseEventsRotation` / `_parseVaultStaleness` design).
17
+ *
18
+ * Defaults:
19
+ * quality.min-narrative-chars: 400 (integer ≥ 0)
20
+ * quality.min-confidence: 0.5 (float in [0.0, 1.0])
21
+ *
22
+ * @param {string} content — full file contents
23
+ * @returns {{ quality: { "min-narrative-chars": number, "min-confidence": number } }}
24
+ */
25
+ export function _parseVaultMirrorQuality(content) {
26
+ const defaults = {
27
+ quality: {
28
+ 'min-narrative-chars': 400,
29
+ 'min-confidence': 0.5,
30
+ },
31
+ };
32
+
33
+ const lines = content.split(/\r?\n/);
34
+ let inBlock = false;
35
+ const blockLines = [];
36
+
37
+ for (const rawLine of lines) {
38
+ const line = rawLine.replace(/\r$/, '');
39
+ if (!inBlock) {
40
+ if (matchBlockHeader(line, 'vault-mirror')) inBlock = true;
41
+ continue;
42
+ }
43
+ // Stop at next top-level (non-indented, non-empty) key
44
+ if (line.length > 0 && !/^\s/.test(line)) break;
45
+ blockLines.push(line);
46
+ }
47
+
48
+ if (blockLines.length === 0) return defaults;
49
+
50
+ let qMinChars = 400;
51
+ let qMinConfidence = 0.5;
52
+ let inQualityBlock = false;
53
+
54
+ for (const rawLine of blockLines) {
55
+ const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
56
+ if (!clean.trim()) continue;
57
+
58
+ // Deeper-indented key (4+ spaces) → quality sub-key
59
+ const deepMatch = clean.match(/^\s{4,}([a-zA-Z_-]+):\s*(.*)/);
60
+ if (deepMatch && inQualityBlock) {
61
+ const k = deepMatch[1];
62
+ let v = deepMatch[2].trim();
63
+ if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
64
+ else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
65
+
66
+ if (k === 'min-narrative-chars') {
67
+ if (/^\d+$/.test(v)) {
68
+ const n = parseInt(v, 10);
69
+ if (n >= 0) qMinChars = n;
70
+ }
71
+ } else if (k === 'min-confidence') {
72
+ if (/^\d+(\.\d+)?$/.test(v)) {
73
+ const f = parseFloat(v);
74
+ if (Number.isFinite(f) && f >= 0.0 && f <= 1.0) qMinConfidence = f;
75
+ }
76
+ }
77
+ continue;
78
+ }
79
+
80
+ // Top-level key inside vault-mirror (2-space indent) — looking for `quality:`
81
+ const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
82
+ if (!kvMatch) continue;
83
+
84
+ inQualityBlock = false;
85
+ const k = kvMatch[1];
86
+ const v = kvMatch[2].trim();
87
+
88
+ if (k === 'quality' && v === '') {
89
+ inQualityBlock = true;
90
+ }
91
+ }
92
+
93
+ return {
94
+ quality: {
95
+ 'min-narrative-chars': qMinChars,
96
+ 'min-confidence': qMinConfidence,
97
+ },
98
+ };
99
+ }