peaks-loop 4.0.0-beta.9 → 4.0.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 (552) hide show
  1. package/CHANGELOG.md +572 -234
  2. package/README-en.md +67 -30
  3. package/README.md +67 -30
  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 +91 -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,257 @@
1
+ /**
2
+ * `peaks cron` — slice 2026-07-29-worktree-l2-extended Part 14.
3
+ *
4
+ * Persistent scheduled-task system. Stores a JSON schedule at
5
+ * `.peaks/cron/schedule.json` and lets the LLM-side runner
6
+ * trigger tasks synchronously (`peaks cron run <id>`) or
7
+ * register a built-in periodic lease gc that the runbook
8
+ * (`skills/peaks-code/`) checks on every session start.
9
+ *
10
+ * Built-in tasks (the only ones auto-registered today):
11
+ * - `lease-gc-daily` — runs `peaks worktree gc --all-sessions
12
+ * --project .` once every 24h. Cleans up orphan leases that
13
+ * leaked past their auto-release hook (Part 3.A) — the
14
+ * safety net for the safety net.
15
+ *
16
+ * Why a JSON file (not a real cron daemon): peaks-loop is a CLI
17
+ * tool, not a service. The schedule is best-effort: the runbook
18
+ * checks it on session start and surfaces overdue tasks. A
19
+ * proper system cron / systemd timer is the production
20
+ * deployment story; this CLI is the portable fallback.
21
+ *
22
+ * File layout:
23
+ * .peaks/cron/schedule.json — registered tasks with their
24
+ * interval + lastRunAt
25
+ * .peaks/cron/history.jsonl — append-only run history
26
+ */
27
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
28
+ import { join } from 'node:path';
29
+ import { randomUUID } from 'node:crypto';
30
+ import { execSync } from 'node:child_process';
31
+ import { fail, getErrorMessage, ok } from 'peaks-loop-shared/result';
32
+ import { addJsonOption, printResult } from '../cli-helpers.js';
33
+ import { findProjectRoot } from '../../services/config/config-safety.js';
34
+ const SCHEDULE_VERSION = 1;
35
+ const SCHEDULE_FILENAME = 'schedule.json';
36
+ const HISTORY_FILENAME = 'history.jsonl';
37
+ const DEFAULT_INTERVAL_MS = 24 * 60 * 60 * 1_000; // 24h
38
+ function cronDir(projectRoot) {
39
+ return join(projectRoot, '.peaks', 'cron');
40
+ }
41
+ function schedulePath(projectRoot) {
42
+ return join(cronDir(projectRoot), SCHEDULE_FILENAME);
43
+ }
44
+ function historyPath(projectRoot) {
45
+ return join(cronDir(projectRoot), HISTORY_FILENAME);
46
+ }
47
+ export function readSchedule(projectRoot) {
48
+ const path = schedulePath(projectRoot);
49
+ if (!existsSync(path))
50
+ return { version: SCHEDULE_VERSION, entries: [] };
51
+ const raw = readFileSync(path, 'utf8');
52
+ let parsed;
53
+ try {
54
+ parsed = JSON.parse(raw);
55
+ }
56
+ catch (err) {
57
+ throw new Error(`schedule.json malformed: ${err.message}`);
58
+ }
59
+ if (typeof parsed !== 'object' || parsed === null) {
60
+ throw new Error('schedule.json root must be an object');
61
+ }
62
+ const obj = parsed;
63
+ if (obj.version !== SCHEDULE_VERSION) {
64
+ throw new Error(`schedule.json version mismatch (got ${String(obj.version)}, expected ${SCHEDULE_VERSION})`);
65
+ }
66
+ if (!Array.isArray(obj.entries)) {
67
+ throw new Error('schedule.json entries must be an array');
68
+ }
69
+ const entries = [];
70
+ for (const e of obj.entries) {
71
+ if (typeof e !== 'object' || e === null)
72
+ continue;
73
+ const ent = e;
74
+ if (typeof ent.id !== 'string' || typeof ent.name !== 'string' || typeof ent.command !== 'string')
75
+ continue;
76
+ if (!Array.isArray(ent.args) || !ent.args.every((a) => typeof a === 'string'))
77
+ continue;
78
+ if (typeof ent.intervalMs !== 'number' || typeof ent.createdAt !== 'number')
79
+ continue;
80
+ entries.push({
81
+ id: ent.id,
82
+ name: ent.name,
83
+ command: ent.command,
84
+ args: ent.args,
85
+ intervalMs: ent.intervalMs,
86
+ lastRunAt: typeof ent.lastRunAt === 'number' ? ent.lastRunAt : null,
87
+ enabled: ent.enabled !== false,
88
+ createdAt: ent.createdAt
89
+ });
90
+ }
91
+ return { version: SCHEDULE_VERSION, entries };
92
+ }
93
+ function writeSchedule(projectRoot, file) {
94
+ const dir = cronDir(projectRoot);
95
+ if (!existsSync(dir))
96
+ mkdirSync(dir, { recursive: true });
97
+ writeFileSync(schedulePath(projectRoot), `${JSON.stringify(file, null, 2)}\n`, 'utf8');
98
+ }
99
+ export function appendHistory(projectRoot, record) {
100
+ const dir = cronDir(projectRoot);
101
+ if (!existsSync(dir))
102
+ mkdirSync(dir, { recursive: true });
103
+ const path = historyPath(projectRoot);
104
+ const line = `${JSON.stringify(record)}\n`;
105
+ if (!existsSync(path)) {
106
+ writeFileSync(path, line, 'utf8');
107
+ }
108
+ else {
109
+ // Append — small file, OK to read+write
110
+ const existing = readFileSync(path, 'utf8');
111
+ writeFileSync(path, existing + line, 'utf8');
112
+ }
113
+ }
114
+ function ensureLeaseGcEntry(file) {
115
+ if (file.entries.some((e) => e.id === 'lease-gc-daily'))
116
+ return file;
117
+ const entry = {
118
+ id: 'lease-gc-daily',
119
+ name: 'Daily lease listing — refresh the alive-lease set; operators run peaks worktree gc --lease-id <id> manually on stale entries',
120
+ command: 'worktree',
121
+ args: ['list'],
122
+ intervalMs: DEFAULT_INTERVAL_MS,
123
+ lastRunAt: null,
124
+ enabled: true,
125
+ createdAt: Date.now()
126
+ };
127
+ return { version: SCHEDULE_VERSION, entries: [...file.entries, entry] };
128
+ }
129
+ export function runTask(projectRoot, task) {
130
+ const id = randomUUID();
131
+ const startedAt = Date.now();
132
+ let exitCode = 0;
133
+ let stderr = '';
134
+ try {
135
+ execSync(`peaks ${task.command} ${task.args.map((a) => `"${a.replace(/"/g, '\\"')}"`).join(' ')}`, {
136
+ cwd: projectRoot,
137
+ stdio: ['ignore', 'pipe', 'pipe'],
138
+ encoding: 'utf8',
139
+ timeout: 5 * 60_000
140
+ });
141
+ }
142
+ catch (err) {
143
+ const e = err;
144
+ exitCode = typeof e.status === 'number' ? e.status : 1;
145
+ stderr = (e.stderr ?? getErrorMessage(err)).slice(0, 2000);
146
+ }
147
+ const record = {
148
+ id,
149
+ taskId: task.id,
150
+ startedAt,
151
+ finishedAt: Date.now(),
152
+ exitCode,
153
+ stderr
154
+ };
155
+ appendHistory(projectRoot, record);
156
+ return record;
157
+ }
158
+ export function listDueTasks(projectRoot, now = Date.now()) {
159
+ const file = readSchedule(projectRoot);
160
+ return file.entries.filter((e) => {
161
+ if (!e.enabled)
162
+ return false;
163
+ if (e.lastRunAt === null)
164
+ return true;
165
+ return now - e.lastRunAt >= e.intervalMs;
166
+ });
167
+ }
168
+ export function registerCronCommand(program, io) {
169
+ const cmd = program
170
+ .command('cron')
171
+ .description('Persistent scheduled tasks (Part 14; companion to peaks worktree / peaks container).');
172
+ addJsonOption(cmd.command('init')
173
+ .description('Create .peaks/cron/schedule.json with the built-in tasks (currently: lease-gc-daily). Idempotent.')
174
+ .option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => {
175
+ try {
176
+ const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
177
+ const file = readSchedule(projectRoot);
178
+ const updated = ensureLeaseGcEntry(file);
179
+ writeSchedule(projectRoot, updated);
180
+ const added = updated.entries.length - file.entries.length;
181
+ printResult(io, ok('cron.init', { projectRoot, schedulePath: schedulePath(projectRoot), totalEntries: updated.entries.length, added }, [], [
182
+ added > 0
183
+ ? `Added ${added} built-in task(s). Use 'peaks cron list' to inspect.`
184
+ : 'Schedule already contains the built-in tasks; no change made.'
185
+ ]), options.json);
186
+ }
187
+ catch (err) {
188
+ printResult(io, fail('cron.init', 'CRON_INIT_FAILED', getErrorMessage(err), { projectRoot: options.project }, [
189
+ 'Verify the project root is a peaks-loop project (.peaks/ exists).',
190
+ 'Check filesystem permissions.'
191
+ ]), options.json);
192
+ process.exitCode = 1;
193
+ }
194
+ });
195
+ addJsonOption(cmd.command('list')
196
+ .description('List all registered cron tasks + their due status (relative to now).')
197
+ .option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => {
198
+ try {
199
+ const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
200
+ const file = readSchedule(projectRoot);
201
+ const now = Date.now();
202
+ const annotated = file.entries.map((e) => ({
203
+ ...e,
204
+ due: e.enabled && (e.lastRunAt === null || now - e.lastRunAt >= e.intervalMs),
205
+ nextDueAt: e.lastRunAt === null ? now : e.lastRunAt + e.intervalMs
206
+ }));
207
+ annotated.sort((a, b) => a.nextDueAt - b.nextDueAt);
208
+ printResult(io, ok('cron.list', { projectRoot, schedulePath: schedulePath(projectRoot), entries: annotated }, [], [
209
+ `${annotated.length} task(s); ${annotated.filter((e) => e.due).length} due now.`
210
+ ]), options.json);
211
+ }
212
+ catch (err) {
213
+ printResult(io, fail('cron.list', 'CRON_LIST_FAILED', getErrorMessage(err), { projectRoot: options.project }, [
214
+ "If schedule.json is missing, run 'peaks cron init' first."
215
+ ]), options.json);
216
+ process.exitCode = 1;
217
+ }
218
+ });
219
+ addJsonOption(cmd.command('run')
220
+ .description('Run the specified task (by id) immediately, update lastRunAt, append a history record.')
221
+ .option('--id <taskId>', 'task id to run (default: all due tasks)')
222
+ .option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => {
223
+ try {
224
+ const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
225
+ const file = readSchedule(projectRoot);
226
+ const targets = options.id
227
+ ? file.entries.filter((e) => e.id === options.id)
228
+ : listDueTasks(projectRoot);
229
+ if (targets.length === 0) {
230
+ printResult(io, ok('cron.run', { projectRoot, ran: 0, records: [] }, [], ['No due tasks; nothing to run.']), options.json);
231
+ return;
232
+ }
233
+ const records = [];
234
+ const updatedEntries = [];
235
+ const now = Date.now();
236
+ for (const task of file.entries) {
237
+ if (!targets.some((t) => t.id === task.id)) {
238
+ updatedEntries.push(task);
239
+ continue;
240
+ }
241
+ const record = runTask(projectRoot, task);
242
+ records.push(record);
243
+ updatedEntries.push({ ...task, lastRunAt: record.finishedAt });
244
+ }
245
+ writeSchedule(projectRoot, { version: SCHEDULE_VERSION, entries: updatedEntries });
246
+ printResult(io, ok('cron.run', { projectRoot, ran: records.length, records }, records.filter((r) => r.exitCode !== 0).map((r) => `Task ${r.taskId} failed (exit=${r.exitCode}): ${r.stderr.slice(0, 200)}`), [`Ran ${records.length} task(s); ${records.filter((r) => r.exitCode === 0).length} succeeded.`]), options.json);
247
+ if (records.some((r) => r.exitCode !== 0))
248
+ process.exitCode = 1;
249
+ }
250
+ catch (err) {
251
+ printResult(io, fail('cron.run', 'CRON_RUN_FAILED', getErrorMessage(err), { projectRoot: options.project }, [
252
+ "If schedule.json is missing, run 'peaks cron init' first."
253
+ ]), options.json);
254
+ process.exitCode = 1;
255
+ }
256
+ });
257
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * `peaks cron scheduler start|stop|status|run-once` — slice 2026-07-29 Part 15.
3
+ *
4
+ * Companion CLI to Part 14 (peaks cron init/list/run). The
5
+ * scheduler is a long-running background daemon that wakes up
6
+ * once per minute, reads `.peaks/cron/schedule.json`, and runs
7
+ * any due tasks via detached execSync (so a misbehaving task
8
+ * cannot block the scheduler). Best-effort persistence via
9
+ * `.peaks/cron/scheduler.pid` (advisory — operators can `kill
10
+ * $(cat scheduler.pid)` if a stale entry lingers).
11
+ *
12
+ * Why a separate `peaks-cron-scheduler` CLI (not a peaks
13
+ * subcommand) — long-running daemons that are spawned from a
14
+ * `peaks ...` invocation confuse a future "which peaks version
15
+ * is running" check. A dedicated binary name keeps the
16
+ * scheduler's startup visible to operators.
17
+ *
18
+ * Windows: the scheduler writes its pid to a file. To run as
19
+ * a real Windows service, the operator wires NSSM (or
20
+ * node-windows) to call `peaks-cron-scheduler start` on
21
+ * service start. Future slice: ship an NSSM install recipe
22
+ * in the operator docs.
23
+ *
24
+ * POSIX: same pid-file pattern; an init.d / systemd unit
25
+ * file would call `peaks-cron-scheduler start` and rely on
26
+ * the scheduler to write its own pid. Or just run from
27
+ * `nohup peaks-cron-scheduler start &` if you don't need
28
+ * restart-on-crash.
29
+ */
30
+ import type { Command } from 'commander';
31
+ import { type ProgramIO } from '../cli-helpers.js';
32
+ export declare function registerCronSchedulerCommand(program: Command, io: ProgramIO): void;
33
+ /**
34
+ * Standalone scheduler entry point (the process the CLI spawns).
35
+ * Runs a setInterval tick + reads schedule + runs due tasks.
36
+ * Exits cleanly on SIGTERM.
37
+ *
38
+ * Exported as `runSchedulerLoop` so the dedicated
39
+ * `peaks-cron-scheduler.js` entry shim can call it; the
40
+ * command-side `registerCronSchedulerCommand` only uses
41
+ * start/stop/status, not the loop.
42
+ */
43
+ export declare function runSchedulerLoop(args: {
44
+ projectRoot: string;
45
+ tickMs?: number;
46
+ signal?: AbortSignal;
47
+ }): Promise<void>;
@@ -0,0 +1,284 @@
1
+ /**
2
+ * `peaks cron scheduler start|stop|status|run-once` — slice 2026-07-29 Part 15.
3
+ *
4
+ * Companion CLI to Part 14 (peaks cron init/list/run). The
5
+ * scheduler is a long-running background daemon that wakes up
6
+ * once per minute, reads `.peaks/cron/schedule.json`, and runs
7
+ * any due tasks via detached execSync (so a misbehaving task
8
+ * cannot block the scheduler). Best-effort persistence via
9
+ * `.peaks/cron/scheduler.pid` (advisory — operators can `kill
10
+ * $(cat scheduler.pid)` if a stale entry lingers).
11
+ *
12
+ * Why a separate `peaks-cron-scheduler` CLI (not a peaks
13
+ * subcommand) — long-running daemons that are spawned from a
14
+ * `peaks ...` invocation confuse a future "which peaks version
15
+ * is running" check. A dedicated binary name keeps the
16
+ * scheduler's startup visible to operators.
17
+ *
18
+ * Windows: the scheduler writes its pid to a file. To run as
19
+ * a real Windows service, the operator wires NSSM (or
20
+ * node-windows) to call `peaks-cron-scheduler start` on
21
+ * service start. Future slice: ship an NSSM install recipe
22
+ * in the operator docs.
23
+ *
24
+ * POSIX: same pid-file pattern; an init.d / systemd unit
25
+ * file would call `peaks-cron-scheduler start` and rely on
26
+ * the scheduler to write its own pid. Or just run from
27
+ * `nohup peaks-cron-scheduler start &` if you don't need
28
+ * restart-on-crash.
29
+ */
30
+ import { spawn } from 'node:child_process';
31
+ import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';
32
+ import { dirname, join, resolve } from 'node:path';
33
+ import { fileURLToPath } from 'node:url';
34
+ import { fail, getErrorMessage, ok } from 'peaks-loop-shared/result';
35
+ import { addJsonOption, printResult } from '../cli-helpers.js';
36
+ import { findProjectRoot } from '../../services/config/config-safety.js';
37
+ import { readSchedule, listDueTasks, runTask } from './cron-commands.js';
38
+ const SCHEDULER_TICK_MS = 60_000; // 1 minute
39
+ const PID_FILENAME = 'scheduler.pid';
40
+ function schedulerPidPath(projectRoot) {
41
+ return join(projectRoot, '.peaks', 'cron', PID_FILENAME);
42
+ }
43
+ function readSchedulerPid(projectRoot) {
44
+ const p = schedulerPidPath(projectRoot);
45
+ if (!existsSync(p))
46
+ return null;
47
+ const raw = readFileSync(p, 'utf8').trim();
48
+ const pid = Number.parseInt(raw, 10);
49
+ if (!Number.isFinite(pid) || pid <= 0)
50
+ return null;
51
+ return pid;
52
+ }
53
+ function isPidAlive(pid) {
54
+ try {
55
+ // `process.kill(pid, 0)` does not actually kill; it just
56
+ // checks if the process exists. ESRCH means no such pid;
57
+ // EPERM means it exists but we don't have permission to
58
+ // signal it (still alive).
59
+ process.kill(pid, 0);
60
+ return true;
61
+ }
62
+ catch (err) {
63
+ const code = err.code;
64
+ return code === 'EPERM';
65
+ }
66
+ }
67
+ function findSchedulerEntryPoint() {
68
+ // The peaks-cron-scheduler.js entry shim lives in bin/ (not
69
+ // dist/, so the pnpm build does not overwrite it). It forwards
70
+ // to dist/cli/commands/cron-scheduler-commands.js with
71
+ // PEAKS_CRON_SCHEDULER_DAEMON=1 set; the CLI detects the env
72
+ // and runs runSchedulerLoop directly.
73
+ const here = dirname(fileURLToPath(import.meta.url));
74
+ // dist/cli/commands/cron-scheduler-commands.js → bin/peaks-cron-scheduler.js
75
+ return resolve(here, '..', '..', '..', 'bin', 'peaks-cron-scheduler.js');
76
+ }
77
+ export function registerCronSchedulerCommand(program, io) {
78
+ const cmd = program
79
+ .command('cron-scheduler')
80
+ .description('Long-running background scheduler for peaks cron tasks (Part 15).');
81
+ addJsonOption(cmd.command('start')
82
+ .description('Spawn the scheduler as a detached background process. Idempotent: refuses to start when an alive pid already exists.')
83
+ .option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => {
84
+ try {
85
+ const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
86
+ const pidFile = schedulerPidPath(projectRoot);
87
+ const existing = readSchedulerPid(projectRoot);
88
+ if (existing !== null && isPidAlive(existing)) {
89
+ printResult(io, ok('cron-scheduler.start', { projectRoot, started: false, alreadyRunning: true, existingPid: existing }, [], [
90
+ `Scheduler already running at pid ${existing}; not starting a second one.`,
91
+ 'Use `peaks cron-scheduler stop` first if you need to restart.'
92
+ ]), options.json);
93
+ return;
94
+ }
95
+ // Spawn detached via `peaks-cron-scheduler.js` — the
96
+ // child runs `runSchedulerLoop` (60s setInterval + due-task
97
+ // runner). The detached flag + stdio:ignore puts the
98
+ // scheduler in its own process group (POSIX) / detaches
99
+ // from the console (Windows). PEAKS_CRON_SCHEDULER_DAEMON
100
+ // env is the canonical "I'm the long-running child" signal.
101
+ const entry = findSchedulerEntryPoint();
102
+ const child = spawn(process.execPath, [entry, '--project', projectRoot], {
103
+ cwd: projectRoot,
104
+ stdio: 'ignore',
105
+ detached: true,
106
+ windowsHide: true,
107
+ env: { ...process.env, PEAKS_CRON_SCHEDULER: '1', PEAKS_CRON_SCHEDULER_DAEMON: '1' }
108
+ });
109
+ child.unref();
110
+ if (typeof child.pid !== 'number') {
111
+ throw new Error('spawn returned no pid');
112
+ }
113
+ writeFileSync(pidFile, String(child.pid), 'utf8');
114
+ printResult(io, ok('cron-scheduler.start', { projectRoot, started: true, pid: child.pid, pidFile }, [], [
115
+ `Scheduler started at pid ${child.pid}; logs go to .peaks/cron/scheduler.log.`,
116
+ 'Use `peaks cron-scheduler status` to confirm it is alive; `stop` to terminate.'
117
+ ]), options.json);
118
+ }
119
+ catch (err) {
120
+ printResult(io, fail('cron-scheduler.start', 'SCHEDULER_START_FAILED', getErrorMessage(err), { projectRoot: options.project }, [
121
+ 'Verify the peaks-cron-scheduler.js entry point is on disk.',
122
+ 'Check that the .peaks/cron/ directory is writable.'
123
+ ]), options.json);
124
+ process.exitCode = 1;
125
+ }
126
+ });
127
+ addJsonOption(cmd.command('stop')
128
+ .description('Send SIGTERM to the scheduler pid (best-effort; removes the pid file either way).')
129
+ .option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => {
130
+ try {
131
+ const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
132
+ const pid = readSchedulerPid(projectRoot);
133
+ if (pid === null) {
134
+ printResult(io, ok('cron-scheduler.stop', { projectRoot, stopped: false, reason: 'no-pid-file' }, [], ['No scheduler pid file found; nothing to stop.']), options.json);
135
+ return;
136
+ }
137
+ let signalSent = false;
138
+ if (isPidAlive(pid)) {
139
+ try {
140
+ process.kill(pid, 'SIGTERM');
141
+ signalSent = true;
142
+ }
143
+ catch {
144
+ signalSent = false;
145
+ }
146
+ }
147
+ const pidFile = schedulerPidPath(projectRoot);
148
+ try {
149
+ unlinkSync(pidFile);
150
+ }
151
+ catch { /* best-effort */ }
152
+ printResult(io, ok('cron-scheduler.stop', { projectRoot, stopped: signalSent, pid, pidFile }, [], [
153
+ signalSent
154
+ ? `Sent SIGTERM to pid ${pid}; pid file removed.`
155
+ : `pid ${pid} was not alive; pid file removed.`
156
+ ]), options.json);
157
+ }
158
+ catch (err) {
159
+ printResult(io, fail('cron-scheduler.stop', 'SCHEDULER_STOP_FAILED', getErrorMessage(err), { projectRoot: options.project }, [
160
+ 'Verify the pid file is readable / the process is yours.'
161
+ ]), options.json);
162
+ process.exitCode = 1;
163
+ }
164
+ });
165
+ addJsonOption(cmd.command('status')
166
+ .description('Report whether the scheduler is alive + when it last ran a task.')
167
+ .option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => {
168
+ try {
169
+ const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
170
+ const pid = readSchedulerPid(projectRoot);
171
+ const alive = pid !== null && isPidAlive(pid);
172
+ let schedule;
173
+ try {
174
+ schedule = readSchedule(projectRoot);
175
+ }
176
+ catch (err) {
177
+ schedule = { version: 1, entries: [] };
178
+ }
179
+ const due = alive ? listDueTasks(projectRoot) : [];
180
+ printResult(io, ok('cron-scheduler.status', { projectRoot, pid, alive, scheduleEntries: schedule.entries.length, dueTaskCount: due.length }, [], [alive
181
+ ? `Scheduler alive at pid ${pid}; ${due.length} task(s) due now.`
182
+ : 'Scheduler is NOT running. Use `peaks cron-scheduler start` to spawn.']), options.json);
183
+ }
184
+ catch (err) {
185
+ printResult(io, fail('cron-scheduler.status', 'SCHEDULER_STATUS_FAILED', getErrorMessage(err), { projectRoot: options.project }, [
186
+ 'Verify the .peaks/cron/ directory exists.'
187
+ ]), options.json);
188
+ process.exitCode = 1;
189
+ }
190
+ });
191
+ addJsonOption(cmd.command('run-once')
192
+ .description('Synchronous foreground one-shot: run every currently-due task and exit. Useful for manual cron substitute.')
193
+ .option('--project <path>', 'project root (default: findProjectRoot(cwd))')).action((options) => {
194
+ try {
195
+ const projectRoot = options.project ?? findProjectRoot(process.cwd()) ?? process.cwd();
196
+ const due = listDueTasks(projectRoot);
197
+ const records = due.map((t) => runTask(projectRoot, t));
198
+ printResult(io, ok('cron-scheduler.run-once', { projectRoot, ran: records.length, records }, [], [
199
+ `${records.length} due task(s) ran; ${records.filter((r) => r.exitCode === 0).length} succeeded.`
200
+ ]), options.json);
201
+ if (records.some((r) => r.exitCode !== 0))
202
+ process.exitCode = 1;
203
+ }
204
+ catch (err) {
205
+ printResult(io, fail('cron-scheduler.run-once', 'SCHEDULER_RUN_ONCE_FAILED', getErrorMessage(err), { projectRoot: options.project }, [
206
+ "If schedule.json is missing, run 'peaks cron init' first."
207
+ ]), options.json);
208
+ process.exitCode = 1;
209
+ }
210
+ });
211
+ }
212
+ /**
213
+ * Standalone scheduler entry point (the process the CLI spawns).
214
+ * Runs a setInterval tick + reads schedule + runs due tasks.
215
+ * Exits cleanly on SIGTERM.
216
+ *
217
+ * Exported as `runSchedulerLoop` so the dedicated
218
+ * `peaks-cron-scheduler.js` entry shim can call it; the
219
+ * command-side `registerCronSchedulerCommand` only uses
220
+ * start/stop/status, not the loop.
221
+ */
222
+ export async function runSchedulerLoop(args) {
223
+ const tickMs = args.tickMs ?? SCHEDULER_TICK_MS;
224
+ // Idempotency: refuse to start a second loop in the same
225
+ // process (the start CLI is expected to be a fresh spawn).
226
+ if (process.__peaksCronScheduler) {
227
+ throw new Error('scheduler loop already running in this process');
228
+ }
229
+ process.__peaksCronScheduler = true;
230
+ const tick = () => {
231
+ try {
232
+ const due = listDueTasks(args.projectRoot);
233
+ for (const task of due) {
234
+ runTask(args.projectRoot, task);
235
+ }
236
+ }
237
+ catch (err) {
238
+ process.stderr.write(`[cron-scheduler] tick error: ${getErrorMessage(err)}\n`);
239
+ }
240
+ };
241
+ // First tick on entry (don't wait the full interval
242
+ // for the first run after a start).
243
+ tick();
244
+ const handle = setInterval(tick, tickMs);
245
+ // Wait for the abort signal (POSIX) or the platform
246
+ // equivalent. We don't use Node's process.on('SIGTERM')
247
+ // for portability — the parent process kills us via
248
+ // `process.kill(pid, 'SIGTERM')` and the event loop
249
+ // exits naturally if the interval is the only thing
250
+ // keeping the loop alive. We clearInterval on exit.
251
+ await new Promise((resolve) => {
252
+ const onAbort = () => {
253
+ clearInterval(handle);
254
+ resolve();
255
+ };
256
+ if (args.signal) {
257
+ args.signal.addEventListener('abort', onAbort, { once: true });
258
+ }
259
+ else {
260
+ // POSIX: SIGTERM. Windows: kill the process directly.
261
+ process.on('SIGTERM', onAbort);
262
+ process.on('SIGINT', onAbort);
263
+ }
264
+ });
265
+ process.exit(0);
266
+ }
267
+ // Standalone entry shim. When this file is run directly via
268
+ // `node peaks-cron-scheduler.js`, the loop starts; when it is
269
+ // imported (e.g. by the CLI), the export is used but the
270
+ // loop is not started.
271
+ if (process.env.PEAKS_CRON_SCHEDULER_DAEMON === '1') {
272
+ // Spawned by `peaks cron-scheduler start` as the long-running
273
+ // detached child. Run the loop until SIGTERM. Gated on the
274
+ // env var (not argv[1]) because on Windows a forked node
275
+ // process inherits the parent's argv[1] (which is bin/peaks.js).
276
+ const projectRoot = (() => {
277
+ const idx = process.argv.indexOf('--project');
278
+ return idx >= 0 ? process.argv[idx + 1] : findProjectRoot(process.cwd()) ?? process.cwd();
279
+ })();
280
+ runSchedulerLoop({ projectRoot }).catch((err) => {
281
+ process.stderr.write(`[cron-scheduler] fatal: ${getErrorMessage(err)}\n`);
282
+ process.exit(1);
283
+ });
284
+ }
@@ -0,0 +1,4 @@
1
+ import type { Command } from 'commander';
2
+ import type { ProgramIO } from '../cli-helpers.js';
3
+ /** Registers the top-level `peaks dashboard` command tree. */
4
+ export declare function registerDashboardCommands(program: Command, io: ProgramIO): void;
@@ -0,0 +1,10 @@
1
+ import { registerDashboardLongRunCommand } from './dashboard-long-run.js';
2
+ import { registerDashboardSummaryCommand } from './dashboard-summary.js';
3
+ /** Registers the top-level `peaks dashboard` command tree. */
4
+ export function registerDashboardCommands(program, io) {
5
+ const dashboard = program
6
+ .command('dashboard')
7
+ .description('peaks dashboard surface (24h long-run view etc.)');
8
+ registerDashboardLongRunCommand(dashboard, io);
9
+ registerDashboardSummaryCommand(dashboard, io);
10
+ }
@@ -0,0 +1,25 @@
1
+ import type { Command } from 'commander';
2
+ import { type ProgramIO } from '../cli-helpers.js';
3
+ type ParseResult = {
4
+ ok: true;
5
+ ms: number;
6
+ } | {
7
+ ok: false;
8
+ error: string;
9
+ };
10
+ declare function parseSince(raw: string | undefined): ParseResult;
11
+ type Boundary = {
12
+ key: 'empty' | 'cap' | 'valid';
13
+ message: string;
14
+ };
15
+ declare function boundaryLabel(raw: string): Boundary;
16
+ export declare function registerDashboardLongRunCommand(dashboard: Command, io: ProgramIO): void;
17
+ export declare const DASHBOARD_LONG_RUN_CONSTANTS: {
18
+ readonly WINDOW_CAP_HOURS: 24;
19
+ readonly WINDOW_CAP_MS: number;
20
+ };
21
+ export declare const __test__: {
22
+ parseSince: typeof parseSince;
23
+ boundaryLabel: typeof boundaryLabel;
24
+ };
25
+ export {};