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,19 @@
1
+ import type { ModelProviderConfig, PeaksConfig } from './config-types.js';
2
+ export declare function isSensitiveConfigPath(path: string): boolean;
3
+ export declare function isLegacyConfigKey(path: string): boolean;
4
+ export declare function isProviderConfigPath(path: string): boolean;
5
+ export declare function isSecretKey(key: string): boolean;
6
+ export declare function isProviderBaseUrlPath(path: string): boolean;
7
+ export declare function validateProviderBaseUrl(value: unknown): void;
8
+ export declare function getProxyUrlCandidate(key: string, value: unknown): unknown;
9
+ export declare function isProxyConfigPath(path: string): boolean;
10
+ export declare function validateModelProviderConfig(providers: ModelProviderConfig): void;
11
+ export declare function validateProviderConfig(partial: Partial<PeaksConfig>): void;
12
+ export declare function isValidProxyUrl(value: string): boolean;
13
+ export declare function validateProxyUrl(value: unknown): void;
14
+ export declare function validateProxyConfig(partial: Partial<PeaksConfig>): void;
15
+ export declare function containsSensitiveConfigValue(value: unknown): boolean;
16
+ export type RedactedConfigValue = string | number | boolean | null | RedactedConfigValue[] | {
17
+ [key: string]: RedactedConfigValue;
18
+ };
19
+ export declare function redactConfigSecrets(value: unknown, path?: string): RedactedConfigValue;
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Config key/URL validators and the secret-redaction surface.
3
+ *
4
+ * Split out of `config-service.ts` (file-size cap campaign). The service
5
+ * re-exports every name declared here, so existing importers keep using
6
+ * `./config-service.js` unchanged.
7
+ */
8
+ import { isRecord } from './config-primitives.js';
9
+ export function isSensitiveConfigPath(path) {
10
+ const normalized = path.toLowerCase().replace(/[^a-z0-9]/g, '');
11
+ return (normalized.includes('apikey') ||
12
+ normalized.includes('accesskey') ||
13
+ normalized.includes('privatekey') ||
14
+ normalized.includes('token') ||
15
+ normalized.includes('secret') ||
16
+ normalized.includes('password') ||
17
+ normalized.includes('bearer') ||
18
+ normalized.includes('credential') ||
19
+ normalized.includes('auth'));
20
+ }
21
+ /**
22
+ * 2.0.1 slim-config contract: `~/.peaks/config.json` only stores
23
+ * `version` + `ocr.llm.*` placeholders. The 1.x → 2.0 migration
24
+ * moved per-project fields (`language`, `model`, `economyMode`,
25
+ * `swarmMode`) to `<project>/.peaks/preferences.json` (per spec
26
+ * §10.4). `setConfig` rejects writes to those keys and points the
27
+ * user to the preferences path; tokens / providers / proxy still
28
+ * live in `~/.peaks/config.json` (the loader is tolerant of them
29
+ * but does not synthesise defaults for them anymore).
30
+ */
31
+ const LEGACY_CONFIG_KEYS = new Set([
32
+ 'language',
33
+ 'model',
34
+ 'economyMode',
35
+ 'swarmMode'
36
+ ]);
37
+ export function isLegacyConfigKey(path) {
38
+ const topLevel = path.split(/[.[].*/, 1)[0] ?? '';
39
+ return LEGACY_CONFIG_KEYS.has(topLevel);
40
+ }
41
+ export function isProviderConfigPath(path) {
42
+ return path === 'providers' || path.startsWith('providers.');
43
+ }
44
+ export function isSecretKey(key) {
45
+ return isSensitiveConfigPath(key);
46
+ }
47
+ function sanitizeBaseUrlForDisplay(value) {
48
+ try {
49
+ const url = new URL(value);
50
+ url.username = '';
51
+ url.password = '';
52
+ url.search = '';
53
+ url.hash = '';
54
+ return url.toString();
55
+ }
56
+ catch {
57
+ return '[invalid-url-redacted]';
58
+ }
59
+ }
60
+ export function isProviderBaseUrlPath(path) {
61
+ return /^providers\.[^.]+\.baseUrl$/.test(path);
62
+ }
63
+ function isValidProviderBaseUrl(value) {
64
+ try {
65
+ const url = new URL(value);
66
+ return (url.protocol === 'https:' &&
67
+ url.username.length === 0 &&
68
+ url.password.length === 0 &&
69
+ url.search.length === 0 &&
70
+ url.hash.length === 0);
71
+ }
72
+ catch {
73
+ return false;
74
+ }
75
+ }
76
+ export function validateProviderBaseUrl(value) {
77
+ if (value !== undefined && (typeof value !== 'string' || !isValidProviderBaseUrl(value))) {
78
+ throw new Error('Provider base URL must be HTTPS without embedded credentials, query, or fragment');
79
+ }
80
+ }
81
+ export function getProxyUrlCandidate(key, value) {
82
+ if (key === 'proxy.httpProxy') {
83
+ return value;
84
+ }
85
+ if (key === 'proxy' && isRecord(value)) {
86
+ return value.httpProxy;
87
+ }
88
+ return undefined;
89
+ }
90
+ export function isProxyConfigPath(path) {
91
+ return path === 'proxy' || path.startsWith('proxy.');
92
+ }
93
+ export function validateModelProviderConfig(providers) {
94
+ for (const provider of Object.values(providers)) {
95
+ validateProviderBaseUrl(provider?.baseUrl);
96
+ }
97
+ }
98
+ export function validateProviderConfig(partial) {
99
+ validateModelProviderConfig(partial.providers ?? {});
100
+ }
101
+ export function isValidProxyUrl(value) {
102
+ try {
103
+ const url = new URL(value);
104
+ return ((url.protocol === 'http:' || url.protocol === 'https:') &&
105
+ url.username.length === 0 &&
106
+ url.password.length === 0 &&
107
+ url.pathname === '/' &&
108
+ url.search.length === 0 &&
109
+ url.hash.length === 0);
110
+ }
111
+ catch {
112
+ return false;
113
+ }
114
+ }
115
+ export function validateProxyUrl(value) {
116
+ if (value !== undefined && (typeof value !== 'string' || !isValidProxyUrl(value))) {
117
+ throw new Error('Proxy URL must be an HTTP or HTTPS URL without embedded credentials');
118
+ }
119
+ }
120
+ export function validateProxyConfig(partial) {
121
+ validateProxyUrl(partial.proxy?.httpProxy);
122
+ }
123
+ export function containsSensitiveConfigValue(value) {
124
+ if (Array.isArray(value)) {
125
+ return value.some(containsSensitiveConfigValue);
126
+ }
127
+ if (value === null || typeof value !== 'object') {
128
+ return false;
129
+ }
130
+ return Object.entries(value).some(([key, entry]) => isSecretKey(key) || containsSensitiveConfigValue(entry));
131
+ }
132
+ export function redactConfigSecrets(value, path = '') {
133
+ if (Array.isArray(value)) {
134
+ return value.map((item, index) => redactConfigSecrets(item, `${path}[${index}]`));
135
+ }
136
+ if (value === null || typeof value !== 'object') {
137
+ if (isProviderBaseUrlPath(path) && typeof value === 'string') {
138
+ return sanitizeBaseUrlForDisplay(value);
139
+ }
140
+ return value;
141
+ }
142
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => {
143
+ const nextPath = path ? `${path}.${key}` : key;
144
+ if (isSecretKey(key)) {
145
+ return [key, '***'];
146
+ }
147
+ if (isProviderBaseUrlPath(nextPath) && typeof entry === 'string') {
148
+ return [key, sanitizeBaseUrlForDisplay(entry)];
149
+ }
150
+ return [key, redactConfigSecrets(entry, nextPath)];
151
+ }));
152
+ }
@@ -0,0 +1,10 @@
1
+ import type { ConfigLayer, WorkspaceConfig } from './config-types.js';
2
+ export declare function getWorkspaceConfig(workspaceId: string, _projectRoot?: string | null): WorkspaceConfig | null;
3
+ export declare function addWorkspace(workspace: WorkspaceConfig, layer?: ConfigLayer): void;
4
+ export declare function removeWorkspace(workspaceId: string, layer?: ConfigLayer): boolean;
5
+ export declare function setCurrentWorkspace(workspaceId: string, layer?: ConfigLayer): boolean;
6
+ export declare function getCurrentWorkspaceConfig(): WorkspaceConfig | null;
7
+ export declare function getWorkspaceConfigForPath(path?: string): WorkspaceConfig | null;
8
+ export declare function ensureWorkspaceConfigForPath(path?: string): WorkspaceConfig | null;
9
+ export declare function getWorkspaceConfigForCurrentPath(): WorkspaceConfig | null;
10
+ export declare function ensureWorkspaceConfigForCurrentPath(): WorkspaceConfig | null;
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Workspace registry: the raw `workspaces` / `currentWorkspace` fields and the artifact marker.
3
+ *
4
+ * Split out of `config-service.ts` (file-size cap campaign). The service
5
+ * re-exports every name declared here, so existing importers keep using
6
+ * `./config-service.js` unchanged.
7
+ */
8
+ import { existsSync } from 'node:fs';
9
+ import { dirname, isAbsolute, resolve } from 'node:path';
10
+ import { stablePath } from '../../shared/path-utils.js';
11
+ import { getUserConfigPath, isInsidePath, resolveProjectRootForConfig, validateArtifactWorkspaceMarkerPath, validateArtifactWorkspaceRoot, validateProjectBootstrapConfigPathForWrite, validateUserConfigPathForWrite, writeConfigFileSafely, writeProjectConfigFile, writeUserConfigFile } from './config-safety.js';
12
+ import { toWorkspaceConfigs } from './config-coercion.js';
13
+ import { ensureDir, getProjectWriteTarget, readJsonFile } from './config-file-io.js';
14
+ import { getConfig } from './config-get.js';
15
+ import { isRecord, isSafeConfigSegment } from './config-primitives.js';
16
+ function readRawWorkspaceData(layer) {
17
+ const config = getConfig({ layer });
18
+ return isRecord(config)
19
+ ? {
20
+ currentWorkspace: typeof config.currentWorkspace === 'string' ? config.currentWorkspace : null,
21
+ workspaces: toWorkspaceConfigs(config.workspaces)
22
+ }
23
+ : { currentWorkspace: null, workspaces: [] };
24
+ }
25
+ function writeRawWorkspaceData(data, layer) {
26
+ const projectTarget = layer === 'project' ? getProjectWriteTarget() : null;
27
+ const targetPath = projectTarget?.configPath ?? getUserConfigPath();
28
+ ensureDir(dirname(targetPath));
29
+ const existing = projectTarget
30
+ ? (readJsonFile(targetPath, () => validateProjectBootstrapConfigPathForWrite(projectTarget.projectRoot, targetPath)) ?? {})
31
+ : (readJsonFile(targetPath, () => validateUserConfigPathForWrite(targetPath)) ?? {});
32
+ const merged = { ...existing, ...data };
33
+ const content = JSON.stringify(merged, null, 2);
34
+ if (projectTarget) {
35
+ writeProjectConfigFile(projectTarget.projectRoot, targetPath, content);
36
+ }
37
+ else {
38
+ writeUserConfigFile(targetPath, content);
39
+ }
40
+ }
41
+ function readAllWorkspaces() {
42
+ const userData = readRawWorkspaceData('user');
43
+ const projectData = readRawWorkspaceData('project');
44
+ const mergedWorkspaces = new Map();
45
+ for (const w of userData.workspaces)
46
+ mergedWorkspaces.set(w.workspaceId, w);
47
+ for (const w of projectData.workspaces)
48
+ mergedWorkspaces.set(w.workspaceId, w);
49
+ return {
50
+ currentWorkspace: projectData.currentWorkspace ?? userData.currentWorkspace,
51
+ workspaces: [...mergedWorkspaces.values()]
52
+ };
53
+ }
54
+ export function getWorkspaceConfig(workspaceId, _projectRoot) {
55
+ // Accepted for signature stability: the registry spans the user and project
56
+ // layers, so the id alone identifies the workspace.
57
+ void _projectRoot;
58
+ const { workspaces } = readAllWorkspaces();
59
+ return workspaces.find((w) => w.workspaceId === workspaceId) ?? null;
60
+ }
61
+ function readLayerConfig(layer) {
62
+ return readRawWorkspaceData(layer);
63
+ }
64
+ export function addWorkspace(workspace, layer = 'user') {
65
+ if (!isSafeConfigSegment(workspace.workspaceId)) {
66
+ throw new Error('Workspace id must only contain letters, numbers, dots, underscores, or hyphens and must not contain path traversal');
67
+ }
68
+ const config = readRawWorkspaceData(layer);
69
+ const workspaces = config.workspaces;
70
+ const existing = workspaces.findIndex((w) => w.workspaceId === workspace.workspaceId);
71
+ const updatedWorkspaces = existing >= 0
72
+ ? workspaces.map((existingWorkspace) => existingWorkspace.workspaceId === workspace.workspaceId ? workspace : existingWorkspace)
73
+ : [...workspaces, workspace];
74
+ writeRawWorkspaceData({ workspaces: updatedWorkspaces }, layer);
75
+ }
76
+ export function removeWorkspace(workspaceId, layer = 'user') {
77
+ if (!isSafeConfigSegment(workspaceId))
78
+ return false;
79
+ const config = readRawWorkspaceData(layer);
80
+ const workspaces = config.workspaces;
81
+ const idx = workspaces.findIndex((w) => w.workspaceId === workspaceId);
82
+ if (idx < 0)
83
+ return false;
84
+ const updatedWorkspaces = workspaces.filter((w) => w.workspaceId !== workspaceId);
85
+ const currentWorkspace = config.currentWorkspace === workspaceId
86
+ ? (updatedWorkspaces[0]?.workspaceId ?? null)
87
+ : (config.currentWorkspace ?? null);
88
+ writeRawWorkspaceData({ workspaces: updatedWorkspaces, currentWorkspace }, layer);
89
+ return true;
90
+ }
91
+ export function setCurrentWorkspace(workspaceId, layer = 'user') {
92
+ if (!isSafeConfigSegment(workspaceId))
93
+ return false;
94
+ const config = readRawWorkspaceData(layer);
95
+ const workspaces = config.workspaces;
96
+ const exists = workspaces.some((w) => w.workspaceId === workspaceId);
97
+ if (!exists)
98
+ return false;
99
+ writeRawWorkspaceData({ currentWorkspace: workspaceId }, layer);
100
+ return true;
101
+ }
102
+ export function getCurrentWorkspaceConfig() {
103
+ const { currentWorkspace, workspaces } = readAllWorkspaces();
104
+ if (!currentWorkspace)
105
+ return null;
106
+ return workspaces.find((w) => w.workspaceId === currentWorkspace) ?? null;
107
+ }
108
+ export function getWorkspaceConfigForPath(path = process.cwd()) {
109
+ const { workspaces } = readAllWorkspaces();
110
+ return findWorkspaceForPath(workspaces, path);
111
+ }
112
+ function findWorkspaceForPath(workspaces, path) {
113
+ const targetPath = stablePath(path);
114
+ const matches = workspaces.flatMap((workspace) => {
115
+ if (!isAbsolute(workspace.rootPath) || !existsSync(workspace.rootPath))
116
+ return [];
117
+ const rootPath = stablePath(workspace.rootPath);
118
+ return isInsidePath(targetPath, rootPath) ? [{ workspace, rootPath }] : [];
119
+ });
120
+ if (matches.length === 0)
121
+ return null;
122
+ return matches.reduce((best, match) => match.rootPath.length > best.rootPath.length ? match : best).workspace;
123
+ }
124
+ function getWorkspaceArtifactRoot(workspace) {
125
+ return workspace.artifactStorage?.localPath
126
+ ? resolve(workspace.artifactStorage.localPath)
127
+ : resolve(workspace.rootPath, '.peaks', 'artifacts');
128
+ }
129
+ function ensureArtifactWorkspaceMarker(workspace) {
130
+ const artifactRoot = getWorkspaceArtifactRoot(workspace);
131
+ const peaksPath = resolve(artifactRoot, '.peaks');
132
+ const markerPath = resolve(peaksPath, 'config.json');
133
+ ensureDir(artifactRoot);
134
+ validateArtifactWorkspaceRoot(artifactRoot, workspace.rootPath);
135
+ ensureDir(peaksPath);
136
+ validateArtifactWorkspaceMarkerPath(artifactRoot, peaksPath, markerPath);
137
+ if (!existsSync(markerPath)) {
138
+ writeConfigFileSafely(markerPath, '{}\n', () => validateArtifactWorkspaceMarkerPath(artifactRoot, peaksPath, markerPath), 'Artifact workspace marker must stay inside the artifact workspace');
139
+ }
140
+ }
141
+ export function ensureWorkspaceConfigForPath(path = process.cwd()) {
142
+ const projectRoot = resolveProjectRootForConfig(path);
143
+ if (!isAbsolute(projectRoot) || !existsSync(projectRoot))
144
+ return null;
145
+ const config = readLayerConfig('user');
146
+ const existingWorkspace = findWorkspaceForPath(config.workspaces, path);
147
+ if (existingWorkspace) {
148
+ ensureArtifactWorkspaceMarker(existingWorkspace);
149
+ return existingWorkspace;
150
+ }
151
+ return null;
152
+ }
153
+ export function getWorkspaceConfigForCurrentPath() {
154
+ return getWorkspaceConfigForPath(process.cwd());
155
+ }
156
+ export function ensureWorkspaceConfigForCurrentPath() {
157
+ return ensureWorkspaceConfigForPath(process.cwd());
158
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Merge the peaks-managed Skill denylist into the existing settings object.
3
+ * Preserves every other `permissions.deny` entry the user (or another tool)
4
+ * has written so the install is additive, not destructive. The output is
5
+ * always deterministic: the same input always yields the same output,
6
+ * regardless of insertion order in the source array.
7
+ *
8
+ * Defensive behavior:
9
+ * - `settings.permissions` is missing or non-object → install creates a
10
+ * fresh `permissions: { deny: [...our entries] }` object.
11
+ * - `settings.permissions.deny` is missing or non-array → install replaces
12
+ * the field with a fresh array containing only our entries.
13
+ * - Duplicate entries (any source) are collapsed to one via `new Set`.
14
+ *
15
+ * The function is pure: it does not mutate the input. Atomic write happens
16
+ * at the call site (`applyHookInstall`).
17
+ */
18
+ export declare function withSuperpowersSkillDenylist(settings: Record<string, unknown>): Record<string, unknown>;
19
+ /**
20
+ * Inverse of `withSuperpowersSkillDenylist`. Removes every peaks-managed
21
+ * `UseSkill(...)` entry from the deny list. If the resulting deny list is
22
+ * empty, the `deny` field itself is deleted; if the `permissions` object
23
+ * becomes empty, the `permissions` field itself is deleted. This is the
24
+ * uninstall path: every field we wrote must be removed exactly, and no
25
+ * other field may be touched.
26
+ *
27
+ * Pure (no mutation).
28
+ */
29
+ export declare function withoutSuperpowersSkillDenylist(settings: Record<string, unknown>): Record<string, unknown>;
30
+ /**
31
+ * Read-only introspection. Returns the deny entries that `peaks hooks
32
+ * install` would write today. Useful for `peaks hooks status` and the
33
+ * dry-run envelope.
34
+ */
35
+ export declare function listSuperpowersDenyEntries(): ReadonlyArray<string>;
36
+ /**
37
+ *
38
+ * In addition to the static SUPERPOWERS_DENIED_SKILLS list, peaks
39
+ * scans the existing settings file for "trigger phrases" that
40
+ * indicate the user has configured the superpowers chain (or
41
+ * any other auto-run worktree-creating tool) and appends a
42
+ * defensive deny to prevent the chain from running raw
43
+ * `git worktree add` (or `podman run`) directly.
44
+ *
45
+ * Triggers detected (substring match on the existing
46
+ * permissions.deny / permissions.allow list):
47
+ *
48
+ * - `superpowers:using-git-worktrees` — the chain's ground zero
49
+ * - `superpowers:brainstorming` etc. — the upstream skill
50
+ * - `Bash(git worktree add` — the user has explicitly
51
+ * allowed raw git worktree, which our L2 lease-aware gate
52
+ * would also intercept (defense in depth)
53
+ *
54
+ * Append-only — never replaces, never re-orders, never removes
55
+ * existing entries. Idempotent: re-running the install with
56
+ * the same input yields the same output.
57
+ */
58
+ export declare const TRIGGER_PHRASES: ReadonlyArray<string>;
59
+ export declare function withTriggeredDenyList(settings: Record<string, unknown>): Record<string, unknown>;
60
+ /** Inverse of withTriggeredDenyList: strip every deny-trigger entry. */
61
+ export declare function withoutTriggeredDenyList(settings: Record<string, unknown>): Record<string, unknown>;
@@ -0,0 +1,173 @@
1
+ /**
2
+ * The peaks-managed `permissions.deny` entries, and their inverses.
3
+ *
4
+ * Split out of `hooks-settings-service.ts` (file-size cap campaign). The
5
+ * service re-exports every name declared here, so existing importers keep
6
+ * using `./hooks-settings-service.js` unchanged.
7
+ */
8
+ import { SUPERPOWERS_DENIED_SKILLS, SUPERPOWERS_DENY_SENTINELS, formatSuperpowersDenyEntry } from './hooks-codegate-superpowers.js';
9
+ /**
10
+ * Merge the peaks-managed Skill denylist into the existing settings object.
11
+ * Preserves every other `permissions.deny` entry the user (or another tool)
12
+ * has written so the install is additive, not destructive. The output is
13
+ * always deterministic: the same input always yields the same output,
14
+ * regardless of insertion order in the source array.
15
+ *
16
+ * Defensive behavior:
17
+ * - `settings.permissions` is missing or non-object → install creates a
18
+ * fresh `permissions: { deny: [...our entries] }` object.
19
+ * - `settings.permissions.deny` is missing or non-array → install replaces
20
+ * the field with a fresh array containing only our entries.
21
+ * - Duplicate entries (any source) are collapsed to one via `new Set`.
22
+ *
23
+ * The function is pure: it does not mutate the input. Atomic write happens
24
+ * at the call site (`applyHookInstall`).
25
+ */
26
+ export function withSuperpowersSkillDenylist(settings) {
27
+ const ourEntries = SUPERPOWERS_DENIED_SKILLS.map(formatSuperpowersDenyEntry);
28
+ const permissions = settings.permissions &&
29
+ typeof settings.permissions === 'object' &&
30
+ !Array.isArray(settings.permissions)
31
+ ? settings.permissions
32
+ : {};
33
+ const existingDeny = Array.isArray(permissions.deny)
34
+ ? permissions.deny.filter((d) => typeof d === 'string')
35
+ : [];
36
+ const otherDeny = existingDeny.filter((d) => !SUPERPOWERS_DENY_SENTINELS.has(d));
37
+ const finalDeny = [...new Set([...otherDeny, ...ourEntries])];
38
+ return {
39
+ ...settings,
40
+ permissions: { ...permissions, deny: finalDeny }
41
+ };
42
+ }
43
+ /**
44
+ * Inverse of `withSuperpowersSkillDenylist`. Removes every peaks-managed
45
+ * `UseSkill(...)` entry from the deny list. If the resulting deny list is
46
+ * empty, the `deny` field itself is deleted; if the `permissions` object
47
+ * becomes empty, the `permissions` field itself is deleted. This is the
48
+ * uninstall path: every field we wrote must be removed exactly, and no
49
+ * other field may be touched.
50
+ *
51
+ * Pure (no mutation).
52
+ */
53
+ export function withoutSuperpowersSkillDenylist(settings) {
54
+ const permissions = settings.permissions &&
55
+ typeof settings.permissions === 'object' &&
56
+ !Array.isArray(settings.permissions)
57
+ ? settings.permissions
58
+ : {};
59
+ if (!Array.isArray(permissions.deny)) {
60
+ return settings;
61
+ }
62
+ const remainingDeny = permissions.deny
63
+ .filter((d) => typeof d === 'string')
64
+ .filter((d) => !SUPERPOWERS_DENY_SENTINELS.has(d));
65
+ const nextPermissions = { ...permissions };
66
+ if (remainingDeny.length > 0) {
67
+ nextPermissions.deny = remainingDeny;
68
+ }
69
+ else {
70
+ delete nextPermissions.deny;
71
+ }
72
+ if (Object.keys(nextPermissions).length === 0) {
73
+ // The whole `permissions` object is empty (no deny, no allow, no other
74
+ // sub-fields). Drop it to avoid leaving an empty object on disk.
75
+ const rest = { ...settings };
76
+ delete rest['permissions'];
77
+ return rest;
78
+ }
79
+ return { ...settings, permissions: nextPermissions };
80
+ }
81
+ /**
82
+ * Read-only introspection. Returns the deny entries that `peaks hooks
83
+ * install` would write today. Useful for `peaks hooks status` and the
84
+ * dry-run envelope.
85
+ */
86
+ export function listSuperpowersDenyEntries() {
87
+ return SUPERPOWERS_DENIED_SKILLS.map(formatSuperpowersDenyEntry);
88
+ }
89
+ /**
90
+ *
91
+ * In addition to the static SUPERPOWERS_DENIED_SKILLS list, peaks
92
+ * scans the existing settings file for "trigger phrases" that
93
+ * indicate the user has configured the superpowers chain (or
94
+ * any other auto-run worktree-creating tool) and appends a
95
+ * defensive deny to prevent the chain from running raw
96
+ * `git worktree add` (or `podman run`) directly.
97
+ *
98
+ * Triggers detected (substring match on the existing
99
+ * permissions.deny / permissions.allow list):
100
+ *
101
+ * - `superpowers:using-git-worktrees` — the chain's ground zero
102
+ * - `superpowers:brainstorming` etc. — the upstream skill
103
+ * - `Bash(git worktree add` — the user has explicitly
104
+ * allowed raw git worktree, which our L2 lease-aware gate
105
+ * would also intercept (defense in depth)
106
+ *
107
+ * Append-only — never replaces, never re-orders, never removes
108
+ * existing entries. Idempotent: re-running the install with
109
+ * the same input yields the same output.
110
+ */
111
+ export const TRIGGER_PHRASES = Object.freeze([
112
+ 'superpowers:using-git-worktrees',
113
+ 'superpowers:brainstorming',
114
+ 'superpowers:writing-plans',
115
+ 'superpowers:subagent-driven-development',
116
+ 'Bash(git worktree add',
117
+ 'Bash(podman run'
118
+ ]);
119
+ /**
120
+ * Format a trigger-phrase into a stable `Edit` deny entry. We deny
121
+ * `Edit` (not `Bash`) on the *settings file* itself, so the
122
+ * user cannot edit the trigger away without an explicit
123
+ * `peaks hooks uninstall` first. The skill name (when
124
+ * applicable) is the value after the colon.
125
+ */
126
+ function formatTriggerDenyEntry(phrase) {
127
+ return `Edit(deny-trigger:${phrase})`;
128
+ }
129
+ export function withTriggeredDenyList(settings) {
130
+ const existingDeny = Array.isArray(settings.permissions?.deny)
131
+ ? settings.permissions.deny.filter((d) => typeof d === 'string')
132
+ : [];
133
+ // Detect triggers in the existing allow + deny lists.
134
+ const existingAllow = Array.isArray(settings.permissions?.allow)
135
+ ? settings.permissions.allow.filter((d) => typeof d === 'string')
136
+ : [];
137
+ const haystack = [...existingDeny, ...existingAllow].join('|');
138
+ const triggered = TRIGGER_PHRASES.filter((p) => haystack.includes(p));
139
+ if (triggered.length === 0)
140
+ return settings;
141
+ const triggeredEntries = triggered.map(formatTriggerDenyEntry);
142
+ const permissions = settings.permissions &&
143
+ typeof settings.permissions === 'object' &&
144
+ !Array.isArray(settings.permissions)
145
+ ? settings.permissions
146
+ : {};
147
+ const otherDeny = existingDeny.filter((d) => !triggeredEntries.includes(d));
148
+ return {
149
+ ...settings,
150
+ permissions: { ...permissions, deny: [...new Set([...otherDeny, ...triggeredEntries])] }
151
+ };
152
+ }
153
+ /** Inverse of withTriggeredDenyList: strip every deny-trigger entry. */
154
+ export function withoutTriggeredDenyList(settings) {
155
+ const permissions = settings.permissions &&
156
+ typeof settings.permissions === 'object' &&
157
+ !Array.isArray(settings.permissions)
158
+ ? settings.permissions
159
+ : {};
160
+ const existingDeny = Array.isArray(permissions.deny)
161
+ ? permissions.deny.filter((d) => typeof d === 'string')
162
+ : [];
163
+ const kept = existingDeny.filter((d) => !d.startsWith('Edit(deny-trigger:'));
164
+ const next = { ...permissions, deny: kept };
165
+ if (kept.length === 0)
166
+ delete next.deny;
167
+ if (Object.keys(next).length === 0) {
168
+ const out = { ...settings };
169
+ delete out.permissions;
170
+ return out;
171
+ }
172
+ return { ...settings, permissions: next };
173
+ }
@@ -0,0 +1,20 @@
1
+ import type { HookScope } from '../ide/shared/safe-path.js';
2
+ import type { HookRemoveResult, HookStatus, HookTarget } from './hooks-settings-types.js';
3
+ /** The uninstall envelope; a `localPath` is reported only when it is a distinct file. */
4
+ export declare function removedResult(scope: HookScope, settingsPath: string, localPath: string | undefined, removed: boolean): HookRemoveResult;
5
+ /**
6
+ * Strip every peaks-managed row from one target's file and write it back.
7
+ *
8
+ * The deny-list helpers run only on the SHARED settings file (the one that
9
+ * carries the committed `permissions.deny` block); the machine-local file
10
+ * carries hook entries plus, for Claude Code, the gate exemptions.
11
+ */
12
+ export declare function applyRemovalToTarget(target: HookTarget, sentinels: ReadonlyArray<string>, isSharedFile: boolean): boolean;
13
+ /**
14
+ * The status envelope for an IDE that can never carry a peaks hook: the query
15
+ * ran, the disk was read, and the honest reply is "nothing, and nothing ever
16
+ * will be".
17
+ */
18
+ export declare function unsupportedHookStatus(scope: HookScope, settingsPath: string, localPath: string | undefined): HookStatus;
19
+ /** The status envelope for a set of resolved targets. */
20
+ export declare function hookStatusFromTargets(scope: HookScope, settingsPath: string, targets: ReadonlyArray<HookTarget>): HookStatus;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The result envelopes the uninstall and status verbs return.
3
+ *
4
+ * Split out of `hooks-settings-service.ts` (file-size cap campaign). The
5
+ * service re-exports every name declared here, so existing importers keep
6
+ * using `./hooks-settings-service.js` unchanged.
7
+ */
8
+ import { existsSync } from 'node:fs';
9
+ import { atomicWriteJson } from '../ide/shared/atomic-json.js';
10
+ import { withoutExternalGateExemptions } from './hooks-codegate-superpowers.js';
11
+ import { withoutSuperpowersSkillDenylist, withoutTriggeredDenyList } from './hooks-settings-deny-list.js';
12
+ import { isInstalledForEntries, readSettingsFile, stripPeaksEntries } from './hooks-settings-file-shape.js';
13
+ /** The uninstall envelope; a `localPath` is reported only when it is a distinct file. */
14
+ export function removedResult(scope, settingsPath, localPath, removed) {
15
+ return {
16
+ scope,
17
+ settingsPath,
18
+ removed,
19
+ ...(localPath !== undefined && localPath !== settingsPath
20
+ ? { localSettingsPath: localPath }
21
+ : {})
22
+ };
23
+ }
24
+ /**
25
+ * Strip every peaks-managed row from one target's file and write it back.
26
+ *
27
+ * The deny-list helpers run only on the SHARED settings file (the one that
28
+ * carries the committed `permissions.deny` block); the machine-local file
29
+ * carries hook entries plus, for Claude Code, the gate exemptions.
30
+ */
31
+ export function applyRemovalToTarget(target, sentinels, isSharedFile) {
32
+ const { settings, removed } = stripPeaksEntries(target, sentinels);
33
+ let finalSettings = settings;
34
+ if (target.envExemptions === true) {
35
+ finalSettings = withoutExternalGateExemptions(finalSettings);
36
+ }
37
+ if (isSharedFile) {
38
+ finalSettings = withoutTriggeredDenyList(withoutSuperpowersSkillDenylist(finalSettings));
39
+ }
40
+ atomicWriteJson(target.settingsPath, finalSettings);
41
+ return removed;
42
+ }
43
+ /**
44
+ * The status envelope for an IDE that can never carry a peaks hook: the query
45
+ * ran, the disk was read, and the honest reply is "nothing, and nothing ever
46
+ * will be".
47
+ */
48
+ export function unsupportedHookStatus(scope, settingsPath, localPath) {
49
+ return {
50
+ scope,
51
+ settingsPath,
52
+ exists: existsSync(settingsPath),
53
+ ...(localPath !== undefined && localPath !== settingsPath
54
+ ? { localSettingsPath: localPath, localExists: existsSync(localPath) }
55
+ : {}),
56
+ installed: false,
57
+ supportsHooks: false
58
+ };
59
+ }
60
+ /** The status envelope for a set of resolved targets. */
61
+ export function hookStatusFromTargets(scope, settingsPath, targets) {
62
+ const localTarget = targets.find((t) => t.settingsPath !== settingsPath);
63
+ return {
64
+ scope,
65
+ settingsPath,
66
+ exists: existsSync(settingsPath),
67
+ ...(localTarget !== undefined
68
+ ? {
69
+ localSettingsPath: localTarget.settingsPath,
70
+ localExists: existsSync(localTarget.settingsPath)
71
+ }
72
+ : {}),
73
+ installed: targets.some((t) => {
74
+ const settings = readSettingsFile(t.settingsPath);
75
+ return Object.keys(settings).length > 0 && isInstalledForEntries(settings, t.entries);
76
+ }),
77
+ supportsHooks: true
78
+ };
79
+ }