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,520 @@
1
+ // scripts/lib/autopilot/mr-draft.mjs
2
+ //
3
+ // Draft MR/PR creation module for autopilot --multi-story per OPEN-6 PRD.
4
+ // Implements the security pattern from ADR-364 C5: execFile (NOT shell) +
5
+ // binary allowlist + shell-metacharacter rejection on title/description.
6
+ //
7
+ // Policy values: 'off' (default), 'on-loop-start', 'on-green' (deferred).
8
+ //
9
+ // References:
10
+ // - "Autopilot Phase D — Per-Story Worktree Pipelines" (#341; archived in the private Meta-Vault) (OPEN-6 [DECIDED])
11
+ // - docs/adr/2026-05-10-364-remote-agent-substrate.md (C5 security finding)
12
+
13
+ import { execFile as execFileCb } from 'node:child_process';
14
+ import { promisify } from 'node:util';
15
+
16
+ const realExecFile = promisify(execFileCb);
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Binary allowlist (ADR-364 C5 + SEC-014)
20
+ // ---------------------------------------------------------------------------
21
+ // Bare binary names only — resolved at runtime via PATH by Node's execve.
22
+ // Reject any string containing '/' or '..' to prevent path traversal.
23
+ const MR_ALLOWLISTED_BINS = Object.freeze({
24
+ glab: 'glab', // GitLab CLI
25
+ gh: 'gh', // GitHub CLI
26
+ });
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // CLI-argument-boundary rejection regex (ADR-364 C5 / OPEN-6 / SEC-PD-MED-1 W4 audit)
30
+ // ---------------------------------------------------------------------------
31
+ // Reject only characters that corrupt CLI arg semantics when passed to execFile
32
+ // with shell: false. The shell metacharacter check (formerly /[;&|`$(){}[\]<>!]/)
33
+ // was over-broad — `shell: false` already prevents shell interpretation, so the
34
+ // regex only served to suppress legitimate GitLab issue titles containing `()`
35
+ // or `[]` (e.g. "Fix nav bug (closes #123)"). Narrowed to newline + null byte
36
+ // per W4 Q6 security-reviewer finding SEC-PD-MED-1 (confidence 0.95).
37
+ const ARG_BOUNDARY_DANGEROUS = /[\n\r\0]/;
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // MrDraftError
41
+ // ---------------------------------------------------------------------------
42
+
43
+ /**
44
+ * Typed error class for MR-draft operations.
45
+ * Codes: 'COLLISION' | 'VALIDATION' | 'EXEC_FAILURE' | 'POLICY_OFF' | 'POLICY_DEFER' | 'UNSUPPORTED_VCS'
46
+ */
47
+ export class MrDraftError extends Error {
48
+ constructor(message, code) {
49
+ super(message);
50
+ this.name = 'MrDraftError';
51
+ this.code = code;
52
+ }
53
+ }
54
+
55
+ // ---------------------------------------------------------------------------
56
+ // Input validation
57
+ // ---------------------------------------------------------------------------
58
+
59
+ /**
60
+ * Validate title and description for shell-metacharacter safety.
61
+ * Throws MrDraftError(VALIDATION) if rejected.
62
+ *
63
+ * Rules:
64
+ * - title: non-empty string, ≤200 chars, no newlines, no shell-dangerous chars
65
+ * - description: string, ≤10000 chars, no shell-dangerous chars
66
+ *
67
+ * Note: this function is designed for validating user-supplied input fields
68
+ * (e.g. raw issueTitle from the issue tracker). The assembled MR body produced
69
+ * by buildMrBody() intentionally contains template-controlled characters such
70
+ * as `()` and `[]` which come from trusted code, not user input. Call this
71
+ * function with the raw user-supplied strings before assembling the body.
72
+ *
73
+ * @param {string} title
74
+ * @param {string} description
75
+ */
76
+ export function validateMrInputs(title, description) {
77
+ if (typeof title !== 'string' || title.length === 0) {
78
+ throw new MrDraftError('MR title must be a non-empty string', 'VALIDATION');
79
+ }
80
+ if (title.length > 200) {
81
+ throw new MrDraftError(`MR title exceeds 200 chars (got ${title.length})`, 'VALIDATION');
82
+ }
83
+ if (ARG_BOUNDARY_DANGEROUS.test(title)) {
84
+ throw new MrDraftError(
85
+ 'MR title must not contain newline or null-byte characters',
86
+ 'VALIDATION',
87
+ );
88
+ }
89
+
90
+ if (typeof description !== 'string') {
91
+ throw new MrDraftError('MR description must be a string', 'VALIDATION');
92
+ }
93
+ if (description.length > 10_000) {
94
+ throw new MrDraftError(
95
+ `MR description exceeds 10000 chars (got ${description.length})`,
96
+ 'VALIDATION',
97
+ );
98
+ }
99
+ if (/\0/.test(description)) {
100
+ throw new MrDraftError('MR description must not contain null bytes', 'VALIDATION');
101
+ }
102
+ }
103
+
104
+ // ---------------------------------------------------------------------------
105
+ // Check for an existing open MR/PR
106
+ // ---------------------------------------------------------------------------
107
+
108
+ /**
109
+ * Check if an MR/PR already exists for the source branch.
110
+ *
111
+ * @param {object} opts
112
+ * @param {'glab'|'gh'} opts.vcs
113
+ * @param {string} opts.branchName
114
+ * @param {Function} [opts.execFile] - defaults to promisified execFile from node:child_process
115
+ * @returns {Promise<{hasMR: boolean, mrIid: number|null, mrUrl: string|null}>}
116
+ */
117
+ export async function checkExistingMR(opts) {
118
+ const { vcs, branchName } = opts;
119
+ const execFile = typeof opts.execFile === 'function' ? opts.execFile : realExecFile;
120
+
121
+ if (vcs === 'glab') {
122
+ const args = [
123
+ 'mr',
124
+ 'list',
125
+ '--source-branch',
126
+ branchName,
127
+ '--state',
128
+ 'opened',
129
+ '--output',
130
+ 'json',
131
+ ];
132
+ const { stdout } = await execFile('glab', args, { shell: false, timeout: 5_000 });
133
+ let mrs;
134
+ try {
135
+ mrs = JSON.parse(stdout);
136
+ } catch {
137
+ throw new MrDraftError(
138
+ `glab output could not be parsed as JSON (stdout: ${stdout.slice(0, 120)})`,
139
+ 'EXEC_FAILURE',
140
+ );
141
+ }
142
+ const existing = mrs[0];
143
+ return {
144
+ hasMR: !!existing,
145
+ mrIid: existing?.iid ?? null,
146
+ mrUrl: existing?.web_url ?? null,
147
+ };
148
+ }
149
+
150
+ if (vcs === 'gh') {
151
+ const args = ['pr', 'list', '--head', branchName, '--state', 'open', '--json', 'number,url'];
152
+ const { stdout } = await execFile('gh', args, { shell: false, timeout: 5_000 });
153
+ let prs;
154
+ try {
155
+ prs = JSON.parse(stdout);
156
+ } catch {
157
+ throw new MrDraftError(
158
+ `gh output could not be parsed as JSON (stdout: ${stdout.slice(0, 120)})`,
159
+ 'EXEC_FAILURE',
160
+ );
161
+ }
162
+ const existing = prs[0];
163
+ return {
164
+ hasMR: !!existing,
165
+ mrIid: existing?.number ?? null,
166
+ mrUrl: existing?.url ?? null,
167
+ };
168
+ }
169
+
170
+ throw new MrDraftError(`Unsupported VCS for checkExistingMR: '${vcs}'`, 'UNSUPPORTED_VCS');
171
+ }
172
+
173
+ // ---------------------------------------------------------------------------
174
+ // Evidence block (issue #669 — downstream-human-review legibility)
175
+ // ---------------------------------------------------------------------------
176
+ // arXiv 2604.16754: reviewing an agent PR takes +441% longer because the
177
+ // reasoning is discarded at diff-time. Attaching a structured evidence block —
178
+ // decision-trace, fresh gate exit-codes, changed-files, carryover — makes the
179
+ // agent's work legible so a human reviews faster.
180
+ //
181
+ // Default-ON; opt-OUT via the SO_MR_EVIDENCE env-var (mirrors the
182
+ // SO_VAULT_DIR / SO_BASELINE_PATH host-local env-override idiom). When
183
+ // SO_MR_EVIDENCE === 'off' the block is omitted entirely.
184
+
185
+ /**
186
+ * Render a single markdown line, falling back to a literal "n/a" when the
187
+ * value is missing/blank. Keeps the block markdown-safe and graceful.
188
+ * @param {unknown} value
189
+ * @returns {string}
190
+ */
191
+ function evidenceValueOr(value) {
192
+ if (value === null || value === undefined) return 'n/a';
193
+ const s = String(value).trim();
194
+ return s.length === 0 ? 'n/a' : s;
195
+ }
196
+
197
+ /**
198
+ * Render the quality-gate sub-section: one row per gate with its exit code and
199
+ * (optional) count summary. A missing gate renders as "n/a".
200
+ * @param {object} [gates] - { test?, typecheck?, lint? } each { exitCode?, summary? }
201
+ * @returns {string[]}
202
+ */
203
+ function renderGateRows(gates) {
204
+ const g = gates && typeof gates === 'object' ? gates : {};
205
+ const row = (label, gate) => {
206
+ if (!gate || typeof gate !== 'object') return `| ${label} | n/a | n/a |`;
207
+ const exit =
208
+ gate.exitCode === null || gate.exitCode === undefined
209
+ ? 'n/a'
210
+ : String(gate.exitCode);
211
+ const summary = evidenceValueOr(gate.summary);
212
+ return `| ${label} | ${exit} | ${summary} |`;
213
+ };
214
+ return [
215
+ '| Gate | Exit code | Summary |',
216
+ '| --- | --- | --- |',
217
+ row('test', g.test),
218
+ row('typecheck', g.typecheck),
219
+ row('lint', g.lint),
220
+ ];
221
+ }
222
+
223
+ /**
224
+ * Build the structured `## Evidence` block (collapsible <details>) from the
225
+ * OPTIONAL evidence fields on the draft context. Every sub-section degrades to
226
+ * "n/a" when its source field is absent — so existing callers
227
+ * (worktree-pipeline.mjs, skill-evolution/mr-opener.mjs) that pass none of
228
+ * these fields keep working and simply render an all-"n/a" block.
229
+ *
230
+ * @param {object} ctx
231
+ * @param {Array<{wave?: string|number, summary?: string}>|string} [ctx.waveSummary]
232
+ * Per-wave decision trace. Array of {wave, summary} rows, or a pre-rendered string.
233
+ * @param {{test?: object, typecheck?: object, lint?: object}} [ctx.gateResults]
234
+ * Quality-gate outcomes; each gate is {exitCode, summary}.
235
+ * @param {string[]|string} [ctx.changedFiles]
236
+ * Changed-files list (array of paths or a pre-rendered string).
237
+ * @param {Array<{ref?: string, note?: string}>|string} [ctx.carryover]
238
+ * Carryover items (array of {ref, note} or a pre-rendered string).
239
+ * @returns {string[]} markdown lines (empty array when no block should render)
240
+ */
241
+ export function buildEvidenceBlock(ctx = {}) {
242
+ const { waveSummary, gateResults, changedFiles, carryover } = ctx;
243
+
244
+ // --- Decision-trace / per-wave summary ---
245
+ const waveLines = [];
246
+ if (typeof waveSummary === 'string' && waveSummary.trim().length > 0) {
247
+ waveLines.push(waveSummary.trim());
248
+ } else if (Array.isArray(waveSummary) && waveSummary.length > 0) {
249
+ for (const w of waveSummary) {
250
+ const label = evidenceValueOr(w?.wave);
251
+ const summary = evidenceValueOr(w?.summary);
252
+ waveLines.push(`- **${label}:** ${summary}`);
253
+ }
254
+ } else {
255
+ waveLines.push('n/a');
256
+ }
257
+
258
+ // --- Changed-files summary ---
259
+ const fileLines = [];
260
+ if (typeof changedFiles === 'string' && changedFiles.trim().length > 0) {
261
+ fileLines.push(changedFiles.trim());
262
+ } else if (Array.isArray(changedFiles) && changedFiles.length > 0) {
263
+ fileLines.push(`${changedFiles.length} file(s) changed:`);
264
+ for (const f of changedFiles) fileLines.push(`- \`${evidenceValueOr(f)}\``);
265
+ } else {
266
+ fileLines.push('n/a');
267
+ }
268
+
269
+ // --- Carryover ---
270
+ const carryLines = [];
271
+ if (typeof carryover === 'string' && carryover.trim().length > 0) {
272
+ carryLines.push(carryover.trim());
273
+ } else if (Array.isArray(carryover) && carryover.length > 0) {
274
+ for (const c of carryover) {
275
+ const ref = evidenceValueOr(c?.ref);
276
+ const note = evidenceValueOr(c?.note);
277
+ carryLines.push(`- ${ref} — ${note}`);
278
+ }
279
+ } else {
280
+ carryLines.push('n/a');
281
+ }
282
+
283
+ return [
284
+ '## Evidence',
285
+ '<details><summary>Decision-trace + verification evidence (for downstream human review)</summary>',
286
+ '',
287
+ '### Decision trace (per wave)',
288
+ ...waveLines,
289
+ '',
290
+ '### Quality gates',
291
+ ...renderGateRows(gateResults),
292
+ '',
293
+ '### Changed files',
294
+ ...fileLines,
295
+ '',
296
+ '### Carryover',
297
+ ...carryLines,
298
+ '',
299
+ '</details>',
300
+ ];
301
+ }
302
+
303
+ // ---------------------------------------------------------------------------
304
+ // Build MR body
305
+ // ---------------------------------------------------------------------------
306
+
307
+ /**
308
+ * Build the MR title and description from issue + autopilot context.
309
+ * Title is trimmed to ≤200 chars with '…' suffix if truncated.
310
+ * Description is capped at 10000 chars.
311
+ *
312
+ * An additive `## Evidence` block (decision-trace, gate exit-codes,
313
+ * changed-files, carryover) is appended by default for downstream-human-review
314
+ * legibility (issue #669). Opt out by setting the SO_MR_EVIDENCE env-var to
315
+ * 'off'. The evidence fields on `ctx` are all OPTIONAL — absent fields render
316
+ * as "n/a", so existing callers that pass none of them keep working.
317
+ *
318
+ * @param {object} ctx
319
+ * @param {string} ctx.issueTitle
320
+ * @param {number} ctx.issueIid
321
+ * @param {string} ctx.parentRunId
322
+ * @param {string} ctx.worktreePath
323
+ * @param {Array|string} [ctx.waveSummary] - optional per-wave decision trace
324
+ * @param {object} [ctx.gateResults] - optional { test, typecheck, lint } gate outcomes
325
+ * @param {string[]|string} [ctx.changedFiles] - optional changed-files summary
326
+ * @param {Array|string} [ctx.carryover] - optional carryover items
327
+ * @returns {{title: string, description: string}}
328
+ */
329
+ export function buildMrBody(ctx) {
330
+ const { issueTitle, issueIid, parentRunId, worktreePath } = ctx;
331
+
332
+ const rawTitle = `[WIP] ${issueTitle} (Autopilot Loop #${parentRunId})`;
333
+ const title =
334
+ rawTitle.length > 200 ? rawTitle.slice(0, 199) + '…' : rawTitle;
335
+
336
+ const lines = [
337
+ '## Autopilot Draft',
338
+ '',
339
+ `**Issue:** #${issueIid}`,
340
+ `**Loop:** ${parentRunId}`,
341
+ `**Worktree:** ${worktreePath}`,
342
+ '',
343
+ '### Tests (TODO)',
344
+ '- [ ] Unit tests passing',
345
+ '- [ ] Integration tests passing',
346
+ '- [ ] CI pipeline green',
347
+ '',
348
+ '### Code Review',
349
+ '- [ ] Architecture review',
350
+ '- [ ] Security review',
351
+ ];
352
+
353
+ // Evidence block — default ON, opt OUT via SO_MR_EVIDENCE=off (issue #669).
354
+ if (process.env.SO_MR_EVIDENCE !== 'off') {
355
+ lines.push('', ...buildEvidenceBlock(ctx));
356
+ }
357
+
358
+ lines.push(
359
+ '',
360
+ '---',
361
+ `*Generated by session-orchestrator autopilot on ${new Date().toISOString()}*`,
362
+ );
363
+
364
+ const description = lines.join('\n');
365
+
366
+ // Cap description at 10000 chars (issue titles fit easily; guard for adversarial input)
367
+ const cappedDescription =
368
+ description.length > 10_000 ? description.slice(0, 10_000) : description;
369
+
370
+ return { title, description: cappedDescription };
371
+ }
372
+
373
+ // ---------------------------------------------------------------------------
374
+ // maybeCreateDraftMR — primary entry point
375
+ // ---------------------------------------------------------------------------
376
+
377
+ /**
378
+ * Create a draft MR/PR per the policy.
379
+ * Returns immediately if policy is 'off' or 'on-green' (the latter signals
380
+ * the caller to defer; caller is responsible for re-invoking with a different
381
+ * policy or after first green test).
382
+ *
383
+ * @param {object} loop
384
+ * @param {'gitlab'|'github'} loop.vcs
385
+ * @param {number} loop.issueIid
386
+ * @param {string} loop.issueTitle
387
+ * @param {string} loop.branchName
388
+ * @param {string} loop.parentRunId
389
+ * @param {string} loop.worktreePath
390
+ * @param {'off'|'on-loop-start'|'on-green'} loop.draftMrPolicy
391
+ * @param {object} [opts]
392
+ * @param {Function} [opts.execFile]
393
+ * @param {(level: string, msg: string) => void} [opts.log]
394
+ * @returns {Promise<{created: boolean, deferred?: boolean, existing?: boolean, mrUrl?: string|null, error?: string}>}
395
+ */
396
+ export async function maybeCreateDraftMR(loop, opts = {}) {
397
+ const log =
398
+ typeof opts.log === 'function'
399
+ ? opts.log
400
+ : (_level, _msg) => {}; // no-op default
401
+ const execFile = typeof opts.execFile === 'function' ? opts.execFile : realExecFile;
402
+
403
+ const { draftMrPolicy, vcs, issueIid, issueTitle, branchName, parentRunId, worktreePath } = loop;
404
+
405
+ // --- Policy: off ---
406
+ if (draftMrPolicy === 'off') {
407
+ log('info', 'mr-draft: policy=off, skipping MR creation');
408
+ return { created: false };
409
+ }
410
+
411
+ // --- Policy: on-green (deferred) ---
412
+ if (draftMrPolicy === 'on-green') {
413
+ log('info', 'mr-draft: policy=on-green, deferring MR creation until first green test');
414
+ return { created: false, deferred: true };
415
+ }
416
+
417
+ // --- Policy: on-loop-start ---
418
+ if (draftMrPolicy === 'on-loop-start') {
419
+ // Map loop.vcs ('gitlab'|'github') to CLI binary ('glab'|'gh')
420
+ let vcsBin;
421
+ if (vcs === 'gitlab') {
422
+ vcsBin = MR_ALLOWLISTED_BINS.glab;
423
+ } else if (vcs === 'github') {
424
+ vcsBin = MR_ALLOWLISTED_BINS.gh;
425
+ } else {
426
+ throw new MrDraftError(`Unsupported vcs value: '${vcs}'`, 'UNSUPPORTED_VCS');
427
+ }
428
+
429
+ // Validate user-supplied issueTitle before building.
430
+ // validateMrInputs guards against shell-dangerous chars from the issue
431
+ // tracker. The description arg is '' here because the description is
432
+ // entirely template-controlled (checkboxes, headers) — only issueTitle
433
+ // is user-supplied and needs the injection guard. The assembled body
434
+ // intentionally contains '()' and '[ ]' from the trusted template.
435
+ validateMrInputs(issueTitle, '');
436
+
437
+ // Build title/description from validated inputs
438
+ const { title, description } = buildMrBody({
439
+ issueTitle,
440
+ issueIid,
441
+ parentRunId,
442
+ worktreePath,
443
+ });
444
+
445
+ // Collision check — skip if MR already exists
446
+ let existingCheck;
447
+ try {
448
+ existingCheck = await checkExistingMR({
449
+ vcs: vcsBin, // 'glab' or 'gh'
450
+ branchName,
451
+ execFile,
452
+ });
453
+ } catch (err) {
454
+ log('error', `mr-draft: collision check failed — ${err.message}`);
455
+ return { created: false, error: err.message };
456
+ }
457
+
458
+ if (existingCheck.hasMR) {
459
+ log(
460
+ 'info',
461
+ `mr-draft: existing MR found (iid=${existingCheck.mrIid}), skipping creation`,
462
+ );
463
+ return { created: false, existing: true, mrUrl: existingCheck.mrUrl };
464
+ }
465
+
466
+ // Build arg vector — no template-string interpolation in command args
467
+ let createArgs;
468
+ if (vcs === 'gitlab') {
469
+ createArgs = [
470
+ 'mr',
471
+ 'create',
472
+ '--draft',
473
+ '--title',
474
+ title,
475
+ '--description',
476
+ description,
477
+ '--source-branch',
478
+ branchName,
479
+ ];
480
+ } else {
481
+ // github
482
+ createArgs = [
483
+ 'pr',
484
+ 'create',
485
+ '--draft',
486
+ '--title',
487
+ title,
488
+ '--body',
489
+ description,
490
+ '--head',
491
+ branchName,
492
+ ];
493
+ }
494
+
495
+ // Execute MR/PR creation
496
+ try {
497
+ const { stdout } = await execFile(vcsBin, createArgs, {
498
+ shell: false,
499
+ timeout: 10_000,
500
+ maxBuffer: 1024 * 1024,
501
+ });
502
+ const mrUrl = stdout.trim() || null;
503
+ log('info', `mr-draft: created draft MR/PR — ${mrUrl}`);
504
+ return { created: true, mrUrl };
505
+ } catch (err) {
506
+ if (err.code === 'ENOENT') {
507
+ log('error', `mr-draft: binary '${vcsBin}' not found in PATH`);
508
+ return { created: false, error: 'binary not found' };
509
+ }
510
+ log('error', `mr-draft: execFile failed — ${err.message}`);
511
+ return { created: false, error: err.message };
512
+ }
513
+ }
514
+
515
+ // --- Unknown policy ---
516
+ throw new MrDraftError(
517
+ `Unknown draftMrPolicy: '${draftMrPolicy}'. Expected 'off', 'on-loop-start', or 'on-green'`,
518
+ 'VALIDATION',
519
+ );
520
+ }
@@ -0,0 +1,184 @@
1
+ // scripts/lib/autopilot/multi-killswitch.mjs
2
+ //
3
+ // 11th kill-switch (STALE_SUBAGENT_MIN) + cohort policy + concurrency cap for
4
+ // autopilot --multi-story. Pure decision logic; no I/O, no shell.
5
+ //
6
+ // References:
7
+ // - "Autopilot Phase D — Per-Story Worktree Pipelines" (#341; archived in the private Meta-Vault) (OPEN-2, OPEN-3, OPEN-5 decisions)
8
+ // - scripts/lib/autopilot/kill-switches.mjs (existing 10 switches; STALL_TIMEOUT precedent)
9
+ // - scripts/lib/resource-probe.mjs (snapshot shape)
10
+
11
+ import { KILL_SWITCHES } from './kill-switches.mjs';
12
+
13
+ // 11th kill-switch constant — additive to the existing 10 in KILL_SWITCHES
14
+ /** @type {string} */
15
+ export const STALE_SUBAGENT_MIN = 'stale-subagent-min';
16
+
17
+ /**
18
+ * Calculate concurrency cap per OPEN-2 decision from PRD §4.
19
+ * Formula: min(staticFloor, max(1, floor(ram_free_gb / ramPerLoopGb) - reserveSlots))
20
+ *
21
+ * Defensive: null/undefined ram_free_gb → 1; memory_pressure_pct_free < 15 → cap 1.
22
+ *
23
+ * @param {{ ram_free_gb: number, memory_pressure_pct_free?: number, claude_processes_count?: number }} snapshot
24
+ * @param {object} [opts]
25
+ * @param {number} [opts.staticFloor=3] - hard cap regardless of resources
26
+ * @param {number} [opts.ramPerLoopGb=4] - per-looper RAM budget
27
+ * @param {number} [opts.reserveSlots=1] - sessions to reserve for system + coordinator
28
+ * @returns {number} integer in [1, staticFloor]
29
+ */
30
+ export function calculateConcurrencyCap(snapshot, opts = {}) {
31
+ const staticFloor = opts.staticFloor ?? 3;
32
+ const ramPerLoopGb = opts.ramPerLoopGb ?? 4;
33
+ const reserveSlots = opts.reserveSlots ?? 1;
34
+
35
+ // macOS memory pressure degraded guard
36
+ if (
37
+ typeof snapshot?.memory_pressure_pct_free === 'number' &&
38
+ snapshot.memory_pressure_pct_free < 15
39
+ ) {
40
+ return 1;
41
+ }
42
+
43
+ const ramFreeGb = snapshot?.ram_free_gb;
44
+ if (ramFreeGb === null || ramFreeGb === undefined || typeof ramFreeGb !== 'number' || !Number.isFinite(ramFreeGb)) {
45
+ return 1;
46
+ }
47
+
48
+ const computed = Math.floor(ramFreeGb / ramPerLoopGb) - reserveSlots;
49
+ return Math.min(staticFloor, Math.max(1, computed));
50
+ }
51
+
52
+ /**
53
+ * @typedef {object} LoopRegistration
54
+ * @property {string} loopId
55
+ * @property {number} pid
56
+ * @property {string} parentRunId
57
+ * @property {number} issueIid
58
+ * @property {'queued'|'running'|'complete'|'failed'} status
59
+ * @property {string|null} killSwitch
60
+ * @property {number} spiralRecoveryCount
61
+ * @property {number} startedAt - epoch ms
62
+ * @property {number} lastActivityAt - epoch ms
63
+ */
64
+
65
+ /**
66
+ * Evaluate cross-loop kill-switches (STALE_SUBAGENT_MIN only — per-loop
67
+ * switches like SPIRAL are handled by postSessionKillSwitch upstream).
68
+ * Returns the FIRST kill condition that fires, or null.
69
+ *
70
+ * @param {LoopRegistration[]} loops
71
+ * @param {object} [opts]
72
+ * @param {number} [opts.staleSubagentMinSeconds=600]
73
+ * @param {() => number} [opts.nowMs=Date.now]
74
+ * @returns {{ kill: string, detail: string, loopId?: string }|null}
75
+ */
76
+ export function evaluateMultiKillSwitches(loops, opts = {}) {
77
+ if (!Array.isArray(loops) || loops.length === 0) return null;
78
+
79
+ const staleThresholdSeconds = opts.staleSubagentMinSeconds ?? 600;
80
+ const now = (opts.nowMs ?? Date.now)();
81
+
82
+ for (const loop of loops) {
83
+ if (!loop || loop.status !== 'running') continue;
84
+
85
+ const lastActivity = loop.lastActivityAt;
86
+ if (typeof lastActivity !== 'number' || !Number.isFinite(lastActivity)) continue;
87
+
88
+ const idleMs = now - lastActivity;
89
+ const idleSeconds = Math.floor(idleMs / 1000);
90
+
91
+ if (idleMs > staleThresholdSeconds * 1000) {
92
+ return {
93
+ kill: STALE_SUBAGENT_MIN,
94
+ detail: `loop ${loop.loopId} stale > ${idleSeconds}s (threshold ${staleThresholdSeconds}s)`,
95
+ loopId: loop.loopId,
96
+ };
97
+ }
98
+ }
99
+
100
+ return null;
101
+ }
102
+
103
+ /**
104
+ * Decide whether a sibling loop's failure should abort the cohort.
105
+ * Per OPEN-5 hybrid policy:
106
+ * - First SPIRAL AND target loop spiralRecoveryCount < 1 → retry
107
+ * - Second SPIRAL OR target already retried → cohort-abort
108
+ *
109
+ * @param {LoopRegistration[]} loops
110
+ * @param {string} failedLoopId
111
+ * @returns {{ action: 'retry'|'cohort-abort', reason: string }}
112
+ */
113
+ export function decideCohortAction(loops, failedLoopId) {
114
+ if (!Array.isArray(loops)) {
115
+ return { action: 'cohort-abort', reason: 'no loop registry provided' };
116
+ }
117
+
118
+ const spiralCount = loops.filter(
119
+ (l) => l && l.killSwitch === KILL_SWITCHES.SPIRAL,
120
+ ).length;
121
+
122
+ const targetLoop = loops.find((l) => l && l.loopId === failedLoopId);
123
+ const targetSpiralRecoveries = targetLoop?.spiralRecoveryCount ?? 0;
124
+
125
+ if (spiralCount <= 1 && targetSpiralRecoveries < 1) {
126
+ return {
127
+ action: 'retry',
128
+ reason: 'first-strike spiral, recovering loop ' + failedLoopId,
129
+ };
130
+ }
131
+
132
+ return {
133
+ action: 'cohort-abort',
134
+ reason: 'second-strike spiral or cohort threshold',
135
+ };
136
+ }
137
+
138
+ /**
139
+ * Check if the orchestrator stop condition is met (OPEN-3 layered policy).
140
+ * Priority: (1) cohort-abort → (2) backlog-empty → (3) inactivity-timeout
141
+ *
142
+ * @param {object} state
143
+ * @param {LoopRegistration[]} state.activeLoops
144
+ * @param {object[]} state.readyBacklog
145
+ * @param {number} state.lastCompletionAt
146
+ * @param {object} [opts]
147
+ * @param {number} [opts.inactivityTimeoutMs=300000]
148
+ * @param {() => number} [opts.nowMs=Date.now]
149
+ * @returns {{ stop: boolean, reason?: 'first-kill-switch'|'backlog-empty'|'inactivity-timeout' }}
150
+ */
151
+ export function shouldStopOrchestrator(state, opts = {}) {
152
+ const inactivityTimeoutMs = opts.inactivityTimeoutMs ?? 300_000;
153
+ const now = (opts.nowMs ?? Date.now)();
154
+
155
+ const activeLoops = Array.isArray(state?.activeLoops) ? state.activeLoops : [];
156
+ const readyBacklog = Array.isArray(state?.readyBacklog) ? state.readyBacklog : [];
157
+
158
+ // Priority 1: cohort-abort triggered by spiral on an active loop
159
+ for (const loop of activeLoops) {
160
+ if (!loop || loop.killSwitch !== KILL_SWITCHES.SPIRAL) continue;
161
+
162
+ const decision = decideCohortAction(activeLoops, loop.loopId);
163
+ if (decision.action === 'cohort-abort') {
164
+ return { stop: true, reason: 'first-kill-switch' };
165
+ }
166
+ }
167
+
168
+ // Priority 2: all work drained
169
+ if (activeLoops.length === 0 && readyBacklog.length === 0) {
170
+ return { stop: true, reason: 'backlog-empty' };
171
+ }
172
+
173
+ // Priority 3: orchestrator inactivity timeout (only meaningful while loops are running)
174
+ if (
175
+ activeLoops.length > 0 &&
176
+ typeof state?.lastCompletionAt === 'number' &&
177
+ Number.isFinite(state.lastCompletionAt) &&
178
+ now - state.lastCompletionAt > inactivityTimeoutMs
179
+ ) {
180
+ return { stop: true, reason: 'inactivity-timeout' };
181
+ }
182
+
183
+ return { stop: false };
184
+ }