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,267 @@
1
+ #!/usr/bin/env node
2
+ // scripts/ci/assert-vitest-green.mjs
3
+ //
4
+ // Fail-closed verifier for a vitest JSON result file. Replaces the brittle
5
+ // grep-the-stdout heuristic the GitLab `test`/`coverage` jobs used to rely on.
6
+ //
7
+ // WHY THIS EXISTS (the silent-regression incident class):
8
+ // The old CI test job ran `timeout --preserve-status 240s npm test … || true`
9
+ // and then counted `✓`/`FAIL` markers in the captured stdout. Two ways that
10
+ // reported a RED suite as GREEN:
11
+ // 1. The suite took longer than the 240s cap under runner contention
12
+ // (observed: 257s on the Mac shell-executor). `timeout` killed vitest
13
+ // BEFORE it printed the bottom failure-summary block; `|| true` swallowed
14
+ // the kill; the grep found zero `FAIL tests/…` lines → false GREEN.
15
+ // 2. The verbose reporter marks failing tests with `×` (U+00D7), which the
16
+ // `✗` (U+2717) regex never matched.
17
+ // Net effect: a 12-failure suite shipped green (commit c6e34e1 / pipeline
18
+ // #5828). This is the same class as the documented 8-pipeline silent
19
+ // regression (CLAUDE.md / AGENTS.md Critical Gotchas).
20
+ //
21
+ // THE FIX:
22
+ // vitest's `--reporter=json --outputFile=<path>` writes a machine-readable
23
+ // result on completion. This script is the single authority on pass/fail.
24
+ // It is FAIL-CLOSED: any ambiguity (file missing, unparseable, truncated run,
25
+ // success!==true) exits non-zero. The only GREEN path is an explicit, complete,
26
+ // all-passing result.
27
+ //
28
+ // Robustness to the legacy vitest-2.1.9 tinypool exit-hang (#268): the JSON
29
+ // file is written at onFinished — AFTER all tests pass but BEFORE the hang —
30
+ // so a post-completion hang (whose non-zero exit the CI step swallows with
31
+ // `|| true`) still yields success:true here. A run killed mid-flight never
32
+ // writes a complete file, so it fails closed. Both behaviours are correct.
33
+ //
34
+ // USAGE:
35
+ // node scripts/ci/assert-vitest-green.mjs <result.json> [--min-tests=N] [--log=<path>]
36
+ // Exit 0 → suite is verifiably green. Exit 1 → fail (with a [ci] reason line).
37
+ //
38
+ // The caller MUST `rm -f` the result file before the vitest run so a stale
39
+ // file from a prior run on a reused shell-executor host cannot be mistaken for
40
+ // the current run's result.
41
+ //
42
+ // SELF-DIAGNOSING HANGS (--log):
43
+ // When the result JSON is missing/unreadable — the runner-contention hang case
44
+ // where vitest is killed before writing onFinished — an optional `--log=<path>`
45
+ // pointing at the captured `--reporter=default` stdout lets the verifier name
46
+ // the test files that were IN-FLIGHT at the kill (started with `❯ <file>` but
47
+ // never reached a `✓`/`×` completion marker). This turns a bare ENOENT into an
48
+ // actionable "these N files were running when the run died" hint. Purely
49
+ // additive: absent `--log` (or an unreadable/uninformative log) falls back to
50
+ // the existing bare message and the exit-code contract is unchanged.
51
+
52
+ import { readFileSync } from 'node:fs';
53
+
54
+ const DEFAULT_MIN_TESTS = 5000;
55
+
56
+ /**
57
+ * Verify a parsed vitest JSON result is a complete, all-passing run.
58
+ * Pure function — returns { ok, reason, summary } and never throws or exits.
59
+ * @param {unknown} result - parsed JSON (any shape; validated here)
60
+ * @param {{ minTests?: number }} [opts]
61
+ * @returns {{ ok: boolean, reason: string, summary: object }}
62
+ */
63
+ export function verifyVitestResult(result, opts = {}) {
64
+ const minTests = Number.isFinite(opts.minTests) ? opts.minTests : DEFAULT_MIN_TESTS;
65
+
66
+ if (result === null || typeof result !== 'object') {
67
+ return { ok: false, reason: 'result is not an object', summary: {} };
68
+ }
69
+
70
+ const numFailedTests = result.numFailedTests ?? null;
71
+ const numFailedTestSuites = result.numFailedTestSuites ?? null;
72
+ const numPassedTests = result.numPassedTests ?? null;
73
+ const numTotalTests = result.numTotalTests ?? null;
74
+ const success = result.success;
75
+
76
+ const summary = { success, numPassedTests, numFailedTests, numFailedTestSuites, numTotalTests };
77
+
78
+ // Shape guard: the required numeric fields must all be present. A partial /
79
+ // truncated JSON (e.g. a half-written file) lacks them → fail closed.
80
+ for (const [k, v] of Object.entries({ numFailedTests, numFailedTestSuites, numPassedTests, numTotalTests })) {
81
+ if (typeof v !== 'number' || !Number.isFinite(v)) {
82
+ return { ok: false, reason: `missing/invalid field "${k}" (truncated or wrong-shape JSON)`, summary };
83
+ }
84
+ }
85
+
86
+ // Failed-count guards run BEFORE the generic success flag so a real failure
87
+ // reports the actionable count ("12 failed test(s)") rather than the opaque
88
+ // "success is false". success!==true with zero counts is a separate edge.
89
+ if (numFailedTests > 0) {
90
+ return { ok: false, reason: `${numFailedTests} failed test(s)`, summary };
91
+ }
92
+ if (numFailedTestSuites > 0) {
93
+ return { ok: false, reason: `${numFailedTestSuites} failed test suite(s)`, summary };
94
+ }
95
+ if (success !== true) {
96
+ return { ok: false, reason: `success is ${JSON.stringify(success)} (expected true)`, summary };
97
+ }
98
+ // Floor guard: a suspiciously small run signals a truncated/partial/empty
99
+ // execution masquerading as green. The real suite is ~12.1k tests (2026-07-17).
100
+ if (numTotalTests < minTests) {
101
+ return {
102
+ ok: false,
103
+ reason: `only ${numTotalTests} total tests (< floor ${minTests}) — truncated or partial run`,
104
+ summary,
105
+ };
106
+ }
107
+
108
+ return { ok: true, reason: 'all tests passed', summary };
109
+ }
110
+
111
+ /**
112
+ * Read + verify a vitest JSON result file. Fail-closed on any read/parse error.
113
+ * @param {string} path
114
+ * @param {{ minTests?: number }} [opts]
115
+ * @returns {{ ok: boolean, reason: string, summary: object }}
116
+ */
117
+ export function assertVitestGreenFile(path, opts = {}) {
118
+ let raw;
119
+ try {
120
+ raw = readFileSync(path, 'utf8');
121
+ } catch (err) {
122
+ return { ok: false, reason: `cannot read result file "${path}": ${err.message}`, summary: {} };
123
+ }
124
+ let parsed;
125
+ try {
126
+ parsed = JSON.parse(raw);
127
+ } catch (err) {
128
+ return { ok: false, reason: `result file "${path}" is not valid JSON: ${err.message}`, summary: {} };
129
+ }
130
+ return verifyVitestResult(parsed, opts);
131
+ }
132
+
133
+ /**
134
+ * Parse a captured vitest `--reporter=default` log and return the test files
135
+ * that bear a `❯ <file>` lead glyph but never reached a per-file completion
136
+ * marker (`✓ <file>` / `× <file>`). The intent is to surface the "in-flight at
137
+ * kill" set — the files that were still running when the runner timed vitest
138
+ * out — so a hang dump names the likely culprit.
139
+ *
140
+ * BEST-EFFORT — DOES NOT reliably mark in-progress files in CI. This is a known
141
+ * limitation, not a bug:
142
+ * - The `❯ U+276F` glyph denotes "in-progress/queued" only on an INTERACTIVE
143
+ * TTY, where vitest live-updates the running-file list in place.
144
+ * - In non-TTY CI (`--reporter=default --no-color`, no live rewrite), `❯`
145
+ * instead marks FAILED files in the FINAL summary block — NOT in-progress.
146
+ * There is no per-file "started" line emitted mid-flight to key off.
147
+ * - Consequence: on a TRUE mid-flight hang (vitest killed before it writes the
148
+ * summary), there is often no `❯` line at all, so this hint returns [] —
149
+ * empty exactly when it would be most useful, and potentially misleading
150
+ * (matching a failed-summary file) when the run did reach the summary.
151
+ *
152
+ * A robust in-flight signal would need `--reporter=verbose` per-file START
153
+ * lines (which DO emit mid-flight). Wiring that in is deferred to a follow-up:
154
+ * it needs a captured real CI log to pin the exact start-line token format
155
+ * before changing the regex. THIS FUNCTION'S PARSE LOGIC IS UNCHANGED — the
156
+ * correction here is documentation-only.
157
+ *
158
+ * Pure function — never throws. Returns [] when the text is empty or no
159
+ * matching files are detectable.
160
+ *
161
+ * Marker glyphs (vitest default reporter, --no-color):
162
+ * ✓ U+2713 per-file PASS completion
163
+ * × U+00D7 per-file FAIL completion
164
+ * ❯ U+276F in-progress/queued on a TTY; FAILED-in-summary in non-TTY CI
165
+ * (see the BEST-EFFORT caveat above — the non-TTY meaning is why
166
+ * this hint can be empty/misleading on a real hang)
167
+ *
168
+ * @param {string} logText - raw captured reporter stdout
169
+ * @returns {string[]} sorted list of candidate test file paths (deduped)
170
+ */
171
+ export function inFlightFilesFromLog(logText) {
172
+ if (typeof logText !== 'string' || logText.length === 0) return [];
173
+
174
+ const started = new Set();
175
+ const completed = new Set();
176
+
177
+ // Lead glyph, optional indentation, then the file path up to a trailing
178
+ // " (N tests…" annotation or end-of-line. The default reporter emits the
179
+ // file path as the first token after the status glyph.
180
+ const STARTED = /[❯>]\s+(\S+\.(?:test|spec)\.[cm]?[jt]sx?)\b/;
181
+ const COMPLETED = /[✓×✗]\s+(\S+\.(?:test|spec)\.[cm]?[jt]sx?)\b/;
182
+
183
+ // Defense-in-depth (security-review Q2 NICE): the captured path is later
184
+ // printed to stderr in a CI log pane. `\S+` admits control/ESC bytes, so
185
+ // strip C0 + DEL before they reach the terminal — a malicious vitest log
186
+ // line cannot smuggle terminal-escape sequences through the hint.
187
+ // eslint-disable-next-line no-control-regex -- intentional: neutralizing C0 + DEL is the whole point
188
+ const stripCtrl = (s) => s.replace(/[\u0000-\u001f\u007f]/g, '?');
189
+
190
+ for (const line of logText.split('\n')) {
191
+ const c = COMPLETED.exec(line);
192
+ if (c) {
193
+ completed.add(stripCtrl(c[1]));
194
+ continue;
195
+ }
196
+ const s = STARTED.exec(line);
197
+ if (s) started.add(stripCtrl(s[1]));
198
+ }
199
+
200
+ const inFlight = [...started].filter((f) => !completed.has(f));
201
+ return inFlight.sort();
202
+ }
203
+
204
+ /**
205
+ * Read a log file and extract the in-flight set. Fail-soft: a missing or
206
+ * unreadable log yields [] (the caller falls back to the bare message).
207
+ * @param {string} path
208
+ * @returns {string[]}
209
+ */
210
+ export function inFlightFilesFromLogFile(path) {
211
+ let raw;
212
+ try {
213
+ raw = readFileSync(path, 'utf8');
214
+ } catch {
215
+ return [];
216
+ }
217
+ return inFlightFilesFromLog(raw);
218
+ }
219
+
220
+ function parseArgs(argv) {
221
+ const positional = [];
222
+ let minTests = DEFAULT_MIN_TESTS;
223
+ let logPath = null;
224
+ for (const arg of argv) {
225
+ const m = /^--min-tests=(\d+)$/.exec(arg);
226
+ const l = /^--log=(.+)$/.exec(arg);
227
+ if (m) minTests = Number(m[1]);
228
+ else if (l) logPath = l[1];
229
+ else positional.push(arg);
230
+ }
231
+ return { path: positional[0], minTests, logPath };
232
+ }
233
+
234
+ // CLI entry — only when run directly, not when imported by tests.
235
+ const isMain = import.meta.url === `file://${process.argv[1]}`;
236
+ if (isMain) {
237
+ const { path, minTests, logPath } = parseArgs(process.argv.slice(2));
238
+ if (!path) {
239
+ console.error('[ci] assert-vitest-green: missing <result.json> argument — failing closed');
240
+ process.exit(1);
241
+ }
242
+ const { ok, reason, summary } = assertVitestGreenFile(path, { minTests });
243
+ const s = summary || {};
244
+ console.log(
245
+ `[ci] vitest result: success=${s.success} passed=${s.numPassedTests} failed=${s.numFailedTests} ` +
246
+ `failedSuites=${s.numFailedTestSuites} total=${s.numTotalTests} (floor=${minTests})`,
247
+ );
248
+ if (ok) {
249
+ console.log(`[ci] ✓ suite verifiably green — ${reason}`);
250
+ process.exit(0);
251
+ }
252
+ console.error(`[ci] ✗ FAIL-CLOSED: ${reason}`);
253
+ // Self-diagnosing hint: the result JSON could not be READ (the hang case
254
+ // where vitest was killed before writing it). When a --log is supplied,
255
+ // surface the test files that were in-flight at the kill. This is purely an
256
+ // enriched stderr message — the exit-1 contract is unchanged.
257
+ if (logPath && reason.startsWith('cannot read result file')) {
258
+ const inFlight = inFlightFilesFromLogFile(logPath);
259
+ if (inFlight.length > 0) {
260
+ console.error(
261
+ `[ci] hint: ${inFlight.length} test file(s) in-flight when killed ` +
262
+ `(likely hang/slowdown): ${inFlight.join(', ')}`,
263
+ );
264
+ }
265
+ }
266
+ process.exit(1);
267
+ }
@@ -0,0 +1,435 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Install Session Orchestrator through Codex's public plugin lifecycle.
4
+ *
5
+ * Exit codes:
6
+ * 0 — installed, enabled, and verified
7
+ * 1 — argument or user-correctable environment error
8
+ * 2 — system, upstream command/JSON, or runtime postcondition failure
9
+ */
10
+
11
+ import { readFileSync } from 'node:fs';
12
+ import path from 'node:path';
13
+ import { spawnSync } from 'node:child_process';
14
+ import { fileURLToPath } from 'node:url';
15
+
16
+ import { validateCodexPluginContract } from './lib/codex/plugin-contract.mjs';
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const SCRIPT_DIR = path.dirname(__filename);
20
+ const SO_ROOT = path.dirname(SCRIPT_DIR);
21
+
22
+ const MIN_CODEX_VERSION = [0, 144, 4];
23
+ const MARKETPLACE_NAME = 'kanevry';
24
+ const PLUGIN_NAME = 'session-orchestrator';
25
+ const PLUGIN_ID = `${PLUGIN_NAME}@${MARKETPLACE_NAME}`;
26
+ const LEGACY_PLUGIN_IDS = [
27
+ `${PLUGIN_NAME}@openai-curated`,
28
+ `${PLUGIN_NAME}@local`,
29
+ ];
30
+ const CODEX_COMMAND_TIMEOUT_MS = 30_000;
31
+ const ERROR_CATEGORIES = Object.freeze({
32
+ USER: 'user',
33
+ SYSTEM: 'system',
34
+ });
35
+
36
+ class InstallerError extends Error {
37
+ constructor(message, category = ERROR_CATEGORIES.SYSTEM) {
38
+ super(message);
39
+ this.name = 'InstallerError';
40
+ this.category = category;
41
+ }
42
+ }
43
+
44
+ function parseArguments(argv) {
45
+ let json = false;
46
+ let help = false;
47
+ let version = false;
48
+
49
+ for (const argument of argv) {
50
+ if (argument === '--json') json = true;
51
+ else if (argument === '--help' || argument === '-h') help = true;
52
+ else if (argument === '--version') version = true;
53
+ else {
54
+ throw new InstallerError(
55
+ `Unknown argument '${argument}'. Run with --help for usage.`,
56
+ ERROR_CATEGORIES.USER,
57
+ );
58
+ }
59
+ }
60
+
61
+ return { json, help, version };
62
+ }
63
+
64
+ function printHelp() {
65
+ process.stdout.write(`Usage: node scripts/codex-install.mjs [options]
66
+
67
+ Install Session Orchestrator through the public Codex plugin lifecycle.
68
+
69
+ Options:
70
+ --json Print the verified final state as JSON
71
+ --version Print the package/plugin base version
72
+ -h, --help Show this help
73
+
74
+ Examples:
75
+ node scripts/codex-install.mjs
76
+ node scripts/codex-install.mjs --json
77
+ node scripts/codex-install.mjs --version
78
+ `);
79
+ }
80
+
81
+ function progress(jsonMode, message) {
82
+ if (!jsonMode) process.stdout.write(`${message}\n`);
83
+ }
84
+
85
+ function formatCommand(args) {
86
+ return ['codex', ...args].map((part) => (
87
+ /\s/.test(part) ? JSON.stringify(part) : part
88
+ )).join(' ');
89
+ }
90
+
91
+ function runCodex(args) {
92
+ const command = formatCommand(args);
93
+ const result = spawnSync('codex', args, {
94
+ encoding: 'utf8',
95
+ timeout: CODEX_COMMAND_TIMEOUT_MS,
96
+ });
97
+
98
+ if (result.error) {
99
+ throw new InstallerError(`Cannot run '${command}': ${result.error.message}`);
100
+ }
101
+ if (result.status !== 0) {
102
+ const diagnostic = (result.stderr || result.stdout || '').trim() || 'no diagnostic output';
103
+ throw new InstallerError(`Command failed with exit ${String(result.status)}: ${command}\n${diagnostic}`);
104
+ }
105
+
106
+ return result.stdout;
107
+ }
108
+
109
+ function runCodexJson(args, label) {
110
+ const stdout = runCodex(args);
111
+ try {
112
+ const parsed = JSON.parse(stdout);
113
+ if (!isRecord(parsed)) {
114
+ throw new Error('top-level value must be an object');
115
+ }
116
+ return parsed;
117
+ } catch (error) {
118
+ throw new InstallerError(
119
+ `${label} returned malformed JSON from '${formatCommand(args)}': ${error.message}`,
120
+ );
121
+ }
122
+ }
123
+
124
+ function parseCodexVersion(output) {
125
+ const match = output.match(/\b(\d+)\.(\d+)\.(\d+)(?:[-+][^\s]+)?\b/);
126
+ if (!match) {
127
+ throw new InstallerError(`Cannot parse Codex version from: ${output.trim() || '<empty output>'}`);
128
+ }
129
+ return match.slice(1, 4).map(Number);
130
+ }
131
+
132
+ function compareVersions(left, right) {
133
+ for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
134
+ const delta = (left[index] ?? 0) - (right[index] ?? 0);
135
+ if (delta !== 0) return Math.sign(delta);
136
+ }
137
+ return 0;
138
+ }
139
+
140
+ function formatVersion(version) {
141
+ return version.join('.');
142
+ }
143
+
144
+ function parseFeatures(output) {
145
+ const features = new Map();
146
+ for (const line of output.split(/\r?\n/)) {
147
+ const match = line.match(/^(\S+)\s+(.+?)\s+(true|false)\s*$/);
148
+ if (!match) continue;
149
+ features.set(match[1], { state: match[2].trim(), enabled: match[3] === 'true' });
150
+ }
151
+ return features;
152
+ }
153
+
154
+ function requireStableFeature(features, name) {
155
+ const feature = features.get(name);
156
+ if (feature?.state !== 'stable' || feature.enabled !== true) {
157
+ const actual = feature ? `${feature.state} ${String(feature.enabled)}` : 'missing';
158
+ throw new InstallerError(
159
+ `Codex feature '${name}' must report 'stable true'; got '${actual}'. `
160
+ + `Upgrade Codex and verify with 'codex features list'.`,
161
+ ERROR_CATEGORIES.USER,
162
+ );
163
+ }
164
+ }
165
+
166
+ function readLocalJson(relativePath, label) {
167
+ try {
168
+ return JSON.parse(readFileSync(path.join(SO_ROOT, relativePath), 'utf8'));
169
+ } catch (error) {
170
+ throw new InstallerError(`Cannot read valid ${label}: ${error.message}`);
171
+ }
172
+ }
173
+
174
+ function readBaseVersion() {
175
+ const packageJson = readLocalJson('package.json', 'package.json');
176
+ if (typeof packageJson.version !== 'string' || packageJson.version.trim() === '') {
177
+ throw new InstallerError('package.json must contain a non-empty version string.');
178
+ }
179
+ return packageJson.version;
180
+ }
181
+
182
+ function validateLocalContract() {
183
+ const expectedBaseVersion = readBaseVersion();
184
+ const manifest = readLocalJson(path.join('.codex-plugin', 'plugin.json'), 'Codex plugin manifest');
185
+ const verdict = validateCodexPluginContract({
186
+ pluginRoot: SO_ROOT,
187
+ expectedBaseVersion,
188
+ });
189
+
190
+ if (!verdict.ok) {
191
+ const details = verdict.errors
192
+ .map((error) => `[${error.rule}] ${error.path}: ${error.message}`)
193
+ .join('\n');
194
+ throw new InstallerError(`Local Codex plugin contract failed:\n${details}`);
195
+ }
196
+ if (manifest.name !== PLUGIN_NAME || typeof manifest.version !== 'string') {
197
+ throw new InstallerError('Codex plugin manifest must contain the expected name and version.');
198
+ }
199
+
200
+ return manifest.version;
201
+ }
202
+
203
+ function requireArray(value, label) {
204
+ if (!Array.isArray(value)) {
205
+ throw new InstallerError(`${label} must be an array in Codex JSON output.`);
206
+ }
207
+ return value;
208
+ }
209
+
210
+ function sameLocalPath(left, right) {
211
+ return typeof left === 'string' && path.resolve(left) === path.resolve(right);
212
+ }
213
+
214
+ function assertMarketplaceCompatible(payload) {
215
+ const marketplaces = requireArray(payload.marketplaces, 'marketplaces');
216
+ const matches = marketplaces.filter((entry) => isRecord(entry) && entry.name === MARKETPLACE_NAME);
217
+
218
+ if (matches.length > 1) {
219
+ throw new InstallerError(
220
+ `Codex reports multiple '${MARKETPLACE_NAME}' marketplaces. `
221
+ + `Inspect them with 'codex plugin marketplace list --json'; this installer will not remove any marketplace.`,
222
+ ERROR_CATEGORIES.USER,
223
+ );
224
+ }
225
+ if (matches.length === 0) return;
226
+
227
+ const existing = matches[0];
228
+ const sourceType = existing.marketplaceSource?.sourceType;
229
+ const source = existing.marketplaceSource?.source ?? existing.root;
230
+ if (sourceType !== 'local' || !sameLocalPath(source, SO_ROOT)) {
231
+ throw new InstallerError(
232
+ `Marketplace '${MARKETPLACE_NAME}' already points to '${String(source)}' (${String(sourceType)}), `
233
+ + `not '${SO_ROOT}'. Resolve the conflict manually after reviewing `
234
+ + `'codex plugin marketplace list --json'; this installer will not remove or replace it.`,
235
+ ERROR_CATEGORIES.USER,
236
+ );
237
+ }
238
+ }
239
+
240
+ function assertMarketplaceAddResult(payload) {
241
+ if (payload.marketplaceName !== MARKETPLACE_NAME) {
242
+ throw new InstallerError(
243
+ `Marketplace add returned '${String(payload.marketplaceName)}', expected '${MARKETPLACE_NAME}'.`,
244
+ );
245
+ }
246
+ if (!sameLocalPath(payload.installedRoot, SO_ROOT)) {
247
+ throw new InstallerError(
248
+ `Marketplace add returned root '${String(payload.installedRoot)}', expected '${SO_ROOT}'.`,
249
+ );
250
+ }
251
+ if (typeof payload.alreadyAdded !== 'boolean') {
252
+ throw new InstallerError("Marketplace add JSON is missing boolean field 'alreadyAdded'.");
253
+ }
254
+ }
255
+
256
+ function assertPluginAddResult(payload, expectedVersion) {
257
+ if (payload.pluginId !== PLUGIN_ID) {
258
+ throw new InstallerError(`Plugin add returned '${String(payload.pluginId)}', expected '${PLUGIN_ID}'.`);
259
+ }
260
+ if (payload.version !== expectedVersion) {
261
+ throw new InstallerError(
262
+ `Plugin add returned version '${String(payload.version)}', expected '${expectedVersion}'.`,
263
+ );
264
+ }
265
+ }
266
+
267
+ function pluginEntries(payload) {
268
+ const installed = requireArray(payload.installed, 'installed plugins');
269
+ const available = requireArray(payload.available, 'available plugins');
270
+ return { installed, available, all: [...installed, ...available] };
271
+ }
272
+
273
+ function assertTargetHealthy(payload, expectedVersion, phase) {
274
+ const entries = pluginEntries(payload);
275
+ const matches = entries.all.filter((entry) => isRecord(entry) && entry.pluginId === PLUGIN_ID);
276
+
277
+ if (matches.length !== 1) {
278
+ throw new InstallerError(
279
+ `${phase}: expected exactly one '${PLUGIN_ID}' entry, found ${matches.length}.`,
280
+ );
281
+ }
282
+
283
+ const target = matches[0];
284
+ if (target.installed !== true || target.enabled !== true) {
285
+ throw new InstallerError(
286
+ `${phase}: '${PLUGIN_ID}' must be installed and enabled; got installed=${String(target.installed)}, `
287
+ + `enabled=${String(target.enabled)}.`,
288
+ );
289
+ }
290
+ if (target.version !== expectedVersion) {
291
+ throw new InstallerError(
292
+ `${phase}: '${PLUGIN_ID}' version '${String(target.version)}' does not match manifest `
293
+ + `'${expectedVersion}'.`,
294
+ );
295
+ }
296
+
297
+ return entries;
298
+ }
299
+
300
+ function installedLegacyPluginIds(entries) {
301
+ return LEGACY_PLUGIN_IDS.filter((pluginId) => entries.installed.some((entry) => (
302
+ isRecord(entry) && entry.pluginId === pluginId && entry.installed === true
303
+ )));
304
+ }
305
+
306
+ function assertRemoveResult(payload, pluginId) {
307
+ if (payload.pluginId !== pluginId) {
308
+ throw new InstallerError(
309
+ `Plugin remove returned '${String(payload.pluginId)}', expected '${pluginId}'.`,
310
+ );
311
+ }
312
+ }
313
+
314
+ function isRecord(value) {
315
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
316
+ }
317
+
318
+ function install({ json }) {
319
+ progress(json, 'Session Orchestrator — Codex Setup');
320
+ progress(json, '=================================');
321
+
322
+ const version = parseCodexVersion(runCodex(['--version']));
323
+ if (compareVersions(version, MIN_CODEX_VERSION) < 0) {
324
+ throw new InstallerError(
325
+ `Codex ${formatVersion(version)} is unsupported; install Codex ${formatVersion(MIN_CODEX_VERSION)} or newer.`,
326
+ ERROR_CATEGORIES.USER,
327
+ );
328
+ }
329
+ progress(json, `Codex: ${formatVersion(version)}`);
330
+
331
+ const features = parseFeatures(runCodex(['features', 'list']));
332
+ requireStableFeature(features, 'plugins');
333
+ requireStableFeature(features, 'hooks');
334
+ progress(json, 'Features: plugins stable true; hooks stable true');
335
+
336
+ const expectedVersion = validateLocalContract();
337
+ progress(json, `Local contract: valid (${expectedVersion})`);
338
+
339
+ const marketplaceList = runCodexJson(
340
+ ['plugin', 'marketplace', 'list', '--json'],
341
+ 'Marketplace list',
342
+ );
343
+ assertMarketplaceCompatible(marketplaceList);
344
+
345
+ progress(json, `Marketplace: adding '${SO_ROOT}'`);
346
+ const marketplaceAdd = runCodexJson(
347
+ ['plugin', 'marketplace', 'add', SO_ROOT, '--json'],
348
+ 'Marketplace add',
349
+ );
350
+ assertMarketplaceAddResult(marketplaceAdd);
351
+ progress(
352
+ json,
353
+ marketplaceAdd.alreadyAdded
354
+ ? `Marketplace: '${MARKETPLACE_NAME}' already uses this source; refreshed`
355
+ : `Marketplace: '${MARKETPLACE_NAME}' added`,
356
+ );
357
+
358
+ progress(json, `Plugin: adding '${PLUGIN_ID}'`);
359
+ const pluginAdd = runCodexJson(
360
+ ['plugin', 'add', PLUGIN_ID, '--json'],
361
+ 'Plugin add',
362
+ );
363
+ assertPluginAddResult(pluginAdd, expectedVersion);
364
+
365
+ const firstPluginList = runCodexJson(
366
+ ['plugin', 'list', '--available', '--json'],
367
+ 'Plugin list',
368
+ );
369
+ const firstEntries = assertTargetHealthy(firstPluginList, expectedVersion, 'Post-install check');
370
+ progress(json, `Plugin: '${PLUGIN_ID}' is installed, enabled, and at ${expectedVersion}`);
371
+
372
+ const removedLegacyPlugins = [];
373
+ for (const legacyPluginId of installedLegacyPluginIds(firstEntries)) {
374
+ const removeResult = runCodexJson(
375
+ ['plugin', 'remove', legacyPluginId, '--json'],
376
+ `Plugin remove (${legacyPluginId})`,
377
+ );
378
+ assertRemoveResult(removeResult, legacyPluginId);
379
+ removedLegacyPlugins.push(legacyPluginId);
380
+ progress(json, `Removed legacy plugin: ${legacyPluginId}`);
381
+ }
382
+
383
+ const finalPluginList = runCodexJson(
384
+ ['plugin', 'list', '--available', '--json'],
385
+ 'Final plugin list',
386
+ );
387
+ const finalEntries = assertTargetHealthy(finalPluginList, expectedVersion, 'Final check');
388
+ const remainingLegacyPlugins = installedLegacyPluginIds(finalEntries);
389
+ if (remainingLegacyPlugins.length > 0) {
390
+ throw new InstallerError(
391
+ `Final check: legacy plugins remain installed: ${remainingLegacyPlugins.join(', ')}.`,
392
+ );
393
+ }
394
+
395
+ const result = {
396
+ ok: true,
397
+ codexVersion: formatVersion(version),
398
+ marketplace: MARKETPLACE_NAME,
399
+ marketplaceSource: SO_ROOT,
400
+ marketplaceAlreadyAdded: marketplaceAdd.alreadyAdded,
401
+ pluginId: PLUGIN_ID,
402
+ pluginVersion: expectedVersion,
403
+ installed: true,
404
+ enabled: true,
405
+ removedLegacyPlugins,
406
+ nextSteps: [
407
+ 'Start a fresh Codex task or fully restart Codex so the plugin and hooks reload.',
408
+ 'In the fresh task, run /hooks and review the hook bundle before approving it.',
409
+ 'This installer does not write or bypass hook trust.',
410
+ ],
411
+ };
412
+
413
+ if (json) {
414
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
415
+ } else {
416
+ process.stdout.write('\nDone. The public Codex plugin state is healthy.\n\n');
417
+ process.stdout.write('Next steps:\n');
418
+ for (const [index, step] of result.nextSteps.entries()) {
419
+ process.stdout.write(` ${index + 1}. ${step}\n`);
420
+ }
421
+ }
422
+ }
423
+
424
+ try {
425
+ const options = parseArguments(process.argv.slice(2));
426
+ if (options.help) printHelp();
427
+ else if (options.version) process.stdout.write(`${readBaseVersion()}\n`);
428
+ else install(options);
429
+ } catch (error) {
430
+ const message = error instanceof Error ? error.message : String(error);
431
+ process.stderr.write(`ERROR: ${message}\n`);
432
+ process.exitCode = error instanceof InstallerError && error.category === ERROR_CATEGORIES.USER
433
+ ? 1
434
+ : 2;
435
+ }