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,802 @@
1
+ // scripts/autopilot-multi.mjs
2
+ //
3
+ // `autopilot --multi-story` CLI entrypoint. Orchestrates N parallel issue
4
+ // pipelines using worktree isolation. v1 thin-slice: apply mode runtime loop
5
+ // wired in by W3 P5-Orchestration-Glue agent.
6
+ //
7
+ // References:
8
+ // - "Autopilot Phase D — Per-Story Worktree Pipelines" (#341; archived in the private Meta-Vault) (PRD, status: shaped)
9
+ // - scripts/lib/autopilot/dep-graph.mjs (NEW, parallel-built by C2 agent)
10
+ // - scripts/lib/autopilot/worktree-pipeline.mjs (NEW, parallel-built by C3 agent)
11
+ // - scripts/lib/autopilot/multi-killswitch.mjs (NEW, parallel-built by C4 agent)
12
+ //
13
+ // CLI guard at bottom — top-level main() never runs on import (deep-2 #368).
14
+
15
+ import { parseArgs } from 'node:util';
16
+ import { execFile as execFileCb, spawnSync } from 'node:child_process';
17
+ import { promisify } from 'node:util';
18
+ import path from 'node:path';
19
+ import fs from 'node:fs';
20
+
21
+ const execFile = promisify(execFileCb);
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // Constants
25
+ // ---------------------------------------------------------------------------
26
+
27
+ const HELP_TEXT = `autopilot-multi — Phase D --multi-story orchestrator (v3.6 scaffold)
28
+
29
+ USAGE:
30
+ autopilot-multi [OPTIONS]
31
+
32
+ OPTIONS:
33
+ --max-stories <N> Max parallel story loops (1..10, default: 3)
34
+ --max-hours <H> Wall-clock budget in hours (0.5..24, default: 8)
35
+ --inactivity-timeout <S> Seconds without completion → stop (60..3600, default: 300)
36
+ --draft-mr <policy> off | on-loop-start | on-green (default: off)
37
+ --stall-seconds <S> Per-loop STALL_TIMEOUT threshold (60..3600, default: 600)
38
+ --dry-run Emit plan only, do not execute (default: true)
39
+ --apply Execute the plan (mutex with --dry-run)
40
+ --json Machine-readable output to stdout
41
+ --verbose Diagnostic output to stderr
42
+ --deconflict-paths <glob> Required when bg-isolation=none AND max-stories>1.
43
+ Confirms per-story file ownership is planned.
44
+ See .claude/rules/parallel-sessions.md PSA-001/002/003.
45
+ -h, --help Show this help and exit
46
+ --version Print version and exit
47
+
48
+ EXIT CODES:
49
+ 0 Success
50
+ 1 User error (bad flags)
51
+ 2 System error (libs/binaries/probe failed)
52
+ `;
53
+
54
+ const FLAGS = {
55
+ 'max-stories': { type: 'string', default: '3' },
56
+ 'max-hours': { type: 'string', default: '8' },
57
+ 'inactivity-timeout': { type: 'string', default: '300' },
58
+ 'draft-mr': { type: 'string', default: 'off' },
59
+ 'stall-seconds': { type: 'string', default: '600' },
60
+ 'dry-run': { type: 'boolean', default: true },
61
+ 'apply': { type: 'boolean', default: false },
62
+ 'json': { type: 'boolean', default: false },
63
+ 'verbose': { type: 'boolean', default: false },
64
+ 'help': { type: 'boolean', default: false, short: 'h' },
65
+ 'version': { type: 'boolean', default: false },
66
+ // bg-isolation: none requires explicit file-scope deconfliction acknowledgement
67
+ // when max-stories > 1. Pass a glob to confirm per-story file ownership is
68
+ // planned. See .claude/rules/parallel-sessions.md PSA-001/002/003 and #431.
69
+ 'deconflict-paths': { type: 'string', default: '' },
70
+ };
71
+
72
+ const VALID_DRAFT_MR_POLICIES = new Set(['off', 'on-loop-start', 'on-green']);
73
+
74
+ // ---------------------------------------------------------------------------
75
+ // parseFlags — parses + validates argv, returns typed flags object
76
+ // ---------------------------------------------------------------------------
77
+
78
+ /**
79
+ * Parse and validate CLI flags.
80
+ *
81
+ * @param {string[]} argv
82
+ * @returns {{
83
+ * maxStories: number,
84
+ * maxHours: number,
85
+ * inactivityTimeoutMs: number,
86
+ * draftMrPolicy: string,
87
+ * stallTimeoutSeconds: number,
88
+ * dryRun: boolean,
89
+ * apply: boolean,
90
+ * json: boolean,
91
+ * verbose: boolean,
92
+ * help: boolean,
93
+ * version: boolean,
94
+ * deconflictPaths: string,
95
+ * }}
96
+ */
97
+ export function parseFlags(argv) {
98
+ const { values } = parseArgs({ args: argv, options: FLAGS, allowPositionals: false });
99
+
100
+ // Mutex: --dry-run and --apply cannot both be explicitly set to true.
101
+ // Since --dry-run defaults to true, treat apply=true + the user explicitly
102
+ // also passing --dry-run as a mutex violation.
103
+ if (values['apply'] && values['dry-run'] && argv.includes('--dry-run')) {
104
+ throw new UserError('--dry-run and --apply are mutually exclusive; pick one.');
105
+ }
106
+
107
+ // Resolve safe default: if neither --apply nor explicit --dry-run, dry-run wins.
108
+ const apply = /** @type {boolean} */ (values['apply']);
109
+ // When apply is true and --dry-run was not explicitly passed, disable dry-run.
110
+ const dryRun = apply ? false : /** @type {boolean} */ (values['dry-run']);
111
+
112
+ // max-stories: int, clamp [1, 10]
113
+ const rawMaxStories = parseInt(/** @type {string} */ (values['max-stories']), 10);
114
+ if (isNaN(rawMaxStories)) {
115
+ throw new UserError(`--max-stories must be an integer, got: ${values['max-stories']}`);
116
+ }
117
+ const maxStories = Math.max(1, Math.min(10, rawMaxStories));
118
+
119
+ // max-hours: float, clamp [0.5, 24]
120
+ const rawMaxHours = parseFloat(/** @type {string} */ (values['max-hours']));
121
+ if (isNaN(rawMaxHours)) {
122
+ throw new UserError(`--max-hours must be a number, got: ${values['max-hours']}`);
123
+ }
124
+ const maxHours = Math.max(0.5, Math.min(24, rawMaxHours));
125
+
126
+ // inactivity-timeout: int seconds, clamp [60, 3600]
127
+ const rawInactivity = parseInt(/** @type {string} */ (values['inactivity-timeout']), 10);
128
+ if (isNaN(rawInactivity)) {
129
+ throw new UserError(`--inactivity-timeout must be an integer, got: ${values['inactivity-timeout']}`);
130
+ }
131
+ const inactivityTimeoutMs = Math.max(60, Math.min(3600, rawInactivity)) * 1000;
132
+
133
+ // draft-mr: validate against allowed set
134
+ const draftMrPolicy = /** @type {string} */ (values['draft-mr']);
135
+ if (!VALID_DRAFT_MR_POLICIES.has(draftMrPolicy)) {
136
+ throw new UserError(
137
+ `--draft-mr must be one of: off, on-loop-start, on-green. Got: "${draftMrPolicy}"`
138
+ );
139
+ }
140
+
141
+ // stall-seconds: int, clamp [60, 3600]
142
+ const rawStall = parseInt(/** @type {string} */ (values['stall-seconds']), 10);
143
+ if (isNaN(rawStall)) {
144
+ throw new UserError(`--stall-seconds must be an integer, got: ${values['stall-seconds']}`);
145
+ }
146
+ const stallTimeoutSeconds = Math.max(60, Math.min(3600, rawStall));
147
+
148
+ return {
149
+ maxStories,
150
+ maxHours,
151
+ inactivityTimeoutMs,
152
+ draftMrPolicy,
153
+ stallTimeoutSeconds,
154
+ dryRun,
155
+ apply,
156
+ json: /** @type {boolean} */ (values['json']),
157
+ verbose: /** @type {boolean} */ (values['verbose']),
158
+ help: /** @type {boolean} */ (values['help']),
159
+ version: /** @type {boolean} */ (values['version']),
160
+ deconflictPaths: /** @type {string} */ (values['deconflict-paths'] ?? ''),
161
+ };
162
+ }
163
+
164
+ // ---------------------------------------------------------------------------
165
+ // buildOrchestratorState — compose plan snapshot from flags + probe + issues
166
+ // ---------------------------------------------------------------------------
167
+
168
+ /**
169
+ * Build a serialisable orchestrator state / plan object.
170
+ *
171
+ * @param {{
172
+ * maxStories: number,
173
+ * maxHours: number,
174
+ * inactivityTimeoutMs: number,
175
+ * draftMrPolicy: string,
176
+ * stallTimeoutSeconds: number,
177
+ * dryRun: boolean,
178
+ * apply: boolean,
179
+ * json: boolean,
180
+ * verbose: boolean,
181
+ * }} flags
182
+ * @param {object|null} snapshot Resource-probe snapshot (null in dry-run without probe)
183
+ * @param {Array<{iid: number, title: string, blocks: number[], blockedBy: number[], labels: string[]}>} issues
184
+ * @param {string} [parentRunId] Unique run-id for this orchestrator session
185
+ * @returns {{
186
+ * concurrencyCap: number,
187
+ * totalIssues: number,
188
+ * readyIssues: number,
189
+ * executionPlan: Array<{iid: number, title: string}>,
190
+ * flags: object,
191
+ * issues: Array<{iid: number, title: string, blocks: number[], blockedBy: number[], labels: string[]}>,
192
+ * parentRunId: string,
193
+ * }}
194
+ */
195
+ export function buildOrchestratorState(flags, snapshot, issues, parentRunId = '') {
196
+ // If a snapshot is available and has a cap, use it; otherwise fall back to maxStories.
197
+ const snapshotCap = snapshot && typeof snapshot.cpuCores === 'number'
198
+ ? snapshot.cpuCores
199
+ : flags.maxStories;
200
+ const concurrencyCap = Math.min(flags.maxStories, snapshotCap);
201
+
202
+ const executionPlan = issues
203
+ .slice(0, concurrencyCap)
204
+ .map(({ iid, title }) => ({ iid, title }));
205
+
206
+ return {
207
+ concurrencyCap,
208
+ totalIssues: issues.length,
209
+ readyIssues: issues.length,
210
+ executionPlan,
211
+ issues,
212
+ parentRunId,
213
+ flags: {
214
+ maxStories: flags.maxStories,
215
+ maxHours: flags.maxHours,
216
+ inactivityTimeoutMs: flags.inactivityTimeoutMs,
217
+ draftMrPolicy: flags.draftMrPolicy,
218
+ stallTimeoutSeconds: flags.stallTimeoutSeconds,
219
+ dryRun: flags.dryRun,
220
+ apply: flags.apply,
221
+ },
222
+ };
223
+ }
224
+
225
+ // ---------------------------------------------------------------------------
226
+ // Session Config helpers
227
+ // ---------------------------------------------------------------------------
228
+
229
+ /**
230
+ * Load Session Config via `node scripts/parse-config.mjs` (same subprocess
231
+ * pattern used by scripts/autopilot.mjs). Returns null on failure — callers
232
+ * apply their own defaults.
233
+ *
234
+ * @returns {object|null}
235
+ */
236
+ function loadSessionConfig() {
237
+ try {
238
+ const scriptPath = path.resolve(
239
+ new URL('.', import.meta.url).pathname,
240
+ 'parse-config.mjs',
241
+ );
242
+ const result = spawnSync(
243
+ process.execPath,
244
+ [scriptPath],
245
+ { encoding: 'utf8', timeout: 10_000 },
246
+ );
247
+ if (result.status !== 0 || !result.stdout) return null;
248
+ return JSON.parse(result.stdout);
249
+ } catch {
250
+ return null;
251
+ }
252
+ }
253
+
254
+ // ---------------------------------------------------------------------------
255
+ // Apply-mode helpers
256
+ // ---------------------------------------------------------------------------
257
+
258
+ /**
259
+ * Extract issue relation refs (blocks / blocked_by) from a raw glab issue
260
+ * object. The glab issue list JSON does not embed these fields by default —
261
+ * they are left as [] for v1.
262
+ *
263
+ * @param {object} _issue Raw glab issue object
264
+ * @param {string} _field Relation field name ('blocks' | 'blocked_by')
265
+ * @returns {number[]}
266
+ */
267
+ // TODO Phase D.2 (#341): query relations via glab api (e.g. glab api
268
+ // projects/:id/issues/:iid/links) to populate blocks/blocked_by.
269
+ function extractRefs(_issue, _field) {
270
+ return [];
271
+ }
272
+
273
+ /**
274
+ * Fetch the ready-backlog from GitLab via `glab issue list`.
275
+ * Uses execFile (shell: false) per SEC-014 / cli-design rules.
276
+ *
277
+ * @param {Function} execFileFn Promisified execFile
278
+ * @returns {Promise<Array<{iid: number, title: string, blocks: number[], blockedBy: number[], labels: string[]}>>}
279
+ */
280
+ async function fetchReadyBacklog(execFileFn) {
281
+ const { stdout } = await execFileFn(
282
+ 'glab',
283
+ ['issue', 'list', '--label', 'status:ready', '--per-page', '50', '--output', 'json'],
284
+ { shell: false, timeout: 30_000 },
285
+ );
286
+ const issues = JSON.parse(stdout);
287
+ return issues.map((i) => ({
288
+ iid: i.iid ?? i.id,
289
+ title: i.title ?? '',
290
+ blocks: extractRefs(i, 'blocks'), // best-effort; default to []
291
+ blockedBy: extractRefs(i, 'blocked_by'), // best-effort; default to []
292
+ labels: i.labels?.map((l) => l.name ?? l) ?? [],
293
+ }));
294
+ }
295
+
296
+ /**
297
+ * Summarise a completed apply run into a canonical result envelope.
298
+ *
299
+ * @param {import('./lib/autopilot/multi-killswitch.mjs').LoopRegistration[]} allLoops
300
+ * @param {string} reason
301
+ * @param {number} startMs
302
+ * @param {{ kill: string, detail: string }|null} [killDetail]
303
+ * @returns {{ success: boolean, data: object }}
304
+ */
305
+ function finalize(allLoops, reason, startMs, killDetail = null) {
306
+ const terminalReasons = new Set([
307
+ 'first-kill-switch',
308
+ 'spiral',
309
+ 'cohort-abort',
310
+ 'spawn-error',
311
+ STALE_SUBAGENT_MIN,
312
+ ]);
313
+ return {
314
+ success: !terminalReasons.has(reason),
315
+ data: {
316
+ reason,
317
+ loopCount: allLoops.length,
318
+ completed: allLoops.filter((l) => l.status === 'complete').length,
319
+ failed: allLoops.filter((l) => l.status === 'failed').length,
320
+ elapsedMs: Date.now() - startMs,
321
+ killDetail: killDetail ?? null,
322
+ },
323
+ };
324
+ }
325
+
326
+ /** Sentinel import — resolved lazily in runApplyLoop. Kept at module scope to
327
+ * allow finalize() to reference STALE_SUBAGENT_MIN without a forward-ref issue. */
328
+ let STALE_SUBAGENT_MIN = 'stale-subagent-min';
329
+
330
+ /**
331
+ * Core apply-mode orchestration loop.
332
+ *
333
+ * Iteratively spawns up to N concurrent worktree-pipelines, polls completions,
334
+ * evaluates cross-loop kill-switches, and returns a canonical result envelope
335
+ * when work is exhausted or a stop condition fires.
336
+ *
337
+ * @param {{ issues: Array<object>, parentRunId: string, flags: object }} state
338
+ * @param {{ depGraph: object, wtPipeline: object, mkLib: object, probe: object }} libs
339
+ * @param {{ bgIsolation?: string, [key: string]: unknown }} [opts]
340
+ * @returns {Promise<{ success: boolean, data: object }>}
341
+ */
342
+ async function runApplyLoop(state, libs, opts) {
343
+ // bg-isolation routing: "none" → skip worktree creation and spawn sub-sessions
344
+ // in the main tree. "worktree" (default) → each story pipeline creates its
345
+ // own worktree via worktree-pipeline.mjs (existing path).
346
+ const bgIsolation = opts?.bgIsolation ?? 'worktree';
347
+ const { depGraph, wtPipeline, mkLib, probe } = libs;
348
+ const { flags } = state;
349
+
350
+ // Patch module-level sentinel with the actual export from the loaded lib.
351
+ STALE_SUBAGENT_MIN = mkLib.STALE_SUBAGENT_MIN ?? 'stale-subagent-min';
352
+
353
+ const startMs = Date.now();
354
+ const maxMs = flags.maxHours * 3600 * 1000;
355
+
356
+ // Early exit when there is nothing to process.
357
+ if (!state.issues || state.issues.length === 0) {
358
+ return finalize([], 'backlog-empty', startMs);
359
+ }
360
+
361
+ // Build graph and tracking state.
362
+ const graph = depGraph.buildGraph(state.issues);
363
+ /** @type {Map<string, { promise: Promise<object>, registration: object }>} */
364
+ const inFlight = new Map(); // loopId → { promise, registration }
365
+ /** @type {Set<number>} */
366
+ const completed = new Set();
367
+ /** @type {object[]} */
368
+ const allLoops = []; // LoopRegistration[]
369
+ let lastCompletionAt = startMs;
370
+
371
+ // TODO Phase D.2 (#341): implement real cross-loop dependency commit-waiting.
372
+ // Currently all issues are treated as independent (blocks/blockedBy are []
373
+ // for v1). When commit-based deps land, nextReady() will need to check
374
+ // whether the blocker's commit is present on the target branch before
375
+ // yielding the blocked issue.
376
+
377
+ while (true) {
378
+ // 1. Stop condition check.
379
+ const activeLoopRegs = Array.from(inFlight.values()).map((v) => v.registration);
380
+ const readyBacklog = depGraph.nextReady(graph, new Set(inFlight.keys().map((id) => {
381
+ const reg = inFlight.get(id)?.registration;
382
+ return reg?.issueIid;
383
+ }).filter((x) => x !== null && x !== undefined)), completed);
384
+
385
+ const orchState = {
386
+ activeLoops: activeLoopRegs,
387
+ readyBacklog,
388
+ lastCompletionAt,
389
+ };
390
+
391
+ const stopDecision = mkLib.shouldStopOrchestrator(orchState, {
392
+ inactivityTimeoutMs: flags.inactivityTimeoutMs,
393
+ });
394
+ if (stopDecision.stop) {
395
+ return finalize(allLoops, stopDecision.reason, startMs);
396
+ }
397
+
398
+ if (Date.now() - startMs > maxMs) {
399
+ return finalize(allLoops, 'max-hours', startMs);
400
+ }
401
+
402
+ // 2. Per-iteration resource probe + cohort kill-switch check.
403
+ let snapshot = null;
404
+ try {
405
+ snapshot = await probe.probe();
406
+ } catch {
407
+ // Resource probe failure is non-fatal — continue with maxStories cap.
408
+ }
409
+
410
+ const recommendedCap = snapshot ? mkLib.calculateConcurrencyCap(snapshot) : flags.maxStories;
411
+ const effectiveCap = Math.min(flags.maxStories, recommendedCap);
412
+
413
+ const crossKill = mkLib.evaluateMultiKillSwitches(allLoops, {
414
+ staleSubagentMinSeconds: flags.stallTimeoutSeconds,
415
+ });
416
+ if (crossKill !== null) {
417
+ return finalize(allLoops, crossKill.kill, startMs, crossKill);
418
+ }
419
+
420
+ // 3. Spawn loops up to cap.
421
+ const spawnableBacklog = [...readyBacklog];
422
+ while (inFlight.size < effectiveCap && spawnableBacklog.length > 0) {
423
+ const issue = spawnableBacklog.shift();
424
+ const loopId = `loop-${issue.iid}-${Date.now()}`;
425
+ /** @type {object} */
426
+ const registration = {
427
+ loopId,
428
+ pid: process.pid, // best-effort; loops are in-process for v1
429
+ parentRunId: state.parentRunId,
430
+ issueIid: issue.iid,
431
+ status: 'running',
432
+ killSwitch: null,
433
+ spiralRecoveryCount: 0,
434
+ startedAt: Date.now(),
435
+ lastActivityAt: Date.now(),
436
+ };
437
+ allLoops.push(registration);
438
+
439
+ // bg-isolation: "none" → main-tree spawn (no worktree, faster for
440
+ // monorepos with heavy build state but requires file-scope discipline).
441
+ // bg-isolation: "worktree" (default) → per-story worktree isolation.
442
+ // worktree-pipeline.mjs respects the bgIsolation option and skips
443
+ // EnterWorktree when set to "none".
444
+ const promise = wtPipeline.runStoryPipeline({
445
+ issueIid: issue.iid,
446
+ issueTitle: issue.title,
447
+ branchName: `issue-${issue.iid}`,
448
+ parentRunId: state.parentRunId,
449
+ repoRoot: process.cwd(),
450
+ draftMrPolicy: flags.draftMrPolicy,
451
+ bgIsolation,
452
+ // TODO Phase D.2 (#341): on-green MR-draft trigger — loop result does not
453
+ // yet signal "first green test"; wire once runStoryPipeline
454
+ // propagates a firstGreenAt timestamp in StoryResult.
455
+ }).then((result) => {
456
+ registration.status = result.killSwitch ? 'failed' : 'complete';
457
+ registration.killSwitch = result.killSwitch ?? null;
458
+ completed.add(issue.iid);
459
+ lastCompletionAt = Date.now();
460
+ return result;
461
+ }).catch((err) => {
462
+ registration.status = 'failed';
463
+ registration.killSwitch = 'spawn-error';
464
+ registration.killSwitchDetail = err.message;
465
+ completed.add(issue.iid);
466
+ lastCompletionAt = Date.now();
467
+ return { error: err.message };
468
+ });
469
+
470
+ inFlight.set(loopId, { promise, registration });
471
+ }
472
+
473
+ // 4. Cohort abort decision for newly-failed loops.
474
+ for (const [, { registration }] of inFlight.entries()) {
475
+ if (registration.status === 'failed' && registration.killSwitch) {
476
+ const cohortDecision = mkLib.decideCohortAction(allLoops, registration.loopId);
477
+ if (cohortDecision.action === 'cohort-abort') {
478
+ // TODO Phase D.2 (#341): send real SIGTERM to in-process promises.
479
+ // In v1 loops are in-process Promises; enforcement is logged only.
480
+ // Full SIGTERM requires spawning each pipeline in a child process
481
+ // with a dedicated pid, tracked on LoopRegistration.pid.
482
+ process.stderr.write(
483
+ `[autopilot-multi] cohort-abort triggered by loop ${registration.loopId}: ${cohortDecision.reason}\n`,
484
+ );
485
+ return finalize(allLoops, 'cohort-abort', startMs, { kill: 'cohort-abort', detail: cohortDecision.reason });
486
+ }
487
+ }
488
+ }
489
+
490
+ // 5. Wait for next completion (Promise.race) OR settle after 5 s tick.
491
+ if (inFlight.size > 0) {
492
+ await Promise.race([
493
+ Promise.race(Array.from(inFlight.values()).map((v) => v.promise.then(() => null))),
494
+ new Promise((r) => setTimeout(r, 5000)),
495
+ ]);
496
+ // Sweep completed / failed entries.
497
+ for (const [id, { registration }] of inFlight.entries()) {
498
+ if (registration.status === 'complete' || registration.status === 'failed') {
499
+ inFlight.delete(id);
500
+ }
501
+ }
502
+ } else if (readyBacklog.length === 0) {
503
+ // No active, no ready — backlog-empty stop condition fires on the next tick.
504
+ await new Promise((r) => setTimeout(r, 1000));
505
+ }
506
+ }
507
+ }
508
+
509
+ // ---------------------------------------------------------------------------
510
+ // Internal helpers
511
+ // ---------------------------------------------------------------------------
512
+
513
+ /** Typed user-error (exit 1). */
514
+ class UserError extends Error {
515
+ constructor(message) {
516
+ super(message);
517
+ this.name = 'UserError';
518
+ }
519
+ }
520
+
521
+ /**
522
+ * Write a canonical JSON envelope to stdout.
523
+ *
524
+ * @param {boolean} success
525
+ * @param {object|null} data
526
+ * @param {{code: string, message: string}|null} error
527
+ */
528
+ function writeJsonEnvelope(success, data, error) {
529
+ const envelope = success
530
+ ? { success: true, data }
531
+ : { success: false, error };
532
+ process.stdout.write(JSON.stringify(envelope) + '\n');
533
+ }
534
+
535
+ /**
536
+ * Emit a diagnostic line to stderr (only when verbose or always for warnings).
537
+ *
538
+ * @param {string} message
539
+ * @param {boolean} [verbose]
540
+ * @param {boolean} [force] If true, always emit regardless of verbose flag.
541
+ */
542
+ function diag(message, verbose, force = false) {
543
+ if (verbose || force) {
544
+ process.stderr.write(`[autopilot-multi] ${message}\n`);
545
+ }
546
+ }
547
+
548
+ // ---------------------------------------------------------------------------
549
+ // main — primary entrypoint
550
+ // ---------------------------------------------------------------------------
551
+
552
+ /**
553
+ * CLI main function. Does NOT execute on import — see CLI guard below.
554
+ *
555
+ * @param {string[]} argv
556
+ * @param {object} [opts] Dependency-injection seam for tests.
557
+ * @param {Function} [opts.exit] Override process.exit (for testing).
558
+ * @returns {Promise<void>}
559
+ */
560
+ export async function main(argv = process.argv.slice(2), opts = {}) {
561
+ const exitFn = opts.exit ?? process.exit;
562
+
563
+ // Unique run-id for this orchestrator session — passed to each child loop.
564
+ const parentRunId = `multi-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
565
+
566
+ // -------------------------------------------------------------------------
567
+ // 1. Parse flags
568
+ // -------------------------------------------------------------------------
569
+ let flags;
570
+ try {
571
+ flags = parseFlags(argv);
572
+ } catch (err) {
573
+ if (err instanceof UserError) {
574
+ process.stderr.write(`autopilot-multi: ${err.message}\n`);
575
+ exitFn(1);
576
+ return;
577
+ }
578
+ process.stderr.write(`autopilot-multi: flag parse error: ${err.message}\n`);
579
+ exitFn(1);
580
+ return;
581
+ }
582
+
583
+ // -------------------------------------------------------------------------
584
+ // 2. --help
585
+ // -------------------------------------------------------------------------
586
+ if (flags.help) {
587
+ process.stdout.write(HELP_TEXT);
588
+ exitFn(0);
589
+ return;
590
+ }
591
+
592
+ // -------------------------------------------------------------------------
593
+ // 3. --version
594
+ // -------------------------------------------------------------------------
595
+ if (flags.version) {
596
+ try {
597
+ const pkgPath = path.join(import.meta.dirname, '..', 'package.json');
598
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
599
+ process.stdout.write(`${pkg.version}\n`);
600
+ } catch {
601
+ process.stderr.write('autopilot-multi: could not read package.json version\n');
602
+ exitFn(2);
603
+ return;
604
+ }
605
+ exitFn(0);
606
+ return;
607
+ }
608
+
609
+ // -------------------------------------------------------------------------
610
+ // 4. Read Session Config and enforce bg-isolation policy (#431)
611
+ //
612
+ // bg-isolation: "none" — skip worktree creation; spawn sub-sessions in the
613
+ // main tree. Requires file-scope discipline: with >1 concurrent story,
614
+ // agents WILL edit the same working copy simultaneously. A hard-error fires
615
+ // unless --deconflict-paths=<glob> is provided to signal that the operator
616
+ // has planned per-story file ownership.
617
+ //
618
+ // bg-isolation: "worktree" (default) — each story gets its own git worktree;
619
+ // safe for parallel writes but costs disk space and EnterWorktree latency.
620
+ //
621
+ // Caution: CC 2.1.133 silently flipped worktree.baseRef default from "head"
622
+ // to "origin/<default>", breaking users relying on unpushed commits. Apply
623
+ // the same operator-awareness here: any future CC change to worktree defaults
624
+ // may silently affect this path. See #431 and SKILL.md § bg-isolation.
625
+ // -------------------------------------------------------------------------
626
+ const sessionConfig = loadSessionConfig();
627
+ const bgIsolation = /** @type {string} */ (
628
+ sessionConfig?.autopilot?.['bg-isolation'] ?? 'worktree'
629
+ );
630
+
631
+ if (bgIsolation === 'none' && flags.maxStories > 1 && !flags.deconflictPaths) {
632
+ // Hard-error per PSA-001/002/003 — see .claude/rules/parallel-sessions.md
633
+ const msg =
634
+ `autopilot-multi: bg-isolation: "none" with --max-stories=${flags.maxStories} ` +
635
+ `requires explicit file-scope deconfliction. ` +
636
+ `Set max-stories=1 OR provide --deconflict-paths=<glob> to confirm you have ` +
637
+ `planned per-story file ownership. ` +
638
+ `See .claude/rules/parallel-sessions.md PSA-001/002/003.`;
639
+ process.stderr.write(`${msg}\n`);
640
+ if (flags.json) {
641
+ writeJsonEnvelope(false, null, { code: 'BG_ISOLATION_CONFLICT', message: msg });
642
+ }
643
+ exitFn(1);
644
+ return;
645
+ }
646
+
647
+ diag(
648
+ `bg-isolation=${bgIsolation}` +
649
+ (bgIsolation === 'none' ? ' (main-tree mode; worktree creation skipped)' : ''),
650
+ flags.verbose,
651
+ );
652
+
653
+ // -------------------------------------------------------------------------
654
+ // 5. Dynamic-import sibling libs (graceful degradation)
655
+ // -------------------------------------------------------------------------
656
+ let buildGraph, nextReady, calculateConcurrencyCap, probe;
657
+ let depGraphMod, mkLibMod, wtPipelineMod, resourceProbeMod;
658
+
659
+ try {
660
+ depGraphMod = await import('./lib/autopilot/dep-graph.mjs');
661
+ mkLibMod = await import('./lib/autopilot/multi-killswitch.mjs');
662
+ wtPipelineMod = await import('./lib/autopilot/worktree-pipeline.mjs');
663
+ resourceProbeMod = await import('./lib/resource-probe.mjs');
664
+
665
+ buildGraph = depGraphMod.buildGraph;
666
+ nextReady = depGraphMod.nextReady;
667
+ calculateConcurrencyCap = mkLibMod.calculateConcurrencyCap;
668
+ probe = resourceProbeMod.probe;
669
+ } catch {
670
+ const msg = 'multi-story libs not yet shipped; this is the v3.6 CLI scaffold';
671
+ process.stderr.write(`autopilot-multi: ${msg}\n`);
672
+ if (flags.json) {
673
+ writeJsonEnvelope(false, null, { code: 'LIBS_NOT_AVAILABLE', message: msg });
674
+ }
675
+ exitFn(2);
676
+ return;
677
+ }
678
+
679
+ // -------------------------------------------------------------------------
680
+ // 6. Resource probe + concurrency cap advisory
681
+ // -------------------------------------------------------------------------
682
+ let snapshot = null;
683
+ try {
684
+ snapshot = await probe();
685
+ } catch (err) {
686
+ process.stderr.write(
687
+ `autopilot-multi: resource-probe failed: ${err.message}; continuing without snapshot\n`
688
+ );
689
+ }
690
+
691
+ const recommendedCap = snapshot ? calculateConcurrencyCap(snapshot) : flags.maxStories;
692
+
693
+ if (flags.maxStories > recommendedCap && !flags.apply) {
694
+ process.stderr.write(
695
+ `autopilot-multi: WARN requested N=${flags.maxStories} but resource-probe recommends` +
696
+ ` N=${recommendedCap}; pass --apply to override\n`
697
+ );
698
+ }
699
+
700
+ diag(
701
+ `resource-probe snapshot received; recommendedCap=${recommendedCap}`,
702
+ flags.verbose
703
+ );
704
+
705
+ // -------------------------------------------------------------------------
706
+ // 7. Build issue backlog
707
+ // -------------------------------------------------------------------------
708
+ let issues;
709
+
710
+ if (flags.dryRun) {
711
+ // Dry-run: synthesize a stub backlog so plan output is always available.
712
+ issues = [{ iid: 999, title: 'dry-run-stub', blocks: [], blockedBy: [], labels: ['status:ready'] }];
713
+ diag('dry-run mode — using synthetic issue stub instead of calling glab', flags.verbose, true);
714
+ } else {
715
+ // Apply path: fetch real issues via glab (execFile, shell: false — SEC-014).
716
+ try {
717
+ issues = await fetchReadyBacklog(execFile);
718
+ } catch (err) {
719
+ const msg = `glab issue list failed: ${err.message}`;
720
+ process.stderr.write(`autopilot-multi: ${msg}\n`);
721
+ if (flags.json) {
722
+ writeJsonEnvelope(false, null, { code: 'GLAB_FAILED', message: msg });
723
+ }
724
+ exitFn(2);
725
+ return;
726
+ }
727
+ }
728
+
729
+ // -------------------------------------------------------------------------
730
+ // 8. Build dep-graph + initial schedulable set
731
+ // -------------------------------------------------------------------------
732
+ const graph = buildGraph(issues);
733
+ const initialSet = nextReady(graph, new Set(), new Set());
734
+
735
+ diag(
736
+ `dep-graph built; total=${issues.length} ready=${initialSet.length ?? initialSet.size ?? 0}`,
737
+ flags.verbose
738
+ );
739
+
740
+ // -------------------------------------------------------------------------
741
+ // 9. Dry-run path (default): emit orchestration plan
742
+ // -------------------------------------------------------------------------
743
+ if (flags.dryRun) {
744
+ const plan = buildOrchestratorState(flags, snapshot, issues, parentRunId);
745
+
746
+ if (flags.json) {
747
+ writeJsonEnvelope(true, { plan });
748
+ } else {
749
+ process.stdout.write('autopilot-multi — dry-run orchestration plan\n');
750
+ process.stdout.write(` concurrencyCap : ${plan.concurrencyCap}\n`);
751
+ process.stdout.write(` totalIssues : ${plan.totalIssues}\n`);
752
+ process.stdout.write(` readyIssues : ${plan.readyIssues}\n`);
753
+ process.stdout.write(` executionPlan :\n`);
754
+ for (const item of plan.executionPlan) {
755
+ process.stdout.write(` #${item.iid} ${item.title}\n`);
756
+ }
757
+ process.stdout.write('\nPass --apply to execute.\n');
758
+ }
759
+
760
+ exitFn(0);
761
+ return;
762
+ }
763
+
764
+ // -------------------------------------------------------------------------
765
+ // 10. Apply path: run the multi-story orchestration loop
766
+ // -------------------------------------------------------------------------
767
+ const state = buildOrchestratorState(flags, snapshot, issues, parentRunId);
768
+ const libs = {
769
+ depGraph: depGraphMod,
770
+ wtPipeline: wtPipelineMod,
771
+ mkLib: mkLibMod,
772
+ probe: resourceProbeMod,
773
+ };
774
+ // Pass bgIsolation into opts so runApplyLoop can route the dispatch path.
775
+ // bg-isolation: "none" → spawn sub-sessions in the main tree (no worktree creation).
776
+ // bg-isolation: "worktree" (default) → each story pipeline creates its own worktree.
777
+ const runOpts = { ...opts, bgIsolation };
778
+
779
+ const result = await runApplyLoop(state, libs, runOpts);
780
+
781
+ if (flags.json) {
782
+ console.log(JSON.stringify(result));
783
+ } else {
784
+ console.log(
785
+ `Multi-story apply complete: ${result.data.reason}` +
786
+ ` — ${result.data.completed}/${result.data.loopCount} loops succeeded`,
787
+ );
788
+ }
789
+
790
+ exitFn(result.success ? 0 : 2);
791
+ }
792
+
793
+ // ---------------------------------------------------------------------------
794
+ // CLI guard — prevents top-level execution on import (deep-2 #368)
795
+ // ---------------------------------------------------------------------------
796
+
797
+ if (import.meta.url === `file://${process.argv[1]}`) {
798
+ main(process.argv.slice(2)).catch((err) => {
799
+ console.error('autopilot-multi failed:', err.message);
800
+ process.exit(2);
801
+ });
802
+ }