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,189 @@
1
+ // src/cli/commands/web-login-command.ts
2
+ //
3
+ // `peaks web login --profile <name>` — the only path that persists a login.
4
+ // Split out of `web-lifecycle-commands.ts`; the verb name, its options, the
5
+ // gate-first order, the fold notices and every envelope shape are unchanged.
6
+ import { fail, getErrorMessage, ok } from 'peaks-loop-shared/result';
7
+ import { degradedEnvelope } from '../../services/web/web-fallback.js';
8
+ import { isWebDisabled } from '../../services/web/web-install-service.js';
9
+ import { cappedEcho, loginStorageStatePath, resolveProfileName, runHeadedLogin } from '../../services/web/web-login-profile.js';
10
+ import { addJsonOption, printResult } from '../cli-helpers.js';
11
+ /** The `degradedEnvelope` tier a disabled-web refusal reports (tech-doc §5.1). */
12
+ const WEB_DISABLED_TIER = 3;
13
+ /** What a caller can actually do after a refusal or an unclosed login. */
14
+ const LOGIN_NEXT_ACTIONS = [
15
+ 'Re-run `peaks web login --profile <name>` when the user is ready to log in',
16
+ 'Close the headed browser window when the login is finished — closing it is what saves the session'
17
+ ];
18
+ /**
19
+ * The fold, said out loud on the one path that CANNOT fold (S4 repair, code F5 /
20
+ * security S5).
21
+ *
22
+ * The gate is statement #1 (tech-doc §5.1), so on this path the name was never
23
+ * validated and never folded — which is exactly why this refusal must not look
24
+ * like it disagrees with a live run about the profile. It reports what happened
25
+ * (nothing was folded, this is what was typed) rather than implying a canonical
26
+ * name was used, and it claims nothing about whether the name would be accepted.
27
+ * The echo is capped by the same helper the guard uses.
28
+ */
29
+ function gateFoldNotice(rawProfile) {
30
+ if (rawProfile === undefined || rawProfile === rawProfile.toLowerCase()) {
31
+ return [];
32
+ }
33
+ return [
34
+ `--profile ${JSON.stringify(cappedEcho(rawProfile))} was NOT folded: PEAKS_WEB_DISABLED is ` +
35
+ 'checked before the profile name, so this refusal echoes what was typed, not a canonical ' +
36
+ 'profile. A run that gets past the gate lower-cases the name first.'
37
+ ];
38
+ }
39
+ /** The disabled-web refusal, with the fold notice appended when there is one. */
40
+ function webDisabledLoginEnvelope(rawProfile) {
41
+ const gateEnvelope = degradedEnvelope('login', 'PEAKS_WEB_DISABLED=1', WEB_DISABLED_TIER, rawProfile === undefined ? {} : { profile: cappedEcho(rawProfile) });
42
+ return { ...gateEnvelope, warnings: [...gateEnvelope.warnings, ...gateFoldNotice(rawProfile)] };
43
+ }
44
+ function profileRequiredEnvelope() {
45
+ return fail('peaks.web.login', 'WEB_PROFILE_REQUIRED', '`peaks web login` requires --profile <name>: it is the only verb that persists a login, ' +
46
+ 'and there is no default profile — without a name nothing is written', {}, LOGIN_NEXT_ACTIONS);
47
+ }
48
+ /**
49
+ * `resolveProfileName`'s canonical name, or the refusal envelope to print.
50
+ * The helper's own message already begins with the code, and `fail()` puts the
51
+ * code in front of the message again — strip it, so human output does not read
52
+ * `WEB_PROFILE_NAME_INVALID: WEB_PROFILE_NAME_INVALID: …`.
53
+ */
54
+ function resolveLoginProfile(rawProfile) {
55
+ try {
56
+ return { profile: resolveProfileName(rawProfile) };
57
+ }
58
+ catch (error) {
59
+ const detail = getErrorMessage(error).replace(/^WEB_PROFILE_NAME_INVALID:\s*/, '');
60
+ return {
61
+ refusal: fail('peaks.web.login', 'WEB_PROFILE_NAME_INVALID', detail, {}, LOGIN_NEXT_ACTIONS)
62
+ };
63
+ }
64
+ }
65
+ /**
66
+ * The two sides are deliberately not the same value — the left is what the
67
+ * caller TYPED (echoed through `cappedEcho`, since it is still caller input),
68
+ * the right is the canonical name the run uses from here on.
69
+ */
70
+ function loginFoldWarnings(rawProfile, profile) {
71
+ return rawProfile === profile
72
+ ? []
73
+ : [`--profile ${JSON.stringify(cappedEcho(rawProfile))} resolved to the profile "${profile}"`];
74
+ }
75
+ /** The headed-browser instructions the user reads while the login is open. */
76
+ function announceHeadedLogin(io, profile) {
77
+ return () => {
78
+ io.stderr([
79
+ `peaks web login: a headed browser is open for profile "${profile}" — log in there yourself.`,
80
+ 'Close the browser window when you are done: that is what saves the session, to ' +
81
+ `${loginStorageStatePath(profile)}.`,
82
+ 'The session is captured while the window is open, so the saved state can be up to a ' +
83
+ 'second older than what you see — finish logging in before you close it.'
84
+ ].join('\n'));
85
+ };
86
+ }
87
+ /**
88
+ * S1's F1. This is the ONLY path on which the runner returns `ok: false` AND a
89
+ * warning (a login whose context never opened and whose headed browser then
90
+ * refused to close — a browser nothing can then stop, because `stop` is
91
+ * daemon-scoped). `fail()` hard-codes `warnings: []`, so the warning is spread
92
+ * back over it, the shape `degradedEnvelope` uses.
93
+ */
94
+ function loginFailedEnvelope(command, outcome, foldWarnings) {
95
+ return {
96
+ ...fail(command, outcome.code, outcome.message, {}, LOGIN_NEXT_ACTIONS),
97
+ warnings: [...foldWarnings, ...outcome.warnings]
98
+ };
99
+ }
100
+ /**
101
+ * The success envelope — counts, never the values: the file holds live session
102
+ * cookies and this envelope reaches a terminal (and a transcript).
103
+ *
104
+ * R5: a capture that was written but could not be read back is `ok` — the file
105
+ * did land, so it is not a failure — but it is not a clean success either. The
106
+ * code is what an ok-only consumer cannot miss.
107
+ */
108
+ function loginResultEnvelope(command, outcome, foldWarnings) {
109
+ const envelope = ok(command, {
110
+ profile: outcome.profile,
111
+ storageStatePath: outcome.storageStatePath,
112
+ bytes: outcome.bytes,
113
+ cookies: outcome.cookies,
114
+ origins: outcome.origins
115
+ }, [...foldWarnings, ...outcome.warnings]);
116
+ return outcome.code === '' ? envelope : { ...envelope, code: outcome.code };
117
+ }
118
+ /**
119
+ * The catch-all failure envelope. A run that reached `resolveProfileName` knows
120
+ * the canonical name, so a failure before the browser was even up reports the
121
+ * fold like every other path (S4 repair, code F5 / security S5).
122
+ */
123
+ function loginThrewEnvelope(command, error, foldWarnings) {
124
+ return {
125
+ ...fail(command, 'WEB_LOGIN_FAILED', `peaks web login failed: ${getErrorMessage(error)}`, {}, LOGIN_NEXT_ACTIONS),
126
+ warnings: [...foldWarnings]
127
+ };
128
+ }
129
+ /**
130
+ * `peaks web login --profile <name>` — the only path that persists a login
131
+ * (design §2/§5, PRD R7).
132
+ *
133
+ * `--profile` is enforced HERE rather than with commander's `requiredOption`,
134
+ * because `requiredOption` refuses before this handler runs — and then the
135
+ * `PEAKS_WEB_DISABLED` gate would no longer be statement #1 (tech-doc §5.1,
136
+ * AC5). A profile-less login refuses without touching the profile root: no
137
+ * directory, no storage state, no browser.
138
+ */
139
+ export async function runWebLogin(io, asJson, rawProfile) {
140
+ const command = 'peaks.web.login';
141
+ // Declared out here so the CATCH can report it too (S4 repair, security S5 /
142
+ // code F3): a launch failure happens AFTER the name was resolved, so a run
143
+ // that dies on `WEB_LAUNCH_FAILED` knows the canonical name just as well as
144
+ // one that succeeds, and must not be the one path where the fold is silent.
145
+ let foldWarnings = [];
146
+ try {
147
+ if (isWebDisabled(process.env)) {
148
+ printResult(io, webDisabledLoginEnvelope(rawProfile), asJson);
149
+ process.exitCode = 1;
150
+ return;
151
+ }
152
+ if (rawProfile === undefined || rawProfile === '') {
153
+ printResult(io, profileRequiredEnvelope(), asJson);
154
+ process.exitCode = 1;
155
+ return;
156
+ }
157
+ const resolved = resolveLoginProfile(rawProfile);
158
+ if ('refusal' in resolved) {
159
+ printResult(io, resolved.refusal, asJson);
160
+ process.exitCode = 1;
161
+ return;
162
+ }
163
+ const profile = resolved.profile;
164
+ foldWarnings = loginFoldWarnings(rawProfile, profile);
165
+ const outcome = await runHeadedLogin({
166
+ profile,
167
+ announce: announceHeadedLogin(io, profile)
168
+ });
169
+ if (!outcome.ok) {
170
+ printResult(io, loginFailedEnvelope(command, outcome, foldWarnings), asJson);
171
+ process.exitCode = 1;
172
+ return;
173
+ }
174
+ printResult(io, loginResultEnvelope(command, outcome, foldWarnings), asJson);
175
+ }
176
+ catch (error) {
177
+ printResult(io, loginThrewEnvelope(command, error, foldWarnings), asJson);
178
+ process.exitCode = 1;
179
+ }
180
+ }
181
+ export function registerWebLoginCommand(web, io) {
182
+ addJsonOption(web
183
+ .command('login')
184
+ .description('Open a HEADED browser so the user can log in themselves, then persist that session to ' +
185
+ '~/.peaks/web-profiles/<name>/storageState.json. Run it only when the user asks for a ' +
186
+ 'persistent login: it writes live session cookies to disk. --profile is required, and ' +
187
+ 'without it nothing is persisted.')
188
+ .option('--profile <name>', 'the login profile to persist (required; [a-z0-9._-], 1-64 chars — upper case folds to lower)')).action((options) => runWebLogin(io, options.json === true, options.profile));
189
+ }
@@ -0,0 +1,22 @@
1
+ import type { ResultEnvelope } from 'peaks-loop-shared/result';
2
+ import type { WebOp } from '../../services/web/web-protocol.js';
3
+ import { type ProgramIO } from '../cli-helpers.js';
4
+ interface WrappedPayload {
5
+ readonly data: Record<string, unknown>;
6
+ /** Raw human-mode stdout, or `null` for verbs whose output is not page content. */
7
+ readonly human: string | null;
8
+ }
9
+ /**
10
+ * Wrap the page-controlled part of each verb's payload (AC4 / §6.2) and pick
11
+ * the bytes that human mode prints verbatim. `shot` is unwrapped: its path and
12
+ * byte count are ours, not the page's.
13
+ */
14
+ export declare function wrapPageData(op: WebOp, raw: Record<string, unknown>): WrappedPayload;
15
+ /**
16
+ * Print the envelope. Failures and `--json` go through `printResult`; a
17
+ * successful wrapped op in human mode prints its payload RAW, because the
18
+ * UNTRUSTED delimiters must stay on their own lines (AC4) and AC2 measures the
19
+ * byte count of exactly this stdout.
20
+ */
21
+ export declare function emit<T>(io: ProgramIO, result: ResultEnvelope<T>, asJson: boolean, humanPayload: string | null): void;
22
+ export {};
@@ -0,0 +1,89 @@
1
+ // src/cli/commands/web-op-payload.ts
2
+ //
3
+ // How one `peaks web` op's daemon payload becomes stdout: the per-verb wrap of
4
+ // the page-controlled fields, the human-mode renderer for `metrics`, and the
5
+ // printer that keeps the UNTRUSTED delimiters on their own lines. Split out of
6
+ // `web-commands.ts`; every branch and every byte cap is unchanged.
7
+ import { capText, MAX_TEXT_BYTES } from '../../services/web/bounded-output.js';
8
+ import { wrapUntrusted, WRAPPED_OPS } from '../../services/web/untrusted-envelope.js';
9
+ import { printResult } from '../cli-helpers.js';
10
+ import { count, text } from './web-command-shared.js';
11
+ /**
12
+ * Wrap the page-controlled part of each verb's payload (AC4 / §6.2) and pick
13
+ * the bytes that human mode prints verbatim. `shot` is unwrapped: its path and
14
+ * byte count are ours, not the page's.
15
+ */
16
+ export function wrapPageData(op, raw) {
17
+ if (!WRAPPED_OPS.has(op)) {
18
+ return { data: raw, human: null };
19
+ }
20
+ switch (op) {
21
+ case 'open': {
22
+ const title = wrapUntrusted(text(raw['title']));
23
+ return { data: { url: wrapUntrusted(text(raw['url'])), title }, human: title };
24
+ }
25
+ case 'text': {
26
+ const value = wrapUntrusted(text(raw['text']));
27
+ return {
28
+ data: {
29
+ text: value,
30
+ truncated: raw['truncated'] === true,
31
+ droppedBytes: count(raw['droppedBytes'])
32
+ },
33
+ human: value
34
+ };
35
+ }
36
+ case 'snap': {
37
+ const snapshot = wrapUntrusted(text(raw['snapshot']));
38
+ return {
39
+ data: {
40
+ snapshot,
41
+ droppedNodes: count(raw['droppedNodes']),
42
+ depthCapped: raw['depthCapped'] === true,
43
+ nodeCapped: raw['nodeCapped'] === true,
44
+ truncated: raw['truncated'] === true,
45
+ droppedBytes: count(raw['droppedBytes'])
46
+ },
47
+ human: snapshot
48
+ };
49
+ }
50
+ case 'click': {
51
+ const result = wrapUntrusted(text(raw['result']));
52
+ return { data: { result }, human: result };
53
+ }
54
+ case 'metrics': {
55
+ // The rendered lines come from the daemon's payload, so they are capped
56
+ // here as well as at the producer: this is the boundary that reaches
57
+ // stdout, and the ceiling must hold whatever the daemon sends.
58
+ const metrics = wrapUntrusted(capText(renderMetrics(raw), MAX_TEXT_BYTES).text);
59
+ return { data: { metrics }, human: metrics };
60
+ }
61
+ default:
62
+ return { data: raw, human: null };
63
+ }
64
+ }
65
+ /**
66
+ * Print the envelope. Failures and `--json` go through `printResult`; a
67
+ * successful wrapped op in human mode prints its payload RAW, because the
68
+ * UNTRUSTED delimiters must stay on their own lines (AC4) and AC2 measures the
69
+ * byte count of exactly this stdout.
70
+ */
71
+ export function emit(io, result, asJson, humanPayload) {
72
+ if (!result.ok || asJson || humanPayload === null) {
73
+ printResult(io, result, asJson);
74
+ return;
75
+ }
76
+ io.stdout(humanPayload);
77
+ for (const warning of result.warnings) {
78
+ io.stderr(`warning: ${warning}`);
79
+ }
80
+ }
81
+ /** `available: false` is reported as such — never as fabricated zeros (C4). */
82
+ function renderMetrics(raw) {
83
+ if (raw['available'] !== true) {
84
+ return `available: false\nreason: ${text(raw['reason']) || 'unavailable'}`;
85
+ }
86
+ const values = (raw['values'] ?? {});
87
+ const lines = Object.entries(values).map(([key, value]) => `${key}: ${String(value)}`);
88
+ return lines.length > 0 ? lines.join('\n') : 'available: true';
89
+ }
@@ -0,0 +1,37 @@
1
+ import { fail } from 'peaks-loop-shared/result';
2
+ import type { WebOp } from '../../services/web/web-protocol.js';
3
+ /**
4
+ * What a caller can do after a refused `--profile` — the same sentence `login`
5
+ * gives, because it is the same mistake and the same verb fixes it.
6
+ */
7
+ export declare const PROFILE_NEXT_ACTIONS: string[];
8
+ /**
9
+ * The resolver's own message begins with the code, and `fail()` puts the code in
10
+ * front of the message again — strip it, so human output does not read
11
+ * `WEB_PROFILE_NAME_INVALID: WEB_PROFILE_NAME_INVALID: …` (the `login` verb does
12
+ * the same).
13
+ */
14
+ export declare function profileRefusal(error: unknown): string;
15
+ /** Every daemon warning, capped and wrapped. Empty entries are dropped. */
16
+ export declare function wrapDiagnostics(values: readonly string[]): string[];
17
+ /**
18
+ * Our own static sentence, then the daemon's own words as a wrapped, capped
19
+ * block. The daemon's `nextActions` are folded into that block rather than
20
+ * forwarded: `printResult` prints `nextActions` to STDOUT as `next: …`, the
21
+ * channel the notice calls instruction, and the daemon's text is not ours to
22
+ * promote there.
23
+ */
24
+ export declare function failureMessage(op: WebOp, message: unknown, nextActions: readonly string[]): string;
25
+ /**
26
+ * A daemon-supplied `code` is printed on the envelope's first line, so only a
27
+ * protocol-shaped identifier is accepted; anything else falls back to ours.
28
+ */
29
+ export declare function safeDaemonCode(value: unknown): string;
30
+ /** The unusable-daemon envelope: a named code, or the generic op failure. */
31
+ export declare function daemonFailureEnvelope(input: {
32
+ readonly op: WebOp;
33
+ readonly command: string;
34
+ readonly code: string;
35
+ readonly message: unknown;
36
+ readonly nextActions: readonly string[];
37
+ }): ReturnType<typeof fail>;
@@ -0,0 +1,73 @@
1
+ // src/cli/commands/web-op-refusals.ts
2
+ //
3
+ // How a `peaks web` op refuses: the diagnostic channel, the daemon failure
4
+ // envelope, and the refused-`--profile` pair of sentences. Split out of
5
+ // `web-commands.ts`; every wrap, every cap and every sentence is unchanged.
6
+ import { fail } from 'peaks-loop-shared/result';
7
+ import { capText, MAX_TEXT_BYTES } from '../../services/web/bounded-output.js';
8
+ import { wrapUntrusted } from '../../services/web/untrusted-envelope.js';
9
+ import { getErrorMessage } from '../cli-helpers.js';
10
+ import { text } from './web-command-shared.js';
11
+ /**
12
+ * What a caller can do after a refused `--profile` — the same sentence `login`
13
+ * gives, because it is the same mistake and the same verb fixes it.
14
+ */
15
+ export const PROFILE_NEXT_ACTIONS = [
16
+ 'Re-run with a name matching [a-z0-9._-], 1-64 chars',
17
+ 'Or run `peaks web login --profile <name>` to create that profile'
18
+ ];
19
+ /**
20
+ * The resolver's own message begins with the code, and `fail()` puts the code in
21
+ * front of the message again — strip it, so human output does not read
22
+ * `WEB_PROFILE_NAME_INVALID: WEB_PROFILE_NAME_INVALID: …` (the `login` verb does
23
+ * the same).
24
+ */
25
+ export function profileRefusal(error) {
26
+ return getErrorMessage(error).replace(/^WEB_PROFILE_NAME_INVALID:\s*/, '');
27
+ }
28
+ /**
29
+ * A daemon- or page-derived diagnostic is DATA, never an instruction: it is
30
+ * byte-capped and wrapped before it can reach `message` or `warnings` (AC4 /
31
+ * R4 — the envelope must cover the diagnostic channel, not only `data`).
32
+ *
33
+ * This matters because Playwright's own error messages embed the matched
34
+ * elements' HTML, so a page with two elements matching a selector can put
35
+ * arbitrary text on a channel the CLI would otherwise print verbatim to stdout.
36
+ */
37
+ function wrapDiagnostic(raw) {
38
+ const capped = capText(text(raw), MAX_TEXT_BYTES).text;
39
+ return capped === '' ? '' : wrapUntrusted(capped);
40
+ }
41
+ /** Every daemon warning, capped and wrapped. Empty entries are dropped. */
42
+ export function wrapDiagnostics(values) {
43
+ return values.map((value) => wrapDiagnostic(value)).filter((value) => value !== '');
44
+ }
45
+ /**
46
+ * Our own static sentence, then the daemon's own words as a wrapped, capped
47
+ * block. The daemon's `nextActions` are folded into that block rather than
48
+ * forwarded: `printResult` prints `nextActions` to STDOUT as `next: …`, the
49
+ * channel the notice calls instruction, and the daemon's text is not ours to
50
+ * promote there.
51
+ */
52
+ export function failureMessage(op, message, nextActions) {
53
+ const detail = [text(message), ...nextActions.map((action) => text(action))]
54
+ .filter((line) => line !== '')
55
+ .join('\n');
56
+ const wrapped = wrapDiagnostic(detail);
57
+ return wrapped === ''
58
+ ? `peaks web ${op} failed in the daemon`
59
+ : `peaks web ${op} failed in the daemon\n${wrapped}`;
60
+ }
61
+ /**
62
+ * A daemon-supplied `code` is printed on the envelope's first line, so only a
63
+ * protocol-shaped identifier is accepted; anything else falls back to ours.
64
+ */
65
+ export function safeDaemonCode(value) {
66
+ return typeof value === 'string' && /^[A-Z][A-Z0-9_]{0,63}$/.test(value)
67
+ ? value
68
+ : 'WEB_OP_FAILED';
69
+ }
70
+ /** The unusable-daemon envelope: a named code, or the generic op failure. */
71
+ export function daemonFailureEnvelope(input) {
72
+ return fail(input.command, input.code, failureMessage(input.op, input.message, input.nextActions), {}, []);
73
+ }
@@ -0,0 +1,14 @@
1
+ import type { WebOp } from '../../services/web/web-protocol.js';
2
+ import { type ProgramIO } from '../cli-helpers.js';
3
+ /**
4
+ * Resolve the session, ensure a daemon, invoke one op, and emit exactly one
5
+ * envelope. `WRAPPED_OPS` is applied here, after the byte caps the daemon
6
+ * already imposed, so the UNTRUSTED markers are never themselves truncated.
7
+ *
8
+ * The `PEAKS_WEB_DISABLED` gate is the FIRST thing that happens (tech-doc §5.1
9
+ * step 1, AC5). Before the session lookup, so a project with no binding still
10
+ * gets `WEB_DISABLED` rather than `NO_SESSION`; before `ensureDaemon`, so
11
+ * nothing is spawned and no lock is taken; and therefore before anything that
12
+ * could touch the browser cache.
13
+ */
14
+ export declare function runWebOp(io: ProgramIO, op: WebOp, args: Record<string, unknown>, asJson: boolean): Promise<void>;
@@ -0,0 +1,166 @@
1
+ // src/cli/commands/web-op-runner.ts
2
+ //
3
+ // `runWebOp` — resolve the session, ensure a daemon, invoke one op, and emit
4
+ // exactly one envelope. Split out of `web-commands.ts`, where this one function
5
+ // had reached 117 lines; the gates, their order and every envelope are
6
+ // unchanged.
7
+ import { fail, getErrorMessage, ok } from 'peaks-loop-shared/result';
8
+ import { ensureDaemon } from '../../services/web/daemon-supervisor.js';
9
+ import { degradedEnvelope } from '../../services/web/web-fallback.js';
10
+ import { isWebDisabled } from '../../services/web/web-install-service.js';
11
+ import { cappedEcho, resolveProfileName } from '../../services/web/web-login-profile.js';
12
+ import { WebDaemonClient } from '../../services/web/web-client.js';
13
+ import { printResult, redactSensitiveErrorMessage } from '../cli-helpers.js';
14
+ import { noSession, resolveSession } from './web-command-shared.js';
15
+ import { emit, wrapPageData } from './web-op-payload.js';
16
+ import { daemonFailureEnvelope, PROFILE_NEXT_ACTIONS, profileRefusal, safeDaemonCode, wrapDiagnostics } from './web-op-refusals.js';
17
+ /** A browser op is user-visible latency; 30 s is generous but bounded. */
18
+ const OP_TIMEOUT_MS = 30_000;
19
+ /**
20
+ * Resolve the session, ensure a daemon, invoke one op, and emit exactly one
21
+ * envelope. `WRAPPED_OPS` is applied here, after the byte caps the daemon
22
+ * already imposed, so the UNTRUSTED markers are never themselves truncated.
23
+ *
24
+ * The `PEAKS_WEB_DISABLED` gate is the FIRST thing that happens (tech-doc §5.1
25
+ * step 1, AC5). Before the session lookup, so a project with no binding still
26
+ * gets `WEB_DISABLED` rather than `NO_SESSION`; before `ensureDaemon`, so
27
+ * nothing is spawned and no lock is taken; and therefore before anything that
28
+ * could touch the browser cache.
29
+ */
30
+ export async function runWebOp(io, op, args, asJson) {
31
+ const command = `peaks.web.${op}`;
32
+ // Declared outside the try so the CATCH reports the fold too (S4's F5/S5 rule
33
+ // for `login`, applied here): a run that dies after the name was resolved
34
+ // knows the canonical name just as well as a successful one.
35
+ let foldWarnings = [];
36
+ try {
37
+ if (isWebDisabled(process.env)) {
38
+ printResult(io, webDisabledEnvelope(op, args), asJson);
39
+ process.exitCode = 1;
40
+ return;
41
+ }
42
+ const profile = resolveWebProfile(command, args);
43
+ foldWarnings = profile.warnings;
44
+ if (profile.envelope !== null) {
45
+ printResult(io, profile.envelope, asJson);
46
+ process.exitCode = 1;
47
+ return;
48
+ }
49
+ const session = resolveSession();
50
+ if (session === null) {
51
+ printResult(io, withFold(noSession(command), foldWarnings), asJson);
52
+ process.exitCode = 1;
53
+ return;
54
+ }
55
+ const response = await callWebDaemon(op, profile.args, session.projectRoot, session.sessionId);
56
+ if (!response.ok || response.data === null) {
57
+ const refusal = daemonRefusal({ op, command, response, opArgs: profile.args, foldWarnings });
58
+ printResult(io, refusal, asJson);
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+ const wrapped = wrapPageData(op, response.data);
63
+ emit(io, ok(command, wrapped.data, [...foldWarnings, ...wrapDiagnostics(response.warnings)]), asJson, wrapped.human);
64
+ }
65
+ catch (error) {
66
+ printResult(io, webOpFailure(op, command, error, foldWarnings), asJson);
67
+ process.exitCode = 1;
68
+ }
69
+ }
70
+ /** The `WEB_OP_FAILED` envelope for a throw anywhere in the run, fold included. */
71
+ function webOpFailure(op, command, error, foldWarnings) {
72
+ return withFold(daemonFailureEnvelope({
73
+ op,
74
+ command,
75
+ code: 'WEB_OP_FAILED',
76
+ message: redactSensitiveErrorMessage(getErrorMessage(error)),
77
+ nextActions: []
78
+ }), foldWarnings);
79
+ }
80
+ /**
81
+ * The `PEAKS_WEB_DISABLED` gate's envelope. The gate is statement #1, so a
82
+ * `--profile` has NOT been through the resolver yet and is still unbounded
83
+ * caller text; `degradedEnvelope` carries every string arg into the payload, so
84
+ * it is capped here — the same cap the `login` gate applies, for the same reason
85
+ * (S1's bounded output is a property of the envelope, not only of stdout).
86
+ */
87
+ function webDisabledEnvelope(op, args) {
88
+ return degradedEnvelope(op, 'PEAKS_WEB_DISABLED=1', 3, cappedProfileArg(args));
89
+ }
90
+ /**
91
+ * The unusable-daemon envelope. The daemon no longer downloads (R3), so "the
92
+ * browser is not installed" arrives as a refusal: it is AC5's tier-3 branch,
93
+ * not an opaque op failure — the caller must be handed the same envelope (MCP
94
+ * tool, install command, screenshot consequence) that the gate produces.
95
+ */
96
+ function daemonRefusal(input) {
97
+ const code = safeDaemonCode(input.response.code);
98
+ if (code === 'WEB_INSTALL_REQUIRED') {
99
+ const reason = `WEB_INSTALL_REQUIRED: ${input.response.message ?? ''}`;
100
+ return withFold(degradedEnvelope(input.op, reason, 3, input.opArgs), input.foldWarnings);
101
+ }
102
+ return withFold(daemonFailureEnvelope({
103
+ op: input.op,
104
+ command: input.command,
105
+ code,
106
+ message: input.response.message,
107
+ nextActions: input.response.nextActions
108
+ }), input.foldWarnings);
109
+ }
110
+ /** Prepend the fold notice to an envelope's warnings; never rewrite them away. */
111
+ function withFold(envelope, warnings) {
112
+ return warnings.length === 0
113
+ ? envelope
114
+ : { ...envelope, warnings: [...warnings, ...envelope.warnings] };
115
+ }
116
+ /** The `PEAKS_WEB_DISABLED` gate's args: a `--profile` still raw, so still capped. */
117
+ function cappedProfileArg(args) {
118
+ return typeof args['profile'] === 'string'
119
+ ? { ...args, profile: cappedEcho(args['profile']) }
120
+ : args;
121
+ }
122
+ /**
123
+ * A caller-supplied `--profile` is validated HERE, before anything is sent, and
124
+ * the daemon runs the SAME resolver again on the payload it receives (a value
125
+ * off the wire is not trusted). `resolveProfileName` folds to lower case, so the
126
+ * canonical name is what travels, and the fold is reported rather than silent —
127
+ * the contract `login` honours.
128
+ */
129
+ function resolveWebProfile(command, args) {
130
+ if (typeof args['profile'] !== 'string') {
131
+ return { args, warnings: [], envelope: null };
132
+ }
133
+ const typed = args['profile'];
134
+ let profile;
135
+ try {
136
+ profile = resolveProfileName(typed);
137
+ }
138
+ catch (error) {
139
+ return {
140
+ args,
141
+ warnings: [],
142
+ envelope: fail(command, 'WEB_PROFILE_NAME_INVALID', profileRefusal(error), {}, PROFILE_NEXT_ACTIONS)
143
+ };
144
+ }
145
+ const warnings = profile === typed
146
+ ? []
147
+ : [`--profile ${JSON.stringify(cappedEcho(typed))} resolved to the profile "${profile}"`];
148
+ return { args: { ...args, profile }, warnings, envelope: null };
149
+ }
150
+ /**
151
+ * Ensure the daemon and invoke one op. The daemon reads `projectRoot` back from
152
+ * `daemon.json` — the record it itself wrote — and that round-trip is the only
153
+ * path that survives the macOS `/var` <-> `/private/var` symlink: the writer's
154
+ * prefix may not match `projectRoot` resolved from `process.cwd()` (the kernel
155
+ * resolves symlinks on `chdir`), and the integration test asserts on that exact
156
+ * round-tripped value.
157
+ */
158
+ async function callWebDaemon(op, args, projectRoot, sessionId) {
159
+ const info = await ensureDaemon(projectRoot, sessionId);
160
+ return new WebDaemonClient(info).call(op, {
161
+ ...args,
162
+ dispatchId: process.env['PEAKS_DISPATCH_ID'] ?? 'current',
163
+ projectRoot: info.projectRoot,
164
+ sessionId
165
+ }, OP_TIMEOUT_MS);
166
+ }
@@ -0,0 +1,4 @@
1
+ import type { Command } from 'commander';
2
+ import { type ProgramIO } from '../cli-helpers.js';
3
+ export declare function runWebStatus(io: ProgramIO, asJson: boolean): Promise<void>;
4
+ export declare function registerWebStatusCommand(web: Command, io: ProgramIO): void;
@@ -0,0 +1,32 @@
1
+ // src/cli/commands/web-status-command.ts
2
+ //
3
+ // `peaks web status` — this session's daemon instances (live / orphaned /
4
+ // stale), read from the filesystem and the loopback port, never from the daemon.
5
+ // Split out of `web-lifecycle-commands.ts`; the verb name, its options and the
6
+ // envelope shape are unchanged.
7
+ import { fail, getErrorMessage, ok } from 'peaks-loop-shared/result';
8
+ import { buildStatusReport } from '../../services/web/web-status-report.js';
9
+ import { addJsonOption, printResult } from '../cli-helpers.js';
10
+ import { noSession, resolveSession } from './web-command-shared.js';
11
+ export async function runWebStatus(io, asJson) {
12
+ const command = 'peaks.web.status';
13
+ try {
14
+ const session = resolveSession();
15
+ if (session === null) {
16
+ printResult(io, noSession(command), asJson);
17
+ process.exitCode = 1;
18
+ return;
19
+ }
20
+ printResult(io, ok(command, await buildStatusReport(session.projectRoot, session.sessionId)), asJson);
21
+ }
22
+ catch (error) {
23
+ printResult(io, fail(command, 'WEB_STATUS_FAILED', `peaks web status failed: ${getErrorMessage(error)}`, {}, []), asJson);
24
+ process.exitCode = 1;
25
+ }
26
+ }
27
+ export function registerWebStatusCommand(web, io) {
28
+ addJsonOption(web
29
+ .command('status')
30
+ .description("Report this session's web daemon instances (live / orphaned / stale). Works with no " +
31
+ 'daemon running and never starts one.')).action((options) => runWebStatus(io, options.json === true));
32
+ }
@@ -0,0 +1,10 @@
1
+ import type { Command } from 'commander';
2
+ import { type ProgramIO } from '../cli-helpers.js';
3
+ /**
4
+ * Stop the daemon and clear its records. `stopped` counts the daemons whose
5
+ * process is confirmed GONE by return — not merely the ones we signalled — so a
6
+ * caller that checks the process table right after this returns is not racing
7
+ * the teardown (AC6).
8
+ */
9
+ export declare function runWebStop(io: ProgramIO, asJson: boolean): Promise<void>;
10
+ export declare function registerWebStopCommand(web: Command, io: ProgramIO): void;