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,139 @@
1
+ /**
2
+ * The public type surface of the hooks settings service.
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 type { IdeId } from '../ide/ide-types.js';
9
+ import type { HookScope } from '../ide/shared/safe-path.js';
10
+ import type { PeaksHookEntry } from './hooks-codegate-superpowers.js';
11
+ export type HookInstallOptions = {
12
+ /**
13
+ * Which IDE's adapter to install for. Defaults to `'claude-code'` for
14
+ * backward compatibility. The CLI command should resolve this from
15
+ * `detectIdeFromContext({ env, cwd, parsedStdin })` and pass the result.
16
+ * Throws if the IDE is not registered in the adapter registry.
17
+ */
18
+ readonly ide?: IdeId;
19
+ /**
20
+ * Slice #013 (bugfix — peaks hooks install --no-progress): when `true`,
21
+ * skip emitting the progress-start PreToolUse hook entry while still
22
+ * installing the gate-enforce entry. The progress-start hook auto-spawns
23
+ * a new terminal running `peaks progress watch`; with dispatch +
24
+ * heartbeat (slice #009 + #010) that auto-spawn is dead weight. Default
25
+ * `false` preserves the pre-slice install shape (both entries). The
26
+ * sentinel-based install is idempotent: re-running with `skipProgress:
27
+ * true` over a settings.json that previously had the progress entry
28
+ * installed will remove that entry. `uninstall` honors the same flag
29
+ * so it can find and remove both entries when both are present and
30
+ * only the gate-enforce entry when only the gate-enforce is present.
31
+ *
32
+ * Slice #014 (refactor — full removal of legacy progress-start surface):
33
+ * the field is preserved for API stability, but the underlying
34
+ * install only ever emits the gate-enforce entry. The progress-start
35
+ * entry is no longer installed regardless of this flag's value. The
36
+ * legacy `peaks progress start|watch|close` CLI surface is gone
37
+ * (replaced by `peaks sub-agent dispatch|heartbeat|share`); the hook
38
+ * entry would have been pointing at a `peaks progress start` that no
39
+ * longer exists. The sentinel `peaks progress start` constant is still
40
+ * exported (some tests + back-compat reads rely on it) but no new
41
+ * hook entries use it.
42
+ */
43
+ readonly skipProgress?: boolean;
44
+ };
45
+ /**
46
+ * One peaks-managed entry paired with the settings file it is (or will be)
47
+ * written to.
48
+ *
49
+ * `entries` is a flat list of the same matcher/sentinel pairs, which reads as
50
+ * "written to `settingsPath`" even when the entry is routed to the other file
51
+ * (see `resolveHookTargets`). This carries the routing explicitly so the
52
+ * dry-run can name the real target without a real run.
53
+ */
54
+ export type HookEntryTarget = {
55
+ matcher: string;
56
+ sentinel: string;
57
+ settingsPath: string;
58
+ };
59
+ export type HookInstallPlan = {
60
+ scope: HookScope;
61
+ settingsPath: string;
62
+ exists: boolean;
63
+ alreadyInstalled: boolean;
64
+ desiredCommand: string;
65
+ sentinel: string;
66
+ matcher: string;
67
+ /**
68
+ * Machine-local, gitignored settings file that the gate-enforce entry is
69
+ * written to instead of `settingsPath`. Undefined when the IDE has no such
70
+ * file (or the scope is global, where the settings file is already
71
+ * machine-local). See `resolveHookTargets`.
72
+ */
73
+ localSettingsPath?: string;
74
+ /** Every entry the install writes, paired with its target file. */
75
+ entryTargets: ReadonlyArray<HookEntryTarget>;
76
+ };
77
+ export type HookInstallResult = HookInstallPlan & {
78
+ applied: boolean;
79
+ };
80
+ export type HookRemoveResult = {
81
+ scope: HookScope;
82
+ settingsPath: string;
83
+ localSettingsPath?: string;
84
+ removed: boolean;
85
+ };
86
+ export type HookStatus = {
87
+ scope: HookScope;
88
+ settingsPath: string;
89
+ exists: boolean;
90
+ localSettingsPath?: string;
91
+ localExists?: boolean;
92
+ installed: boolean;
93
+ /**
94
+ * Whether this IDE can host a peaks hook AT ALL (`hasHookSpec`).
95
+ *
96
+ * `status` answers "what is on disk", and for an IDE with no
97
+ * `HOOK_COMMAND_BY_IDE` entry the answer is "nothing, and nothing ever will
98
+ * be" — which is a successful query returning a negative fact, not a failed
99
+ * one. The exit code says the query succeeded; this field says what it found.
100
+ * Without it `installed: false` would be indistinguishable from a supported
101
+ * IDE that simply has no hook installed yet, which is a state the user can
102
+ * act on.
103
+ */
104
+ supportsHooks: boolean;
105
+ };
106
+ export type HookHandler = {
107
+ type?: string;
108
+ command?: string;
109
+ };
110
+ export type HookMatcherEntry = {
111
+ matcher?: string;
112
+ hooks?: HookHandler[];
113
+ };
114
+ /**
115
+ * A peaks-managed hook entry set grouped by the settings file that must
116
+ * carry it.
117
+ *
118
+ * Peaks hooks normally land in the adapter's settings file. The gate-enforce
119
+ * Bash entry is the exception: on Windows its `shell` must be pinned to
120
+ * `powershell`, because the default Git-Bash shell force-allocates a console
121
+ * window on every Bash tool call (MSYS2 behaviour — see the 2026-09-10
122
+ * hook-console finding). A machine-specific value must never be committed
123
+ * into the SHARED `.claude/settings.json` that a macOS/Linux teammate reads
124
+ * too, so that entry is materialized into the machine-local file instead.
125
+ * The routing decision is platform-independent (it keys off the entry's
126
+ * `machineLocal` flag, not off `process.platform`) so the shared file's
127
+ * content does not depend on which OS ran the install.
128
+ */
129
+ export type HookTarget = {
130
+ settingsPath: string;
131
+ entries: PeaksHookEntry[];
132
+ /**
133
+ * When true this file also receives the third-party PreToolUse gate
134
+ * exemptions (`EXTERNAL_GATE_EXEMPT_ENV`). Claude Code only — `env` is a
135
+ * Claude Code settings key — and only ever on a machine-local file, never
136
+ * on the committed shared one.
137
+ */
138
+ envExemptions?: boolean;
139
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,89 @@
1
+ /**
2
+ * `claude-settings-template-merge.ts` — the comparison and the merge that decide
3
+ * whether an on-disk settings file still declares what the template declares, and
4
+ * that carry every entry the template does not declare across untouched.
5
+ *
6
+ * Split out of `claude-settings-template.ts` (475 raw lines against the 300 cap)
7
+ * when the two layer-B feedback hook entries had to be added to the template: that
8
+ * file now holds the template's own shape, and this one holds the merge machinery.
9
+ * The bodies moved verbatim; the three non-null assertions became the explicit
10
+ * `undefined` checks they already were in effect, so this module is clean at birth.
11
+ * `claude-settings-template.ts` re-exports every symbol below, so it stays the
12
+ * single public entry point for this concern.
13
+ */
14
+ /**
15
+ * Compare two serialized template strings: does the on-disk file already
16
+ * declare every entry the generated tree declares?
17
+ *
18
+ * This comparator answers "is each entry the GENERATED tree declares present
19
+ * on disk?", NOT "are the two `hooks` trees identical". Extra on-disk entries
20
+ * are IGNORED, so an entry another writer put in this file never makes it look
21
+ * drifted.
22
+ *
23
+ * That is the deliberate other half of the entry-level merge in
24
+ * `mergeTemplateOwnedHooks` / `workspace-claude-settings-materializer.ts`.
25
+ * `.claude/settings.local.json` has a SECOND writer of `hooks.PreToolUse`:
26
+ * `installAutoCompactHook` appends a `Bash|Task` entry. Under the previous
27
+ * exact-tree rule the merged file carried 4 entries against a 3-entry
28
+ * generated tree, so every `peaks workspace init` answered "drifted",
29
+ * rewrote, and reported `refreshed` forever — precisely the state whole-key
30
+ * ownership existed to prevent, and the reason the merge could not ship alone.
31
+ *
32
+ * Matching is order-insensitive AND multiset-aware: the template declares TWO
33
+ * `Bash` entries, and each must have its own counterpart on disk, so a file
34
+ * carrying only one of them is still reported as drifted (the previous
35
+ * index-by-index loop had the same property; it is load-bearing, not a
36
+ * detail).
37
+ *
38
+ * Returns `true` iff both strings parse to objects whose `hooks.PreToolUse`
39
+ * arrays satisfy that containment, the on-disk file carries NO entry this
40
+ * template has retired (`isRetiredTemplateEntry`), AND the on-disk `env`
41
+ * already carries every exemption the template declares (extra on-disk keys
42
+ * and extra globs are allowed — a user may exempt other trees, and a
43
+ * requirement the file already exceeds must not re-trigger a write).
44
+ *
45
+ * Returns `false` on any `JSON.parse` error, shape mismatch, or
46
+ * missing `hooks.PreToolUse`. Whitespace and key order do NOT affect
47
+ * the result — the comparison is on the parsed AST, not on bytes.
48
+ *
49
+ * This is the comparator `initWorkspace` uses to decide whether to
50
+ * refresh a stale `.peaks/.claude-settings-template.json` on disk.
51
+ */
52
+ export declare function templateContentMatches(generated: string, onDisk: string): boolean;
53
+ /**
54
+ * Merge the on-disk `hooks.PreToolUse` list with the template's.
55
+ *
56
+ * the entries IT DECLARES — and nothing else. Every other on-disk entry is
57
+ * carried across verbatim, whatever its matcher, because the template has no
58
+ * opinion about it:
59
+ *
60
+ * - a `matcher` the template does not declare (`Bash|Task`, the auto-compact
61
+ * hook `installAutoCompactHook` appends) is never touched;
62
+ * - surplus entries BEYOND the template's count for a declared matcher (a
63
+ * user's own `Bash` hook) are surplus too, and survive;
64
+ * - an on-disk entry that fills a declared slot is REPLACED by the template's
65
+ * entry for it. That is what makes a hand-edited (or older-release) entry
66
+ * self-heal instead of lingering next to a correct copy of itself.
67
+ *
68
+ * Slot counting is per `matcher` and positional within it: the template
69
+ * declares TWO `Bash` entries, so the first two on-disk `Bash` entries are
70
+ * theirs and a third is the user's. The template's entries are emitted first,
71
+ * in template order, then the preserved ones in their on-disk order — which is
72
+ * a fixed point: re-merging the result yields the result (the template's own
73
+ * entries are encountered first and refill their own slots).
74
+ *
75
+ * Non-conforming entries (no string `matcher`, no `hooks` array) are preserved
76
+ * rather than dropped: guessing at their shape is how a user's entry gets
77
+ * deleted.
78
+ *
79
+ * ONE exception to "preserve what I do not declare": an entry this template
80
+ * used to declare and RETIRED (TEMPLATE_VERSION 1.8.0's `Write|Edit|MultiEdit`
81
+ * gate — see `isRetiredTemplateEntry`) is dropped rather than preserved.
82
+ * Declaring less cannot retire an entry on its own, because preserving
83
+ * undeclared entries is exactly what this function does; without the drop, a
84
+ * pre-1.8.0 install would keep the no-op handler and its version-pinned script
85
+ * path forever. The predicate is narrow enough that only the exact command
86
+ * this template emitted matches.
87
+ */
88
+ export declare function mergeTemplateOwnedHooks(onDisk: ReadonlyArray<unknown>, template: ReadonlyArray<unknown>): unknown[];
89
+ export declare function isRetiredTemplateEntry(entry: unknown): boolean;
@@ -0,0 +1,243 @@
1
+ /**
2
+ * `claude-settings-template-merge.ts` — the comparison and the merge that decide
3
+ * whether an on-disk settings file still declares what the template declares, and
4
+ * that carry every entry the template does not declare across untouched.
5
+ *
6
+ * Split out of `claude-settings-template.ts` (475 raw lines against the 300 cap)
7
+ * when the two layer-B feedback hook entries had to be added to the template: that
8
+ * file now holds the template's own shape, and this one holds the merge machinery.
9
+ * The bodies moved verbatim; the three non-null assertions became the explicit
10
+ * `undefined` checks they already were in effect, so this module is clean at birth.
11
+ * `claude-settings-template.ts` re-exports every symbol below, so it stays the
12
+ * single public entry point for this concern.
13
+ */
14
+ import { hasExternalGateExemptions } from '../skills/hooks-codegate-superpowers.js';
15
+ /**
16
+ * Compare two serialized template strings: does the on-disk file already
17
+ * declare every entry the generated tree declares?
18
+ *
19
+ * This comparator answers "is each entry the GENERATED tree declares present
20
+ * on disk?", NOT "are the two `hooks` trees identical". Extra on-disk entries
21
+ * are IGNORED, so an entry another writer put in this file never makes it look
22
+ * drifted.
23
+ *
24
+ * That is the deliberate other half of the entry-level merge in
25
+ * `mergeTemplateOwnedHooks` / `workspace-claude-settings-materializer.ts`.
26
+ * `.claude/settings.local.json` has a SECOND writer of `hooks.PreToolUse`:
27
+ * `installAutoCompactHook` appends a `Bash|Task` entry. Under the previous
28
+ * exact-tree rule the merged file carried 4 entries against a 3-entry
29
+ * generated tree, so every `peaks workspace init` answered "drifted",
30
+ * rewrote, and reported `refreshed` forever — precisely the state whole-key
31
+ * ownership existed to prevent, and the reason the merge could not ship alone.
32
+ *
33
+ * Matching is order-insensitive AND multiset-aware: the template declares TWO
34
+ * `Bash` entries, and each must have its own counterpart on disk, so a file
35
+ * carrying only one of them is still reported as drifted (the previous
36
+ * index-by-index loop had the same property; it is load-bearing, not a
37
+ * detail).
38
+ *
39
+ * Returns `true` iff both strings parse to objects whose `hooks.PreToolUse`
40
+ * arrays satisfy that containment, the on-disk file carries NO entry this
41
+ * template has retired (`isRetiredTemplateEntry`), AND the on-disk `env`
42
+ * already carries every exemption the template declares (extra on-disk keys
43
+ * and extra globs are allowed — a user may exempt other trees, and a
44
+ * requirement the file already exceeds must not re-trigger a write).
45
+ *
46
+ * Returns `false` on any `JSON.parse` error, shape mismatch, or
47
+ * missing `hooks.PreToolUse`. Whitespace and key order do NOT affect
48
+ * the result — the comparison is on the parsed AST, not on bytes.
49
+ *
50
+ * This is the comparator `initWorkspace` uses to decide whether to
51
+ * refresh a stale `.peaks/.claude-settings-template.json` on disk.
52
+ */
53
+ export function templateContentMatches(generated, onDisk) {
54
+ let parsedGenerated;
55
+ let parsedOnDisk;
56
+ try {
57
+ parsedGenerated = JSON.parse(generated);
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ try {
63
+ parsedOnDisk = JSON.parse(onDisk);
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ if (!isTemplateShape(parsedGenerated) || !isTemplateShape(parsedOnDisk)) {
69
+ return false;
70
+ }
71
+ // Multiset containment: consume one on-disk entry per generated entry so a
72
+ // file holding a single copy of a doubly-declared entry still fails.
73
+ const unmatched = [...parsedOnDisk.hooks.PreToolUse];
74
+ for (const required of parsedGenerated.hooks.PreToolUse) {
75
+ const at = unmatched.findIndex((candidate) => sameEntry(required, candidate));
76
+ if (at === -1) {
77
+ return false;
78
+ }
79
+ unmatched.splice(at, 1);
80
+ }
81
+ // A RETIRED entry on disk is drift, and this clause is what makes the
82
+ // retirement in `mergeTemplateOwnedHooks` reach an installed file at all.
83
+ //
84
+ // Containment alone cannot express it: a file still carrying
85
+ // `Write|Edit|MultiEdit` declares every entry the template declares, so
86
+ // `templateContentMatches` answered "current", no rewrite ran, and the merge
87
+ // never got the chance to drop it. Measured on a throwaway project root
88
+ // before this clause existed — init against the rebuilt CLI reported
89
+ // `already-current` and the retired entry survived verbatim. Declaring less
90
+ // is not a retirement; the comparator has to say so.
91
+ //
92
+ // One extra rewrite per affected install, then the fixed point holds: the
93
+ // merge emits no retired entry, so the next comparison finds none and
94
+ // answers `current`.
95
+ if (parsedOnDisk.hooks.PreToolUse.some((entry) => isRetiredTemplateEntry(entry))) {
96
+ return false;
97
+ }
98
+ // A project installed by a release that predates a template-declared
99
+ // exemption still needs the refresh this comparator gates — otherwise the
100
+ // entry would only ever appear on a machine that re-ran `peaks hooks
101
+ // install`. `hasExternalGateExemptions` is the same predicate the installer
102
+ // uses, so the two writers cannot drift apart.
103
+ return hasExternalGateExemptions({ env: parsedOnDisk.env });
104
+ }
105
+ /**
106
+ * Merge the on-disk `hooks.PreToolUse` list with the template's.
107
+ *
108
+ * the entries IT DECLARES — and nothing else. Every other on-disk entry is
109
+ * carried across verbatim, whatever its matcher, because the template has no
110
+ * opinion about it:
111
+ *
112
+ * - a `matcher` the template does not declare (`Bash|Task`, the auto-compact
113
+ * hook `installAutoCompactHook` appends) is never touched;
114
+ * - surplus entries BEYOND the template's count for a declared matcher (a
115
+ * user's own `Bash` hook) are surplus too, and survive;
116
+ * - an on-disk entry that fills a declared slot is REPLACED by the template's
117
+ * entry for it. That is what makes a hand-edited (or older-release) entry
118
+ * self-heal instead of lingering next to a correct copy of itself.
119
+ *
120
+ * Slot counting is per `matcher` and positional within it: the template
121
+ * declares TWO `Bash` entries, so the first two on-disk `Bash` entries are
122
+ * theirs and a third is the user's. The template's entries are emitted first,
123
+ * in template order, then the preserved ones in their on-disk order — which is
124
+ * a fixed point: re-merging the result yields the result (the template's own
125
+ * entries are encountered first and refill their own slots).
126
+ *
127
+ * Non-conforming entries (no string `matcher`, no `hooks` array) are preserved
128
+ * rather than dropped: guessing at their shape is how a user's entry gets
129
+ * deleted.
130
+ *
131
+ * ONE exception to "preserve what I do not declare": an entry this template
132
+ * used to declare and RETIRED (TEMPLATE_VERSION 1.8.0's `Write|Edit|MultiEdit`
133
+ * gate — see `isRetiredTemplateEntry`) is dropped rather than preserved.
134
+ * Declaring less cannot retire an entry on its own, because preserving
135
+ * undeclared entries is exactly what this function does; without the drop, a
136
+ * pre-1.8.0 install would keep the no-op handler and its version-pinned script
137
+ * path forever. The predicate is narrow enough that only the exact command
138
+ * this template emitted matches.
139
+ */
140
+ export function mergeTemplateOwnedHooks(onDisk, template) {
141
+ const slots = new Map();
142
+ for (const entry of template) {
143
+ if (!isPreToolUseEntry(entry))
144
+ continue;
145
+ slots.set(entry.matcher, (slots.get(entry.matcher) ?? 0) + 1);
146
+ }
147
+ const taken = new Map();
148
+ const preserved = [];
149
+ for (const entry of onDisk) {
150
+ // Retired by this template — dropped, not carried across.
151
+ if (isRetiredTemplateEntry(entry)) {
152
+ continue;
153
+ }
154
+ // Unowned by construction: not a shape the template could have declared.
155
+ if (!isPreToolUseEntry(entry)) {
156
+ preserved.push(entry);
157
+ continue;
158
+ }
159
+ const declared = slots.get(entry.matcher) ?? 0;
160
+ const used = taken.get(entry.matcher) ?? 0;
161
+ if (used >= declared) {
162
+ preserved.push(entry);
163
+ continue;
164
+ }
165
+ taken.set(entry.matcher, used + 1);
166
+ }
167
+ return [...template, ...preserved];
168
+ }
169
+ /** Structural equality of two `PreToolUse` entries. */
170
+ function sameEntry(a, b) {
171
+ return a.matcher === b.matcher && sameHooksArray(a.hooks, b.hooks);
172
+ }
173
+ function isPreToolUseEntry(value) {
174
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
175
+ return false;
176
+ }
177
+ const candidate = value;
178
+ return typeof candidate.matcher === 'string' && Array.isArray(candidate.hooks);
179
+ }
180
+ function isTemplateShape(value) {
181
+ if (typeof value !== 'object' || value === null) {
182
+ return false;
183
+ }
184
+ const candidate = value;
185
+ if (typeof candidate.hooks !== 'object' || candidate.hooks === null) {
186
+ return false;
187
+ }
188
+ const hooksObj = candidate.hooks;
189
+ return Array.isArray(hooksObj.PreToolUse);
190
+ }
191
+ function sameHooksArray(a, b) {
192
+ if (a.length !== b.length) {
193
+ return false;
194
+ }
195
+ for (let i = 0; i < a.length; i += 1) {
196
+ const ha = a[i];
197
+ const hb = b[i];
198
+ if (ha === undefined || hb === undefined) {
199
+ return false;
200
+ }
201
+ // `shell` participates in the comparison: it is machine-specific (see
202
+ // `resolveHookShell`), so a file written on one platform must be
203
+ // recognized as drifted on the other instead of silently kept.
204
+ if (ha.type !== hb.type || ha.command !== hb.command || ha.shell !== hb.shell) {
205
+ return false;
206
+ }
207
+ }
208
+ return true;
209
+ }
210
+ /**
211
+ * The retired `Write|Edit|MultiEdit` gate entry, as an on-disk file written by
212
+ * a pre-1.8.0 release holds it.
213
+ *
214
+ * TEMPLATE_VERSION 1.8.0 stopped emitting this entry. Declaring less is not
215
+ * enough on its own: `mergeTemplateOwnedHooks` preserves every on-disk entry
216
+ * the template does not declare — that is the whole point of the entry-level
217
+ * ownership rule (it is what keeps `installAutoCompactHook`'s `Bash|Task`
218
+ * entry alive) — so a project installed by an earlier release would keep the
219
+ * no-op handler, and its `node "C:/…/nvm/v24.14.0/…"` path, forever. This
220
+ * predicate is the retirement: `mergeTemplateOwnedHooks` drops a match.
221
+ *
222
+ * Deliberately narrow. It matches the exact command shape this template used
223
+ * to emit — one handler, `node "<…>/services/hooks/write-gate.js"` — under the
224
+ * exact legacy matcher spelling, so a user's OWN `Write|Edit|MultiEdit` entry
225
+ * (a different command, or more than one handler) is preserved like any other
226
+ * entry the template does not declare. A looser "drop anything on this
227
+ * matcher" rule would delete a user's hook, which is the failure the ownership
228
+ * rule exists to prevent.
229
+ */
230
+ const RETIRED_WRITE_GATE_MATCHER = 'Write|Edit|MultiEdit';
231
+ const RETIRED_WRITE_GATE_COMMAND = /^node "[^"]*\/services\/hooks\/write-gate\.js"$/;
232
+ export function isRetiredTemplateEntry(entry) {
233
+ if (!isPreToolUseEntry(entry))
234
+ return false;
235
+ if (entry.matcher !== RETIRED_WRITE_GATE_MATCHER)
236
+ return false;
237
+ if (entry.hooks.length !== 1)
238
+ return false;
239
+ const [handler] = entry.hooks;
240
+ if (handler === undefined)
241
+ return false;
242
+ return handler.type === 'command' && RETIRED_WRITE_GATE_COMMAND.test(handler.command);
243
+ }
@@ -23,10 +23,11 @@
23
23
  * it can be unit-tested in isolation and so the on-disk file matches
24
24
  * the in-memory template byte-for-byte.
25
25
  *
26
- * Two `Bash` matchers are emitted (the Step 0.8 mechanical gate and the
27
- * SOP gate-enforce handler). No `Write|Edit|MultiEdit` entry is emitted:
28
- * that matcher's gate is `peaks code-gate --json`, installed into the
29
- * committed `.claude/settings.json` by `peaks hooks install`.
26
+ * Four `Bash` matchers are emitted: the Step 0.8 mechanical gate, the SOP
27
+ * gate-enforce handler, and the two layer-B feedback hooks. No
28
+ * `Write|Edit|MultiEdit` entry is emitted: that matcher's gate is
29
+ * `peaks code-gate --json`, installed into the committed
30
+ * `.claude/settings.json` by `peaks hooks install`.
30
31
  *
31
32
  * The previous `Bash` matcher (which whitelisted a fixed `peaks
32
33
  * <subcommand>` prefix) was removed in TEMPLATE_VERSION 1.2.0. The
@@ -40,6 +41,14 @@
40
41
  * consumer project's `.claude/settings.json` and which exits 0
41
42
  * silently for any command not guarded by a registered SOP gate.
42
43
  */
44
+ /**
45
+ * The comparison and the entry-level merge live in
46
+ * `claude-settings-template-merge.ts` — they were two thirds of this file's
47
+ * bytes and none of its template shape. Re-exported here so this module stays
48
+ * the single public entry point for the template concern: no caller has to
49
+ * know which half a symbol lives in.
50
+ */
51
+ export { isRetiredTemplateEntry, mergeTemplateOwnedHooks, templateContentMatches } from './claude-settings-template-merge.js';
43
52
  export declare const CLAUDE_SETTINGS_LOCAL_FILENAME = ".claude/settings.local.json";
44
53
  /**
45
54
  * Informational version of the offline template shape. Bumped when the
@@ -97,84 +106,17 @@ export declare const CLAUDE_SETTINGS_LOCAL_FILENAME = ".claude/settings.local.js
97
106
  * `mergeTemplateOwnedHooks` drops the retired entry from
98
107
  * existing on-disk files, so an earlier install converges
99
108
  * instead of keeping a no-op with a stale absolute path.
109
+ * 1.9.0 — added the two layer-B feedback hook entries
110
+ * (`pre-tool-peaks-current-directory-scope.sh` and
111
+ * `pre-tool-piping-a-test-run-reports-the-pipes-exit-code.sh`),
112
+ * pinned to `shell: bash`. Until now their registration existed only
113
+ * in the generated copies on the machine that hand-wrote them: a
114
+ * fresh clone got the two scripts and no registration, so the
115
+ * promotion they carry was true only locally. See
116
+ * `buildFeedbackHookHandler` for why the pin is `bash` and not the
117
+ * `powershell` its three siblings take.
100
118
  */
101
- export declare const TEMPLATE_VERSION = "1.8.0";
102
- /**
103
- * Compare two serialized template strings: does the on-disk file already
104
- * declare every entry the generated tree declares?
105
- *
106
- * This comparator answers "is each entry the GENERATED tree declares present
107
- * on disk?", NOT "are the two `hooks` trees identical". Extra on-disk entries
108
- * are IGNORED, so an entry another writer put in this file never makes it look
109
- * drifted.
110
- *
111
- * That is the deliberate other half of the entry-level merge in
112
- * `mergeTemplateOwnedHooks` / `workspace-claude-settings-materializer.ts`.
113
- * `.claude/settings.local.json` has a SECOND writer of `hooks.PreToolUse`:
114
- * `installAutoCompactHook` appends a `Bash|Task` entry. Under the previous
115
- * exact-tree rule the merged file carried 4 entries against a 3-entry
116
- * generated tree, so every `peaks workspace init` answered "drifted",
117
- * rewrote, and reported `refreshed` forever — precisely the state whole-key
118
- * ownership existed to prevent, and the reason the merge could not ship alone.
119
- *
120
- * Matching is order-insensitive AND multiset-aware: the template declares TWO
121
- * `Bash` entries, and each must have its own counterpart on disk, so a file
122
- * carrying only one of them is still reported as drifted (the previous
123
- * index-by-index loop had the same property; it is load-bearing, not a
124
- * detail).
125
- *
126
- * Returns `true` iff both strings parse to objects whose `hooks.PreToolUse`
127
- * arrays satisfy that containment, the on-disk file carries NO entry this
128
- * template has retired (`isRetiredTemplateEntry`), AND the on-disk `env`
129
- * already carries every exemption the template declares (extra on-disk keys
130
- * and extra globs are allowed — a user may exempt other trees, and a
131
- * requirement the file already exceeds must not re-trigger a write).
132
- *
133
- * Returns `false` on any `JSON.parse` error, shape mismatch, or
134
- * missing `hooks.PreToolUse`. Whitespace and key order do NOT affect
135
- * the result — the comparison is on the parsed AST, not on bytes.
136
- *
137
- * This is the comparator `initWorkspace` uses to decide whether to
138
- * refresh a stale `.peaks/.claude-settings-template.json` on disk.
139
- */
140
- export declare function templateContentMatches(generated: string, onDisk: string): boolean;
141
- /**
142
- * Merge the on-disk `hooks.PreToolUse` list with the template's.
143
- *
144
- * the entries IT DECLARES — and nothing else. Every other on-disk entry is
145
- * carried across verbatim, whatever its matcher, because the template has no
146
- * opinion about it:
147
- *
148
- * - a `matcher` the template does not declare (`Bash|Task`, the auto-compact
149
- * hook `installAutoCompactHook` appends) is never touched;
150
- * - surplus entries BEYOND the template's count for a declared matcher (a
151
- * user's own `Bash` hook) are surplus too, and survive;
152
- * - an on-disk entry that fills a declared slot is REPLACED by the template's
153
- * entry for it. That is what makes a hand-edited (or older-release) entry
154
- * self-heal instead of lingering next to a correct copy of itself.
155
- *
156
- * Slot counting is per `matcher` and positional within it: the template
157
- * declares TWO `Bash` entries, so the first two on-disk `Bash` entries are
158
- * theirs and a third is the user's. The template's entries are emitted first,
159
- * in template order, then the preserved ones in their on-disk order — which is
160
- * a fixed point: re-merging the result yields the result (the template's own
161
- * entries are encountered first and refill their own slots).
162
- *
163
- * Non-conforming entries (no string `matcher`, no `hooks` array) are preserved
164
- * rather than dropped: guessing at their shape is how a user's entry gets
165
- * deleted.
166
- *
167
- * ONE exception to "preserve what I do not declare": an entry this template
168
- * used to declare and RETIRED (TEMPLATE_VERSION 1.8.0's `Write|Edit|MultiEdit`
169
- * gate — see `isRetiredTemplateEntry`) is dropped rather than preserved.
170
- * Declaring less cannot retire an entry on its own, because preserving
171
- * undeclared entries is exactly what this function does; without the drop, a
172
- * pre-1.8.0 install would keep the no-op handler and its version-pinned script
173
- * path forever. The predicate is narrow enough that only the exact command
174
- * this template emitted matches.
175
- */
176
- export declare function mergeTemplateOwnedHooks(onDisk: ReadonlyArray<unknown>, template: ReadonlyArray<unknown>): unknown[];
177
- export declare function isRetiredTemplateEntry(entry: unknown): boolean;
119
+ export declare const TEMPLATE_VERSION = "1.9.0";
178
120
  type ClaudeHookCommand = {
179
121
  type: 'command';
180
122
  command: string;
@@ -203,11 +145,11 @@ type ClaudeSettingsLocal = {
203
145
  * forcing gate is a core feature that PreToolUse hooks can short-
204
146
  * circuit but that the `permissions` block cannot.
205
147
  *
206
- * As of TEMPLATE_VERSION 1.8.0 the template emits the two `Bash` matchers
207
- * only. The `Write|Edit|MultiEdit` fact-forcing bypass is no longer a hook:
208
- * it is the `env` exemption above, and that matcher's gate
209
- * (`peaks code-gate --json`) is installed into the committed
210
- * `.claude/settings.json` by `peaks hooks install`.
148
+ * As of TEMPLATE_VERSION 1.9.0 the template emits four `Bash` matchers: the
149
+ * two above, plus one per layer-B feedback hook (`FEEDBACK_HOOK_SCRIPTS`). The
150
+ * `Write|Edit|MultiEdit` fact-forcing bypass is no longer a hook: it is the
151
+ * `env` exemption above, and that matcher's gate (`peaks code-gate --json`) is
152
+ * installed into the committed `.claude/settings.json` by `peaks hooks
153
+ * install`.
211
154
  */
212
155
  export declare function buildClaudeSettingsLocalJson(): ClaudeSettingsLocal;
213
- export {};