peaks-loop 4.1.3 → 4.1.4

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 (402) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +56 -0
  3. package/README-en.md +1 -1
  4. package/README.md +1 -1
  5. package/dist/cli/commands/asset-command-shared.d.ts +12 -0
  6. package/dist/cli/commands/asset-command-shared.js +45 -0
  7. package/dist/cli/commands/asset-commands.d.ts +6 -1
  8. package/dist/cli/commands/asset-commands.js +11 -372
  9. package/dist/cli/commands/asset-crystallize-command.d.ts +3 -0
  10. package/dist/cli/commands/asset-crystallize-command.js +60 -0
  11. package/dist/cli/commands/asset-crystallize-payload.d.ts +47 -0
  12. package/dist/cli/commands/asset-crystallize-payload.js +85 -0
  13. package/dist/cli/commands/asset-crystallize-runner.d.ts +3 -0
  14. package/dist/cli/commands/asset-crystallize-runner.js +133 -0
  15. package/dist/cli/commands/asset-dispose-command.d.ts +3 -0
  16. package/dist/cli/commands/asset-dispose-command.js +99 -0
  17. package/dist/cli/commands/asset-status-command.d.ts +3 -0
  18. package/dist/cli/commands/asset-status-command.js +100 -0
  19. package/dist/cli/commands/baseline-audit-command.d.ts +3 -0
  20. package/dist/cli/commands/baseline-audit-command.js +64 -0
  21. package/dist/cli/commands/baseline-command-shared.d.ts +23 -0
  22. package/dist/cli/commands/baseline-command-shared.js +39 -0
  23. package/dist/cli/commands/baseline-commands.js +33 -313
  24. package/dist/cli/commands/baseline-freeze-commands.d.ts +4 -0
  25. package/dist/cli/commands/baseline-freeze-commands.js +81 -0
  26. package/dist/cli/commands/baseline-guard-command.d.ts +3 -0
  27. package/dist/cli/commands/baseline-guard-command.js +52 -0
  28. package/dist/cli/commands/baseline-read-commands.d.ts +5 -0
  29. package/dist/cli/commands/baseline-read-commands.js +72 -0
  30. package/dist/cli/commands/baseline-rollback-commands.d.ts +4 -0
  31. package/dist/cli/commands/baseline-rollback-commands.js +88 -0
  32. package/dist/cli/commands/classify-downgrade-command.d.ts +9 -0
  33. package/dist/cli/commands/classify-downgrade-command.js +21 -0
  34. package/dist/cli/commands/classify-run-command.d.ts +9 -0
  35. package/dist/cli/commands/classify-run-command.js +73 -0
  36. package/dist/cli/commands/classify-signals.d.ts +5 -0
  37. package/dist/cli/commands/classify-signals.js +104 -0
  38. package/dist/cli/commands/code-emit-handoff-command.js +40 -3
  39. package/dist/cli/commands/code-gate-step-08-command.js +25 -9
  40. package/dist/cli/commands/codegraph-command-options.d.ts +22 -0
  41. package/dist/cli/commands/codegraph-command-options.js +22 -0
  42. package/dist/cli/commands/codegraph-commands.d.ts +2 -2
  43. package/dist/cli/commands/codegraph-commands.js +14 -397
  44. package/dist/cli/commands/codegraph-config-restore-command.d.ts +3 -0
  45. package/dist/cli/commands/codegraph-config-restore-command.js +200 -0
  46. package/dist/cli/commands/codegraph-proxy-commands.d.ts +10 -0
  47. package/dist/cli/commands/codegraph-proxy-commands.js +159 -0
  48. package/dist/cli/commands/codegraph-repair-commands.d.ts +3 -0
  49. package/dist/cli/commands/codegraph-repair-commands.js +94 -0
  50. package/dist/cli/commands/codegraph-status-command.d.ts +1 -1
  51. package/dist/cli/commands/codegraph-status-command.js +27 -214
  52. package/dist/cli/commands/codegraph-status-integrity.d.ts +44 -0
  53. package/dist/cli/commands/codegraph-status-integrity.js +121 -0
  54. package/dist/cli/commands/codegraph-status-json.d.ts +5 -0
  55. package/dist/cli/commands/codegraph-status-json.js +127 -0
  56. package/dist/cli/commands/container-command-shared.d.ts +60 -0
  57. package/dist/cli/commands/container-command-shared.js +52 -0
  58. package/dist/cli/commands/container-commands.d.ts +1 -1
  59. package/dist/cli/commands/container-commands.js +4 -216
  60. package/dist/cli/commands/container-release-command.d.ts +3 -0
  61. package/dist/cli/commands/container-release-command.js +105 -0
  62. package/dist/cli/commands/container-spawn-command.d.ts +3 -0
  63. package/dist/cli/commands/container-spawn-command.js +148 -0
  64. package/dist/cli/commands/context-check-command.d.ts +3 -0
  65. package/dist/cli/commands/context-check-command.js +81 -0
  66. package/dist/cli/commands/context-commands.d.ts +2 -7
  67. package/dist/cli/commands/context-commands.js +6 -276
  68. package/dist/cli/commands/context-layer-command.d.ts +3 -0
  69. package/dist/cli/commands/context-layer-command.js +34 -0
  70. package/dist/cli/commands/context-layer-fetchers.d.ts +15 -0
  71. package/dist/cli/commands/context-layer-fetchers.js +162 -0
  72. package/dist/cli/commands/context-status-command.d.ts +17 -0
  73. package/dist/cli/commands/context-status-command.js +41 -0
  74. package/dist/cli/commands/contract-write-command.d.ts +3 -0
  75. package/dist/cli/commands/contract-write-command.js +144 -0
  76. package/dist/cli/commands/core/doctor-bindings.d.ts +17 -0
  77. package/dist/cli/commands/core/doctor-bindings.js +30 -0
  78. package/dist/cli/commands/core/doctor-command.d.ts +4 -18
  79. package/dist/cli/commands/core/doctor-command.js +2 -323
  80. package/dist/cli/commands/core/doctor-logs.d.ts +8 -0
  81. package/dist/cli/commands/core/doctor-logs.js +32 -0
  82. package/dist/cli/commands/core/doctor-probes.d.ts +3 -0
  83. package/dist/cli/commands/core/doctor-probes.js +55 -0
  84. package/dist/cli/commands/core/doctor-run-command.d.ts +12 -0
  85. package/dist/cli/commands/core/doctor-run-command.js +172 -0
  86. package/dist/cli/commands/core/doctor-summary.d.ts +7 -0
  87. package/dist/cli/commands/core/doctor-summary.js +39 -0
  88. package/dist/cli/commands/core/memory-command-shared.d.ts +25 -0
  89. package/dist/cli/commands/core/memory-command-shared.js +20 -0
  90. package/dist/cli/commands/core/memory-command.d.ts +1 -1
  91. package/dist/cli/commands/core/memory-command.js +6 -227
  92. package/dist/cli/commands/core/memory-delegated-verbs.d.ts +4 -0
  93. package/dist/cli/commands/core/memory-delegated-verbs.js +178 -0
  94. package/dist/cli/commands/core/memory-extract-command.d.ts +3 -0
  95. package/dist/cli/commands/core/memory-extract-command.js +90 -0
  96. package/dist/cli/commands/core/memory-sync-command.d.ts +3 -0
  97. package/dist/cli/commands/core/memory-sync-command.js +38 -0
  98. package/dist/cli/commands/core/session-command.d.ts +1 -1
  99. package/dist/cli/commands/core/session-command.js +12 -206
  100. package/dist/cli/commands/core/session-info-command.d.ts +3 -0
  101. package/dist/cli/commands/core/session-info-command.js +142 -0
  102. package/dist/cli/commands/core/session-verb-commands.d.ts +5 -0
  103. package/dist/cli/commands/core/session-verb-commands.js +58 -0
  104. package/dist/cli/commands/core/standards-command.d.ts +1 -24
  105. package/dist/cli/commands/core/standards-command.js +33 -201
  106. package/dist/cli/commands/core/standards-init-command.d.ts +3 -0
  107. package/dist/cli/commands/core/standards-init-command.js +87 -0
  108. package/dist/cli/commands/core/standards-lint.d.ts +24 -0
  109. package/dist/cli/commands/core/standards-lint.js +57 -0
  110. package/dist/cli/commands/core/standards-migrate-command.d.ts +3 -0
  111. package/dist/cli/commands/core/standards-migrate-command.js +57 -0
  112. package/dist/cli/commands/cron-scheduler-commands.d.ts +5 -1
  113. package/dist/cli/commands/cron-scheduler-commands.js +36 -206
  114. package/dist/cli/commands/cron-scheduler-run-once-command.d.ts +7 -0
  115. package/dist/cli/commands/cron-scheduler-run-once-command.js +35 -0
  116. package/dist/cli/commands/cron-scheduler-shared.d.ts +6 -0
  117. package/dist/cli/commands/cron-scheduler-shared.js +48 -0
  118. package/dist/cli/commands/cron-scheduler-start-command.d.ts +7 -0
  119. package/dist/cli/commands/cron-scheduler-start-command.js +65 -0
  120. package/dist/cli/commands/cron-scheduler-status-command.d.ts +7 -0
  121. package/dist/cli/commands/cron-scheduler-status-command.js +46 -0
  122. package/dist/cli/commands/cron-scheduler-stop-command.d.ts +7 -0
  123. package/dist/cli/commands/cron-scheduler-stop-command.js +61 -0
  124. package/dist/cli/commands/dispatch-dag-envelope.d.ts +41 -0
  125. package/dist/cli/commands/dispatch-dag-envelope.js +49 -0
  126. package/dist/cli/commands/dispatch-dag-failure.d.ts +18 -0
  127. package/dist/cli/commands/dispatch-dag-failure.js +16 -0
  128. package/dist/cli/commands/dispatch-dag-preflight.d.ts +51 -0
  129. package/dist/cli/commands/dispatch-dag-preflight.js +105 -0
  130. package/dist/cli/commands/dispatch-dag-runners.d.ts +48 -0
  131. package/dist/cli/commands/dispatch-dag-runners.js +73 -0
  132. package/dist/cli/commands/dispatch-from-dag.d.ts +27 -0
  133. package/dist/cli/commands/dispatch-from-dag.js +87 -257
  134. package/dist/cli/commands/final-review-command-envelopes.d.ts +44 -0
  135. package/dist/cli/commands/final-review-command-envelopes.js +100 -0
  136. package/dist/cli/commands/final-review-command-shared.d.ts +52 -0
  137. package/dist/cli/commands/final-review-command-shared.js +35 -0
  138. package/dist/cli/commands/final-review-commands.d.ts +7 -27
  139. package/dist/cli/commands/final-review-commands.js +13 -240
  140. package/dist/cli/commands/final-review-prepare-command.d.ts +3 -0
  141. package/dist/cli/commands/final-review-prepare-command.js +200 -0
  142. package/dist/cli/commands/governance-classify-contract-commands.d.ts +23 -9
  143. package/dist/cli/commands/governance-classify-contract-commands.js +26 -269
  144. package/dist/cli/commands/hooks-command-shared.d.ts +42 -0
  145. package/dist/cli/commands/hooks-command-shared.js +32 -0
  146. package/dist/cli/commands/hooks-commands.d.ts +20 -0
  147. package/dist/cli/commands/hooks-commands.js +75 -309
  148. package/dist/cli/commands/hooks-install-envelopes.d.ts +6 -0
  149. package/dist/cli/commands/hooks-install-envelopes.js +144 -0
  150. package/dist/cli/commands/hooks-status-command.d.ts +3 -0
  151. package/dist/cli/commands/hooks-status-command.js +93 -0
  152. package/dist/cli/commands/hooks-uninstall-command.d.ts +3 -0
  153. package/dist/cli/commands/hooks-uninstall-command.js +43 -0
  154. package/dist/cli/commands/loop-command-shared.d.ts +31 -0
  155. package/dist/cli/commands/loop-command-shared.js +15 -0
  156. package/dist/cli/commands/loop-commands.d.ts +12 -17
  157. package/dist/cli/commands/loop-commands.js +56 -238
  158. package/dist/cli/commands/loop-export-command.d.ts +3 -0
  159. package/dist/cli/commands/loop-export-command.js +73 -0
  160. package/dist/cli/commands/loop-goal-compose-command.d.ts +3 -0
  161. package/dist/cli/commands/loop-goal-compose-command.js +36 -0
  162. package/dist/cli/commands/loop-import-command.d.ts +3 -0
  163. package/dist/cli/commands/loop-import-command.js +86 -0
  164. package/dist/cli/commands/loop-placeholder-commands.d.ts +3 -0
  165. package/dist/cli/commands/loop-placeholder-commands.js +52 -0
  166. package/dist/cli/commands/memory-command-shared.d.ts +59 -0
  167. package/dist/cli/commands/memory-command-shared.js +39 -0
  168. package/dist/cli/commands/memory-commands.d.ts +6 -79
  169. package/dist/cli/commands/memory-commands.js +19 -309
  170. package/dist/cli/commands/memory-ingest-command.d.ts +3 -0
  171. package/dist/cli/commands/memory-ingest-command.js +50 -0
  172. package/dist/cli/commands/memory-list-command.d.ts +16 -0
  173. package/dist/cli/commands/memory-list-command.js +129 -0
  174. package/dist/cli/commands/memory-reindex-command.d.ts +9 -0
  175. package/dist/cli/commands/memory-reindex-command.js +78 -0
  176. package/dist/cli/commands/memory-rotate-command.d.ts +3 -0
  177. package/dist/cli/commands/memory-rotate-command.js +55 -0
  178. package/dist/cli/commands/memory-search-command.d.ts +7 -0
  179. package/dist/cli/commands/memory-search-command.js +46 -0
  180. package/dist/cli/commands/openspec-archive-command.d.ts +3 -0
  181. package/dist/cli/commands/openspec-archive-command.js +55 -0
  182. package/dist/cli/commands/openspec-command-shared.d.ts +62 -0
  183. package/dist/cli/commands/openspec-command-shared.js +135 -0
  184. package/dist/cli/commands/openspec-commands.d.ts +1 -1
  185. package/dist/cli/commands/openspec-commands.js +33 -306
  186. package/dist/cli/commands/openspec-from-doctor-command.d.ts +3 -0
  187. package/dist/cli/commands/openspec-from-doctor-command.js +66 -0
  188. package/dist/cli/commands/openspec-init-command.d.ts +3 -0
  189. package/dist/cli/commands/openspec-init-command.js +49 -0
  190. package/dist/cli/commands/openspec-list-command.d.ts +3 -0
  191. package/dist/cli/commands/openspec-list-command.js +27 -0
  192. package/dist/cli/commands/openspec-render-command.d.ts +3 -0
  193. package/dist/cli/commands/openspec-render-command.js +33 -0
  194. package/dist/cli/commands/openspec-show-command.d.ts +3 -0
  195. package/dist/cli/commands/openspec-show-command.js +33 -0
  196. package/dist/cli/commands/openspec-to-rd-command.d.ts +3 -0
  197. package/dist/cli/commands/openspec-to-rd-command.js +33 -0
  198. package/dist/cli/commands/openspec-validate-command.d.ts +3 -0
  199. package/dist/cli/commands/openspec-validate-command.js +45 -0
  200. package/dist/cli/commands/playwright-browser-command.d.ts +8 -0
  201. package/dist/cli/commands/playwright-browser-command.js +61 -0
  202. package/dist/cli/commands/playwright-commands.d.ts +10 -62
  203. package/dist/cli/commands/playwright-commands.js +77 -400
  204. package/dist/cli/commands/playwright-envelope.d.ts +8 -0
  205. package/dist/cli/commands/playwright-envelope.js +29 -0
  206. package/dist/cli/commands/playwright-ls-stop-commands.d.ts +4 -0
  207. package/dist/cli/commands/playwright-ls-stop-commands.js +74 -0
  208. package/dist/cli/commands/playwright-session-store.d.ts +65 -0
  209. package/dist/cli/commands/playwright-session-store.js +189 -0
  210. package/dist/cli/commands/project-commands.d.ts +19 -0
  211. package/dist/cli/commands/project-commands.js +98 -259
  212. package/dist/cli/commands/project-context-command.d.ts +3 -0
  213. package/dist/cli/commands/project-context-command.js +44 -0
  214. package/dist/cli/commands/project-dashboard-command.d.ts +3 -0
  215. package/dist/cli/commands/project-dashboard-command.js +74 -0
  216. package/dist/cli/commands/project-knowledge-command.d.ts +3 -0
  217. package/dist/cli/commands/project-knowledge-command.js +48 -0
  218. package/dist/cli/commands/project-memories-show-command.d.ts +3 -0
  219. package/dist/cli/commands/project-memories-show-command.js +87 -0
  220. package/dist/cli/commands/project-memory-index-command.d.ts +3 -0
  221. package/dist/cli/commands/project-memory-index-command.js +31 -0
  222. package/dist/cli/commands/qa-archive-screenshots-command.d.ts +3 -0
  223. package/dist/cli/commands/qa-archive-screenshots-command.js +53 -0
  224. package/dist/cli/commands/qa-commands.d.ts +14 -87
  225. package/dist/cli/commands/qa-commands.js +17 -315
  226. package/dist/cli/commands/qa-context-prestep.d.ts +1 -0
  227. package/dist/cli/commands/qa-context-prestep.js +34 -0
  228. package/dist/cli/commands/qa-run-command.d.ts +3 -0
  229. package/dist/cli/commands/qa-run-command.js +105 -0
  230. package/dist/cli/commands/qa-run-options.d.ts +23 -0
  231. package/dist/cli/commands/qa-run-options.js +31 -0
  232. package/dist/cli/commands/qa-run-slice.d.ts +41 -0
  233. package/dist/cli/commands/qa-run-slice.js +145 -0
  234. package/dist/cli/commands/release-canary-command.d.ts +28 -0
  235. package/dist/cli/commands/release-canary-command.js +129 -0
  236. package/dist/cli/commands/release-command-shared.d.ts +13 -0
  237. package/dist/cli/commands/release-command-shared.js +18 -0
  238. package/dist/cli/commands/release-commands.d.ts +10 -18
  239. package/dist/cli/commands/release-commands.js +25 -298
  240. package/dist/cli/commands/release-done-command.d.ts +3 -0
  241. package/dist/cli/commands/release-done-command.js +64 -0
  242. package/dist/cli/commands/release-hotfix-command.d.ts +3 -0
  243. package/dist/cli/commands/release-hotfix-command.js +50 -0
  244. package/dist/cli/commands/release-plan-command.d.ts +3 -0
  245. package/dist/cli/commands/release-plan-command.js +33 -0
  246. package/dist/cli/commands/release-precheck-command.d.ts +3 -0
  247. package/dist/cli/commands/release-precheck-command.js +28 -0
  248. package/dist/cli/commands/release-promote-command.d.ts +3 -0
  249. package/dist/cli/commands/release-promote-command.js +34 -0
  250. package/dist/cli/commands/release-rollback-command.d.ts +3 -0
  251. package/dist/cli/commands/release-rollback-command.js +33 -0
  252. package/dist/cli/commands/release-watch-command.d.ts +3 -0
  253. package/dist/cli/commands/release-watch-command.js +44 -0
  254. package/dist/cli/commands/sediment-argv-flags.d.ts +54 -0
  255. package/dist/cli/commands/sediment-argv-flags.js +116 -0
  256. package/dist/cli/commands/sediment-command-shared.d.ts +15 -0
  257. package/dist/cli/commands/sediment-command-shared.js +5 -0
  258. package/dist/cli/commands/sediment-commands.d.ts +35 -59
  259. package/dist/cli/commands/sediment-commands.js +36 -590
  260. package/dist/cli/commands/sediment-pool-commands.d.ts +9 -0
  261. package/dist/cli/commands/sediment-pool-commands.js +185 -0
  262. package/dist/cli/commands/sediment-query-commands.d.ts +4 -0
  263. package/dist/cli/commands/sediment-query-commands.js +94 -0
  264. package/dist/cli/commands/sediment-release-commands.d.ts +8 -0
  265. package/dist/cli/commands/sediment-release-commands.js +232 -0
  266. package/dist/cli/commands/sop-advance-command.d.ts +3 -0
  267. package/dist/cli/commands/sop-advance-command.js +160 -0
  268. package/dist/cli/commands/sop-check-command.d.ts +3 -0
  269. package/dist/cli/commands/sop-check-command.js +44 -0
  270. package/dist/cli/commands/sop-command-shared.d.ts +23 -0
  271. package/dist/cli/commands/sop-command-shared.js +18 -0
  272. package/dist/cli/commands/sop-commands.d.ts +15 -1
  273. package/dist/cli/commands/sop-commands.js +26 -240
  274. package/dist/cli/commands/sop-init-command.d.ts +3 -0
  275. package/dist/cli/commands/sop-init-command.js +51 -0
  276. package/dist/cli/commands/sop-lint-command.d.ts +3 -0
  277. package/dist/cli/commands/sop-lint-command.js +64 -0
  278. package/dist/cli/commands/sop-register-command.d.ts +3 -0
  279. package/dist/cli/commands/sop-register-command.js +48 -0
  280. package/dist/cli/commands/sop-registry-command.d.ts +3 -0
  281. package/dist/cli/commands/sop-registry-command.js +30 -0
  282. package/dist/cli/commands/statusline-command-shared.d.ts +73 -0
  283. package/dist/cli/commands/statusline-command-shared.js +90 -0
  284. package/dist/cli/commands/statusline-commands.d.ts +1 -19
  285. package/dist/cli/commands/statusline-commands.js +48 -287
  286. package/dist/cli/commands/statusline-compact-command.d.ts +4 -0
  287. package/dist/cli/commands/statusline-compact-command.js +54 -0
  288. package/dist/cli/commands/statusline-install-command.d.ts +3 -0
  289. package/dist/cli/commands/statusline-install-command.js +48 -0
  290. package/dist/cli/commands/statusline-render-command.d.ts +9 -0
  291. package/dist/cli/commands/statusline-render-command.js +55 -0
  292. package/dist/cli/commands/statusline-status-command.d.ts +3 -0
  293. package/dist/cli/commands/statusline-status-command.js +23 -0
  294. package/dist/cli/commands/statusline-uninstall-command.d.ts +3 -0
  295. package/dist/cli/commands/statusline-uninstall-command.js +23 -0
  296. package/dist/cli/commands/test-command-run-helpers.d.ts +27 -0
  297. package/dist/cli/commands/test-command-run-helpers.js +73 -0
  298. package/dist/cli/commands/test-command-runner-resolution.d.ts +57 -0
  299. package/dist/cli/commands/test-command-runner-resolution.js +183 -0
  300. package/dist/cli/commands/test-commands.d.ts +8 -56
  301. package/dist/cli/commands/test-commands.js +26 -249
  302. package/dist/cli/commands/vm-command-shared.d.ts +23 -0
  303. package/dist/cli/commands/vm-command-shared.js +23 -0
  304. package/dist/cli/commands/vm-commands.d.ts +1 -28
  305. package/dist/cli/commands/vm-commands.js +36 -270
  306. package/dist/cli/commands/vm-hypervisor-runtime.d.ts +15 -0
  307. package/dist/cli/commands/vm-hypervisor-runtime.js +64 -0
  308. package/dist/cli/commands/vm-release-command.d.ts +5 -0
  309. package/dist/cli/commands/vm-release-command.js +101 -0
  310. package/dist/cli/commands/vm-spawn-command.d.ts +5 -0
  311. package/dist/cli/commands/vm-spawn-command.js +177 -0
  312. package/dist/cli/commands/web-command-shared.d.ts +12 -0
  313. package/dist/cli/commands/web-command-shared.js +30 -0
  314. package/dist/cli/commands/web-commands.d.ts +7 -14
  315. package/dist/cli/commands/web-commands.js +6 -314
  316. package/dist/cli/commands/web-install-command.d.ts +10 -0
  317. package/dist/cli/commands/web-install-command.js +116 -0
  318. package/dist/cli/commands/web-lifecycle-commands.d.ts +9 -30
  319. package/dist/cli/commands/web-lifecycle-commands.js +14 -322
  320. package/dist/cli/commands/web-login-command.d.ts +14 -0
  321. package/dist/cli/commands/web-login-command.js +189 -0
  322. package/dist/cli/commands/web-op-payload.d.ts +22 -0
  323. package/dist/cli/commands/web-op-payload.js +89 -0
  324. package/dist/cli/commands/web-op-refusals.d.ts +37 -0
  325. package/dist/cli/commands/web-op-refusals.js +73 -0
  326. package/dist/cli/commands/web-op-runner.d.ts +14 -0
  327. package/dist/cli/commands/web-op-runner.js +166 -0
  328. package/dist/cli/commands/web-status-command.d.ts +4 -0
  329. package/dist/cli/commands/web-status-command.js +32 -0
  330. package/dist/cli/commands/web-stop-command.d.ts +10 -0
  331. package/dist/cli/commands/web-stop-command.js +59 -0
  332. package/dist/cli/commands/web-verb-specs.d.ts +18 -0
  333. package/dist/cli/commands/web-verb-specs.js +66 -0
  334. package/dist/cli/commands/workflow-command-shared.d.ts +102 -0
  335. package/dist/cli/commands/workflow-command-shared.js +74 -0
  336. package/dist/cli/commands/workflow-graph-commands.d.ts +3 -0
  337. package/dist/cli/commands/workflow-graph-commands.js +73 -0
  338. package/dist/cli/commands/workflow-init-command.d.ts +3 -0
  339. package/dist/cli/commands/workflow-init-command.js +68 -0
  340. package/dist/cli/commands/workflow-lifecycle-commands.d.ts +9 -59
  341. package/dist/cli/commands/workflow-lifecycle-commands.js +14 -348
  342. package/dist/cli/commands/workflow-node-commands.d.ts +3 -0
  343. package/dist/cli/commands/workflow-node-commands.js +154 -0
  344. package/dist/cli/commands/workflow-terminalize-command.d.ts +3 -0
  345. package/dist/cli/commands/workflow-terminalize-command.js +56 -0
  346. package/dist/services/code/auto-compact-artifacts.d.ts +54 -0
  347. package/dist/services/code/auto-compact-artifacts.js +135 -0
  348. package/dist/services/code/auto-compact-attempt.d.ts +46 -0
  349. package/dist/services/code/auto-compact-attempt.js +88 -0
  350. package/dist/services/code/auto-compact-decision.d.ts +74 -0
  351. package/dist/services/code/auto-compact-decision.js +149 -0
  352. package/dist/services/code/auto-compact-dispatch-gate.d.ts +36 -0
  353. package/dist/services/code/auto-compact-dispatch-gate.js +86 -0
  354. package/dist/services/code/auto-compact-envelopes.d.ts +33 -0
  355. package/dist/services/code/auto-compact-envelopes.js +134 -0
  356. package/dist/services/code/auto-compact-history.d.ts +46 -0
  357. package/dist/services/code/auto-compact-history.js +17 -0
  358. package/dist/services/code/auto-compact-orchestrator.d.ts +11 -240
  359. package/dist/services/code/auto-compact-orchestrator.js +165 -686
  360. package/dist/services/code/auto-compact-run-types.d.ts +123 -0
  361. package/dist/services/code/auto-compact-run-types.js +1 -0
  362. package/dist/services/code/emit-handoff.d.ts +35 -1
  363. package/dist/services/code/emit-handoff.js +128 -7
  364. package/dist/services/code/step-08-gate.d.ts +28 -19
  365. package/dist/services/code/step-08-gate.js +92 -35
  366. package/dist/services/config/config-coercion.d.ts +7 -0
  367. package/dist/services/config/config-coercion.js +156 -0
  368. package/dist/services/config/config-file-io.d.ts +11 -0
  369. package/dist/services/config/config-file-io.js +61 -0
  370. package/dist/services/config/config-get.d.ts +2 -0
  371. package/dist/services/config/config-get.js +36 -0
  372. package/dist/services/config/config-global-loader.d.ts +15 -0
  373. package/dist/services/config/config-global-loader.js +111 -0
  374. package/dist/services/config/config-nested-path.d.ts +3 -0
  375. package/dist/services/config/config-nested-path.js +53 -0
  376. package/dist/services/config/config-primitives.d.ts +16 -0
  377. package/dist/services/config/config-primitives.js +24 -0
  378. package/dist/services/config/config-service.d.ts +9 -33
  379. package/dist/services/config/config-service.js +16 -665
  380. package/dist/services/config/config-validation.d.ts +19 -0
  381. package/dist/services/config/config-validation.js +152 -0
  382. package/dist/services/config/config-workspace.d.ts +10 -0
  383. package/dist/services/config/config-workspace.js +158 -0
  384. package/dist/services/skills/hooks-settings-deny-list.d.ts +61 -0
  385. package/dist/services/skills/hooks-settings-deny-list.js +173 -0
  386. package/dist/services/skills/hooks-settings-envelopes.d.ts +20 -0
  387. package/dist/services/skills/hooks-settings-envelopes.js +79 -0
  388. package/dist/services/skills/hooks-settings-file-shape.d.ts +43 -0
  389. package/dist/services/skills/hooks-settings-file-shape.js +207 -0
  390. package/dist/services/skills/hooks-settings-paths.d.ts +34 -0
  391. package/dist/services/skills/hooks-settings-paths.js +75 -0
  392. package/dist/services/skills/hooks-settings-read-installed.d.ts +39 -0
  393. package/dist/services/skills/hooks-settings-read-installed.js +60 -0
  394. package/dist/services/skills/hooks-settings-service.d.ts +12 -212
  395. package/dist/services/skills/hooks-settings-service.js +71 -657
  396. package/dist/services/skills/hooks-settings-types.d.ts +139 -0
  397. package/dist/services/skills/hooks-settings-types.js +1 -0
  398. package/dist/services/workspace/claude-settings-template-merge.d.ts +89 -0
  399. package/dist/services/workspace/claude-settings-template-merge.js +243 -0
  400. package/dist/services/workspace/claude-settings-template.d.ts +29 -87
  401. package/dist/services/workspace/claude-settings-template.js +81 -236
  402. package/package.json +5 -5
