peaks-loop 4.1.2 → 4.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (323) hide show
  1. package/.claude-plugin/marketplace.json +136 -47
  2. package/CHANGELOG.md +56 -0
  3. package/README-en.md +1 -1
  4. package/README.md +1 -1
  5. package/contracts/readonly-argv-whitelist.json +211 -0
  6. package/dist/cli/commands/audit-artifact-runners.d.ts +16 -0
  7. package/dist/cli/commands/audit-artifact-runners.js +170 -0
  8. package/dist/cli/commands/audit-command-shared.d.ts +97 -0
  9. package/dist/cli/commands/audit-command-shared.js +60 -0
  10. package/dist/cli/commands/audit-commands.d.ts +7 -31
  11. package/dist/cli/commands/audit-commands.js +64 -473
  12. package/dist/cli/commands/audit-goal-runners.d.ts +17 -0
  13. package/dist/cli/commands/audit-goal-runners.js +114 -0
  14. package/dist/cli/commands/audit-red-lines-runners.d.ts +11 -0
  15. package/dist/cli/commands/audit-red-lines-runners.js +43 -0
  16. package/dist/cli/commands/audit-refusal-data.d.ts +23 -0
  17. package/dist/cli/commands/audit-refusal-data.js +69 -0
  18. package/dist/cli/commands/audit-static-runners.d.ts +13 -0
  19. package/dist/cli/commands/audit-static-runners.js +139 -0
  20. package/dist/cli/commands/await-runners.d.ts +11 -0
  21. package/dist/cli/commands/await-runners.js +148 -0
  22. package/dist/cli/commands/code-auto-compact-command.d.ts +3 -0
  23. package/dist/cli/commands/code-auto-compact-command.js +124 -0
  24. package/dist/cli/commands/code-auto-compact-envelope.d.ts +22 -0
  25. package/dist/cli/commands/code-auto-compact-envelope.js +39 -0
  26. package/dist/cli/commands/code-context-audit-command.d.ts +3 -0
  27. package/dist/cli/commands/code-context-audit-command.js +68 -0
  28. package/dist/cli/commands/code-context-now-command.d.ts +3 -0
  29. package/dist/cli/commands/code-context-now-command.js +124 -0
  30. package/dist/cli/commands/code-context-now-envelope.d.ts +66 -0
  31. package/dist/cli/commands/code-context-now-envelope.js +136 -0
  32. package/dist/cli/commands/code-context-now-mapping.d.ts +27 -0
  33. package/dist/cli/commands/code-context-now-mapping.js +43 -0
  34. package/dist/cli/commands/code-emit-handoff-command.d.ts +3 -0
  35. package/dist/cli/commands/code-emit-handoff-command.js +99 -0
  36. package/dist/cli/commands/code-gate-step-08-command.d.ts +3 -0
  37. package/dist/cli/commands/code-gate-step-08-command.js +139 -0
  38. package/dist/cli/commands/code-post-compact-detect-command.d.ts +3 -0
  39. package/dist/cli/commands/code-post-compact-detect-command.js +50 -0
  40. package/dist/cli/commands/code-runtime-commands.d.ts +9 -43
  41. package/dist/cli/commands/code-runtime-commands.js +20 -672
  42. package/dist/cli/commands/code-runtime-session.d.ts +1 -0
  43. package/dist/cli/commands/code-runtime-session.js +15 -0
  44. package/dist/cli/commands/compact-command.d.ts +6 -2
  45. package/dist/cli/commands/compact-command.js +12 -559
  46. package/dist/cli/commands/compact-dry-run-command.d.ts +3 -0
  47. package/dist/cli/commands/compact-dry-run-command.js +87 -0
  48. package/dist/cli/commands/compact-force-command.d.ts +3 -0
  49. package/dist/cli/commands/compact-force-command.js +98 -0
  50. package/dist/cli/commands/compact-harness-window-command.d.ts +3 -0
  51. package/dist/cli/commands/compact-harness-window-command.js +174 -0
  52. package/dist/cli/commands/compact-history-command.d.ts +3 -0
  53. package/dist/cli/commands/compact-history-command.js +89 -0
  54. package/dist/cli/commands/compact-read-commands.d.ts +3 -0
  55. package/dist/cli/commands/compact-read-commands.js +123 -0
  56. package/dist/cli/commands/compact-settle-command.d.ts +3 -0
  57. package/dist/cli/commands/compact-settle-command.js +130 -0
  58. package/dist/cli/commands/compact-shared.d.ts +9 -0
  59. package/dist/cli/commands/compact-shared.js +26 -0
  60. package/dist/cli/commands/core/skill-command.d.ts +1 -44
  61. package/dist/cli/commands/core/skill-command.js +13 -541
  62. package/dist/cli/commands/core/skill-context-verdict.d.ts +38 -0
  63. package/dist/cli/commands/core/skill-context-verdict.js +63 -0
  64. package/dist/cli/commands/core/skill-generated-config-notice.d.ts +41 -0
  65. package/dist/cli/commands/core/skill-generated-config-notice.js +75 -0
  66. package/dist/cli/commands/core/skill-heartbeat-commands.d.ts +3 -0
  67. package/dist/cli/commands/core/skill-heartbeat-commands.js +50 -0
  68. package/dist/cli/commands/core/skill-presence-commands.d.ts +3 -0
  69. package/dist/cli/commands/core/skill-presence-commands.js +123 -0
  70. package/dist/cli/commands/core/skill-presence-housekeeping-commands.d.ts +3 -0
  71. package/dist/cli/commands/core/skill-presence-housekeeping-commands.js +165 -0
  72. package/dist/cli/commands/core/skill-registry-commands.d.ts +3 -0
  73. package/dist/cli/commands/core/skill-registry-commands.js +117 -0
  74. package/dist/cli/commands/core/skill-runbook-command.d.ts +3 -0
  75. package/dist/cli/commands/core/skill-runbook-command.js +29 -0
  76. package/dist/cli/commands/dispatch-command-spec.d.ts +2 -0
  77. package/dist/cli/commands/dispatch-command-spec.js +62 -0
  78. package/dist/cli/commands/dispatch-commands.js +159 -775
  79. package/dist/cli/commands/dispatch-detached-branch.d.ts +3 -0
  80. package/dist/cli/commands/dispatch-detached-branch.js +58 -0
  81. package/dist/cli/commands/dispatch-envelope.d.ts +36 -0
  82. package/dist/cli/commands/dispatch-envelope.js +104 -0
  83. package/dist/cli/commands/dispatch-isolation-lease.d.ts +17 -0
  84. package/dist/cli/commands/dispatch-isolation-lease.js +149 -0
  85. package/dist/cli/commands/dispatch-preflight.d.ts +7 -0
  86. package/dist/cli/commands/dispatch-preflight.js +105 -0
  87. package/dist/cli/commands/dispatch-prompt-blocks.d.ts +10 -0
  88. package/dist/cli/commands/dispatch-prompt-blocks.js +56 -0
  89. package/dist/cli/commands/dispatch-prompt-composition.d.ts +30 -0
  90. package/dist/cli/commands/dispatch-prompt-composition.js +171 -0
  91. package/dist/cli/commands/dispatch-record-write.d.ts +24 -0
  92. package/dist/cli/commands/dispatch-record-write.js +96 -0
  93. package/dist/cli/commands/dispatch-tool-call.d.ts +15 -0
  94. package/dist/cli/commands/dispatch-tool-call.js +128 -0
  95. package/dist/cli/commands/evolution-command-shared.d.ts +78 -0
  96. package/dist/cli/commands/evolution-command-shared.js +107 -0
  97. package/dist/cli/commands/evolution-commands.d.ts +11 -1
  98. package/dist/cli/commands/evolution-commands.js +19 -350
  99. package/dist/cli/commands/evolution-evaluate-command.d.ts +24 -0
  100. package/dist/cli/commands/evolution-evaluate-command.js +138 -0
  101. package/dist/cli/commands/evolution-propose-command.d.ts +23 -0
  102. package/dist/cli/commands/evolution-propose-command.js +145 -0
  103. package/dist/cli/commands/evolution-status-command.d.ts +17 -0
  104. package/dist/cli/commands/evolution-status-command.js +41 -0
  105. package/dist/cli/commands/evolution-verdict-commands.d.ts +30 -0
  106. package/dist/cli/commands/evolution-verdict-commands.js +100 -0
  107. package/dist/cli/commands/finalize-accumulator.d.ts +44 -0
  108. package/dist/cli/commands/finalize-accumulator.js +55 -0
  109. package/dist/cli/commands/finalize-branches.d.ts +34 -0
  110. package/dist/cli/commands/finalize-branches.js +119 -0
  111. package/dist/cli/commands/finalize-runners.d.ts +3 -0
  112. package/dist/cli/commands/finalize-runners.js +92 -0
  113. package/dist/cli/commands/finalize-selection.d.ts +65 -0
  114. package/dist/cli/commands/finalize-selection.js +35 -0
  115. package/dist/cli/commands/gate-commands.js +26 -8
  116. package/dist/cli/commands/job-checkpoint-commands.d.ts +3 -0
  117. package/dist/cli/commands/job-checkpoint-commands.js +157 -0
  118. package/dist/cli/commands/job-command-shared.d.ts +109 -0
  119. package/dist/cli/commands/job-command-shared.js +72 -0
  120. package/dist/cli/commands/job-commands.d.ts +4 -64
  121. package/dist/cli/commands/job-commands.js +42 -552
  122. package/dist/cli/commands/job-cost-check-command.d.ts +3 -0
  123. package/dist/cli/commands/job-cost-check-command.js +41 -0
  124. package/dist/cli/commands/job-init-status-commands.d.ts +3 -0
  125. package/dist/cli/commands/job-init-status-commands.js +149 -0
  126. package/dist/cli/commands/job-run-commands.d.ts +3 -0
  127. package/dist/cli/commands/job-run-commands.js +97 -0
  128. package/dist/cli/commands/job-state-root.d.ts +35 -0
  129. package/dist/cli/commands/job-state-root.js +76 -0
  130. package/dist/cli/commands/loop-eval-capture-index.d.ts +4 -0
  131. package/dist/cli/commands/loop-eval-capture-index.js +44 -0
  132. package/dist/cli/commands/loop-eval-commands.d.ts +8 -5
  133. package/dist/cli/commands/loop-eval-commands.js +12 -626
  134. package/dist/cli/commands/loop-eval-eval-command.d.ts +3 -0
  135. package/dist/cli/commands/loop-eval-eval-command.js +168 -0
  136. package/dist/cli/commands/loop-eval-monotonic-command.d.ts +3 -0
  137. package/dist/cli/commands/loop-eval-monotonic-command.js +90 -0
  138. package/dist/cli/commands/loop-eval-parents.d.ts +7 -0
  139. package/dist/cli/commands/loop-eval-parents.js +20 -0
  140. package/dist/cli/commands/loop-eval-run-code.d.ts +7 -0
  141. package/dist/cli/commands/loop-eval-run-code.js +40 -0
  142. package/dist/cli/commands/loop-eval-run-command.d.ts +3 -0
  143. package/dist/cli/commands/loop-eval-run-command.js +113 -0
  144. package/dist/cli/commands/loop-eval-spec-commands.d.ts +3 -0
  145. package/dist/cli/commands/loop-eval-spec-commands.js +165 -0
  146. package/dist/cli/commands/loop-eval-spec-lint-command.d.ts +3 -0
  147. package/dist/cli/commands/loop-eval-spec-lint-command.js +42 -0
  148. package/dist/cli/commands/loop-eval-workflow-commands.d.ts +3 -0
  149. package/dist/cli/commands/loop-eval-workflow-commands.js +141 -0
  150. package/dist/cli/commands/mcp-commands.d.ts +10 -0
  151. package/dist/cli/commands/mcp-commands.js +157 -0
  152. package/dist/cli/commands/request-command-options.d.ts +49 -0
  153. package/dist/cli/commands/request-command-options.js +1 -0
  154. package/dist/cli/commands/request-commands.d.ts +3 -9
  155. package/dist/cli/commands/request-commands.js +17 -522
  156. package/dist/cli/commands/request-init-command.d.ts +3 -0
  157. package/dist/cli/commands/request-init-command.js +100 -0
  158. package/dist/cli/commands/request-lint-command.d.ts +3 -0
  159. package/dist/cli/commands/request-lint-command.js +50 -0
  160. package/dist/cli/commands/request-list-command.d.ts +10 -0
  161. package/dist/cli/commands/request-list-command.js +53 -0
  162. package/dist/cli/commands/request-repair-status-command.d.ts +3 -0
  163. package/dist/cli/commands/request-repair-status-command.js +61 -0
  164. package/dist/cli/commands/request-show-command.d.ts +3 -0
  165. package/dist/cli/commands/request-show-command.js +56 -0
  166. package/dist/cli/commands/request-transition-command.d.ts +3 -0
  167. package/dist/cli/commands/request-transition-command.js +122 -0
  168. package/dist/cli/commands/request-transition-failures.d.ts +8 -0
  169. package/dist/cli/commands/request-transition-failures.js +90 -0
  170. package/dist/cli/commands/request-transition-hooks.d.ts +50 -0
  171. package/dist/cli/commands/request-transition-hooks.js +115 -0
  172. package/dist/cli/commands/request-transition-preflight.d.ts +10 -0
  173. package/dist/cli/commands/request-transition-preflight.js +107 -0
  174. package/dist/cli/commands/scan-command-shared.d.ts +96 -0
  175. package/dist/cli/commands/scan-command-shared.js +83 -0
  176. package/dist/cli/commands/scan-commands.d.ts +3 -2
  177. package/dist/cli/commands/scan-commands.js +23 -463
  178. package/dist/cli/commands/scan-inventory-commands.d.ts +3 -0
  179. package/dist/cli/commands/scan-inventory-commands.js +96 -0
  180. package/dist/cli/commands/scan-project-commands.d.ts +3 -0
  181. package/dist/cli/commands/scan-project-commands.js +65 -0
  182. package/dist/cli/commands/scan-scope-commands.d.ts +3 -0
  183. package/dist/cli/commands/scan-scope-commands.js +149 -0
  184. package/dist/cli/commands/scan-scope-helpers.d.ts +8 -0
  185. package/dist/cli/commands/scan-scope-helpers.js +54 -0
  186. package/dist/cli/commands/scan-structural-commands.d.ts +3 -0
  187. package/dist/cli/commands/scan-structural-commands.js +113 -0
  188. package/dist/cli/commands/share-commands.d.ts +12 -68
  189. package/dist/cli/commands/share-commands.js +47 -556
  190. package/dist/cli/commands/share-error-hints.d.ts +14 -0
  191. package/dist/cli/commands/share-error-hints.js +38 -0
  192. package/dist/cli/commands/share-identity.d.ts +13 -0
  193. package/dist/cli/commands/share-identity.js +22 -0
  194. package/dist/cli/commands/share-record-paths.d.ts +37 -0
  195. package/dist/cli/commands/share-record-paths.js +68 -0
  196. package/dist/cli/commands/share-runners.d.ts +3 -0
  197. package/dist/cli/commands/share-runners.js +158 -0
  198. package/dist/cli/commands/shared-read-runners.d.ts +3 -0
  199. package/dist/cli/commands/shared-read-runners.js +51 -0
  200. package/dist/cli/commands/slice-check-command.d.ts +3 -0
  201. package/dist/cli/commands/slice-check-command.js +54 -0
  202. package/dist/cli/commands/slice-commands.d.ts +2 -22
  203. package/dist/cli/commands/slice-commands.js +18 -517
  204. package/dist/cli/commands/slice-decompose-artifacts.d.ts +18 -0
  205. package/dist/cli/commands/slice-decompose-artifacts.js +79 -0
  206. package/dist/cli/commands/slice-decompose-command.d.ts +3 -0
  207. package/dist/cli/commands/slice-decompose-command.js +123 -0
  208. package/dist/cli/commands/slice-list-commands.d.ts +3 -0
  209. package/dist/cli/commands/slice-list-commands.js +182 -0
  210. package/dist/cli/commands/slice-pick-command.d.ts +3 -0
  211. package/dist/cli/commands/slice-pick-command.js +60 -0
  212. package/dist/cli/commands/slice-plan-command.d.ts +24 -0
  213. package/dist/cli/commands/slice-plan-command.js +111 -0
  214. package/dist/cli/commands/workflow-commands.d.ts +10 -1
  215. package/dist/cli/commands/workflow-commands.js +6 -594
  216. package/dist/cli/commands/workflow-gate-commands.d.ts +3 -0
  217. package/dist/cli/commands/workflow-gate-commands.js +116 -0
  218. package/dist/cli/commands/workflow-plan-helpers.d.ts +48 -0
  219. package/dist/cli/commands/workflow-plan-helpers.js +103 -0
  220. package/dist/cli/commands/workflow-planning-commands.d.ts +3 -0
  221. package/dist/cli/commands/workflow-planning-commands.js +56 -0
  222. package/dist/cli/commands/workflow-swarm-actions.d.ts +7 -0
  223. package/dist/cli/commands/workflow-swarm-actions.js +109 -0
  224. package/dist/cli/commands/workflow-swarm-commands.d.ts +3 -0
  225. package/dist/cli/commands/workflow-swarm-commands.js +138 -0
  226. package/dist/cli/commands/workflow-tech-actions.d.ts +10 -0
  227. package/dist/cli/commands/workflow-tech-actions.js +150 -0
  228. package/dist/cli/commands/workspace/init-actions.d.ts +10 -0
  229. package/dist/cli/commands/workspace/init-actions.js +199 -0
  230. package/dist/cli/commands/workspace/init-codegraph-stake.d.ts +10 -0
  231. package/dist/cli/commands/workspace/init-codegraph-stake.js +54 -0
  232. package/dist/cli/commands/workspace/init-command.d.ts +8 -124
  233. package/dist/cli/commands/workspace/init-command.js +59 -623
  234. package/dist/cli/commands/workspace/init-context.d.ts +58 -0
  235. package/dist/cli/commands/workspace/init-context.js +121 -0
  236. package/dist/cli/commands/workspace/init-envelope.d.ts +3 -0
  237. package/dist/cli/commands/workspace/init-envelope.js +34 -0
  238. package/dist/cli/commands/workspace/init-failures.d.ts +3 -0
  239. package/dist/cli/commands/workspace/init-failures.js +84 -0
  240. package/dist/cli/commands/workspace/init-hooks-decision.d.ts +24 -0
  241. package/dist/cli/commands/workspace/init-hooks-decision.js +189 -0
  242. package/dist/cli/commands/workspace/init-options.d.ts +102 -0
  243. package/dist/cli/commands/workspace/init-options.js +1 -0
  244. package/dist/cli/commands/worktree-lease-commands.d.ts +10 -6
  245. package/dist/cli/commands/worktree-lease-commands.js +42 -512
  246. package/dist/cli/commands/worktree-lease-gc-command.d.ts +12 -0
  247. package/dist/cli/commands/worktree-lease-gc-command.js +117 -0
  248. package/dist/cli/commands/worktree-lease-git.d.ts +22 -0
  249. package/dist/cli/commands/worktree-lease-git.js +48 -0
  250. package/dist/cli/commands/worktree-lease-list-command.d.ts +12 -0
  251. package/dist/cli/commands/worktree-lease-list-command.js +100 -0
  252. package/dist/cli/commands/worktree-lease-load.d.ts +37 -0
  253. package/dist/cli/commands/worktree-lease-load.js +28 -0
  254. package/dist/cli/commands/worktree-lease-release-command.d.ts +13 -0
  255. package/dist/cli/commands/worktree-lease-release-command.js +105 -0
  256. package/dist/cli/commands/worktree-lease-renew-command.d.ts +11 -0
  257. package/dist/cli/commands/worktree-lease-renew-command.js +99 -0
  258. package/dist/cli/commands/worktree-lease-session.d.ts +22 -0
  259. package/dist/cli/commands/worktree-lease-session.js +29 -0
  260. package/dist/cli/commands/worktree-lease-spawn-command.d.ts +11 -0
  261. package/dist/cli/commands/worktree-lease-spawn-command.js +119 -0
  262. package/dist/cli/commands/worktree-lease-status-command.d.ts +11 -0
  263. package/dist/cli/commands/worktree-lease-status-command.js +86 -0
  264. package/dist/cli/commands/worktree-lease-store.d.ts +19 -0
  265. package/dist/cli/commands/worktree-lease-store.js +24 -0
  266. package/dist/cli/program.js +5 -0
  267. package/dist/services/distribution/mcp-install-runner.d.ts +21 -0
  268. package/dist/services/distribution/mcp-install-runner.js +59 -0
  269. package/dist/services/distribution/mcp-install.d.ts +95 -0
  270. package/dist/services/distribution/mcp-install.js +179 -0
  271. package/dist/services/distribution/plugin-manifest.d.ts +97 -0
  272. package/dist/services/distribution/plugin-manifest.js +126 -0
  273. package/dist/services/hooks/mcp-surface-gate.d.ts +19 -0
  274. package/dist/services/hooks/mcp-surface-gate.js +87 -0
  275. package/dist/services/ide/adapters/claude-code-adapter.d.ts +4 -35
  276. package/dist/services/ide/adapters/claude-code-adapter.js +48 -171
  277. package/dist/services/ide/adapters/claude-code-local-state.d.ts +28 -0
  278. package/dist/services/ide/adapters/claude-code-local-state.js +112 -0
  279. package/dist/services/ide/adapters/claude-code-model-window.d.ts +37 -0
  280. package/dist/services/ide/adapters/claude-code-model-window.js +113 -0
  281. package/dist/services/ide/ide-mcp-install-types.d.ts +78 -0
  282. package/dist/services/ide/ide-mcp-install-types.js +104 -0
  283. package/dist/services/ide/ide-types.d.ts +45 -1
  284. package/dist/services/ide/mcp-tool-matcher.d.ts +34 -0
  285. package/dist/services/ide/mcp-tool-matcher.js +84 -0
  286. package/dist/services/lint/npx-resolver.js +7 -0
  287. package/dist/services/mcp/cli-executor.d.ts +36 -0
  288. package/dist/services/mcp/cli-executor.js +97 -0
  289. package/dist/services/mcp/json-rpc.d.ts +81 -0
  290. package/dist/services/mcp/json-rpc.js +116 -0
  291. package/dist/services/mcp/memory-tool.d.ts +3 -0
  292. package/dist/services/mcp/memory-tool.js +62 -0
  293. package/dist/services/mcp/server-main.d.ts +1 -0
  294. package/dist/services/mcp/server-main.js +66 -0
  295. package/dist/services/mcp/server.d.ts +22 -0
  296. package/dist/services/mcp/server.js +152 -0
  297. package/dist/services/mcp/surface.d.ts +62 -0
  298. package/dist/services/mcp/surface.js +198 -0
  299. package/dist/services/mcp/tool-core.d.ts +42 -0
  300. package/dist/services/mcp/tool-core.js +137 -0
  301. package/dist/services/mcp/tools.d.ts +13 -0
  302. package/dist/services/mcp/tools.js +58 -0
  303. package/dist/services/readonly-surface/argv-guard.d.ts +32 -0
  304. package/dist/services/readonly-surface/argv-guard.js +164 -0
  305. package/dist/services/readonly-surface/readonly-whitelist.d.ts +147 -0
  306. package/dist/services/readonly-surface/readonly-whitelist.js +107 -0
  307. package/dist/services/readonly-surface/whitelist-generator.d.ts +64 -0
  308. package/dist/services/readonly-surface/whitelist-generator.js +212 -0
  309. package/dist/services/skills/hooks-codegate-superpowers.d.ts +1 -0
  310. package/dist/services/skills/hooks-codegate-superpowers.js +26 -0
  311. package/dist/services/skills/hooks-settings-service.js +10 -2
  312. package/package.json +17 -6
  313. package/scripts/install-skills-bundles.mjs +233 -0
  314. package/scripts/install-skills-fs.mjs +148 -0
  315. package/scripts/install-skills-ide.mjs +279 -0
  316. package/scripts/install-skills-output-style-default.mjs +196 -0
  317. package/scripts/install-skills-output-styles.mjs +121 -0
  318. package/scripts/install-skills-report.mjs +42 -0
  319. package/scripts/install-skills-user-config.mjs +198 -0
  320. package/scripts/install-skills.mjs +36 -1066
  321. package/scripts/watch-tree.mjs +140 -0
  322. package/scripts/watch.mjs +4 -126
  323. package/skills/peaks-status/SKILL.md +31 -13
