peaks-loop 4.1.2 → 4.1.3

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 (323) hide show
  1. package/.claude-plugin/marketplace.json +136 -47
  2. package/CHANGELOG.md +56 -0
  3. package/README-en.md +1 -1
  4. package/README.md +1 -1
  5. package/contracts/readonly-argv-whitelist.json +211 -0
  6. package/dist/cli/commands/audit-artifact-runners.d.ts +16 -0
  7. package/dist/cli/commands/audit-artifact-runners.js +170 -0
  8. package/dist/cli/commands/audit-command-shared.d.ts +97 -0
  9. package/dist/cli/commands/audit-command-shared.js +60 -0
  10. package/dist/cli/commands/audit-commands.d.ts +7 -31
  11. package/dist/cli/commands/audit-commands.js +64 -473
  12. package/dist/cli/commands/audit-goal-runners.d.ts +17 -0
  13. package/dist/cli/commands/audit-goal-runners.js +114 -0
  14. package/dist/cli/commands/audit-red-lines-runners.d.ts +11 -0
  15. package/dist/cli/commands/audit-red-lines-runners.js +43 -0
  16. package/dist/cli/commands/audit-refusal-data.d.ts +23 -0
  17. package/dist/cli/commands/audit-refusal-data.js +69 -0
  18. package/dist/cli/commands/audit-static-runners.d.ts +13 -0
  19. package/dist/cli/commands/audit-static-runners.js +139 -0
  20. package/dist/cli/commands/await-runners.d.ts +11 -0
  21. package/dist/cli/commands/await-runners.js +148 -0
  22. package/dist/cli/commands/code-auto-compact-command.d.ts +3 -0
  23. package/dist/cli/commands/code-auto-compact-command.js +124 -0
  24. package/dist/cli/commands/code-auto-compact-envelope.d.ts +22 -0
  25. package/dist/cli/commands/code-auto-compact-envelope.js +39 -0
  26. package/dist/cli/commands/code-context-audit-command.d.ts +3 -0
  27. package/dist/cli/commands/code-context-audit-command.js +68 -0
  28. package/dist/cli/commands/code-context-now-command.d.ts +3 -0
  29. package/dist/cli/commands/code-context-now-command.js +124 -0
  30. package/dist/cli/commands/code-context-now-envelope.d.ts +66 -0
  31. package/dist/cli/commands/code-context-now-envelope.js +136 -0
  32. package/dist/cli/commands/code-context-now-mapping.d.ts +27 -0
  33. package/dist/cli/commands/code-context-now-mapping.js +43 -0
  34. package/dist/cli/commands/code-emit-handoff-command.d.ts +3 -0
  35. package/dist/cli/commands/code-emit-handoff-command.js +99 -0
  36. package/dist/cli/commands/code-gate-step-08-command.d.ts +3 -0
  37. package/dist/cli/commands/code-gate-step-08-command.js +139 -0
  38. package/dist/cli/commands/code-post-compact-detect-command.d.ts +3 -0
  39. package/dist/cli/commands/code-post-compact-detect-command.js +50 -0
  40. package/dist/cli/commands/code-runtime-commands.d.ts +9 -43
  41. package/dist/cli/commands/code-runtime-commands.js +20 -672
  42. package/dist/cli/commands/code-runtime-session.d.ts +1 -0
  43. package/dist/cli/commands/code-runtime-session.js +15 -0
  44. package/dist/cli/commands/compact-command.d.ts +6 -2
  45. package/dist/cli/commands/compact-command.js +12 -559
  46. package/dist/cli/commands/compact-dry-run-command.d.ts +3 -0
  47. package/dist/cli/commands/compact-dry-run-command.js +87 -0
  48. package/dist/cli/commands/compact-force-command.d.ts +3 -0
  49. package/dist/cli/commands/compact-force-command.js +98 -0
  50. package/dist/cli/commands/compact-harness-window-command.d.ts +3 -0
  51. package/dist/cli/commands/compact-harness-window-command.js +174 -0
  52. package/dist/cli/commands/compact-history-command.d.ts +3 -0
  53. package/dist/cli/commands/compact-history-command.js +89 -0
  54. package/dist/cli/commands/compact-read-commands.d.ts +3 -0
  55. package/dist/cli/commands/compact-read-commands.js +123 -0
  56. package/dist/cli/commands/compact-settle-command.d.ts +3 -0
  57. package/dist/cli/commands/compact-settle-command.js +130 -0
  58. package/dist/cli/commands/compact-shared.d.ts +9 -0
  59. package/dist/cli/commands/compact-shared.js +26 -0
  60. package/dist/cli/commands/core/skill-command.d.ts +1 -44
  61. package/dist/cli/commands/core/skill-command.js +13 -541
  62. package/dist/cli/commands/core/skill-context-verdict.d.ts +38 -0
  63. package/dist/cli/commands/core/skill-context-verdict.js +63 -0
  64. package/dist/cli/commands/core/skill-generated-config-notice.d.ts +41 -0
  65. package/dist/cli/commands/core/skill-generated-config-notice.js +75 -0
  66. package/dist/cli/commands/core/skill-heartbeat-commands.d.ts +3 -0
  67. package/dist/cli/commands/core/skill-heartbeat-commands.js +50 -0
  68. package/dist/cli/commands/core/skill-presence-commands.d.ts +3 -0
  69. package/dist/cli/commands/core/skill-presence-commands.js +123 -0
  70. package/dist/cli/commands/core/skill-presence-housekeeping-commands.d.ts +3 -0
  71. package/dist/cli/commands/core/skill-presence-housekeeping-commands.js +165 -0
  72. package/dist/cli/commands/core/skill-registry-commands.d.ts +3 -0
  73. package/dist/cli/commands/core/skill-registry-commands.js +117 -0
  74. package/dist/cli/commands/core/skill-runbook-command.d.ts +3 -0
  75. package/dist/cli/commands/core/skill-runbook-command.js +29 -0
  76. package/dist/cli/commands/dispatch-command-spec.d.ts +2 -0
  77. package/dist/cli/commands/dispatch-command-spec.js +62 -0
  78. package/dist/cli/commands/dispatch-commands.js +159 -775
  79. package/dist/cli/commands/dispatch-detached-branch.d.ts +3 -0
  80. package/dist/cli/commands/dispatch-detached-branch.js +58 -0
  81. package/dist/cli/commands/dispatch-envelope.d.ts +36 -0
  82. package/dist/cli/commands/dispatch-envelope.js +104 -0
  83. package/dist/cli/commands/dispatch-isolation-lease.d.ts +17 -0
  84. package/dist/cli/commands/dispatch-isolation-lease.js +149 -0
  85. package/dist/cli/commands/dispatch-preflight.d.ts +7 -0
  86. package/dist/cli/commands/dispatch-preflight.js +105 -0
  87. package/dist/cli/commands/dispatch-prompt-blocks.d.ts +10 -0
  88. package/dist/cli/commands/dispatch-prompt-blocks.js +56 -0
  89. package/dist/cli/commands/dispatch-prompt-composition.d.ts +30 -0
  90. package/dist/cli/commands/dispatch-prompt-composition.js +171 -0
  91. package/dist/cli/commands/dispatch-record-write.d.ts +24 -0
  92. package/dist/cli/commands/dispatch-record-write.js +96 -0
  93. package/dist/cli/commands/dispatch-tool-call.d.ts +15 -0
  94. package/dist/cli/commands/dispatch-tool-call.js +128 -0
  95. package/dist/cli/commands/evolution-command-shared.d.ts +78 -0
  96. package/dist/cli/commands/evolution-command-shared.js +107 -0
  97. package/dist/cli/commands/evolution-commands.d.ts +11 -1
  98. package/dist/cli/commands/evolution-commands.js +19 -350
  99. package/dist/cli/commands/evolution-evaluate-command.d.ts +24 -0
  100. package/dist/cli/commands/evolution-evaluate-command.js +138 -0
  101. package/dist/cli/commands/evolution-propose-command.d.ts +23 -0
  102. package/dist/cli/commands/evolution-propose-command.js +145 -0
  103. package/dist/cli/commands/evolution-status-command.d.ts +17 -0
  104. package/dist/cli/commands/evolution-status-command.js +41 -0
  105. package/dist/cli/commands/evolution-verdict-commands.d.ts +30 -0
  106. package/dist/cli/commands/evolution-verdict-commands.js +100 -0
  107. package/dist/cli/commands/finalize-accumulator.d.ts +44 -0
  108. package/dist/cli/commands/finalize-accumulator.js +55 -0
  109. package/dist/cli/commands/finalize-branches.d.ts +34 -0
  110. package/dist/cli/commands/finalize-branches.js +119 -0
  111. package/dist/cli/commands/finalize-runners.d.ts +3 -0
  112. package/dist/cli/commands/finalize-runners.js +92 -0
  113. package/dist/cli/commands/finalize-selection.d.ts +65 -0
  114. package/dist/cli/commands/finalize-selection.js +35 -0
  115. package/dist/cli/commands/gate-commands.js +26 -8
  116. package/dist/cli/commands/job-checkpoint-commands.d.ts +3 -0
  117. package/dist/cli/commands/job-checkpoint-commands.js +157 -0
  118. package/dist/cli/commands/job-command-shared.d.ts +109 -0
  119. package/dist/cli/commands/job-command-shared.js +72 -0
  120. package/dist/cli/commands/job-commands.d.ts +4 -64
  121. package/dist/cli/commands/job-commands.js +42 -552
  122. package/dist/cli/commands/job-cost-check-command.d.ts +3 -0
  123. package/dist/cli/commands/job-cost-check-command.js +41 -0
  124. package/dist/cli/commands/job-init-status-commands.d.ts +3 -0
  125. package/dist/cli/commands/job-init-status-commands.js +149 -0
  126. package/dist/cli/commands/job-run-commands.d.ts +3 -0
  127. package/dist/cli/commands/job-run-commands.js +97 -0
  128. package/dist/cli/commands/job-state-root.d.ts +35 -0
  129. package/dist/cli/commands/job-state-root.js +76 -0
  130. package/dist/cli/commands/loop-eval-capture-index.d.ts +4 -0
  131. package/dist/cli/commands/loop-eval-capture-index.js +44 -0
  132. package/dist/cli/commands/loop-eval-commands.d.ts +8 -5
  133. package/dist/cli/commands/loop-eval-commands.js +12 -626
  134. package/dist/cli/commands/loop-eval-eval-command.d.ts +3 -0
  135. package/dist/cli/commands/loop-eval-eval-command.js +168 -0
  136. package/dist/cli/commands/loop-eval-monotonic-command.d.ts +3 -0
  137. package/dist/cli/commands/loop-eval-monotonic-command.js +90 -0
  138. package/dist/cli/commands/loop-eval-parents.d.ts +7 -0
  139. package/dist/cli/commands/loop-eval-parents.js +20 -0
  140. package/dist/cli/commands/loop-eval-run-code.d.ts +7 -0
  141. package/dist/cli/commands/loop-eval-run-code.js +40 -0
  142. package/dist/cli/commands/loop-eval-run-command.d.ts +3 -0
  143. package/dist/cli/commands/loop-eval-run-command.js +113 -0
  144. package/dist/cli/commands/loop-eval-spec-commands.d.ts +3 -0
  145. package/dist/cli/commands/loop-eval-spec-commands.js +165 -0
  146. package/dist/cli/commands/loop-eval-spec-lint-command.d.ts +3 -0
  147. package/dist/cli/commands/loop-eval-spec-lint-command.js +42 -0
  148. package/dist/cli/commands/loop-eval-workflow-commands.d.ts +3 -0
  149. package/dist/cli/commands/loop-eval-workflow-commands.js +141 -0
  150. package/dist/cli/commands/mcp-commands.d.ts +10 -0
  151. package/dist/cli/commands/mcp-commands.js +157 -0
  152. package/dist/cli/commands/request-command-options.d.ts +49 -0
  153. package/dist/cli/commands/request-command-options.js +1 -0
  154. package/dist/cli/commands/request-commands.d.ts +3 -9
  155. package/dist/cli/commands/request-commands.js +17 -522
  156. package/dist/cli/commands/request-init-command.d.ts +3 -0
  157. package/dist/cli/commands/request-init-command.js +100 -0
  158. package/dist/cli/commands/request-lint-command.d.ts +3 -0
  159. package/dist/cli/commands/request-lint-command.js +50 -0
  160. package/dist/cli/commands/request-list-command.d.ts +10 -0
  161. package/dist/cli/commands/request-list-command.js +53 -0
  162. package/dist/cli/commands/request-repair-status-command.d.ts +3 -0
  163. package/dist/cli/commands/request-repair-status-command.js +61 -0
  164. package/dist/cli/commands/request-show-command.d.ts +3 -0
  165. package/dist/cli/commands/request-show-command.js +56 -0
  166. package/dist/cli/commands/request-transition-command.d.ts +3 -0
  167. package/dist/cli/commands/request-transition-command.js +122 -0
  168. package/dist/cli/commands/request-transition-failures.d.ts +8 -0
  169. package/dist/cli/commands/request-transition-failures.js +90 -0
  170. package/dist/cli/commands/request-transition-hooks.d.ts +50 -0
  171. package/dist/cli/commands/request-transition-hooks.js +115 -0
  172. package/dist/cli/commands/request-transition-preflight.d.ts +10 -0
  173. package/dist/cli/commands/request-transition-preflight.js +107 -0
  174. package/dist/cli/commands/scan-command-shared.d.ts +96 -0
  175. package/dist/cli/commands/scan-command-shared.js +83 -0
  176. package/dist/cli/commands/scan-commands.d.ts +3 -2
  177. package/dist/cli/commands/scan-commands.js +23 -463
  178. package/dist/cli/commands/scan-inventory-commands.d.ts +3 -0
  179. package/dist/cli/commands/scan-inventory-commands.js +96 -0
  180. package/dist/cli/commands/scan-project-commands.d.ts +3 -0
  181. package/dist/cli/commands/scan-project-commands.js +65 -0
  182. package/dist/cli/commands/scan-scope-commands.d.ts +3 -0
  183. package/dist/cli/commands/scan-scope-commands.js +149 -0
  184. package/dist/cli/commands/scan-scope-helpers.d.ts +8 -0
  185. package/dist/cli/commands/scan-scope-helpers.js +54 -0
  186. package/dist/cli/commands/scan-structural-commands.d.ts +3 -0
  187. package/dist/cli/commands/scan-structural-commands.js +113 -0
  188. package/dist/cli/commands/share-commands.d.ts +12 -68
  189. package/dist/cli/commands/share-commands.js +47 -556
  190. package/dist/cli/commands/share-error-hints.d.ts +14 -0
  191. package/dist/cli/commands/share-error-hints.js +38 -0
  192. package/dist/cli/commands/share-identity.d.ts +13 -0
  193. package/dist/cli/commands/share-identity.js +22 -0
  194. package/dist/cli/commands/share-record-paths.d.ts +37 -0
  195. package/dist/cli/commands/share-record-paths.js +68 -0
  196. package/dist/cli/commands/share-runners.d.ts +3 -0
  197. package/dist/cli/commands/share-runners.js +158 -0
  198. package/dist/cli/commands/shared-read-runners.d.ts +3 -0
  199. package/dist/cli/commands/shared-read-runners.js +51 -0
  200. package/dist/cli/commands/slice-check-command.d.ts +3 -0
  201. package/dist/cli/commands/slice-check-command.js +54 -0
  202. package/dist/cli/commands/slice-commands.d.ts +2 -22
  203. package/dist/cli/commands/slice-commands.js +18 -517
  204. package/dist/cli/commands/slice-decompose-artifacts.d.ts +18 -0
  205. package/dist/cli/commands/slice-decompose-artifacts.js +79 -0
  206. package/dist/cli/commands/slice-decompose-command.d.ts +3 -0
  207. package/dist/cli/commands/slice-decompose-command.js +123 -0
  208. package/dist/cli/commands/slice-list-commands.d.ts +3 -0
  209. package/dist/cli/commands/slice-list-commands.js +182 -0
  210. package/dist/cli/commands/slice-pick-command.d.ts +3 -0
  211. package/dist/cli/commands/slice-pick-command.js +60 -0
  212. package/dist/cli/commands/slice-plan-command.d.ts +24 -0
  213. package/dist/cli/commands/slice-plan-command.js +111 -0
  214. package/dist/cli/commands/workflow-commands.d.ts +10 -1
  215. package/dist/cli/commands/workflow-commands.js +6 -594
  216. package/dist/cli/commands/workflow-gate-commands.d.ts +3 -0
  217. package/dist/cli/commands/workflow-gate-commands.js +116 -0
  218. package/dist/cli/commands/workflow-plan-helpers.d.ts +48 -0
  219. package/dist/cli/commands/workflow-plan-helpers.js +103 -0
  220. package/dist/cli/commands/workflow-planning-commands.d.ts +3 -0
  221. package/dist/cli/commands/workflow-planning-commands.js +56 -0
  222. package/dist/cli/commands/workflow-swarm-actions.d.ts +7 -0
  223. package/dist/cli/commands/workflow-swarm-actions.js +109 -0
  224. package/dist/cli/commands/workflow-swarm-commands.d.ts +3 -0
  225. package/dist/cli/commands/workflow-swarm-commands.js +138 -0
  226. package/dist/cli/commands/workflow-tech-actions.d.ts +10 -0
  227. package/dist/cli/commands/workflow-tech-actions.js +150 -0
  228. package/dist/cli/commands/workspace/init-actions.d.ts +10 -0
  229. package/dist/cli/commands/workspace/init-actions.js +199 -0
  230. package/dist/cli/commands/workspace/init-codegraph-stake.d.ts +10 -0
  231. package/dist/cli/commands/workspace/init-codegraph-stake.js +54 -0
  232. package/dist/cli/commands/workspace/init-command.d.ts +8 -124
  233. package/dist/cli/commands/workspace/init-command.js +59 -623
  234. package/dist/cli/commands/workspace/init-context.d.ts +58 -0
  235. package/dist/cli/commands/workspace/init-context.js +121 -0
  236. package/dist/cli/commands/workspace/init-envelope.d.ts +3 -0
  237. package/dist/cli/commands/workspace/init-envelope.js +34 -0
  238. package/dist/cli/commands/workspace/init-failures.d.ts +3 -0
  239. package/dist/cli/commands/workspace/init-failures.js +84 -0
  240. package/dist/cli/commands/workspace/init-hooks-decision.d.ts +24 -0
  241. package/dist/cli/commands/workspace/init-hooks-decision.js +189 -0
  242. package/dist/cli/commands/workspace/init-options.d.ts +102 -0
  243. package/dist/cli/commands/workspace/init-options.js +1 -0
  244. package/dist/cli/commands/worktree-lease-commands.d.ts +10 -6
  245. package/dist/cli/commands/worktree-lease-commands.js +42 -512
  246. package/dist/cli/commands/worktree-lease-gc-command.d.ts +12 -0
  247. package/dist/cli/commands/worktree-lease-gc-command.js +117 -0
  248. package/dist/cli/commands/worktree-lease-git.d.ts +22 -0
  249. package/dist/cli/commands/worktree-lease-git.js +48 -0
  250. package/dist/cli/commands/worktree-lease-list-command.d.ts +12 -0
  251. package/dist/cli/commands/worktree-lease-list-command.js +100 -0
  252. package/dist/cli/commands/worktree-lease-load.d.ts +37 -0
  253. package/dist/cli/commands/worktree-lease-load.js +28 -0
  254. package/dist/cli/commands/worktree-lease-release-command.d.ts +13 -0
  255. package/dist/cli/commands/worktree-lease-release-command.js +105 -0
  256. package/dist/cli/commands/worktree-lease-renew-command.d.ts +11 -0
  257. package/dist/cli/commands/worktree-lease-renew-command.js +99 -0
  258. package/dist/cli/commands/worktree-lease-session.d.ts +22 -0
  259. package/dist/cli/commands/worktree-lease-session.js +29 -0
  260. package/dist/cli/commands/worktree-lease-spawn-command.d.ts +11 -0
  261. package/dist/cli/commands/worktree-lease-spawn-command.js +119 -0
  262. package/dist/cli/commands/worktree-lease-status-command.d.ts +11 -0
  263. package/dist/cli/commands/worktree-lease-status-command.js +86 -0
  264. package/dist/cli/commands/worktree-lease-store.d.ts +19 -0
  265. package/dist/cli/commands/worktree-lease-store.js +24 -0
  266. package/dist/cli/program.js +5 -0
  267. package/dist/services/distribution/mcp-install-runner.d.ts +21 -0
  268. package/dist/services/distribution/mcp-install-runner.js +59 -0
  269. package/dist/services/distribution/mcp-install.d.ts +95 -0
  270. package/dist/services/distribution/mcp-install.js +179 -0
  271. package/dist/services/distribution/plugin-manifest.d.ts +97 -0
  272. package/dist/services/distribution/plugin-manifest.js +126 -0
  273. package/dist/services/hooks/mcp-surface-gate.d.ts +19 -0
  274. package/dist/services/hooks/mcp-surface-gate.js +87 -0
  275. package/dist/services/ide/adapters/claude-code-adapter.d.ts +4 -35
  276. package/dist/services/ide/adapters/claude-code-adapter.js +48 -171
  277. package/dist/services/ide/adapters/claude-code-local-state.d.ts +28 -0
  278. package/dist/services/ide/adapters/claude-code-local-state.js +112 -0
  279. package/dist/services/ide/adapters/claude-code-model-window.d.ts +37 -0
  280. package/dist/services/ide/adapters/claude-code-model-window.js +113 -0
  281. package/dist/services/ide/ide-mcp-install-types.d.ts +78 -0
  282. package/dist/services/ide/ide-mcp-install-types.js +104 -0
  283. package/dist/services/ide/ide-types.d.ts +45 -1
  284. package/dist/services/ide/mcp-tool-matcher.d.ts +34 -0
  285. package/dist/services/ide/mcp-tool-matcher.js +84 -0
  286. package/dist/services/lint/npx-resolver.js +7 -0
  287. package/dist/services/mcp/cli-executor.d.ts +36 -0
  288. package/dist/services/mcp/cli-executor.js +97 -0
  289. package/dist/services/mcp/json-rpc.d.ts +81 -0
  290. package/dist/services/mcp/json-rpc.js +116 -0
  291. package/dist/services/mcp/memory-tool.d.ts +3 -0
  292. package/dist/services/mcp/memory-tool.js +62 -0
  293. package/dist/services/mcp/server-main.d.ts +1 -0
  294. package/dist/services/mcp/server-main.js +66 -0
  295. package/dist/services/mcp/server.d.ts +22 -0
  296. package/dist/services/mcp/server.js +152 -0
  297. package/dist/services/mcp/surface.d.ts +62 -0
  298. package/dist/services/mcp/surface.js +198 -0
  299. package/dist/services/mcp/tool-core.d.ts +42 -0
  300. package/dist/services/mcp/tool-core.js +137 -0
  301. package/dist/services/mcp/tools.d.ts +13 -0
  302. package/dist/services/mcp/tools.js +58 -0
  303. package/dist/services/readonly-surface/argv-guard.d.ts +32 -0
  304. package/dist/services/readonly-surface/argv-guard.js +164 -0
  305. package/dist/services/readonly-surface/readonly-whitelist.d.ts +147 -0
  306. package/dist/services/readonly-surface/readonly-whitelist.js +107 -0
  307. package/dist/services/readonly-surface/whitelist-generator.d.ts +64 -0
  308. package/dist/services/readonly-surface/whitelist-generator.js +212 -0
  309. package/dist/services/skills/hooks-codegate-superpowers.d.ts +1 -0
  310. package/dist/services/skills/hooks-codegate-superpowers.js +26 -0
  311. package/dist/services/skills/hooks-settings-service.js +10 -2
  312. package/package.json +17 -6
  313. package/scripts/install-skills-bundles.mjs +233 -0
  314. package/scripts/install-skills-fs.mjs +148 -0
  315. package/scripts/install-skills-ide.mjs +279 -0
  316. package/scripts/install-skills-output-style-default.mjs +196 -0
  317. package/scripts/install-skills-output-styles.mjs +121 -0
  318. package/scripts/install-skills-report.mjs +42 -0
  319. package/scripts/install-skills-user-config.mjs +198 -0
  320. package/scripts/install-skills.mjs +36 -1066
  321. package/scripts/watch-tree.mjs +140 -0
  322. package/scripts/watch.mjs +4 -126
  323. package/skills/peaks-status/SKILL.md +31 -13