@@ -0,0 +1,65 @@
1
+ import { spawn } from 'node:child_process';
2
+ export declare const DEFAULT_PORT = 8931;
3
+ export declare const MAX_PORT = 8949;
4
+ /** The lowest TCP port the `--port` flag accepts. */
5
+ export declare const MIN_PORT = 1024;
6
+ /** The highest TCP port the `--port` flag accepts. */
7
+ export declare const MAX_TCP_PORT = 65535;
8
+ export declare const BROWSERS: readonly ["chromium", "firefox", "webkit"];
9
+ export type Browser = (typeof BROWSERS)[number];
10
+ export interface PlaywrightSession {
11
+ terminalId: string;
12
+ port: number;
13
+ browser: Browser;
14
+ userDataDir: string;
15
+ startedAt: string;
16
+ pid?: number;
17
+ }
18
+ export declare const PLAYWRIGHT_SESSIONS_DIR = "playwright-sessions";
19
+ export declare function playwrightSessionsDir(projectRoot: string): string;
20
+ export declare function sessionFilePath(projectRoot: string, terminalId: string): string;
21
+ /**
22
+ * The per-terminal default `--user-data-dir` under the runtime tree. Guarded here,
23
+ * beside the join, for the same reason `sessionFilePath` above is: rule D keys the
24
+ * guard to the FILE, and the caller (`peaks playwright start`) reaches this only
25
+ * through `readSession` — so a guard that leaned on that call order would be the
26
+ * file-scoped hole the rule exists to keep visible.
27
+ */
28
+ export declare function defaultUserDataDir(projectRoot: string, terminalId: string): string;
29
+ /**
30
+ * Derive a stable terminal id from the process environment. Prefers
31
+ * the platform's own terminal-session id (macOS Terminal, Windows
32
+ * Terminal) and falls back to a hash of (ppid, tty).
33
+ */
34
+ export declare function deriveTerminalId(env?: NodeJS.ProcessEnv, ppid?: number): string;
35
+ /**
36
+ * Walk port range starting at `start` and return the first port
37
+ * that is NOT bound. Defaults: 8931 → 8949. If the range is exhausted,
38
+ * returns null.
39
+ */
40
+ export declare function findFreePort(start?: number, max?: number, probe?: (port: number) => Promise<boolean>): Promise<number | null>;
41
+ export declare function listSessions(projectRoot: string): PlaywrightSession[];
42
+ export declare function readSession(projectRoot: string, terminalId: string): PlaywrightSession | null;
43
+ export declare function writeSession(projectRoot: string, session: PlaywrightSession): void;
44
+ export declare function removeSession(projectRoot: string, terminalId: string): boolean;
45
+ /**
46
+ * Spawn the playwright MCP via npx. We do NOT bundle the binary;
47
+ * we just orchestrate the lifecycle. Returns the child PID so the
48
+ * session file can record it.
49
+ */
50
+ export declare function spawnPlaywrightMcp(port: number, browser: Browser, userDataDir: string, projectRoot: string): {
51
+ pid: number | undefined;
52
+ child: ReturnType<typeof spawn>;
53
+ };
54
+ /**
55
+ * Resolve and validate a caller-supplied `--user-data-dir`. The dir must
56
+ * live under `projectRoot` so a malicious `--user-data-dir /etc/foo`
57
+ * cannot coerce the playwright-mcp browser into writing state to an
58
+ *
59
+ * Resolves `..` segments before checking, so a path like
60
+ * `<projectRoot>/../escape` is correctly normalized and rejected.
61
+ *
62
+ * Throws `Error('INVALID_USER_DATA_DIR: ...')` on validation failure;
63
+ * the action handler catches and emits the JSON envelope.
64
+ */
65
+ export declare function resolveUserDataDir(raw: string, projectRoot: string): string;
@@ -0,0 +1,189 @@
1
+ // src/cli/commands/playwright-session-store.ts
2
+ //
3
+ // The Playwright MCP session store: port range, terminal-id derivation, the
4
+ // session-record file layout, the port probe and the process spawn. Split out
5
+ // of `playwright-commands.ts`, which re-exports every symbol below so its
6
+ // public surface is unchanged.
7
+ import { createHash } from 'node:crypto';
8
+ import { spawn } from 'node:child_process';
9
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, unlinkSync } from 'node:fs';
10
+ import net from 'node:net';
11
+ import { join, dirname, resolve } from 'node:path';
12
+ import { isUnsafePathInput } from '../../shared/path-safety.js';
13
+ export const DEFAULT_PORT = 8931;
14
+ export const MAX_PORT = 8949;
15
+ /** The lowest TCP port the `--port` flag accepts. */
16
+ export const MIN_PORT = 1024;
17
+ /** The highest TCP port the `--port` flag accepts. */
18
+ export const MAX_TCP_PORT = 65535;
19
+ /** Hex characters kept from the sha256 of (ppid, tty) when deriving a terminal id. */
20
+ const TERMINAL_HASH_CHARS = 16;
21
+ /** Longest id `sanitizeTerminalId` will emit. */
22
+ const TERMINAL_ID_MAX_CHARS = 64;
23
+ export const BROWSERS = ['chromium', 'firefox', 'webkit'];
24
+ export const PLAYWRIGHT_SESSIONS_DIR = 'playwright-sessions';
25
+ export function playwrightSessionsDir(projectRoot) {
26
+ return join(projectRoot, '.peaks', '_runtime', PLAYWRIGHT_SESSIONS_DIR);
27
+ }
28
+ export function sessionFilePath(projectRoot, terminalId) {
29
+ // Terminal-id axis. The derived id is already sanitised (`deriveTerminalId`),
30
+ // but `--terminal` is caller-supplied and reaches this join unsanitised.
31
+ // Measured (repair cycle 1, item 1): `playwright stop --terminal ../../../../X`
32
+ // read a session record planted OUTSIDE the project root, sent SIGTERM to the
33
+ // pid it named, unlinked that file, and returned `ok: true` — arbitrary
34
+ // process termination plus an arbitrary file delete, one flag away. This is
35
+ // the join every reader/writer of a session record goes through, so this is
36
+ // where the invariant lives.
37
+ if (isUnsafePathInput(terminalId)) {
38
+ throw new Error(`Invalid terminal id: ${terminalId} (must be a single path segment)`);
39
+ }
40
+ return join(playwrightSessionsDir(projectRoot), `${terminalId}.json`);
41
+ }
42
+ /**
43
+ * The per-terminal default `--user-data-dir` under the runtime tree. Guarded here,
44
+ * beside the join, for the same reason `sessionFilePath` above is: rule D keys the
45
+ * guard to the FILE, and the caller (`peaks playwright start`) reaches this only
46
+ * through `readSession` — so a guard that leaned on that call order would be the
47
+ * file-scoped hole the rule exists to keep visible.
48
+ */
49
+ export function defaultUserDataDir(projectRoot, terminalId) {
50
+ if (isUnsafePathInput(terminalId)) {
51
+ throw new Error(`Invalid terminal id: ${terminalId} (must be a single path segment)`);
52
+ }
53
+ return join(projectRoot, '.peaks', '_runtime', 'playwright-userdata', terminalId);
54
+ }
55
+ /**
56
+ * Derive a stable terminal id from the process environment. Prefers
57
+ * the platform's own terminal-session id (macOS Terminal, Windows
58
+ * Terminal) and falls back to a hash of (ppid, tty).
59
+ */
60
+ export function deriveTerminalId(env = process.env, ppid = process.ppid) {
61
+ const termSession = env.TERM_SESSION_ID;
62
+ if (termSession && termSession.length > 0) {
63
+ return sanitizeTerminalId(termSession);
64
+ }
65
+ const wtSession = env.WT_SESSION;
66
+ if (wtSession && wtSession.length > 0) {
67
+ return sanitizeTerminalId(`wt-${wtSession}`);
68
+ }
69
+ const tty = env.SSH_TTY ?? 'no-tty';
70
+ const hash = createHash('sha256')
71
+ .update(`${ppid}-${tty}`)
72
+ .digest('hex')
73
+ .slice(0, TERMINAL_HASH_CHARS);
74
+ return `tty-${hash}`;
75
+ }
76
+ function sanitizeTerminalId(raw) {
77
+ return raw.replace(/[^a-zA-Z0-9_.-]/g, '_').slice(0, TERMINAL_ID_MAX_CHARS);
78
+ }
79
+ /**
80
+ * Walk port range starting at `start` and return the first port
81
+ * that is NOT bound. Defaults: 8931 → 8949. If the range is exhausted,
82
+ * returns null.
83
+ */
84
+ export async function findFreePort(start = DEFAULT_PORT, max = MAX_PORT, probe = defaultPortProbe) {
85
+ for (let p = start; p <= max; p += 1) {
86
+ if (await probe(p))
87
+ return p;
88
+ }
89
+ return null;
90
+ }
91
+ async function defaultPortProbe(port) {
92
+ return new Promise((resolveProbe) => {
93
+ const server = net.createServer();
94
+ server.once('error', () => resolveProbe(false));
95
+ server.once('listening', () => {
96
+ server.close(() => resolveProbe(true));
97
+ });
98
+ server.listen(port, '127.0.0.1');
99
+ });
100
+ }
101
+ export function listSessions(projectRoot) {
102
+ const dir = playwrightSessionsDir(projectRoot);
103
+ if (!existsSync(dir))
104
+ return [];
105
+ const out = [];
106
+ for (const entry of readdirSync(dir)) {
107
+ if (!entry.endsWith('.json'))
108
+ continue;
109
+ try {
110
+ const raw = readFileSync(join(dir, entry), 'utf8');
111
+ const session = JSON.parse(raw);
112
+ out.push(session);
113
+ }
114
+ catch {
115
+ // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
116
+ // skip malformed session file
117
+ }
118
+ }
119
+ return out;
120
+ }
121
+ export function readSession(projectRoot, terminalId) {
122
+ const path = sessionFilePath(projectRoot, terminalId);
123
+ if (!existsSync(path))
124
+ return null;
125
+ try {
126
+ return JSON.parse(readFileSync(path, 'utf8'));
127
+ }
128
+ catch {
129
+ // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
130
+ return null;
131
+ }
132
+ }
133
+ export function writeSession(projectRoot, session) {
134
+ const path = sessionFilePath(projectRoot, session.terminalId);
135
+ const dir = dirname(path);
136
+ if (!existsSync(dir)) {
137
+ mkdirSync(dir, { recursive: true });
138
+ }
139
+ writeFileSync(path, JSON.stringify(session, null, 2) + '\n', 'utf8');
140
+ }
141
+ export function removeSession(projectRoot, terminalId) {
142
+ const path = sessionFilePath(projectRoot, terminalId);
143
+ if (!existsSync(path))
144
+ return false;
145
+ unlinkSync(path);
146
+ return true;
147
+ }
148
+ /**
149
+ * Spawn the playwright MCP via npx. We do NOT bundle the binary;
150
+ * we just orchestrate the lifecycle. Returns the child PID so the
151
+ * session file can record it.
152
+ */
153
+ export function spawnPlaywrightMcp(port, browser, userDataDir, projectRoot) {
154
+ const child = spawn('npx', [
155
+ 'playwright-mcp@latest',
156
+ `--port=${port}`,
157
+ `--browser=${browser}`,
158
+ `--user-data-dir=${userDataDir}`
159
+ ], {
160
+ cwd: projectRoot,
161
+ env: process.env,
162
+ stdio: 'ignore',
163
+ detached: true,
164
+ windowsHide: true
165
+ });
166
+ return { pid: child.pid, child };
167
+ }
168
+ /**
169
+ * Resolve and validate a caller-supplied `--user-data-dir`. The dir must
170
+ * live under `projectRoot` so a malicious `--user-data-dir /etc/foo`
171
+ * cannot coerce the playwright-mcp browser into writing state to an
172
+ *
173
+ * Resolves `..` segments before checking, so a path like
174
+ * `<projectRoot>/../escape` is correctly normalized and rejected.
175
+ *
176
+ * Throws `Error('INVALID_USER_DATA_DIR: ...')` on validation failure;
177
+ * the action handler catches and emits the JSON envelope.
178
+ */
179
+ export function resolveUserDataDir(raw, projectRoot) {
180
+ const resolved = resolve(projectRoot, raw);
181
+ const rootResolved = resolve(projectRoot) + (projectRoot.endsWith('/') || projectRoot.endsWith('\\') ? '' : '/');
182
+ // Use the projectRoot + sep as the prefix; require either an exact
183
+ // match or a child path. The `+ '/'` guard prevents sibling-prefix
184
+ // collisions (e.g. /home/A/proj2 passes the check for /home/A/proj).
185
+ if (resolved !== resolve(projectRoot) && !resolved.startsWith(rootResolved)) {
186
+ throw new Error(`INVALID_USER_DATA_DIR: --user-data-dir must resolve to a path under project root ${projectRoot} (got ${resolved})`);
187
+ }
188
+ return resolved;
189
+ }
@@ -1,3 +1,22 @@
1
+ /**
2
+ * `peaks project *` — aggregate Peaks state for a target project (read-only).
3
+ *
4
+ * The umbrella verb plus the two memory verbs whose envelopes are pinned by
5
+ * source-scanning tests, which is why they stay in this file rather than moving
6
+ * to a sibling module beside the others:
7
+ *
8
+ * - `tests/unit/services/memory/memory-kind-llm-surfaces.test.ts` requires the
9
+ * literal `VALID_PROJECT_MEMORY_KINDS` here (the `--kind` help must stay
10
+ * derived, never hand-maintained);
11
+ * - `tests/unit/services/memory/memory-block-drop-diagnostics.test.ts` requires
12
+ * the literal `describeMemoryBlockDrops(result.droppedBlocks)` here (the
13
+ * drops must reach the `ok(..., warnings)` channel).
14
+ *
15
+ * The rest live one module per verb:
16
+ * `project-dashboard-command.ts`, `project-context-command.ts`,
17
+ * `project-memory-index-command.ts`, `project-memories-show-command.ts`,
18
+ * `project-knowledge-command.ts`.
19
+ */
1
20
  import type { Command } from 'commander';