@@ -0,0 +1,150 @@
1
+ import { createTechPlan, getTechStatus } from '../../services/tech/tech-service.js';
2
+ import { createWorkflowRouterPlan, isWorkflowMode } from '../../services/workflow/workflow-router-service.js';
3
+ import { createAutonomousWorkflowPlan } from '../../services/workflow/workflow-autonomous-service.js';
4
+ import { readConfig } from '../../services/config/config-service.js';
5
+ import { addJsonOption, failUnsupportedNonDryRun, getErrorMessage, printResult } from '../cli-helpers.js';
6
+ import { fail, ok } from 'peaks-loop-shared/result';
7
+ // catch sites below (tech.plan / workflow.route / workflow.autonomous /
8
+ // swarm.plan) so provider-config errors surface as `INVALID_PROVIDERS`
9
+ // instead of being silently re-labelled `INVALID_GOAL`.
10
+ import { mapServiceError } from './_cli-error-envelope.js';
11
+ import { getCurrentWorkspaceContext, getWorkflowWorkspaceContext, parseCodeMode, parseMaxWorkers, validatePlanningInput } from './workflow-plan-helpers.js';
12
+ export function runTechPlan(io, options) {
13
+ if (options.dryRun === false) {
14
+ failUnsupportedNonDryRun(io, 'tech.plan', options.json);
15
+ return;
16
+ }
17
+ try {
18
+ validatePlanningInput(options.goal);
19
+ const workspaceContext = getCurrentWorkspaceContext();
20
+ // gone. The planner derives scope from the active session; the
21
+ // legacy `sessionId` field is passed as empty string for back-compat
22
+ // with the existing service signature.
23
+ const plan = createTechPlan({
24
+ sessionId: '',
25
+ goal: options.goal,
26
+ swarm: options.swarm ?? false,
27
+ dryRun: true,
28
+ ...workspaceContext
29
+ });
30
+ printResult(io, ok('tech.plan', plan), options.json);
31
+ }
32
+ catch (error) {
33
+ const mapping = mapServiceError(error);
34
+ printResult(io, fail('tech.plan', mapping.code, getErrorMessage(error), {}, [...mapping.nextActions]), options.json);
35
+ process.exitCode = 1;
36
+ }
37
+ }
38
+ export function runTechStatus(io, options) {
39
+ try {
40
+ const workspaceContext = getCurrentWorkspaceContext();
41
+ printResult(io, ok('tech.status', getTechStatus({ sessionId: '', ...workspaceContext })), options.json);
42
+ }
43
+ catch (error) {
44
+ printResult(io, fail('tech.status', 'TECH_STATUS_FAILED', getErrorMessage(error), {}, [
45
+ 'Verify the project setup'
46
+ ]), options.json);
47
+ process.exitCode = 1;
48
+ }
49
+ }
50
+ /**
51
+ * The dry-run / mode / maxWorkers / codeMode preamble the two workflow planners
52
+ * share. Lifted from their common prefix verbatim, parameterised only by the
53
+ * command label both already spelled out; it runs at the same point in the
54
+ * sequence and returns `null` where the original returned early.
55
+ */
56
+ function resolveWorkflowPlanInputs(io, label, options) {
57
+ if (options.dryRun === false) {
58
+ failUnsupportedNonDryRun(io, label, options.json);
59
+ return null;
60
+ }
61
+ if (!isWorkflowMode(options.mode)) {
62
+ printResult(io, fail(label, 'UNSUPPORTED_WORKFLOW_MODE', `Unsupported workflow mode ${options.mode}`, {}, [
63
+ 'Use --mode code or --mode team'
64
+ ]), options.json);
65
+ process.exitCode = 1;
66
+ return null;
67
+ }
68
+ const maxWorkers = parseMaxWorkers(io, label, options.maxWorkers, options.json);
69
+ if (maxWorkers === null)
70
+ return null;
71
+ const codeMode = parseCodeMode(io, label, options.mode, options.codeMode, options.json);
72
+ if (codeMode === null)
73
+ return null;
74
+ // `options.mode` is narrowed to `WorkflowMode` by the `isWorkflowMode` guard
75
+ // above; carrying it out with the pair keeps the call sites free of a cast.
76
+ return { maxWorkers, codeMode, mode: options.mode };
77
+ }
78
+ export function runWorkflowRoute(io, options) {
79
+ const inputs = resolveWorkflowPlanInputs(io, 'workflow.route', options);
80
+ if (inputs === null)
81
+ return;
82
+ try {
83
+ validatePlanningInput(options.goal);
84
+ const workspaceContext = getWorkflowWorkspaceContext();
85
+ const plan = createWorkflowRouterPlan({
86
+ sessionId: '',
87
+ goal: options.goal,
88
+ mode: inputs.mode,
89
+ ...(inputs.codeMode ? { codeMode: inputs.codeMode } : {}),
90
+ maxWorkers: inputs.maxWorkers,
91
+ dryRun: true,
92
+ config: readConfig(),
93
+ ...workspaceContext
94
+ });
95
+ printResult(io, ok('workflow.route', plan), options.json);
96
+ }
97
+ catch (error) {
98
+ const mapping = mapServiceError(error);
99
+ printResult(io, fail('workflow.route', mapping.code, getErrorMessage(error), {}, [...mapping.nextActions]), options.json);
100
+ process.exitCode = 1;
101
+ }
102
+ }
103
+ export function runAutonomousWorkflow(io, options) {
104
+ const inputs = resolveWorkflowPlanInputs(io, 'workflow.autonomous', options);
105
+ if (inputs === null)
106
+ return;
107
+ try {
108
+ validatePlanningInput(options.goal);
109
+ const workspaceContext = getWorkflowWorkspaceContext();
110
+ const plan = createAutonomousWorkflowPlan({
111
+ sessionId: '',
112
+ goal: options.goal,
113
+ mode: inputs.mode,
114
+ ...(inputs.codeMode ? { codeMode: inputs.codeMode } : {}),
115
+ maxWorkers: inputs.maxWorkers,
116
+ dryRun: true,
117
+ config: readConfig(),
118
+ ...workspaceContext
119
+ });
120
+ printResult(io, ok('workflow.autonomous', plan), options.json);
121
+ }
122
+ catch (error) {
123
+ const mapping = mapServiceError(error);
124
+ printResult(io, fail('workflow.autonomous', mapping.code, getErrorMessage(error), {}, [
125
+ ...mapping.nextActions
126
+ ]), options.json);
127
+ process.exitCode = 1;
128
+ }
129
+ }
130
+ export function addTechPlanOptions(command) {
131
+ return addJsonOption(command
132
+ .description('Generate a technical dry-run graph')
133
+ .requiredOption('--goal <goal>', 'planning goal')
134
+ .option('--swarm', 'opt into swarm-oriented planning')
135
+ .option('--dry-run', 'preview without writing files', true)
136
+ .option('--no-dry-run', 'unsupported: do not execute tech planning from this CLI'));
137
+ }
138
+ export function addTechStatusOptions(command) {
139
+ return addJsonOption(command.description('Inspect technical approval status'));
140
+ }
141
+ export function addWorkflowRouteOptions(command, description) {
142
+ return addJsonOption(command
143
+ .description(description)
144
+ .requiredOption('--mode <mode>', 'workflow mode: code or team')
145
+ .requiredOption('--goal <goal>', 'planning goal')
146
+ .option('--code-mode <mode>', 'code mode: full-auto, guided, or rnd')
147
+ .option('--max-workers <count>', 'maximum worker count', '40')
148
+ .option('--dry-run', 'preview without writing files', true)
149
+ .option('--no-dry-run', 'unsupported: do not execute workflow planning from this CLI'));
150
+ }
@@ -0,0 +1,10 @@
1
+ import type { WorkspaceInitContext } from './init-context.js';
2
+ import type { CodegraphAutoStakeOutcome, FirstTimeHooksInstallOutcome } from './init-options.js';
3
+ export type InitEnvelopeParts = {
4
+ nextActions: string[];
5
+ warnings: string[];
6
+ hooksOutcome: FirstTimeHooksInstallOutcome;
7
+ codegraphAutoOutcome: CodegraphAutoStakeOutcome | null;
8
+ };
9
+ /** Collect the envelope's nextActions + warnings in the original push order. */
10
+ export declare function collectInitEnvelope(ctx: WorkspaceInitContext): Promise<InitEnvelopeParts>;
@@ -0,0 +1,199 @@
1
+ import { clearStalePresenceOnRotation } from '../../../services/skills/skill-presence-service.js';
2
+ import { gcStalePresenceLeases } from '../../../services/skills/presence-lease-service.js';
3
+ import { hasStandardsCheckedMarker, markStandardsChecked } from '../../../services/standards/missing-standards-detector.js';
4
+ import { getErrorMessage } from '../../cli-helpers.js';
5
+ import { stakeCodegraphForInit } from './init-codegraph-stake.js';
6
+ import { resolveFirstTimeHooksInstall } from './init-hooks-decision.js';
7
+ function pushBindingReplacedAction(nextActions, report) {
8
+ if (report.previousSessionId !== null && report.bound) {
9
+ nextActions.push(`Replaced prior session binding "${report.previousSessionId}" with "${report.sessionId}".`);
10
+ }
11
+ }
12
+ /**
13
+ * Outer-session-mismatch rotation: the previous Claude / harness
14
+ * session is no longer the LLM driver. The new binding is fresh,
15
+ * the old session dir is preserved on disk.
16
+ *
17
+ * The OLD outer session is now stale (defect A from the PRD). peaks-code
18
+ * Step 1 would otherwise pick up the old `mode` field and silently lock the
19
+ * new session into a mode the user never explicitly chose. Clear it here so
20
+ * Step 1's presence:check-stale reports `reason: 'no-presence'` and the re-ask
21
+ * fires.
22
+ */
23
+ function pushRotationActions(nextActions, rotation, projectRoot, sessionId) {
24
+ if (rotation.previousSessionId === null || rotation.reason !== 'outer-session-mismatch')
25
+ return;
26
+ nextActions.push(`Auto-rotated session binding: outer session id changed (was "${rotation.previousSessionId}"). ` +
27
+ `New binding is "${sessionId}". The previous session dir is preserved at .peaks/_runtime/${rotation.previousSessionId}/. ` +
28
+ `Re-run with --no-rotate-on-outer-mismatch to suppress this rotation.`);
29
+ const presenceClearOutcome = clearStalePresenceOnRotation({
30
+ projectRootOverride: projectRoot,
31
+ currentOuterSessionId: process.env.PEAKS_OUTER_SESSION_ID ?? process.env.CLAUDE_CODE_SESSION_ID,
32
+ rotatedOutSessionId: rotation.previousSessionId
33
+ });
34
+ if (presenceClearOutcome.cleared) {
35
+ nextActions.push(`Auto-cleared stale skill presence (recorded outer id "${presenceClearOutcome.recordedOuter ?? '?'}" did not match the new outer session). ` +
36
+ 'peaks-code Step 1 will now AskUserQuestion to confirm the mode.');
37
+ }
38
+ else if (presenceClearOutcome.reason === 'recorded-by-different-outer') {
39
+ nextActions.push(`Kept skill presence: it was recorded by a different live outer session (id "${presenceClearOutcome.recordedOuter ?? '?'}"). ` +
40
+ 'The new outer session will not auto-clear it.');
41
+ }
42
+ else if (presenceClearOutcome.reason === 'not-stale') {
43
+ nextActions.push('Kept skill presence: it was re-stamped by the new outer session during the rotation window (not stale).');
44
+ }
45
+ }
46
+ function pushCreatedAction(nextActions, report) {
47
+ if (report.created.length === 0) {
48
+ nextActions.push('Workspace already initialized — proceed to project scan.');
49
+ return;
50
+ }
51
+ nextActions.push('Run `peaks scan archetype --project <path> --json` next to populate rd/project-scan.md.');
52
+ }
53
+ /**
54
+ * Slice 2.0.1-bug3-fact-forcing-bypass: surface the consumer-project
55
+ * .claude/settings.local.json materialization outcome. When the bypass is in
56
+ * effect, the LLM knows subsequent Writes and Bash calls targeting .peaks/**
57
+ * will not be blocked by the [Fact-Forcing Gate]. When the user opted out, we
58
+ * surface a nextAction so the manual recovery is documented.
59
+ *
60
+ * The `refreshed` offline-template nextAction also carries a loud warning that
61
+ * any MANUAL EDITS the user made to the offline template have been overwritten
62
+ * — drift detection cannot tell stale-from-prior-release apart from
63
+ * user-customised, so we surface the warning unconditionally to make sure
64
+ * anyone who customised sees the prompt.
65
+ */
66
+ function pushSettingsActions(nextActions, report) {
67
+ if (report.claudeSettings.action === 'written' || report.claudeSettings.action === 'refreshed') {
68
+ nextActions.push(`Materialized .claude/settings.local.json (action: ${report.claudeSettings.action}) — ` +
69
+ `the [Fact-Forcing Gate] is bypassed for tool calls inside .peaks/**. ` +
70
+ 'Restart Claude Code so the hooks take effect.');
71
+ }
72
+ else if (report.claudeSettings.action === 'already-current') {
73
+ // No-op: the bypass is already in effect and matches the
74
+ // current release. Do not spam the nextAction list on every
75
+ // init.
76
+ }
77
+ else if (report.claudeSettings.action === 'skipped') {
78
+ nextActions.push('Skipped .claude/settings.local.json materialization (--no-claude-hooks). ' +
79
+ 'If the [Fact-Forcing Gate] blocks subsequent Writes, run `peaks workspace init` ' +
80
+ 'again without --no-claude-hooks, or drop the contents of ' +
81
+ '`.peaks/.claude-settings-template.json` into `.claude/settings.local.json` manually.');
82
+ }
83
+ if (report.claudeSettings.offlineTemplate.action === 'refreshed') {
84
+ nextActions.push(`Self-healed .peaks/.claude-settings-template.json (action: refreshed) — ` +
85
+ 'the offline recovery anchor now matches the current peaks-loop template. ' +
86
+ 'No action required; future manual recoveries will copy the corrected wrapper.');
87
+ nextActions.push('⚠️ If you had manually edited .peaks/.claude-settings-template.json, ' +
88
+ 'those edits have been overwritten by the self-heal. ' +
89
+ 'Re-apply your custom matchers / commands on top of the freshly-written template, ' +
90
+ 'or open an issue if your customisation is a recurring need (the team may promote it to the canonical template).');
91
+ }
92
+ else if (report.claudeSettings.offlineTemplate.action === 'written') {
93
+ nextActions.push(`Wrote .peaks/.claude-settings-template.json (action: written) — ` +
94
+ 'the offline recovery anchor is now in place for future manual recoveries.');
95
+ }
96
+ }
97
+ function pushHooksActions(nextActions, hooksOutcome) {
98
+ if (hooksOutcome.decision === 'installed') {
99
+ nextActions.push(hooksOutcome.action === 'reinstalled'
100
+ ? 'Re-installed the peaks-managed PreToolUse hooks (Bash→gate enforce, Task→progress start) — the marker said installed but the hooks were missing.'
101
+ : 'Installed the peaks-managed PreToolUse hooks (Bash→gate enforce, Task→progress start). Restart Claude Code so the hooks take effect.');
102
+ }
103
+ else if (hooksOutcome.action === 'first-decision' && hooksOutcome.decision === 'skipped') {
104
+ nextActions.push('Skipped peaks-managed hook install for this project. Re-run with --install-hooks=auto (or peaks hooks install) to install later.');
105
+ }
106
+ }
107
+ /**
108
+ * Slice 4.0.8 (D3): after session binding, run the same canonical GC sweep
109
+ * `peaks skill presence:set` would perform. A `peaks workspace init` is a
110
+ * natural sweep trigger (the session id was just minted, all prior leases for
111
+ * the project are by definition same-project). Failures surface as warnings;
112
+ * the GC never blocks init.
113
+ */
114
+ async function collectLeaseSweepWarning(warnings, projectRoot) {
115
+ try {
116
+ const gcResult = await gcStalePresenceLeases({
117
+ projectRoot,
118
+ trigger: 'workspace-init'
119
+ });
120
+ if (gcResult.removed > 0) {
121
+ warnings.push(`Stale lease sweep removed ${gcResult.removed} lease(s) for the canonical project (retained ${gcResult.retained}).`);
122
+ }
123
+ }
124
+ catch (err) {
125
+ warnings.push(`lease sweep failed: ${getErrorMessage(err)}`);
126
+ }
127
+ }
128
+ /**
129
+ * When the consumer project's `.claude/rules/` is missing or empty, emit the
130
+ * copy-pasteable diagnostic into the JSON envelope's `warnings` array AND
131
+ * surface the structured descriptor. AC7: the diagnostic banner is skipped on
132
+ * subsequent invocations within the same session — the once-per-session marker
133
+ * `.peaks/_runtime/<sid>/.standards-checked` is written after the FIRST emit.
134
+ * AC3: when --init-standards was passed, `report.standardsApplied` lists the
135
+ * freshly-written files, surfaced as a nextAction.
136
+ */
137
+ function pushStandardsActions(nextActions, warnings, ctx) {
138
+ const { report, projectRoot, sessionId } = ctx;
139
+ if (report.standardsMissing.missing && !hasStandardsCheckedMarker(projectRoot, sessionId)) {
140
+ warnings.push(report.standardsMissing.remediation);
141
+ nextActions.push(`Run \`peaks workspace init --init-standards --project ${projectRoot}\` to auto-apply the scaffold, or \`peaks standards init --project ${projectRoot} --apply\` manually.`);
142
+ }
143
+ if (report.standardsApplied !== undefined) {
144
+ nextActions.push(`Auto-applied .claude/rules/${report.standardsApplied.language}/ scaffold (slice 2026-06-16-peaks-code-auto-scaffold): ` +
145
+ `wrote ${report.standardsApplied.writtenFiles.length} file(s), ` +
146
+ `kept ${report.standardsApplied.skippedFiles.length} existing file(s).`);
147
+ }
148
+ }
149
+ /**
150
+ * The project-scan bootstrap outcome. The envelope carries the write counts and
151
+ * duration so the LLM (and the human) see what landed. The nextAction only
152
+ * fires when the project-scan tree is fresh — idempotent re-runs are silent to
153
+ * keep the nextAction list scannable.
154
+ */
155
+ function pushProjectScanActions(nextActions, warnings, ctx) {
156
+ const { projectScanError, projectScanEnvelope, projectRoot } = ctx;
157
+ if (projectScanError !== null) {
158
+ warnings.push(`project-scan bootstrap failed: ${projectScanError}`);
159
+ }
160
+ else if (projectScanEnvelope !== null && projectScanEnvelope.created) {
161
+ nextActions.push(`Bootstrapped .peaks/project-scan/ (project-scan.md + 4 audit/business templates) — ` +
162
+ `${projectScanEnvelope.templatesBooted} file(s) written, ${projectScanEnvelope.templatesSkipped} preserved. ` +
163
+ `Run \`peaks scan archetype --project ${projectRoot}\` and \`peaks scan libraries --project ${projectRoot}\` next to refresh the scan.`);
164
+ }
165
+ }
166
+ /** Write the once-per-session marker AFTER the envelope is built (so subsequent
167
+ * inits skip the warning even on rapid back-to-back calls). */
168
+ function markStandardsCheckedIfMissing(ctx) {
169
+ if (!ctx.report.standardsMissing.missing)
170
+ return;
171
+ markStandardsChecked(ctx.projectRoot, ctx.sessionId);
172
+ }
173
+ /** Collect the envelope's nextActions + warnings in the original push order. */
174
+ export async function collectInitEnvelope(ctx) {
175
+ const nextActions = [];
176
+ const warnings = [];
177
+ pushBindingReplacedAction(nextActions, ctx.report);
178
+ pushRotationActions(nextActions, ctx.rotation, ctx.projectRoot, ctx.sessionId);
179
+ pushCreatedAction(nextActions, ctx.report);
180
+ pushSettingsActions(nextActions, ctx.report);
181
+ // First-time hooks install decision. Sticky-marker at
182
+ // .peaks/.peaks-init-hooks-decision.json records the user's answer
183
+ // (or the auto-decision) so subsequent inits for new sessions in the
184
+ // same project do not re-prompt. The marker is the only state that
185
+ // survives across sessions — without it, every new session would
186
+ // re-trigger the question.
187
+ const hooksOutcome = await resolveFirstTimeHooksInstall({
188
+ projectRoot: ctx.projectRoot,
189
+ ...(ctx.options.installHooks !== undefined ? { explicitMode: ctx.options.installHooks } : {}),
190
+ jsonMode: ctx.options.json === true
191
+ });
192
+ pushHooksActions(nextActions, hooksOutcome);
193
+ await collectLeaseSweepWarning(warnings, ctx.projectRoot);
194
+ pushStandardsActions(nextActions, warnings, ctx);
195
+ pushProjectScanActions(nextActions, warnings, ctx);
196
+ markStandardsCheckedIfMissing(ctx);
197
+ const codegraphAutoOutcome = await stakeCodegraphForInit(nextActions, warnings, ctx.projectRoot);
198
+ return { nextActions, warnings, hooksOutcome, codegraphAutoOutcome };
199
+ }
@@ -0,0 +1,10 @@
1
+ import type { CodegraphAutoStakeOutcome } from './init-options.js';
2
+ /**
3
+ * Run a REAL upstream `codegraph init` (not just mkdir + marker) so the schema
4
+ * actually has a `codegraph.db`, which is what post-slice auto-refresh and the
5
+ * pre-dispatch preflight gate on. `codegraph init` (WITHOUT `--index`) is fast
6
+ * (~1 s) and offline-safe — it only `Parser.init()`s WASM grammars that resolve
7
+ * from node_modules; the slow/offline concern applies to `index` (full build),
8
+ * not `init`.
9
+ */
10
+ export declare function stakeCodegraphForInit(nextActions: string[], warnings: string[], projectRoot: string): Promise<CodegraphAutoStakeOutcome | null>;
@@ -0,0 +1,54 @@
1
+ // Split out of `workspace/init-command.ts`: the
2
+ // best-effort `codegraph init` stake that runs after a successful workspace
3
+ // init. Never fails the init — every failure lands in the envelope's warnings.
4
+ import { mkdirSync } from 'node:fs';
5
+ import { createCodegraphInvocation, defaultCodegraphInitGuard, executeCodegraphInvocation, writeCodegraphMarker } from '../../../services/codegraph/codegraph-service.js';
6
+ import { getErrorMessage } from '../../cli-helpers.js';
7
+ /**
8
+ * Upstream `codegraph init` creates `.codegraph/`; mkdir is a no-op in the real
9
+ * path and lets the marker write succeed. Best-effort.
10
+ */
11
+ async function stakeFreshCodegraph(nextActions, warnings, projectRoot, codegraphDir) {
12
+ const initResult = await executeCodegraphInvocation(createCodegraphInvocation({ subcommand: 'init', project: projectRoot }));
13
+ if (initResult.exitCode !== 0) {
14
+ warnings.push(`codegraph auto-stake init failed (exit ${String(initResult.exitCode)}). ` +
15
+ 'Run `peaks codegraph init --project <path>` manually to enable codegraph.');
16
+ return null;
17
+ }
18
+ mkdirSync(codegraphDir, { recursive: true });
19
+ writeCodegraphMarker(codegraphDir);
20
+ nextActions.push(`Auto-staked a peaks-loop-managed ${codegraphDir}/ (upstream init + marker). ` +
21
+ 'Run `peaks codegraph index --project <path>` next to build the SQLite-backed index.');
22
+ return { status: 'fresh' };
23
+ }
24
+ /**
25
+ * Run a REAL upstream `codegraph init` (not just mkdir + marker) so the schema
26
+ * actually has a `codegraph.db`, which is what post-slice auto-refresh and the
27
+ * pre-dispatch preflight gate on. `codegraph init` (WITHOUT `--index`) is fast
28
+ * (~1 s) and offline-safe — it only `Parser.init()`s WASM grammars that resolve
29
+ * from node_modules; the slow/offline concern applies to `index` (full build),
30
+ * not `init`.
31
+ */
32
+ export async function stakeCodegraphForInit(nextActions, warnings, projectRoot) {
33
+ let outcome = null;
34
+ try {
35
+ const guard = defaultCodegraphInitGuard(projectRoot);
36
+ if (guard.status === 'fresh') {
37
+ // 'fresh' here also covers the dangling state (marker present but
38
+ // no codegraph.db) — running init self-heals both.
39
+ outcome = await stakeFreshCodegraph(nextActions, warnings, projectRoot, guard.codegraphDir);
40
+ }
41
+ else if (guard.status === 'noop-already-peaks-loop') {
42
+ outcome = { status: 'noop' };
43
+ }
44
+ else {
45
+ outcome = { status: 'conflict' };
46
+ warnings.push(`${guard.codegraphDir} already exists with a non-peaks-loop schema; ` +
47
+ 'refusing to auto-init codegraph. Run `peaks codegraph init --project <path>` after moving the foreign directory.');
48
+ }
49
+ }
50
+ catch (err) {
51
+ warnings.push(`codegraph auto-stake failed: ${getErrorMessage(err)}`);
52
+ }
53
+ return outcome;
54
+ }
@@ -1,133 +1,17 @@
1
1
  /**
2
+ * `peaks workspace init` — the registrar.
2
3
  *
3
4
  * Extracted from `src/cli/commands/workspace-commands.ts` (slice
4
- * 800-line Karpathy cap. Owns:
5
- * - commander option wiring (`--project`, `--session-id`, `--change-id`, etc.)
6
- * - canonical project-root resolution
7
- * - session id resolution (with slice-018 rotation)
8
- * - first-time hooks install prompt + sticky marker
9
- * - missing-standards diagnostic surface (AC1-AC7) and `--init-standards` apply
5
+ * 800-line Karpathy cap). Split further by responsibility.
6
+ * The option/outcome shapes, the first-time hooks
7
+ * decision, project-root + session resolution, the nextAction/warning
8
+ * collectors, the codegraph stake, the envelope builder and the typed failure
9
+ * arms each live in their own module under `./`. This file wires them up.
10
10
  *
11
11
  * Imports the shared hooks-decision marker helpers from `./helpers.ts`.
12
12
  */
