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,248 @@
1
+ /**
2
+ * coercers.mjs — Value coercion helpers for Session Config parsing.
3
+ *
4
+ * Ported from config-json-coercion.sh (v2). Shared by all per-section parsers.
5
+ * Two functions are exported for external callers (_coerceEnum, _coerceCollisionRisk);
6
+ * the rest are internal to the config subsystem.
7
+ */
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Internal: raw lookup
11
+ // ---------------------------------------------------------------------------
12
+
13
+ /**
14
+ * Look up a key in the parsed KV map; returns the raw string value or the
15
+ * given default. Last match wins (mirrors the shell `tail -1` behaviour).
16
+ * @param {Map<string, string>} kv
17
+ * @param {string} key
18
+ * @param {string|undefined} def
19
+ * @returns {string|undefined}
20
+ */
21
+ export function _getVal(kv, key, def) {
22
+ const val = kv.get(key);
23
+ if (val !== undefined) return val;
24
+ return def;
25
+ }
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Coercion helpers
29
+ // ---------------------------------------------------------------------------
30
+
31
+ /**
32
+ * Coerce a value to a JSON string or null.
33
+ * @param {Map<string, string>} kv
34
+ * @param {string} key
35
+ * @param {string} [def] — omit for null default
36
+ * @returns {string|null}
37
+ */
38
+ export function _coerceString(kv, key, def) {
39
+ const val = _getVal(kv, key, def);
40
+ if (val === undefined || val === '' || val === 'none' || val === 'null') return null;
41
+ return val;
42
+ }
43
+
44
+ /**
45
+ * Coerce a value to an integer, supporting override syntax "N (k: M)".
46
+ * @param {Map<string, string>} kv
47
+ * @param {string} key
48
+ * @param {number} def
49
+ * @returns {number | {default: number, [k: string]: number}}
50
+ */
51
+ export function _coerceInteger(kv, key, def) {
52
+ const raw = _getVal(kv, key, String(def));
53
+
54
+ // Override syntax: "6 (deep: 18)" or "6 (deep: 18, fast: 4)"
55
+ const overrideMatch = raw.match(/^(\d+)\s*\(([^)]+)\)\s*$/);
56
+ if (overrideMatch) {
57
+ const base = parseInt(overrideMatch[1], 10);
58
+ if (isNaN(base)) throw new Error(`config.mjs: invalid integer base for '${key}': '${raw}'`);
59
+ const overridesStr = overrideMatch[2];
60
+ const result = { default: base };
61
+ for (const pair of overridesStr.split(',')) {
62
+ const colonIdx = pair.indexOf(':');
63
+ if (colonIdx === -1) continue;
64
+ const okey = pair.slice(0, colonIdx).trim();
65
+ const oval = pair.slice(colonIdx + 1).trim();
66
+ const oint = parseInt(oval, 10);
67
+ if (isNaN(oint) || !/^\d+$/.test(oval)) {
68
+ throw new Error(`config.mjs: invalid integer override for '${key}.${okey}': '${oval}'`);
69
+ }
70
+ result[okey] = oint;
71
+ }
72
+ return result;
73
+ }
74
+
75
+ if (!/^\d+$/.test(raw)) {
76
+ throw new Error(`config.mjs: invalid integer for '${key}': '${raw}'`);
77
+ }
78
+ return parseInt(raw, 10);
79
+ }
80
+
81
+ /**
82
+ * Coerce a value to a float with optional bounds.
83
+ * @param {Map<string, string>} kv
84
+ * @param {string} key
85
+ * @param {number} def
86
+ * @param {number} [min]
87
+ * @param {number} [max] — exclusive upper bound
88
+ * @returns {number}
89
+ */
90
+ export function _coerceFloat(kv, key, def, min, max) {
91
+ const raw = _getVal(kv, key, String(def));
92
+
93
+ if (!/^\d+(\.\d+)?$/.test(raw)) {
94
+ throw new Error(`config.mjs: invalid float for '${key}': '${raw}' (expected non-negative number)`);
95
+ }
96
+ const val = parseFloat(raw);
97
+
98
+ if (min !== undefined && val < min) {
99
+ throw new Error(`config.mjs: float '${key}' value '${raw}' is below minimum '${min}'`);
100
+ }
101
+ if (max !== undefined && val >= max) {
102
+ throw new Error(`config.mjs: float '${key}' value '${raw}' must be less than '${max}'`);
103
+ }
104
+ return val;
105
+ }
106
+
107
+ /**
108
+ * Coerce a value to a boolean.
109
+ * @param {Map<string, string>} kv
110
+ * @param {string} key
111
+ * @param {boolean} def
112
+ * @returns {boolean}
113
+ */
114
+ export function _coerceBoolean(kv, key, def) {
115
+ const raw = _getVal(kv, key, def ? 'true' : 'false');
116
+ const lower = raw.toLowerCase();
117
+ if (lower === 'true') return true;
118
+ if (lower === 'false') return false;
119
+ throw new Error(`config.mjs: invalid boolean for '${key}': '${raw}' (expected true or false)`);
120
+ }
121
+
122
+ /**
123
+ * Coerce a value to a JSON array of strings, or null.
124
+ * Handles "[a, b, c]", "a, b, c", "[]", "none", or absent (null).
125
+ * @param {Map<string, string>} kv
126
+ * @param {string} key
127
+ * @param {string|null} [def] — raw default string like "[all]" or "[]"
128
+ * @returns {string[]|null}
129
+ */
130
+ export function _coerceList(kv, key, def) {
131
+ const raw = _getVal(kv, key, def !== undefined ? def : undefined);
132
+
133
+ if (raw === undefined || raw === 'none' || raw === 'null') return null;
134
+
135
+ // Strip surrounding brackets
136
+ const stripped = raw.replace(/^\s*\[/, '').replace(/\]\s*$/, '').trim();
137
+
138
+ if (stripped === '') return [];
139
+
140
+ // If value contains '{', bail to null (complex object)
141
+ if (stripped.includes('{')) return null;
142
+
143
+ const items = stripped.split(',').map(s => s.trim()).filter(s => s.length > 0);
144
+ return items;
145
+ }
146
+
147
+ /**
148
+ * Coerce a value to an enum string (lower-cased), throw on invalid.
149
+ * @param {Map<string, string>} kv
150
+ * @param {string} key
151
+ * @param {string} def
152
+ * @param {string[]} allowed
153
+ * @returns {string}
154
+ */
155
+ export function _coerceEnum(kv, key, def, allowed) {
156
+ const raw = _getVal(kv, key, def);
157
+ const lower = raw.toLowerCase();
158
+ if (!allowed.includes(lower)) {
159
+ throw new Error(`config.mjs: ${key} must be ${allowed.join('|')}, got '${raw}'`);
160
+ }
161
+ return lower;
162
+ }
163
+
164
+ /**
165
+ * Validate and normalise a collision-risk value from plan output JSON.
166
+ * Returns the default when value is null/undefined; throws TypeError on invalid.
167
+ * @param {*} value
168
+ * @param {string} [def='low']
169
+ * @returns {'low'|'medium'|'high'}
170
+ */
171
+ export function _coerceCollisionRisk(value, def = 'low') {
172
+ const ALLOWED = ['low', 'medium', 'high'];
173
+ if (value === null || value === undefined) return def;
174
+ const lower = String(value).toLowerCase();
175
+ if (!ALLOWED.includes(lower)) {
176
+ throw new TypeError(`_coerceCollisionRisk: must be low|medium|high, got '${value}'`);
177
+ }
178
+ return lower;
179
+ }
180
+
181
+ /**
182
+ * Coerce a value to a plain object of string values, or null.
183
+ * Handles "{ key1: val1, key2: val2 }".
184
+ * @param {Map<string, string>} kv
185
+ * @param {string} key
186
+ * @returns {Record<string,string>|null}
187
+ */
188
+ export function _coerceObject(kv, key) {
189
+ const raw = _getVal(kv, key, undefined);
190
+ if (raw === undefined || raw === 'none' || raw === 'null') return null;
191
+
192
+ const stripped = raw.replace(/^\s*\{/, '').replace(/\}\s*$/, '').trim();
193
+ if (stripped === '') return null;
194
+
195
+ const result = {};
196
+ for (const pair of stripped.split(',')) {
197
+ const colonIdx = pair.indexOf(':');
198
+ if (colonIdx === -1) continue;
199
+ const k = pair.slice(0, colonIdx).trim();
200
+ const v = pair.slice(colonIdx + 1).trim();
201
+ if (k) result[k] = v;
202
+ }
203
+ return Object.keys(result).length === 0 ? null : result;
204
+ }
205
+
206
+ /**
207
+ * Coerce a value to an object of boolean values (for enforcement-gates).
208
+ * @param {Map<string, string>} kv
209
+ * @param {string} key
210
+ * @returns {Record<string,boolean>|null}
211
+ */
212
+ export function _coerceBoolObject(kv, key) {
213
+ const raw = _getVal(kv, key, undefined);
214
+ if (raw === undefined || raw === 'none' || raw === 'null') return null;
215
+
216
+ const stripped = raw.replace(/^\s*\{/, '').replace(/\}\s*$/, '').trim();
217
+ if (stripped === '') return null;
218
+
219
+ const result = {};
220
+ for (const pair of stripped.split(',')) {
221
+ const colonIdx = pair.indexOf(':');
222
+ if (colonIdx === -1) continue;
223
+ const k = pair.slice(0, colonIdx).trim();
224
+ const v = pair.slice(colonIdx + 1).trim().toLowerCase();
225
+ if (!k) continue;
226
+ if (v === 'true') result[k] = true;
227
+ else if (v === 'false') result[k] = false;
228
+ else throw new Error(`config.mjs: invalid enforcement-gates value for '${k}': '${v}' (must be true or false)`);
229
+ }
230
+ return Object.keys(result).length === 0 ? null : result;
231
+ }
232
+
233
+ /**
234
+ * Coerce max-turns: positive integer or "auto".
235
+ * @param {Map<string, string>} kv
236
+ * @returns {number|string}
237
+ */
238
+ export function _coerceMaxTurns(kv) {
239
+ const raw = _getVal(kv, 'max-turns', 'auto');
240
+ const lower = raw.toLowerCase();
241
+ if (lower === 'auto') return 'auto';
242
+ if (/^\d+$/.test(raw)) {
243
+ const n = parseInt(raw, 10);
244
+ if (n <= 0) throw new Error(`config.mjs: invalid max-turns: '${raw}' (must be positive integer or 'auto')`);
245
+ return n;
246
+ }
247
+ throw new Error(`config.mjs: invalid max-turns: '${raw}' (must be positive integer or 'auto')`);
248
+ }
@@ -0,0 +1,92 @@
1
+ import { matchBlockHeader } from './block-header.mjs';
2
+
3
+ /**
4
+ * cold-start.mjs — Parser for the top-level `cold-start:` YAML block (PRD F1.3 /
5
+ * issue #500). Drives the cold-start detector that nudges operators about long
6
+ * idle periods or memory silence.
7
+ *
8
+ * Returns `{ enabled, "nudge-after-hours", "silence-after-sessions" }`.
9
+ * Tolerant parser: malformed values silently fall back to defaults.
10
+ *
11
+ * Consumer: `scripts/lib/cold-start-detector.mjs` (I2's code).
12
+ */
13
+
14
+ /**
15
+ * Parse the top-level `cold-start:` YAML block from markdown content.
16
+ * Independent of the `## Session Config` section boundary.
17
+ *
18
+ * Defaults:
19
+ * enabled: true
20
+ * nudge-after-hours: 1 (integer ≥ 0)
21
+ * silence-after-sessions: 1 (integer ≥ 0)
22
+ *
23
+ * @param {string} content — full file contents
24
+ * @returns {{ enabled: boolean, "nudge-after-hours": number, "silence-after-sessions": number }}
25
+ */
26
+ export function _parseColdStart(content) {
27
+ const defaults = {
28
+ enabled: true,
29
+ 'nudge-after-hours': 1,
30
+ 'silence-after-sessions': 1,
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, 'cold-start')) 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 csEnabled = true;
50
+ let csNudgeAfterHours = 1;
51
+ let csSilenceAfterSessions = 1;
52
+
53
+ for (const rawLine of blockLines) {
54
+ const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
55
+ if (!clean.trim()) continue;
56
+
57
+ const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
58
+ if (!kvMatch) continue;
59
+
60
+ const k = kvMatch[1];
61
+ let v = kvMatch[2].trim();
62
+ if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
63
+ else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
64
+
65
+ switch (k) {
66
+ case 'enabled':
67
+ // Default is true → only flip to false on explicit "false"
68
+ csEnabled = v.toLowerCase() !== 'false';
69
+ break;
70
+ case 'nudge-after-hours': {
71
+ if (/^\d+$/.test(v)) {
72
+ const n = parseInt(v, 10);
73
+ if (n >= 0) csNudgeAfterHours = n;
74
+ }
75
+ break;
76
+ }
77
+ case 'silence-after-sessions': {
78
+ if (/^\d+$/.test(v)) {
79
+ const n = parseInt(v, 10);
80
+ if (n >= 0) csSilenceAfterSessions = n;
81
+ }
82
+ break;
83
+ }
84
+ }
85
+ }
86
+
87
+ return {
88
+ enabled: csEnabled,
89
+ 'nudge-after-hours': csNudgeAfterHours,
90
+ 'silence-after-sessions': csSilenceAfterSessions,
91
+ };
92
+ }
@@ -0,0 +1,120 @@
1
+ import { matchBlockHeader } from './block-header.mjs';
2
+
3
+ /**
4
+ * config-protection.mjs — Parser for the top-level `config-protection:` YAML
5
+ * block (ecc-analysis / issue #622).
6
+ *
7
+ * Drives the PreToolUse Edit|Write guard that intercepts edits to a small
8
+ * allow-list of quality-gate config files (eslint / vitest / tsconfig /
9
+ * prettier / commitlint / gitleaks) and WARNs — or, in `strict` mode, blocks —
10
+ * when an edit LOOSENS a gate (threshold lowered, disable/ignore directive
11
+ * added, rule removed, gitleaks allowlist widened, tsconfig strictness
12
+ * relaxed). The edit-tool analogue of the test-the-mock gate-cheating
13
+ * anti-pattern. First-time creation, tightening, and neutral edits are always
14
+ * allowed. A `allow-config-weakening: true` Session Config line bypasses the
15
+ * guard for the session (mirrors `allow-destructive-ops`).
16
+ *
17
+ * Returns `{ enabled, mode }`.
18
+ * Tolerant parser: malformed values silently fall back to defaults.
19
+ *
20
+ * Consumer: `hooks/config-protection.mjs`.
21
+ */
22
+
23
+ /** Valid `mode` values. Unknown values fall back to the default. */
24
+ const VALID_MODES = new Set(['warn', 'strict']);
25
+ const DEFAULT_MODE = 'warn';
26
+
27
+ /**
28
+ * Parse the top-level `config-protection:` YAML block from markdown content.
29
+ * Independent of the `## Session Config` section boundary (mirrors the other
30
+ * config parsers in this directory — tolerant, defaults-on-malformed).
31
+ *
32
+ * Defaults:
33
+ * enabled: true
34
+ * mode: 'warn' (warn → stderr + event + exit 0; strict → block, exit 2)
35
+ *
36
+ * @param {string} content — full file contents
37
+ * @returns {{ enabled: boolean, mode: 'warn'|'strict' }}
38
+ */
39
+ export function _parseConfigProtection(content) {
40
+ const defaults = {
41
+ enabled: true,
42
+ mode: DEFAULT_MODE,
43
+ };
44
+
45
+ if (typeof content !== 'string' || content.length === 0) return defaults;
46
+
47
+ const lines = content.split(/\r?\n/);
48
+ let inBlock = false;
49
+ const blockLines = [];
50
+
51
+ for (const rawLine of lines) {
52
+ const line = rawLine.replace(/\r$/, '');
53
+ if (!inBlock) {
54
+ if (matchBlockHeader(line, 'config-protection')) inBlock = true;
55
+ continue;
56
+ }
57
+ if (line.length > 0 && !/^\s/.test(line)) break;
58
+ blockLines.push(line);
59
+ }
60
+
61
+ if (blockLines.length === 0) return defaults;
62
+
63
+ let cpEnabled = true;
64
+ let cpMode = DEFAULT_MODE;
65
+
66
+ for (const rawLine of blockLines) {
67
+ const clean = rawLine.replace(/\s*#.*$/, '').replace(/\s+$/, '');
68
+ if (!clean.trim()) continue;
69
+
70
+ const kvMatch = clean.match(/^\s+([a-zA-Z_-]+):\s*(.*)/);
71
+ if (!kvMatch) continue;
72
+
73
+ const k = kvMatch[1];
74
+ let v = kvMatch[2].trim();
75
+ if (v.startsWith('"') && v.endsWith('"') && v.length >= 2) v = v.slice(1, -1);
76
+ else if (v.startsWith("'") && v.endsWith("'") && v.length >= 2) v = v.slice(1, -1);
77
+
78
+ switch (k) {
79
+ case 'enabled':
80
+ // Default is true → only flip to false on explicit "false".
81
+ cpEnabled = v.toLowerCase() !== 'false';
82
+ break;
83
+ case 'mode': {
84
+ const lower = v.toLowerCase();
85
+ cpMode = VALID_MODES.has(lower) ? lower : DEFAULT_MODE;
86
+ break;
87
+ }
88
+ }
89
+ }
90
+
91
+ return {
92
+ enabled: cpEnabled,
93
+ mode: cpMode,
94
+ };
95
+ }
96
+
97
+ /**
98
+ * Detect the per-session bypass `allow-config-weakening: true`. This is a
99
+ * top-level Session Config line (NOT inside the `config-protection:` block),
100
+ * mirroring `allow-destructive-ops`. Line-scoped within the `## Session Config`
101
+ * section, exactly like `pre-bash-destructive-guard.mjs`'s bypass scan.
102
+ *
103
+ * @param {string} content — full file contents
104
+ * @returns {boolean} true when the bypass is explicitly set to `true`
105
+ */
106
+ export function _isConfigWeakeningAllowed(content) {
107
+ if (typeof content !== 'string' || content.length === 0) return false;
108
+
109
+ const lines = content.split(/\r?\n/);
110
+ let inConfig = false;
111
+ for (const line of lines) {
112
+ if (line === '## Session Config') { inConfig = true; continue; }
113
+ if (inConfig && /^## /.test(line)) break;
114
+ if (inConfig) {
115
+ const m = line.match(/^\s*(?:-\s+\*\*)?allow-config-weakening(?::\*\*)?\s*:\s*(\S+)/);
116
+ if (m && m[1].toLowerCase() === 'true') return true;
117
+ }
118
+ }
119
+ return false;
120
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * cross-repo.mjs — Parser for the `cross-repo:` sub-block in Session Config (#469, #478).
3
+ *
4
+ * Exports:
5
+ * _parseCrossRepo(content) — PURE, no side effects. Extracts cross-repo.projects from
6
+ * the top-level `cross-repo:` block in markdown content.
7
+ * getCrossRepoProjects(cwd?) — async accessor: reads config file, parses, returns list.
8
+ *
9
+ * Uses block-scanner (not _parseKV) because the dot in "cross-repo.projects" is not
10
+ * supported by the KV regex. Scans for a `cross-repo:` block and then reads `projects:`.
11
+ */
12
+
13
+ // `readConfigFile` is imported from the dependency-free leaf config/io.mjs (a
14
+ // sibling), NOT from config.mjs. This avoids the former length-2 cycle
15
+ // config.mjs ⇄ config/cross-repo.mjs (config.mjs imports `_parseCrossRepo` from
16
+ // here). We deliberately do NOT import `parseSessionConfig` — calling it from
17
+ // `getCrossRepoProjects` would re-run `_parseCrossRepo` (double-parse). By calling
18
+ // `_parseCrossRepo` directly on the raw content we parse exactly once. (issue #664)
19
+ import { homedir } from 'node:os';
20
+ import { join } from 'node:path';
21
+ import { readConfigFile } from './io.mjs';
22
+ import { matchBlockHeader } from './block-header.mjs';
23
+
24
+ /**
25
+ * Resolve the cross-repo confinement root. Defaults to ~/Projects.
26
+ * Override via CROSS_REPO_CONFINEMENT_ROOT env (test-only — never set in production).
27
+ *
28
+ * @returns {string} absolute path
29
+ */
30
+ export function getConfinementRoot() {
31
+ const v = process.env.CROSS_REPO_CONFINEMENT_ROOT;
32
+ return (v && v.trim()) ? v : join(homedir(), 'Projects');
33
+ }
34
+
35
+ // Allowlist: only characters that are safe in shell contexts and file paths.
36
+ // Rejects entries containing shell metacharacters (;, $, `, |, &, >, <, (, ), space, etc.).
37
+ const SAFE_PATH_RE = /^[A-Za-z0-9._~/-]+$/;
38
+
39
+ /**
40
+ * Parse the `cross-repo:` block from markdown content and extract the `projects:` list.
41
+ *
42
+ * Behaviour-preserving lift of the IIFE that previously lived in config.mjs.
43
+ * Scans lines for `cross-repo:` block header, then reads the `projects:` key inside.
44
+ * Stops scanning at the next non-indented, non-empty line (next top-level YAML key).
45
+ *
46
+ * @param {string} content — full CLAUDE.md / AGENTS.md file content
47
+ * @returns {string[]} list of project paths, or [] when absent/empty/none/null
48
+ */
49
+ export function _parseCrossRepo(content) {
50
+ const lines = content.split(/\r?\n/);
51
+ let inBlock = false;
52
+
53
+ for (const rawLine of lines) {
54
+ const line = rawLine.replace(/\r$/, '');
55
+
56
+ if (!inBlock) {
57
+ if (matchBlockHeader(line, 'cross-repo')) { inBlock = true; }
58
+ continue;
59
+ }
60
+
61
+ // Stop at next top-level (non-indented, non-empty) key
62
+ if (line.length > 0 && !/^\s/.test(line)) break;
63
+
64
+ const m = line.match(/^\s+projects:\s*(.*)/);
65
+ if (m) {
66
+ const raw = m[1].replace(/\s*#.*$/, '').trim();
67
+ if (!raw || raw === 'none' || raw === 'null') return [];
68
+ const stripped = raw.replace(/^\s*\[/, '').replace(/\]\s*$/, '').trim();
69
+ if (stripped === '') return [];
70
+ // SEAM(#477): per-entry shell-meta validation — reject entries with shell metacharacters.
71
+ return stripped.split(',').map(s => s.trim()).filter(s => {
72
+ if (s.length === 0) return false;
73
+ if (!SAFE_PATH_RE.test(s)) {
74
+ process.stderr.write(`cross-repo: rejected project entry with shell metacharacter: ${JSON.stringify(s)}\n`);
75
+ return false;
76
+ }
77
+ return true;
78
+ });
79
+ }
80
+ }
81
+
82
+ return [];
83
+ }
84
+
85
+ /**
86
+ * Load cross-repo.projects from Session Config (CLAUDE.md / AGENTS.md) in the
87
+ * given working directory (defaults to process.cwd()).
88
+ *
89
+ * Returns an empty array when the field is absent or the config file is not found.
90
+ * Never throws.
91
+ *
92
+ * @param {string} [cwd] — directory to search for CLAUDE.md / AGENTS.md
93
+ * @returns {Promise<string[]>}
94
+ */
95
+ export async function getCrossRepoProjects(cwd = process.cwd()) {
96
+ try {
97
+ const mdContent = await readConfigFile(cwd);
98
+ // Direct call (not via parseSessionConfig) — avoids the double-parse and tightens
99
+ // the cycle surface to a single readConfigFile edge. See module-header note.
100
+ return _parseCrossRepo(mdContent);
101
+ } catch {
102
+ return [];
103
+ }
104
+ }