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,224 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ecosystem-health.mjs — Plugin-monitor watcher for ecosystem-health skill.
4
+ *
5
+ * Runs as a persistent background process for the lifetime of the session
6
+ * (registered via .claude-plugin/plugin.json -> experimental.monitors path).
7
+ * Each NDJSON line written to stdout becomes a `<task_notification>` event
8
+ * Claude sees mid-session.
9
+ *
10
+ * Behaviour:
11
+ * - Watches .orchestrator/metrics/ecosystem-health.jsonl for state changes
12
+ * (line-count growth + last-line change detection).
13
+ * - If the state file does not exist yet, emits one `no-state-yet` event
14
+ * at startup and idles until it appears.
15
+ * - Coverage rule LM-002: stdout emits cover both progress AND failure
16
+ * cases. Errors during the watch loop are surfaced as `error` events,
17
+ * never silently swallowed (silence != success).
18
+ *
19
+ * Line-buffering contract:
20
+ * Every emit uses `process.stdout.write(line + '\n')` — one line per
21
+ * notification. Never console.log multi-line strings.
22
+ *
23
+ * Flags:
24
+ * --watch Run the watcher loop (required; no other mode supported).
25
+ * --interval=N Probe cadence in seconds (default 900 = 15min). Cron-style
26
+ * pre-warming pattern: keep cadence below any cache-related TTLs.
27
+ * --help Print usage to stderr and exit 0.
28
+ *
29
+ * Exit codes:
30
+ * 0 — clean shutdown (SIGTERM/SIGINT received).
31
+ * 1 — user/input error (unknown flag, --watch missing).
32
+ * 2 — system error (unexpected failure outside the watch loop).
33
+ *
34
+ * @typedef {Object} EmitEvent
35
+ * @property {string} event Event name (lowercase.dot.case).
36
+ * @property {string} ts ISO-8601 timestamp.
37
+ * @property {Record<string, unknown>} [details] Optional structured payload.
38
+ */
39
+
40
+ import { existsSync, statSync, readFileSync } from 'node:fs';
41
+ import { join } from 'node:path';
42
+
43
+ const DEFAULT_INTERVAL_S = 15 * 60; // 15min
44
+ const STATE_FILE_REL = '.orchestrator/metrics/ecosystem-health.jsonl';
45
+
46
+ /**
47
+ * Parse CLI args into a typed config object. No deps — node:util's parseArgs
48
+ * is overkill for this surface and adds 2 lines of overhead per call.
49
+ * @param {string[]} argv
50
+ * @returns {{ watch: boolean, intervalS: number, help: boolean }}
51
+ */
52
+ function parseArgs(argv) {
53
+ let watch = false;
54
+ let intervalS = DEFAULT_INTERVAL_S;
55
+ let help = false;
56
+ for (const arg of argv) {
57
+ if (arg === '--watch') {
58
+ watch = true;
59
+ } else if (arg === '--help' || arg === '-h') {
60
+ help = true;
61
+ } else if (arg.startsWith('--interval=')) {
62
+ const v = Number(arg.slice('--interval='.length));
63
+ if (!Number.isFinite(v) || v <= 0) {
64
+ process.stderr.write(`ecosystem-health: invalid --interval value: ${arg}\n`);
65
+ process.exit(1);
66
+ }
67
+ intervalS = v;
68
+ } else {
69
+ process.stderr.write(`ecosystem-health: unknown flag: ${arg}\n`);
70
+ process.exit(1);
71
+ }
72
+ }
73
+ return { watch, intervalS, help };
74
+ }
75
+
76
+ /**
77
+ * Emit one NDJSON line to stdout (one notification = one line).
78
+ * @param {EmitEvent} payload
79
+ */
80
+ function emit(payload) {
81
+ process.stdout.write(`${JSON.stringify(payload)}\n`);
82
+ }
83
+
84
+ /**
85
+ * Read state-file fingerprint (size + last-line) for change detection.
86
+ * @param {string} absPath
87
+ * @returns {{ exists: boolean, size: number, mtimeMs: number, lastLine: string | null }}
88
+ */
89
+ function fingerprint(absPath) {
90
+ if (!existsSync(absPath)) {
91
+ return { exists: false, size: 0, mtimeMs: 0, lastLine: null };
92
+ }
93
+ try {
94
+ const st = statSync(absPath);
95
+ // Tail read for last line — small file in practice (append-only JSONL).
96
+ // Reading full file is acceptable here at 15-min cadence.
97
+ let lastLine = null;
98
+ if (st.size > 0) {
99
+ const text = readFileSync(absPath, 'utf8');
100
+ const trimmed = text.replace(/\n$/, '');
101
+ const idx = trimmed.lastIndexOf('\n');
102
+ lastLine = idx === -1 ? trimmed : trimmed.slice(idx + 1);
103
+ }
104
+ return { exists: true, size: st.size, mtimeMs: st.mtimeMs, lastLine };
105
+ } catch (err) {
106
+ // Surface as an error event rather than silently returning a fake fingerprint.
107
+ emit({
108
+ event: 'error',
109
+ ts: new Date().toISOString(),
110
+ details: { phase: 'fingerprint', file: absPath, message: String(err?.message ?? err) },
111
+ });
112
+ return { exists: false, size: 0, mtimeMs: 0, lastLine: null };
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Main watch loop. Runs until SIGTERM/SIGINT.
118
+ * @param {number} intervalS
119
+ */
120
+ async function watchLoop(intervalS) {
121
+ const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || process.cwd();
122
+ const absPath = join(pluginRoot, STATE_FILE_REL);
123
+
124
+ // Startup event — confirms the watcher is alive even when nothing has
125
+ // happened yet. Without this, a "no events" stream is indistinguishable
126
+ // from a crashed monitor.
127
+ let prev = fingerprint(absPath);
128
+ emit({
129
+ event: prev.exists ? 'watcher.started' : 'no-state-yet',
130
+ ts: new Date().toISOString(),
131
+ details: { file: STATE_FILE_REL, intervalSeconds: intervalS, exists: prev.exists },
132
+ });
133
+
134
+ // Loop forever — the Claude harness sends SIGTERM on session-end and the
135
+ // process exits 0 via the signal handlers below.
136
+ while (true) {
137
+ await sleep(intervalS * 1000);
138
+ const next = fingerprint(absPath);
139
+ if (!prev.exists && next.exists) {
140
+ emit({
141
+ event: 'state-file.appeared',
142
+ ts: new Date().toISOString(),
143
+ details: { file: STATE_FILE_REL, size: next.size },
144
+ });
145
+ } else if (prev.exists && !next.exists) {
146
+ emit({
147
+ event: 'state-file.disappeared',
148
+ ts: new Date().toISOString(),
149
+ details: { file: STATE_FILE_REL },
150
+ });
151
+ } else if (next.exists && (next.size !== prev.size || next.lastLine !== prev.lastLine)) {
152
+ emit({
153
+ event: 'state.changed',
154
+ ts: new Date().toISOString(),
155
+ details: {
156
+ file: STATE_FILE_REL,
157
+ sizeDelta: next.size - prev.size,
158
+ lastLine: next.lastLine,
159
+ },
160
+ });
161
+ }
162
+ prev = next;
163
+ }
164
+ }
165
+
166
+ /**
167
+ * @param {number} ms
168
+ * @returns {Promise<void>}
169
+ */
170
+ function sleep(ms) {
171
+ return new Promise((resolve) => {
172
+ const t = setTimeout(resolve, ms);
173
+ t.unref?.();
174
+ });
175
+ }
176
+
177
+ function main() {
178
+ const args = parseArgs(process.argv.slice(2));
179
+ if (args.help) {
180
+ process.stderr.write(
181
+ [
182
+ 'Usage: ecosystem-health.mjs --watch [--interval=<seconds>]',
183
+ '',
184
+ 'Plugin-monitor watcher for the ecosystem-health skill. Persistent',
185
+ 'background process; one NDJSON line per state change → stdout.',
186
+ '',
187
+ 'Flags:',
188
+ ' --watch Required. Run the watch loop.',
189
+ ' --interval=<s> Probe cadence in seconds (default 900).',
190
+ ' --help, -h Print this message.',
191
+ '',
192
+ 'Exit codes: 0 clean / 1 user-error / 2 system-error.',
193
+ ].join('\n') + '\n',
194
+ );
195
+ process.exit(0);
196
+ }
197
+ if (!args.watch) {
198
+ process.stderr.write('ecosystem-health: --watch is required\n');
199
+ process.exit(1);
200
+ }
201
+
202
+ // Graceful shutdown — Claude harness sends SIGTERM at session-end.
203
+ const shutdown = (sig) => {
204
+ emit({
205
+ event: 'watcher.shutdown',
206
+ ts: new Date().toISOString(),
207
+ details: { signal: sig },
208
+ });
209
+ process.exit(0);
210
+ };
211
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
212
+ process.on('SIGINT', () => shutdown('SIGINT'));
213
+
214
+ watchLoop(args.intervalS).catch((err) => {
215
+ emit({
216
+ event: 'error',
217
+ ts: new Date().toISOString(),
218
+ details: { phase: 'watchLoop', message: String(err?.message ?? err) },
219
+ });
220
+ process.exit(2);
221
+ });
222
+ }
223
+
224
+ main();
@@ -0,0 +1,18 @@
1
+ /**
2
+ * ci-detector.mjs — detects CI provider from repo structure.
3
+ * Checks for .gitlab-ci.yml (GitLab) or .github/workflows/ (GitHub).
4
+ */
5
+
6
+ import { existsSync } from 'node:fs';
7
+ import { join } from 'node:path';
8
+
9
+ /**
10
+ * Detects CI provider from repo structure.
11
+ * @param {string} repoRoot
12
+ * @returns {'gitlab' | 'github' | 'none'}
13
+ */
14
+ export function detectCiProvider(repoRoot) {
15
+ if (existsSync(join(repoRoot, '.gitlab-ci.yml'))) return 'gitlab';
16
+ if (existsSync(join(repoRoot, '.github', 'workflows'))) return 'github';
17
+ return 'none';
18
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * config-parser.mjs — pure parsing utilities for comma-separated user input.
3
+ * Converts raw wizard answer strings into typed endpoint/pipeline/label arrays.
4
+ */
5
+
6
+ /**
7
+ * Parses a comma-separated string into a trimmed array, filtering empty items.
8
+ * @param {string} input
9
+ * @returns {string[]}
10
+ */
11
+ export function parseCommaSeparated(input) {
12
+ return input
13
+ .split(',')
14
+ .map((s) => s.trim())
15
+ .filter((s) => s.length > 0);
16
+ }
17
+
18
+ /**
19
+ * Parses endpoint input lines. Format: "Name|URL" per entry, separated by commas.
20
+ * @param {string} input
21
+ * @returns {Array<{name: string, url: string}>}
22
+ */
23
+ export function parseEndpoints(input) {
24
+ return parseCommaSeparated(input)
25
+ .map((entry) => {
26
+ const pipe = entry.indexOf('|');
27
+ if (pipe === -1) return null;
28
+ const name = entry.slice(0, pipe).trim();
29
+ const url = entry.slice(pipe + 1).trim();
30
+ if (!name || !url) return null;
31
+ return { name, url };
32
+ })
33
+ .filter(Boolean);
34
+ }
35
+
36
+ /**
37
+ * Parses pipeline input lines. Format: "id" or "id:label" per entry.
38
+ * @param {string} input
39
+ * @returns {Array<{id: string, label?: string}>}
40
+ */
41
+ export function parsePipelines(input) {
42
+ return parseCommaSeparated(input)
43
+ .map((entry) => {
44
+ const colon = entry.indexOf(':');
45
+ if (colon === -1) {
46
+ return entry.trim() ? { id: entry.trim() } : null;
47
+ }
48
+ const id = entry.slice(0, colon).trim();
49
+ const label = entry.slice(colon + 1).trim();
50
+ if (!id) return null;
51
+ return label ? { id, label } : { id };
52
+ })
53
+ .filter(Boolean);
54
+ }
@@ -0,0 +1,287 @@
1
+ /**
2
+ * config-writer.mjs — validates ecosystem policy shape and writes artifacts:
3
+ * .orchestrator/policy/ecosystem.json and the ecosystem-health block in Session Config.
4
+ */
5
+
6
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
7
+ import { join } from 'node:path';
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Validation
11
+ // ---------------------------------------------------------------------------
12
+
13
+ /** @param {unknown} arr @param {string} field @param {string[]} errors */
14
+ function _validateEndpoints(arr, field, errors) {
15
+ if (!Array.isArray(arr)) { errors.push(`${field} must be an array`); return; }
16
+ for (let i = 0; i < arr.length; i++) {
17
+ const ep = arr[i];
18
+ if (ep === null || typeof ep !== 'object' || Array.isArray(ep)) {
19
+ errors.push(`${field}[${i}] must be a plain object`); continue;
20
+ }
21
+ if (typeof ep['name'] !== 'string' || ep['name'].trim() === '')
22
+ errors.push(`${field}[${i}].name must be a non-empty string`);
23
+ if (typeof ep['url'] !== 'string' || ep['url'].trim() === '')
24
+ errors.push(`${field}[${i}].url must be a non-empty string`);
25
+ }
26
+ }
27
+
28
+ /** @param {unknown} arr @param {string} field @param {string[]} errors */
29
+ function _validatePipelines(arr, field, errors) {
30
+ if (!Array.isArray(arr)) { errors.push(`${field} must be an array`); return; }
31
+ for (let i = 0; i < arr.length; i++) {
32
+ const pl = arr[i];
33
+ if (pl === null || typeof pl !== 'object' || Array.isArray(pl)) {
34
+ errors.push(`${field}[${i}] must be a plain object`); continue;
35
+ }
36
+ if (typeof pl['id'] !== 'string' || pl['id'].trim() === '')
37
+ errors.push(`${field}[${i}].id must be a non-empty string`);
38
+ }
39
+ }
40
+
41
+ /** @param {unknown} arr @param {string} field @param {string[]} errors */
42
+ function _validateLabels(arr, field, errors) {
43
+ if (!Array.isArray(arr)) { errors.push(`${field} must be an array`); return; }
44
+ for (let i = 0; i < arr.length; i++) {
45
+ if (typeof arr[i] !== 'string' || arr[i].trim() === '')
46
+ errors.push(`${field}[${i}] must be a non-empty string`);
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Validates the ecosystem policy shape.
52
+ * Returns [] when valid; an array of error strings when invalid.
53
+ *
54
+ * @param {unknown} policy
55
+ * @returns {string[]}
56
+ */
57
+ export function validateEcosystemPolicy(policy) {
58
+ const errors = [];
59
+ if (policy === null || typeof policy !== 'object' || Array.isArray(policy)) {
60
+ errors.push('policy must be a plain object');
61
+ return errors;
62
+ }
63
+ if (policy['version'] !== 1) {
64
+ errors.push(`version must be 1, got ${JSON.stringify(policy['version'])}`);
65
+ }
66
+ if (policy['endpoints'] !== undefined) _validateEndpoints(policy['endpoints'], 'endpoints', errors);
67
+ if (policy['pipelines'] !== undefined) _validatePipelines(policy['pipelines'], 'pipelines', errors);
68
+ if (policy['criticalIssueLabels'] !== undefined)
69
+ _validateLabels(policy['criticalIssueLabels'], 'criticalIssueLabels', errors);
70
+ return errors;
71
+ }
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Session Config reader/writer
75
+ // ---------------------------------------------------------------------------
76
+
77
+ /**
78
+ * Returns whether the Session Config section in `text` already contains an
79
+ * ecosystem-health key.
80
+ * @param {string} text
81
+ * @param {RegExpMatchArray|null} startMatch
82
+ * @returns {boolean}
83
+ */
84
+ function _ecosystemBlockPresent(text, startMatch) {
85
+ if (!startMatch || startMatch.index === undefined) return false;
86
+ const afterBlock = text.slice(startMatch.index + startMatch[0].length);
87
+ const nextHeadingMatch = afterBlock.match(/^## /m);
88
+ const blockContent = nextHeadingMatch ? afterBlock.slice(0, nextHeadingMatch.index) : afterBlock;
89
+ return /^\s*ecosystem-health\s*:/m.test(blockContent);
90
+ }
91
+
92
+ /**
93
+ * Replaces an existing ecosystem-health block in `text` with `snippetLines`.
94
+ * Returns the new text (which may equal `text` if the regex matched nothing different).
95
+ * @param {string} text
96
+ * @param {string[]} snippetLines
97
+ * @returns {string}
98
+ */
99
+ function _replaceEcosystemBlock(text, snippetLines) {
100
+ return text.replace(/^ecosystem-health:(?:\n(?!##|\S).*)*\n?/m, snippetLines.join('\n') + '\n');
101
+ }
102
+
103
+ /**
104
+ * Inserts a new ecosystem-health snippet into `text` within the Session Config
105
+ * section, or appends a new section when none exists.
106
+ * @param {string} text
107
+ * @param {RegExpMatchArray|null} startMatch
108
+ * @param {string[]} snippetLines
109
+ * @returns {string}
110
+ */
111
+ function _insertEcosystemBlock(text, startMatch, snippetLines) {
112
+ const snippet = '\n' + snippetLines.join('\n');
113
+ if (!startMatch || startMatch.index === undefined) {
114
+ return text + '\n## Session Config\n' + snippet + '\n';
115
+ }
116
+ const afterStartIdx = startMatch.index + startMatch[0].length;
117
+ const afterBlock = text.slice(afterStartIdx);
118
+ const nextHeadingMatch = afterBlock.match(/^## /m);
119
+ if (nextHeadingMatch && nextHeadingMatch.index !== undefined) {
120
+ const insertAt = afterStartIdx + nextHeadingMatch.index;
121
+ return text.slice(0, insertAt) + snippet + '\n' + text.slice(insertAt);
122
+ }
123
+ return text + snippet + '\n';
124
+ }
125
+
126
+ /**
127
+ * Builds the YAML snippet lines for an ecosystem-health block.
128
+ * @param {{endpoints: object[], pipelines: object[], criticalIssueLabels: string[]}} config
129
+ * @returns {string[]}
130
+ */
131
+ function _buildEcosystemSnippetLines(config) {
132
+ const lines = ['ecosystem-health:'];
133
+ if (config.endpoints.length > 0) {
134
+ lines.push(' health-endpoints:');
135
+ for (const ep of config.endpoints) {
136
+ lines.push(` - name: ${ep.name}`);
137
+ lines.push(` url: ${ep.url}`);
138
+ }
139
+ }
140
+ if (config.pipelines.length > 0) {
141
+ lines.push(' pipelines:');
142
+ for (const pl of config.pipelines) {
143
+ const label = pl.label ? ` # ${pl.label}` : '';
144
+ lines.push(` - id: ${pl.id}${label}`);
145
+ }
146
+ }
147
+ if (config.criticalIssueLabels.length > 0) {
148
+ lines.push(
149
+ ` critical-issue-labels: [${config.criticalIssueLabels.map((l) => JSON.stringify(l)).join(', ')}]`
150
+ );
151
+ }
152
+ return lines;
153
+ }
154
+
155
+ /**
156
+ * Resolves the config file path (CLAUDE.md or AGENTS.md).
157
+ * @param {string} repoRoot
158
+ * @returns {string|null}
159
+ */
160
+ export function resolveConfigFile(repoRoot) {
161
+ const claude = join(repoRoot, 'CLAUDE.md');
162
+ const agents = join(repoRoot, 'AGENTS.md');
163
+ if (existsSync(claude)) return claude;
164
+ if (existsSync(agents)) return agents;
165
+ return null;
166
+ }
167
+
168
+ /**
169
+ * Reads existing ecosystem-health config from the policy JSON file.
170
+ * Uses .orchestrator/policy/ecosystem.json as the reliable source of truth
171
+ * (valid JSON, precisely parseable). Returns null when missing or malformed.
172
+ *
173
+ * @param {string} repoRoot
174
+ * @returns {{endpoints: object[], pipelines: object[], criticalIssueLabels: string[]} | null}
175
+ */
176
+ export function readExistingEcosystemConfig(repoRoot) {
177
+ const policyPath = join(repoRoot, '.orchestrator', 'policy', 'ecosystem.json');
178
+ if (!existsSync(policyPath)) return null;
179
+ let parsed;
180
+ try {
181
+ parsed = JSON.parse(readFileSync(policyPath, 'utf8'));
182
+ } catch {
183
+ return null;
184
+ }
185
+ const errors = validateEcosystemPolicy(parsed);
186
+ if (errors.length > 0) return null;
187
+ return {
188
+ endpoints: Array.isArray(parsed.endpoints) ? parsed.endpoints : [],
189
+ pipelines: Array.isArray(parsed.pipelines) ? parsed.pipelines : [],
190
+ criticalIssueLabels: Array.isArray(parsed.criticalIssueLabels) ? parsed.criticalIssueLabels : [],
191
+ };
192
+ }
193
+
194
+ /**
195
+ * Writes (or updates) an `ecosystem-health:` block inside Session Config.
196
+ * When `overwrite` is true and an ecosystem-health block already exists, it is
197
+ * replaced with the new config (diff-aware merge). When `overwrite` is false
198
+ * and ecosystem-health already exists, the function skips (legacy behaviour).
199
+ *
200
+ * @param {string} configFilePath
201
+ * @param {{endpoints: object[], pipelines: object[], criticalIssueLabels: string[]}} config
202
+ * @param {boolean} dryRun
203
+ * @param {boolean} [overwrite=false]
204
+ * @returns {'written' | 'skipped' | 'error'}
205
+ */
206
+ export function writeSessionConfigBlock(configFilePath, config, dryRun, overwrite = false) {
207
+ let text;
208
+ try {
209
+ text = readFileSync(configFilePath, 'utf8');
210
+ } catch {
211
+ return 'error';
212
+ }
213
+
214
+ const startMatch = text.match(/^## Session Config[ \t]*(?:\r?\n|$)/m);
215
+ const snippetLines = _buildEcosystemSnippetLines(config);
216
+
217
+ if (_ecosystemBlockPresent(text, startMatch)) {
218
+ if (!overwrite) return 'skipped';
219
+ // Replace the existing ecosystem-health block with the new snippet.
220
+ // The block spans from "ecosystem-health:" to the next top-level key or heading.
221
+ const newText = _replaceEcosystemBlock(text, snippetLines);
222
+ // If text did not change after replacement (regex produced the same string), skip.
223
+ // Also skip if the only difference is trailing whitespace on the replaced block — this
224
+ // happens when the existing file has an equivalent but differently formatted placeholder.
225
+ if (newText === text) return 'skipped';
226
+ if (!dryRun) {
227
+ try { writeFileSync(configFilePath, newText, 'utf8'); } catch { return 'error'; }
228
+ }
229
+ return 'written';
230
+ }
231
+
232
+ // Insert path: append ecosystem-health block to Session Config section
233
+ const newText = _insertEcosystemBlock(text, startMatch, snippetLines);
234
+ if (!dryRun) {
235
+ try { writeFileSync(configFilePath, newText, 'utf8'); } catch { return 'error'; }
236
+ }
237
+ return 'written';
238
+ }
239
+
240
+ /**
241
+ * Writes .orchestrator/policy/ecosystem.json.
242
+ *
243
+ * @param {string} repoRoot
244
+ * @param {{endpoints: object[], pipelines: object[], criticalIssueLabels: string[]}} config
245
+ * @param {boolean} dryRun
246
+ * @returns {'written' | 'skipped' | 'error'}
247
+ */
248
+ export function writePolicyFile(repoRoot, config, dryRun) {
249
+ const policyDir = join(repoRoot, '.orchestrator', 'policy');
250
+ const policyPath = join(policyDir, 'ecosystem.json');
251
+
252
+ // Idempotency: read existing — if contents are identical, skip
253
+ if (existsSync(policyPath)) {
254
+ try {
255
+ const existing = JSON.parse(readFileSync(policyPath, 'utf8'));
256
+ // Re-check if it already has the same data (simple deep-equal via JSON round-trip)
257
+ const proposed = buildPolicyObject(config);
258
+ if (JSON.stringify(existing) === JSON.stringify(proposed)) {
259
+ return 'skipped';
260
+ }
261
+ } catch {
262
+ // malformed existing file — overwrite
263
+ }
264
+ }
265
+
266
+ const policy = buildPolicyObject(config);
267
+ if (!dryRun) {
268
+ try {
269
+ mkdirSync(policyDir, { recursive: true });
270
+ writeFileSync(policyPath, JSON.stringify(policy, null, 2) + '\n', 'utf8');
271
+ } catch {
272
+ return 'error';
273
+ }
274
+ }
275
+ return 'written';
276
+ }
277
+
278
+ export function buildPolicyObject(config) {
279
+ return {
280
+ version: 1,
281
+ rationale:
282
+ 'Ecosystem health configuration. Generated by /bootstrap --ecosystem-health. Hand-edit to add or remove endpoints.',
283
+ endpoints: config.endpoints,
284
+ pipelines: config.pipelines,
285
+ criticalIssueLabels: config.criticalIssueLabels,
286
+ };
287
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * package-manager-detector.mjs — detects package manager from lockfile presence
3
+ * and reads package.json script names for informational surfacing.
4
+ *
5
+ * A root lockfile that is gitignored is treated as absent (issue #715 bug
6
+ * class) — reuses the shared isIgnoredRootFile() helper from
7
+ * package-manager.mjs rather than re-implementing .gitignore parsing.
8
+ */
9
+
10
+ import { existsSync, readFileSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { isIgnoredRootFile } from '../package-manager.mjs';
13
+
14
+ /**
15
+ * Detects package manager from lockfile presence. A root lockfile that is
16
+ * gitignored is treated as absent.
17
+ * @param {string} repoRoot
18
+ * @returns {'pnpm' | 'yarn' | 'bun' | 'npm' | null}
19
+ */
20
+ export function detectPackageManagerFromRoot(repoRoot) {
21
+ if (existsSync(join(repoRoot, 'pnpm-lock.yaml')) && !isIgnoredRootFile(repoRoot, 'pnpm-lock.yaml')) return 'pnpm';
22
+ if (existsSync(join(repoRoot, 'yarn.lock')) && !isIgnoredRootFile(repoRoot, 'yarn.lock')) return 'yarn';
23
+ if (existsSync(join(repoRoot, 'bun.lockb')) && !isIgnoredRootFile(repoRoot, 'bun.lockb')) return 'bun';
24
+ if (existsSync(join(repoRoot, 'package-lock.json')) && !isIgnoredRootFile(repoRoot, 'package-lock.json')) return 'npm';
25
+ return null;
26
+ }
27
+
28
+ /**
29
+ * Reads package.json scripts to surface script names (informational).
30
+ * @param {string} repoRoot
31
+ * @returns {string[]}
32
+ */
33
+ export function readPackageScripts(repoRoot) {
34
+ const pkgPath = join(repoRoot, 'package.json');
35
+ if (!existsSync(pkgPath)) return [];
36
+ try {
37
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
38
+ return Object.keys(pkg.scripts || {});
39
+ } catch {
40
+ return [];
41
+ }
42
+ }