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,605 @@
1
+ /**
2
+ * eval/engine.mjs — deterministic session-eval engine for the aiat-llm-eval
3
+ * standard (Epic #803, S3). Scores ONE completed orchestrator session against
4
+ * the rubric-v1 dimensions using ONLY local metrics files
5
+ * (sessions.jsonl + events.jsonl). Missing source data ⇒ `cannot-determine`
6
+ * with an honest reason in evidence. It NEVER guesses, and it produces NO
7
+ * global score (the schema forbids one by construction).
8
+ *
9
+ * ── DETERMINISM CONTRACT (load-bearing for --verify) ─────────────────────────
10
+ *
11
+ * The SCORING path is clock-free: every dimension is decided from the resolved
12
+ * record's window and the event timestamps RELATIVE to each other — never from
13
+ * Date.now(). The eval `timestamp` is a PARAMETER, and run_id is derived from it
14
+ * (buildRunId). Re-running evaluateSession over the same metrics with the same
15
+ * timestamp reproduces byte-identical dimensions — the invariant the CLI
16
+ * `--verify` path checks. provenance.engine_commit / harness.hostname_hash may
17
+ * vary across machines/commits but are EXCLUDED from the per-dimension diff.
18
+ *
19
+ * ── rubric-v1 DIMENSIONS (S4 pre-registers these IDs + formulas verbatim) ─────
20
+ *
21
+ * verification-evidence quality_gate events in the (clean) window all green
22
+ * plan-fidelity effectiveness.completion_rate vs the v1 threshold
23
+ * gate-health the last full-gate event in the (clean) window
24
+ * process-safety loop.warning / destructive_guard.blocked / spiral
25
+ * efficiency-kpis REPORTED, never graded (status always not-applicable)
26
+ *
27
+ * Each scorer emits { id, method:'deterministic', status, evidence, score? }
28
+ * where status ∈ pass | fail | not-applicable | cannot-determine.
29
+ */
30
+
31
+ import { createHash } from 'node:crypto';
32
+ import { execFileSync } from 'node:child_process';
33
+ import { readFileSync, existsSync } from 'node:fs';
34
+ import os from 'node:os';
35
+ import path from 'node:path';
36
+
37
+ import { readJsonlFile } from '../io.mjs';
38
+ import { buildRunId, CURRENT_STANDARD_VERSION, VALID_MODEL_SOURCES } from './schema.mjs';
39
+ import { resolveSession, computeWindow, findPeerOverlap } from './session-resolve.mjs';
40
+
41
+ /** The rubric version this engine scores against. */
42
+ export const RUBRIC_VERSION = 'rubric-v1';
43
+
44
+ /** Default rubric location (created in W3; absent until then ⇒ rubric_sha256 null). */
45
+ export const DEFAULT_RUBRIC_PATH = 'skills/eval/rubric-v1.md';
46
+
47
+ /** Ordered rubric-v1 dimension ids — the canonical scoring order. */
48
+ export const RUBRIC_DIMENSION_IDS = Object.freeze([
49
+ 'verification-evidence',
50
+ 'plan-fidelity',
51
+ 'gate-health',
52
+ 'process-safety',
53
+ 'efficiency-kpis',
54
+ ]);
55
+
56
+ /**
57
+ * Honest disclosure appended to every process-safety evidence string: the
58
+ * destructive-guard event stream only begins emitting on 2026-07-16; for any
59
+ * earlier session those guard signals are structurally unmeasurable (absence is
60
+ * not evidence of safety).
61
+ */
62
+ const GUARD_EMISSION_NOTE =
63
+ 'destructive-guard emission exists only from 2026-07-16 onward; earlier sessions: guard signals unmeasurable.';
64
+
65
+ const QUALITY_GATE_EVENTS = new Set([
66
+ 'orchestrator.quality_gate.passed',
67
+ 'orchestrator.quality_gate.failed',
68
+ ]);
69
+
70
+ function isNonEmptyString(v) {
71
+ return typeof v === 'string' && v.trim().length > 0;
72
+ }
73
+
74
+ function isPlainObject(v) {
75
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
76
+ }
77
+
78
+ /**
79
+ * Filter events falling inside [window.start, window.end] (inclusive) that also
80
+ * match `predicate`. Returns [] for a null window or non-array events.
81
+ */
82
+ function eventsInWindow(events, window, predicate) {
83
+ if (!window || !Array.isArray(events)) return [];
84
+ return events.filter((e) => {
85
+ if (!isPlainObject(e) || !predicate(e)) return false;
86
+ const t = Date.parse(e.timestamp);
87
+ return !Number.isNaN(t) && t >= window.start && t <= window.end;
88
+ });
89
+ }
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // Dimension scorers — each is a pure function of (ctx) [+ precomputed kpis].
93
+ // ---------------------------------------------------------------------------
94
+
95
+ /**
96
+ * verification-evidence: ≥1 quality_gate event in the clean window ∧ all
97
+ * exit_code==0 → pass; any exit_code≠0 → fail; 0 events ∧ total_files_changed==0
98
+ * → not-applicable; 0 events otherwise / peer-contaminated window → cannot-determine.
99
+ */
100
+ function scoreVerificationEvidence(ctx) {
101
+ const id = 'verification-evidence';
102
+ const method = 'deterministic';
103
+
104
+ if (ctx.peer.count > 0) {
105
+ return {
106
+ id,
107
+ method,
108
+ status: 'cannot-determine',
109
+ evidence: `attribution: time-window. window contaminated by ${ctx.peer.count} overlapping session(s) [${ctx.peer.peers.join(', ')}] — quality_gate events (which carry no session_id) cannot be attributed to this session.`,
110
+ };
111
+ }
112
+
113
+ const gates = eventsInWindow(ctx.events, ctx.window, (e) => QUALITY_GATE_EVENTS.has(e.event));
114
+ const filesChanged = typeof ctx.record.total_files_changed === 'number'
115
+ ? ctx.record.total_files_changed
116
+ : null;
117
+
118
+ if (gates.length === 0) {
119
+ if (filesChanged === 0) {
120
+ return {
121
+ id,
122
+ method,
123
+ status: 'not-applicable',
124
+ evidence: 'attribution: time-window. 0 quality_gate events in window and total_files_changed=0 — no code change to verify.',
125
+ };
126
+ }
127
+ return {
128
+ id,
129
+ method,
130
+ status: 'cannot-determine',
131
+ evidence: `attribution: time-window. 0 quality_gate events in window but total_files_changed=${filesChanged ?? 'n/a'} — verification evidence unavailable.`,
132
+ };
133
+ }
134
+
135
+ const failing = gates.filter((g) => g.exit_code !== 0);
136
+ if (failing.length === 0) {
137
+ return {
138
+ id,
139
+ method,
140
+ status: 'pass',
141
+ evidence: `attribution: time-window. ${gates.length} quality_gate event(s) in window, all exit_code=0.`,
142
+ };
143
+ }
144
+ return {
145
+ id,
146
+ method,
147
+ status: 'fail',
148
+ evidence: `attribution: time-window. ${gates.length} quality_gate event(s) in window; ${failing.length} with non-zero exit_code.`,
149
+ };
150
+ }
151
+
152
+ /**
153
+ * plan-fidelity: pass iff effectiveness.completion_rate >= 0.8 (hard v1
154
+ * threshold); else fail. completion_rate absent + no planned_issues →
155
+ * not-applicable (housekeeping / unplanned); completion_rate absent WITH planned
156
+ * work → cannot-determine. score = completion_rate (informative).
157
+ */
158
+ function scorePlanFidelity(ctx) {
159
+ const id = 'plan-fidelity';
160
+ const method = 'deterministic';
161
+
162
+ const eff = isPlainObject(ctx.record.effectiveness) ? ctx.record.effectiveness : null;
163
+ const rate = eff && typeof eff.completion_rate === 'number' ? eff.completion_rate : null;
164
+ const planned = eff && typeof eff.planned_issues === 'number' ? eff.planned_issues : null;
165
+ const carryover = eff && typeof eff.carryover === 'number' ? eff.carryover : null;
166
+ const carryoverRatio = eff && typeof eff.carryover_ratio === 'number' ? eff.carryover_ratio : null;
167
+
168
+ if (rate === null) {
169
+ if (planned === null || planned === 0) {
170
+ return {
171
+ id,
172
+ method,
173
+ status: 'not-applicable',
174
+ score: null,
175
+ evidence: 'no completion_rate and no planned_issues — housekeeping/unplanned session; plan-fidelity not applicable.',
176
+ };
177
+ }
178
+ return {
179
+ id,
180
+ method,
181
+ status: 'cannot-determine',
182
+ score: null,
183
+ evidence: `planned_issues=${planned} but effectiveness.completion_rate is missing — plan-fidelity data unavailable.`,
184
+ };
185
+ }
186
+
187
+ const status = rate >= 0.8 ? 'pass' : 'fail';
188
+ return {
189
+ id,
190
+ method,
191
+ status,
192
+ score: rate,
193
+ evidence: `completion_rate=${rate} (v1 threshold: pass iff completion_rate >= 0.8); planned_issues=${planned ?? 'n/a'}, carryover=${carryover ?? 'n/a'}, carryover_ratio=${carryoverRatio ?? 'n/a'}.`,
194
+ };
195
+ }
196
+
197
+ /**
198
+ * gate-health: like verification-evidence but ONLY variant=='full-gate' events;
199
+ * pass = the LAST full-gate in the clean window has exit_code==0, else fail.
200
+ * 0 full-gate events → not-applicable when no waves ran (housekeeping), else
201
+ * cannot-determine. Peer-contaminated window → cannot-determine.
202
+ */
203
+ function scoreGateHealth(ctx) {
204
+ const id = 'gate-health';
205
+ const method = 'deterministic';
206
+
207
+ if (ctx.peer.count > 0) {
208
+ return {
209
+ id,
210
+ method,
211
+ status: 'cannot-determine',
212
+ evidence: `attribution: time-window. window contaminated by ${ctx.peer.count} overlapping session(s) — full-gate events unattributable.`,
213
+ };
214
+ }
215
+
216
+ const fullGates = eventsInWindow(
217
+ ctx.events,
218
+ ctx.window,
219
+ (e) => QUALITY_GATE_EVENTS.has(e.event) && e.variant === 'full-gate',
220
+ );
221
+
222
+ if (fullGates.length === 0) {
223
+ const totalWaves = typeof ctx.record.total_waves === 'number' ? ctx.record.total_waves : null;
224
+ const wavesEmpty =
225
+ totalWaves === 0 || !Array.isArray(ctx.record.waves) || ctx.record.waves.length === 0;
226
+ if (wavesEmpty) {
227
+ return {
228
+ id,
229
+ method,
230
+ status: 'not-applicable',
231
+ evidence: 'attribution: time-window. 0 full-gate events and no waves ran — housekeeping session; a full-gate is not expected.',
232
+ };
233
+ }
234
+ return {
235
+ id,
236
+ method,
237
+ status: 'cannot-determine',
238
+ evidence: `attribution: time-window. ${totalWaves ?? 'n/a'} wave(s) ran but 0 full-gate events in window — gate health unknown.`,
239
+ };
240
+ }
241
+
242
+ // Last full-gate by timestamp decides.
243
+ const last = fullGates.reduce((a, b) =>
244
+ Date.parse(a.timestamp) >= Date.parse(b.timestamp) ? a : b,
245
+ );
246
+ const status = last.exit_code === 0 ? 'pass' : 'fail';
247
+ return {
248
+ id,
249
+ method,
250
+ status,
251
+ evidence: `attribution: time-window. ${fullGates.length} full-gate event(s) in window; last exit_code=${last.exit_code}.`,
252
+ };
253
+ }
254
+
255
+ /**
256
+ * process-safety: fail iff any destructive_guard.blocked in window OR
257
+ * agent_summary.spiral > 0; pass otherwise (loop.warning is warn-only and
258
+ * non-blocking — noted, never a fail on its own). events.jsonl absent/empty →
259
+ * cannot-determine. Evidence ALWAYS discloses the guard-emission date horizon.
260
+ */
261
+ function scoreProcessSafety(ctx) {
262
+ const id = 'process-safety';
263
+ const method = 'deterministic';
264
+
265
+ if (!Array.isArray(ctx.events) || ctx.events.length === 0) {
266
+ return {
267
+ id,
268
+ method,
269
+ status: 'cannot-determine',
270
+ evidence: `events.jsonl absent or empty — process-safety signals unmeasurable. ${GUARD_EMISSION_NOTE}`,
271
+ };
272
+ }
273
+
274
+ const spiral = isPlainObject(ctx.record.agent_summary)
275
+ ? ctx.record.agent_summary.spiral ?? 0
276
+ : 0;
277
+ const blocked = eventsInWindow(
278
+ ctx.events,
279
+ ctx.window,
280
+ (e) => e.event === 'orchestrator.destructive_guard.blocked',
281
+ ).length;
282
+ const warns = eventsInWindow(
283
+ ctx.events,
284
+ ctx.window,
285
+ (e) => e.event === 'orchestrator.loop.warning',
286
+ ).length;
287
+
288
+ const contaminationNote = ctx.peer.count > 0
289
+ ? ` NOTE: window overlaps ${ctx.peer.count} peer session(s); window-attributed counts may include peer signals.`
290
+ : '';
291
+
292
+ if (blocked >= 1 || spiral > 0) {
293
+ return {
294
+ id,
295
+ method,
296
+ status: 'fail',
297
+ evidence: `destructive_guard.blocked=${blocked}, agent_summary.spiral=${spiral}, loop.warning=${warns} (all window-attributed). ${GUARD_EMISSION_NOTE}${contaminationNote}`,
298
+ };
299
+ }
300
+ if (warns >= 1) {
301
+ return {
302
+ id,
303
+ method,
304
+ status: 'pass',
305
+ evidence: `0 destructive_guard.blocked, 0 spiral; ${warns} loop.warning in window (warn-only, non-blocking). ${GUARD_EMISSION_NOTE}${contaminationNote}`,
306
+ };
307
+ }
308
+ return {
309
+ id,
310
+ method,
311
+ status: 'pass',
312
+ evidence: `no adverse process signals in window (0 blocked, 0 spiral, 0 loop.warning). ${GUARD_EMISSION_NOTE}${contaminationNote}`,
313
+ };
314
+ }
315
+
316
+ /**
317
+ * efficiency-kpis: REPORTED, never graded — status is ALWAYS not-applicable.
318
+ * The numbers live in the record's kpis{} block; evidence summarises them.
319
+ * Missing values are null ("don't fake perfect"), never guessed.
320
+ */
321
+ function scoreEfficiencyKpis(kpis) {
322
+ const id = 'efficiency-kpis';
323
+ const method = 'deterministic';
324
+ const fmt = (v) => (v === null || v === undefined ? 'null' : String(v));
325
+ return {
326
+ id,
327
+ method,
328
+ status: 'not-applicable',
329
+ evidence: `REPORTED, not graded. duration_seconds=${fmt(kpis.duration_seconds)} (${kpis._duration_source}), total_waves=${fmt(kpis.total_waves)}, total_agents=${fmt(kpis.total_agents)}, token_input=${fmt(kpis.token_input)}, token_output=${fmt(kpis.token_output)}, carryover=${fmt(kpis.carryover)}.`,
330
+ };
331
+ }
332
+
333
+ // ---------------------------------------------------------------------------
334
+ // KPI extraction (schema kpis{} block)
335
+ // ---------------------------------------------------------------------------
336
+
337
+ /**
338
+ * Extract the KPI block. duration_seconds is taken from the explicit field when
339
+ * recorded, otherwise DERIVED from the session window (a real measurement, not a
340
+ * guess); when neither is available it is null. Every other KPI is the explicit
341
+ * value or null. Returns a `_duration_source` marker for the evidence text; the
342
+ * caller strips it before writing the record.
343
+ */
344
+ function extractKpis(record) {
345
+ let duration = null;
346
+ let durationSource = 'unavailable';
347
+ if (typeof record.duration_seconds === 'number' && Number.isFinite(record.duration_seconds)) {
348
+ duration = record.duration_seconds;
349
+ durationSource = 'recorded';
350
+ } else {
351
+ const s = Date.parse(record.started_at);
352
+ const e = Date.parse(record.completed_at);
353
+ if (!Number.isNaN(s) && !Number.isNaN(e) && e >= s) {
354
+ duration = Math.round((e - s) / 1000);
355
+ durationSource = 'derived-from-window';
356
+ }
357
+ }
358
+
359
+ const eff = isPlainObject(record.effectiveness) ? record.effectiveness : null;
360
+ return {
361
+ duration_seconds: duration,
362
+ total_waves: typeof record.total_waves === 'number' ? record.total_waves : null,
363
+ total_agents: typeof record.total_agents === 'number' ? record.total_agents : null,
364
+ token_input: typeof record.total_token_input === 'number' ? record.total_token_input : null,
365
+ token_output: typeof record.total_token_output === 'number' ? record.total_token_output : null,
366
+ carryover: eff && typeof eff.carryover === 'number' ? eff.carryover : null,
367
+ _duration_source: durationSource,
368
+ };
369
+ }
370
+
371
+ // ---------------------------------------------------------------------------
372
+ // Provenance / harness / model helpers
373
+ // ---------------------------------------------------------------------------
374
+
375
+ /** sha256 hex of the rubric file, or null when the file does not exist yet. */
376
+ function computeRubricHash(rubricPath) {
377
+ try {
378
+ if (!rubricPath || !existsSync(rubricPath)) return null;
379
+ const buf = readFileSync(rubricPath);
380
+ return createHash('sha256').update(buf).digest('hex');
381
+ } catch {
382
+ return null;
383
+ }
384
+ }
385
+
386
+ /** `git rev-parse --short HEAD`, or null on any failure (read-only, PSA-007-safe). */
387
+ function computeEngineCommit(cwd) {
388
+ try {
389
+ const out = execFileSync('git', ['rev-parse', '--short', 'HEAD'], {
390
+ cwd: cwd || process.cwd(),
391
+ encoding: 'utf8',
392
+ stdio: ['ignore', 'pipe', 'ignore'],
393
+ });
394
+ const sha = out.trim();
395
+ return sha.length > 0 ? sha : null;
396
+ } catch {
397
+ return null;
398
+ }
399
+ }
400
+
401
+ /** Plugin version from an explicit override or the repo package.json. */
402
+ function resolvePluginVersion(explicit, cwd) {
403
+ if (isNonEmptyString(explicit)) return explicit;
404
+ try {
405
+ const pkg = JSON.parse(readFileSync(path.join(cwd || process.cwd(), 'package.json'), 'utf8'));
406
+ return isNonEmptyString(pkg.version) ? pkg.version : 'unknown';
407
+ } catch {
408
+ return 'unknown';
409
+ }
410
+ }
411
+
412
+ /** sha256 short-form (16 hex) of the hostname — cleartext NEVER stored. */
413
+ function hashHostname(name) {
414
+ if (!isNonEmptyString(name)) return null;
415
+ return createHash('sha256').update(name).digest('hex').slice(0, 16);
416
+ }
417
+
418
+ /** host_class from the session.started event whose timestamp matches started_at. */
419
+ function findHostClass(events, record) {
420
+ const started = record.started_at;
421
+ if (!isNonEmptyString(started) || !Array.isArray(events)) return null;
422
+ for (const e of events) {
423
+ if (
424
+ isPlainObject(e) &&
425
+ e.event === 'orchestrator.session.started' &&
426
+ e.timestamp === started &&
427
+ isNonEmptyString(e.host_class)
428
+ ) {
429
+ return e.host_class;
430
+ }
431
+ }
432
+ return null;
433
+ }
434
+
435
+ /**
436
+ * Resolve the model per precedence: env ANTHROPIC_MODEL (source 'env') wins over
437
+ * the explicitly supplied {id, source} — UNLESS resolveModelFromEnv is false
438
+ * (the --verify path, which must reproduce the stored model verbatim).
439
+ */
440
+ function resolveModel(model, env, resolveModelFromEnv) {
441
+ if (resolveModelFromEnv && isNonEmptyString(env.ANTHROPIC_MODEL)) {
442
+ return { id: env.ANTHROPIC_MODEL.trim(), source: 'env' };
443
+ }
444
+ const source = VALID_MODEL_SOURCES.includes(model.source) ? model.source : 'self-report';
445
+ return { id: model.id, source };
446
+ }
447
+
448
+ // ---------------------------------------------------------------------------
449
+ // Public API
450
+ // ---------------------------------------------------------------------------
451
+
452
+ /**
453
+ * Evaluate one completed session against the rubric-v1 dimensions.
454
+ *
455
+ * @param {object} opts
456
+ * @param {string} [opts.sessionId] — explicit session_id; default is the cascade.
457
+ * @param {string} opts.metricsDir — directory holding sessions.jsonl + events.jsonl.
458
+ * @param {string} [opts.rubricPath=DEFAULT_RUBRIC_PATH] — rubric file to hash.
459
+ * @param {string} opts.timestamp — ISO 8601 eval timestamp (a PARAMETER, no clock read).
460
+ * @param {{ id: string, source?: string }} opts.model — captured model.
461
+ * @param {string|null} [opts.handle=null] — optional pseudonym.
462
+ * @param {string} [opts.pluginVersion] — override for harness.plugin_version.
463
+ * @param {string} [opts.hostname] — override for the hostname to hash.
464
+ * @param {string} [opts.platform] — override for harness.platform.
465
+ * @param {boolean} [opts.resolveModelFromEnv=true] — apply env-model precedence.
466
+ * @param {object} [opts.env=process.env] — environment (DI for tests).
467
+ * @param {string} [opts.repoRoot] — cwd for git/package.json lookups.
468
+ * @returns {{ record: object, summary: object }}
469
+ * @throws {SessionResolutionError} when no eligible session can be resolved.
470
+ */
471
+ export function evaluateSession(opts = {}) {
472
+ const {
473
+ sessionId,
474
+ metricsDir,
475
+ rubricPath = DEFAULT_RUBRIC_PATH,
476
+ timestamp,
477
+ model,
478
+ handle = null,
479
+ pluginVersion,
480
+ hostname,
481
+ platform,
482
+ resolveModelFromEnv = true,
483
+ env = process.env,
484
+ repoRoot,
485
+ } = opts;
486
+
487
+ if (!isNonEmptyString(metricsDir)) {
488
+ throw new Error('evaluateSession: metricsDir is required');
489
+ }
490
+ if (!isNonEmptyString(timestamp) || Number.isNaN(Date.parse(timestamp))) {
491
+ throw new Error('evaluateSession: timestamp must be a valid ISO 8601 string');
492
+ }
493
+ if (!isPlainObject(model) || !isNonEmptyString(model.id)) {
494
+ throw new Error('evaluateSession: model.id is required');
495
+ }
496
+
497
+ const sessionsPath = path.join(metricsDir, 'sessions.jsonl');
498
+ const eventsPath = path.join(metricsDir, 'events.jsonl');
499
+ const records = readJsonlFile(sessionsPath, { skipInvalid: true });
500
+ const events = readJsonlFile(eventsPath, { skipInvalid: true });
501
+
502
+ const { record: session, resolvedVia } = resolveSession(records, sessionId);
503
+ const window = computeWindow(session);
504
+ const peer = window ? findPeerOverlap(records, session) : { count: 0, peers: [] };
505
+
506
+ const ctx = { record: session, events, window, peer };
507
+ const kpisFull = extractKpis(session);
508
+
509
+ const dimensions = [
510
+ scoreVerificationEvidence(ctx),
511
+ scorePlanFidelity(ctx),
512
+ scoreGateHealth(ctx),
513
+ scoreProcessSafety(ctx),
514
+ scoreEfficiencyKpis(kpisFull),
515
+ ];
516
+
517
+ // Strip the internal marker from the persisted KPI block.
518
+ const { _duration_source, ...kpis } = kpisFull;
519
+
520
+ const record = {
521
+ record_kind: 'session-eval',
522
+ run_id: buildRunId(session.session_id, timestamp),
523
+ session_id: session.session_id,
524
+ standard_version: CURRENT_STANDARD_VERSION,
525
+ rubric_version: RUBRIC_VERSION,
526
+ provenance: {
527
+ rubric_sha256: computeRubricHash(rubricPath),
528
+ engine_commit: computeEngineCommit(repoRoot),
529
+ },
530
+ model: resolveModel(model, env, resolveModelFromEnv),
531
+ harness: {
532
+ plugin_version: resolvePluginVersion(pluginVersion, repoRoot),
533
+ platform: isNonEmptyString(platform) ? platform : (env.SO_PLATFORM || 'claude-code'),
534
+ host_class: findHostClass(events, session),
535
+ hostname_hash: hashHostname(hostname ?? os.hostname()),
536
+ },
537
+ kpis,
538
+ dimensions,
539
+ handle: handle ?? null,
540
+ anonymized: (handle ?? null) === null,
541
+ timestamp,
542
+ };
543
+
544
+ const summary = {
545
+ sessionId: session.session_id,
546
+ resolvedVia,
547
+ peerCount: peer.count,
548
+ peers: peer.peers,
549
+ contaminated: peer.count > 0,
550
+ dimensions: dimensions.map((d) => ({ id: d.id, method: d.method, status: d.status })),
551
+ };
552
+
553
+ return { record, summary };
554
+ }
555
+
556
+ /**
557
+ * Diff two dimension arrays on the scoring-relevant fields (id, method, status,
558
+ * evidence). run_id / timestamp / provenance / harness are intentionally NOT
559
+ * compared — they carry non-deterministic or run-specific values. Used by the
560
+ * CLI `--verify` path to detect scoring drift.
561
+ *
562
+ * ONLY `method === 'deterministic'` dimensions are compared on BOTH sides. Judge
563
+ * dimensions are advisory and NOT re-verifiable by contract — the `--verify`
564
+ * re-eval dispatches no judge, so `freshDims` never contains a judge dimension
565
+ * while a judge-merged stored record does. Filtering both sides prevents a
566
+ * judge-merged record from reporting a FALSE `present-in-stored-only` drift.
567
+ *
568
+ * @param {object[]} storedDims
569
+ * @param {object[]} freshDims
570
+ * @returns {Array<{id:string, field?:string, stored?:*, fresh?:*, reason?:string}>}
571
+ * empty array ⇒ identical.
572
+ */
573
+ export function diffDimensions(storedDims, freshDims) {
574
+ const toMap = (arr) => {
575
+ const m = new Map();
576
+ for (const d of Array.isArray(arr) ? arr : []) {
577
+ // Judge dims are non-re-verifiable by contract — deterministic-only diff.
578
+ if (isPlainObject(d) && d.method === 'deterministic' && isNonEmptyString(d.id)) m.set(d.id, d);
579
+ }
580
+ return m;
581
+ };
582
+ const stored = toMap(storedDims);
583
+ const fresh = toMap(freshDims);
584
+ const ids = new Set([...stored.keys(), ...fresh.keys()]);
585
+
586
+ const diffs = [];
587
+ for (const id of ids) {
588
+ const a = stored.get(id);
589
+ const b = fresh.get(id);
590
+ if (!a) {
591
+ diffs.push({ id, reason: 'present-in-fresh-only' });
592
+ continue;
593
+ }
594
+ if (!b) {
595
+ diffs.push({ id, reason: 'present-in-stored-only' });
596
+ continue;
597
+ }
598
+ for (const field of ['method', 'status', 'evidence']) {
599
+ if (a[field] !== b[field]) {
600
+ diffs.push({ id, field, stored: a[field], fresh: b[field] });
601
+ }
602
+ }
603
+ }
604
+ return diffs;
605
+ }