2
21
  import { type ProgramIO } from '../cli-helpers.js';
3
22
  export declare function registerProjectCommands(program: Command, io: ProgramIO): void;
@@ -1,96 +1,104 @@
1
- import { loadProjectDashboard } from '../../services/dashboard/project-dashboard-service.js';
2
- import { generateProjectContext, readProjectContext } from '../../services/memory/project-context-service.js';
3
- import { describeMemoryBlockDrops, describeSessionScanFailures, extractSessionMemories, readMemoryIndex, readProjectMemories, readProjectMemoryBody, VALID_PROJECT_MEMORY_KINDS } from '../../services/memory/project-memory-service.js';
4
- import { readBusinessKnowledge } from '../../services/prd/project-scan-reader.js';
5
- import { applyStalePolicy, DEFAULT_STALE_DAYS } from '../../shared/stale-policy.js';
6
- import { formatMdCompact } from '../../shared/format-md-compact.js';
1
+ /**
2
+ * `peaks project *` — aggregate Peaks state for a target project (read-only).
3
+ *
4
+ * The umbrella verb plus the two memory verbs whose envelopes are pinned by
5
+ * source-scanning tests, which is why they stay in this file rather than moving
6
+ * to a sibling module beside the others:
7
+ *
8
+ * - `tests/unit/services/memory/memory-kind-llm-surfaces.test.ts` requires the
9
+ * literal `VALID_PROJECT_MEMORY_KINDS` here (the `--kind` help must stay
10
+ * derived, never hand-maintained);
11
+ * - `tests/unit/services/memory/memory-block-drop-diagnostics.test.ts` requires
12
+ * the literal `describeMemoryBlockDrops(result.droppedBlocks)` here (the
13
+ * drops must reach the `ok(..., warnings)` channel).
14
+ *
15
+ * The rest live one module per verb:
16
+ * `project-dashboard-command.ts`, `project-context-command.ts`,
17
+ * `project-memory-index-command.ts`, `project-memories-show-command.ts`,
18
+ * `project-knowledge-command.ts`.
19
+ */
20
+ import { describeMemoryBlockDrops, describeSessionScanFailures, extractSessionMemories, readProjectMemories, VALID_PROJECT_MEMORY_KINDS } from '../../services/memory/project-memory-service.js';
7
21
  import { fail, ok } from 'peaks-loop-shared/result';