@@ -0,0 +1,145 @@
1
+ import { EvolutionIntegrityError } from '../../services/evolution/evolution-service.js';
2
+ import { addJsonOption, printResult } from '../cli-helpers.js';
3
+ import { ok } from 'peaks-loop-shared/result';
4
+ import { deltaMinFailure, invalidTargetFailure, isScoreInRange, parseTargetFlag, reportFailure, reportIntegrityFailure, scoreRangeFailure, withEvolutionDb } from './evolution-command-shared.js';
5
+ const PROPOSE_DESCRIPTION = "M4: persist a new evolution proposal. Enforces AC-8 (single object + single dimension). The proposal's verdict starts at 'needs-user-decision' until the scoring + skeptic step lands.";
6
+ /**
7
+ * Validate `--target`, `--before-score`, `--after-score` and
8
+ * `--delta-min` in that order, returning the first failure envelope
9
+ * the original action would have printed.
10
+ */
11
+ function preparePropose(options) {
12
+ const target = parseTargetFlag(options.target);
13
+ if (!target)
14
+ return { ok: false, failure: invalidTargetFailure('evolution.propose', options.target) };
15
+ const before = Number(options.beforeScore);
16
+ if (!isScoreInRange(before)) {
17
+ return {
18
+ ok: false,
19
+ failure: scoreRangeFailure({
20
+ command: 'evolution.propose',
21
+ code: 'EVOLUTION_INVALID_BEFORE_SCORE',
22
+ label: 'before_score',
23
+ flag: '--before-score',
24
+ key: 'beforeScore',
25
+ raw: options.beforeScore
26
+ })
27
+ };
28
+ }
29
+ const after = Number(options.afterScore);
30
+ if (!isScoreInRange(after)) {
31
+ return {
32
+ ok: false,
33
+ failure: scoreRangeFailure({
34
+ command: 'evolution.propose',
35
+ code: 'EVOLUTION_INVALID_AFTER_SCORE',
36
+ label: 'after_score',
37
+ flag: '--after-score',
38
+ key: 'afterScore',
39
+ raw: options.afterScore
40
+ })
41
+ };
42
+ }
43
+ const deltaMin = Number(options.deltaMin);
44
+ if (!Number.isFinite(deltaMin) || deltaMin < 0) {
45
+ return { ok: false, failure: deltaMinFailure('evolution.propose', options.deltaMin) };
46
+ }
47
+ return { ok: true, target, before, after, deltaMin };
48
+ }
49
+ /** The `EvolutionProposalInput` the service receives. */
50
+ function proposeInput(prep, options) {
51
+ return {
52
+ target_kind: prep.target.kind,
53
+ target_release_id: prep.target.id,
54
+ optimization_dimension: options.dimension,
55
+ before_snapshot: {},
56
+ after_snapshot: { after_score: prep.after },
57
+ diff: {},
58
+ before_score: prep.before,
59
+ after_score: prep.after,
60
+ score_delta_min: prep.deltaMin,
61
+ author_id: options.author,
62
+ single_object: true,
63
+ single_optimization_dimension: true,
64
+ rubric: {},
65
+ red_lines: [],
66
+ source_traces: []
67
+ };
68
+ }
69
+ /** The `ok(...)` `data` payload for a freshly created proposal. */
70
+ function proposeEnvelopeData(proposal, options) {
71
+ return {
72
+ proposal: {
73
+ id: proposal.id,
74
+ target_kind: proposal.target_kind,
75
+ target_release_id: proposal.target_release_id,
76
+ optimization_dimension: proposal.optimization_dimension,
77
+ before_score: proposal.before_score,
78
+ after_score: proposal.after_score,
79
+ score_delta: proposal.score_delta,
80
+ score_delta_min: proposal.score_delta_min,
81
+ author_id: proposal.author_id,
82
+ verdict: 'needs-user-decision',
83
+ ...(options.briefPointer !== undefined ? { brief_pointer: options.briefPointer } : {})
84
+ },
85
+ nextActions: [
86
+ `Run \`peaks evolution evaluate --proposal ${proposal.id} --evaluator <id> --skeptic <id> --evaluator-score <n> --json\` to score the proposal.`
87
+ ]
88
+ };
89
+ }
90
+ /** Print the propose failure envelope for `err` and set exit code 1. */
91
+ function reportProposeFailure(io, err, options) {
92
+ if (err instanceof EvolutionIntegrityError) {
93
+ reportIntegrityFailure({
94
+ io,
95
+ command: 'evolution.propose',
96
+ error: err,
97
+ nextActions: [
98
+ 'Re-shape the proposal per spec §6: single object, single dimension, separate scorer.',
99
+ 'If you intended a multi-object change, split it into multiple rounds.'
100
+ ],
101
+ asJson: options.json
102
+ });
103
+ return;
104
+ }
105
+ reportFailure({
106
+ io,
107
+ command: 'evolution.propose',
108
+ code: 'EVOLUTION_PROPOSE_FAILED',
109
+ error: err,
110
+ data: {},
111
+ nextActions: ['Verify the target flag and dimension.'],
112
+ asJson: options.json
113
+ });
114
+ }
115
+ /** The `propose` action body. */
116
+ export function runPropose(options, io) {
117
+ try {
118
+ const prep = preparePropose(options);
119
+ if (!prep.ok) {
120
+ printResult(io, prep.failure, options.json);
121
+ process.exitCode = 1;
122
+ return;
123
+ }
124
+ const input = proposeInput(prep, options);
125
+ const proposal = withEvolutionDb(options.project, (svc) => svc.createProposal(input));
126
+ printResult(io, ok('evolution.propose', proposeEnvelopeData(proposal, options), [], []), options.json);
127
+ }
128
+ catch (err) {
129
+ reportProposeFailure(io, err, options);
130
+ }
131
+ }
132
+ /** Register `peaks evolution propose` on the `evolution` parent. */
133
+ export function registerProposeCommand(evolution, io) {
134
+ addJsonOption(evolution
135
+ .command('propose')
136
+ .description(PROPOSE_DESCRIPTION)
137
+ .requiredOption('--target <kind:id>', "target asset, e.g. 'loop:loop-onboarding-research' or 'bee:42'")
138
+ .requiredOption('--dimension <name>', "single optimization dimension (e.g. 'clarity')")
139
+ .requiredOption('--before-score <n>', 'score on the 0..10 scale BEFORE the change')
140
+ .requiredOption('--after-score <n>', 'score on the 0..10 scale AFTER the change (LLM-claimed)')
141
+ .option('--delta-min <n>', `minimum score delta for promotion (default: 1.0; spec §6.1 #5)`, '1.0')
142
+ .requiredOption('--author <id>', 'author agent id (the LLM proposing the change)')
143
+ .option('--brief-pointer <ptr>', 'pointer to the evidence brief used in the recommendation (spec §4.7 / §4.4)')
144
+ .option('--project <path>', 'project root (default: cwd)')).action((options) => runPropose(options, io));
145
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `peaks evolution status` — M4 / spec §4.4. Split out of
3
+ * `evolution-commands.ts`: the option surface, the envelope and the
4
+ * exit-code sites are unchanged.
5
+ */
6
+ import type { Command } from 'commander';
7
+ import { type ProgramIO } from '../cli-helpers.js';
8
+ /** The `--options` Commander hands to the `status` action. */
9
+ export interface StatusOptions {
10
+ target: string;
11
+ project?: string;
12
+ json?: boolean;
13
+ }
14
+ /** The `status` action body. */
15
+ export declare function runStatus(options: StatusOptions, io: ProgramIO): void;
16
+ /** Register `peaks evolution status` on the `evolution` parent. */
17
+ export declare function registerStatusCommand(evolution: Command, io: ProgramIO): void;
@@ -0,0 +1,41 @@
1
+ import { addJsonOption, printResult } from '../cli-helpers.js';
2
+ import { ok } from 'peaks-loop-shared/result';
3
+ import { invalidTargetFailure, parseTargetFlag, reportFailure, withEvolutionDb } from './evolution-command-shared.js';
4
+ const STATUS_DESCRIPTION = 'M4: read the status snapshot for a target (counts of evaluations by verdict + latest evaluation id).';
5
+ /** The `{ target_kind, target_release_id }` argument `svc.status` takes. */
6
+ function statusTarget(target) {
7
+ return { target_kind: target.kind, target_release_id: target.id };
8
+ }
9
+ /** The `status` action body. */
10
+ export function runStatus(options, io) {
11
+ try {
12
+ const target = parseTargetFlag(options.target);
13
+ if (!target) {
14
+ printResult(io, invalidTargetFailure('evolution.status', options.target), options.json);
15
+ process.exitCode = 1;
16
+ return;
17
+ }
18
+ const targetArg = statusTarget(target);
19
+ const status = withEvolutionDb(options.project, (svc) => svc.status(targetArg));
20
+ printResult(io, ok('evolution.status', status, [], []), options.json);
21
+ }
22
+ catch (err) {
23
+ reportFailure({
24
+ io,
25
+ command: 'evolution.status',
26
+ code: 'EVOLUTION_STATUS_FAILED',
27
+ error: err,
28
+ data: { target: options.target },
29
+ nextActions: ['Verify the target flag.'],
30
+ asJson: options.json
31
+ });
32
+ }
33
+ }
34
+ /** Register `peaks evolution status` on the `evolution` parent. */
35
+ export function registerStatusCommand(evolution, io) {
36
+ addJsonOption(evolution
37
+ .command('status')
38
+ .description(STATUS_DESCRIPTION)
39
+ .requiredOption('--target <kind:id>', "target asset, e.g. 'loop:loop-onboarding-research'")
40
+ .option('--project <path>', 'project root (default: cwd)')).action((options) => runStatus(options, io));
41
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `peaks evolution mark-keep` + `peaks evolution revert` — the two
3
+ * explicit-verdict verbs (spec §6.1 #8). Split out of
4
+ * `evolution-commands.ts`: the option surfaces, the envelope keys and
5
+ * the exit-code sites are unchanged.
6
+ */
7
+ import type { Command } from 'commander';
8
+ import { type ProgramIO } from '../cli-helpers.js';
9
+ /** The `--options` Commander hands to the `mark-keep` action. */
10
+ export interface MarkKeepOptions {
11
+ proposal: string;
12
+ userConfirmation: string;
13
+ project?: string;
14
+ json?: boolean;
15
+ }
16
+ /** The `--options` Commander hands to the `revert` action. */
17
+ export interface RevertOptions {
18
+ proposal: string;
19
+ userConfirmation?: string;
20
+ project?: string;
21
+ json?: boolean;
22
+ }
23
+ /** The `mark-keep` action body. */
24
+ export declare function runMarkKeep(options: MarkKeepOptions, io: ProgramIO): void;
25
+ /** The `revert` action body. */
26
+ export declare function runRevert(options: RevertOptions, io: ProgramIO): void;
27
+ /** Register `peaks evolution mark-keep` on the `evolution` parent. */
28
+ export declare function registerMarkKeepCommand(evolution: Command, io: ProgramIO): void;
29
+ /** Register `peaks evolution revert` on the `evolution` parent. */
30
+ export declare function registerRevertCommand(evolution: Command, io: ProgramIO): void;
@@ -0,0 +1,100 @@
1
+ import { EvolutionIntegrityError } from '../../services/evolution/evolution-service.js';
2
+ import { addJsonOption, printResult } from '../cli-helpers.js';
3
+ import { ok } from 'peaks-loop-shared/result';
4
+ import { proposalNotFoundFailure, reportFailure, reportIntegrityFailure, withEvolutionDb } from './evolution-command-shared.js';
5
+ const MARK_KEEP_DESCRIPTION = 'M4: explicit user-confirmed `keep` verdict. Requires --user-confirmation <ptr> and a score_delta >= score_delta_min (AC-11/AC-15).';
6
+ const REVERT_DESCRIPTION = 'M4: revert a proposal (universal recovery; spec §6.1 #8). Always allowed; the user may supply --user-confirmation for audit.';
7
+ /** Print the mark-keep failure envelope for `err` and set exit code 1. */
8
+ function reportMarkKeepFailure(io, err, options) {
9
+ if (err instanceof EvolutionIntegrityError) {
10
+ reportIntegrityFailure({
11
+ io,
12
+ command: 'evolution.mark-keep',
13
+ error: err,
14
+ nextActions: ['Re-shape the proposal or the score so score_delta >= score_delta_min.'],
15
+ asJson: options.json
16
+ });
17
+ return;
18
+ }
19
+ reportFailure({
20
+ io,
21
+ command: 'evolution.mark-keep',
22
+ code: 'EVOLUTION_MARK_KEEP_FAILED',
23
+ error: err,
24
+ data: { proposalId: options.proposal },
25
+ nextActions: ['Verify the proposal id.'],
26
+ asJson: options.json
27
+ });
28
+ }
29
+ /** The `ok(...)` `data` payload for a confirmed `keep`. */
30
+ function markKeepEnvelopeData(updated) {
31
+ return {
32
+ proposalId: updated.id,
33
+ verdict: updated.verdict,
34
+ user_confirmation_pointer: updated.user_confirmation_pointer ?? null,
35
+ score_delta: updated.proposal.score_delta,
36
+ score_delta_min: updated.proposal.score_delta_min
37
+ };
38
+ }
39
+ /** The `mark-keep` action body. */
40
+ export function runMarkKeep(options, io) {
41
+ try {
42
+ const updated = withEvolutionDb(options.project, (svc) => svc.markVerdict(options.proposal, 'keep', options.userConfirmation));
43
+ if (!updated) {
44
+ printResult(io, proposalNotFoundFailure('evolution.mark-keep', options.proposal, [
45
+ 'Verify the proposal id.'
46
+ ]), options.json);
47
+ process.exitCode = 1;
48
+ return;
49
+ }
50
+ printResult(io, ok('evolution.mark-keep', markKeepEnvelopeData(updated), [], []), options.json);
51
+ }
52
+ catch (err) {
53
+ reportMarkKeepFailure(io, err, options);
54
+ }
55
+ }
56
+ /** The `revert` action body. */
57
+ export function runRevert(options, io) {
58
+ try {
59
+ const updated = withEvolutionDb(options.project, (svc) => svc.revert(options.proposal, options.userConfirmation));
60
+ if (!updated) {
61
+ printResult(io, proposalNotFoundFailure('evolution.revert', options.proposal, ['Verify the proposal id.']), options.json);
62
+ process.exitCode = 1;
63
+ return;
64
+ }
65
+ printResult(io, ok('evolution.revert', {
66
+ proposalId: updated.id,
67
+ verdict: updated.verdict,
68
+ user_confirmation_pointer: updated.user_confirmation_pointer ?? null
69
+ }, [], []), options.json);
70
+ }
71
+ catch (err) {
72
+ reportFailure({
73
+ io,
74
+ command: 'evolution.revert',
75
+ code: 'EVOLUTION_REVERT_FAILED',
76
+ error: err,
77
+ data: { proposalId: options.proposal },
78
+ nextActions: ['Verify the proposal id.'],
79
+ asJson: options.json
80
+ });
81
+ }
82
+ }
83
+ /** Register `peaks evolution mark-keep` on the `evolution` parent. */
84
+ export function registerMarkKeepCommand(evolution, io) {
85
+ addJsonOption(evolution
86
+ .command('mark-keep')
87
+ .description(MARK_KEEP_DESCRIPTION)
88
+ .requiredOption('--proposal <id>', 'proposal id')
89
+ .option('--user-confirmation <ptr>', 'pointer to the user choice record (AC-15) — omit to surface the EVOLUTION_MISSING_USER_CONFIRMATION service-layer error')
90
+ .option('--project <path>', 'project root (default: cwd)')).action((options) => runMarkKeep(options, io));
91
+ }
92
+ /** Register `peaks evolution revert` on the `evolution` parent. */
93
+ export function registerRevertCommand(evolution, io) {
94
+ addJsonOption(evolution
95
+ .command('revert')
96
+ .description(REVERT_DESCRIPTION)
97
+ .requiredOption('--proposal <id>', 'proposal id')
98
+ .option('--user-confirmation <ptr>', 'optional pointer to the user choice record')
99
+ .option('--project <path>', 'project root (default: cwd)')).action((options) => runRevert(options, io));
100
+ }
@@ -0,0 +1,44 @@
1
+ import type { DispatchRecord } from '../../services/dispatch/dispatch-record-writer.js';
2
+ import type { FinalizeSelection } from './finalize-selection.js';
3
+ interface FinalizedEntry {
4
+ recordPath: string;
5
+ requestId: string;
6
+ status: string;
7
+ }
8
+ interface SkippedEntry {
9
+ recordPath: string;
10
+ reason: string;
11
+ }
12
+ interface FailedEntry {
13
+ recordPath: string;
14
+ error: string;
15
+ }
16
+ /** The sweep's three counters, threaded explicitly instead of closed over. */
17
+ export interface FinalizeAccumulator {
18
+ readonly finalized: FinalizedEntry[];
19
+ readonly skipped: SkippedEntry[];
20
+ readonly errors: FailedEntry[];
21
+ }
22
+ export interface MappedOutcome {
23
+ readonly status: 'done' | 'failed' | 'cancelled';
24
+ readonly outcome: 'success' | 'failed' | 'cancelled';
25
+ }
26
+ export declare const OUTCOME_MAP: Record<string, MappedOutcome>;
27
+ export declare function makeAccumulator(): FinalizeAccumulator;
28
+ /**
29
+ * N2 — one unreadable record must not abort the sweep.
30
+ *
31
+ * Skipping `active-dispatches.json` and `batch-*.counter.json` by FILENAME
32
+ * removed the two non-record files that happened to be in the directory, but a
33
+ * single stale or foreign `dispatch-*.json` (an old `version`, hand-edited
34
+ * JSON, a truncated write) still made `readRecord` throw from OUTSIDE any
35
+ * try/catch — and the throw escaped to the action's outer handler, so
36
+ * `--request-id` AND `--batch` both died with `FINALIZE_ERROR` and exit 1
37
+ * without touching a single healthy record.
38
+ *
39
+ * A record that cannot be read is now reported in `errors[]` and skipped;
40
+ * every other record is processed as before.
41
+ */
42
+ export declare function tryReadRecord(recordPath: string, readRecord: (recordPath: string) => DispatchRecord, acc: FinalizeAccumulator): DispatchRecord | null;
43
+ export declare function buildFinalizeHints(acc: FinalizeAccumulator, selection: FinalizeSelection | null): string[];
44
+ export {};
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The finalize sweep's counters and the two pure helpers that read them, split
3
+ * out of `finalize-runners.ts` to keep each module under the line cap. The
4
+ * accumulator object replaces the mutable arrays the pre-split action closed
5
+ * over: it is created once and threaded explicitly through every branch.
6
+ */
7
+ import { getErrorMessage } from 'peaks-loop-shared/result';
8
+ // map outcome -> (status, outcome)
9
+ export const OUTCOME_MAP = {
10
+ done: { status: 'done', outcome: 'success' },
11
+ failed: { status: 'failed', outcome: 'failed' },
12
+ cancelled: { status: 'cancelled', outcome: 'cancelled' }
13
+ };
14
+ export function makeAccumulator() {
15
+ return { finalized: [], skipped: [], errors: [] };
16
+ }
17
+ /**
18
+ * N2 — one unreadable record must not abort the sweep.
19
+ *
20
+ * Skipping `active-dispatches.json` and `batch-*.counter.json` by FILENAME
21
+ * removed the two non-record files that happened to be in the directory, but a
22
+ * single stale or foreign `dispatch-*.json` (an old `version`, hand-edited
23
+ * JSON, a truncated write) still made `readRecord` throw from OUTSIDE any
24
+ * try/catch — and the throw escaped to the action's outer handler, so
25
+ * `--request-id` AND `--batch` both died with `FINALIZE_ERROR` and exit 1
26
+ * without touching a single healthy record.
27
+ *
28
+ * A record that cannot be read is now reported in `errors[]` and skipped;
29
+ * every other record is processed as before.
30
+ */
31
+ export function tryReadRecord(recordPath, readRecord, acc) {
32
+ try {
33
+ return readRecord(recordPath);
34
+ }
35
+ catch (e) {
36
+ acc.errors.push({ recordPath, error: getErrorMessage(e) });
37
+ return null;
38
+ }
39
+ }
40
+ export function buildFinalizeHints(acc, selection) {
41
+ const hints = [];
42
+ if (acc.errors.length > 0) {
43
+ hints.push('Re-run after fixing; unreadable records are listed in errors[] and were skipped, not fatal.');
44
+ }
45
+ else if (acc.finalized.length === 0 && acc.skipped.length > 0) {
46
+ hints.push("Nothing was finalized: every matching record had already left `queued`. See skipped[] for each record's status.");
47
+ }
48
+ else {
49
+ hints.push('All targeted records transitioned out of queued.');
50
+ }
51
+ if (selection !== null) {
52
+ hints.push(`--request-id selection (${selection.rule}): chose ${selection.chosen ?? '(none)'} of ${selection.matched} matching record(s); ${selection.rejected.length} rejected.`);
53
+ }
54
+ return hints;
55
+ }
@@ -0,0 +1,34 @@
1
+ import { type ProgramIO } from '../cli-helpers.js';
2
+ import type { ActiveDispatchEntry, DispatchRecord } from '../../services/dispatch/dispatch-record-writer.js';
3
+ import { type FinalizeSelection } from './finalize-selection.js';
4
+ import type { FinalizeAccumulator } from './finalize-accumulator.js';
5
+ export declare function finalizeAllStale(input: {
6
+ readActiveDispatchIndex: (projectRoot: string, sessionId: string) => Record<string, ActiveDispatchEntry>;
7
+ projectRoot: string;
8
+ sessionId: string;
9
+ apply: (recordPath: string, rid: string) => void;
10
+ acc: FinalizeAccumulator;
11
+ }): void;
12
+ export declare function finalizeByRequestId(input: {
13
+ projectRoot: string;
14
+ sessionId: string;
15
+ requestId: string;
16
+ io: ProgramIO;
17
+ asJson: boolean;
18
+ readOne: (recordPath: string) => DispatchRecord | null;
19
+ apply: (recordPath: string, rid: string) => void;
20
+ acc: FinalizeAccumulator;
21
+ }): Promise<{
22
+ kind: 'not-found';
23
+ } | {
24
+ kind: 'ok';
25
+ selection: FinalizeSelection;
26
+ }>;
27
+ export declare function finalizeByBatch(input: {
28
+ projectRoot: string;
29
+ sessionId: string;
30
+ batchId: string | undefined;
31
+ readOne: (recordPath: string) => DispatchRecord | null;
32
+ apply: (recordPath: string, rid: string) => void;
33
+ acc: FinalizeAccumulator;
34
+ }): Promise<void>;
@@ -0,0 +1,119 @@
1
+ /**
2
+ * The three finalize sweep branches — `--all-stale`, `--request-id` and
3
+ * `--batch` — split out of `finalize-runners.ts` to keep each module under the
4
+ * line cap. Each branch reads records, decides which to act on, and records
5
+ * the outcome in the shared accumulator; the runner owns the envelope.
6
+ */
7
+ import { fail, getErrorMessage } from 'peaks-loop-shared/result';
8
+ import { printResult } from '../cli-helpers.js';
9
+ import { FINALIZE_SELECTION_RULE, describeFinalizeRejection, selectFinalizeTarget } from './finalize-selection.js';
10
+ import { safeRecordPath } from './share-record-paths.js';
11
+ export function finalizeAllStale(input) {
12
+ const index = input.readActiveDispatchIndex(input.projectRoot, input.sessionId);
13
+ for (const [recordPath, entry] of Object.entries(index)) {
14
+ if (entry.status !== 'queued') {
15
+ input.acc.skipped.push({ recordPath, reason: 'status is ' + entry.status });
16
+ continue;
17
+ }
18
+ try {
19
+ input.apply(recordPath, entry.requestId);
20
+ }
21
+ catch (e) {
22
+ input.acc.errors.push({ recordPath, error: getErrorMessage(e) });
23
+ }
24
+ }
25
+ }
26
+ export async function finalizeByRequestId(input) {
27
+ const candidates = await collectRequestIdCandidates(input);
28
+ if (candidates.length === 0) {
29
+ printResult(input.io, fail('sub-agent.finalize', 'RECORD_NOT_FOUND', 'No dispatch record for requestId=' + input.requestId, { ok: false }, ['Check --request-id matches the dispatch envelope.']), input.asJson);
30
+ process.exitCode = 1;
31
+ return { kind: 'not-found' };
32
+ }
33
+ // N3: same rule as `--batch` — see `selectFinalizeTarget`.
34
+ const { selection, chosen } = buildRequestIdSelection(candidates, input.requestId);
35
+ for (const rejected of selection.rejected) {
36
+ input.acc.skipped.push({ recordPath: rejected.recordPath, reason: rejected.reason });
37
+ }
38
+ if (chosen !== null) {
39
+ try {
40
+ input.apply(chosen.recordPath, chosen.requestId);
41
+ }
42
+ catch (e) {
43
+ input.acc.errors.push({ recordPath: chosen.recordPath, error: getErrorMessage(e) });
44
+ }
45
+ }
46
+ return { kind: 'ok', selection };
47
+ }
48
+ async function collectRequestIdCandidates(input) {
49
+ const fs2 = await import('node:fs');
50
+ const path2 = await import('node:path');
51
+ const dir = path2.resolve(input.projectRoot, '.peaks', '_sub_agents', input.sessionId);
52
+ const candidates = [];
53
+ if (fs2.existsSync(dir)) {
54
+ for (const f of fs2.readdirSync(dir)) {
55
+ // Only dispatch records are readable records. The session directory also
56
+ // holds `active-dispatches.json` (an index) and `batch-<uuid>.counter.json`
57
+ // (batch counters); neither carries a `version` field, so `readRecord` on
58
+ // them throws `Dispatch record version mismatch ... got undefined`. The
59
+ // `--batch` branch below has always used this same filter.
60
+ if (!f.startsWith('dispatch-') || !f.endsWith('.json'))
61
+ continue;
62
+ const p = safeRecordPath(path2.join(dir, f));
63
+ const r = input.readOne(p);
64
+ if (r === null || r.requestId !== input.requestId)
65
+ continue;
66
+ candidates.push({
67
+ recordPath: p,
68
+ requestId: r.requestId,
69
+ status: r.status,
70
+ createdAt: r.createdAt
71
+ });
72
+ }
73
+ }
74
+ return candidates;
75
+ }
76
+ function buildRequestIdSelection(candidates, requestId) {
77
+ const chosen = selectFinalizeTarget(candidates);
78
+ const selection = {
79
+ requestId,
80
+ rule: FINALIZE_SELECTION_RULE,
81
+ matched: candidates.length,
82
+ chosen: chosen?.recordPath ?? null,
83
+ rejected: candidates
84
+ .filter((candidate) => candidate !== chosen)
85
+ .map((candidate) => ({
86
+ recordPath: candidate.recordPath,
87
+ status: candidate.status,
88
+ reason: describeFinalizeRejection(candidate, chosen)
89
+ }))
90
+ };
91
+ return { selection, chosen };
92
+ }
93
+ export async function finalizeByBatch(input) {
94
+ const fs2 = await import('node:fs');
95
+ const path2 = await import('node:path');
96
+ const dir = path2.resolve(input.projectRoot, '.peaks', '_sub_agents', input.sessionId);
97
+ if (!fs2.existsSync(dir))
98
+ return;
99
+ for (const f of fs2.readdirSync(dir)) {
100
+ if (!f.startsWith('dispatch-') || !f.endsWith('.json'))
101
+ continue;
102
+ const p = safeRecordPath(path2.join(dir, f));
103
+ const r = input.readOne(p);
104
+ if (r === null)
105
+ continue;
106
+ if (r.batchId !== input.batchId)
107
+ continue;
108
+ if (r.status !== 'queued') {
109
+ input.acc.skipped.push({ recordPath: p, reason: 'status is ' + r.status });
110
+ continue;
111
+ }
112
+ try {
113
+ input.apply(p, r.requestId);
114
+ }
115
+ catch (e) {
116
+ input.acc.errors.push({ recordPath: p, error: getErrorMessage(e) });
117
+ }
118
+ }
119
+ }
@@ -0,0 +1,3 @@
1
+ import { type ProgramIO } from '../cli-helpers.js';
2
+ import type { FinalizeOptions } from './finalize-selection.js';
3
+ export declare function runFinalize(options: FinalizeOptions, io: ProgramIO): Promise<void>;