13
13
  import type { Command } from 'commander';
14
14
  import { type ProgramIO } from '../../cli-helpers.js';
15
- import { type HooksDecision } from './helpers.js';
16
- export type WorkspaceInitOptions = {
17
- project: string;
18
- sessionId?: string;
19
- json?: boolean;
20
- allowSessionRebind?: boolean;
21
- /**
22
- * flag is `--no-rotate-on-outer-mismatch`; commander strips the
23
- * `--no-` prefix and assigns the boolean to this property (default
24
- * `true`, set to `false` when the flag is passed). The wrapper
25
- * reads this as `=== false` to opt out. The presence file still
26
- * records `outerSessionMismatch` regardless of the flag's value.
27
- */
28
- rotateOnOuterMismatch?: boolean;
29
- /**
30
- * How to handle the first-time "install peaks hooks" prompt.
31
- * - ask (default in TTY): prompt the user once, sticky-marker the answer
32
- * - auto (default in --json / non-TTY): install silently, sticky-marker installed
33
- * - skip: write sticky-marker skipped, do not install
34
- * After the first decision the sticky marker wins, regardless of --install-hooks
35
- * (re-runs respect the recorded decision; only re-install when the marker says
36
- * installed but the hooks have been removed out from under us).
37
- */
38
- installHooks?: 'ask' | 'auto' | 'skip';
39
- /**
40
- * Slice 2.0.1-bug3-fact-forcing-bypass: opt out of writing the
41
- * consumer-project `.claude/settings.local.json` file. Default
42
- * (commander `--no-` prefix) is `true`; pass `--no-claude-hooks` to
43
- * set this to `false`. The wrapper reads this as `=== false` to
44
- * skip the materialization. The bypass is documented in
45
- * `peaks-code/references/anchoring-and-session-info.md`.
46
- */
47
- claudeHooks?: boolean;
48
- /**
49
- * auto-scaffold `.claude/rules/{common,<language>}/` when missing.
50
- * Default `false` — the diagnostic fires but no write happens.
51
- * Set to `true` (via `--init-standards`) to also run
52
- * `executeProjectStandardsInit({ projectRoot, apply: true })`.
53
- */
54
- initStandards?: boolean;
55
- /**
56
- * commander-style `--no-project-scan-bootstrap` opt-out. Default
57
- * (no flag) leaves this `undefined` (treated as `true`). Pass the
58
- * flag to set `options.projectScanBootstrap === false`, which the
59
- * caller reads as `=== false` to skip the bootstrap call.
60
- */
61
- projectScanBootstrap?: boolean;
62
- /**
63
- * `--force-project-scan-templates` flag. Default (no flag)
64
- * leaves this `undefined`. Pass the flag to set
65
- * `options.forceProjectScanTemplates === true`, which forces the
66
- * bootstrap service to overwrite the 4 bundled audit/business
67
- * templates even when they already exist (sediment is preserved
68
- * otherwise).
69
- */
70
- forceProjectScanTemplates?: boolean;
71
- };
72
- /**
73
- * Outcome of the first-time "install peaks hooks" decision attached to
74
- * `peaks workspace init`. Reported in the response data so the LLM and
75
- * the human both see what happened.
76
- */
77
- export type FirstTimeHooksInstallOutcome = {
78
- /** The decision recorded (or already on file) in the sticky marker. */
79
- decision: HooksDecision;
80
- /**
81
- * What the install path actually did this call.
82
- * - first-decision: we recorded a brand-new sticky marker (and may have installed)
83
- * - reinstalled: the marker said installed but the hooks were missing — we re-applied
84
- * - marker-honored: the marker already existed; we did not touch the hooks
85
- * - already-installed: the hooks were already present and the marker does not exist yet
86
- * (we write a fresh marker to lock in the answer for next time)
87
- */
88
- action: 'first-decision' | 'reinstalled' | 'marker-honored' | 'already-installed';
89
- scope: 'project' | 'global';
90
- /**
91
- * Why the action was the way it was (e.g. "stdin-not-tty", "user-answered-no",
92
- * "marker-installed-hooks-missing"). Surfaced for forensics.
93
- */
94
- reason?: string;
95
- };
96
- export type ResolveFirstTimeHooksInstallOptions = {
97
- projectRoot: string;
98
- /**
99
- * Explicit mode from the --install-hooks flag. When omitted, the default
100
- * is "ask" in TTY mode and "auto" otherwise (see `defaultMode` logic).
101
- */
102
- explicitMode?: 'ask' | 'auto' | 'skip' | undefined;
103
- /**
104
- * Whether the caller is in --json mode. In --json mode we never prompt
105
- * (the LLM cannot answer an interactive question) — we silently treat
106
- * "ask" as "auto" and proceed.
107
- */
108
- jsonMode: boolean;
109
- };
15
+ export { resolveFirstTimeHooksInstall } from './init-hooks-decision.js';
16
+ export type { FirstTimeHooksInstallOutcome, ResolveFirstTimeHooksInstallOptions, WorkspaceInitOptions } from './init-options.js';
110
17
  export declare function registerWorkspaceInitCommand(workspace: Command, io: ProgramIO): void;
