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
+ # Vault & Docs Architecture — Umbrella Narrative
2
+
3
+ **Audience:** Plugin contributors (Dev). New contributors who need to understand
4
+ how the four documentation skills, one orchestrator skill, one agent, and two
5
+ discovery probes fit together — what fires when, who owns which file, and how
6
+ to recover when something breaks.
7
+
8
+ **Status:** Living document. Tracks Epic #229 (Vault & Docs Orchestration).
9
+
10
+ ---
11
+
12
+ ## 1. Purpose
13
+
14
+ The session-orchestrator plugin treats documentation as a first-class side
15
+ effect of every session, not a manual afterthought. Three problems motivate
16
+ the layer:
17
+
18
+ - **Cross-session memory loss.** A session ends, the chat closes, the next
19
+ session starts cold. Without a structured place to land decisions, status
20
+ changes, and learnings, every session re-discovers context. The Meta-Vault
21
+ (`~/Projects/vault`) is that place. Source: "Vault & Docs Orchestration" (#229; archived in the private Meta-Vault)
22
+ Section 1 ("Why" — 14 active projects, daily multi-session workflow).
23
+ - **Audience-specific documentation rotting in parallel.** READMEs,
24
+ `CLAUDE.md`, and Vault narratives drift independently because nothing
25
+ reminds the session to update them in lock-step with the diff. Source:
26
+ "Vault & Docs Orchestration" (#229; archived in the private Meta-Vault) Section 1 (no
27
+ Docs-Planning step in session-start; doku only touched in session-end Phase 3.1).
28
+ - **Operational telemetry without a home.** Wave outcomes, learnings, and
29
+ session metrics are JSONL on disk; humans need them as Markdown notes
30
+ cross-linked into the Vault graph. Source: `skills/vault-mirror/SKILL.md`
31
+ ("Purpose" — converts JSONL into vault-conformant Markdown).
32
+
33
+ The architecture below ties these three concerns together with deliberate
34
+ non-overlap: each component owns a narrow slice of the documentation surface,
35
+ and the lifecycle hooks ensure the slices are written, validated, and
36
+ mirrored at the right phase.
37
+
38
+ ---
39
+
40
+ ## 2. Architecture Diagram
41
+
42
+ Data flow within a single `/session feature → /go → /close` cycle:
43
+
44
+ ```
45
+ ┌──────────────────────────────────────────────────────────────────┐
46
+ │ user invokes: /session feature → /go → /close │
47
+ └──────────────────────────────────────────────────────────────────┘
48
+
49
+ ┌──────────────────────────────────────────────────────────────────┐
50
+ │ session-start │
51
+ │ Phase 2.5 docs-orchestrator (opt-in) │
52
+ │ └─ audience detection → docs-tasks block in STATE.md │
53
+ │ Source: skills/session-start/phase-2-5-docs-planning.md │
54
+ └──────────────────────────────────────────────────────────────────┘
55
+
56
+ ┌──────────────────────────────────────────────────────────────────┐
57
+ │ session-plan │
58
+ │ Step 1.5 docs-writer added to agent registry │
59
+ │ Step 1.8 Docs-classified tasks → docs-writer assignment │
60
+ │ Source: skills/docs-orchestrator/SKILL.md (Invocation) │
61
+ └──────────────────────────────────────────────────────────────────┘
62
+
63
+ ┌──────────────────────────────────────────────────────────────────┐
64
+ │ wave-executor │
65
+ │ dispatches docs-writer agent with the canonical four sources: │
66
+ │ diff │ git-log │ session-memory │ affected-files │
67
+ │ Source: agents/docs-writer.md (Inputs) │
68
+ └──────────────────────────────────────────────────────────────────┘
69
+
70
+ ┌──────────────────────────────────────────────────────────────────┐
71
+ │ code/diff lands; tests run; metrics written │
72
+ └──────────────────────────────────────────────────────────────────┘
73
+
74
+ ┌──────────────────────────────────────────────────────────────────┐
75
+ │ session-end │
76
+ │ Phase 2.1 vault-sync (frontmatter + wiki-link gate) │
77
+ │ Phase 2.2 claude-md-drift (5 narrative drift checks) │
78
+ │ Phase 2.3 vault-staleness (opt-in: stale projects) │
79
+ │ Phase 3.2 docs-verify (per-task ok/partial/gap) │
80
+ │ Phase 3.7 vault-mirror (sessions.jsonl → 50-sessions/) │
81
+ │ Source: skills/session-end/SKILL.md (phase markers) │
82
+ └──────────────────────────────────────────────────────────────────┘
83
+
84
+ ┌──────────────────────────────────────────────────────────────────┐
85
+ │ Meta-Vault (~/Projects/vault) │
86
+ │ 01-projects/<slug>/ ← context.md / decisions.md / people.md │
87
+ │ (docs-writer, Vault audience) │
88
+ │ 01-projects/<slug>/ ← _overview.md (vault-mirror, no humans) │
89
+ │ 03-daily/YYYY-MM-DD.md (daily skill, idempotent) │
90
+ │ 40-learnings/<slug>.md (vault-mirror, evolve hook) │
91
+ │ 50-sessions/<id>.md (vault-mirror, session-end Phase 3.7) │
92
+ └──────────────────────────────────────────────────────────────────┘
93
+
94
+ ┌──────────────────────────────────────────────────────────────────┐
95
+ │ /discovery vault — on-demand staleness probes │
96
+ │ vault-staleness.mjs + vault-narrative-staleness.mjs │
97
+ │ Source: skills/discovery/probes-vault.md │
98
+ └──────────────────────────────────────────────────────────────────┘
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 3. Component Table
104
+
105
+ | Component | Owner | Trigger | Input | Output | Audience |
106
+ |-----------|-------|---------|-------|--------|----------|
107
+ | `vault-sync` | `skills/vault-sync/SKILL.md` | session-end Phase 2.1 (hard gate) | `VAULT_DIR/**/*.md` frontmatter + wiki-links | JSON report (`status`, `errors`, `warnings`) on stdout, exit code 0/1/2 | Dev (validation) |
108
+ | `claude-md-drift-check` | `skills/claude-md-drift-check/SKILL.md` | session-end Phase 2.2 (opt-in gate) | `CLAUDE.md`, `_meta/**/*.md` | JSON report with 5 named checks (path-resolver, project-count-sync, issue-reference-freshness, session-file-existence, command-count) | Dev (validation) |
109
+ | `vault-staleness` probes | `skills/discovery/probes-vault.md` + `skills/discovery/probes/vault-staleness.mjs` | `/discovery vault` (on-demand) and session-end Phase 2.3 (opt-in close-time gate) | `VAULT_DIR/01-projects/*/` `_overview.md` + narrative files | JSONL findings under `.orchestrator/metrics/vault-staleness.jsonl` and `vault-narrative-staleness.jsonl` | Vault/Ops (telemetry) |
110
+ | `docs-orchestrator` | `skills/docs-orchestrator/SKILL.md` | session-start Phase 2.5, session-plan Step 1.5/1.8, session-end Phase 3.2 (all gated on `enabled: true`) | Session scope + Session Config audience list | `docs-tasks` block in STATE.md (write side); `### Documentation Coverage` block in final report (verify side) | All three (User / Dev / Vault) |
111
+ | `docs-writer` agent | `agents/docs-writer.md` | Dispatched by `wave-executor` for each `Docs`-classified task | `diff`, `git-log`, `session-memory`, `affected-files` | Audience-targeted Markdown writes (Edit/Write); `[docs-orchestrator] Docs task complete` report line | All three (per task) |
112
+ | `daily` | `skills/daily/SKILL.md` | User-invocable (`/daily`), idempotent | `VAULT_DIR/03-daily/`, `templates/daily.md.tpl` | `<vault>/03-daily/YYYY-MM-DD.md` (created or no-op) | Vault/Ops (PKM anchor) |
113
+ | `vault-mirror` | `skills/vault-mirror/SKILL.md` + `scripts/vault-mirror.mjs` | session-end Phase 3.7 (sessions); evolve Phase 3.5 (learnings) | `.orchestrator/metrics/sessions.jsonl`, `.orchestrator/metrics/learnings.jsonl` | `<vault>/50-sessions/<id>.md`, `<vault>/40-learnings/<slug>.md` (`_generator` marker `session-orchestrator-vault-mirror@1`) | Vault/Ops (telemetry → Markdown) |
114
+ | `vault-backfill` CLI | `scripts/vault-backfill.mjs` | Manual, also surfaced via `/plan retro vault-backfill` sub-mode | `vault-integration.gitlab-groups` config + GitLab API | `.vault.yaml` per repo + Vault stub directories | Vault/Ops (one-shot migration) |
115
+
116
+ ---
117
+
118
+ ## 4. Audience Model
119
+
120
+ Three audiences, three documentation surfaces. The split is enforced by
121
+ `skills/docs-orchestrator/audience-mapping.md` (Audiences & File Patterns
122
+ table), which is the **single source of truth** for which files belong to
123
+ which audience. Never inline this table elsewhere — always cross-link.
124
+
125
+ - **User** — external/internal users of the repo. Targets: `README.md`,
126
+ `docs/user/**/*.md`, `docs/getting-started.md`, `examples/**/*.md`. Source:
127
+ `skills/docs-orchestrator/audience-mapping.md` § Audiences & File Patterns.
128
+ - **Dev** — contributors to the repo, including future Claude sessions.
129
+ Targets: `CLAUDE.md`, `docs/dev/**/*.md`, `docs/adr/**/*.md`. Source: same.
130
+ - **Vault/Ops** — strategic continuity across sessions. Targets:
131
+ `<vault>/01-projects/<slug>/context.md`, `decisions.md`, `people.md`.
132
+ Source: same.
133
+
134
+ The Session Config field `docs-orchestrator.audiences` accepts any subset of
135
+ `[user, dev, vault]`; narrowing it (e.g., `[user, dev]` on a project without a
136
+ Vault) suppresses Vault-targeted docs without disabling the orchestrator
137
+ entirely. Source: `docs/session-config-reference.md` § Docs Orchestrator.
138
+
139
+ ---
140
+
141
+ ## 5. Source-Cited Content Rule
142
+
143
+ The `docs-writer` agent operates under a **hallucination ban**: every
144
+ substantive paragraph must trace to one of the canonical four sources, or
145
+ carry an inline `<!-- REVIEW: source needed -->` marker. The four sources are
146
+ defined once and reused everywhere:
147
+
148
+ 1. **diff** — `git diff $SESSION_START_REF..HEAD`
149
+ 2. **git-log** — `git log $SESSION_START_REF..HEAD --format="%H %s%n%b"`
150
+ 3. **session-memory** — `~/.claude/projects/<project>/memory/session-*.md` and
151
+ `.orchestrator/` outputs
152
+ 4. **affected-files** — files in the wave-scope `allowedPaths` block
153
+
154
+ Source: `agents/docs-writer.md` § Inputs / Source Citation Rules and
155
+ `skills/docs-orchestrator/SKILL.md` Phase 4 (Source Grounding).
156
+
157
+ The `<!-- REVIEW: source needed -->` marker is **load-bearing**: it signals
158
+ to the human reviewer that a section needs verification before the next
159
+ release. The agent is explicitly forbidden from removing the marker to make
160
+ output appear cleaner. Source: `skills/docs-orchestrator/SKILL.md` Phase 5
161
+ ("Sourceless content").
162
+
163
+ **Hard guard in Phase 4:** if ALL four source blocks are empty or absent in
164
+ the dispatched task prompt, the docs-writer aborts rather than producing
165
+ silent REVIEW-marker-only output. Source:
166
+ `skills/docs-orchestrator/SKILL.md` Phase 4 step 1.
167
+
168
+ ---
169
+
170
+ ## 6. Non-Overlap Discipline
171
+
172
+ Three forbidden cross-writes are enforced by the architecture, not just by
173
+ convention:
174
+
175
+ - **`<vault>/01-projects/*/_overview.md` is owned by `vault-mirror`.** The
176
+ file is regenerated from JSONL metrics on every session-end Phase 3.7. A
177
+ second writer would corrupt the metrics-derived content or introduce human
178
+ prose that vault-mirror's next run overwrites silently. Source:
179
+ `skills/docs-orchestrator/audience-mapping.md` § Non-Overlap (vault-mirror
180
+ row) and `skills/vault-mirror/SKILL.md` § Idempotency (the `_generator`
181
+ marker `session-orchestrator-vault-mirror@1` is the discriminator).
182
+ - **`<vault>/03-daily/YYYY-MM-DD.md` is owned by `daily`.** Idempotent by
183
+ design — re-running `/daily` opens the existing note, never overwrites.
184
+ Source: `skills/daily/SKILL.md` § Idempotency Guarantee. A second writer
185
+ would corrupt the day's scratch notes. Source:
186
+ `skills/docs-orchestrator/audience-mapping.md` § Non-Overlap (daily row).
187
+ - **`CLAUDE.md` may be remediated by `docs-writer` (Dev audience), but
188
+ `claude-md-drift-check` only diagnoses it.** The two skills must not run
189
+ on `CLAUDE.md` in parallel within the same wave. Source:
190
+ `skills/docs-orchestrator/audience-mapping.md` § Non-Overlap
191
+ (claude-md-drift-check row).
192
+
193
+ The forbidden patterns are checked in `skills/docs-orchestrator/SKILL.md`
194
+ Phase 3 with an abort-on-match guard before any write occurs.
195
+
196
+ ---
197
+
198
+ ## 7. Lifecycle
199
+
200
+ Concrete answer to "when does each component fire":
201
+
202
+ | Phase | Skill / Probe | Gating |
203
+ |-------|---------------|--------|
204
+ | `/session` start, Phase 2.5 | `docs-orchestrator` audience detection | `docs-orchestrator.enabled: true` |
205
+ | `/session` start, Phase 4.5 | resource-health probe | always (env-aware) |
206
+ | session-plan Step 1.5/1.8 | `docs-writer` registered + Docs role classified | `docs-orchestrator.enabled: true` |
207
+ | `/go` waves | `docs-writer` agent dispatched per Docs task | task present in plan |
208
+ | `/close` Phase 2.1 | `vault-sync` validator | `vault-sync.enabled: true` (hard gate by mode) |
209
+ | `/close` Phase 2.2 | `claude-md-drift-check` | `drift-check.enabled: true` |
210
+ | `/close` Phase 2.3 | `vault-staleness` + `vault-narrative-staleness` probes | `vault-staleness.enabled: true` |
211
+ | `/close` Phase 3.2 | `docs-orchestrator` verification | `docs-orchestrator.enabled: true` AND `docs-tasks` block present |
212
+ | `/close` Phase 3.7 | `vault-mirror` (sessions) | `vault-integration.enabled: true` AND `mode != off` |
213
+ | evolve Phase 3.5 | `vault-mirror` (learnings) | same as above |
214
+ | `/discovery vault` | `vault-staleness` probes (on-demand) | `.vault.yaml` present OR `vault-integration.enabled: true` |
215
+ | `/daily` | `daily` skill | user-invocable; no Session Config gate |
216
+
217
+ Sources: `skills/session-end/SKILL.md` (Phase markers), `docs/session-config-reference.md`
218
+ (per-skill enabled-flag semantics), `skills/discovery/probes-vault.md` (probe
219
+ activation rules).
220
+
221
+ The **opt-in default** is the design contract: when no Session Config block
222
+ is present for a given skill, that skill's hook short-circuits silently —
223
+ zero overhead. Source: "Vault & Docs Orchestration" (#229; archived in the private Meta-Vault)
224
+ Section 5 (Risk: "Marketplace-Kompatibilität — alle neuen Config-Felder
225
+ opt-in mit sicherem Default → zero-impact für bestehende Plugin-User").
226
+
227
+ ---
228
+
229
+ ## 8. Failure Modes & Escape Hatches
230
+
231
+ | What breaks | Symptom | Recovery |
232
+ |-------------|---------|----------|
233
+ | `vault-sync` finds invalid frontmatter, `mode: hard` | session-end Phase 2.1 blocks `/close` | Fix the offending file, re-run `/close`. Or temporarily set `vault-sync.mode: warn` to unblock and file an issue. Source: `skills/vault-sync/SKILL.md` § "How session-end invokes it" (exit 1 → block). |
234
+ | `claude-md-drift-check` finds stale issue refs, `mode: hard` | Phase 2.2 blocks `/close` | Update CLAUDE.md to reflect actual state, or set `drift-check.mode: warn`. Source: `skills/claude-md-drift-check/SKILL.md` § "Session-End Phase 2.2". |
235
+ | `vault-staleness` probe finds stale projects, `mode: strict` | Phase 2.3 blocks `/close` with interactive override | Run `/discovery vault` to triage; update narrative files, or use the AskUserQuestion override (logged to STATE.md). Source: `docs/session-config-reference.md` § Vault Staleness ("Mode behavior" table). |
236
+ | `docs-writer` cannot find a source for a section | Section is written with `<!-- REVIEW: source needed -->` | Human review before next release; do NOT remove the marker. Source: `skills/docs-orchestrator/SKILL.md` Phase 5. |
237
+ | `docs-writer` is dispatched with **all four** source blocks empty | Agent aborts with `docs-writer: no grounding sources available` | Coordinator surfaces the failure; fix the task spec to include at least one source. Source: `skills/docs-orchestrator/SKILL.md` Phase 4 step 1 (Hard guard). |
238
+ | `vault-mirror` finds a hand-written file at the target path | `skipped-handwritten` action emitted; file untouched | Intentional safety: human files are never overwritten. If the file should be regenerated, delete it manually. Source: `skills/vault-mirror/SKILL.md` § Idempotency item 4. |
239
+ | Session Config block absent | All hooks skip silently | Default behavior. To enable, add the relevant block per `docs/session-config-reference.md`. |
240
+ | `docs-orchestrator.mode: off` | Phase 2.5 / 3.2 read config but skip all execution | Lighter than `enabled: false` (config still parsed). Useful during onboarding. Source: `skills/docs-orchestrator/SKILL.md` § "Session Config Reference". |
241
+ | Repo lacks `.vault.yaml` but `vault-integration.enabled: true` | vault-sync warns "kein .vault.yaml gefunden" but does not block | Run `scripts/vault-backfill.mjs` (dry-run default) to generate. Source: "Vault & Docs Orchestration" (#229; archived in the private Meta-Vault) § Edge Cases. |
242
+
243
+ ---
244
+
245
+ ## 9. Future Direction
246
+
247
+ **Epic #229 (Vault & Docs Orchestration) is in-progress.** Closed slices to
248
+ date (per CLAUDE.md "Current State"):
249
+
250
+ - docs-orchestrator skill + docs-writer agent (foundation #230, hooks #233 /
251
+ #234 / #235, config #236).
252
+ - vault-staleness probes + Phase 2.3 integration (#232, #242).
253
+ - vault-backfill CLI + `/plan retro vault-backfill` sub-mode (#241).
254
+ - vault-mirror auto-commit phase via `--session-id` (GH#31).
255
+
256
+ Source: `CLAUDE.md` § "Current State" and "Vault & Docs Orchestration" (#229; archived in the private Meta-Vault)
257
+ § Sub-Epic A/B/C tracking lists.
258
+
259
+ **Open work:** Sub-Epic B (projects-baseline `setup-project.sh` Vault auto-
260
+ provisioning) lives in a sibling repo and ships independently. CLAUDE.md
261
+ narrative-sync remediation across consumer repos remains a recurring
262
+ maintenance load. Source: "Vault & Docs Orchestration" (#229; archived in the private Meta-Vault)
263
+ § Sub-Epic B.
264
+
265
+ **Explicit non-goals** — these are not on the roadmap:
266
+
267
+ - **Team-Vault sharing.** Today single-user-local under
268
+ `~/Projects/vault`. Team sharing requires its own infra (sync, permissions,
269
+ conflict resolution) and is a separate epic.
270
+ - **Two-way sync (Vault → Repo).** Today one-way (Repo → Vault via
271
+ `.vault.yaml` + Clank). Reversal would break the ownership model.
272
+ - **LLM-autogenerated User-Docs without source.** docs-writer writes only
273
+ from the canonical four sources. Sourceless sections get
274
+ `<!-- REVIEW: source needed -->`, never invented content.
275
+ - **Full ADR autogeneration.** ADRs remain human-authored decisions;
276
+ docs-writer may suggest skeletons but never commits autonomously.
277
+ - **Migration of historical 50-sessions / 40-learnings entries.** vault-mirror
278
+ is forward-compatible only.
279
+
280
+ Source: "Vault & Docs Orchestration" (#229; archived in the private Meta-Vault) § Out-of-Scope.
281
+
282
+ ---
283
+
284
+ ## See Also
285
+
286
+ - `docs/session-config-reference.md` — authoritative config reference for all
287
+ fields mentioned above (Vault Sync, CLAUDE.md Drift Check, Vault
288
+ Integration, Vault Staleness, Docs Orchestrator).
289
+ - "Vault & Docs Orchestration" (#229; archived in the private Meta-Vault) — PRD for the umbrella
290
+ epic, including layering diagram and ownership table this document
291
+ derives from.
292
+ - `skills/docs-orchestrator/audience-mapping.md` — single source of truth
293
+ for audience → file-pattern mapping and non-overlap rules.
294
+ - `agents/docs-writer.md` — the sole agent permitted to write audience-
295
+ targeted documentation within a session.
296
+ - `CLAUDE.md` § "Current State" — running ledger of which umbrella-epic
297
+ slices have shipped.
@@ -0,0 +1,272 @@
1
+ /**
2
+ * lock-bootstrap.mjs — mechanical session.lock writer for the SessionStart hook.
3
+ *
4
+ * Epic #583 P3 closes the D1 wiring gap: until P3, `acquire()` from
5
+ * scripts/lib/session-lock.mjs had no mechanical caller in the
6
+ * /session or /deep flow (only the autopilot-multi pipeline called it).
7
+ * The lock was written only when the coordinator-LLM happened to invoke
8
+ * Phase 1.2 prose — silent skip → discoverActiveSessions() returns empty →
9
+ * parallel-session AUQ never fires.
10
+ *
11
+ * This helper is invoked from hooks/on-session-start.mjs once per session.
12
+ * It is intentionally best-effort: every failure path swallows its error
13
+ * so the hook stays non-blocking (the hook's contract is informational-only;
14
+ * a write failure here must NEVER break session-start).
15
+ *
16
+ * Schema v2 (Epic #583 D4 #587):
17
+ * {
18
+ * session_id: string, // semantic OR UUID — whatever resolveSessionId returned
19
+ * semantic_session_id: string, // ALWAYS the semantic form (closes D4)
20
+ * started_at: ISO,
21
+ * last_heartbeat: ISO, // basis for liveness; replaces PID-liveness checks
22
+ * mode: string, // "deep"|"feature"|"housekeeping"|"session"|...
23
+ * pid: number, // forensics only — DO NOT use for liveness (D2/D4)
24
+ * host: string,
25
+ * ttl_hours: number,
26
+ * }
27
+ *
28
+ * The current scripts/lib/session-lock.mjs (pre-I3) writes the v1 shape
29
+ * (no last_heartbeat, no semantic_session_id). This helper layers v2 fields
30
+ * on top via an atomic tmp+rename overwrite — when I3 ships its v2 schema,
31
+ * this helper's overlay becomes a no-op (the field is already there) and
32
+ * everything continues to work.
33
+ *
34
+ * @module hooks/_lib/lock-bootstrap
35
+ */
36
+
37
+ import fs from 'node:fs';
38
+ import path from 'node:path';
39
+ import { writeJsonAtomicSync } from '../../scripts/lib/io.mjs';
40
+
41
+ /**
42
+ * Bootstrap the session.lock for this hook invocation.
43
+ *
44
+ * Best-effort: every internal failure is swallowed, the helper returns null
45
+ * instead of throwing. Callers (the SessionStart hook) wrap this in a
46
+ * try/catch anyway, but the helper itself never propagates.
47
+ *
48
+ * @param {object} opts
49
+ * @param {string} opts.repoRoot — absolute path to the repository root.
50
+ * @param {string} opts.sessionId — the resolved session id (semantic OR UUID).
51
+ * @param {string} [opts.semanticSessionId] — the semantic form, ALWAYS surfaced
52
+ * even when sessionId is a UUID (closes D4 issue #587). When omitted, the
53
+ * field is populated by mirroring sessionId.
54
+ * @param {string} opts.mode — session mode (e.g. "deep", "feature").
55
+ * @param {number} [opts.ttlHours=4] — lock TTL in hours.
56
+ * @param {Function} [opts._acquireImpl] — DI for tests (defaults to importing acquire from session-lock.mjs).
57
+ * @param {Function} [opts._forceAcquireImpl] — DI for tests (defaults to importing forceAcquire from session-lock.mjs).
58
+ * @param {Function} [opts._emitEventImpl] — DI for tests (defaults to importing emitEvent from events.mjs).
59
+ * @returns {Promise<object|null>} the enriched v2 lock body on success, null on any failure.
60
+ */
61
+ export async function bootstrapLock({
62
+ repoRoot,
63
+ sessionId,
64
+ semanticSessionId,
65
+ mode,
66
+ ttlHours = 4,
67
+ _acquireImpl,
68
+ _forceAcquireImpl,
69
+ _emitEventImpl,
70
+ } = {}) {
71
+ // Sanity-check required inputs. Anything missing → bail silently.
72
+ if (typeof repoRoot !== 'string' || repoRoot.length === 0) return null;
73
+ if (typeof sessionId !== 'string' || sessionId.length === 0) return null;
74
+ if (typeof mode !== 'string' || mode.length === 0) return null;
75
+
76
+ // Resolve DI shims at call time so test mocks can replace the imports.
77
+ let acquireFn = _acquireImpl;
78
+ let forceAcquireFn = _forceAcquireImpl;
79
+ if (!acquireFn || !forceAcquireFn) {
80
+ try {
81
+ const lockMod = await import('../../scripts/lib/session-lock.mjs');
82
+ acquireFn = acquireFn ?? lockMod.acquire;
83
+ forceAcquireFn = forceAcquireFn ?? lockMod.forceAcquire;
84
+ } catch {
85
+ return null;
86
+ }
87
+ }
88
+
89
+ // Step 1: try to acquire. If a fresh acquire succeeds, we are done.
90
+ // If a stale-PID-dead/-alive lock exists, force-overwrite it (the prior
91
+ // session has died; we own the worktree now).
92
+ // If the existing lock has the same sessionId, force-overwrite so the
93
+ // last_heartbeat gets refreshed.
94
+ let acquireResult;
95
+ try {
96
+ // quiet: true suppresses the unknown-mode stderr WARN in acquire() (#592 MED-2).
97
+ // The hook is informational-only and tests assert stderr is empty.
98
+ acquireResult = acquireFn({ sessionId, mode, ttlHours, repoRoot, quiet: true });
99
+ } catch {
100
+ return null;
101
+ }
102
+
103
+ if (!acquireResult || typeof acquireResult !== 'object') return null;
104
+
105
+ const shouldForce =
106
+ acquireResult.ok !== true && (
107
+ acquireResult.reason === 'stale-pid-dead' ||
108
+ acquireResult.reason === 'stale-pid-alive' ||
109
+ (acquireResult.reason === 'active' &&
110
+ acquireResult.existingLock &&
111
+ acquireResult.existingLock.session_id === sessionId)
112
+ );
113
+
114
+ if (!acquireResult.ok && shouldForce) {
115
+ try {
116
+ acquireResult = forceAcquireFn({ sessionId, mode, ttlHours, repoRoot });
117
+ } catch {
118
+ return null;
119
+ }
120
+ }
121
+
122
+ // Any other non-ok reason (parallel-conflict, fs-error, other-session-active)
123
+ // → bail without enriching. The hook stays non-blocking.
124
+ //
125
+ // Issue #590 Item 1: before bailing, record a durable conflict signal for the
126
+ // FOREIGN-active case — reason 'active' where the existing lock belongs to a
127
+ // DIFFERENT session than ours (the same-session case was already force-refreshed
128
+ // above via shouldForce). Without this, the operator gets no signal that a
129
+ // parallel session owns the worktree. We persist the foreign session_id into
130
+ // current-session.json for forensics/operator visibility. Best-effort: any FS
131
+ // failure is swallowed and the bail proceeds. The return contract is unchanged —
132
+ // bootstrapLock STILL returns null on this path.
133
+ if (!acquireResult || acquireResult.ok !== true) {
134
+ if (
135
+ acquireResult &&
136
+ acquireResult.reason === 'active' &&
137
+ acquireResult.existingLock &&
138
+ typeof acquireResult.existingLock.session_id === 'string' &&
139
+ acquireResult.existingLock.session_id.length > 0 &&
140
+ acquireResult.existingLock.session_id !== sessionId
141
+ ) {
142
+ recordConflictSignal(repoRoot, acquireResult.existingLock.session_id);
143
+ }
144
+ return null;
145
+ }
146
+
147
+ // Step 2: enrich the lock with v2 fields (last_heartbeat + semantic_session_id).
148
+ // We re-read the file fresh (acquire() just wrote it) and overlay the new
149
+ // fields, then atomically tmp+rename. When I3 lands and acquire() writes the
150
+ // v2 shape natively, this overlay becomes idempotent (already-present fields
151
+ // get overwritten with identical values).
152
+ const lockFile = path.join(repoRoot, '.orchestrator', 'session.lock');
153
+ let baseLock;
154
+ try {
155
+ const raw = fs.readFileSync(lockFile, 'utf8');
156
+ baseLock = JSON.parse(raw);
157
+ if (typeof baseLock !== 'object' || baseLock === null) return null;
158
+ } catch {
159
+ // Lock vanished between write and read — best-effort, return null.
160
+ return null;
161
+ }
162
+
163
+ const startedAt = typeof baseLock.started_at === 'string'
164
+ ? baseLock.started_at
165
+ : new Date().toISOString();
166
+
167
+ const enriched = {
168
+ ...baseLock,
169
+ // last_heartbeat is the basis for liveness — set to started_at on bootstrap
170
+ // so an immediate liveness check (< ttl_hours from now) succeeds.
171
+ last_heartbeat: startedAt,
172
+ // semantic_session_id is ALWAYS the semantic form, even when session_id is
173
+ // a UUID-v4 (closes D4 #587). Fallback to mirroring session_id if no
174
+ // semantic was provided.
175
+ semantic_session_id:
176
+ typeof semanticSessionId === 'string' && semanticSessionId.length > 0
177
+ ? semanticSessionId
178
+ : (typeof baseLock.session_id === 'string' ? baseLock.session_id : sessionId),
179
+ };
180
+
181
+ {
182
+ const w = writeJsonAtomicSync(lockFile, enriched, { tmpPrefix: '.session.lock.boot.tmp' });
183
+ if (!w.ok) {
184
+ // Failed to overwrite — base lock is still on disk, so we degrade
185
+ // gracefully. Return null so the caller logs no spurious success.
186
+ return null;
187
+ }
188
+ }
189
+
190
+ // Step 3: best-effort observability breadcrumb. Failures are swallowed
191
+ // so a missing events module never breaks the hook.
192
+ try {
193
+ let emitFn = _emitEventImpl;
194
+ if (!emitFn) {
195
+ const eventsMod = await import('../../scripts/lib/events.mjs');
196
+ emitFn = eventsMod.emitEvent;
197
+ }
198
+ if (typeof emitFn === 'function') {
199
+ await emitFn('orchestrator.session.lock.acquired', {
200
+ session_id: enriched.session_id,
201
+ semantic_session_id: enriched.semantic_session_id,
202
+ mode: enriched.mode,
203
+ pid: enriched.pid,
204
+ host: enriched.host,
205
+ ttl_hours: enriched.ttl_hours,
206
+ });
207
+ }
208
+ } catch { /* observability is best-effort */ }
209
+
210
+ return enriched;
211
+ }
212
+
213
+ /**
214
+ * Record a foreign-session conflict signal into current-session.json (Issue #590
215
+ * Item 1). When bootstrapLock detects that a DIFFERENT session already owns the
216
+ * worktree lock, it persists the colliding session_id (plus a forensic timestamp)
217
+ * so the operator and downstream skills have a durable record of the collision —
218
+ * the previous behaviour bailed silently with no signal whatsoever.
219
+ *
220
+ * Uses an atomic read-modify-write (read → merge → tmp+rename) that PRESERVES
221
+ * every existing field (`session_id`, `semantic_session_id`, `pid`, `source`,
222
+ * `timestamp`, and any concurrently-appended `cwd_changes` / `corrective_context`
223
+ * / `last_batch` arrays). It never overwrites the whole file — it overlays only
224
+ * the two conflict fields on top of whatever is currently on disk.
225
+ *
226
+ * Best-effort: any FS error (missing file, parse failure, write race) is swallowed
227
+ * so the SessionStart hook stays non-blocking. The conflict signal is a forensic
228
+ * breadcrumb, not a correctness requirement.
229
+ *
230
+ * Lost-update window (Issue #596, deep-6 R2 MED — ACCEPTED): the read→merge→write
231
+ * is not lock-serialised. recordConflictSignal's only caller is the SessionStart hook
232
+ * (on-session-start.mjs), which runs it early — well before the slow detectPeers phase.
233
+ * That hook is async:true, so strict ordering vs the corrective_context/cwd_changes/
234
+ * last_batch writers (PostToolUse/CwdChanged/PostToolBatch) is not MECHANICALLY
235
+ * guaranteed; but in practice recordConflictSignal completes in a few ms, long before
236
+ * any tool-triggered hook can fire. Crucially, the conflict_* fields have zero readers
237
+ * (forensic-only), so even a lost update is harmless. The real anti-stomp guard is
238
+ * state.lock/PSA-005, not this advisory file.
239
+ *
240
+ * @param {string} repoRoot — absolute path to the repository root.
241
+ * @param {string} foreignSessionId — the session_id of the lock holder we collided with.
242
+ */
243
+ function recordConflictSignal(repoRoot, foreignSessionId) {
244
+ try {
245
+ const sessionFile = path.join(repoRoot, '.orchestrator', 'current-session.json');
246
+
247
+ // Read-modify-write: start from whatever is on disk (or {} when absent /
248
+ // unparseable) so concurrently-written fields survive the overlay.
249
+ let current = {};
250
+ try {
251
+ const raw = fs.readFileSync(sessionFile, 'utf8');
252
+ const parsed = JSON.parse(raw);
253
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
254
+ current = parsed;
255
+ }
256
+ } catch {
257
+ // File absent or unparseable — start from an empty object. The conflict
258
+ // signal is still worth recording even if the session file was not yet written.
259
+ }
260
+
261
+ const merged = {
262
+ ...current,
263
+ conflict_with_session_id: foreignSessionId,
264
+ conflict_detected_at: new Date().toISOString(),
265
+ };
266
+
267
+ // Best-effort atomic write — return value swallowed intentionally.
268
+ writeJsonAtomicSync(sessionFile, merged, { tmpPrefix: '.current-session.conflict.tmp' });
269
+ } catch {
270
+ // Best-effort — any failure is swallowed; the caller still returns null.
271
+ }
272
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * lock-reconcile.mjs — root-cause reconciliation fallback for the SessionEnd hook.
3
+ *
4
+ * Extracted (Issue #748) from the inline reconciliation branch that used to live
5
+ * in `hooks/on-session-end.mjs`'s `main()` — that branch was only reachable via
6
+ * a subprocess spawn in tests, so its behaviour could only be verified through
7
+ * events.jsonl side effects, never asserted in-process. This module is the
8
+ * importable, DI-testable seam; `on-session-end.mjs` now just calls it.
9
+ *
10
+ * Context (Epic #724 Wave 3 — "ended logged but lock survived"): neither the
11
+ * UUID nor the semantic id matched the recorded lock (a rotated harness UUID
12
+ * racing ahead of current-session.json's semantic bridge), but the lease is
13
+ * already dead. Reconcile now via the same reaper the SessionStart hook uses
14
+ * (Epic #724 C7), instead of leaving the orphaned lease for the next
15
+ * session-start to discover. Safe by construction: reapRepoLock() never
16
+ * touches a live lease, a cross-host lease, or a lease whose recorded PID is
17
+ * still alive on this host.
18
+ *
19
+ * Best-effort by design, mirroring hooks/_lib/lock-bootstrap.mjs: every
20
+ * internal failure is swallowed so the SessionEnd hook stays non-blocking (the
21
+ * hook's contract is informational-only; a reconciliation failure here must
22
+ * NEVER break session teardown).
23
+ *
24
+ * @module hooks/_lib/lock-reconcile
25
+ */
26
+
27
+ import { isLockLive } from '../../scripts/lib/session-lock.mjs';
28
+
29
+ /**
30
+ * Attempt a best-effort reconciliation of a dead, orphaned session.lock that
31
+ * neither ownership check (UUID nor semantic id) matched. No-op when `lock`
32
+ * is missing or still live (isLockLive) — mirrors the `else if (!isLockLive(lock))`
33
+ * guard this function replaces at the call site.
34
+ *
35
+ * Never throws. Any failure resolving the DI defaults, calling reapRepoLock,
36
+ * or emitting the breadcrumb event is swallowed.
37
+ *
38
+ * @param {object} opts
39
+ * @param {string} opts.repoRoot — absolute path to the repository root.
40
+ * @param {string|null} opts.sessionId — the ending session's id (UUID or semantic).
41
+ * @param {object} opts.lock — the recorded lock the caller already read via readLock().
42
+ * @param {Function} [opts._reapRepoLockImpl] — DI for tests (defaults to importing
43
+ * reapRepoLock from scripts/lib/lock-reaper.mjs).
44
+ * @param {Function} [opts._emitEventImpl] — DI for tests (defaults to importing
45
+ * emitEvent from scripts/lib/events.mjs).
46
+ * @returns {Promise<void>}
47
+ */
48
+ export async function attemptLockReconciliation({
49
+ repoRoot,
50
+ sessionId,
51
+ lock,
52
+ _reapRepoLockImpl,
53
+ _emitEventImpl,
54
+ } = {}) {
55
+ // Mirrors the caller's original `else if (!isLockLive(lock))` guard — a
56
+ // missing or still-live lock is never reconciled.
57
+ if (!lock || typeof lock !== 'object' || isLockLive(lock)) return;
58
+
59
+ // Resolve DI shims at call time so test mocks can replace the imports.
60
+ let reapFn = _reapRepoLockImpl;
61
+ if (!reapFn) {
62
+ try {
63
+ const reaperMod = await import('../../scripts/lib/lock-reaper.mjs');
64
+ reapFn = reaperMod.reapRepoLock;
65
+ } catch {
66
+ return;
67
+ }
68
+ }
69
+
70
+ let emitFn = _emitEventImpl;
71
+ if (!emitFn) {
72
+ try {
73
+ const eventsMod = await import('../../scripts/lib/events.mjs');
74
+ emitFn = eventsMod.emitEvent;
75
+ } catch {
76
+ return;
77
+ }
78
+ }
79
+
80
+ try {
81
+ const reapResult = await reapFn({
82
+ repoRoot,
83
+ currentSessionId: sessionId,
84
+ dryRun: false,
85
+ reapMode: 'auto-session-end',
86
+ });
87
+ await emitFn('orchestrator.session.lock.reconcile_attempted', {
88
+ session_id: sessionId,
89
+ action: reapResult?.action ?? 'unknown',
90
+ reason: reapResult?.reason ?? null,
91
+ });
92
+ } catch { /* best-effort — reconciliation must never block teardown */ }
93
+ }