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,293 @@
1
+ /**
2
+ * autopilot-effectiveness.mjs — /evolve type 8 analyzer (issue #298).
3
+ *
4
+ * Type 8: autopilot-effectiveness — compares manual vs autopilot effectiveness
5
+ * per session mode (housekeeping / feature / deep). Surfaces a learning per
6
+ * mode once enough paired runs accumulate to make the comparison statistically
7
+ * useful.
8
+ *
9
+ * DATA-GATING (intentional): the analyzer returns [] until at least
10
+ * `minPairedRuns` (default 20) sessions of EACH variant (manual + autopilot)
11
+ * exist for a given mode. This keeps the skeleton inert through the early
12
+ * autopilot rollout while wiring lives end-to-end. Once data accumulates the
13
+ * function activates without any further code change.
14
+ *
15
+ * Manual vs. autopilot is determined by the presence of an `autopilot_run_id`
16
+ * field on the session record (written by `scripts/autopilot.mjs` for every
17
+ * session it spawns). Sessions without that field are treated as manual.
18
+ *
19
+ * Existing analyzer types (1-7) for reference: fragile-file, effective-sizing,
20
+ * recurring-issue, scope-guidance, deviation-pattern, stagnation-class-frequency,
21
+ * hardware-pattern. This module adds type 8 to the family.
22
+ *
23
+ * Contract: pure, no-throw, ES module, zero external deps. Mirrors the style of
24
+ * `scripts/lib/hardware-pattern-detector.mjs` (issue #171 / C2).
25
+ */
26
+
27
+ import { randomUUID } from 'node:crypto';
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Constants
31
+ // ---------------------------------------------------------------------------
32
+
33
+ /** Default data-gating threshold per mode (manual AND autopilot side). */
34
+ export const DEFAULT_MIN_PAIRED_RUNS = 20;
35
+
36
+ /** Modes recognised by mode-selector / autopilot. */
37
+ export const KNOWN_MODES = Object.freeze(['housekeeping', 'feature', 'deep']);
38
+
39
+ /** Initial confidence — lifecycle (decay/boost) handled by evolve infrastructure. */
40
+ const INITIAL_CONFIDENCE = 0.5;
41
+
42
+ /** Learning lifetime: 90 days from emit. */
43
+ const EXPIRY_DAYS = 90;
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Defensive helpers
47
+ // ---------------------------------------------------------------------------
48
+
49
+ /** Safe number coercion. Returns null for non-finite inputs. */
50
+ function num(v) {
51
+ if (typeof v !== 'number' || !Number.isFinite(v)) return null;
52
+ return v;
53
+ }
54
+
55
+ /** Round to 3 decimals for stable evidence shape (no float noise). */
56
+ function round3(v) {
57
+ if (v === null || v === undefined) return null;
58
+ return Math.round(v * 1000) / 1000;
59
+ }
60
+
61
+ /** ISO-8601 string for `now + N days`. */
62
+ function isoPlusDays(nowIso, days) {
63
+ try {
64
+ const t = new Date(nowIso).getTime();
65
+ if (!Number.isFinite(t)) return new Date(Date.now() + days * 86400e3).toISOString();
66
+ return new Date(t + days * 86400e3).toISOString();
67
+ } catch {
68
+ return new Date(Date.now() + days * 86400e3).toISOString();
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Extract a completion ratio from a session record. Sessions encode this in a
74
+ * few historically-evolved shapes; we tolerate all of them and fall back to
75
+ * `null` (excluded from the average) when nothing usable is present.
76
+ *
77
+ * @param {object} s
78
+ * @returns {number|null} ratio in [0, 1], or null when unknown
79
+ */
80
+ function completionOf(s) {
81
+ if (!s || typeof s !== 'object') return null;
82
+ // Direct ratio fields
83
+ const direct = num(s.completion_rate ?? s.completion_ratio);
84
+ if (direct !== null && direct >= 0 && direct <= 1) return direct;
85
+ // Planned vs completed counts
86
+ const planned = num(s.planned_count ?? s.tasks_planned);
87
+ const completed = num(s.completed_count ?? s.tasks_completed);
88
+ if (planned !== null && completed !== null && planned > 0) {
89
+ return Math.max(0, Math.min(1, completed / planned));
90
+ }
91
+ return null;
92
+ }
93
+
94
+ /**
95
+ * Extract a carryover ratio from a session record. Carryover = work not closed
96
+ * within the session that flowed to a follow-up. Same tolerance pattern as
97
+ * `completionOf`.
98
+ *
99
+ * @param {object} s
100
+ * @returns {number|null} ratio in [0, 1], or null when unknown
101
+ */
102
+ function carryoverOf(s) {
103
+ if (!s || typeof s !== 'object') return null;
104
+ const direct = num(s.carryover_ratio ?? s.carryover_rate);
105
+ if (direct !== null && direct >= 0 && direct <= 1) return direct;
106
+ const planned = num(s.planned_count ?? s.tasks_planned);
107
+ const carried = num(s.carryover_count ?? s.tasks_carried_over);
108
+ if (planned !== null && carried !== null && planned > 0) {
109
+ return Math.max(0, Math.min(1, carried / planned));
110
+ }
111
+ return null;
112
+ }
113
+
114
+ /** Mean of an array of numbers, ignoring null/undefined. Returns null when empty. */
115
+ function mean(values) {
116
+ const xs = values.filter((v) => typeof v === 'number' && Number.isFinite(v));
117
+ if (xs.length === 0) return null;
118
+ return xs.reduce((a, b) => a + b, 0) / xs.length;
119
+ }
120
+
121
+ // ---------------------------------------------------------------------------
122
+ // Grouping
123
+ // ---------------------------------------------------------------------------
124
+
125
+ /**
126
+ * Group sessions by mode and split into manual vs. autopilot variants.
127
+ * A session is "autopilot" when it carries an `autopilot_run_id` field (added
128
+ * by scripts/autopilot.mjs for every spawned wave), "manual" otherwise.
129
+ *
130
+ * The `autopilotRuns` array is accepted for symmetry with the public `analyze`
131
+ * signature and to allow future per-run filtering (e.g., only count sessions
132
+ * whose autopilot_run_id matches a known run). For the skeleton it is used
133
+ * only as a non-emptiness signal.
134
+ *
135
+ * @param {Array} autopilotRuns
136
+ * @param {Array} sessions
137
+ * @returns {Map<string, {n_manual:number, n_autopilot:number,
138
+ * completion_rate_manual:number|null, completion_rate_autopilot:number|null,
139
+ * carryover_ratio_manual:number|null, carryover_ratio_autopilot:number|null}>}
140
+ */
141
+ export function groupByMode(autopilotRuns, sessions) {
142
+ const out = new Map();
143
+ if (!Array.isArray(sessions) || sessions.length === 0) return out;
144
+
145
+ // Optional: known autopilot_run_id set for stricter pairing. Empty set means
146
+ // accept any session with a non-empty autopilot_run_id field.
147
+ const knownRunIds = new Set();
148
+ if (Array.isArray(autopilotRuns)) {
149
+ for (const r of autopilotRuns) {
150
+ if (r && typeof r === 'object') {
151
+ const id = r.autopilot_run_id ?? r.run_id ?? r.id;
152
+ if (typeof id === 'string' && id.length > 0) knownRunIds.add(id);
153
+ }
154
+ }
155
+ }
156
+
157
+ // Bucket: mode → {manual: [], autopilot: []}
158
+ const buckets = new Map();
159
+ for (const s of sessions) {
160
+ if (!s || typeof s !== 'object') continue;
161
+ const mode = typeof s.mode === 'string' ? s.mode : null;
162
+ if (!mode) continue;
163
+ const apId = typeof s.autopilot_run_id === 'string' ? s.autopilot_run_id : null;
164
+ const isAutopilot =
165
+ apId !== null && apId.length > 0 && (knownRunIds.size === 0 || knownRunIds.has(apId));
166
+ const variant = isAutopilot ? 'autopilot' : 'manual';
167
+ if (!buckets.has(mode)) buckets.set(mode, { manual: [], autopilot: [] });
168
+ buckets.get(mode)[variant].push(s);
169
+ }
170
+
171
+ for (const [mode, { manual, autopilot }] of buckets) {
172
+ out.set(mode, {
173
+ n_manual: manual.length,
174
+ n_autopilot: autopilot.length,
175
+ completion_rate_manual: round3(mean(manual.map(completionOf))),
176
+ completion_rate_autopilot: round3(mean(autopilot.map(completionOf))),
177
+ carryover_ratio_manual: round3(mean(manual.map(carryoverOf))),
178
+ carryover_ratio_autopilot: round3(mean(autopilot.map(carryoverOf))),
179
+ });
180
+ }
181
+ return out;
182
+ }
183
+
184
+ // ---------------------------------------------------------------------------
185
+ // Learning record builder
186
+ // ---------------------------------------------------------------------------
187
+
188
+ /**
189
+ * Build a canonical schema_version:1 learning record for a single mode.
190
+ * Subject form: `<mode>-manual-vs-autopilot`. Insight is human-readable.
191
+ *
192
+ * @param {string} mode
193
+ * @param {object} stats — output of `groupByMode().get(mode)`
194
+ * @param {string} nowIso
195
+ * @returns {object} learning record
196
+ */
197
+ export function buildLearning(mode, stats, nowIso) {
198
+ const cm = stats.completion_rate_manual;
199
+ const ca = stats.completion_rate_autopilot;
200
+ const km = stats.carryover_ratio_manual;
201
+ const ka = stats.carryover_ratio_autopilot;
202
+
203
+ const completionDelta = cm !== null && ca !== null ? round3(ca - cm) : null;
204
+ const carryoverDelta = km !== null && ka !== null ? round3(ka - km) : null;
205
+
206
+ const parts = [];
207
+ if (completionDelta !== null) {
208
+ const dir = completionDelta > 0 ? 'higher' : completionDelta < 0 ? 'lower' : 'matched';
209
+ parts.push(`autopilot completion ${dir} by ${Math.abs(completionDelta)} (${ca} vs ${cm})`);
210
+ }
211
+ if (carryoverDelta !== null) {
212
+ const dir = carryoverDelta > 0 ? 'more' : carryoverDelta < 0 ? 'less' : 'equal';
213
+ parts.push(`carryover ${dir} (${ka} vs ${km})`);
214
+ }
215
+ const insight =
216
+ parts.length > 0
217
+ ? `Mode '${mode}': ${parts.join('; ')} across ${stats.n_manual} manual + ${stats.n_autopilot} autopilot runs.`
218
+ : `Mode '${mode}': insufficient effectiveness data despite ${stats.n_manual}+${stats.n_autopilot} paired runs.`;
219
+
220
+ const sourceSession = `evolve-${nowIso.slice(0, 10)}`;
221
+
222
+ return {
223
+ schema_version: 1,
224
+ id: randomUUID(),
225
+ type: 'autopilot-effectiveness',
226
+ subject: `${mode}-manual-vs-autopilot`,
227
+ insight,
228
+ evidence: {
229
+ mode,
230
+ n_manual: stats.n_manual,
231
+ n_autopilot: stats.n_autopilot,
232
+ completion_rate_manual: cm,
233
+ completion_rate_autopilot: ca,
234
+ carryover_ratio_manual: km,
235
+ carryover_ratio_autopilot: ka,
236
+ completion_delta: completionDelta,
237
+ carryover_delta: carryoverDelta,
238
+ },
239
+ confidence: INITIAL_CONFIDENCE,
240
+ source_session: sourceSession,
241
+ created_at: nowIso,
242
+ expires_at: isoPlusDays(nowIso, EXPIRY_DAYS),
243
+ };
244
+ }
245
+
246
+ // ---------------------------------------------------------------------------
247
+ // Public entry point
248
+ // ---------------------------------------------------------------------------
249
+
250
+ /**
251
+ * Analyze paired manual + autopilot runs and emit `autopilot-effectiveness`
252
+ * learnings — one per qualifying mode. Returns `[]` until the data-gating
253
+ * threshold is met (default: 20 paired runs per mode).
254
+ *
255
+ * Never throws. Defensive against malformed entries.
256
+ *
257
+ * @param {Array} autopilotRuns — entries from .orchestrator/metrics/autopilot.jsonl
258
+ * @param {Array} sessions — entries from .orchestrator/metrics/sessions.jsonl
259
+ * @param {object} [opts]
260
+ * @param {number} [opts.minPairedRuns=20] — min(n_manual, n_autopilot) per mode
261
+ * @param {string} [opts.now] — ISO 8601 timestamp for created_at (testable)
262
+ * @returns {Array<object>} learning records (empty until threshold met)
263
+ */
264
+ export function analyze(autopilotRuns, sessions, opts = {}) {
265
+ const minPairedRuns = Number.isFinite(opts.minPairedRuns)
266
+ ? opts.minPairedRuns
267
+ : DEFAULT_MIN_PAIRED_RUNS;
268
+ const now = typeof opts.now === 'string' && opts.now.length > 0
269
+ ? opts.now
270
+ : new Date().toISOString();
271
+
272
+ if (!Array.isArray(autopilotRuns) || autopilotRuns.length === 0) return [];
273
+ if (!Array.isArray(sessions) || sessions.length === 0) return [];
274
+
275
+ let grouped;
276
+ try {
277
+ grouped = groupByMode(autopilotRuns, sessions);
278
+ } catch {
279
+ return [];
280
+ }
281
+ if (!grouped || grouped.size === 0) return [];
282
+
283
+ const learnings = [];
284
+ for (const [mode, stats] of grouped) {
285
+ if (Math.min(stats.n_manual, stats.n_autopilot) < minPairedRuns) continue;
286
+ try {
287
+ learnings.push(buildLearning(mode, stats, now));
288
+ } catch {
289
+ // Skip a single failed mode rather than collapsing the whole analysis.
290
+ }
291
+ }
292
+ return learnings;
293
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * exclusivity-matrix.mjs — Classify orchestrator skill modes into exclusivity classes.
3
+ *
4
+ * Pure ESM, no imports required. Stateless pure functions only.
5
+ *
6
+ * Exclusivity classes control whether a session mode may run concurrently with
7
+ * other active sessions in the same working directory:
8
+ * - "exclusive" — must hold the session lock alone (e.g., housekeeping)
9
+ * - "parallel-ok" — may coexist with other parallel-ok sessions
10
+ * - "always-ok" — lightweight; always allowed regardless of active sessions
11
+ *
12
+ * Used by:
13
+ * - parallel-aware-preamble (W3-P3, #574) — inject concurrency guardrail text
14
+ * - acquire() integration (P1.2, #570) — enforce lock semantics at session-start
15
+ *
16
+ * Stable contract: the list of modes per class is documented in
17
+ * `skills/_shared/state-ownership.md` (PRD §3.A line 195).
18
+ * Do NOT add or move modes without coordinating with that document.
19
+ */
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // EXCLUSIVITY_MATRIX
23
+ // ---------------------------------------------------------------------------
24
+
25
+ /**
26
+ * Static, frozen mapping from exclusivity class → mode names.
27
+ *
28
+ * All inner arrays are also frozen to prevent mutation. Any attempt to push,
29
+ * splice, or reassign will throw a TypeError in strict mode (and silently fail
30
+ * in sloppy mode after Object.freeze — prefer strict mode callers).
31
+ *
32
+ * @type {{ exclusive: readonly string[], "parallel-ok": readonly string[], "always-ok": readonly string[] }}
33
+ */
34
+ export const EXCLUSIVITY_MATRIX = Object.freeze({
35
+ exclusive: Object.freeze(['bootstrap', 'housekeeping', 'memory-cleanup']),
36
+ 'parallel-ok': Object.freeze(['deep', 'feature']),
37
+ 'always-ok': Object.freeze(['discovery', 'evolve', 'plan', 'repo-audit', 'portfolio']),
38
+ });
39
+
40
+ // ---------------------------------------------------------------------------
41
+ // classifyMode
42
+ // ---------------------------------------------------------------------------
43
+
44
+ /**
45
+ * Classify a skill mode name into its exclusivity class.
46
+ *
47
+ * Lookup is case-sensitive; all documented modes are lowercase. Whitespace is
48
+ * trimmed defensively before the lookup so callers do not need to pre-strip.
49
+ *
50
+ * @param {string} modeName - The skill mode name to classify (e.g. "deep").
51
+ * @returns {"exclusive" | "parallel-ok" | "always-ok"} The exclusivity class.
52
+ * @throws {Error} If `modeName` (after trimming) is not a recognised mode.
53
+ *
54
+ * @example
55
+ * classifyMode('deep') // → "parallel-ok"
56
+ * classifyMode('housekeeping') // → "exclusive"
57
+ * classifyMode('discovery') // → "always-ok"
58
+ */
59
+ export function classifyMode(modeName) {
60
+ const name = String(modeName).trim();
61
+
62
+ for (const [cls, modes] of Object.entries(EXCLUSIVITY_MATRIX)) {
63
+ if (modes.includes(name)) return cls;
64
+ }
65
+
66
+ const known = Object.values(EXCLUSIVITY_MATRIX).flat().join(', ');
67
+ throw new Error(`classifyMode: unknown mode "${name}". Known modes: ${known}`);
68
+ }
@@ -0,0 +1,311 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * scripts/lib/fetch-baseline.mjs
4
+ *
5
+ * Fetch a file from a GitLab project's repository raw endpoint.
6
+ * Node.js port of scripts/lib/fetch-baseline.sh (issue #218).
7
+ *
8
+ * Used by the bootstrap skill to pull canonical baseline files (rules, agents,
9
+ * CLAUDE.md / AGENTS.md snippets) on demand instead of relying on local copies
10
+ * that drift.
11
+ *
12
+ * Required env vars:
13
+ * GITLAB_TOKEN — personal access token with read_api or read_repository scope
14
+ *
15
+ * Optional env vars:
16
+ * GITLAB_HOST — GitLab host (required; no private domain fallback)
17
+ * BASELINE_REF — default: main
18
+ * FETCH_TIMEOUT_MS — default: 10000 (ms; maps to FETCH_TIMEOUT seconds in .sh)
19
+ * BASELINE_CACHE_DIR — override cache directory
20
+ *
21
+ * Named export (module usage):
22
+ * import { fetchBaselineFile } from './fetch-baseline.mjs';
23
+ * const result = await fetchBaselineFile({ baselineRef, filePath, token, projectId });
24
+ *
25
+ * CLI usage:
26
+ * node scripts/lib/fetch-baseline.mjs <project_id> <file_path> [ref]
27
+ */
28
+
29
+ import { promises as fs } from 'node:fs';
30
+ import path from 'node:path';
31
+ import { execSync } from 'node:child_process';
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // Configuration defaults (mirrors the .sh defaults)
35
+ // ---------------------------------------------------------------------------
36
+
37
+ const DEFAULT_BASELINE_REF = 'main';
38
+ const DEFAULT_FETCH_TIMEOUT_MS = 10_000;
39
+
40
+ // ---------------------------------------------------------------------------
41
+ // Internal helpers
42
+ // ---------------------------------------------------------------------------
43
+
44
+ /**
45
+ * Resolve the cache directory.
46
+ * Honours BASELINE_CACHE_DIR env override, then falls back to
47
+ * <repo-root>/.claude/.baseline-cache (same logic as .sh).
48
+ *
49
+ * @returns {string}
50
+ */
51
+ function _cacheDir() {
52
+ if (process.env.BASELINE_CACHE_DIR) {
53
+ return process.env.BASELINE_CACHE_DIR;
54
+ }
55
+ let root;
56
+ try {
57
+ root = execSync('git rev-parse --show-toplevel', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
58
+ } catch {
59
+ root = process.cwd();
60
+ }
61
+ return path.join(root, '.claude', '.baseline-cache');
62
+ }
63
+
64
+ /**
65
+ * URL-encode a file path for the GitLab API.
66
+ * Encodes slashes as %2F and other special characters via encodeURIComponent.
67
+ *
68
+ * @param {string} filePath
69
+ * @returns {string}
70
+ */
71
+ function _urlEncodePath(filePath) {
72
+ // encodeURIComponent handles all characters except A-Z a-z 0-9 - _ . ! ~ * ' ( )
73
+ // GitLab expects slashes encoded as %2F in the path segment (already the default output).
74
+ return encodeURIComponent(filePath);
75
+ }
76
+
77
+ /**
78
+ * Derive a filesystem-safe cache key from (projectId, ref, filePath).
79
+ * Mirrors the __cache_key() function in the .sh original.
80
+ *
81
+ * @param {string} projectId
82
+ * @param {string} ref
83
+ * @param {string} filePath
84
+ * @returns {string}
85
+ */
86
+ function _cacheKey(projectId, ref, filePath) {
87
+ const raw = `${projectId}-${ref}-${filePath}`;
88
+ return raw.replace(/[/.]/g, '_');
89
+ }
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // Public named export
93
+ // ---------------------------------------------------------------------------
94
+
95
+ /**
96
+ * Fetch a single file from a GitLab project's repository.
97
+ *
98
+ * @param {object} opts
99
+ * @param {string} opts.filePath - repo-relative path (e.g. ".claude/rules/security.md")
100
+ * @param {string} [opts.baselineRef] - git ref (default: BASELINE_REF env or "main")
101
+ * @param {string} [opts.token] - GitLab personal access token (default: GITLAB_TOKEN env)
102
+ * @param {string|number} [opts.projectId] - GitLab project ID (default: 52)
103
+ * @param {string} [opts.host] - GitLab host (required; falls back to GITLAB_HOST env; no default private host)
104
+ * @param {number} [opts.timeoutMs] - fetch timeout in ms (default: FETCH_TIMEOUT_MS env or 10000)
105
+ *
106
+ * @returns {Promise<{
107
+ * ok: boolean,
108
+ * body?: string,
109
+ * status?: number,
110
+ * error?: string,
111
+ * fromCache?: boolean
112
+ * }>}
113
+ *
114
+ * Exit-code semantics (mirrored as result shapes):
115
+ * ok:true — success (network or cache fallback)
116
+ * ok:false, status:401/403 — auth failure — fatal
117
+ * ok:false, status:404 — file not found + no cache
118
+ * ok:false, status:0 — network/transport failure + no cache (status 0 = transport)
119
+ */
120
+ export async function fetchBaselineFile({
121
+ filePath,
122
+ baselineRef,
123
+ token,
124
+ projectId = 52,
125
+ host,
126
+ timeoutMs,
127
+ } = {}) {
128
+ const resolvedToken = token ?? process.env.GITLAB_TOKEN;
129
+ const resolvedRef = baselineRef ?? process.env.BASELINE_REF ?? DEFAULT_BASELINE_REF;
130
+ const resolvedHost = host ?? process.env.GITLAB_HOST;
131
+ const resolvedTimeout = timeoutMs ?? Number(process.env.FETCH_TIMEOUT_MS ?? DEFAULT_FETCH_TIMEOUT_MS);
132
+
133
+ if (!resolvedHost) {
134
+ const errMsg = 'GITLAB_HOST not configured — set GITLAB_HOST env or pass opts.host';
135
+ process.stderr.write(`ERROR: ${errMsg}\n`);
136
+ return {
137
+ ok: false,
138
+ status: 0,
139
+ error: errMsg,
140
+ };
141
+ }
142
+
143
+ if (!resolvedToken) {
144
+ const errMsg = 'GITLAB_TOKEN not set — cannot fetch from baseline.';
145
+ process.stderr.write(`ERROR: ${errMsg}\n`);
146
+ return {
147
+ ok: false,
148
+ status: 401,
149
+ error: errMsg,
150
+ };
151
+ }
152
+
153
+ if (!filePath) {
154
+ return {
155
+ ok: false,
156
+ status: 0,
157
+ error: 'filePath is required.',
158
+ };
159
+ }
160
+
161
+ const cacheDirectory = _cacheDir();
162
+ const cacheKey = _cacheKey(String(projectId), resolvedRef, filePath);
163
+ const cacheFile = path.join(cacheDirectory, cacheKey);
164
+
165
+ const encodedPath = _urlEncodePath(filePath);
166
+ const url = `https://${resolvedHost}/api/v4/projects/${projectId}/repository/files/${encodedPath}/raw?ref=${resolvedRef}`;
167
+
168
+ // ---------------------------------------------------------------------------
169
+ // Attempt network fetch
170
+ // ---------------------------------------------------------------------------
171
+ let response;
172
+ try {
173
+ const controller = new AbortController();
174
+ const timer = setTimeout(() => controller.abort(), resolvedTimeout);
175
+ try {
176
+ response = await fetch(url, {
177
+ headers: { 'PRIVATE-TOKEN': resolvedToken },
178
+ signal: controller.signal,
179
+ });
180
+ } finally {
181
+ clearTimeout(timer);
182
+ }
183
+ } catch (err) {
184
+ // Transport/network failure (DNS, timeout, connection refused, etc.)
185
+ const errMsg = err instanceof Error ? err.message : String(err);
186
+
187
+ // Try cache fallback
188
+ try {
189
+ const cached = await fs.readFile(cacheFile, 'utf8');
190
+ process.stderr.write(`WARNING: fetch failed (network error: ${errMsg}); using cache for ${filePath}\n`);
191
+ return { ok: true, body: cached, fromCache: true };
192
+ } catch {
193
+ process.stderr.write(
194
+ `ERROR: fetch failed and no cache for ${filePath} (project ${projectId}, ref ${resolvedRef}): ${errMsg}\n`,
195
+ );
196
+ return { ok: false, status: 0, error: errMsg };
197
+ }
198
+ }
199
+
200
+ // ---------------------------------------------------------------------------
201
+ // Handle HTTP status codes (mirrors the case statement in .sh)
202
+ // ---------------------------------------------------------------------------
203
+
204
+ if (response.status === 200) {
205
+ const body = await response.text();
206
+ // Write to cache (best-effort — don't fail the caller if cache write fails)
207
+ try {
208
+ await fs.mkdir(cacheDirectory, { recursive: true });
209
+ await fs.writeFile(cacheFile, body, 'utf8');
210
+ } catch {
211
+ // ignore cache write errors
212
+ }
213
+ return { ok: true, body, status: 200 };
214
+ }
215
+
216
+ if (response.status === 401 || response.status === 403) {
217
+ // Auth failure — fatal, no cache fallback (matches .sh behaviour)
218
+ const errMsg = `auth failed (${response.status}) fetching ${filePath} — check GITLAB_TOKEN scope`;
219
+ process.stderr.write(`ERROR: ${errMsg}\n`);
220
+ return { ok: false, status: response.status, error: errMsg };
221
+ }
222
+
223
+ if (response.status === 404) {
224
+ // Try cache fallback
225
+ try {
226
+ const cached = await fs.readFile(cacheFile, 'utf8');
227
+ process.stderr.write(
228
+ `WARNING: 404 for ${filePath}; using cache (file may have been removed from baseline)\n`,
229
+ );
230
+ return { ok: true, body: cached, status: 404, fromCache: true };
231
+ } catch {
232
+ const errMsg = `file not found (${filePath} on ${resolvedRef}) and no cache`;
233
+ process.stderr.write(`ERROR: ${errMsg}\n`);
234
+ return { ok: false, status: 404, error: errMsg };
235
+ }
236
+ }
237
+
238
+ // Any other non-2xx status — try cache fallback
239
+ try {
240
+ const cached = await fs.readFile(cacheFile, 'utf8');
241
+ process.stderr.write(`WARNING: HTTP ${response.status} for ${filePath}; using cache\n`);
242
+ return { ok: true, body: cached, status: response.status, fromCache: true };
243
+ } catch {
244
+ const errMsg = `HTTP ${response.status} fetching ${filePath} — no cache`;
245
+ process.stderr.write(`ERROR: ${errMsg}\n`);
246
+ return { ok: false, status: response.status, error: errMsg };
247
+ }
248
+ }
249
+
250
+ // ---------------------------------------------------------------------------
251
+ // CLI mode
252
+ // ---------------------------------------------------------------------------
253
+
254
+ /**
255
+ * When invoked directly: node scripts/lib/fetch-baseline.mjs <project_id> <file_path> [ref]
256
+ *
257
+ * Fetches the file and prints the body to stdout.
258
+ * Exit codes mirror the .sh original:
259
+ * 0 — success
260
+ * 1 — auth failure (401/403) or missing GITLAB_TOKEN
261
+ * 2 — file not found (404, no cache)
262
+ * 3 — network/transport failure, no cache; or unexpected HTTP status
263
+ */
264
+ async function _cliMain() {
265
+ const args = process.argv.slice(2);
266
+
267
+ if (args.length < 2) {
268
+ process.stderr.write(
269
+ `Usage: node ${path.basename(process.argv[1])} <project_id> <file_path> [ref]\n`,
270
+ );
271
+ process.exit(1);
272
+ }
273
+
274
+ const [projectId, filePath, ref] = args;
275
+
276
+ const result = await fetchBaselineFile({
277
+ projectId,
278
+ filePath,
279
+ baselineRef: ref, // undefined when not supplied → uses env/default
280
+ });
281
+
282
+ if (result.ok) {
283
+ process.stdout.write(result.body ?? '');
284
+ process.exit(0);
285
+ }
286
+
287
+ // Map error to exit code matching .sh
288
+ const status = result.status ?? 0;
289
+ if (status === 401 || status === 403) {
290
+ process.exit(1);
291
+ }
292
+ if (status === 404) {
293
+ process.exit(2);
294
+ }
295
+ // network failure or unexpected HTTP status
296
+ process.exit(3);
297
+ }
298
+
299
+ // Detect CLI invocation: import.meta.url matches the argv[1] path
300
+ const isMain = process.argv[1] && (
301
+ process.argv[1] === new URL(import.meta.url).pathname ||
302
+ // Handle invocation without file:// prefix
303
+ process.argv[1].endsWith('fetch-baseline.mjs')
304
+ );
305
+
306
+ if (isMain) {
307
+ _cliMain().catch((err) => {
308
+ process.stderr.write(`FATAL: ${err instanceof Error ? err.message : String(err)}\n`);
309
+ process.exit(3);
310
+ });
311
+ }