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
@@ -1,13 +1,175 @@
1
- import { mkdir, rename } from 'node:fs/promises';
2
- import { dirname, join } from 'node:path';
3
- import { isDirectory } from '../../shared/fs.js';
4
- const CHANGE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
1
+ import { mkdir, readFile, rename, readdir } from 'node:fs/promises';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { isDirectory } from 'peaks-loop-shared/fs';
4
+ import { validateChangeId } from './artifact-boundary.js';
5
+ import { findStaleChangeFiles, parseCapabilityMapping, readC8Summary, resolveCoverageSummaryPath, validateCapabilityCoverage, } from './coverage-evidence-reader.js';
6
+ export class OpenSpecArchiveError extends Error {
7
+ code;
8
+ detail;
9
+ constructor(code, message, detail = {}) {
10
+ super(message);
11
+ this.code = code;
12
+ this.detail = detail;
13
+ this.name = 'OpenSpecArchiveError';
14
+ }
15
+ }
5
16
  function defaultOpenSpecRoot() {
6
17
  return join(process.cwd(), 'openspec');
7
18
  }
19
+ /**
20
+ * Parse the `## Coverage Evidence` block out of a proposal.md.
21
+ *
22
+ * Accepted shape (markdown table):
23
+ *
24
+ * ## Coverage Evidence
25
+ *
26
+ * | capability | requirement | status | testAnchor |
27
+ * | --- | --- | --- | --- |
28
+ * | quality-gates | 100% coverage for included modules | covered | tests/unit/quality-gates.test.ts |
29
+ *
30
+ * Returns `{ present: false }` when the heading is missing. Throws
31
+ * `OpenSpecArchiveError` with `code: 'OPENSPEC_COVERAGE_EVIDENCE_MALFORMED'`
32
+ * when the heading is present but no parsable rows are extracted.
33
+ */
34
+ export async function parseCoverageEvidence(proposalPath) {
35
+ let raw;
36
+ try {
37
+ raw = await readFile(proposalPath, 'utf8');
38
+ }
39
+ catch {
40
+ return {
41
+ rows: [],
42
+ present: false,
43
+ capabilityRows: [],
44
+ summaryStatus: 'unavailable',
45
+ capabilityValidation: 'not-enforced',
46
+ staleFiles: [],
47
+ mismatches: [],
48
+ };
49
+ }
50
+ const lines = raw.split(/\r?\n/);
51
+ const headingIdx = lines.findIndex((line) => /^##\s+Coverage\s+Evidence\s*$/.test(line));
52
+ if (headingIdx === -1) {
53
+ return {
54
+ rows: [],
55
+ present: false,
56
+ capabilityRows: [],
57
+ summaryStatus: 'unavailable',
58
+ capabilityValidation: 'not-enforced',
59
+ staleFiles: [],
60
+ mismatches: [],
61
+ };
62
+ }
63
+ const rows = [];
64
+ let i = headingIdx + 1;
65
+ let inFence = false;
66
+ while (i < lines.length) {
67
+ const line = lines[i];
68
+ if (line === undefined)
69
+ break;
70
+ if (!inFence && /^##\s+/.test(line))
71
+ break;
72
+ if (/^```/.test(line.trim())) {
73
+ inFence = !inFence;
74
+ i += 1;
75
+ continue;
76
+ }
77
+ const parsed = parseTableRow(line);
78
+ if (parsed !== null) {
79
+ rows.push({ ...parsed, line: i + 1 });
80
+ }
81
+ i += 1;
82
+ }
83
+ if (rows.length === 0) {
84
+ throw new OpenSpecArchiveError('OPENSPEC_COVERAGE_EVIDENCE_MALFORMED', `proposal.md contains a "## Coverage Evidence" heading but no parsable requirement rows`, { proposalPath });
85
+ }
86
+ return {
87
+ rows,
88
+ present: true,
89
+ capabilityRows: [],
90
+ summaryStatus: 'unavailable',
91
+ capabilityValidation: 'not-enforced',
92
+ staleFiles: [],
93
+ mismatches: [],
94
+ };
95
+ }
96
+ function parseTableRow(line) {
97
+ const trimmed = line.trim();
98
+ if (!trimmed.startsWith('|'))
99
+ return null;
100
+ const cells = trimmed.split('|').slice(1, -1).map((c) => c.trim());
101
+ if (cells.length < 3)
102
+ return null;
103
+ const capability = cells[0];
104
+ const requirement = cells[1];
105
+ const statusRaw = cells[2];
106
+ const testAnchor = cells[3];
107
+ if (capability === undefined || requirement === undefined || statusRaw === undefined)
108
+ return null;
109
+ if (capability.toLowerCase() === 'capability' && requirement.toLowerCase() === 'requirement')
110
+ return null;
111
+ if (/^-+$/.test(capability.replace(/\s+/g, '')))
112
+ return null;
113
+ const status = statusRaw.toLowerCase();
114
+ if (status !== 'covered' && status !== 'partial' && status !== 'uncovered')
115
+ return null;
116
+ const row = {
117
+ capability,
118
+ requirement,
119
+ status: status,
120
+ };
121
+ if (testAnchor !== undefined && testAnchor !== '') {
122
+ row.testAnchor = testAnchor;
123
+ }
124
+ return row;
125
+ }
126
+ /**
127
+ * Determine whether the change has any spec files (specs/<capability>/spec.md).
128
+ * When the change has zero spec files, there are no requirements to enforce,
129
+ * and the Pre-cond 2 gate is skipped — backward-compat for legacy spec-less
130
+ * changes (e.g. design-only or doc-only changes).
131
+ */
132
+ async function changeHasSpecs(changeRoot) {
133
+ const specsRoot = join(changeRoot, 'specs');
134
+ if (!(await isDirectory(specsRoot)))
135
+ return false;
136
+ const entries = await readdir(specsRoot);
137
+ for (const entry of entries) {
138
+ const specPath = join(specsRoot, entry, 'spec.md');
139
+ if (await isDirectory(join(specsRoot, entry))) {
140
+ try {
141
+ await readFile(specPath, 'utf8');
142
+ return true;
143
+ }
144
+ catch {
145
+ // missing spec.md; keep scanning siblings
146
+ }
147
+ }
148
+ }
149
+ return false;
150
+ }
151
+ function evaluateGate(evidence) {
152
+ const failing = evidence.rows.filter((r) => r.status !== 'covered');
153
+ if (failing.length > 0) {
154
+ return {
155
+ ok: false,
156
+ reason: 'requirement-not-fully-covered',
157
+ failing,
158
+ };
159
+ }
160
+ if (evidence.rows.length === 0) {
161
+ return {
162
+ ok: false,
163
+ reason: 'no-coverage-evidence-block',
164
+ failing: [],
165
+ };
166
+ }
167
+ return { ok: true };
168
+ }
8
169
  export async function archiveOpenSpecChange(changeId, options = {}) {
9
- if (!CHANGE_ID_PATTERN.test(changeId)) {
10
- throw new Error(`Invalid changeId: ${changeId} (expected letters, digits, dots, underscores, or dashes)`);
170
+ const changeIdResult = validateChangeId(changeId);
171
+ if (!changeIdResult.ok) {
172
+ throw new Error(`changeId ${changeId} does not match [A-Za-z0-9][A-Za-z0-9._-]*`);
11
173
  }
12
174
  const openspecRoot = options.openspecRoot ?? defaultOpenSpecRoot();
13
175
  const archiveDir = options.archiveDirName ?? 'archive';
@@ -16,13 +178,163 @@ export async function archiveOpenSpecChange(changeId, options = {}) {
16
178
  if (!(await isDirectory(from))) {
17
179
  return null;
18
180
  }
181
+ // Pre-cond 2 (Fix-6A + Fix-6B): Coverage Evidence gate.
182
+ // Only enforce when the change declares at least one spec (otherwise there
183
+ // are no requirements to gate on — backward-compat for design-only changes).
184
+ let coverage;
185
+ let coverageGateBypassed;
186
+ let coverageMismatchBypassed;
187
+ if (options.apply === true && (await changeHasSpecs(from))) {
188
+ const proposalPath = join(from, 'proposal.md');
189
+ // --- Fix-6A: parse Coverage Evidence block (declarative half) ---
190
+ const evidence = await parseCoverageEvidence(proposalPath);
191
+ coverage = evidence;
192
+ if (!evidence.present) {
193
+ throw new OpenSpecArchiveError('OPENSPEC_COVERAGE_GATE_FAILED', `Refusing to archive "${changeId}": proposal.md is missing a "## Coverage Evidence" block. ` +
194
+ 'Add a Coverage Evidence table listing every Requirement from specs/*/spec.md with status covered/partial/uncovered, ' +
195
+ 'or re-run with --force to bypass the gate.', { changeId, reason: 'no-coverage-evidence-block', coverage });
196
+ }
197
+ const verdict = evaluateGate(evidence);
198
+ if (!verdict.ok) {
199
+ if (options.force === true) {
200
+ coverageGateBypassed = true;
201
+ }
202
+ else {
203
+ throw new OpenSpecArchiveError('OPENSPEC_COVERAGE_GATE_PARTIAL', `Refusing to archive "${changeId}": ${verdict.failing.length} requirement(s) not fully covered. ` +
204
+ 'Re-run with --force to bypass the gate, or update the Coverage Evidence table to mark each requirement as covered.', {
205
+ changeId,
206
+ reason: verdict.reason,
207
+ failing: verdict.failing.map((r) => ({
208
+ capability: r.capability,
209
+ requirement: r.requirement,
210
+ status: r.status,
211
+ testAnchor: r.testAnchor,
212
+ line: r.line,
213
+ })),
214
+ coverage,
215
+ });
216
+ }
217
+ }
218
+ // --- Fix-6B: parse Capability Mapping block + validate against c8 summary ---
219
+ const mapping = await parseCapabilityMapping(proposalPath);
220
+ coverage = {
221
+ ...coverage,
222
+ capabilityRows: mapping.rows,
223
+ };
224
+ if (mapping.rows.length === 0) {
225
+ // No mapping → cannot enforce per-capability. Refuse with the same
226
+ // gate-failed code but a distinct reason in detail (Fix-6B AC3).
227
+ throw new OpenSpecArchiveError('OPENSPEC_COVERAGE_GATE_FAILED', `Refusing to archive "${changeId}": proposal.md is missing a "## Capability Mapping" block. ` +
228
+ 'Add a Capability Mapping table listing each declared capability alongside its source file or subtree, ' +
229
+ 'or re-run with --force to bypass the gate.', { changeId, reason: 'no-capability-mapping-block', coverage });
230
+ }
231
+ // Discover coverage-summary.json
232
+ const projectRoot = resolve(openspecRoot, '..');
233
+ const summaryPathResult = await resolveCoverageSummaryPath({
234
+ projectRoot,
235
+ ...(options.coverageSummaryPath !== undefined ? { explicitPath: options.coverageSummaryPath } : {}),
236
+ });
237
+ if (!summaryPathResult.ok) {
238
+ // AC1: missing or not-readable
239
+ const triedPaths = summaryPathResult.error.code === 'missing' ? summaryPathResult.error.triedPaths : [summaryPathResult.error.path];
240
+ throw new OpenSpecArchiveError('OPENSPEC_COVERAGE_EVIDENCE_MISSING', `Refusing to archive "${changeId}": no coverage-summary.json found at any of: ${triedPaths.join(', ')}. ` +
241
+ 'Run `pnpm test:coverage` (which invokes scripts/coverage-c8.mjs) to generate one, ' +
242
+ 'or pass --coverage-summary <path> to point at an existing summary, ' +
243
+ 'or re-run with --force to bypass.', {
244
+ changeId,
245
+ triedPaths,
246
+ coverage,
247
+ });
248
+ }
249
+ // Parse summary + check freshness (AC2)
250
+ let summary;
251
+ try {
252
+ summary = await readC8Summary(summaryPathResult.value);
253
+ }
254
+ catch (error) {
255
+ throw new OpenSpecArchiveError('OPENSPEC_COVERAGE_EVIDENCE_MISSING', `Refusing to archive "${changeId}": coverage-summary.json at ${summaryPathResult.value} is malformed (${error.message}). ` +
256
+ 'Re-run `pnpm test:coverage` to regenerate, or pass --coverage-summary <path> to point at a valid summary.', { changeId, path: summaryPathResult.value, coverage });
257
+ }
258
+ coverage = {
259
+ ...coverage,
260
+ summaryPath: summary.path,
261
+ };
262
+ const staleFiles = await findStaleChangeFiles({
263
+ projectRoot,
264
+ openspecRoot,
265
+ changeId,
266
+ summary,
267
+ });
268
+ if (staleFiles.length > 0) {
269
+ coverage = {
270
+ ...coverage,
271
+ summaryStatus: 'stale',
272
+ staleFiles,
273
+ };
274
+ throw new OpenSpecArchiveError('OPENSPEC_COVERAGE_EVIDENCE_STALE', `Refusing to archive "${changeId}": coverage-summary.json is older than ${staleFiles.length} change file(s). ` +
275
+ 'Re-run `pnpm test:coverage` to refresh, or re-run with --force to bypass.', { changeId, staleFiles, summaryPath: summary.path, coverage });
276
+ }
277
+ coverage = {
278
+ ...coverage,
279
+ summaryStatus: 'fresh',
280
+ };
281
+ // Per-capability coverage check (AC4)
282
+ const validation = await validateCapabilityCoverage({
283
+ projectRoot,
284
+ summary,
285
+ rows: mapping.rows,
286
+ });
287
+ if (!validation.ok) {
288
+ coverage = {
289
+ ...coverage,
290
+ capabilityValidation: 'mismatch',
291
+ mismatches: validation.mismatches,
292
+ };
293
+ if (options.force === true) {
294
+ coverageMismatchBypassed = true;
295
+ }
296
+ else {
297
+ throw new OpenSpecArchiveError('OPENSPEC_COVERAGE_EVIDENCE_MISMATCH', `Refusing to archive "${changeId}": ${validation.mismatches.length} capability row(s) claim "covered" in proposal.md but c8 reports < 100% coverage. ` +
298
+ 'Re-run `pnpm test:coverage` after closing the gap, or re-run with --force to bypass.', {
299
+ changeId,
300
+ mismatches: validation.mismatches,
301
+ coverage,
302
+ });
303
+ }
304
+ }
305
+ else {
306
+ coverage = {
307
+ ...coverage,
308
+ capabilityValidation: 'ok',
309
+ };
310
+ }
311
+ }
312
+ else if (options.apply === true) {
313
+ // Spec-less change — surface coverage evidence for visibility, never fail.
314
+ const proposalPath = join(from, 'proposal.md');
315
+ coverage = await parseCoverageEvidence(proposalPath);
316
+ }
19
317
  if (options.apply !== true) {
20
- return { changeId, from, to, applied: false };
318
+ return {
319
+ changeId,
320
+ from,
321
+ to,
322
+ applied: false,
323
+ ...(coverage !== undefined ? { coverage } : {}),
324
+ };
21
325
  }
22
326
  if (await isDirectory(to)) {
23
327
  throw new Error(`Refusing to archive: target already exists at ${to}`);
24
328
  }
25
329
  await mkdir(dirname(to), { recursive: true });
26
330
  await rename(from, to);
27
- return { changeId, from, to, applied: true };
331
+ return {
332
+ changeId,
333
+ from,
334
+ to,
335
+ applied: true,
336
+ ...(coverage !== undefined ? { coverage } : {}),
337
+ ...(coverageGateBypassed === true ? { coverageGateBypassed: true } : {}),
338
+ ...(coverageMismatchBypassed === true ? { coverageMismatchBypassed: true } : {}),
339
+ };
28
340
  }
@@ -1,4 +1,4 @@
1
- import { readText } from '../../shared/fs.js';
1
+ import { readText } from 'peaks-loop-shared/fs';
2
2
  import { loadOpenSpecChange } from './openspec-scan-service.js';
3
3
  function splitTaskSections(markdown) {
4
4
  const sections = [];
@@ -1,6 +1,6 @@
1
1
  import { mkdir, writeFile } from 'node:fs/promises';
2
2
  import { join } from 'node:path';
3
- import { isDirectory, pathExists } from '../../shared/fs.js';
3
+ import { isDirectory, pathExists } from 'peaks-loop-shared/fs';
4
4
  const README_BODY = `# OpenSpec — change proposals for this project
5
5
 
6
6
  This directory hosts the \`peaks openspec\` change proposal lifecycle:
@@ -12,7 +12,7 @@
12
12
  */
13
13
  import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
14
14
  import { join } from 'node:path';
15
- import { getErrorMessage } from '../../shared/result.js';
15
+ import { getErrorMessage } from 'peaks-loop-shared/result';
16
16
  const SLUGIFY = /[^a-z0-9]+/g;
17
17
  function slugify(text) {
18
18
  return text
@@ -1,9 +1,9 @@
1
1
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
2
  import { dirname, join, resolve } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
- import { isDirectory, pathExists } from '../../shared/fs.js';
4
+ import { isDirectory, pathExists } from 'peaks-loop-shared/fs';
5
5
  import { validateAgainstSchema } from '../../shared/json-schema-mini.js';
6
- const CHANGE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
6
+ import { validateChangeId } from './artifact-boundary.js';
7
7
  function defaultOpenSpecRoot() {
8
8
  return join(process.cwd(), 'openspec');
9
9
  }
@@ -113,8 +113,11 @@ export async function renderOpenSpecChange(request, options = {}) {
113
113
  throw new OpenSpecRenderRequestInvalidError(result.errors);
114
114
  }
115
115
  }
116
- else if (!CHANGE_ID_PATTERN.test(request.changeId)) {
117
- throw new Error(`Invalid changeId: ${request.changeId} (expected letters, digits, dots, underscores, or dashes)`);
116
+ else {
117
+ const changeIdResult = validateChangeId(request.changeId);
118
+ if (!changeIdResult.ok) {
119
+ throw new Error(`changeId ${request.changeId} does not match [A-Za-z0-9][A-Za-z0-9._-]*`);
120
+ }
118
121
  }
119
122
  const openspecRoot = options.openspecRoot ?? defaultOpenSpecRoot();
120
123
  const changeRoot = join(openspecRoot, 'changes', request.changeId);
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
- import { isDirectory, listDirectories, pathExists, readText } from '../../shared/fs.js';
2
+ import { isDirectory, listDirectories, pathExists, readText } from 'peaks-loop-shared/fs';
3
3
  function defaultOpenSpecRoot() {
4
4
  return join(process.cwd(), 'openspec');
5
5
  }
@@ -1,7 +1,7 @@
1
1
  import { join } from 'node:path';
2
- import { isDirectory } from '../../shared/fs.js';
2
+ import { isDirectory } from 'peaks-loop-shared/fs';
3
3
  import { loadOpenSpecChange } from './openspec-scan-service.js';
4
- const CHANGE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
4
+ import { validateChangeId } from './artifact-boundary.js';
5
5
  function defaultOpenSpecRoot() {
6
6
  return join(process.cwd(), 'openspec');
7
7
  }
@@ -10,11 +10,12 @@ async function defaultExternalRunner(_command, _args) {
10
10
  }
11
11
  function buildInternalIssues(changeId, detail) {
12
12
  const issues = [];
13
- if (!CHANGE_ID_PATTERN.test(changeId)) {
13
+ const changeIdResult = validateChangeId(changeId);
14
+ if (!changeIdResult.ok) {
14
15
  issues.push({
15
16
  level: 'error',
16
17
  rule: 'change-id-format',
17
- message: `changeId ${changeId} does not match [A-Za-z0-9][A-Za-z0-9._-]*`
18
+ message: changeIdResult.error.message
18
19
  });
19
20
  }
20
21
  if (detail === null || detail.proposal === null) {
@@ -9,6 +9,16 @@ export function preferencesPath(projectRoot) {
9
9
  export function loadPreferences(projectRoot) {
10
10
  const filePath = preferencesPath(projectRoot);
11
11
  if (!existsSync(filePath)) {
12
+ // Slice 2026-07-22-orchestrator-memory-preflight: when
13
+ // .peaks/preferences.json is missing, this returns a clone of
14
+ // DEFAULT_PREFERENCES, which now carries the `memoryPreflight`
15
+ // block (see preferences-types.ts). Partial overlays fall through
16
+ // to mergePreferences below, where the new `memoryPreflight` block
17
+ // shallow-replaces the default block — `mergePreferences` does not
18
+ // deep-merge `memoryPreflight` (only `fanout` is deep-merged), so a
19
+ // partial overlay will replace the whole block. Resolution still
20
+ // works because `resolveMemoryPreflightConfig` applies field-level
21
+ // defaults over the partial input (see memory-preflight-config.ts).
12
22
  return structuredClone(DEFAULT_PREFERENCES);
13
23
  }
14
24
  let raw;
@@ -131,6 +131,19 @@ export interface ProjectPreferences {
131
131
  * saved file is rejected at load time.
132
132
  */
133
133
  readonly fanout: FanoutPreference;
134
+ /**
135
+ * Slice 2026-07-22-orchestrator-memory-preflight: orchestrator-side memory
136
+ * preflight knobs. Optional — `resolveMemoryPreflightConfig` (see
137
+ * src/services/context/memory-preflight-config.ts) merges over a hard-coded
138
+ * default block when this key is absent, so legacy preferences.json files
139
+ * keep working unchanged.
140
+ */
141
+ readonly memoryPreflight?: {
142
+ readonly enabled?: boolean;
143
+ readonly maxTokens?: number;
144
+ readonly listCap?: number;
145
+ readonly contentCacheBytes?: number;
146
+ };
134
147
  }
135
148
  export type FanoutMode = 'fan-out';
136
149
  export declare const FANOUT_MODES: readonly FanoutMode[];
@@ -50,4 +50,15 @@ export const DEFAULT_PREFERENCES = {
50
50
  fanout: {
51
51
  defaultMode: 'fan-out'
52
52
  },
53
+ // Slice 2026-07-22-orchestrator-memory-preflight: defaults aligned with
54
+ // memory-preflight-config.ts::DEFAULTS. Kept in sync manually because
55
+ // loadPreferences() returns DEFAULT_PREFERENCES verbatim when the on-disk
56
+ // file is absent, and partial overlays rely on memoryPreflight being
57
+ // defined here.
58
+ memoryPreflight: {
59
+ enabled: true,
60
+ maxTokens: 1200,
61
+ listCap: 12,
62
+ contentCacheBytes: 6000,
63
+ },
53
64
  };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * rid-012 (2026-07-27) — screenshot archive service.
3
+ *
4
+ * Purpose: enforce the peaks-qa SKILL.md "Hard contracts for browser
5
+ * validation" Contract 1 — every Playwright screenshot MUST land under
6
+ * `.peaks/_runtime/<sessionId>/qa/screenshots/`, not at the project
7
+ * root. When the LLM forgets to pass `filename` to
8
+ * `browser_take_screenshot`, Playwright MCP writes to the current
9
+ * working directory (typically the project root), which scatters
10
+ * `.png` files at the repo top level. This service is the
11
+ * remediation: scan a directory, move stray screenshot files into
12
+ * the canonical screenshots/ subdir under the active QA scope.
13
+ *
14
+ * CLI surface (peaks qa archive-screenshots):
15
+ * peaks qa archive-screenshots [--source <dir>] [--project <root>]
16
+ *
17
+ * Behavior:
18
+ * - Scan `--source` for *.png / *.jpg / *.jpeg files (case-insensitive
19
+ * extension match). Recurse exactly 1 level deep — the project
20
+ * root plus one subdir (covers `./foo.png` + `./screenshots/*.png`).
21
+ * Avoid recursing into `.peaks/` or `node_modules/` (artifact dirs).
22
+ * - Auto-create `.peaks/_runtime/<session-id>/qa/screenshots/` if
23
+ * missing (mkdirSync recursive, mode 0o755).
24
+ * - For each stray file: `fs.renameSync(src, dst)`. If `dst` exists
25
+ * (filename collision across multiple invocations), suffix with
26
+ * `-<ISO-timestamp>` so the move is non-destructive.
27
+ * - Return JSON envelope with moved list + skipped list + final
28
+ * screenshots/ dir contents.
29
+ */
30
+ export type ScreenshotExtension = '.png' | '.jpg' | '.jpeg';
31
+ export interface ArchiveScreenshotOptions {
32
+ readonly sourceDir: string;
33
+ readonly targetDir: string;
34
+ readonly now?: Date;
35
+ }
36
+ export interface ArchiveScreenshotEnvelope {
37
+ readonly scannedSource: string;
38
+ readonly targetDir: string;
39
+ readonly moved: readonly {
40
+ readonly from: string;
41
+ readonly to: string;
42
+ }[];
43
+ readonly skipped: readonly {
44
+ readonly path: string;
45
+ readonly reason: string;
46
+ }[];
47
+ readonly targetContentsBefore: readonly string[];
48
+ readonly targetContentsAfter: readonly string[];
49
+ readonly archivedAt: string;
50
+ }
51
+ export declare function archiveScreenshots(options: ArchiveScreenshotOptions): ArchiveScreenshotEnvelope;
@@ -0,0 +1,134 @@
1
+ /**
2
+ * rid-012 (2026-07-27) — screenshot archive service.
3
+ *
4
+ * Purpose: enforce the peaks-qa SKILL.md "Hard contracts for browser
5
+ * validation" Contract 1 — every Playwright screenshot MUST land under
6
+ * `.peaks/_runtime/<sessionId>/qa/screenshots/`, not at the project
7
+ * root. When the LLM forgets to pass `filename` to
8
+ * `browser_take_screenshot`, Playwright MCP writes to the current
9
+ * working directory (typically the project root), which scatters
10
+ * `.png` files at the repo top level. This service is the
11
+ * remediation: scan a directory, move stray screenshot files into
12
+ * the canonical screenshots/ subdir under the active QA scope.
13
+ *
14
+ * CLI surface (peaks qa archive-screenshots):
15
+ * peaks qa archive-screenshots [--source <dir>] [--project <root>]
16
+ *
17
+ * Behavior:
18
+ * - Scan `--source` for *.png / *.jpg / *.jpeg files (case-insensitive
19
+ * extension match). Recurse exactly 1 level deep — the project
20
+ * root plus one subdir (covers `./foo.png` + `./screenshots/*.png`).
21
+ * Avoid recursing into `.peaks/` or `node_modules/` (artifact dirs).
22
+ * - Auto-create `.peaks/_runtime/<session-id>/qa/screenshots/` if
23
+ * missing (mkdirSync recursive, mode 0o755).
24
+ * - For each stray file: `fs.renameSync(src, dst)`. If `dst` exists
25
+ * (filename collision across multiple invocations), suffix with
26
+ * `-<ISO-timestamp>` so the move is non-destructive.
27
+ * - Return JSON envelope with moved list + skipped list + final
28
+ * screenshots/ dir contents.
29
+ */
30
+ import { existsSync, mkdirSync, readdirSync, renameSync } from 'node:fs';
31
+ import { join, resolve } from 'node:path';
32
+ const SCREENSHOT_EXTS = new Set(['.png', '.jpg', '.jpeg']);
33
+ function isScreenshotFile(name) {
34
+ const lower = name.toLowerCase();
35
+ for (const ext of SCREENSHOT_EXTS) {
36
+ if (lower.endsWith(ext)) {
37
+ return true;
38
+ }
39
+ }
40
+ return false;
41
+ }
42
+ function listScreenshotFiles(sourceDir, targetDir) {
43
+ // Recurse 1 level deep. Skip .peaks/ + node_modules/ + hidden dirs.
44
+ // Also skip the targetDir itself to avoid re-scanning already-archived files
45
+ // (otherwise the same file would appear twice across calls, and the second
46
+ // call's collision check would treat it as a duplicate).
47
+ const targetBaseName = targetDir.split(/[\\/]/).pop();
48
+ const out = [];
49
+ const top = readdirSync(sourceDir, { withFileTypes: true });
50
+ for (const entry of top) {
51
+ if (entry.name === targetBaseName) {
52
+ continue;
53
+ }
54
+ const full = join(sourceDir, entry.name);
55
+ if (entry.isFile()) {
56
+ if (isScreenshotFile(entry.name)) {
57
+ out.push(full);
58
+ }
59
+ continue;
60
+ }
61
+ if (entry.isDirectory()) {
62
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') {
63
+ continue;
64
+ }
65
+ try {
66
+ const sub = readdirSync(full, { withFileTypes: true });
67
+ for (const subEntry of sub) {
68
+ if (subEntry.isFile() && isScreenshotFile(subEntry.name)) {
69
+ out.push(join(full, subEntry.name));
70
+ }
71
+ }
72
+ }
73
+ catch {
74
+ // unreadable subdir — skip silently
75
+ }
76
+ }
77
+ }
78
+ return out;
79
+ }
80
+ export function archiveScreenshots(options) {
81
+ const sourceDir = resolve(options.sourceDir);
82
+ const targetDir = resolve(options.targetDir);
83
+ const now = options.now ?? new Date();
84
+ if (!existsSync(sourceDir)) {
85
+ return {
86
+ scannedSource: sourceDir,
87
+ targetDir,
88
+ moved: [],
89
+ skipped: [{ path: sourceDir, reason: 'source dir not found' }],
90
+ targetContentsBefore: [],
91
+ targetContentsAfter: [],
92
+ archivedAt: now.toISOString()
93
+ };
94
+ }
95
+ const targetContentsBefore = existsSync(targetDir)
96
+ ? readdirSync(targetDir)
97
+ : [];
98
+ mkdirSync(targetDir, { recursive: true });
99
+ const candidates = listScreenshotFiles(sourceDir, targetDir);
100
+ const moved = [];
101
+ const skipped = [];
102
+ for (const src of candidates) {
103
+ const baseName = src.split(/[\\/]/).pop() ?? 'unknown.png';
104
+ let dst = join(targetDir, baseName);
105
+ if (existsSync(dst)) {
106
+ // collision: suffix with ISO timestamp
107
+ const dot = baseName.lastIndexOf('.');
108
+ const stem = dot > 0 ? baseName.slice(0, dot) : baseName;
109
+ const ext = dot > 0 ? baseName.slice(dot) : '';
110
+ const stamp = now.toISOString().replace(/[:.]/g, '-');
111
+ dst = join(targetDir, `${stem}-${stamp}${ext}`);
112
+ }
113
+ try {
114
+ renameSync(src, dst);
115
+ moved.push({ from: src, to: dst });
116
+ }
117
+ catch (err) {
118
+ skipped.push({
119
+ path: src,
120
+ reason: err instanceof Error ? err.message : 'rename failed'
121
+ });
122
+ }
123
+ }
124
+ const targetContentsAfter = readdirSync(targetDir);
125
+ return {
126
+ scannedSource: sourceDir,
127
+ targetDir,
128
+ moved,
129
+ skipped,
130
+ targetContentsBefore,
131
+ targetContentsAfter,
132
+ archivedAt: now.toISOString()
133
+ };
134
+ }