peaks-loop 4.0.0-beta.9 → 4.0.1

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 (552) hide show
  1. package/CHANGELOG.md +910 -141
  2. package/README-en.md +26 -7
  3. package/README.md +75 -6
  4. package/agents/karpathy-reviewer.md +33 -0
  5. package/bin/peaks.js +0 -0
  6. package/dist/cli/cli-helpers.d.ts +31 -6
  7. package/dist/cli/cli-helpers.js +48 -25
  8. package/dist/cli/commands/_register.d.ts +3 -0
  9. package/dist/cli/commands/_register.js +139 -0
  10. package/dist/cli/commands/_super.d.ts +10 -0
  11. package/dist/cli/commands/_super.js +97 -0
  12. package/dist/cli/commands/adapter-commands-s2a.js +1 -1
  13. package/dist/cli/commands/asset-commands.js +33 -16
  14. package/dist/cli/commands/audit-commands.js +2 -2
  15. package/dist/cli/commands/autonomous-swarm-commands.d.ts +12 -0
  16. package/dist/cli/commands/autonomous-swarm-commands.js +120 -0
  17. package/dist/cli/commands/bee-commands.js +1 -1
  18. package/dist/cli/commands/capability-commands.js +1 -1
  19. package/dist/cli/commands/capability-worker-config-sc-commands.js +0 -2
  20. package/dist/cli/commands/changeset-commands.d.ts +13 -0
  21. package/dist/cli/commands/changeset-commands.js +46 -0
  22. package/dist/cli/commands/code-commands.d.ts +11 -1
  23. package/dist/cli/commands/code-commands.js +19 -699
  24. package/dist/cli/commands/code-job-shape-commands.d.ts +9 -0
  25. package/dist/cli/commands/code-job-shape-commands.js +164 -0
  26. package/dist/cli/commands/code-mode-gate-commands.d.ts +9 -0
  27. package/dist/cli/commands/code-mode-gate-commands.js +223 -0
  28. package/dist/cli/commands/code-review-commands.js +2 -2
  29. package/dist/cli/commands/code-run-command.d.ts +12 -0
  30. package/dist/cli/commands/code-run-command.js +68 -0
  31. package/dist/cli/commands/code-runtime-commands.d.ts +11 -0
  32. package/dist/cli/commands/code-runtime-commands.js +391 -0
  33. package/dist/cli/commands/codegraph-commands.js +1 -1
  34. package/dist/cli/commands/compact-command.js +53 -1
  35. package/dist/cli/commands/complexity-commands.js +1 -1
  36. package/dist/cli/commands/config-commands.js +4 -75
  37. package/dist/cli/commands/container-commands.d.ts +28 -0
  38. package/dist/cli/commands/container-commands.js +221 -0
  39. package/dist/cli/commands/context-commands.js +3 -2
  40. package/dist/cli/commands/core/artifacts-command.js +1 -1
  41. package/dist/cli/commands/core/binding-commands.js +1 -1
  42. package/dist/cli/commands/core/doctor-command.js +63 -3
  43. package/dist/cli/commands/core/memory-command.js +1 -1
  44. package/dist/cli/commands/core/profile-command.js +1 -1
  45. package/dist/cli/commands/core/proxy-command.js +1 -1
  46. package/dist/cli/commands/core/session-command.js +9 -7
  47. package/dist/cli/commands/core/skill-command.js +7 -4
  48. package/dist/cli/commands/core/standards-command.js +1 -1
  49. package/dist/cli/commands/cron-commands.d.ts +57 -0
  50. package/dist/cli/commands/cron-commands.js +257 -0
  51. package/dist/cli/commands/cron-scheduler-commands.d.ts +47 -0
  52. package/dist/cli/commands/cron-scheduler-commands.js +284 -0
  53. package/dist/cli/commands/dashboard-commands.d.ts +4 -0
  54. package/dist/cli/commands/dashboard-commands.js +10 -0
  55. package/dist/cli/commands/dashboard-long-run.d.ts +25 -0
  56. package/dist/cli/commands/dashboard-long-run.js +122 -0
  57. package/dist/cli/commands/dashboard-summary.d.ts +12 -0
  58. package/dist/cli/commands/dashboard-summary.js +58 -0
  59. package/dist/cli/commands/dispatch-commands.d.ts +0 -7
  60. package/dist/cli/commands/dispatch-commands.js +372 -8
  61. package/dist/cli/commands/dispatch-from-dag.js +4 -1
  62. package/dist/cli/commands/doc-commands.js +1 -1
  63. package/dist/cli/commands/ecc-commands.d.ts +30 -0
  64. package/dist/cli/commands/ecc-commands.js +119 -0
  65. package/dist/cli/commands/evolution-commands.js +1 -1
  66. package/dist/cli/commands/feedback-commands.js +1 -1
  67. package/dist/cli/commands/final-review-commands.js +1 -1
  68. package/dist/cli/commands/fixture-commands.js +1 -1
  69. package/dist/cli/commands/fork-commands.js +1 -1
  70. package/dist/cli/commands/gate-commands.js +128 -6
  71. package/dist/cli/commands/governance-classify-contract-commands.d.ts +21 -0
  72. package/dist/cli/commands/governance-classify-contract-commands.js +273 -0
  73. package/dist/cli/commands/heartbeat-commands.js +76 -5
  74. package/dist/cli/commands/heartbeat-watch-command.d.ts +31 -0
  75. package/dist/cli/commands/heartbeat-watch-command.js +146 -0
  76. package/dist/cli/commands/hook-handle.js +1 -1
  77. package/dist/cli/commands/hooks-commands.js +126 -10
  78. package/dist/cli/commands/ide-commands.js +1 -1
  79. package/dist/cli/commands/impact-commands.js +1 -1
  80. package/dist/cli/commands/job-commands.js +34 -1
  81. package/dist/cli/commands/lease-metrics-commands.d.ts +67 -0
  82. package/dist/cli/commands/lease-metrics-commands.js +231 -0
  83. package/dist/cli/commands/lease-stats-commands.d.ts +65 -0
  84. package/dist/cli/commands/lease-stats-commands.js +107 -0
  85. package/dist/cli/commands/legacy-commands.js +1 -1
  86. package/dist/cli/commands/log-commands.js +1 -1
  87. package/dist/cli/commands/loop-commands.js +1 -1
  88. package/dist/cli/commands/loop-eval-commands.js +1 -1
  89. package/dist/cli/commands/memory-commands.js +1 -1
  90. package/dist/cli/commands/migrate-1-4-1-command.js +1 -1
  91. package/dist/cli/commands/migrate-v2-10-to-v2-11-command.js +1 -1
  92. package/dist/cli/commands/mut-commands.d.ts +1 -1
  93. package/dist/cli/commands/mut-commands.js +1 -5
  94. package/dist/cli/commands/observability-commands.js +1 -1
  95. package/dist/cli/commands/openspec-commands.js +65 -4
  96. package/dist/cli/commands/perf-audit-commands.js +3 -3
  97. package/dist/cli/commands/perf-commands.js +1 -1
  98. package/dist/cli/commands/polyrepo-commands.js +1 -1
  99. package/dist/cli/commands/prd-blocks-commands.js +1 -1
  100. package/dist/cli/commands/prd-commands.js +4 -2
  101. package/dist/cli/commands/preferences-commands.js +23 -3
  102. package/dist/cli/commands/project-commands.js +1 -1
  103. package/dist/cli/commands/qa-business-review-commands.js +1 -1
  104. package/dist/cli/commands/qa-commands.d.ts +1 -1
  105. package/dist/cli/commands/qa-commands.js +39 -3
  106. package/dist/cli/commands/release-commands.d.ts +15 -0
  107. package/dist/cli/commands/release-commands.js +113 -21
  108. package/dist/cli/commands/request-commands.js +1 -1
  109. package/dist/cli/commands/retrospective-commands.js +1 -1
  110. package/dist/cli/commands/reviewer-commands.js +1 -1
  111. package/dist/cli/commands/role-commands.js +1 -1
  112. package/dist/cli/commands/runtime-commands-helpers.d.ts +7 -0
  113. package/dist/cli/commands/runtime-commands-helpers.js +24 -0
  114. package/dist/cli/commands/runtime-commands.js +1 -2
  115. package/dist/cli/commands/sc-commands.js +4 -2
  116. package/dist/cli/commands/scan-commands.js +1 -1
  117. package/dist/cli/commands/security-audit-commands.js +3 -3
  118. package/dist/cli/commands/sediment-commands.js +10 -1
  119. package/dist/cli/commands/session-24h-mode.d.ts +26 -0
  120. package/dist/cli/commands/session-24h-mode.js +196 -0
  121. package/dist/cli/commands/share-commands.d.ts +19 -0
  122. package/dist/cli/commands/share-commands.js +121 -2
  123. package/dist/cli/commands/skill-conformance-commands.js +1 -1
  124. package/dist/cli/commands/skill-loop-engineering-readiness-commands.js +1 -1
  125. package/dist/cli/commands/skill-search-commands.js +4 -1
  126. package/dist/cli/commands/slice-commands.js +1 -1
  127. package/dist/cli/commands/slice-integrate-commands.js +1 -1
  128. package/dist/cli/commands/slice-review-commands.js +1 -1
  129. package/dist/cli/commands/smoke-commands.js +1 -1
  130. package/dist/cli/commands/sop-commands.js +1 -1
  131. package/dist/cli/commands/spill-demo-command.d.ts +7 -0
  132. package/dist/cli/commands/spill-demo-command.js +29 -0
  133. package/dist/cli/commands/statusline-commands.d.ts +12 -0
  134. package/dist/cli/commands/statusline-commands.js +79 -17
  135. package/dist/cli/commands/sub-agent-commands.js +2 -1
  136. package/dist/cli/commands/sub-agent-shared.d.ts +10 -0
  137. package/dist/cli/commands/sub-agent-shared.js +24 -1
  138. package/dist/cli/commands/swarm-commands.d.ts +13 -0
  139. package/dist/cli/commands/swarm-commands.js +77 -0
  140. package/dist/cli/commands/tech-commands.d.ts +64 -0
  141. package/dist/cli/commands/tech-commands.js +195 -0
  142. package/dist/cli/commands/understand-commands.js +1 -1
  143. package/dist/cli/commands/upgrade-commands.d.ts +2 -0
  144. package/dist/cli/commands/upgrade-commands.js +40 -5
  145. package/dist/cli/commands/user-touchpoint-commands.js +1 -1
  146. package/dist/cli/commands/verdict-aggregate-command.js +1 -1
  147. package/dist/cli/commands/vm-commands.d.ts +31 -0
  148. package/dist/cli/commands/vm-commands.js +274 -0
  149. package/dist/cli/commands/workflow-commands.js +24 -1
  150. package/dist/cli/commands/workflow-plan-commands.js +1 -1
  151. package/dist/cli/commands/workspace/init-command.js +1 -1
  152. package/dist/cli/commands/workspace/migrate-command.js +1 -1
  153. package/dist/cli/commands/workspace/reconcile-command.js +1 -1
  154. package/dist/cli/commands/worktree-auth-commands.d.ts +29 -0
  155. package/dist/cli/commands/worktree-auth-commands.js +652 -0
  156. package/dist/cli/index.js +58 -13
  157. package/dist/cli/program.d.ts +2 -2
  158. package/dist/cli/program.js +86 -281
  159. package/dist/services/24h-mode/decider.d.ts +103 -0
  160. package/dist/services/24h-mode/decider.js +144 -0
  161. package/dist/services/24h-mode/index.d.ts +12 -0
  162. package/dist/services/24h-mode/index.js +12 -0
  163. package/dist/services/24h-mode/state.d.ts +48 -0
  164. package/dist/services/24h-mode/state.js +51 -0
  165. package/dist/services/24h-mode/store.d.ts +27 -0
  166. package/dist/services/24h-mode/store.js +119 -0
  167. package/dist/services/artifacts/artifact-prerequisites.js +1 -1
  168. package/dist/services/artifacts/request-artifact-service.js +1 -1
  169. package/dist/services/artifacts/workspace-service.js +1 -1
  170. package/dist/services/audit/enforcers/lint-bee-runtime-contract.d.ts +25 -0
  171. package/dist/services/audit/enforcers/lint-bee-runtime-contract.js +91 -0
  172. package/dist/services/audit/enforcers/lint-peaks-code-runtime.d.ts +16 -0
  173. package/dist/services/audit/enforcers/lint-peaks-code-runtime.js +31 -0
  174. package/dist/services/audit/enforcers/lint-peaks-skill-runtime.d.ts +23 -0
  175. package/dist/services/audit/enforcers/lint-peaks-skill-runtime.js +59 -0
  176. package/dist/services/audit/enforcers/lint-peaks-ui-sc-txt-runtime.d.ts +28 -0
  177. package/dist/services/audit/enforcers/lint-peaks-ui-sc-txt-runtime.js +86 -0
  178. package/dist/services/audit/enforcers/lint-prd-artifact-handoff.d.ts +16 -0
  179. package/dist/services/audit/enforcers/lint-prd-artifact-handoff.js +41 -0
  180. package/dist/services/audit/enforcers/lint-prd-source-snapshot.d.ts +27 -0
  181. package/dist/services/audit/enforcers/lint-prd-source-snapshot.js +47 -0
  182. package/dist/services/audit/enforcers/lint-qa-gateguard-and-runtime.d.ts +19 -0
  183. package/dist/services/audit/enforcers/lint-qa-gateguard-and-runtime.js +47 -0
  184. package/dist/services/audit/enforcers/lint-rd-handoff-coverage.d.ts +18 -0
  185. package/dist/services/audit/enforcers/lint-rd-handoff-coverage.js +70 -0
  186. package/dist/services/audit/enforcers/lint-skill-presence-mandatory.d.ts +25 -0
  187. package/dist/services/audit/enforcers/lint-skill-presence-mandatory.js +53 -0
  188. package/dist/services/audit/red-line-catalog-p2-a.d.ts +0 -6
  189. package/dist/services/audit/red-line-catalog-p2-a.js +230 -1
  190. package/dist/services/audit/static-service.d.ts +32 -25
  191. package/dist/services/audit/static-service.js +30 -109
  192. package/dist/services/audit-independent/index.d.ts +2 -0
  193. package/dist/services/audit-independent/index.js +2 -0
  194. package/dist/services/autonomous-swarm/autonomous-swarm-service.d.ts +127 -0
  195. package/dist/services/autonomous-swarm/autonomous-swarm-service.js +446 -0
  196. package/dist/services/changeset/changeset-check-service.d.ts +22 -0
  197. package/dist/services/changeset/changeset-check-service.js +47 -0
  198. package/dist/services/code/auto-compact-modes.d.ts +30 -0
  199. package/dist/services/code/auto-compact-modes.js +38 -0
  200. package/dist/services/code/auto-compact-orchestrator.d.ts +43 -5
  201. package/dist/services/code/auto-compact-orchestrator.js +101 -21
  202. package/dist/services/code/dag-orchestrator.d.ts +30 -1
  203. package/dist/services/code/dag-orchestrator.js +106 -1
  204. package/dist/services/code/status-line-renderer.d.ts +2 -0
  205. package/dist/services/code/status-line-renderer.js +21 -3
  206. package/dist/services/code-review/ocr-service.d.ts +1 -1
  207. package/dist/services/code-review/ocr-service.js +6 -3
  208. package/dist/services/compact-history/compact-history-service.d.ts +41 -0
  209. package/dist/services/compact-history/compact-history-service.js +62 -0
  210. package/dist/services/compact-statusline/compact-statusline-service.d.ts +16 -0
  211. package/dist/services/compact-statusline/compact-statusline-service.js +83 -0
  212. package/dist/services/config/config-service.d.ts +1 -12
  213. package/dist/services/config/config-service.js +3 -72
  214. package/dist/services/config/config-types.d.ts +2 -4
  215. package/dist/services/config/config-types.js +1 -1
  216. package/dist/services/container/container-lease.d.ts +67 -0
  217. package/dist/services/container/container-lease.js +135 -0
  218. package/dist/services/context/auto-compact-dispatcher.d.ts +40 -5
  219. package/dist/services/context/auto-compact-dispatcher.js +32 -102
  220. package/dist/services/context/auto-compact-reader.js +1 -1
  221. package/dist/services/context/auto-compact-types.d.ts +27 -2
  222. package/dist/services/context/auto-compact-types.js +8 -1
  223. package/dist/services/context/build-dispatch-system-prompt.d.ts +75 -0
  224. package/dist/services/context/build-dispatch-system-prompt.js +117 -0
  225. package/dist/services/context/collector.d.ts +2 -2
  226. package/dist/services/context/context-builder.d.ts +4 -4
  227. package/dist/services/context/context-schema.d.ts +48 -48
  228. package/dist/services/context/ide-detect.d.ts +4 -0
  229. package/dist/services/context/ide-detect.js +24 -0
  230. package/dist/services/context/main-session-monitor.d.ts +1 -4
  231. package/dist/services/context/main-session-monitor.js +1 -24
  232. package/dist/services/context/memory-index-reader.d.ts +8 -0
  233. package/dist/services/context/memory-index-reader.js +57 -0
  234. package/dist/services/context/memory-lru-cache.d.ts +12 -0
  235. package/dist/services/context/memory-lru-cache.js +60 -0
  236. package/dist/services/context/memory-preflight-config.d.ts +19 -0
  237. package/dist/services/context/memory-preflight-config.js +25 -0
  238. package/dist/services/context/memory-preflight-service.d.ts +19 -0
  239. package/dist/services/context/memory-preflight-service.js +120 -0
  240. package/dist/services/context/spillover-store.d.ts +23 -0
  241. package/dist/services/context/spillover-store.js +155 -0
  242. package/dist/services/context/spillover-types.d.ts +18 -0
  243. package/dist/services/context/spillover-types.js +1 -0
  244. package/dist/services/crystallization/crystallization-service.d.ts +22 -5
  245. package/dist/services/crystallization/crystallization-service.js +8 -14
  246. package/dist/services/crystallization/crystallization-types.d.ts +6 -6
  247. package/dist/services/crystallization/evidence-brief-builder.d.ts +1 -1
  248. package/dist/services/crystallization/index.d.ts +13 -0
  249. package/dist/services/crystallization/index.js +13 -0
  250. package/dist/services/dashboard/project-dashboard-service.js +2 -2
  251. package/dist/services/dispatch/await-batch.d.ts +70 -0
  252. package/dist/services/dispatch/await-batch.js +272 -0
  253. package/dist/services/dispatch/batch-counter.js +1 -1
  254. package/dist/services/dispatch/dispatch-record-writer.d.ts +126 -4
  255. package/dist/services/dispatch/dispatch-record-writer.js +239 -9
  256. package/dist/services/dispatch/slice-dag.d.ts +46 -0
  257. package/dist/services/dispatch/slice-dag.js +6 -0
  258. package/dist/services/dispatch/stage-enum.d.ts +27 -0
  259. package/dist/services/dispatch/stage-enum.js +48 -0
  260. package/dist/services/dispatch/startup-timeout.d.ts +86 -0
  261. package/dist/services/dispatch/startup-timeout.js +97 -0
  262. package/dist/services/dispatch/sub-agent-dispatcher.js +40 -89
  263. package/dist/services/dispatch/test-tool-detection.d.ts +25 -1
  264. package/dist/services/dispatch/test-tool-detection.js +80 -0
  265. package/dist/services/doctor/doctor-service/checks/check-id-schema.d.ts +18 -0
  266. package/dist/services/doctor/doctor-service/checks/check-id-schema.js +64 -0
  267. package/dist/services/doctor/doctor-service/checks/codegraph-capability.d.ts +14 -0
  268. package/dist/services/doctor/doctor-service/checks/codegraph-capability.js +69 -0
  269. package/dist/services/doctor/doctor-service/checks/dist-source-version.d.ts +32 -0
  270. package/dist/services/doctor/doctor-service/checks/dist-source-version.js +110 -0
  271. package/dist/services/doctor/doctor-service/checks/gateguard-conflict.d.ts +24 -0
  272. package/dist/services/doctor/doctor-service/checks/gateguard-conflict.js +164 -0
  273. package/dist/services/doctor/doctor-service/checks/l3-memory-health.d.ts +16 -0
  274. package/dist/services/doctor/doctor-service/checks/l3-memory-health.js +57 -0
  275. package/dist/services/doctor/doctor-service/checks/l3-orphan-sessions.d.ts +19 -0
  276. package/dist/services/doctor/doctor-service/checks/l3-orphan-sessions.js +66 -0
  277. package/dist/services/doctor/doctor-service/checks/schema-validity.d.ts +10 -0
  278. package/dist/services/doctor/doctor-service/checks/schema-validity.js +33 -0
  279. package/dist/services/doctor/doctor-service/checks/skill-apply-note.d.ts +20 -0
  280. package/dist/services/doctor/doctor-service/checks/skill-apply-note.js +85 -0
  281. package/dist/services/doctor/doctor-service/checks/skill-existence.d.ts +13 -0
  282. package/dist/services/doctor/doctor-service/checks/skill-existence.js +30 -0
  283. package/dist/services/doctor/doctor-service/checks/skill-name-match.d.ts +10 -0
  284. package/dist/services/doctor/doctor-service/checks/skill-name-match.js +25 -0
  285. package/dist/services/doctor/doctor-service/checks/skill-parse.d.ts +10 -0
  286. package/dist/services/doctor/doctor-service/checks/skill-parse.js +19 -0
  287. package/dist/services/doctor/doctor-service/checks/skill-presence.d.ts +21 -0
  288. package/dist/services/doctor/doctor-service/checks/skill-presence.js +75 -0
  289. package/dist/services/doctor/doctor-service/checks/skill-runbook.d.ts +14 -0
  290. package/dist/services/doctor/doctor-service/checks/skill-runbook.js +47 -0
  291. package/dist/services/doctor/doctor-service/checks/statusline-install.d.ts +14 -0
  292. package/dist/services/doctor/doctor-service/checks/statusline-install.js +32 -0
  293. package/dist/services/doctor/doctor-service/checks/statusline-runtime.d.ts +13 -0
  294. package/dist/services/doctor/doctor-service/checks/statusline-runtime.js +30 -0
  295. package/dist/services/doctor/doctor-service/checks/user-config.d.ts +11 -0
  296. package/dist/services/doctor/doctor-service/checks/user-config.js +27 -0
  297. package/dist/services/doctor/doctor-service/checks/workspace-init.d.ts +16 -0
  298. package/dist/services/doctor/doctor-service/checks/workspace-init.js +34 -0
  299. package/dist/services/doctor/doctor-service/checks/workspace-layout.d.ts +33 -0
  300. package/dist/services/doctor/doctor-service/checks/workspace-layout.js +180 -0
  301. package/dist/services/doctor/doctor-service/index.d.ts +48 -0
  302. package/dist/services/doctor/doctor-service/index.js +254 -0
  303. package/dist/services/doctor/doctor-service/plugin-registry.d.ts +41 -0
  304. package/dist/services/doctor/doctor-service/plugin-registry.js +77 -0
  305. package/dist/services/doctor/doctor-service/report/final-summary.d.ts +20 -0
  306. package/dist/services/doctor/doctor-service/report/final-summary.js +29 -0
  307. package/dist/services/doctor/doctor-service/types.d.ts +245 -0
  308. package/dist/services/doctor/doctor-service/types.js +15 -0
  309. package/dist/services/doctor/doctor-service.d.ts +15 -146
  310. package/dist/services/doctor/doctor-service.js +22 -926
  311. package/dist/services/doctor/index.d.ts +22 -0
  312. package/dist/services/doctor/index.js +22 -0
  313. package/dist/services/env/shell-probe.d.ts +71 -0
  314. package/dist/services/env/shell-probe.js +161 -0
  315. package/dist/services/evolution/evolution-types.d.ts +39 -39
  316. package/dist/services/final-review/final-review-service.d.ts +11 -1
  317. package/dist/services/final-review/index.d.ts +2 -0
  318. package/dist/services/final-review/index.js +1 -0
  319. package/dist/services/hooks/auto-compact-hook-install.d.ts +4 -5
  320. package/dist/services/hooks/auto-compact-hook-install.js +4 -5
  321. package/dist/services/hooks/worktree-authorization-gate.d.ts +205 -0
  322. package/dist/services/hooks/worktree-authorization-gate.js +492 -0
  323. package/dist/services/ide/adapters/claude-code-adapter.js +2 -2
  324. package/dist/services/ide/adapters/qoder-adapter.d.ts +25 -0
  325. package/dist/services/ide/adapters/qoder-adapter.js +57 -0
  326. package/dist/services/ide/adapters/tongyi-lingma-adapter.d.ts +16 -0
  327. package/dist/services/ide/adapters/tongyi-lingma-adapter.js +45 -0
  328. package/dist/services/ide/ide-registry.js +6 -0
  329. package/dist/services/ide/ide-types.d.ts +1 -1
  330. package/dist/services/job/job-types.d.ts +56 -56
  331. package/dist/services/job-snapshot/index.d.ts +8 -0
  332. package/dist/services/job-snapshot/index.js +7 -0
  333. package/dist/services/{job/job-resource-snapshot.d.ts → job-snapshot/snapshot.d.ts} +1 -1
  334. package/dist/services/job-snapshot/types.d.ts +7 -0
  335. package/dist/services/job-snapshot/types.js +1 -0
  336. package/dist/services/karpathy-cost/karpathy-cost-check-service.d.ts +67 -0
  337. package/dist/services/karpathy-cost/karpathy-cost-check-service.js +108 -0
  338. package/dist/services/log/retention.d.ts +16 -0
  339. package/dist/services/log/retention.js +17 -0
  340. package/dist/services/loop/loop-bee-relation-types.d.ts +6 -6
  341. package/dist/services/loop/loop-release-types.d.ts +24 -24
  342. package/dist/services/loop/monotonic-runner.d.ts +17 -11
  343. package/dist/services/loop/monotonic-runner.js +118 -79
  344. package/dist/services/memory/project-memory-service/index/kind-dispatch.d.ts +8 -0
  345. package/dist/services/memory/project-memory-service/index/kind-dispatch.js +253 -0
  346. package/dist/services/memory/project-memory-service/index/ranking.d.ts +6 -0
  347. package/dist/services/memory/project-memory-service/index/ranking.js +171 -0
  348. package/dist/services/memory/project-memory-service/index/search.d.ts +34 -0
  349. package/dist/services/memory/project-memory-service/index/search.js +194 -0
  350. package/dist/services/memory/project-memory-service/index.d.ts +9 -0
  351. package/dist/services/memory/project-memory-service/index.js +24 -0
  352. package/dist/services/memory/project-memory-service/parsers/frontmatter.d.ts +9 -0
  353. package/dist/services/memory/project-memory-service/parsers/frontmatter.js +106 -0
  354. package/dist/services/memory/project-memory-service/parsers/markdown-pure.d.ts +7 -0
  355. package/dist/services/memory/project-memory-service/parsers/markdown-pure.js +96 -0
  356. package/dist/services/memory/project-memory-service/store/atomic-write.d.ts +5 -0
  357. package/dist/services/memory/project-memory-service/store/atomic-write.js +56 -0
  358. package/dist/services/memory/project-memory-service/store/paths.d.ts +8 -0
  359. package/dist/services/memory/project-memory-service/store/paths.js +116 -0
  360. package/dist/services/memory/project-memory-service/types.d.ts +128 -0
  361. package/dist/services/memory/project-memory-service/types.js +9 -0
  362. package/dist/services/memory/project-memory-service.d.ts +1 -167
  363. package/dist/services/memory/project-memory-service.js +19 -816
  364. package/dist/services/migrate-skill-name/schema.d.ts +2 -2
  365. package/dist/services/observability/aggregation.d.ts +27 -0
  366. package/dist/services/observability/aggregation.js +72 -0
  367. package/dist/services/observability/observability-service.d.ts +73 -7
  368. package/dist/services/observability/observability-service.js +87 -1
  369. package/dist/services/openspec/artifact-boundary.d.ts +138 -0
  370. package/dist/services/openspec/artifact-boundary.js +150 -0
  371. package/dist/services/openspec/coverage-evidence-reader.d.ts +191 -0
  372. package/dist/services/openspec/coverage-evidence-reader.js +386 -0
  373. package/dist/services/openspec/openspec-archive-service.d.ts +70 -0
  374. package/dist/services/openspec/openspec-archive-service.js +320 -8
  375. package/dist/services/openspec/openspec-bridge-service.js +1 -1
  376. package/dist/services/openspec/openspec-init-service.js +1 -1
  377. package/dist/services/openspec/openspec-propose-from-doctor-service.js +1 -1
  378. package/dist/services/openspec/openspec-render-service.js +7 -4
  379. package/dist/services/openspec/openspec-scan-service.js +1 -1
  380. package/dist/services/openspec/openspec-validate-service.js +5 -4
  381. package/dist/services/preferences/preferences-service.js +10 -0
  382. package/dist/services/preferences/preferences-types.d.ts +13 -0
  383. package/dist/services/preferences/preferences-types.js +11 -0
  384. package/dist/services/qa/screenshot-archive-service.d.ts +51 -0
  385. package/dist/services/qa/screenshot-archive-service.js +134 -0
  386. package/dist/services/rd/rd-service.js +10 -11
  387. package/dist/services/rd/types.d.ts +32 -32
  388. package/dist/services/rd-swarm/rd-swarm-service.d.ts +60 -0
  389. package/dist/services/rd-swarm/rd-swarm-service.js +93 -0
  390. package/dist/services/recommendations/capability-seed-items.js +0 -1
  391. package/dist/services/recommendations/capability-seed-mappings.js +0 -1
  392. package/dist/services/recommendations/capability-seed-sources.js +0 -1
  393. package/dist/services/release/version-precheck-service.d.ts +51 -0
  394. package/dist/services/release/version-precheck-service.js +257 -0
  395. package/dist/services/scan/acceptance-coverage-service.js +1 -1
  396. package/dist/services/scan/archetype-service.js +1 -1
  397. package/dist/services/scan/existing-system-service.js +1 -1
  398. package/dist/services/scan/libraries-service.js +1 -1
  399. package/dist/services/sediment/json-schema.d.ts +40 -40
  400. package/dist/services/share/bundle-types.d.ts +12 -12
  401. package/dist/services/share/run-state-contract.d.ts +2 -2
  402. package/dist/services/skill/skill-search-service.d.ts +12 -7
  403. package/dist/services/skill/skill-search-service.js +8 -4
  404. package/dist/services/skillhub/migrations/001-initial.sql +71 -0
  405. package/dist/services/skillhub/migrations/002-loop-release.sql +32 -0
  406. package/dist/services/skillhub/migrations/003-loop-bee-relation.sql +35 -0
  407. package/dist/services/skillhub/migrations/004-loop-bee-extension.sql +65 -0
  408. package/dist/services/skillhub/migrations/005-evolution-evaluation.sql +81 -0
  409. package/dist/services/skillhub/migrations/006-crystallization-event.sql +92 -0
  410. package/dist/services/skills/hooks-settings-service.d.ts +75 -0
  411. package/dist/services/skills/hooks-settings-service.js +230 -2
  412. package/dist/services/skills/skill-registry.d.ts +1 -0
  413. package/dist/services/skills/skill-registry.js +6 -4
  414. package/dist/services/skills/skill-runbook-service.js +1 -1
  415. package/dist/services/slice/slice-check-service.js +1 -1
  416. package/dist/services/standards/main-session-monitor-ban-hook.d.ts +14 -0
  417. package/dist/services/standards/main-session-monitor-ban-hook.js +19 -0
  418. package/dist/services/standards/missing-standards-detector.d.ts +25 -0
  419. package/dist/services/standards/missing-standards-detector.js +43 -12
  420. package/dist/services/tech/tech-change-id-service.d.ts +82 -0
  421. package/dist/services/tech/tech-change-id-service.js +117 -0
  422. package/dist/services/understand/understand-hybrid-service.js +1 -1
  423. package/dist/services/understand/understand-scan-service.js +2 -2
  424. package/dist/services/upgrade/upgrade-service.js +4 -3
  425. package/dist/services/verdict/envelopes.d.ts +2 -2
  426. package/dist/services/verdict/envelopes.js +2 -2
  427. package/dist/services/verdict/verdict-aggregator.d.ts +3 -3
  428. package/dist/services/vm/vm-lease.d.ts +40 -0
  429. package/dist/services/vm/vm-lease.js +137 -0
  430. package/dist/services/workflow/autonomous-resume-writer.js +1 -1
  431. package/dist/services/workflow/pipeline-verify-gate-support.d.ts +47 -0
  432. package/dist/services/workflow/pipeline-verify-gate-support.js +194 -0
  433. package/dist/services/workflow/pipeline-verify-service.d.ts +17 -81
  434. package/dist/services/workflow/pipeline-verify-service.js +42 -218
  435. package/dist/services/workflow/pipeline-verify-types.d.ts +90 -0
  436. package/dist/services/workflow/pipeline-verify-types.js +10 -0
  437. package/dist/services/workflow/plan-reader.d.ts +1 -1
  438. package/dist/services/workflow/plan-reader.js +1 -1
  439. package/dist/services/workflow/plan-refresher.d.ts +1 -1
  440. package/dist/services/workflow/plan-refresher.js +1 -1
  441. package/dist/services/workflow/plan-trigger-detector.d.ts +1 -1
  442. package/dist/services/workflow/plan-trigger-detector.js +1 -1
  443. package/dist/services/workflow/workflow-autonomous-resume-helpers.d.ts +1 -1
  444. package/dist/services/workflow/workflow-autonomous-service.d.ts +2 -98
  445. package/dist/services/workflow/workflow-autonomous-types.d.ts +114 -0
  446. package/dist/services/workflow/workflow-autonomous-types.js +21 -0
  447. package/dist/services/workflow/workflow-router-service.js +18 -16
  448. package/dist/services/workflow/workflow-spec-lint.d.ts +13 -0
  449. package/dist/services/workflow/workflow-spec-lint.js +75 -0
  450. package/dist/services/workflow/workflow-spec-types.d.ts +100 -0
  451. package/dist/services/workflow/workflow-spec-types.js +13 -0
  452. package/dist/services/workflow/workflow-spec-yaml.d.ts +17 -0
  453. package/dist/services/workflow/workflow-spec-yaml.js +88 -0
  454. package/dist/services/workflow/workflow-spec.d.ts +11 -91
  455. package/dist/services/workflow/workflow-spec.js +16 -145
  456. package/dist/services/workspace/migrate-service.js +1 -1
  457. package/dist/services/workspace/workspace-service.js +1 -1
  458. package/dist/services/worktree/worktree-lease.d.ts +170 -0
  459. package/dist/services/worktree/worktree-lease.js +242 -0
  460. package/package.json +47 -51
  461. package/scripts/clean-dist.mjs +31 -1
  462. package/scripts/copy-templates.mjs +16 -0
  463. package/scripts/sync-version.mjs +53 -2
  464. package/skills/bee/peaks-perf-audit/SKILL.md +17 -0
  465. package/skills/bee/peaks-prd/SKILL.md +16 -0
  466. package/skills/bee/peaks-prd/test-prompts.json +12 -0
  467. package/skills/bee/peaks-qa/SKILL.md +16 -1
  468. package/skills/bee/peaks-qa/references/qa-sub-agent-dispatch.md +22 -0
  469. package/skills/bee/peaks-qa/test-prompts.json +12 -0
  470. package/skills/bee/peaks-rd/SKILL.md +29 -20
  471. package/skills/bee/peaks-rd/references/rd-sub-agent-dispatch.md +39 -0
  472. package/skills/bee/peaks-rd/test-prompts.json +12 -0
  473. package/skills/bee/peaks-reviewer/SKILL.md +17 -0
  474. package/skills/bee/peaks-sc/SKILL.md +16 -0
  475. package/skills/bee/peaks-security-audit/SKILL.md +17 -0
  476. package/skills/bee/peaks-txt/SKILL.md +16 -0
  477. package/skills/bee/peaks-txt/test-prompts.json +12 -0
  478. package/skills/bee/peaks-ui/SKILL.md +49 -43
  479. package/skills/bee/peaks-ui/test-prompts.json +12 -0
  480. package/skills/peaks-code/SKILL.md +54 -109
  481. package/skills/peaks-code/references/boundaries.md +15 -1
  482. package/skills/peaks-code/references/cron-scheduler-deployment.md +313 -0
  483. package/skills/peaks-code/references/external-skill-invocation.md +27 -0
  484. package/skills/peaks-code/references/lease-dashboard.html +224 -0
  485. package/skills/peaks-code/references/lease-stats.sample.json +26 -0
  486. package/skills/peaks-code/references/peaks-worktree-l2-enforcers.md +208 -0
  487. package/skills/peaks-code/references/periodic-checkpoint.md +4 -4
  488. package/skills/peaks-code/references/runbook.md +63 -1
  489. package/skills/peaks-code/references/startup-sequence.md +110 -0
  490. package/skills/peaks-code/references/step-0-8-gate.md +1 -1
  491. package/skills/peaks-code/references/sub-agent-dispatch.md +92 -1
  492. package/skills/peaks-code/references/worktree-governance.md +123 -0
  493. package/skills/peaks-code/test-prompts.json +12 -0
  494. package/skills/peaks-doctor/SKILL.md +1 -1
  495. package/skills/peaks-ide/SKILL.md +1 -1
  496. package/skills/peaks-solo/SKILL.md +21 -0
  497. package/skills/peaks-solo/references/triage-decision-table.md +6 -0
  498. package/skills/peaks-sop/test-prompts.json +17 -0
  499. package/dist/cli/commands/agent-commands.d.ts +0 -20
  500. package/dist/cli/commands/agent-commands.js +0 -48
  501. package/dist/cli/commands/classify-classify-commands.d.ts +0 -19
  502. package/dist/cli/commands/classify-classify-commands.js +0 -151
  503. package/dist/cli/commands/contract-commands.d.ts +0 -26
  504. package/dist/cli/commands/contract-commands.js +0 -114
  505. package/dist/cli/commands/session-auto-compact-hook-command.d.ts +0 -37
  506. package/dist/cli/commands/session-auto-compact-hook-command.js +0 -127
  507. package/dist/cli/commands/worker-commands.d.ts +0 -3
  508. package/dist/cli/commands/worker-commands.js +0 -52
  509. package/dist/services/agent/ecc-agent-service.d.ts +0 -47
  510. package/dist/services/agent/ecc-agent-service.js +0 -143
  511. package/dist/services/config/provider-service.d.ts +0 -48
  512. package/dist/services/config/provider-service.js +0 -143
  513. package/dist/services/context/dispatch-context-guard.d.ts +0 -27
  514. package/dist/services/context/dispatch-context-guard.js +0 -192
  515. package/dist/services/context/shared-channel.d.ts +0 -93
  516. package/dist/services/context/shared-channel.js +0 -308
  517. package/dist/services/filesystem/file-lock.d.ts +0 -11
  518. package/dist/services/filesystem/file-lock.js +0 -152
  519. package/dist/services/mut/assert-scanner.d.ts +0 -6
  520. package/dist/services/mut/assert-scanner.js +0 -116
  521. package/dist/services/mut/index.d.ts +0 -8
  522. package/dist/services/mut/index.js +0 -7
  523. package/dist/services/mut/mut-runner.d.ts +0 -39
  524. package/dist/services/mut/mut-runner.js +0 -29
  525. package/dist/services/mut/production-stryker.d.ts +0 -2
  526. package/dist/services/mut/production-stryker.js +0 -75
  527. package/dist/services/mut/report-builder.d.ts +0 -11
  528. package/dist/services/mut/report-builder.js +0 -110
  529. package/dist/services/mut/report-loader.d.ts +0 -31
  530. package/dist/services/mut/report-loader.js +0 -78
  531. package/dist/services/mut/thresholds.d.ts +0 -21
  532. package/dist/services/mut/thresholds.js +0 -22
  533. package/dist/services/mut/types.d.ts +0 -336
  534. package/dist/services/mut/types.js +0 -59
  535. package/dist/services/providers/minimax-provider-service.d.ts +0 -24
  536. package/dist/services/providers/minimax-provider-service.js +0 -143
  537. package/dist/services/providers/minimax-worker-service.d.ts +0 -21
  538. package/dist/services/providers/minimax-worker-service.js +0 -83
  539. package/dist/shared/fs.d.ts +0 -4
  540. package/dist/shared/fs.js +0 -26
  541. package/dist/shared/paths.d.ts +0 -6
  542. package/dist/shared/paths.js +0 -50
  543. package/dist/shared/result.d.ts +0 -22
  544. package/dist/shared/result.js +0 -46
  545. package/dist/shared/version.d.ts +0 -1
  546. package/dist/shared/version.js +0 -1
  547. package/examples/video-demo/README.md +0 -142
  548. package/examples/video-demo/out/en-closing-960.png +0 -0
  549. package/examples/video-demo/out/zh-closing-960.png +0 -0
  550. package/examples/video-demo/preview/peaks-loop-demo-en.mp4 +0 -0
  551. package/examples/video-demo/preview/peaks-loop-demo.mp4 +0 -0
  552. /package/dist/services/{job/job-resource-snapshot.js → job-snapshot/snapshot.js} +0 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * MemoryPreflightService — orchestrator-facing API for the
