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,160 @@
1
+ /**
2
+ * Phase B-1 Mode-Selector heuristic v1 (issue #291, Epic #271).
3
+ *
4
+ * Thin orchestrator — delegates to submodules (W1A2 split, issue #358).
5
+ * Pure function: same inputs → same outputs, zero side effects, no I/O.
6
+ *
7
+ * Public API:
8
+ * selectMode(signals) → Recommendation
9
+ * computeContextPressure (re-export from context-pressure.mjs)
10
+ */
11
+
12
+ import { isValidMode } from './recommendations-v0.mjs';
13
+ import { DEFAULT_MODE } from './mode-selector/constants.mjs';
14
+ import { computeDelta, round2, isNonExecutionMode } from './mode-selector/scoring.mjs';
15
+ import { buildAlternatives } from './mode-selector/alternatives.mjs';
16
+ import { buildPassthroughRationale } from './mode-selector/rationale.mjs';
17
+ import { computeContextPressure } from './mode-selector/context-pressure.mjs';
18
+ export { computeContextPressure };
19
+
20
+ // clamp inlined — used only in selectMode; avoids importing scoring helpers
21
+ // for a single expression.
22
+ function clamp(v, min, max) {
23
+ return Math.min(max, Math.max(min, v));
24
+ }
25
+
26
+ /**
27
+ * Deterministic mode selection for session-start.
28
+ *
29
+ * Pure function: same inputs → same outputs, zero side effects, no I/O.
30
+ *
31
+ * Heuristic v1 (issue #291) — consumes carryoverRatio, completionRate,
32
+ * recentSessions trend, bootstrapLock tier-alignment, and learnings hints
33
+ * to compute a confidence-weighted recommendation with alternatives.
34
+ *
35
+ * Decision priority:
36
+ * 1. SPIRAL — completionRate < 0.5
37
+ * 2. CARRYOVER — carryoverRatio >= 0.3
38
+ * 3. PASSTHROUGH-WEIGHTED — valid recommendedMode + signal scoring
39
+ * 4. DEFAULT — no valid mode, no spiral/carryover trigger
40
+ *
41
+ * @param {import('./mode-selector/constants.mjs').Signals|null|undefined} signals
42
+ * @returns {import('./mode-selector/constants.mjs').Recommendation}
43
+ */
44
+ export function selectMode(signals) {
45
+ // Null-guard: treat null/undefined as empty signals object.
46
+ if (signals === null || signals === undefined) {
47
+ return {
48
+ mode: DEFAULT_MODE,
49
+ rationale: 'scaffold: null signals → default',
50
+ confidence: 0.0,
51
+ alternatives: [],
52
+ context_pressure: computeContextPressure({}),
53
+ };
54
+ }
55
+
56
+ // Defensive extraction of numeric signals.
57
+ const completionRate =
58
+ typeof signals.completionRate === 'number' && !Number.isNaN(signals.completionRate)
59
+ ? signals.completionRate
60
+ : null;
61
+ const carryoverRatio =
62
+ typeof signals.carryoverRatio === 'number' && !Number.isNaN(signals.carryoverRatio)
63
+ ? signals.carryoverRatio
64
+ : null;
65
+
66
+ // Branch 1 — SPIRAL: low completion rate
67
+ if (completionRate !== null && completionRate < 0.5) {
68
+ return {
69
+ mode: 'plan-retro',
70
+ rationale: 'low completion → retrospective',
71
+ confidence: 0.8,
72
+ alternatives: [
73
+ { mode: 'feature', confidence: 0.3 },
74
+ { mode: 'discovery', confidence: 0.25 },
75
+ ],
76
+ context_pressure: computeContextPressure(signals),
77
+ };
78
+ }
79
+
80
+ // Branch 2 — CARRYOVER: high carryover ratio
81
+ if (carryoverRatio !== null && carryoverRatio >= 0.3) {
82
+ const pct = Math.round(carryoverRatio * 100);
83
+ return {
84
+ mode: 'deep',
85
+ rationale: `carryover ${pct}% — deep clear`,
86
+ confidence: 0.75,
87
+ alternatives: [
88
+ { mode: 'feature', confidence: 0.3 },
89
+ { mode: 'plan-retro', confidence: 0.2 },
90
+ ],
91
+ context_pressure: computeContextPressure(signals),
92
+ };
93
+ }
94
+
95
+ // Branch 3 — PASSTHROUGH-WEIGHTED: valid recommendedMode from Phase A
96
+ const m = signals.recommendedMode;
97
+ if (typeof m === 'string' && isValidMode(m)) {
98
+ const delta = computeDelta(m, signals);
99
+ const confidence = round2(clamp(0.5 + delta, 0.0, 0.9));
100
+ const pressure = computeContextPressure(signals);
101
+ let rationale = buildPassthroughRationale(m, confidence, signals);
102
+
103
+ // Annotate rationale with pressure level when non-trivial (≤120 char limit).
104
+ if (pressure.level !== 'low') {
105
+ const pressureAnnotation = `; pressure:${pressure.level}(${pressure.score})`;
106
+ rationale = (rationale + pressureAnnotation).slice(0, 120);
107
+ }
108
+
109
+ const alternatives = buildAlternatives(m, signals);
110
+
111
+ // Global-max swap (#299): the primary recommendation must be the
112
+ // highest-confidence mode across {primary, ...alternatives}. When an
113
+ // alternative outranks the passthrough primary (strict greater-than to
114
+ // preserve passthrough preference on ties), promote it and demote the
115
+ // original primary into alternatives, re-sort, slice to top-3.
116
+ //
117
+ // NON-EXECUTION GUARDRAIL (#678, PRD §2 line 56 / §4 line 244): read-only
118
+ // precursor modes (discovery / plan-retro) must NEVER be scoring-promoted
119
+ // into the primary executed `mode`. They stay surfaceable as SUGGESTIONS in
120
+ // the alternatives[] list, but the swap candidate is the highest-confidence
121
+ // EXECUTABLE alternative only. This is guard (b): exclude precursors from
122
+ // the global-max promotion (the alternatives list itself is unchanged).
123
+ const promotable = alternatives.find((a) => !isNonExecutionMode(a.mode));
124
+ if (promotable !== undefined && promotable.confidence > confidence) {
125
+ const promoted = promotable;
126
+ const demoted = { mode: m, confidence };
127
+ // Remove the promoted alternative by reference (it may not be at index 0
128
+ // once precursors are skipped), then fold the demoted primary back in.
129
+ // Precursor alternatives are retained here so they remain SUGGESTIONS.
130
+ const reranked = [demoted, ...alternatives.filter((a) => a !== promoted)]
131
+ .filter((e) => e.confidence >= 0.1)
132
+ .sort((a, b) => b.confidence - a.confidence)
133
+ .slice(0, 3);
134
+ return {
135
+ mode: promoted.mode,
136
+ rationale: `global-max swap: ${promoted.mode} (${promoted.confidence}) outranked passthrough ${m} (${confidence})`.slice(0, 120),
137
+ confidence: promoted.confidence,
138
+ alternatives: reranked,
139
+ context_pressure: pressure,
140
+ };
141
+ }
142
+
143
+ return {
144
+ mode: m,
145
+ rationale,
146
+ confidence,
147
+ alternatives,
148
+ context_pressure: pressure,
149
+ };
150
+ }
151
+
152
+ // Branch 4 — DEFAULT: no valid mode signal and no spiral/carryover trigger
153
+ return {
154
+ mode: DEFAULT_MODE,
155
+ rationale: 'missing/invalid recommendedMode → default',
156
+ confidence: 0.0,
157
+ alternatives: [],
158
+ context_pressure: computeContextPressure(signals),
159
+ };
160
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * scripts/lib/multi-provider-build/providers.mjs
3
+ *
4
+ * Provider configuration for the single-source → many-provider build PoC.
5
+ *
6
+ * Scope: the THREE harnesses session-orchestrator actually targets
7
+ * (Claude Code primary, Codex CLI, Cursor IDE). Inspired by pbakaus/impeccable's
8
+ * 12-provider build (Apache-2.0) — we deliberately keep the templating mechanic
9
+ * and drop the 12-provider breadth (maintenance ≫ value for providers with ~0
10
+ * users; see the linked backlog issue's overengineering verdict).
11
+ *
12
+ * Each provider entry:
13
+ * {
14
+ * key, // canonical id used in build output paths
15
+ * tags, // <tag> block markers this provider keeps (rest are stripped)
16
+ * configDir, // on-disk harness dir
17
+ * placeholders: { model, configFile, commandPrefix, askInstruction }
18
+ * }
19
+ */
20
+
21
+ /** @typedef {{key:string, tags:string[], configDir:string, placeholders:{model:string, configFile:string, commandPrefix:string, askInstruction:string}}} ProviderConfig */
22
+
23
+ /** @type {Record<string, ProviderConfig>} */
24
+ export const PROVIDERS = {
25
+ 'claude-code': {
26
+ key: 'claude-code',
27
+ tags: ['claude-code', 'claude'],
28
+ configDir: '.claude',
29
+ placeholders: {
30
+ model: 'Claude',
31
+ configFile: 'CLAUDE.md',
32
+ commandPrefix: '/',
33
+ askInstruction: 'STOP and call the AskUserQuestion tool to clarify.',
34
+ },
35
+ },
36
+ codex: {
37
+ key: 'codex',
38
+ tags: ['codex'],
39
+ configDir: '.codex',
40
+ placeholders: {
41
+ model: 'GPT',
42
+ configFile: 'AGENTS.md',
43
+ commandPrefix: '$',
44
+ askInstruction: "STOP and use Codex's structured user-input tool to clarify.",
45
+ },
46
+ },
47
+ cursor: {
48
+ key: 'cursor',
49
+ tags: ['cursor'],
50
+ configDir: '.cursor',
51
+ placeholders: {
52
+ model: 'the model',
53
+ configFile: '.cursorrules',
54
+ commandPrefix: '/',
55
+ askInstruction: 'ask the user directly to clarify before proceeding.',
56
+ },
57
+ },
58
+ };
59
+
60
+ /** The full set of recognized provider block tags across ALL providers. */
61
+ export const ALL_BLOCK_TAGS = new Set(Object.values(PROVIDERS).flatMap((p) => p.tags));
62
+
63
+ /** Provider keys in a stable order. */
64
+ export const PROVIDER_KEYS = Object.keys(PROVIDERS);
@@ -0,0 +1,130 @@
1
+ /**
2
+ * scripts/lib/multi-provider-build/templating.mjs
3
+ *
4
+ * Single-source → many-provider templating (PoC). One source document with
5
+ * provider-conditional blocks + placeholders renders to a provider-specific
6
+ * artifact. This replaces the "maintain N near-identical copies by hand" model
7
+ * our codex-install.mjs / cursor-install.mjs currently imply.
8
+ *
9
+ * Two primitives (clean-room reimplementation of impeccable's mechanic):
10
+ * 1. compileProviderBlocks(content, activeTags)
11
+ * <codex> … </codex> blocks: keep body iff the tag is active, else drop.
12
+ * Unknown tags are left untouched (so real HTML/JSX isn't mangled).
13
+ * 2. replacePlaceholders(content, providerKey, opts)
14
+ * {{model}} {{config_file}} {{command_prefix}} {{ask_instruction}}
15
+ * {{available_commands}} substitution + optional /cmd → $cmd rewrite.
16
+ *
17
+ * renderForProvider() composes both in the correct order (blocks first, then
18
+ * placeholders — matching impeccable's pipeline).
19
+ */
20
+
21
+ import { PROVIDERS, ALL_BLOCK_TAGS } from './providers.mjs';
22
+
23
+ /**
24
+ * Keep `<tag>…</tag>` blocks whose tag is in `activeTags`; strip the rest.
25
+ * Only tags in `knownTags` are treated as conditional blocks — any other
26
+ * `<foo>…</foo>` (e.g. real markup) is left exactly as-is.
27
+ *
28
+ * Tags must sit on their own line, e.g.:
29
+ * <codex>
30
+ * Codex-only text.
31
+ * </codex>
32
+ *
33
+ * @param {string} content
34
+ * @param {Iterable<string>} activeTags
35
+ * @param {Iterable<string>} [knownTags] — defaults to ALL_BLOCK_TAGS
36
+ * @returns {string}
37
+ */
38
+ export function compileProviderBlocks(content, activeTags, knownTags = ALL_BLOCK_TAGS) {
39
+ const active = new Set(activeTags);
40
+ const known = new Set(knownTags);
41
+ let compiledAny = false;
42
+
43
+ // Match a block: leading newline (or start), <tag> on its own line, body,
44
+ // </tag> on its own line. Non-greedy body; the backreference enforces matching.
45
+ const blockRe = /(^|\r?\n)[ \t]*<([a-z][a-z0-9-]*)>[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*<\/\2>[ \t]*(?=\r?\n|$)/g;
46
+
47
+ const out = content.replace(blockRe, (match, prefix, tag, body) => {
48
+ if (!known.has(tag)) return match; // not a provider block — leave untouched
49
+ compiledAny = true;
50
+ return active.has(tag) ? `${prefix}${body}` : prefix;
51
+ });
52
+
53
+ // Collapse the 3+ blank-line runs that stripping can leave behind.
54
+ return compiledAny ? out.replace(/(\r?\n){3,}/g, '\n\n') : out;
55
+ }
56
+
57
+ /**
58
+ * Substitute {{placeholders}} for a provider and (optionally) rewrite command
59
+ * invocations from `/name` to the provider's prefix.
60
+ *
61
+ * @param {string} content
62
+ * @param {string} providerKey
63
+ * @param {{ commandNames?: string[] }} [opts]
64
+ * @returns {string}
65
+ */
66
+ export function replacePlaceholders(content, providerKey, opts = {}) {
67
+ const provider = PROVIDERS[providerKey];
68
+ if (!provider) throw new Error(`Unknown provider: ${providerKey}`);
69
+ const { model, configFile, commandPrefix, askInstruction } = provider.placeholders;
70
+ const commandNames = opts.commandNames ?? [];
71
+
72
+ const availableCommands = commandNames.map((n) => `${commandPrefix}${n}`).join(', ');
73
+
74
+ let result = content
75
+ .replace(/\{\{model\}\}/g, model)
76
+ .replace(/\{\{config_file\}\}/g, configFile)
77
+ .replace(/\{\{ask_instruction\}\}/g, askInstruction)
78
+ .replace(/\{\{available_commands\}\}/g, availableCommands)
79
+ .replace(/\{\{command_prefix\}\}/g, commandPrefix);
80
+
81
+ // Rewrite `/cmd` invocations to the provider prefix (e.g. Codex uses `$`).
82
+ // Longest names first so `/session-end` is rewritten before `/session`.
83
+ if (commandPrefix !== '/' && commandNames.length > 0) {
84
+ const sorted = [...commandNames].sort((a, b) => b.length - a.length);
85
+ for (const name of sorted) {
86
+ // `/name` where name is followed by a non-identifier char or end.
87
+ const re = new RegExp(`\\/(${escapeRegex(name)})(?=[^a-zA-Z0-9_-]|$)`, 'g');
88
+ // Use a replacement FUNCTION, not a string — a `$` commandPrefix would
89
+ // otherwise collide with String.replace's `$$`/`$1` escape syntax.
90
+ result = result.replace(re, (_match, g1) => `${commandPrefix}${g1}`);
91
+ }
92
+ }
93
+
94
+ return result;
95
+ }
96
+
97
+ /**
98
+ * Render a source document for a single provider: compile blocks, then
99
+ * substitute placeholders.
100
+ *
101
+ * @param {string} source
102
+ * @param {string} providerKey
103
+ * @param {{ commandNames?: string[] }} [opts]
104
+ * @returns {string}
105
+ */
106
+ export function renderForProvider(source, providerKey, opts = {}) {
107
+ const provider = PROVIDERS[providerKey];
108
+ if (!provider) throw new Error(`Unknown provider: ${providerKey}`);
109
+ const compiled = compileProviderBlocks(source, provider.tags);
110
+ return replacePlaceholders(compiled, providerKey, opts);
111
+ }
112
+
113
+ /**
114
+ * Render a source for every configured provider.
115
+ * @param {string} source
116
+ * @param {{ commandNames?: string[] }} [opts]
117
+ * @returns {Record<string,string>} keyed by provider key
118
+ */
119
+ export function renderAll(source, opts = {}) {
120
+ const out = {};
121
+ for (const key of Object.keys(PROVIDERS)) {
122
+ out[key] = renderForProvider(source, key, opts);
123
+ }
124
+ return out;
125
+ }
126
+
127
+ /** @param {string} s */
128
+ function escapeRegex(s) {
129
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
130
+ }
@@ -0,0 +1,233 @@
1
+ /**
2
+ * named-baseline-resolver.mjs — Per-context plan-baseline resolution (Issue #819).
3
+ *
4
+ * Cousin of `named-vault-resolver.mjs`. Where the vault resolver matches a repo
5
+ * to a named vault by its git-remote org/repo slug, this resolver matches the
6
+ * current working directory to a named baseline by a local FILESYSTEM directory
7
+ * prefix. Each named baseline is declared in the host-local `owner.yaml` under an
8
+ * optional `baselines:` list. When `baselines:` is absent, every export degrades
9
+ * gracefully to a null-fallback — absent-tolerant, never throws.
10
+ *
11
+ * ── Deliberate divergences from named-vault-resolver ─────────────────────────
12
+ *
13
+ * - Match key is `path-prefix` (a local directory tree like `~/Projects/private-world`),
14
+ * NOT `org-prefix` (which matches git-remote slugs). Baseline selection is by
15
+ * directory tree, so no git calls are needed — this module is pure/synchronous.
16
+ * - Entry field is `path` (a single directory), replacing vaults' `root` + `suffix`.
17
+ * - `match` is REQUIRED: a baseline with no `path-prefix` can never be selected, so
18
+ * it is dropped-and-WARNed rather than kept (vaults keep entries without a match).
19
+ *
20
+ * ── Precedence (implemented by resolveNamedBaseline) ─────────────────────────
21
+ *
22
+ * The caller (scripts/lib/config.mjs) owns the full plan-baseline-path chain:
23
+ * 1. SO_BASELINE_PATH env (highest)
24
+ * 2. baselines: match (this module → {source:'match'})
25
+ * 3. owner.yaml paths.baseline-path (legacy)
26
+ * 4. committed Session Config value
27
+ *
28
+ * This module implements tier 2 only. As a self-contained, testable contract it
29
+ * also YIELDS to tier 1: when SO_BASELINE_PATH is set (non-blank), resolveNamedBaseline
30
+ * returns the null-fallback ({source:null}) so the caller's env tier wins.
31
+ *
32
+ * ── Exports ──────────────────────────────────────────────────────────────────
33
+ *
34
+ * parseBaselines(ownerConfig)
35
+ * matchBaselineForPath(absPath, baselines)
36
+ * resolveNamedBaseline({ cwd, ownerConfig, env })
37
+ */
38
+
39
+ import { normalize, sep } from 'node:path';
40
+ import { expandTilde } from './common.mjs';
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // Internal helpers
44
+ // ---------------------------------------------------------------------------
45
+
46
+ /** @param {unknown} v */
47
+ function isPlainObject(v) {
48
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
49
+ }
50
+
51
+ /**
52
+ * Tilde-expand + normalize a filesystem path, stripping any trailing separator
53
+ * (but preserving the filesystem root). Used to canonicalise BOTH the target
54
+ * path and each configured prefix before a directory-prefix comparison.
55
+ *
56
+ * @param {unknown} p
57
+ * @returns {string}
58
+ */
59
+ function _normalizePath(p) {
60
+ const expanded = expandTilde(String(p ?? ''));
61
+ const normalized = normalize(expanded);
62
+ if (normalized.length > 1 && normalized.endsWith(sep)) {
63
+ return normalized.slice(0, -1);
64
+ }
65
+ return normalized;
66
+ }
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // parseBaselines — PURE
70
+ // ---------------------------------------------------------------------------
71
+
72
+ /**
73
+ * Extract and validate the `baselines:` list from a raw ownerConfig object.
74
+ *
75
+ * Drop-and-WARN on malformed entries; never throw. Returns [] when the section
76
+ * is absent, null, or empty — the backward-compat no-op path.
77
+ *
78
+ * Each valid entry: { name: string, path: string, match: { 'path-prefix': string } }
79
+ *
80
+ * @param {object|undefined} ownerConfig — raw parsed owner.yaml (NOT merged with defaults)
81
+ * @returns {Array<{name:string, path:string, match:{'path-prefix':string}}>}
82
+ */
83
+ export function parseBaselines(ownerConfig) {
84
+ const raw = ownerConfig?.baselines;
85
+
86
+ // Absent or explicit null/empty → no-op
87
+ if (raw === undefined || raw === null) return [];
88
+ if (Array.isArray(raw) && raw.length === 0) return [];
89
+
90
+ if (!Array.isArray(raw)) {
91
+ process.stderr.write(
92
+ 'WARN named-baseline-resolver: owner.yaml baselines: must be an array; ignoring\n',
93
+ );
94
+ return [];
95
+ }
96
+
97
+ const result = [];
98
+ for (let i = 0; i < raw.length; i++) {
99
+ const entry = raw[i];
100
+ if (!isPlainObject(entry)) {
101
+ process.stderr.write(
102
+ `WARN named-baseline-resolver: owner.yaml baselines[${i}] is not an object; dropping\n`,
103
+ );
104
+ continue;
105
+ }
106
+
107
+ const { name, path: entryPath, match } = entry;
108
+
109
+ if (typeof name !== 'string' || name.trim() === '') {
110
+ process.stderr.write(
111
+ `WARN named-baseline-resolver: owner.yaml baselines[${i}].name must be a non-empty string; dropping entry\n`,
112
+ );
113
+ continue;
114
+ }
115
+ if (typeof entryPath !== 'string' || entryPath.trim() === '') {
116
+ process.stderr.write(
117
+ `WARN named-baseline-resolver: owner.yaml baselines[${i}].path must be a non-empty string; dropping entry\n`,
118
+ );
119
+ continue;
120
+ }
121
+
122
+ // match is REQUIRED (unlike vaults) — a baseline with no path-prefix can
123
+ // never be selected, so it is dropped rather than kept.
124
+ if (!isPlainObject(match)) {
125
+ process.stderr.write(
126
+ `WARN named-baseline-resolver: owner.yaml baselines[${i}].match must be an object; dropping entry\n`,
127
+ );
128
+ continue;
129
+ }
130
+ const pathPrefix = match['path-prefix'];
131
+ if (typeof pathPrefix !== 'string' || pathPrefix.trim() === '') {
132
+ process.stderr.write(
133
+ `WARN named-baseline-resolver: owner.yaml baselines[${i}].match.path-prefix must be a non-empty string; dropping entry\n`,
134
+ );
135
+ continue;
136
+ }
137
+
138
+ result.push({
139
+ name: name.trim(),
140
+ path: entryPath.trim(),
141
+ match: { 'path-prefix': pathPrefix.trim() },
142
+ });
143
+ }
144
+
145
+ return result;
146
+ }
147
+
148
+ // ---------------------------------------------------------------------------
149
+ // matchBaselineForPath — PURE
150
+ // ---------------------------------------------------------------------------
151
+
152
+ /**
153
+ * Find the first named baseline whose `match.path-prefix` is a directory-prefix
154
+ * of the given absolute path. Both the path and each prefix are tilde-expanded
155
+ * and path-normalized before comparison.
156
+ *
157
+ * A prefix matches when the target path IS the prefix, or starts with
158
+ * `prefix + path.sep` (so `/a/b` matches `/a/b` and `/a/b/c`, but NOT `/a/bc`).
159
+ *
160
+ * First-match-wins. On an ambiguous multi-match, emits a WARN (never throws) and
161
+ * returns the first match.
162
+ *
163
+ * @param {string} absPath — the working directory to classify
164
+ * @param {Array<{name:string, path:string, match:{'path-prefix':string}}>} baselines
165
+ * @returns {{name:string, path:string, match:{'path-prefix':string}}|null}
166
+ */
167
+ export function matchBaselineForPath(absPath, baselines) {
168
+ if (!absPath || !Array.isArray(baselines) || baselines.length === 0) return null;
169
+
170
+ const target = _normalizePath(absPath);
171
+ const matched = [];
172
+
173
+ for (const b of baselines) {
174
+ const prefixRaw = b?.match?.['path-prefix'];
175
+ if (typeof prefixRaw !== 'string' || prefixRaw.trim() === '') continue;
176
+ const prefix = _normalizePath(prefixRaw);
177
+ if (target === prefix || target.startsWith(`${prefix}${sep}`)) {
178
+ matched.push(b);
179
+ }
180
+ }
181
+
182
+ if (matched.length > 1) {
183
+ process.stderr.write(
184
+ `WARN named-baseline-resolver: multiple baselines match path "${absPath}": ${matched
185
+ .map((b) => b.name)
186
+ .join(', ')}; using first match "${matched[0].name}"\n`,
187
+ );
188
+ }
189
+
190
+ return matched.length > 0 ? matched[0] : null;
191
+ }
192
+
193
+ // ---------------------------------------------------------------------------
194
+ // resolveNamedBaseline — main resolution entry point (tier 2)
195
+ // ---------------------------------------------------------------------------
196
+
197
+ /**
198
+ * Resolve the `baselines:` match tier for a given cwd.
199
+ *
200
+ * Returns:
201
+ * { path, name, source:'match' } when a baseline directory-prefix matches cwd.
202
+ * { path:null, name:null, source:null } (the null-fallback) otherwise — including
203
+ * when SO_BASELINE_PATH env is set (this tier yields to the higher env tier the
204
+ * caller owns), when no `baselines:` are configured, or when nothing matches.
205
+ *
206
+ * Pure + synchronous — no git calls, no disk reads. Never throws.
207
+ *
208
+ * @param {{
209
+ * cwd?: string,
210
+ * ownerConfig?: object,
211
+ * env?: Record<string, string|undefined>,
212
+ * }} [opts]
213
+ * @returns {{ path: string|null, name: string|null, source: 'match'|null }}
214
+ */
215
+ export function resolveNamedBaseline({
216
+ cwd = process.cwd(),
217
+ ownerConfig,
218
+ env = process.env,
219
+ } = {}) {
220
+ // Yield to the higher-precedence env tier the caller owns (SO_BASELINE_PATH).
221
+ const envVal = env?.SO_BASELINE_PATH;
222
+ if (typeof envVal === 'string' && envVal.trim() !== '') {
223
+ return { path: null, name: null, source: null };
224
+ }
225
+
226
+ const baselines = parseBaselines(ownerConfig);
227
+ const matched = baselines.length > 0 ? matchBaselineForPath(cwd, baselines) : null;
228
+ if (matched !== null) {
229
+ return { path: matched.path, name: matched.name, source: 'match' };
230
+ }
231
+
232
+ return { path: null, name: null, source: null };
233
+ }