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,507 @@
1
+ /**
2
+ * memory-proposals/sink.mjs — Promotion + archival sink for AUQ-reviewed proposals.
3
+ *
4
+ * Converts AUQ-approved proposals into learnings.jsonl records and archives
5
+ * rejected proposals to .orchestrator/proposals.rejected.log. Clears
6
+ * proposals.jsonl at end-of-cycle.
7
+ *
8
+ * Responsibilities:
9
+ * - writeApproved: promote approved ProposalRecords → learnings.jsonl
10
+ * - archiveRejected: append rejected ProposalRecords → proposals.rejected.log
11
+ * - clearProposalsJsonl: atomically clear proposals.jsonl (tmp + rename),
12
+ * archiving the pre-clear content to a recovery sidecar first, AND
13
+ * reset every per-wave proposals-summary-*.json sidecar in the same
14
+ * metrics directory (issue #723 B3 — see function docstring for the
15
+ * fleet-wide desync bug this closes).
16
+ * - promoteAndClear: compose writeApproved + clearProposalsJsonl into a
17
+ * single verified-write-then-clear call (issue #828 — see function
18
+ * docstring for the incident class this closes: a caller that ran
19
+ * writeApproved() then clearProposalsJsonl() unconditionally could drain
20
+ * the queue even when writeApproved returned written:0).
21
+ *
22
+ * All three exported functions:
23
+ * - Never throw on individual record errors — collect into errors[] and continue.
24
+ * - Use the canonical two-phase path-safety guard validatePathInsideProject
25
+ * (from ../path-utils.mjs) with canonicalizeRoot:true on every write target.
26
+ * - Use the appendLearning() atomic-append pattern from learnings/io.mjs.
27
+ *
28
+ * writeApproved additionally guards against a caller-mistake class (#797):
29
+ * calling `writeApproved({ proposals: [...] })` instead of
30
+ * `writeApproved({ approved: [...] })` previously returned a silent
31
+ * `{ written: 0, errors: [] }` no-op — indistinguishable from "nothing was
32
+ * approved". A subsequent `clearProposalsJsonl()` then drained the queue
33
+ * anyway, permanently losing the approved proposals. `writeApproved` now
34
+ * throws a `TypeError` when `approved` is `undefined` but the caller passed
35
+ * OTHER (unrecognised) keys — the signature that fingerprints an arg-name
36
+ * typo rather than a legitimate no-op call.
37
+ *
38
+ * Issue: #501 (F2.1 Memory-Proposals); #544 M3 (path-utils canonicalization);
39
+ * #723 B3 (clearProposalsJsonl atomicity + summary-reset fix); #797
40
+ * (writeApproved fail-silent guard + clearProposalsJsonl archive-before-clear);
41
+ * #828 (promoteAndClear — clear the queue ONLY after a verified write).
42
+ */
43
+
44
+ import { appendFile, mkdir, readdir, rm } from 'node:fs/promises';
45
+ import { writeFileSync, renameSync, readFileSync, existsSync } from 'node:fs';
46
+ import path from 'node:path';
47
+ import crypto from 'node:crypto';
48
+ import { appendLearning } from '../learnings/io.mjs';
49
+ import { validatePathInsideProject } from '../path-utils.mjs';
50
+
51
+ // ---------------------------------------------------------------------------
52
+ // Path constants (relative to repoRoot)
53
+ // ---------------------------------------------------------------------------
54
+
55
+ const LEARNINGS_REL = path.join('.orchestrator', 'metrics', 'learnings.jsonl');
56
+ const PROPOSALS_REL = path.join('.orchestrator', 'metrics', 'proposals.jsonl');
57
+ const REJECTED_LOG_REL = path.join('.orchestrator', 'proposals.rejected.log');
58
+ // #797 recovery sidecar: pre-clear proposals.jsonl content is appended here
59
+ // before every truncate, so a downstream clear that follows a botched
60
+ // writeApproved call (or any other pre-clear mistake) is recoverable.
61
+ const PROPOSALS_ARCHIVE_REL = path.join('.orchestrator', 'runtime', 'proposals-archive.jsonl');
62
+
63
+ // ---------------------------------------------------------------------------
64
+ // Internal helpers
65
+ // ---------------------------------------------------------------------------
66
+
67
+ /**
68
+ * Build a learning record from an approved proposal.
69
+ *
70
+ * Adds the 6 required extra fields:
71
+ * schema_version, source_session, expires_at (via appendLearning),
72
+ * scope, occurrences, _provenance
73
+ *
74
+ * Strips proposed_by_agent (audit-only, not persisted in learnings — privacy).
75
+ *
76
+ * NOTE: expires_at derivation is delegated to appendLearning() in io.mjs,
77
+ * which calls deriveExpiresAt(createdAt, type) from learnings/schema.mjs.
78
+ * We do not pre-compute it here to avoid duplicating that logic.
79
+ *
80
+ * NOTE: scope 'project' from the task spec is not a valid VALID_SCOPES value
81
+ * in learnings/schema.mjs (valid: 'local' | 'private' | 'public'). We use
82
+ * 'local' as the correct project-scoped equivalent to avoid a ValidationError.
83
+ *
84
+ * @param {object} proposal - full ProposalRecord
85
+ * @param {string} sessionId - e.g. 'main-2026-05-23-1249-deep'
86
+ * @returns {object} learning record ready for appendLearning()
87
+ */
88
+ function _proposalToLearning(proposal, sessionId) {
89
+ // Destructure to strip proposed_by_agent (privacy — not persisted)
90
+ const { proposed_by_agent: _strip, ...base } = proposal;
91
+
92
+ return {
93
+ ...base,
94
+ schema_version: 1,
95
+ source_session: sessionId,
96
+ scope: 'local',
97
+ occurrences: 1,
98
+ _provenance: `agent-proposed@${proposal.wave_id}`,
99
+ // expires_at: intentionally omitted — appendLearning() derives it via
100
+ // deriveExpiresAt(created_at, type) from learnings/schema.mjs
101
+ };
102
+ }
103
+
104
+ // ---------------------------------------------------------------------------
105
+ // Exports
106
+ // ---------------------------------------------------------------------------
107
+
108
+ /**
109
+ * Promote AUQ-approved proposals to learnings.jsonl.
110
+ *
111
+ * For each approved proposal:
112
+ * 1. Builds the learning record (adds 6 extra fields, strips proposed_by_agent).
113
+ * 2. Appends to .orchestrator/metrics/learnings.jsonl via appendLearning().
114
+ *
115
+ * Individual record errors are collected into errors[] — the function never
116
+ * throws on a per-record basis.
117
+ *
118
+ * Argument contract (#797 fail-silent guard):
119
+ * - `approved` is an array (possibly empty) → normal path / legitimate no-op.
120
+ * - `approved` is `undefined` and no OTHER (unrecognised) key was passed →
121
+ * legitimate no-op (e.g. an empty-selection AUQ round) → `{written:0, errors:[]}`.
122
+ * - `approved` is `undefined` BUT the caller passed unrecognised key(s)
123
+ * (e.g. `{ proposals: [...] }` instead of `{ approved: [...] }`) → throws
124
+ * `TypeError`, since this is almost certainly an arg-name typo that would
125
+ * otherwise silently no-op and lose the proposals on the next
126
+ * `clearProposalsJsonl()` call.
127
+ * - `approved` is defined but not an array → throws `TypeError` (clear
128
+ * contract violation, not a legitimate call shape).
129
+ *
130
+ * @param {object} opts
131
+ * @param {object[]} [opts.approved] - ProposalRecord[] selected by user via AUQ
132
+ * @param {string} opts.repoRoot - absolute project root path
133
+ * @param {string} opts.sessionId - e.g. 'main-2026-05-23-1249-deep'
134
+ * @returns {Promise<{ written: number, errors: string[] }>}
135
+ * @throws {TypeError} When `approved` is missing alongside unrecognised keys,
136
+ * or when `approved` is present but not an array.
137
+ */
138
+ export async function writeApproved({ approved, repoRoot, sessionId, ...rest }) {
139
+ const errors = [];
140
+ let written = 0;
141
+
142
+ if (approved === undefined) {
143
+ const unknownKeys = Object.keys(rest);
144
+ if (unknownKeys.length > 0) {
145
+ throw new TypeError(
146
+ `writeApproved: missing "approved" — got unknown key(s): ${unknownKeys.join(', ')}. Did you mean approved:?`
147
+ );
148
+ }
149
+ return { written: 0, errors: [] };
150
+ }
151
+
152
+ if (!Array.isArray(approved)) {
153
+ throw new TypeError(
154
+ `writeApproved: "approved" must be an array of ProposalRecord objects (got ${typeof approved})`
155
+ );
156
+ }
157
+
158
+ if (approved.length === 0) {
159
+ return { written: 0, errors: [] };
160
+ }
161
+
162
+ const learningsResult = validatePathInsideProject(LEARNINGS_REL, repoRoot, { canonicalizeRoot: true });
163
+ if (!learningsResult.ok) {
164
+ return { written: 0, errors: [`path-safety: ${learningsResult.reason} (${LEARNINGS_REL})`] };
165
+ }
166
+ const learningsPath = learningsResult.realPath ?? learningsResult.lexicalPath;
167
+
168
+ for (const proposal of approved) {
169
+ try {
170
+ const learningRecord = _proposalToLearning(proposal, sessionId);
171
+ await appendLearning(learningsPath, learningRecord);
172
+ written++;
173
+ } catch (err) {
174
+ const id = (proposal && proposal.id) ? proposal.id : '<unknown>';
175
+ errors.push(`proposal ${id}: ${err.message}`);
176
+ }
177
+ }
178
+
179
+ return { written, errors };
180
+ }
181
+
182
+ /**
183
+ * Archive AUQ-rejected proposals to .orchestrator/proposals.rejected.log.
184
+ *
185
+ * For each rejected proposal, appends a JSONL line:
186
+ * { ...originalProposal, _rejected_reason, _rejected_at }
187
+ *
188
+ * Individual record errors are collected into errors[] — the function never
189
+ * throws on a per-record basis.
190
+ *
191
+ * @param {object} opts
192
+ * @param {object[]} opts.rejected - ProposalRecord[] declined by user
193
+ * @param {string} opts.repoRoot - absolute project root path
194
+ * @param {string} opts.reason - 'user-declined' | 'overflow-truncate' | 'manual-skip'
195
+ * @returns {Promise<{ archived: number, errors: string[] }>}
196
+ */
197
+ export async function archiveRejected({ rejected, repoRoot, reason }) {
198
+ const errors = [];
199
+ let archived = 0;
200
+
201
+ if (!Array.isArray(rejected) || rejected.length === 0) {
202
+ return { archived: 0, errors: [] };
203
+ }
204
+
205
+ const rejectedResult = validatePathInsideProject(REJECTED_LOG_REL, repoRoot, { canonicalizeRoot: true });
206
+ if (!rejectedResult.ok) {
207
+ return { archived: 0, errors: [`path-safety: ${rejectedResult.reason} (${REJECTED_LOG_REL})`] };
208
+ }
209
+ const rejectedLogPath = rejectedResult.realPath ?? rejectedResult.lexicalPath;
210
+
211
+ // Ensure parent directory exists
212
+ try {
213
+ await mkdir(path.dirname(rejectedLogPath), { recursive: true });
214
+ } catch (err) {
215
+ return { archived: 0, errors: [`mkdir failed: ${err.message}`] };
216
+ }
217
+
218
+ const rejectedAt = new Date().toISOString();
219
+
220
+ for (const proposal of rejected) {
221
+ try {
222
+ const archiveRecord = {
223
+ ...proposal,
224
+ _rejected_reason: reason,
225
+ _rejected_at: rejectedAt,
226
+ };
227
+ const line = JSON.stringify(archiveRecord) + '\n';
228
+ await appendFile(rejectedLogPath, line, 'utf8');
229
+ archived++;
230
+ } catch (err) {
231
+ const id = (proposal && proposal.id) ? proposal.id : '<unknown>';
232
+ errors.push(`proposal ${id}: ${err.message}`);
233
+ }
234
+ }
235
+
236
+ return { archived, errors };
237
+ }
238
+
239
+ /**
240
+ * Atomically clear proposals.jsonl AND reset every per-wave summary sidecar
241
+ * (end-of-cycle clear).
242
+ *
243
+ * Root cause this fixes (#723 B3, reproduced fleet-wide 3x): the previous
244
+ * implementation truncated ONLY proposals.jsonl via a direct `writeFileSync`
245
+ * — it never reset the per-wave `proposals-summary-<wave-id>.json` sidecars
246
+ * written by `store.mjs` `incrementSummary()`. `collector.mjs`
247
+ * `accumulateSummaryStats()` reads `stats.queued` exclusively from those
248
+ * summary files, and its short-circuit (return zero stats when
249
+ * proposals.jsonl does not exist) never engages after a clear because the
250
+ * clear leaves a 0-byte-but-EXISTING file behind. Net effect: every
251
+ * session-end after the first non-empty cycle reported a stale
252
+ * `queued > 0` count against a genuinely empty (0-byte) proposals.jsonl.
253
+ *
254
+ * Three-step fix:
255
+ * 0. (#797) Archive the pre-clear content of proposals.jsonl (if non-empty)
256
+ * by appending it verbatim to `.orchestrator/runtime/proposals-archive.jsonl`
257
+ * BEFORE truncating. This is the recovery path for the drain-after-
258
+ * fail-silent-write class of bug: `clearProposalsJsonl()` unconditionally
259
+ * drains the queue regardless of whether the preceding `writeApproved()`
260
+ * call actually wrote anything, so a caller-side mistake (wrong arg name,
261
+ * partial write failure) no longer means the queued proposals are gone
262
+ * for good — they are recoverable from the archive sidecar. Best-effort:
263
+ * an archive failure never blocks the clear itself, and an empty/missing
264
+ * proposals.jsonl produces no archive append (nothing to preserve).
265
+ * 1. Clear proposals.jsonl via tmp-file + rename (POSIX-atomic on the same
266
+ * filesystem) instead of an in-place `writeFileSync` truncate — this also
267
+ * brings the implementation in line with the documented contract in
268
+ * `agents/memory-proposal-collector.md` ("atomic clear ... write empty
269
+ * content to a tmp file, then rename over the target"), so a concurrent
270
+ * reader never observes a partially-truncated file.
271
+ * 2. Remove every `proposals-summary-*.json` sidecar in the same metrics
272
+ * directory so the NEXT `collectProposals()` call starts from zero
273
+ * instead of re-summing a prior cycle's counters.
274
+ *
275
+ * Contract (skills/session-end/SKILL.md § 3.6 failure modes): this function
276
+ * must NEVER throw. Step 1 failures short-circuit with
277
+ * `{ cleared: false, summariesCleared: 0 }`. Step 2 is best-effort per file —
278
+ * a single summary file that fails to delete is skipped (not fatal) so a
279
+ * transient fs error on one sidecar cannot block the whole clear.
280
+ *
281
+ * Creates the file (with empty content) if it does not yet exist.
282
+ *
283
+ * @param {object} opts
284
+ * @param {string} opts.repoRoot - absolute project root path
285
+ * @returns {Promise<{ cleared: boolean, summariesCleared: number }>}
286
+ */
287
+ export async function clearProposalsJsonl({ repoRoot }) {
288
+ const proposalsResult = validatePathInsideProject(PROPOSALS_REL, repoRoot, { canonicalizeRoot: true });
289
+ if (!proposalsResult.ok) {
290
+ return { cleared: false, summariesCleared: 0 };
291
+ }
292
+ const proposalsPath = proposalsResult.realPath ?? proposalsResult.lexicalPath;
293
+ const metricsDirPath = path.dirname(proposalsPath);
294
+
295
+ // Step 0 (#797): archive pre-clear content before truncating. Best-effort
296
+ // — never lets an archive-side failure block the clear (same never-throw
297
+ // contract as the rest of this function).
298
+ if (existsSync(proposalsPath)) {
299
+ try {
300
+ const preClearContent = readFileSync(proposalsPath, 'utf8');
301
+ if (preClearContent.length > 0) {
302
+ const archiveResult = validatePathInsideProject(PROPOSALS_ARCHIVE_REL, repoRoot, { canonicalizeRoot: true });
303
+ if (archiveResult.ok) {
304
+ const archivePath = archiveResult.realPath ?? archiveResult.lexicalPath;
305
+ await mkdir(path.dirname(archivePath), { recursive: true });
306
+ const normalized = preClearContent.endsWith('\n') ? preClearContent : `${preClearContent}\n`;
307
+ await appendFile(archivePath, normalized, 'utf8');
308
+ }
309
+ }
310
+ } catch {
311
+ // Best-effort — a read/append failure on the archive sidecar must not
312
+ // block the clear itself (function-level never-throw contract).
313
+ }
314
+ }
315
+
316
+ try {
317
+ // Ensure parent directory exists before clear/create.
318
+ await mkdir(metricsDirPath, { recursive: true });
319
+ // Atomic clear: write empty content to a tmp file, then rename over the
320
+ // target — a concurrent hook reading proposals.jsonl mid-clear observes
321
+ // either the pre-clear content or the fully-cleared file, never a
322
+ // partial truncate.
323
+ const tmpSuffix = crypto.randomBytes(6).toString('hex');
324
+ const tmpFile = path.join(metricsDirPath, `.proposals.jsonl.tmp.${tmpSuffix}`);
325
+ writeFileSync(tmpFile, '', 'utf8');
326
+ renameSync(tmpFile, proposalsPath);
327
+ } catch {
328
+ return { cleared: false, summariesCleared: 0 };
329
+ }
330
+
331
+ // Reset per-wave summaries so a subsequent collectProposals() does not
332
+ // re-report a prior cycle's queued/dropped/below_floor counts against the
333
+ // now-empty proposals.jsonl (the #723 B3 root cause described above).
334
+ let summariesCleared = 0;
335
+ try {
336
+ const names = await readdir(metricsDirPath);
337
+ const summaryFiles = names.filter(
338
+ (n) => n.startsWith('proposals-summary-') && n.endsWith('.json')
339
+ );
340
+ for (const filename of summaryFiles) {
341
+ try {
342
+ await rm(path.join(metricsDirPath, filename), { force: true });
343
+ summariesCleared++;
344
+ } catch {
345
+ // Best-effort per file — a single sidecar failing to delete must not
346
+ // fail the overall clear (function-level never-throw contract).
347
+ }
348
+ }
349
+ } catch {
350
+ // Metrics dir became unreadable between mkdir and readdir (e.g. removed
351
+ // concurrently) — non-fatal, the JSONL clear above already succeeded.
352
+ }
353
+
354
+ return { cleared: true, summariesCleared };
355
+ }
356
+
357
+ /**
358
+ * Promote approved proposals AND clear the queue — but ONLY when the write
359
+ * is verified complete. Composes writeApproved() + clearProposalsJsonl()
360
+ * behind a single mechanical guard so a caller can no longer reproduce the
361
+ * incident class this closes (#828, 2nd occurrence 2026-07-18): a caller
362
+ * ran writeApproved() (which returned `written: 0` — e.g. every record
363
+ * failed round-trip validation because `sessionId` was missing/wrong) and
364
+ * then ran clearProposalsJsonl() anyway, unconditionally draining the queue
365
+ * even though nothing had actually been promoted.
366
+ *
367
+ * writeApproved() and clearProposalsJsonl() themselves are untouched by this
368
+ * function — both keep their existing signatures and never-throw-per-record
369
+ * contracts. promoteAndClear() is a NEW, additive orchestration layer; it
370
+ * does not replace direct calls to either lower-level function for callers
371
+ * that need finer-grained control (e.g. archiveRejected() must still run as
372
+ * a separate, caller-driven step between writeApproved() and this call — see
373
+ * below).
374
+ *
375
+ * Guard (mechanical, not semantic): the clear proceeds if and only if
376
+ * `writeApproved()` wrote exactly as many records as were requested
377
+ * (`written === expected`) AND reported zero per-record errors. This is a
378
+ * purely mechanical count/error check — it does NOT distinguish "operator
379
+ * approved nothing this cycle" from "operator approved everything and it all
380
+ * wrote cleanly". Both are `expected === 0` or `written === expected` with no
381
+ * errors, and BOTH legitimately clear the queue. The only case the guard
382
+ * blocks is a MISMATCH — some or all approved records failed to write — which
383
+ * is precisely the #828 incident class.
384
+ *
385
+ * `approved: []` (or `approved` omitted) is a legitimate clear-with-nothing-
386
+ * approved call: `expected` computes to 0, `writeApproved()` returns
387
+ * `{written: 0, errors: []}` without touching the filesystem, the guard
388
+ * evaluates `0 === 0 && no errors` → true, and the clear proceeds. This is
389
+ * intentional — a cycle where the operator approved nothing must still be
390
+ * able to drain a queue of now-rejected/stale proposals once the caller has
391
+ * separately archived them via archiveRejected().
392
+ *
393
+ * archiveRejected() is INTENTIONALLY NOT folded into this function — it
394
+ * operates on a disjoint subset of proposals (the rejected ones) and has no
395
+ * bearing on whether the write of the APPROVED subset succeeded. Callers
396
+ * should sequence: writeApproved-relevant work → archiveRejected(rejected) →
397
+ * promoteAndClear(approved) (or call promoteAndClear() first, then
398
+ * archiveRejected() — order between the two does not matter, since
399
+ * archiveRejected() never reads or clears proposals.jsonl itself).
400
+ *
401
+ * Own argument-typo guard (own-level #797 mirror; fixes a reintroduction
402
+ * found by session-reviewer): the original implementation destructured only
403
+ * its three known keys and forwarded a FRESH `{ approved, repoRoot,
404
+ * sessionId }` literal to writeApproved() — so a caller typo like
405
+ * `promoteAndClear({ proposals: [...], sessionId, repoRoot })` silently
406
+ * dropped the unrecognised `proposals` key. writeApproved() then received
407
+ * `approved: undefined` with NO unknown keys (the fresh literal has none),
408
+ * so writeApproved()'s OWN #797 rest-based typo guard could never fire —
409
+ * it took the legitimate-no-op branch and returned `{written: 0, errors:
410
+ * []}`, `expected` computed to 0, the mechanical guard evaluated
411
+ * `0 === 0 && no errors` → true, and the queue was drained with
412
+ * `cleared: true, skippedReason: null`. That is the exact #828 incident
413
+ * class, reintroduced one layer up. Fix: promoteAndClear() now captures
414
+ * `...rest` itself and throws its OWN `TypeError` when `approved ===
415
+ * undefined` alongside unrecognised key(s) — before ever calling
416
+ * writeApproved() — using the same detection shape and message wording as
417
+ * writeApproved()'s guard (lines ~136-144 above). An explicit local guard
418
+ * was chosen over forwarding `...rest` into writeApproved() so the typo is
419
+ * caught (and named) at the layer the caller actually invoked, rather than
420
+ * relying on an internal delegate to surface it.
421
+ *
422
+ * @param {object} opts
423
+ * @param {object[]} [opts.approved] - ProposalRecord[] selected by user via
424
+ * AUQ. Same contract as writeApproved()'s `approved` param:
425
+ * omitted/`undefined` WITH NO other (unrecognised) keys present is a
426
+ * legitimate no-op batch (computes `expected: 0`, clear proceeds — mirrors
427
+ * writeApproved()'s own no-op semantics exactly, see the guard above);
428
+ * omitted/`undefined` WITH unrecognised key(s) present throws `TypeError`
429
+ * (arg-name-typo detection, see above); present-but-not-an-array is a
430
+ * caller-mistake and is NOT pre-checked here — it is left to propagate as
431
+ * the `TypeError` writeApproved() already throws for that shape (avoids
432
+ * duplicating that validation in two places).
433
+ * @param {string} opts.sessionId - e.g. 'main-2026-05-23-1249-deep'. MUST be
434
+ * a non-empty string — this function throws `TypeError` immediately
435
+ * (before calling writeApproved()) when it is not, since a missing/blank
436
+ * sessionId is a caller bug (every record would fail writeApproved's
437
+ * round-trip validation with "missing required field: source_session",
438
+ * guaranteeing the write-verification guard below blocks the clear anyway
439
+ * — this throws earlier and louder rather than silently skipping to a
440
+ * `skippedReason`).
441
+ * @param {string} opts.repoRoot - absolute project root path
442
+ * @returns {Promise<{
443
+ * written: number,
444
+ * expected: number,
445
+ * errors: string[],
446
+ * cleared: boolean,
447
+ * summariesCleared: number,
448
+ * skippedReason: string|null,
449
+ * }>}
450
+ * @throws {TypeError} When `approved` is missing alongside unrecognised
451
+ * key(s) (own-level arg-typo guard), when `sessionId` is not a non-empty
452
+ * string, or (propagated) when `approved` is present but not an array.
453
+ */
454
+ export async function promoteAndClear({ approved, sessionId, repoRoot, ...rest }) {
455
+ if (approved === undefined) {
456
+ const unknownKeys = Object.keys(rest);
457
+ if (unknownKeys.length > 0) {
458
+ throw new TypeError(
459
+ `promoteAndClear: missing "approved" — got unknown key(s): ${unknownKeys.join(', ')}. Did you mean approved:?`
460
+ );
461
+ }
462
+ }
463
+
464
+ if (typeof sessionId !== 'string' || sessionId.trim().length === 0) {
465
+ throw new TypeError(
466
+ `promoteAndClear: "sessionId" must be a non-empty string (got ${typeof sessionId})`
467
+ );
468
+ }
469
+
470
+ // `expected` mirrors writeApproved()'s own no-op semantics: a non-array
471
+ // `approved` (including `undefined`, already guarded above against the
472
+ // arg-typo shape) computes as 0 here. When `approved` is present but
473
+ // genuinely not an array, writeApproved() below throws its own TypeError
474
+ // before this value is ever consulted by the guard.
475
+ const expected = Array.isArray(approved) ? approved.length : 0;
476
+
477
+ const w = await writeApproved({ approved, repoRoot, sessionId });
478
+
479
+ const ok = w.written === expected && w.errors.length === 0;
480
+
481
+ if (!ok) {
482
+ const skippedReason =
483
+ w.errors.length > 0
484
+ ? 'write-errors'
485
+ : `partial-write: ${w.written}/${expected} written`;
486
+ // Clear is SKIPPED entirely — proposals.jsonl (and its summary sidecars)
487
+ // remain untouched on this path. This is the mechanical fix for #828:
488
+ // the queue is never drained on an unverified/incomplete write.
489
+ return {
490
+ ...w,
491
+ expected,
492
+ cleared: false,
493
+ summariesCleared: 0,
494
+ skippedReason,
495
+ };
496
+ }
497
+
498
+ const c = await clearProposalsJsonl({ repoRoot });
499
+
500
+ return {
501
+ ...w,
502
+ expected,
503
+ cleared: c.cleared,
504
+ summariesCleared: c.summariesCleared,
505
+ skippedReason: null,
506
+ };
507
+ }