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,297 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * playwright-driver/runner.mjs — Phase 2 entry-point for the /test command.
4
+ *
5
+ * Spawns `npx playwright test` in the target repo directory, pipes output to
6
+ * ${RUN_DIR}/console.log, and exits with a deterministic exit code per the
7
+ * Composability Contract in skills/playwright-driver/SKILL.md.
8
+ *
9
+ * Exit codes:
10
+ * 0 — all tests passed
11
+ * 1 — at least one test failed (Playwright exit 1)
12
+ * 2 — framework error, timeout, spawn failure, or invalid profile
13
+ *
14
+ * CLI args (all also accepted via env vars as fallback):
15
+ * --run-dir <path> absolute path to artifact dir (env: RUN_DIR)
16
+ * --profile <name> profile name, e.g. "web-gate" (env: PROFILE)
17
+ * --target <path> absolute path to target repo (env: TARGET)
18
+ * --dry-run print resolved command, skip subprocess, exit 0
19
+ *
20
+ * DI seams for testability (all optional, accepted via opts object):
21
+ * opts.spawn — override node:child_process spawn
22
+ * opts.fs — override node:fs (sync subset: mkdirSync, createWriteStream, readFileSync, existsSync, writeFileSync)
23
+ *
24
+ * Issue: #385 — web-gate end-to-end proof against an EspoCRM web target
25
+ */
26
+
27
+ import { spawn as realSpawn } from 'node:child_process';
28
+ import realFs from 'node:fs';
29
+ import os from 'node:os';
30
+ import path from 'node:path';
31
+ import { parseArgs } from 'node:util';
32
+ import { getProfile, loadProfiles, validateProfile } from '../profiles/registry.mjs';
33
+ import { validatePathInsideProject } from '../path-utils.mjs';
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // Path resolution helper
37
+ // ---------------------------------------------------------------------------
38
+
39
+ /**
40
+ * Expand a leading `~` to $HOME; absolute paths pass through verbatim;
41
+ * relative paths are resolved against process.cwd().
42
+ * @param {string} p
43
+ * @returns {string}
44
+ */
45
+ function resolvePath(p) {
46
+ if (!p) return process.cwd();
47
+ if (p.startsWith('~/') || p === '~') {
48
+ return path.join(os.homedir(), p.slice(1));
49
+ }
50
+ if (path.isAbsolute(p)) return p;
51
+ return path.resolve(process.cwd(), p);
52
+ }
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // axe-core presence check
56
+ // ---------------------------------------------------------------------------
57
+
58
+ /**
59
+ * Check whether @axe-core/playwright is listed in the target's package.json.
60
+ * Returns true if present (or if package.json cannot be read — fail-open).
61
+ * @param {string} targetPath
62
+ * @param {{ readFileSync: Function, existsSync: Function }} fsImpl
63
+ * @returns {{ present: boolean, skipped: boolean }}
64
+ */
65
+ function checkAxeCore(targetPath, fsImpl) {
66
+ const pkgPath = path.join(targetPath, 'package.json');
67
+ if (!fsImpl.existsSync(pkgPath)) {
68
+ return { present: false, skipped: true };
69
+ }
70
+ let pkg;
71
+ try {
72
+ pkg = JSON.parse(fsImpl.readFileSync(pkgPath, 'utf8'));
73
+ } catch {
74
+ return { present: false, skipped: true };
75
+ }
76
+ const deps = pkg.dependencies ?? {};
77
+ const devDeps = pkg.devDependencies ?? {};
78
+ const present = '@axe-core/playwright' in deps || '@axe-core/playwright' in devDeps;
79
+ return { present, skipped: false };
80
+ }
81
+
82
+ // ---------------------------------------------------------------------------
83
+ // Main run() function
84
+ // ---------------------------------------------------------------------------
85
+
86
+ /**
87
+ * @param {object} [opts]
88
+ * @param {Function} [opts.spawn]
89
+ * @param {object} [opts.fs]
90
+ * @returns {Promise<void>}
91
+ */
92
+ export default async function run(opts = {}) {
93
+ const spawnFn = opts.spawn ?? realSpawn;
94
+ const fsImpl = opts.fs ?? realFs;
95
+
96
+ // -------------------------------------------------------------------------
97
+ // Parse CLI args + env fallbacks
98
+ // -------------------------------------------------------------------------
99
+
100
+ const { values } = parseArgs({
101
+ args: process.argv.slice(2),
102
+ options: {
103
+ 'run-dir': { type: 'string' },
104
+ 'profile': { type: 'string' },
105
+ 'target': { type: 'string' },
106
+ 'dry-run': { type: 'boolean', default: false },
107
+ },
108
+ strict: false,
109
+ });
110
+
111
+ const runDir = resolvePath(values['run-dir'] ?? process.env.RUN_DIR ?? '');
112
+ const profileName = values['profile'] ?? process.env.PROFILE ?? '';
113
+ const targetRaw = values['target'] ?? process.env.TARGET ?? '';
114
+ const dryRun = values['dry-run'] ?? false;
115
+
116
+ if (!runDir) {
117
+ console.error('runner: --run-dir (or env RUN_DIR) is required');
118
+ process.exit(2);
119
+ }
120
+
121
+ // SEC-PD-MED-2: reject runDir values containing commas or colons as defensive
122
+ // path-sanitization (original rationale: reporter comma+colon split is now obsolete
123
+ // after the 2026-05-14 deep-3 reporter fix — paths flow via env vars, not CLI string).
124
+ // Kept as belt-and-braces against pathological run-dirs; revisit alongside #390 path-traversal.
125
+ if (/[,:]/.test(runDir)) {
126
+ console.error('runner: --run-dir must not contain commas or colons');
127
+ process.exit(2);
128
+ }
129
+
130
+ // #398 / #402: path-traversal guard — runDir must be strictly inside
131
+ // .orchestrator/metrics/test-runs/ relative to cwd (CWE-22).
132
+ // Delegated to validatePathInsideProject (two-phase: lexical + realpath).
133
+ const testRunsRoot = path.resolve(process.cwd(), '.orchestrator/metrics/test-runs');
134
+ const result = validatePathInsideProject(runDir, testRunsRoot);
135
+ if (!result.ok) {
136
+ if (result.reason === 'symlink') {
137
+ console.error('runner: --run-dir resolves (via symlink) outside .orchestrator/metrics/test-runs');
138
+ } else {
139
+ console.error(`runner: --run-dir must be inside .orchestrator/metrics/test-runs/ (got: ${runDir})`);
140
+ }
141
+ process.exit(2);
142
+ }
143
+
144
+ if (!profileName) {
145
+ console.error('runner: --profile (or env PROFILE) is required');
146
+ process.exit(2);
147
+ }
148
+
149
+ // -------------------------------------------------------------------------
150
+ // Load + validate profile
151
+ // -------------------------------------------------------------------------
152
+
153
+ const loadResult = await loadProfiles();
154
+ if (!loadResult.ok) {
155
+ console.error(`runner: failed to load profiles — ${loadResult.error.message}`);
156
+ process.exit(2);
157
+ }
158
+
159
+ const getResult = getProfile(loadResult.profiles, profileName);
160
+ if (!getResult.ok) {
161
+ console.error(`runner: ${getResult.error.message}`);
162
+ process.exit(2);
163
+ }
164
+
165
+ const validateResult = validateProfile(getResult.profile);
166
+ if (!validateResult.ok) {
167
+ console.error(`runner: profile '${profileName}' is invalid — ${validateResult.error.message}`);
168
+ process.exit(2);
169
+ }
170
+
171
+ const profile = validateResult.value;
172
+
173
+ // -------------------------------------------------------------------------
174
+ // Resolve target path
175
+ // -------------------------------------------------------------------------
176
+
177
+ const targetPath = resolvePath(targetRaw || profile.target || process.cwd());
178
+
179
+ // -------------------------------------------------------------------------
180
+ // axe-core presence check
181
+ // -------------------------------------------------------------------------
182
+
183
+ const axe = checkAxeCore(targetPath, fsImpl);
184
+ if (!axe.present && !axe.skipped) {
185
+ console.log('axe-violations: skipped — @axe-core/playwright not installed in target');
186
+ }
187
+
188
+ // -------------------------------------------------------------------------
189
+ // Build Playwright args
190
+ // -------------------------------------------------------------------------
191
+
192
+ // Playwright reporter syntax: comma-separated reporter NAMES, paths via env vars.
193
+ // Canonical: https://playwright.dev/docs/test-reporters#html-reporter (PLAYWRIGHT_HTML_OUTPUT_DIR)
194
+ // and #json-reporter (PLAYWRIGHT_JSON_OUTPUT_FILE). The previous `html:<path>` form
195
+ // was Jest/Vitest syntax — Playwright rejected it as `Cannot find module 'html:<path>'`.
196
+ const playwrightArgs = [
197
+ 'playwright',
198
+ 'test',
199
+ '--output', path.join(runDir, 'test-results'),
200
+ '--reporter', 'html,json',
201
+ '--trace', 'on',
202
+ ];
203
+
204
+ if (profile.mode === 'headed') {
205
+ playwrightArgs.push('--headed');
206
+ }
207
+
208
+ if (dryRun) {
209
+ console.log('runner: dry-run mode — resolved command:');
210
+ console.log(` npx ${playwrightArgs.join(' ')}`);
211
+ console.log(` cwd: ${targetPath}`);
212
+ process.exit(0);
213
+ }
214
+
215
+ // -------------------------------------------------------------------------
216
+ // Create artifact directories
217
+ // -------------------------------------------------------------------------
218
+
219
+ fsImpl.mkdirSync(path.join(runDir, 'test-results'), { recursive: true });
220
+
221
+ // #396: pre-create artifact namespace directories so test fixtures don't fail
222
+ // on missing parent paths. `test-results/` is created by Playwright via --output.
223
+ // `console.log` is created by createWriteStream below. AX + screenshots dirs are
224
+ // written by fixtures — pre-creating ensures a clean artifact layout on every run.
225
+ fsImpl.mkdirSync(path.join(runDir, 'ax-snapshots'), { recursive: true });
226
+ fsImpl.mkdirSync(path.join(runDir, 'screenshots'), { recursive: true });
227
+
228
+ // -------------------------------------------------------------------------
229
+ // Spawn Playwright
230
+ // -------------------------------------------------------------------------
231
+
232
+ const controller = new AbortController();
233
+ const timeoutHandle = setTimeout(
234
+ () => controller.abort(),
235
+ profile.timeout_ms,
236
+ );
237
+
238
+ const logStream = fsImpl.createWriteStream(path.join(runDir, 'console.log'), { flags: 'a' });
239
+
240
+ const proc = spawnFn('npx', playwrightArgs, {
241
+ cwd: targetPath,
242
+ signal: controller.signal,
243
+ stdio: ['ignore', 'pipe', 'pipe'],
244
+ env: {
245
+ ...process.env,
246
+ PLAYWRIGHT_HTML_OUTPUT_DIR: path.join(runDir, 'report'),
247
+ PLAYWRIGHT_JSON_OUTPUT_FILE: path.join(runDir, 'results.json'),
248
+ PLAYWRIGHT_HTML_OPEN: 'never',
249
+ },
250
+ });
251
+
252
+ proc.stdout.pipe(logStream, { end: false });
253
+ proc.stderr.pipe(logStream, { end: false });
254
+
255
+ // -------------------------------------------------------------------------
256
+ // Exit-code resolution
257
+ // -------------------------------------------------------------------------
258
+
259
+ /**
260
+ * @param {number} mapped
261
+ */
262
+ function finish(mapped) {
263
+ clearTimeout(timeoutHandle);
264
+ logStream.end(() => {
265
+ fsImpl.writeFileSync(path.join(runDir, 'exit_code'), String(mapped));
266
+ process.exit(mapped);
267
+ });
268
+ }
269
+
270
+ proc.on('error', (err) => {
271
+ console.error(`runner: spawn error — ${err.message}`);
272
+ finish(2);
273
+ });
274
+
275
+ proc.on('close', (code, signal) => {
276
+ if (signal === 'SIGTERM' || code === null) {
277
+ finish(2);
278
+ } else if (code === 0) {
279
+ finish(0);
280
+ } else if (code === 1) {
281
+ finish(1);
282
+ } else {
283
+ finish(2);
284
+ }
285
+ });
286
+ }
287
+
288
+ // ---------------------------------------------------------------------------
289
+ // CLI entry-point
290
+ // ---------------------------------------------------------------------------
291
+
292
+ if (import.meta.url === `file://${process.argv[1]}`) {
293
+ run().catch((err) => {
294
+ console.error(`runner: unhandled error — ${err.message}`);
295
+ process.exit(2);
296
+ });
297
+ }
@@ -0,0 +1,210 @@
1
+ /**
2
+ * plugin-root.mjs — Robust plugin root resolution with layered fallback.
3
+ *
4
+ * Issue #212: manual installs may not have CLAUDE_PLUGIN_ROOT set. This module
5
+ * provides a deterministic, testable resolution strategy so hook handlers and
6
+ * scripts never silently fall back to an empty path or wrong directory.
7
+ *
8
+ * Fallback order (stops at first success):
9
+ * 1. PLUGIN_ROOT native env var
10
+ * 2. Compatibility root matching explicit SO_PLATFORM
11
+ * 3. Remaining Claude, Codex, Cursor, and Pi compatibility roots
12
+ * 4. Walk up from import.meta.url looking for package.json whose name === "session-orchestrator"
13
+ * 5. Walk up from process.cwd() looking for the same marker
14
+ *
15
+ * Throws PluginRootResolutionError when all resolution levels fail.
16
+ *
17
+ * Backward compat: without native or explicit platform inputs, compatibility
18
+ * roots retain their legacy Claude → Codex → Cursor → Pi order.
19
+ */
20
+
21
+ import { existsSync, readFileSync, statSync } from 'node:fs';
22
+ import path from 'node:path';
23
+ import { fileURLToPath } from 'node:url';
24
+
25
+ const COMPATIBILITY_ROOTS = [
26
+ ['claude', 'CLAUDE_PLUGIN_ROOT'],
27
+ ['codex', 'CODEX_PLUGIN_ROOT'],
28
+ ['cursor', 'CURSOR_RULES_DIR'],
29
+ ['pi', 'PI_PLUGIN_ROOT'],
30
+ ];
31
+ const VALID_PLATFORMS = new Set(COMPATIBILITY_ROOTS.map(([platform]) => platform));
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // PluginRootResolutionError
35
+ // ---------------------------------------------------------------------------
36
+
37
+ /**
38
+ * Thrown when all resolution levels fail. Callers may inspect
39
+ * `error.triedPaths` to understand what was attempted.
40
+ */
41
+ export class PluginRootResolutionError extends Error {
42
+ /**
43
+ * @param {string} message
44
+ * @param {string[]} triedPaths Directories / env vars that were checked
45
+ */
46
+ constructor(message, triedPaths = []) {
47
+ super(message);
48
+ this.name = 'PluginRootResolutionError';
49
+ this.triedPaths = triedPaths;
50
+ }
51
+ }
52
+
53
+ // ---------------------------------------------------------------------------
54
+ // Internal helpers
55
+ // ---------------------------------------------------------------------------
56
+
57
+ /**
58
+ * Return true when `dir` is an existing directory.
59
+ * @param {string} dir
60
+ * @returns {boolean}
61
+ */
62
+ function _isDir(dir) {
63
+ try { return statSync(dir).isDirectory(); } catch { return false; }
64
+ }
65
+
66
+ /**
67
+ * Return a trimmed allowlisted platform or null.
68
+ * @param {string|undefined} value
69
+ * @returns {"claude"|"codex"|"cursor"|"pi"|null}
70
+ */
71
+ function _validPlatform(value) {
72
+ const platform = (value || '').trim();
73
+ if (!VALID_PLATFORMS.has(platform)) return null;
74
+ return /** @type {"claude"|"codex"|"cursor"|"pi"} */ (platform);
75
+ }
76
+
77
+ /**
78
+ * Resolve one environment path, recording why it was skipped.
79
+ * @param {string} envName
80
+ * @param {string[]} tried
81
+ * @returns {string|null}
82
+ */
83
+ function _envDirectory(envName, tried) {
84
+ const rawValue = process.env[envName];
85
+ const value = (rawValue || '').trim();
86
+
87
+ if (!value) {
88
+ tried.push(rawValue === undefined
89
+ ? `${envName} (not set)`
90
+ : `${envName} (empty after trim)`);
91
+ return null;
92
+ }
93
+
94
+ if (_isDir(value)) return value;
95
+ tried.push(`${envName}=${value} (not a directory)`);
96
+ return null;
97
+ }
98
+
99
+ /**
100
+ * Order compatibility roots by explicit platform, then an optional caller hint,
101
+ * while retaining the legacy Claude → Codex → Cursor → Pi order for the rest.
102
+ * @param {string|undefined} platformHint
103
+ * @returns {Array<[string, string]>}
104
+ */
105
+ function _orderedCompatibilityRoots(platformHint) {
106
+ const preferredPlatform = _validPlatform(process.env.SO_PLATFORM) ?? _validPlatform(platformHint);
107
+ if (!preferredPlatform) return COMPATIBILITY_ROOTS;
108
+
109
+ const matching = COMPATIBILITY_ROOTS.filter(([platform]) => platform === preferredPlatform);
110
+ const remaining = COMPATIBILITY_ROOTS.filter(([platform]) => platform !== preferredPlatform);
111
+ return [...matching, ...remaining];
112
+ }
113
+
114
+ /**
115
+ * Return true when `dir` contains a package.json whose `name` field equals
116
+ * `"session-orchestrator"`. Silently returns false on any read/parse error.
117
+ *
118
+ * @param {string} dir Candidate directory to inspect
119
+ * @returns {boolean}
120
+ */
121
+ function _isPluginRoot(dir) {
122
+ try {
123
+ const pkgPath = path.join(dir, 'package.json');
124
+ if (!existsSync(pkgPath)) return false;
125
+ const raw = readFileSync(pkgPath, 'utf8');
126
+ const pkg = JSON.parse(raw);
127
+ return pkg.name === 'session-orchestrator';
128
+ } catch {
129
+ return false;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Walk up the directory tree from `startDir`, testing each directory with
135
+ * `_isPluginRoot`. Returns the matching directory path or `null`.
136
+ *
137
+ * Terminates at the filesystem root ("/", "C:\\", etc.) or when the parent
138
+ * path stops changing (guard against edge cases).
139
+ *
140
+ * @param {string} startDir Absolute directory to begin walking from
141
+ * @returns {string|null}
142
+ */
143
+ function _walkUp(startDir) {
144
+ let dir = path.resolve(startDir);
145
+ const root = path.parse(dir).root;
146
+
147
+ while (dir !== root) {
148
+ if (_isPluginRoot(dir)) return dir;
149
+ const parent = path.dirname(dir);
150
+ if (parent === dir) break; // safety guard
151
+ dir = parent;
152
+ }
153
+
154
+ // Check root itself
155
+ if (_isPluginRoot(root)) return root;
156
+
157
+ return null;
158
+ }
159
+
160
+ // ---------------------------------------------------------------------------
161
+ // resolvePluginRoot
162
+ // ---------------------------------------------------------------------------
163
+
164
+ /**
165
+ * Resolve the absolute path to the session-orchestrator plugin directory.
166
+ *
167
+ * Fallback order:
168
+ * 1. Trimmed native PLUGIN_ROOT when it is an existing directory
169
+ * 2. Compatibility root matching a valid explicit SO_PLATFORM
170
+ * 3. Remaining compatibility roots in legacy order
171
+ * 4. Walk up from import.meta.url (the location of this file) looking for a
172
+ * package.json with name "session-orchestrator"
173
+ * 5. Walk up from process.cwd() looking for the same marker
174
+ *
175
+ * @param {string} [platformHint] Optional compatibility hint for wrapper callers
176
+ * @returns {string} Absolute path to the plugin root
177
+ * @throws {PluginRootResolutionError} When all resolution levels fail
178
+ */
179
+ export function resolvePluginRoot(platformHint) {
180
+ const tried = [];
181
+
182
+ // Level 1: native root identifies location only; platform detection is separate.
183
+ const nativeRoot = _envDirectory('PLUGIN_ROOT', tried);
184
+ if (nativeRoot) return nativeRoot;
185
+
186
+ // Levels 2-5: prefer the compatibility root matching explicit SO_PLATFORM.
187
+ for (const [, envName] of _orderedCompatibilityRoots(platformHint)) {
188
+ const compatibilityRoot = _envDirectory(envName, tried);
189
+ if (compatibilityRoot) return compatibilityRoot;
190
+ }
191
+
192
+ // Level 6: walk up from this file's location
193
+ const thisDir = path.dirname(fileURLToPath(import.meta.url));
194
+ const byImportMeta = _walkUp(thisDir);
195
+ if (byImportMeta) return byImportMeta;
196
+ tried.push(`walk from import.meta.url (${thisDir}) — no package.json{name:session-orchestrator} found`);
197
+
198
+ // Level 7: walk up from cwd
199
+ const byCwd = _walkUp(process.cwd());
200
+ if (byCwd) return byCwd;
201
+ tried.push(`walk from cwd (${process.cwd()}) — no package.json{name:session-orchestrator} found`);
202
+
203
+ throw new PluginRootResolutionError(
204
+ 'Could not resolve session-orchestrator plugin root. ' +
205
+ 'Set PLUGIN_ROOT, CLAUDE_PLUGIN_ROOT, CODEX_PLUGIN_ROOT, CURSOR_RULES_DIR, or PI_PLUGIN_ROOT ' +
206
+ 'to the plugin directory, or ensure a package.json with name "session-orchestrator" exists in an ' +
207
+ 'ancestor of the cwd or this script. Attempted: ' + tried.join('; '),
208
+ tried,
209
+ );
210
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * pre-dispatch-check.mjs — guard against untracked-file data loss when
3
+ * Claude Code's Agent tool runs with `isolation: "worktree"`.
4
+ *
5
+ * Background (issue #180): the Agent tool's built-in worktree isolation
6
+ * syncs directories back to the coordinator's working tree when the agent
7
+ * completes. If the coordinator holds untracked files that overlap with
8
+ * the agent's scope, the sync silently overwrites them. This helper lets
9
+ * the coordinator detect the overlap before dispatching, and either warn
10
+ * or hard-refuse per the caller's policy.
11
+ *
12
+ * Stdlib-only, cross-platform, no zx.
13
+ */
14
+
15
+ import { execFileSync } from 'node:child_process';
16
+ import { pathMatchesPattern } from './hardening.mjs';
17
+
18
+ /**
19
+ * @typedef {Object} OverlapResult
20
+ * @property {string[]} overlapping relative paths of untracked files overlapping the scope
21
+ * @property {string[]} untracked full list of untracked files discovered
22
+ * @property {'ok'|'warn'|'block'} decision
23
+ * @property {string} message human-readable summary
24
+ */
25
+
26
+ /**
27
+ * Detect untracked coordinator files that overlap a planned agent scope.
28
+ *
29
+ * @param {Object} opts
30
+ * @param {string[]} opts.scope agent file scope (paths, directories, or globs)
31
+ * @param {string} [opts.cwd] project root (defaults to process.cwd())
32
+ * @param {'warn'|'block'|'off'} [opts.mode='warn']
33
+ * - `warn` — return decision:'warn' when overlap found
34
+ * - `block` — return decision:'block' when overlap found
35
+ * - `off` — never flag (short-circuit, decision:'ok')
36
+ * @returns {OverlapResult}
37
+ */
38
+ export function checkUntrackedOverlap({ scope, cwd = process.cwd(), mode = 'warn' } = {}) {
39
+ if (mode === 'off') {
40
+ return { overlapping: [], untracked: [], decision: 'ok', message: 'pre-dispatch check disabled' };
41
+ }
42
+
43
+ if (!Array.isArray(scope) || scope.length === 0) {
44
+ return { overlapping: [], untracked: [], decision: 'ok', message: 'empty scope — no overlap possible' };
45
+ }
46
+
47
+ const untracked = listUntracked(cwd);
48
+
49
+ const overlapping = untracked.filter((file) => scope.some((pat) => pathMatchesPattern(file, pat)));
50
+
51
+ if (overlapping.length === 0) {
52
+ return { overlapping: [], untracked, decision: 'ok', message: 'no overlap between untracked files and agent scope' };
53
+ }
54
+
55
+ const decision = mode === 'block' ? 'block' : 'warn';
56
+ const verb = decision === 'block' ? 'REFUSING' : 'WARNING';
57
+ const action =
58
+ decision === 'block'
59
+ ? 'commit or stash them before dispatching, or rerun with mode=warn to acknowledge the risk'
60
+ : 'the Agent tool\'s worktree isolation may overwrite these on merge-back (issue #180)';
61
+ const message =
62
+ `${verb}: ${overlapping.length} untracked coordinator file(s) overlap the agent scope — ${action}\n` +
63
+ overlapping.map((f) => ` - ${f}`).join('\n');
64
+
65
+ return { overlapping, untracked, decision, message };
66
+ }
67
+
68
+ /**
69
+ * Run `git status --porcelain` and extract untracked files (prefix "??").
70
+ * Returns paths relative to `cwd`. Returns [] on any git failure.
71
+ *
72
+ * @param {string} cwd
73
+ * @returns {string[]}
74
+ */
75
+ export function listUntracked(cwd) {
76
+ let stdout;
77
+ try {
78
+ stdout = execFileSync('git', ['status', '--porcelain'], { cwd, encoding: 'utf8' });
79
+ } catch {
80
+ return [];
81
+ }
82
+
83
+ const files = [];
84
+ for (const rawLine of stdout.split('\n')) {
85
+ if (!rawLine.startsWith('?? ')) continue;
86
+ // Porcelain v1 wraps paths in quotes when they contain special chars. Strip them.
87
+ let rel = rawLine.slice(3);
88
+ if (rel.startsWith('"') && rel.endsWith('"')) {
89
+ rel = rel.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
90
+ }
91
+ // Directory entries end with `/` in porcelain output — expand to file list for fidelity.
92
+ if (rel.endsWith('/')) {
93
+ files.push(...expandDirectory(cwd, rel));
94
+ } else {
95
+ files.push(rel);
96
+ }
97
+ }
98
+ return files;
99
+ }
100
+
101
+ /**
102
+ * Enumerate untracked files under a directory via `git ls-files --others`.
103
+ * Runs in the given cwd and resolves the directory relative to that root.
104
+ * Returns repo-relative paths. Best-effort — swallows errors and falls back
105
+ * to the directory entry itself so callers still see something.
106
+ *
107
+ * @param {string} cwd
108
+ * @param {string} relDir repo-relative directory with trailing `/`
109
+ * @returns {string[]}
110
+ */
111
+ function expandDirectory(cwd, relDir) {
112
+ try {
113
+ const stdout = execFileSync(
114
+ 'git',
115
+ ['ls-files', '--others', '--exclude-standard', '--', relDir],
116
+ { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }
117
+ );
118
+ const lines = stdout
119
+ .split('\n')
120
+ .map((line) => line.trim())
121
+ .filter((line) => line.length > 0);
122
+ return lines.length > 0 ? lines : [relDir];
123
+ } catch {
124
+ return [relDir];
125
+ }
126
+ }