111
- /**
112
- * Resolve the first-time "install peaks hooks" decision for this project.
113
- * Decision tree:
114
- *
115
- * 1. Read the sticky marker.
116
- * - Marker present:
117
- * - marker.decision === 'installed' AND hooks are present → action: marker-honored, no side effects
118
- * - marker.decision === 'installed' AND hooks are MISSING → re-install, action: reinstalled
119
- * - marker.decision === 'skipped' → action: marker-honored, no install
120
- * - Marker absent:
121
- * - hooks already present → write a fresh 'installed' marker, action: already-installed
122
- * - otherwise:
123
- * - explicit --install-hooks=auto → install + marker, action: first-decision
124
- * - explicit --install-hooks=skip → marker only, action: first-decision
125
- * - explicit --install-hooks=ask OR default in TTY:
126
- * - jsonMode → silently auto-install (LLM cannot answer), action: first-decision
127
- * - TTY → prompt; on yes install + marker, on no marker-only
128
- * - default in non-TTY → auto-install, action: first-decision
129
- *
130
- * Project scope is the only supported scope here; global scope is reserved
131
- * for explicit `peaks hooks install --global` invocations.
132
- */
133
- export declare function resolveFirstTimeHooksInstall(options: ResolveFirstTimeHooksInstallOptions): Promise<FirstTimeHooksInstallOutcome>;