8
22
  import { addJsonOption, getErrorMessage, printResult } from '../cli-helpers.js';
23
+ import { registerProjectDashboardCommand } from './project-dashboard-command.js';
24
+ import { registerProjectContextCommand } from './project-context-command.js';
25
+ import { registerProjectKnowledgeCommand } from './project-knowledge-command.js';
26
+ import { registerProjectMemoriesShowCommand } from './project-memories-show-command.js';
27
+ import { registerProjectMemoryIndexCommand } from './project-memory-index-command.js';
9
28
  /** Derived from the canonical kind vocabulary — never hand-maintain a list here. */
10
29
  const KIND_HELP = VALID_PROJECT_MEMORY_KINDS.join(', ');
30
+ /** The `ok` payload for `memories:extract` — the counts the caller acts on. */
31
+ function extractData(result) {
32
+ return {
33
+ scannedFiles: result.scannedFiles,
34
+ extractedCount: result.extractedCount,
35
+ writtenFiles: result.writtenFiles,
36
+ memoryDir: result.primaryMemoryDir,
37
+ indexUpdated: result.updatedIndex
38
+ };
39
+ }
40
+ /**
41
+ * Two drop axes, one channel. `droppedBlocks` = a block was found and rejected
42
+ * (or a marker-shaped comment was not findable at all); `scanFailures` = the
43
+ * whole artifact could not be read, so its blocks were never candidates.
44
+ * `data` is unchanged by either — same contract as `memory.extract`.
45
+ */
46
+ function extractWarnings(result) {
47
+ return [
48
+ ...describeMemoryBlockDrops(result.droppedBlocks),
49
+ ...describeSessionScanFailures(result.scanFailures)
50
+ ];
51
+ }
52
+ function runProjectMemories(io, options) {
53
+ try {
54
+ const result = readProjectMemories(options.project);
55
+ if (options.kind) {
56
+ const memories = result.memories.filter((memory) => memory.kind === options.kind);
57
+ printResult(io, ok('project.memories', {
58
+ memoryDir: result.memoryDir,
59
+ kind: options.kind,
60
+ total: memories.length,
61
+ memories
62
+ }), options.json);
63
+ return;
64
+ }
65
+ printResult(io, ok('project.memories', {
66
+ memoryDir: result.memoryDir,
67
+ total: result.total,
68
+ byKind: result.byKind,
69
+ memories: result.memories
70
+ }), options.json);
71
+ }
72
+ catch (error) {
73
+ printResult(io, fail('project.memories', 'PROJECT_MEMORIES_FAILED', getErrorMessage(error), { projectRoot: options.project }, ['Check the project path and .peaks/memory directory']), options.json);
74
+ process.exitCode = 1;
75
+ }
76
+ }
77
+ function runMemoriesExtract(io, options) {
78
+ if (options.dryRun === true && options.apply === true) {
79
+ printResult(io, fail('project.memories:extract', 'INVALID_MEMORY_EXTRACT_FLAGS', 'Use either --dry-run or --apply, not both', { sessionId: options.sessionId, projectRoot: options.project }, ['Run without --apply to preview writes, or pass --apply to write memories']), options.json);
80
+ process.exitCode = 1;
81
+ return;
82
+ }
83
+ try {
84
+ const result = extractSessionMemories({
85
+ projectRoot: options.project,
86
+ sessionId: options.sessionId,
87
+ apply: options.apply === true
88
+ });
89
+ printResult(io, ok('project.memories:extract', extractData(result), extractWarnings(result)), options.json);
90
+ }
91
+ catch (error) {
92
+ printResult(io, fail('project.memories:extract', 'MEMORY_EXTRACT_FAILED', getErrorMessage(error), { sessionId: options.sessionId, projectRoot: options.project }, ['Check the session-id and project path']), options.json);
93
+ process.exitCode = 1;
94
+ }
95
+ }
11
96
  export function registerProjectCommands(program, io) {
12
97
  const project = program
13
98
  .command('project')
14
99
  .description('Aggregate Peaks state for a target project (read-only)');
15
- addJsonOption(project
16
- .command('dashboard')
17
- .description('One-call snapshot of doctor / MCP / OpenSpec / requests / capabilities for a project')
18
- .requiredOption('--project <path>', 'target project root')
19
- .option('--strict', 'ok follows the doctor aggregate (legacy semantics). Default: workspace-only (ok tracks the runbook health)', false)).action(async (options) => {
20
- try {
21
- const dashboard = await loadProjectDashboard({
22
- projectRoot: options.project,
23
- okPolicy: options.strict === true ? 'strict' : 'workspace-only'
24
- });
25
- if (!dashboard.runbookHealth.ok) {
26
- const suggestions = [
27
- dashboard.runbookHealth.missingRunbook.length > 0
28
- ? `Add a ## Default runbook section to: ${dashboard.runbookHealth.missingRunbook.join(', ')}`
29
- : null,
30
- dashboard.runbookHealth.applyNoteFailed.length > 0
31
- ? `Add authorization/--dry-run notes next to destructive --apply lines in: ${dashboard.runbookHealth.applyNoteFailed.join(', ')}`
32
- : null
33
- ].filter((line) => line !== null);
34
- printResult(io, fail('project.dashboard', 'PROJECT_DASHBOARD_RUNBOOK_UNHEALTHY', `Skill runbook health failing: ${dashboard.runbookHealth.healthy}/${dashboard.runbookHealth.required} healthy`, dashboard, suggestions), options.json);
35
- process.exitCode = 1;
36
- return;
37
- }
38
- if (dashboard.skillPresence.active && !dashboard.skillPresence.fresh) {
39
- printResult(io, fail('project.dashboard', 'PROJECT_DASHBOARD_STALE_SKILL_PRESENCE', `Active Peaks skill presence ${dashboard.skillPresence.skill ?? '<unknown>'} is stale (set ${dashboard.skillPresence.setAt ?? '<unknown>'})`, dashboard, [
40
- 'Run `peaks skill presence:clear` if the role has ended, or `peaks skill presence:set <skill>` to refresh it'
41
- ]), options.json);
42
- process.exitCode = 1;
43
- return;
44
- }
45
- if (!dashboard.doctor.ok && options.strict === true) {
46
- printResult(io, fail('project.dashboard', 'PROJECT_DASHBOARD_DOCTOR_STRICT_FAIL', `Doctor reports ${dashboard.doctor.failed} failed check(s) (${dashboard.doctor.passed} passed) — --strict mode requires the doctor aggregate to pass`, dashboard, [
47
- 'Run `peaks doctor --json` and resolve the failing checks, or drop --strict to use the workspace-only policy'
48
- ]), options.json);
49
- process.exitCode = 1;
50
- return;
51
- }
52
- printResult(io, ok('project.dashboard', dashboard), options.json);
53
- }
54
- catch (error) {
55
- printResult(io, fail('project.dashboard', 'PROJECT_DASHBOARD_FAILED', getErrorMessage(error), { projectRoot: options.project }, ['Check the project path before retrying']), options.json);
56
- process.exitCode = 1;
57
- }
58
- });
59
- addJsonOption(project
60
- .command('context')
61
- .description('Generate or read persistent project context for cross-session Peaks understanding. Generates BOTH `.peaks/PROJECT.md` (session history) AND `.peaks/project-scan/project-scan.md` (tech stack + archetypes) — see `peaks workspace init` for the full 5-template boot (G4b/AC9).')
62
- .requiredOption('--project <path>', 'target project root')
63
- .option('--read', 'read existing PROJECT.md without regenerating')).action(async (options) => {
64
- try {
65
- if (options.read) {
66
- const content = readProjectContext(options.project);
67
- if (content === null) {
68
- printResult(io, ok('project.context', { exists: false, path: `${options.project}/.peaks/PROJECT.md` }), options.json);
69
- return;
70
- }
71
- printResult(io, ok('project.context', {
72
- exists: true,
73
- path: `${options.project}/.peaks/PROJECT.md`,
74
- content
75
- }), options.json);
76
- return;
77
- }
78
- const result = await generateProjectContext(options.project);
79
- printResult(io, ok('project.context', {
80
- path: result.path,
81
- sessionCount: result.sessionCount,
82
- content: result.content,
83
- // context command also bootstraps the project-scan tree.
84
- // The envelope surfaces write counts + duration so the LLM
85
- // (and the user) see what landed.
86
- projectScan: result.projectScan
87
- }), options.json);
88
- }
89
- catch (error) {
90
- printResult(io, fail('project.context', 'PROJECT_CONTEXT_FAILED', getErrorMessage(error), { projectRoot: options.project }, ['Check the project path and .peaks directory']), options.json);
91
- process.exitCode = 1;
92
- }
93
- });
100
+ registerProjectDashboardCommand(project, io);
101
+ registerProjectContextCommand(project, io);
94
102
  // --- Extract memories from a session's artifacts into .peaks/memory ---
95
103
  addJsonOption(project
96
104
  .command('memories:extract')
@@ -104,183 +112,14 @@ export function registerProjectCommands(program, io) {
104
112
  // opt-in; the mutual-exclusion check below is correct without a
105
113
  // special-case.
106
114
  .option('--dry-run', 'preview writes without changing files')
107
- .option('--apply', 'write extracted memories into .peaks/memory/')).action((options) => {
108
- if (options.dryRun === true && options.apply === true) {
109
- printResult(io, fail('project.memories:extract', 'INVALID_MEMORY_EXTRACT_FLAGS', 'Use either --dry-run or --apply, not both', { sessionId: options.sessionId, projectRoot: options.project }, ['Run without --apply to preview writes, or pass --apply to write memories']), options.json);
110
- process.exitCode = 1;
111
- return;
112
- }
113
- try {
114
- const result = extractSessionMemories({
115
- projectRoot: options.project,
116
- sessionId: options.sessionId,
117
- apply: options.apply === true
118
- });
119
- printResult(io, ok('project.memories:extract', {
120
- scannedFiles: result.scannedFiles,
121
- extractedCount: result.extractedCount,
122
- writtenFiles: result.writtenFiles,
123
- memoryDir: result.primaryMemoryDir,
124
- indexUpdated: result.updatedIndex
125
- }, [
126
- // Two drop axes, one channel. `droppedBlocks` = a block was found and
127
- // rejected (or a marker-shaped comment was not findable at all);
128
- // `scanFailures` = the whole artifact could not be read, so its blocks
129
- // were never candidates. `data` is unchanged by either — same contract
130
- // as `memory.extract`.
131
- ...describeMemoryBlockDrops(result.droppedBlocks),
132
- ...describeSessionScanFailures(result.scanFailures)
133
- ]), options.json);
134
- }
135
- catch (error) {
136
- printResult(io, fail('project.memories:extract', 'MEMORY_EXTRACT_FAILED', getErrorMessage(error), { sessionId: options.sessionId, projectRoot: options.project }, ['Check the session-id and project path']), options.json);
137
- process.exitCode = 1;
138
- }
139
- });
140
- // --- Read memory index (lightweight, always-safe to load) ---
141
- addJsonOption(project
142
- .command('memory-index')
143
- .description('Read the memory index — lightweight hot/warm分层 view of all project memories')
144
- .requiredOption('--project <path>', 'target project root')).action((options) => {
145
- try {
146
- const index = readMemoryIndex(options.project);
147
- if (!index) {
148
- printResult(io, ok('project.memory-index', {
149
- exists: false,
150
- message: 'No memory index found. Run `peaks project memories:extract` first.'
151
- }), options.json);
152
- return;
153
- }
154
- printResult(io, ok('project.memory-index', { exists: true, index }), options.json);
155
- }
156
- catch (error) {
157
- printResult(io, fail('project.memory-index', 'MEMORY_INDEX_FAILED', getErrorMessage(error), { projectRoot: options.project }, ['Check the project path and .peaks/memory directory']), options.json);
158
- process.exitCode = 1;
159
- }
160
- });
115
+ .option('--apply', 'write extracted memories into .peaks/memory/')).action((options) => runMemoriesExtract(io, options));
116
+ registerProjectMemoryIndexCommand(project, io);
161
117
  // --- Structured project memory (durable, LLM-authored, stored under .peaks/memory) ---
162
118
  addJsonOption(project
163
119
  .command('memories')
164
120
  .description('Read durable project memories (decisions, conventions, modules, rules) from .peaks/memory for LLM consumption')
165
121
  .requiredOption('--project <path>', 'target project root')
166
- .option('--kind <kind>', `filter by memory kind (one of: ${KIND_HELP})`)).action((options) => {
167
- try {
168
- const result = readProjectMemories(options.project);
169
- if (options.kind) {
170
- const memories = result.memories.filter((memory) => memory.kind === options.kind);
171
- printResult(io, ok('project.memories', {
172
- memoryDir: result.memoryDir,
173
- kind: options.kind,
174
- total: memories.length,
175
- memories
176
- }), options.json);
177
- return;
178
- }
179
- printResult(io, ok('project.memories', {
180
- memoryDir: result.memoryDir,
181
- total: result.total,
182
- byKind: result.byKind,
183
- memories: result.memories
184
- }), options.json);
185
- }
186
- catch (error) {
187
- printResult(io, fail('project.memories', 'PROJECT_MEMORIES_FAILED', getErrorMessage(error), { projectRoot: options.project }, ['Check the project path and .peaks/memory directory']), options.json);
188
- process.exitCode = 1;
189
- }
190
- });
191
- // --- Show one project memory's body (R3: default = compact) ---
192
- addJsonOption(project
193
- .command('memories:show <name>')
194
- .description('Show one project memory body by name. Default format is `compact` (LLM-primary); pass --pretty for the disk verbatim. Stale entries (default ≥30 days) are excluded; pass --include-stale or --stale-days <N> to override.')
195
- .requiredOption('--project <path>', 'target project root')
196
- .option('--pretty', 'return the on-disk body verbatim; overrides the compact default')
197
- .option('--include-stale', 'include stale entries (the default excludes them)')
198
- .option('--stale-days <n>', 'override the 30-day stale threshold (must be > 0)', (value) => Number(value))).action((name, options) => {
199
- try {
200
- const memory = readProjectMemoryBody(options.project, name);
201
- if (memory === null) {
202
- printResult(io, fail('project.memories:show', 'MEMORY_NOT_FOUND', `memory ${name} not found in .peaks/memory`, { name, projectRoot: options.project }, ['Run `peaks project memories --json` to see available names']), options.json);
203
- process.exitCode = 1;
204
- return;
205
- }
206
- // Compute the stale decision. R4: stale is computed at CLI load time
207
- // only; the source `.md` file is never modified.
208
- const updatedAt = memory.updatedAt;
209
- const thresholdDays = options.staleDays !== undefined &&
210
- Number.isFinite(options.staleDays) &&
211
- options.staleDays > 0
212
- ? options.staleDays
213
- : DEFAULT_STALE_DAYS;
214
- const policy = applyStalePolicy([{ name: memory.name, updatedAt }], {
215
- thresholdDays,
216
- includeStale: options.includeStale === true
217
- });
218
- if (policy.entries.length === 0) {
219
- const ageDays = policy.entries.length === 0 && policy.droppedCount > 0
220
- ? (applyStalePolicy([{ name: memory.name, updatedAt }], {
221
- thresholdDays,
222
- includeStale: true
223
- }).entries[0]?.ageDays ?? 0)
224
- : 0;
225
- printResult(io, fail('project.memories:show', 'MEMORY_STALE', `memory ${name} is stale (age ${ageDays} days > ${thresholdDays} day threshold); pass --include-stale to override`, { name, ageDays, thresholdDays }, [
226
- 'Pass --include-stale to load stale memories; pass --stale-days <N> to override the threshold'
227
- ]), options.json);
228
- process.exitCode = 1;
229
- return;
230
- }
231
- const ageDays = policy.entries[0]?.ageDays ?? 0;
232
- const isStale = policy.entries[0]?.stale ?? false;
233
- const format = options.pretty === true ? 'pretty' : 'compact';
234
- const body = format === 'pretty' ? memory.body : formatMdCompact(memory.body);
235
- printResult(io, ok('project.memories:show', {
236
- name: memory.name,
237
- title: memory.title,
238
- kind: memory.kind,
239
- sourcePath: memory.filePath,
240
- updatedAt,
241
- ageDays,
242
- stale: isStale,
243
- body,
244
- format,
245
- bodyBytes: Buffer.byteLength(body, 'utf8')
246
- }), options.json);
247
- }
248
- catch (error) {
249
- printResult(io, fail('project.memories:show', 'PROJECT_MEMORY_SHOW_FAILED', getErrorMessage(error), { name, projectRoot: options.project }, ['Check the project path and .peaks/memory directory']), options.json);
250
- process.exitCode = 1;
251
- }
252
- });
253
- // --- Read business-knowledge sediment (v2.11.0 Group B — D3) ---
254
- addJsonOption(project
255
- .command('knowledge')
256
- .description('Read .peaks/project-scan/business-knowledge.md (the schema-sedimented concept table). LLM-consumable; use --filter for a concept substring.')
257
- .requiredOption('--project <path>', 'target project root')
258
- .option('--filter <glob>', 'substring filter on the concept name (case-insensitive)')).action(async (options) => {
259
- try {
260
- const knowledge = await readBusinessKnowledge(options.project);
261
- if (knowledge === null) {
262
- printResult(io, ok('project.knowledge', {
263
- exists: false,
264
- projectRoot: options.project,
265
- path: `${options.project}/.peaks/project-scan/business-knowledge.md`
266
- }), options.json);
267
- return;
268
- }
269
- const concepts = options.filter
270
- ? knowledge.concepts.filter((c) => c.concept.toLowerCase().includes(options.filter.toLowerCase()))
271
- : knowledge.concepts;
272
- printResult(io, ok('project.knowledge', {
273
- exists: true,
274
- schemaVersion: knowledge.schemaVersion,
275
- total: knowledge.concepts.length,
276
- matched: concepts.length,
277
- filter: options.filter ?? null,
278
- concepts
279
- }), options.json);
280
- }
281
- catch (error) {
282
- printResult(io, fail('project.knowledge', 'PROJECT_KNOWLEDGE_FAILED', getErrorMessage(error), { projectRoot: options.project }, ['Check the project path and .peaks/project-scan directory']), options.json);
283
- process.exitCode = 1;
284
- }
285
- });
122
+ .option('--kind <kind>', `filter by memory kind (one of: ${KIND_HELP})`)).action((options) => runProjectMemories(io, options));
123
+ registerProjectMemoriesShowCommand(project, io);
124
+ registerProjectKnowledgeCommand(project, io);
286
125
  }
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import { type ProgramIO } from '../cli-helpers.js';
3
+ export declare function registerProjectContextCommand(project: Command, io: ProgramIO): void;