3
+ * "Orchestrator Memory Preflight" slice (see
4
+ * docs/superpowers/specs/2026-07-22-orchestrator-memory-preflight-design.md).
5
+ *
6
+ * Consumes:
7
+ * - resolveMemoryPreflightConfig (Task 1) — merged defaults + per-project overlay
8
+ * - MemoryIndexReader (Task 3) — reads .peaks/memory/index.json + layer=A filter
9
+ * - MemoryLruCache (Task 2) — constructed for capacity parity, but NOT used
10
+ * for memo content (see deviation note below)
11
+ * - compressPrompt (existing) — headroom-ai wrapper for hard-cap compression
12
+ *
13
+ * Deviation from brief — controller-accepted (pre-task 4):
14
+ * The brief mandated use of `MemoryLruCache` for memo content caching. The
15
+ * orchestrator dispatch flow only ever has at most a handful of explicit
16
+ * `cacheMemoContent` calls per task (typically 0-3), and ordering / explicit
17
+ * invalidation is preferred over LRU eviction by recency. To keep the
18
+ * semantic obvious and the byte budget check trivial, this implementation
19
+ * uses a plain `Map<path, body>` for memo path -> body content. The
20
+ * `MemoryLruCache` class remains as a separate, reusable LRU primitive
21
+ * (Task 2) and is not consumed by this service.
22
+ */
23
+ import { compressPrompt } from './headroom-client.js';
24
+ import { MemoryIndexReader } from './memory-index-reader.js';
25
+ import { resolveMemoryPreflightConfig, } from './memory-preflight-config.js';
26
+ async function compressToCap(text, capBytes, mode) {
27
+ try {
28
+ const result = await compressPrompt(text, mode);
29
+ if (result.warning !== null || result.compressedPrompt === null) {
30
+ return { text, truncated: false };
31
+ }
32
+ const compressed = result.compressedPrompt;
33
+ if (Buffer.byteLength(compressed, 'utf8') > capBytes) {
34
+ const sliced = compressed.slice(0, Math.max(0, capBytes - 64)) + '\n…[truncated]';
35
+ return { text: sliced, truncated: true };
36
+ }
37
+ return { text: compressed, truncated: false };
38
+ }
39
+ catch {
40
+ return { text, truncated: false };
41
+ }
42
+ }
43
+ export class MemoryPreflightService {
44
+ reader;
45
+ config;
46
+ /** path -> body; sub-agent-requested memo contents (Task 4 deviation, see module header). */
47
+ cachedMemoContents = new Map();
48
+ constructor(projectRoot, prefs) {
49
+ this.config = resolveMemoryPreflightConfig(prefs);
50
+ this.reader = new MemoryIndexReader(projectRoot);
51
+ }
52
+ cacheMemoContent(path, content) {
53
+ if (!this.config.enabled)
54
+ return;
55
+ const bytes = Buffer.byteLength(content, 'utf8');
56
+ if (bytes > this.config.contentCacheBytes) {
57
+ // too big to ever fit; do not cache.
58
+ return;
59
+ }
60
+ this.cachedMemoContents.set(path, content);
61
+ }
62
+ async fetchBlock(_taskTitle) {
63
+ if (!this.config.enabled)
64
+ return { available: false, reason: 'DISABLED' };
65
+ const selected = this.reader.selectFeedbackLayerA(this.config.listCap);
66
+ if (selected.length === 0) {
67
+ const any = this.reader.loadIfStale();
68
+ if (any.length === 0)
69
+ return { available: false, reason: 'MEMORY_INDEX_MISSING' };
70
+ return { available: false, reason: 'NO_FEEDBACK_LAYER_A' };
71
+ }
72
+ const listLines = selected
73
+ .map((e) => `- * ${e.name}\n Path: ${e.sourcePath}\n One-line: ${summarize(e.description)}`)
74
+ .join('\n');
75
+ let tail = '\n';
76
+ let cachedCount = 0;
77
+ if (this.cachedMemoContents.size > 0) {
78
+ const sections = [];
79
+ for (const [path, body] of this.cachedMemoContents) {
80
+ sections.push(`### ${path}\n\n${body}`);
81
+ cachedCount += 1;
82
+ }
83
+ tail = `\n\n## Requested memory details:\n${sections.join('\n\n')}\n`;
84
+ }
85
+ const header = '## Project memory relevant to this task\n';
86
+ const composed = `${header}${listLines}${tail}`;
87
+ const capBytes = Math.max(64, this.config.maxTokens * 4);
88
+ const { text, truncated } = await compressToCap(composed, capBytes, 'balanced');
89
+ const droppedCount = truncated ? selected.length - countItemsInBlock(text) : 0;
90
+ return {
91
+ available: true,
92
+ block: text,
93
+ feedbackListItems: selected.length,
94
+ cachedItemCount: cachedCount,
95
+ truncated,
96
+ droppedCount: droppedCount > 0 ? droppedCount : undefined,
97
+ };
98
+ }
99
+ }
100
+ function summarize(description) {
101
+ // Drop the <!-- peaks-feedback-promoted: layer=A --> marker, take the next 1 line.
102
+ const cleaned = description.replace(/<!--[^>]*-->/g, '').trim();
103
+ return cleaned.split('\n')[0] ?? cleaned;
104
+ }
105
+ function countItemsInBlock(text) {
106
+ // Count `- * ` markers ONLY in the list portion (between the
107
+ // `## Project memory relevant to this task` header and the
108
+ // `## Requested memory details:` sub-section, if present). Memo
109
+ // bodies appended under `## Requested memory details:` may
110
+ // legitimately contain their own `- * ` markdown bullets, which
111
+ // would otherwise inflate the count and produce a wrong
112
+ // `droppedCount` in the truncated case.
113
+ const headerEnd = text.indexOf('\n## ');
114
+ if (headerEnd === -1) {
115
+ return (text.match(/- \* /g) ?? []).length;
116
+ }
117
+ const tailStart = text.indexOf('\n## Requested memory details:', headerEnd + 1);
118
+ const listEnd = tailStart === -1 ? text.length : tailStart;
119
+ return (text.slice(0, listEnd).match(/- \* /g) ?? []).length;
120
+ }
@@ -0,0 +1,23 @@
1
+ import type { SpillId, SpillOptions, SpillRecord, SpillState } from './spillover-types.js';
2
+ /**
3
+ * Defense-in-depth: assert the given path is NOT a symbolic link.
4
+ *
5
+ * Symlinks pointing outside the spill directory could be used to bypass
6
+ * the containment check (assertInside). This function uses lstat (which
7
+ * does NOT follow symlinks) to detect symbolic links and reject them.
8
+ *
9
+ * Note: this check is redundant with the entry.isFile() check in
10
+ * listSpills() (which rejects symlinks on most platforms), but
11
+ * provides belt-and-suspenders defense for the writeRecord and
12
+ * hydrate entry points.
13
+ */
14
+ export declare function assertNotSymlink(path: string): void;
15
+ export declare function spillDir(projectRoot: string, sessionId: string): string;
16
+ export declare function spillPath(projectRoot: string, sessionId: string, spillId: SpillId): string;
17
+ export declare function createSpillId(now?: Date): SpillId;
18
+ export declare function spill(options: SpillOptions, payload: Readonly<Record<string, unknown>>): SpillRecord;
19
+ export declare function hydrate(projectRoot: string, sessionId: string, spillId: SpillId): SpillRecord | null;
20
+ export declare function listSpills(projectRoot: string, sessionId: string, options?: {
21
+ readonly state?: SpillState;
22
+ }): readonly SpillRecord[];
23
+ export declare function pruneExpiredSpills(projectRoot: string, sessionId: string): readonly string[];
@@ -0,0 +1,155 @@
1
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { isAbsolute, join, relative } from 'node:path';
4
+ import { SPILL_TTL_MS } from './spillover-types.js';
5
+ const SAFE_SEGMENT = /^[A-Za-z0-9._-]+$/;
6
+ function assertSafeSegment(value, name) {
7
+ if (!SAFE_SEGMENT.test(value) || value === '.' || value === '..') {
8
+ throw new Error(`${name} must be a safe path segment`);
9
+ }
10
+ }
11
+ function assertInside(base, target) {
12
+ const rel = relative(base, target);
13
+ if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`) || isAbsolute(rel)) {
14
+ throw new Error('Spill path must stay inside the session spill directory');
15
+ }
16
+ }
17
+ /**
18
+ * Defense-in-depth: assert the given path is NOT a symbolic link.
19
+ *
20
+ * Symlinks pointing outside the spill directory could be used to bypass
21
+ * the containment check (assertInside). This function uses lstat (which
22
+ * does NOT follow symlinks) to detect symbolic links and reject them.
23
+ *
24
+ * Note: this check is redundant with the entry.isFile() check in
25
+ * listSpills() (which rejects symlinks on most platforms), but
26
+ * provides belt-and-suspenders defense for the writeRecord and
27
+ * hydrate entry points.
28
+ */
29
+ export function assertNotSymlink(path) {
30
+ if (!existsSync(path))
31
+ return; // file doesn't exist yet (writeRecord) or already gone (hydrate)
32
+ const st = lstatSync(path);
33
+ if (st.isSymbolicLink()) {
34
+ throw new Error(`Refusing to operate on symbolic link: ${path}`);
35
+ }
36
+ }
37
+ export function spillDir(projectRoot, sessionId) {
38
+ assertSafeSegment(sessionId, 'sessionId');
39
+ return join(projectRoot, '.peaks', '_runtime', sessionId, 'spill');
40
+ }
41
+ export function spillPath(projectRoot, sessionId, spillId) {
42
+ assertSafeSegment(spillId, 'spillId');
43
+ const dir = spillDir(projectRoot, sessionId);
44
+ const path = join(dir, `${spillId}.json`);
45
+ assertInside(dir, path);
46
+ return path;
47
+ }
48
+ export function createSpillId(now = new Date()) {
49
+ const date = now.toISOString().slice(0, 10);
50
+ const timestamp = now.getTime().toString(36);
51
+ return `spill-${date}-${timestamp}-${randomUUID().slice(0, 8)}`;
52
+ }
53
+ function writeRecord(path, record) {
54
+ assertNotSymlink(path);
55
+ const content = JSON.stringify(record, null, 2);
56
+ const temporaryPath = `${path}.${randomUUID()}.tmp`;
57
+ writeFileSync(temporaryPath, content, 'utf8');
58
+ try {
59
+ renameSync(temporaryPath, path);
60
+ }
61
+ catch {
62
+ writeFileSync(path, content, 'utf8');
63
+ try {
64
+ unlinkSync(temporaryPath);
65
+ }
66
+ catch {
67
+ // Best-effort cleanup after the direct-write fallback.
68
+ }
69
+ }
70
+ }
71
+ export function spill(options, payload) {
72
+ const record = {
73
+ spillId: createSpillId(),
74
+ sessionId: options.sessionId,
75
+ projectRoot: options.projectRoot,
76
+ createdAt: new Date().toISOString(),
77
+ state: 'pending',
78
+ payload,
79
+ ...(options.batchId === undefined ? {} : { batchId: options.batchId })
80
+ };
81
+ mkdirSync(spillDir(options.projectRoot, options.sessionId), { recursive: true });
82
+ writeRecord(spillPath(options.projectRoot, options.sessionId, record.spillId), record);
83
+ return record;
84
+ }
85
+ function readRecord(path) {
86
+ try {
87
+ return JSON.parse(readFileSync(path, 'utf8'));
88
+ }
89
+ catch {
90
+ return null;
91
+ }
92
+ }
93
+ export function hydrate(projectRoot, sessionId, spillId) {
94
+ const path = spillPath(projectRoot, sessionId, spillId);
95
+ if (!existsSync(path))
96
+ return null;
97
+ try {
98
+ assertNotSymlink(path);
99
+ const record = readRecord(path);
100
+ if (record === null)
101
+ return null;
102
+ const hydrated = {
103
+ ...record,
104
+ state: 'hydrated',
105
+ hydratedAt: new Date().toISOString()
106
+ };
107
+ writeRecord(path, hydrated);
108
+ return hydrated;
109
+ }
110
+ catch {
111
+ return null;
112
+ }
113
+ }
114
+ export function listSpills(projectRoot, sessionId, options) {
115
+ const dir = spillDir(projectRoot, sessionId);
116
+ if (!existsSync(dir))
117
+ return [];
118
+ const now = Date.now();
119
+ const records = readdirSync(dir, { withFileTypes: true })
120
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.json'))
121
+ .map((entry) => readRecord(join(dir, entry.name)))
122
+ .filter((record) => record !== null)
123
+ .map((record) => {
124
+ const age = now - new Date(record.createdAt).getTime();
125
+ return age > SPILL_TTL_MS && record.state === 'pending'
126
+ ? { ...record, state: 'expired' }
127
+ : record;
128
+ })
129
+ .filter((record) => options?.state === undefined || record.state === options.state);
130
+ records.sort((left, right) => left.createdAt.localeCompare(right.createdAt));
131
+ return records;
132
+ }
133
+ export function pruneExpiredSpills(projectRoot, sessionId) {
134
+ const dir = spillDir(projectRoot, sessionId);
135
+ if (!existsSync(dir))
136
+ return [];
137
+ const now = Date.now();
138
+ const removed = [];
139
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
140
+ if (!entry.isFile() || !entry.name.endsWith('.json'))
141
+ continue;
142
+ const path = join(dir, entry.name);
143
+ const record = readRecord(path);
144
+ if (record === null || now - new Date(record.createdAt).getTime() <= SPILL_TTL_MS)
145
+ continue;
146
+ try {
147
+ unlinkSync(path);
148
+ removed.push(path);
149
+ }
150
+ catch {
151
+ // Best-effort pruning leaves failed paths for a later attempt.
152
+ }
153
+ }
154
+ return removed;
155
+ }
@@ -0,0 +1,18 @@
1
+ export type SpillId = string;
2
+ export type SpillState = 'pending' | 'hydrated' | 'expired';
3
+ export interface SpillRecord {
4
+ readonly spillId: SpillId;
5
+ readonly sessionId: string;
6
+ readonly projectRoot: string;
7
+ readonly createdAt: string;
8
+ readonly state: SpillState;
9
+ readonly payload: Readonly<Record<string, unknown>>;
10
+ readonly batchId?: string;
11
+ readonly hydratedAt?: string;
12
+ }
13
+ export interface SpillOptions {
14
+ readonly sessionId: string;
15
+ readonly projectRoot: string;
16
+ readonly batchId?: string;
17
+ }
18
+ export declare const SPILL_TTL_MS: number;
@@ -0,0 +1 @@
1
+ export const SPILL_TTL_MS = 24 * 60 * 60 * 1000;
@@ -2,7 +2,17 @@ import type Database from "better-sqlite3";
2
2
  import { z } from "zod";
3
3
  import { type CrystallizationEvent, type CrystallizationEventInput, type CrystallizationEventStatus, type EvidenceBrief } from "./crystallization-types.js";
4
4
  import { listCrystallizationEvents } from "./crystallization-store.js";
5
- import { type LoopReleaseInput } from "../loop/loop-release-types.js";
5
+ type LoopReleaseZodSchema = {
6
+ parse: (input: unknown) => unknown;
7
+ };
8
+ type LoopBeeRelationZodSchema = {
9
+ parse: (input: unknown) => unknown;
10
+ omit: (keys: Record<string, true>) => {
11
+ parse: (input: unknown) => unknown;
12
+ };
13
+ };
14
+ type InsertLoopReleaseFn = (db: Database.Database, row: unknown) => void;
15
+ type InsertLoopBeeRelationFn = (db: Database.Database, row: unknown) => unknown;
6
16
  /**
7
17
  * CrystallizationService — spec §5 (post-run crystallization)
8
18
  * + §4.5 + §4.7 + §10 RL-2 / RL-3 / RL-7.
@@ -88,7 +98,7 @@ export interface CrystallizePayload {
88
98
  /** The candidate task state. Must satisfy the pre-run gate. */
89
99
  task: CrystallizationTaskState;
90
100
  /** The loop_release to create (new). Must include main bee via relation. */
91
- loop_input: LoopReleaseInput;
101
+ loop_input: unknown;
92
102
  /**
93
103
  * The main bee_release to create. Note: bee_release requires a
94
104
  * manifest row to keep the existing 4.x schema consistent;
@@ -153,9 +163,16 @@ export interface CrystallizationResult {
153
163
  /**
154
164
  * Service interface for the post-run crystallization flow.
155
165
  */
166
+ export interface CrystallizationOptions {
167
+ loopReleaseSchema: LoopReleaseZodSchema;
168
+ loopBeeRelationSchema: LoopBeeRelationZodSchema;
169
+ insertLoopRelease: InsertLoopReleaseFn;
170
+ insertLoopBeeRelation: InsertLoopBeeRelationFn;
171
+ }
156
172
  export declare class CrystallizationService {
157
173
  private readonly db;
158
- constructor(db: Database.Database);
174
+ private readonly opts;
175
+ constructor(db: Database.Database, opts: CrystallizationOptions);
159
176
  /**
160
177
  * Read a CrystallizationEvent by id.
161
178
  */
@@ -167,8 +184,6 @@ export declare class CrystallizationService {
167
184
  */
168
185
  list(opts?: Parameters<typeof listCrystallizationEvents>[1]): {
169
186
  schema_version: "peaks.crystallization/1";
170
- id: string;
171
- lifecycle_status: "candidate" | "stable" | "retired";
172
187
  trigger: "user_explicit" | "llm_suggested" | "success_default_prompt" | "similar_task_recurrence";
173
188
  evidence_brief: {
174
189
  what_happened: string;
@@ -180,6 +195,8 @@ export declare class CrystallizationService {
180
195
  source_trace_pointers: string[];
181
196
  evaluator_summary: string;
182
197
  user_decision_summary: string;
198
+ lifecycle_status: "candidate" | "stable" | "retired";
199
+ id: string;
183
200
  created_at: string;
184
201
  created_loop_release_id?: string | undefined;
185
202
  updated_loop_release_id?: string | undefined;
@@ -2,10 +2,6 @@ import { z, ZodError } from "zod";
2
2
  import { CrystallizationEventSchema, EvidenceBriefSchema, } from "./crystallization-types.js";
3
3
  import { BriefSectionError } from "./evidence-brief-builder.js";
4
4
  import { CRYSTALLIZATION_SCHEMA_VERSION, ensureCrystallizationEventTable, getCrystallizationEvent, listCrystallizationEvents, newCrystallizationId, updateCrystallizationEventStatus, } from "./crystallization-store.js";
5
- import { insertLoopRelease } from "../loop/loop-release-store.js";
6
- import { LoopReleaseSchema } from "../loop/loop-release-types.js";
7
- import { insertLoopBeeRelation } from "../loop/loop-bee-relation-store.js";
8
- import { LoopBeeRelationSchema, } from "../loop/loop-bee-relation-types.js";
9
5
  /**
10
6
  * CrystallizationService — spec §5 (post-run crystallization)
11
7
  * + §4.5 + §4.7 + §10 RL-2 / RL-3 / RL-7.
@@ -126,13 +122,12 @@ const BeeCrystallizeInputSchema = z.object({
126
122
  parent_version: z.string().trim().max(64).optional(),
127
123
  changelog: z.string().trim().max(8000).optional(),
128
124
  });
129
- /**
130
- * Service interface for the post-run crystallization flow.
131
- */
132
125
  export class CrystallizationService {
133
126
  db;
134
- constructor(db) {
127
+ opts;
128
+ constructor(db, opts) {
135
129
  this.db = db;
130
+ this.opts = opts;
136
131
  // Idempotent — safe to call on every constructor invocation; the
137
132
  // openStateDb pipeline already applied the SQL migration, but a
138
133
  // caller-built DB (e.g. tests) needs this.
@@ -256,14 +251,14 @@ export class CrystallizationService {
256
251
  }
257
252
  // Re-validate loop_input via Zod so a hand-crafted caller input
258
253
  // cannot bypass the schema. (M8 dogfood follow-up.)
259
- const loopRow = LoopReleaseSchema.parse(payload.loop_input);
254
+ const loopRow = this.opts.loopReleaseSchema.parse(payload.loop_input);
260
255
  // Re-validate bee_input.
261
256
  const beeRow = BeeCrystallizeInputSchema.parse(payload.bee_input);
262
257
  // Loop-bee relation input (the relation's `reason` is the NL
263
258
  // account the LLM authored). We validate the shape WITHOUT
264
259
  // bee_release_id (which is filled in by the bee insert below),
265
260
  // then validate the final tuple after the SQL writes.
266
- const relationInputShape = LoopBeeRelationSchema.omit({
261
+ const relationInputShape = this.opts.loopBeeRelationSchema.omit({
267
262
  id: true,
268
263
  created_at: true,
269
264
  bee_release_id: true,
@@ -280,7 +275,7 @@ export class CrystallizationService {
280
275
  let eventPersistedId = eventId;
281
276
  const tx = this.db.transaction(() => {
282
277
  // 1. Insert loop_release.
283
- insertLoopRelease(this.db, loopRow);
278
+ this.opts.insertLoopRelease(this.db, loopRow);
284
279
  // 2. Insert bee_release header. The existing
285
280
  // `retainRelease` adds segment_ref / file / change rows; the
286
281
  // minimal crystallization write here only opens the bee_release
@@ -311,7 +306,7 @@ export class CrystallizationService {
311
306
  // 4. Insert the loop_bee_relation row (FKs now valid). Re-parse
312
307
  // through the input schema so the bee_release_id is validated
313
308
  // too — defense in depth. `id` is autoincrement (not in input).
314
- const fullRelation = LoopBeeRelationSchema.omit({
309
+ const fullRelation = this.opts.loopBeeRelationSchema.omit({
315
310
  id: true,
316
311
  created_at: true,
317
312
  }).parse({
@@ -319,9 +314,8 @@ export class CrystallizationService {
319
314
  bee_release_id: beeReleaseId,
320
315
  role: relationInputShape.role,
321
316
  reason: relationInputShape.reason,
322
- schema_version: "peaks.loop-bee-relation/1",
323
317
  });
324
- const relationRow = insertLoopBeeRelation(this.db, fullRelation);
318
+ const relationRow = this.opts.insertLoopBeeRelation(this.db, fullRelation);
325
319
  relationId = relationRow.id;
326
320
  // 5. Persist the crystallization_event row with the brief inline
327
321
  // (the brief is the durable evidence — AC-17).
@@ -136,7 +136,6 @@ export declare const CrystallizationEventInputSchema: z.ZodObject<{
136
136
  updated_bee_release_id: z.ZodOptional<z.ZodNumber>;
137
137
  lifecycle_status: z.ZodDefault<z.ZodEnum<["candidate", "stable", "retired"]>>;
138
138
  }, "strip", z.ZodTypeAny, {
139
- lifecycle_status: "candidate" | "stable" | "retired";
140
139
  trigger: "user_explicit" | "llm_suggested" | "success_default_prompt" | "similar_task_recurrence";
141
140
  evidence_brief: {
142
141
  what_happened: string;
@@ -148,6 +147,7 @@ export declare const CrystallizationEventInputSchema: z.ZodObject<{
148
147
  source_trace_pointers: string[];
149
148
  evaluator_summary: string;
150
149
  user_decision_summary: string;
150
+ lifecycle_status: "candidate" | "stable" | "retired";
151
151
  created_loop_release_id?: string | undefined;
152
152
  updated_loop_release_id?: string | undefined;
153
153
  created_bee_release_id?: number | undefined;
@@ -160,7 +160,6 @@ export declare const CrystallizationEventInputSchema: z.ZodObject<{
160
160
  what_learned: string;
161
161
  what_action: string;
162
162
  };
163
- lifecycle_status?: "candidate" | "stable" | "retired" | undefined;
164
163
  evidence_bullets?: string[] | undefined;
165
164
  source_trace_pointers?: string[] | undefined;
166
165
  evaluator_summary?: string | undefined;
@@ -169,6 +168,7 @@ export declare const CrystallizationEventInputSchema: z.ZodObject<{
169
168
  updated_loop_release_id?: string | undefined;
170
169
  created_bee_release_id?: number | undefined;
171
170
  updated_bee_release_id?: number | undefined;
171
+ lifecycle_status?: "candidate" | "stable" | "retired" | undefined;
172
172
  }>;
173
173
  export type CrystallizationEventInput = z.input<typeof CrystallizationEventInputSchema>;
174
174
  /**
@@ -223,8 +223,6 @@ export declare const CrystallizationEventSchema: z.ZodObject<{
223
223
  created_at: z.ZodString;
224
224
  }, "strip", z.ZodTypeAny, {
225
225
  schema_version: "peaks.crystallization/1";
226
- id: string;
227
- lifecycle_status: "candidate" | "stable" | "retired";
228
226
  trigger: "user_explicit" | "llm_suggested" | "success_default_prompt" | "similar_task_recurrence";
229
227
  evidence_brief: {
230
228
  what_happened: string;
@@ -236,13 +234,14 @@ export declare const CrystallizationEventSchema: z.ZodObject<{
236
234
  source_trace_pointers: string[];
237
235
  evaluator_summary: string;
238
236
  user_decision_summary: string;
237
+ lifecycle_status: "candidate" | "stable" | "retired";
238
+ id: string;
239
239
  created_at: string;
240
240
  created_loop_release_id?: string | undefined;
241
241
  updated_loop_release_id?: string | undefined;
242
242
  created_bee_release_id?: number | undefined;
243
243
  updated_bee_release_id?: number | undefined;
244
244
  }, {
245
- id: string;
246
245
  trigger: "user_explicit" | "llm_suggested" | "success_default_prompt" | "similar_task_recurrence";
247
246
  evidence_brief: {
248
247
  what_happened: string;
@@ -250,9 +249,9 @@ export declare const CrystallizationEventSchema: z.ZodObject<{
250
249
  what_learned: string;
251
250
  what_action: string;
252
251
  };
252
+ id: string;
253
253
  created_at: string;
254
254
  schema_version?: "peaks.crystallization/1" | undefined;
255
- lifecycle_status?: "candidate" | "stable" | "retired" | undefined;
256
255
  evidence_bullets?: string[] | undefined;
257
256
  source_trace_pointers?: string[] | undefined;
258
257
  evaluator_summary?: string | undefined;
@@ -261,6 +260,7 @@ export declare const CrystallizationEventSchema: z.ZodObject<{
261
260
  updated_loop_release_id?: string | undefined;
262
261
  created_bee_release_id?: number | undefined;
263
262
  updated_bee_release_id?: number | undefined;
263
+ lifecycle_status?: "candidate" | "stable" | "retired" | undefined;
264
264
  }>;
265
265
  export type CrystallizationEvent = z.infer<typeof CrystallizationEventSchema>;
266
266
  /**
@@ -76,11 +76,11 @@ export declare const BriefTraceInputSchema: z.ZodObject<{
76
76
  */
77
77
  source_trace_pointers: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
78
78
  }, "strip", z.ZodTypeAny, {
79
- source_trace_pointers: string[];
80
79
  what_happened: string;
81
80
  why_it_matters: string;
82
81
  what_learned: string;
83
82
  what_action: string;
83
+ source_trace_pointers: string[];
84
84
  trace_id: string;
85
85
  bullets: string[];
86
86
  }, {
@@ -0,0 +1,13 @@
1
+ /**
2
+ * peaks-loop-crystallization area (consolidated into peaks-loop).
3
+ *
4
+ * Loop domain (loop-release / loop-bee-relation) lives in the main
5
+ * peaks-loop package. They are injected via CrystallizationOptions
6
+ * at call-site in src/cli/commands/asset-commands.ts, so this
7
+ * subpackage stays standalone and does NOT depend on the main
8
+ * peaks-loop package (avoiding workspace:* circular trap).
9
+ */
10
+ export { CrystallizationService, CrystallizationIntegrityError, type CrystallizationOptions, type CrystallizationTaskState, } from './crystallization-service.js';
11
+ export { ensureCrystallizationEventTable, insertCrystallizationEvent, getCrystallizationEvent, listCrystallizationEvents, newCrystallizationId, updateCrystallizationEventStatus, } from './crystallization-store.js';
12
+ export { CRYSTALLIZATION_TRIGGERS, parseEvidenceBrief, EvidenceBriefSchema, CrystallizationEventSchema, parseCrystallizationEvent, safeParseEvidenceBrief, safeParseCrystallizationEvent, hasAllFourBriefSections, type CrystallizationTrigger, type CrystallizationEvent, type CrystallizationEventInput, type CrystallizationEventStatus, type EvidenceBrief, } from './crystallization-types.js';
13
+ export { BriefSectionError, renderRecommendationPayload, safeRenderRecommendationPayload, buildEvidenceBrief, type BriefTraceInput, } from './evidence-brief-builder.js';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * peaks-loop-crystallization area (consolidated into peaks-loop).
3
+ *
4
+ * Loop domain (loop-release / loop-bee-relation) lives in the main
5
+ * peaks-loop package. They are injected via CrystallizationOptions
6
+ * at call-site in src/cli/commands/asset-commands.ts, so this
7
+ * subpackage stays standalone and does NOT depend on the main
8
+ * peaks-loop package (avoiding workspace:* circular trap).
9
+ */
10
+ export { CrystallizationService, CrystallizationIntegrityError, } from './crystallization-service.js';
11
+ export { ensureCrystallizationEventTable, insertCrystallizationEvent, getCrystallizationEvent, listCrystallizationEvents, newCrystallizationId, updateCrystallizationEventStatus, } from './crystallization-store.js';
12
+ export { CRYSTALLIZATION_TRIGGERS, parseEvidenceBrief, EvidenceBriefSchema, CrystallizationEventSchema, parseCrystallizationEvent, safeParseEvidenceBrief, safeParseCrystallizationEvent, hasAllFourBriefSections, } from './crystallization-types.js';
13
+ export { BriefSectionError, renderRecommendationPayload, safeRenderRecommendationPayload, buildEvidenceBrief, } from './evidence-brief-builder.js';
@@ -2,7 +2,7 @@ import { listRequestArtifacts } from '../artifacts/request-artifact-service.js';
2
2
  import { scanOpenSpec } from '../openspec/openspec-scan-service.js';
3
3
  import { scanUnderstandAnything } from '../understand/understand-scan-service.js';
4
4
  import { seedCapabilityItems } from '../recommendations/capability-seed-items.js';
5
- import { requiredSkillNames } from '../../shared/paths.js';
5
+ import { requiredSkillNames } from 'peaks-loop-shared/paths';
6
6
  import { getSkillPresence } from '../skills/skill-presence-service.js';
7
7
  const SKILL_PRESENCE_FRESHNESS_THRESHOLD_MS = 24 * 60 * 60 * 1000;
8
8
  /**
@@ -45,7 +45,7 @@ async function loadDoctorAndRunbookHealth(doctorOverride, runbookOverride) {
45
45
  runbookHealth: { ok: true, required: 0, healthy: 0, missingRunbook: [], applyNoteFailed: [] }
46
46
  };
47
47
  }
48
- const { runDoctor } = await import('../doctor/doctor-service.js');
48
+ const { runDoctor } = await import('../doctor/index.js');
49
49
  const report = await runDoctor();
50
50
  return {
51
51
  doctor: { ok: report.summary.ok, passed: report.summary.passed, failed: report.summary.failed },
@@ -0,0 +1,70 @@
1
+ export type AwaitBatchOutcome = 'completed' | 'timed-out' | 'clamped' | 'no-progress';
2
+ export interface AwaitBatchOptions {
3
+ /** Caller-supplied per-IDE default when no timeoutMs is provided. */
4
+ readonly defaultTimeoutMs: number;
5
+ /** Hard cap on the effective wait, in ms. Default: 120_000. */
6
+ readonly hardCapMs?: number;
7
+ /** Optional per-IDE label written into result `note` for attribution. */
8
+ readonly notePrefix?: string;
9
+ /**
10
+ * No-progress watchdog. If a slot's progress is unchanged for
11
+ * `noProgressMs`, the batch escalates with outcome `no-progress`
12
+ * (and the slot's status is left as the caller would observe at
13
+ * that moment — typically still `running` or `queued`).
14
+ */
15
+ readonly noProgressMs?: number;
16
+ /**
17
+ * Test seam: override Date.now() and setTimeout's clock. Production
18
+ * callers leave this undefined.
19
+ */
20
+ readonly now?: () => number;
21
+ /**
22
+ * Test seam: override setTimeout / setInterval. Production callers
23
+ * leave this undefined.
24
+ */
25
+ readonly schedule?: (cb: () => void, ms: number) => void;
26
+ /**
27
+ * Test seam: how to read a record's status. Production callers
28
+ * leave this undefined (the default reads `status` from the file).
29
+ * Returning a plain string is treated as the record's status; the
30
+ * default reader also exposes the `outcome` field via the optional
31
+ * second tuple element (see `defaultReadOutcome`).
32
+ *
33
+ * Test-only escape hatch: callers that need to return both status
34
+ * and outcome can implement `readRecord` instead.
35
+ */
36
+ readonly readOutcome?: (recordPath: string) => string | null;
37
+ /**
38
+ * Test seam: read a record's status AND outcome together. When
39
+ * defined, this overrides `readOutcome`. Implementations should
40
+ * return `{ status: null, outcome: null }` when the file is missing
41
+ * or unreadable, and `{ status }` / `{ status, outcome }` otherwise.
42
+ */
43
+ readonly readRecord?: (recordPath: string) => {
44
+ status: string | null;
45
+ outcome: string | null;
46
+ };
47
+ }
48
+ export interface AwaitBatchResult {
49
+ /** Per-dispatch slot, in dispatchIndex order. */
50
+ readonly results: ReadonlyArray<{
51
+ readonly dispatchIndex: number;
52
+ readonly recordPath: string;
53
+ readonly status: 'done' | 'failed' | 'cancelled' | 'timeout';
54
+ readonly durationMs: number;
55
+ readonly note: string | null;
56
+ }>;
57
+ /** Batch-level outcome — distinct, machine-readable. */
58
+ readonly outcome: AwaitBatchOutcome;
59
+ /** What the caller asked for (or the IDE default, when omitted). */
60
+ readonly requestedTimeoutMs: number;
61
+ /** What the loop actually waited (≤ requestedTimeoutMs after clamp). */
62
+ readonly effectiveTimeoutMs: number;
63
+ /** The hard cap applied; equals `requestedTimeoutMs` if no clamp. */
64
+ readonly hardCapMs: number;
65
+ }
66
+ /**
67
+ * Run one awaitBatch. Pure (no module-level state); the two
68
+ * back-compat wrappers in sub-agent-dispatcher.ts call this.
69
+ */
70
+ export declare function awaitBatch(dispatchCount: number, recordPaths: readonly string[], timeoutMs: number | undefined, options?: AwaitBatchOptions): Promise<AwaitBatchResult>;