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,241 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # MCP stdio server for session-orchestrator
5
+ # Speaks JSON-RPC 2.0 over stdin/stdout
6
+ #
7
+ # Exposes two read-only tools:
8
+ # - session_config — reads Session Config from the project instruction file
9
+ # (CLAUDE.md, or AGENTS.md alias on Codex CLI — see
10
+ # skills/_shared/instruction-file-resolution.md)
11
+ # - session_metrics — reads last 5 session metrics entries
12
+
13
+ # ---------------------------------------------------------------------------
14
+ # Helpers
15
+ # ---------------------------------------------------------------------------
16
+
17
+ respond() {
18
+ # $id is expected to be valid JSON already (a quoted string, a number, or the
19
+ # literal null — see the main loop's id extraction). Rebuild via jq so the id
20
+ # and result are re-encoded as valid JSON regardless of their original type.
21
+ local id="$1" result="$2"
22
+ jq -nc --argjson id "$id" --argjson result "$result" \
23
+ '{jsonrpc:"2.0",id:$id,result:$result}'
24
+ }
25
+
26
+ respond_error() {
27
+ # $id is valid JSON (quoted string / number / null). $code is numeric
28
+ # (--argjson); $msg is an arbitrary string (--arg, jq quotes + escapes it).
29
+ local id="$1" code="$2" msg="$3"
30
+ jq -nc --argjson id "$id" --argjson code "$code" --arg msg "$msg" \
31
+ '{jsonrpc:"2.0",id:$id,error:{code:$code,message:$msg}}'
32
+ }
33
+
34
+ text_content() {
35
+ local text="$1"
36
+ jq -nc --arg t "$text" '{"content":[{"type":"text","text":$t}]}'
37
+ }
38
+
39
+ # ---------------------------------------------------------------------------
40
+ # Verify jq is available (fatal — we cannot parse JSON without it)
41
+ # ---------------------------------------------------------------------------
42
+ if ! command -v jq >/dev/null 2>&1; then
43
+ # Emit a single error and exit; without jq we cannot operate
44
+ printf '{"jsonrpc":"2.0","id":null,"error":{"code":-32603,"message":"jq is required but not found in PATH"}}\n'
45
+ exit 1
46
+ fi
47
+
48
+ # ---------------------------------------------------------------------------
49
+ # Protocol handlers
50
+ # ---------------------------------------------------------------------------
51
+
52
+ handle_initialize() {
53
+ local id="$1"
54
+ local result
55
+ result=$(jq -nc '{
56
+ "protocolVersion": "2024-11-05",
57
+ "capabilities": {"tools": {}},
58
+ "serverInfo": {
59
+ "name": "session-orchestrator",
60
+ "version": "2.0.0"
61
+ }
62
+ }')
63
+ respond "$id" "$result"
64
+ }
65
+
66
+ handle_tools_list() {
67
+ local id="$1"
68
+ local result
69
+ result=$(jq -nc '{
70
+ "tools": [
71
+ {
72
+ "name": "session_config",
73
+ "description": "Reads Session Config section from the project instruction file (CLAUDE.md or AGENTS.md alias)",
74
+ "inputSchema": {"type": "object", "properties": {}, "required": []}
75
+ },
76
+ {
77
+ "name": "session_metrics",
78
+ "description": "Reads the last 5 session metrics entries from .orchestrator/metrics/sessions.jsonl",
79
+ "inputSchema": {"type": "object", "properties": {}, "required": []}
80
+ }
81
+ ]
82
+ }')
83
+ respond "$id" "$result"
84
+ }
85
+
86
+ handle_tools_call() {
87
+ local id="$1" line="$2"
88
+
89
+ local tool_name
90
+ tool_name=$(printf '%s' "$line" | jq -r '.params.name // empty' 2>/dev/null) || true
91
+
92
+ case "$tool_name" in
93
+ session_config)
94
+ tool_session_config "$id"
95
+ ;;
96
+ session_metrics)
97
+ tool_session_metrics "$id"
98
+ ;;
99
+ *)
100
+ respond_error "$id" -32602 "Unknown tool: $tool_name"
101
+ ;;
102
+ esac
103
+ }
104
+
105
+ # ---------------------------------------------------------------------------
106
+ # Tool implementations
107
+ # ---------------------------------------------------------------------------
108
+
109
+ tool_session_config() {
110
+ local id="$1"
111
+ local project_root
112
+ project_root=$(git rev-parse --show-toplevel 2>/dev/null) || {
113
+ respond "$id" "$(text_content "Error: not inside a git repository")"
114
+ return
115
+ }
116
+
117
+ # Resolve project-instruction file (CLAUDE.md or AGENTS.md alias).
118
+ # See skills/_shared/instruction-file-resolution.md for the alias rule.
119
+ local instr_file=""
120
+ if [[ -s "$project_root/CLAUDE.md" ]]; then
121
+ instr_file="$project_root/CLAUDE.md"
122
+ elif [[ -s "$project_root/AGENTS.md" ]]; then
123
+ instr_file="$project_root/AGENTS.md"
124
+ fi
125
+ if [[ -z "$instr_file" ]]; then
126
+ respond "$id" "$(text_content "No CLAUDE.md or AGENTS.md found at $project_root")"
127
+ return
128
+ fi
129
+
130
+ # Extract everything from "## Session Config" to the next heading or EOF
131
+ local config
132
+ config=$(sed -n '/^## Session Config$/,/^## /{/^## Session Config$/d;/^## /d;p;}' "$instr_file" 2>/dev/null) || true
133
+
134
+ if [[ -z "$config" ]]; then
135
+ respond "$id" "$(text_content "No '## Session Config' section found in $instr_file")"
136
+ return
137
+ fi
138
+
139
+ respond "$id" "$(text_content "$config")"
140
+ }
141
+
142
+ tool_session_metrics() {
143
+ local id="$1"
144
+ local project_root
145
+ project_root=$(git rev-parse --show-toplevel 2>/dev/null) || {
146
+ respond "$id" "$(text_content "Error: not inside a git repository")"
147
+ return
148
+ }
149
+
150
+ local metrics_file="$project_root/.orchestrator/metrics/sessions.jsonl"
151
+ if [[ ! -f "$metrics_file" ]]; then
152
+ metrics_file="$project_root/.claude/metrics/sessions.jsonl"
153
+ fi
154
+ if [[ ! -f "$metrics_file" ]]; then
155
+ respond "$id" "$(text_content "No metrics found (checked .orchestrator/metrics/ and .claude/metrics/)")"
156
+ return
157
+ fi
158
+
159
+ local entries
160
+ entries=$(tail -n 5 "$metrics_file" 2>/dev/null) || true
161
+
162
+ if [[ -z "$entries" ]]; then
163
+ respond "$id" "$(text_content "No metrics found (file is empty)")"
164
+ return
165
+ fi
166
+
167
+ # Derive a token summary from the most-recent record that carries token totals.
168
+ # Fields total_token_input / total_token_output / subagents_with_tokens are
169
+ # optional (null when no subagent token data was captured for that session).
170
+ # Low coverage (subagents_with_tokens == 0 while matched_records > 0) means
171
+ # the total is PARTIAL — do not read it as "free / zero cost".
172
+ local token_summary
173
+ # Use -Rrs (raw-input + slurp + raw-output) so jq receives the multi-line
174
+ # JSONL block as a single string, can split + parse each line independently,
175
+ # and outputs plain text (no surrounding JSON quotes on the result string).
176
+ # The plain -r flag alone does not work for multi-record JSONL piped as one
177
+ # string — it treats the entire input as a single JSON value.
178
+ token_summary=$(printf '%s' "$entries" | \
179
+ jq -Rrs '
180
+ # Parse each non-empty line as JSON; skip malformed lines.
181
+ [ split("\n")[] | select(length > 0) | (try fromjson catch null) | select(. != null) ]
182
+ | reverse
183
+ | ( map(select( (.total_token_input != null) or (.total_token_output != null) )) | first ) as $rec
184
+ | if $rec then
185
+ "tokens: \($rec.total_token_input // "?") in / \($rec.total_token_output // "?") out" +
186
+ " (coverage: \($rec.subagents_with_tokens // 0) subagents)" +
187
+ ( if ($rec.subagents_with_tokens // 0) == 0 then
188
+ " ⚠ partial — subagent token data missing; total is not a reliable cost estimate"
189
+ else "" end ) +
190
+ " [session: \($rec.session_id // "unknown")]"
191
+ else
192
+ "tokens: no token data in last 5 sessions (subagent telemetry not yet captured)"
193
+ end
194
+ ' 2>/dev/null) || token_summary=""
195
+
196
+ local output
197
+ if [[ -n "$token_summary" ]]; then
198
+ output="${entries}
199
+
200
+ --- token summary ---
201
+ ${token_summary}"
202
+ else
203
+ output="$entries"
204
+ fi
205
+
206
+ respond "$id" "$(text_content "$output")"
207
+ }
208
+
209
+ # ---------------------------------------------------------------------------
210
+ # Main loop — read JSON-RPC messages from stdin, one per line
211
+ # ---------------------------------------------------------------------------
212
+
213
+ while IFS= read -r line; do
214
+ [[ -z "$line" ]] && continue
215
+
216
+ method=$(printf '%s' "$line" | jq -r '.method // empty' 2>/dev/null) || continue
217
+ # Extract id as VALID JSON (never bare, never empty): a quoted string ("foo"),
218
+ # a number (5), or the literal null. -c keeps it compact so it can be fed
219
+ # straight back into jq via --argjson in respond()/respond_error().
220
+ id=$(printf '%s' "$line" | jq -c '.id // null' 2>/dev/null) || id=null
221
+
222
+ case "$method" in
223
+ initialize)
224
+ handle_initialize "$id"
225
+ ;;
226
+ notifications/*)
227
+ # Notifications require no response
228
+ ;;
229
+ tools/list)
230
+ handle_tools_list "$id"
231
+ ;;
232
+ tools/call)
233
+ handle_tools_call "$id" "$line"
234
+ ;;
235
+ *)
236
+ # $id is already valid JSON (literal null when the request omitted it),
237
+ # so no ${id:-null} fallback is needed.
238
+ respond_error "$id" -32601 "Method not found: $method"
239
+ ;;
240
+ esac
241
+ done
@@ -0,0 +1,427 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * measure-policy-cache-effectiveness.mjs
4
+ *
5
+ * Validates whether the quality-gates baseline cache (#258) is effective under
6
+ * Claude Code's subprocess-per-call hook model, where each hook invocation
7
+ * spawns a fresh Node.js process (erasing all in-process state).
8
+ *
9
+ * Two cache layers are measured:
10
+ *
11
+ * 1. quality-gates-cache.mjs — JSONL file-based baseline-result cache.
12
+ * Persists to .orchestrator/metrics/baseline-results.jsonl. Survives
13
+ * subprocess boundaries because it reads/writes disk on every call.
14
+ *
15
+ * 2. quality-gates-policy.mjs — policy file loader. Reads
16
+ * .orchestrator/policy/quality-gates.json synchronously. No in-process
17
+ * memoisation — every call re-reads the file.
18
+ *
19
+ * Measurement model:
20
+ * - "subprocess-per-call" = spawn N child Node processes, each importing the
21
+ * module and calling the lookup once (simulates hook model).
22
+ * - "multi-call-in-process" = call the lookup M times in a single process
23
+ * (simulates repeated invocations in a long-running worker).
24
+ *
25
+ * Exit codes:
26
+ * 0 Measurement complete (JSON written to stdout).
27
+ * 1 Fatal setup error.
28
+ *
29
+ * Flags:
30
+ * --subprocess-count N Number of subprocesses to spawn (default 8).
31
+ * --inprocess-count M Calls per single-process warm test (default 5).
32
+ * --repo-root PATH Repo root to measure against (default: cwd).
33
+ * --json Machine-readable JSON output (default: human).
34
+ */
35
+
36
+ import { spawnSync } from 'node:child_process';
37
+ import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'node:fs';
38
+ import { join, resolve } from 'node:path';
39
+ import { tmpdir } from 'node:os';
40
+ import { fileURLToPath } from 'node:url';
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // CLI flags
44
+ // ---------------------------------------------------------------------------
45
+
46
+ const args = process.argv.slice(2);
47
+ function flagValue(name, defaultVal) {
48
+ const idx = args.indexOf(name);
49
+ if (idx === -1) return defaultVal;
50
+ return args[idx + 1] ?? defaultVal;
51
+ }
52
+ const flagBool = (name) => args.includes(name);
53
+
54
+ const SUBPROCESS_COUNT = parseInt(flagValue('--subprocess-count', '8'), 10);
55
+ const INPROCESS_COUNT = parseInt(flagValue('--inprocess-count', '5'), 10);
56
+ const _REPO_ROOT = resolve(flagValue('--repo-root', process.cwd()));
57
+ const JSON_MODE = flagBool('--json');
58
+
59
+ const SCRIPT_DIR = fileURLToPath(new URL('.', import.meta.url));
60
+ const CACHE_MODULE = join(SCRIPT_DIR, 'lib', 'quality-gates-cache.mjs');
61
+ const POLICY_MODULE = join(SCRIPT_DIR, 'lib', 'quality-gates-policy.mjs');
62
+
63
+ // ---------------------------------------------------------------------------
64
+ // Helpers
65
+ // ---------------------------------------------------------------------------
66
+
67
+ function hrMs(hrStart) {
68
+ const [s, ns] = process.hrtime(hrStart);
69
+ return s * 1000 + ns / 1e6;
70
+ }
71
+
72
+ function median(arr) {
73
+ const sorted = [...arr].sort((a, b) => a - b);
74
+ const mid = Math.floor(sorted.length / 2);
75
+ return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
76
+ }
77
+
78
+ function mean(arr) {
79
+ return arr.reduce((s, v) => s + v, 0) / arr.length;
80
+ }
81
+
82
+ // ---------------------------------------------------------------------------
83
+ // Subprocess runner — each child does ONE cache/policy lookup and prints timing
84
+ // ---------------------------------------------------------------------------
85
+
86
+ /**
87
+ * Build a one-shot child script that imports the module and times the call.
88
+ * The child prints a single JSON line to stdout: { callMs: number, hit: boolean }
89
+ */
90
+ function buildChildScript_cache(repoRoot, sessionStartRef, _sessionId) {
91
+ return `
92
+ import { loadLatestBaselineResult, isCacheValid, shouldSkipIncremental } from ${JSON.stringify(CACHE_MODULE)};
93
+ const start = process.hrtime();
94
+ const record = loadLatestBaselineResult({ repoRoot: ${JSON.stringify(repoRoot)} });
95
+ const validity = isCacheValid({ repoRoot: ${JSON.stringify(repoRoot)}, latestRecord: record, currentSessionStartRef: ${JSON.stringify(sessionStartRef)} });
96
+ const [s, ns] = process.hrtime(start);
97
+ const callMs = s * 1000 + ns / 1e6;
98
+ console.log(JSON.stringify({ callMs, hit: validity.valid, reason: validity.reason }));
99
+ `;
100
+ }
101
+
102
+ function buildChildScript_policy(repoRoot) {
103
+ return `
104
+ import { loadQualityGatesPolicy } from ${JSON.stringify(POLICY_MODULE)};
105
+ const start = process.hrtime();
106
+ const policy = loadQualityGatesPolicy(${JSON.stringify(repoRoot)});
107
+ const [s, ns] = process.hrtime(start);
108
+ const callMs = s * 1000 + ns / 1e6;
109
+ console.log(JSON.stringify({ callMs, found: policy !== null }));
110
+ `;
111
+ }
112
+
113
+ function runChildScript(scriptSrc) {
114
+ const tmpDir = mkdtempSync(join(tmpdir(), 'pce-'));
115
+ const scriptPath = join(tmpDir, 'child.mjs');
116
+ try {
117
+ writeFileSync(scriptPath, scriptSrc, 'utf8');
118
+ const result = spawnSync(process.execPath, ['--input-type=module'], {
119
+ input: scriptSrc,
120
+ encoding: 'utf8',
121
+ timeout: 10_000,
122
+ });
123
+ return result;
124
+ } finally {
125
+ rmSync(tmpDir, { recursive: true, force: true });
126
+ }
127
+ }
128
+
129
+ // ---------------------------------------------------------------------------
130
+ // Setup: create a tmpdir repo with a seeded cache record
131
+ // ---------------------------------------------------------------------------
132
+
133
+ function setupTmpRepo() {
134
+ const tmpRepo = mkdtempSync(join(tmpdir(), 'pce-repo-'));
135
+ // Minimal package.json so computeDependencyHash has something to hash
136
+ writeFileSync(join(tmpRepo, 'package.json'), JSON.stringify({ name: 'test', version: '1.0.0' }), 'utf8');
137
+ // Minimal .orchestrator/policy directory (empty — no quality-gates.json)
138
+ mkdirSync(join(tmpRepo, '.orchestrator', 'policy'), { recursive: true });
139
+ return tmpRepo;
140
+ }
141
+
142
+ function teardownTmpRepo(tmpRepo) {
143
+ rmSync(tmpRepo, { recursive: true, force: true });
144
+ }
145
+
146
+ // ---------------------------------------------------------------------------
147
+ // Seed a valid baseline-results.jsonl into the tmp repo
148
+ // ---------------------------------------------------------------------------
149
+
150
+ async function seedCacheRecord(tmpRepo, sessionStartRef, sessionId) {
151
+ const { saveBaselineResult } = await import(CACHE_MODULE);
152
+ saveBaselineResult({
153
+ repoRoot: tmpRepo,
154
+ sessionId,
155
+ sessionStartRef,
156
+ results: {
157
+ typecheck: { status: 'pass', error_count: 0 },
158
+ test: { status: 'pass' },
159
+ lint: { status: 'pass' },
160
+ },
161
+ });
162
+ }
163
+
164
+ // ---------------------------------------------------------------------------
165
+ // Measurement A: cache reads across N subprocesses (subprocess-per-call model)
166
+ // ---------------------------------------------------------------------------
167
+
168
+ async function measureCacheSubprocessModel(tmpRepo, sessionStartRef, sessionId) {
169
+ const timings = [];
170
+ const hits = [];
171
+
172
+ for (let i = 0; i < SUBPROCESS_COUNT; i++) {
173
+ const script = buildChildScript_cache(tmpRepo, sessionStartRef, sessionId);
174
+ const wallStart = process.hrtime();
175
+ const result = runChildScript(script);
176
+ const wallMs = hrMs(wallStart);
177
+
178
+ if (result.status !== 0 || !result.stdout.trim()) {
179
+ timings.push(wallMs);
180
+ hits.push(false);
181
+ continue;
182
+ }
183
+ try {
184
+ const parsed = JSON.parse(result.stdout.trim());
185
+ // Use the child's self-reported timing (excludes Node.js startup overhead)
186
+ timings.push(parsed.callMs);
187
+ hits.push(parsed.hit);
188
+ } catch {
189
+ timings.push(wallMs);
190
+ hits.push(false);
191
+ }
192
+ }
193
+
194
+ return {
195
+ model: 'subprocess-per-call',
196
+ n: SUBPROCESS_COUNT,
197
+ timingsMs: timings,
198
+ meanMs: mean(timings),
199
+ medianMs: median(timings),
200
+ hitCount: hits.filter(Boolean).length,
201
+ hitRate: hits.filter(Boolean).length / SUBPROCESS_COUNT,
202
+ };
203
+ }
204
+
205
+ // ---------------------------------------------------------------------------
206
+ // Measurement B: cache reads in a single process (multi-call-in-process model)
207
+ // ---------------------------------------------------------------------------
208
+
209
+ async function measureCacheInProcessModel(tmpRepo, sessionStartRef) {
210
+ const { loadLatestBaselineResult, isCacheValid } = await import(CACHE_MODULE + '?bust=' + Date.now());
211
+ const timings = [];
212
+ const hits = [];
213
+
214
+ for (let i = 0; i < INPROCESS_COUNT; i++) {
215
+ const start = process.hrtime();
216
+ const record = loadLatestBaselineResult({ repoRoot: tmpRepo });
217
+ const validity = isCacheValid({ repoRoot: tmpRepo, latestRecord: record, currentSessionStartRef: sessionStartRef });
218
+ timings.push(hrMs(start));
219
+ hits.push(validity.valid);
220
+ }
221
+
222
+ return {
223
+ model: 'multi-call-in-process',
224
+ n: INPROCESS_COUNT,
225
+ timingsMs: timings,
226
+ coldMs: timings[0],
227
+ warmMs: timings.slice(1),
228
+ warmMeanMs: timings.length > 1 ? mean(timings.slice(1)) : null,
229
+ hitCount: hits.filter(Boolean).length,
230
+ hitRate: hits.filter(Boolean).length / INPROCESS_COUNT,
231
+ };
232
+ }
233
+
234
+ // ---------------------------------------------------------------------------
235
+ // Measurement C: policy file reads across N subprocesses
236
+ // ---------------------------------------------------------------------------
237
+
238
+ async function measurePolicySubprocessModel(tmpRepo) {
239
+ const timings = [];
240
+ const found = [];
241
+
242
+ for (let i = 0; i < SUBPROCESS_COUNT; i++) {
243
+ const script = buildChildScript_policy(tmpRepo);
244
+ const result = runChildScript(script);
245
+ if (result.status !== 0 || !result.stdout.trim()) {
246
+ timings.push(0);
247
+ found.push(false);
248
+ continue;
249
+ }
250
+ try {
251
+ const parsed = JSON.parse(result.stdout.trim());
252
+ timings.push(parsed.callMs);
253
+ found.push(parsed.found);
254
+ } catch {
255
+ timings.push(0);
256
+ found.push(false);
257
+ }
258
+ }
259
+
260
+ return {
261
+ model: 'policy-subprocess-per-call',
262
+ n: SUBPROCESS_COUNT,
263
+ timingsMs: timings,
264
+ meanMs: mean(timings),
265
+ medianMs: median(timings),
266
+ foundCount: found.filter(Boolean).length,
267
+ };
268
+ }
269
+
270
+ // ---------------------------------------------------------------------------
271
+ // Measurement D: policy file reads in a single process
272
+ // ---------------------------------------------------------------------------
273
+
274
+ async function measurePolicyInProcessModel(tmpRepo) {
275
+ // Dynamic import with cache-bust forces module re-evaluation for fresh measurement
276
+ const { loadQualityGatesPolicy } = await import(POLICY_MODULE + '?bust2=' + Date.now());
277
+ const timings = [];
278
+
279
+ for (let i = 0; i < INPROCESS_COUNT; i++) {
280
+ const start = process.hrtime();
281
+ loadQualityGatesPolicy(tmpRepo);
282
+ timings.push(hrMs(start));
283
+ }
284
+
285
+ return {
286
+ model: 'policy-multi-call-in-process',
287
+ n: INPROCESS_COUNT,
288
+ timingsMs: timings,
289
+ coldMs: timings[0],
290
+ warmMs: timings.slice(1),
291
+ warmMeanMs: timings.length > 1 ? mean(timings.slice(1)) : null,
292
+ };
293
+ }
294
+
295
+ // ---------------------------------------------------------------------------
296
+ // Main
297
+ // ---------------------------------------------------------------------------
298
+
299
+ async function main() {
300
+ const SESSION_START_REF = 'abc1234def5678';
301
+ const SESSION_ID = 'measure-pce-test-session';
302
+
303
+ const tmpRepo = setupTmpRepo();
304
+
305
+ try {
306
+ // Seed the JSONL cache with a valid record
307
+ await seedCacheRecord(tmpRepo, SESSION_START_REF, SESSION_ID);
308
+
309
+ // Run all four measurements
310
+ const [cacheSubprocess, cacheInProcess, policySubprocess, policyInProcess] = await Promise.all([
311
+ measureCacheSubprocessModel(tmpRepo, SESSION_START_REF, SESSION_ID),
312
+ measureCacheInProcessModel(tmpRepo, SESSION_START_REF),
313
+ measurePolicySubprocessModel(tmpRepo),
314
+ measurePolicyInProcessModel(tmpRepo),
315
+ ]);
316
+
317
+ const report = {
318
+ measured_at: new Date().toISOString(),
319
+ config: { subprocessCount: SUBPROCESS_COUNT, inprocessCount: INPROCESS_COUNT },
320
+ findings: {
321
+ cache: {
322
+ subprocess_model: cacheSubprocess,
323
+ inprocess_model: cacheInProcess,
324
+ // Key insight: cache survives subprocess boundaries (JSONL on disk)
325
+ // Hit rate across subprocesses is expected to be 1.0 when record is valid
326
+ persists_across_subprocesses: cacheSubprocess.hitRate === 1.0,
327
+ },
328
+ policy: {
329
+ subprocess_model: policySubprocess,
330
+ inprocess_model: policyInProcess,
331
+ // Policy loader has NO in-process memoisation — every call reads disk
332
+ // "warm" calls in-process are only marginally faster (OS page cache)
333
+ },
334
+ },
335
+ recommendation: deriveRecommendation(cacheSubprocess, cacheInProcess, policySubprocess, policyInProcess),
336
+ };
337
+
338
+ if (JSON_MODE) {
339
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
340
+ } else {
341
+ printHumanReport(report);
342
+ }
343
+
344
+ process.exit(0);
345
+ } finally {
346
+ teardownTmpRepo(tmpRepo);
347
+ }
348
+ }
349
+
350
+ function deriveRecommendation(cacheSubprocess, cacheInProcess, policySubprocess, _policyInProcess) {
351
+ const cacheHitsOk = cacheSubprocess.hitRate === 1.0;
352
+ const cacheFastEnough = cacheSubprocess.medianMs < 5; // 5ms threshold
353
+ const _policyFastEnough = policySubprocess.medianMs < 2; // 2ms threshold
354
+
355
+ if (cacheHitsOk && cacheFastEnough) {
356
+ return {
357
+ verdict: 'KEEP',
358
+ summary:
359
+ 'quality-gates-cache is effective under the subprocess-per-call model. ' +
360
+ 'The JSONL file-based persistence survives process boundaries. ' +
361
+ 'Call latency is within acceptable bounds.',
362
+ };
363
+ }
364
+ if (!cacheHitsOk) {
365
+ return {
366
+ verdict: 'INVESTIGATE',
367
+ summary:
368
+ 'Cache misses detected across subprocesses. The JSONL record may be ' +
369
+ 'invalid (session-ref-mismatch, dependency-changed, or ttl-expired). ' +
370
+ 'This is expected behaviour — the cache is correctly validating staleness.',
371
+ };
372
+ }
373
+ return {
374
+ verdict: 'KEEP_WITH_NOTE',
375
+ summary:
376
+ 'Cache is structurally effective (hits across processes) but call latency ' +
377
+ 'is above threshold. Consider OS page-cache warm-up or mtime shortcut.',
378
+ };
379
+ }
380
+
381
+ function printHumanReport(report) {
382
+ const { findings, recommendation } = report;
383
+ const cs = findings.cache.subprocess_model;
384
+ const ci = findings.cache.inprocess_model;
385
+ const ps = findings.policy.subprocess_model;
386
+ const pi = findings.policy.inprocess_model;
387
+
388
+ process.stdout.write('\n=== Policy-Cache Effectiveness Report ===\n\n');
389
+ process.stdout.write(`Measured at: ${report.measured_at}\n`);
390
+ process.stdout.write(`Config: ${report.config.subprocessCount} subprocesses × ${report.config.inprocessCount} in-process calls\n\n`);
391
+
392
+ process.stdout.write('--- Baseline-Result Cache (quality-gates-cache.mjs) ---\n');
393
+ process.stdout.write(` Model: subprocess-per-call\n`);
394
+ process.stdout.write(` Hit rate across ${cs.n} subprocesses : ${(cs.hitRate * 100).toFixed(0)}%\n`);
395
+ process.stdout.write(` Mean call time (self-reported) : ${cs.meanMs.toFixed(3)} ms\n`);
396
+ process.stdout.write(` Median call time : ${cs.medianMs.toFixed(3)} ms\n`);
397
+ process.stdout.write(` Persists across subprocess bounds : ${findings.cache.persists_across_subprocesses}\n\n`);
398
+
399
+ process.stdout.write(` Model: multi-call-in-process\n`);
400
+ process.stdout.write(` Cold call (call #1) : ${ci.coldMs.toFixed(3)} ms\n`);
401
+ if (ci.warmMeanMs !== null) {
402
+ process.stdout.write(` Warm mean (calls #2–${ci.n}) : ${ci.warmMeanMs.toFixed(3)} ms\n`);
403
+ }
404
+ process.stdout.write(` Hit rate : ${(ci.hitRate * 100).toFixed(0)}%\n\n`);
405
+
406
+ process.stdout.write('--- Policy File Loader (quality-gates-policy.mjs) ---\n');
407
+ process.stdout.write(` Model: subprocess-per-call\n`);
408
+ process.stdout.write(` Policy files found : ${ps.foundCount}/${ps.n}\n`);
409
+ process.stdout.write(` Mean call time (self-reported) : ${ps.meanMs.toFixed(3)} ms\n`);
410
+ process.stdout.write(` Median call time : ${ps.medianMs.toFixed(3)} ms\n\n`);
411
+
412
+ process.stdout.write(` Model: multi-call-in-process\n`);
413
+ process.stdout.write(` Cold call (call #1) : ${pi.coldMs.toFixed(3)} ms\n`);
414
+ if (pi.warmMeanMs !== null) {
415
+ process.stdout.write(` Warm mean (calls #2–${pi.n}) : ${pi.warmMeanMs.toFixed(3)} ms\n`);
416
+ }
417
+ process.stdout.write('\n');
418
+
419
+ process.stdout.write(`--- Recommendation ---\n`);
420
+ process.stdout.write(` Verdict : ${recommendation.verdict}\n`);
421
+ process.stdout.write(` Summary : ${recommendation.summary}\n\n`);
422
+ }
423
+
424
+ main().catch((err) => {
425
+ process.stderr.write(`Fatal: ${err.message}\n${err.stack}\n`);
426
+ process.exit(1);
427
+ });