@entelligentsia/forgecli 0.21.0 → 1.0.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 (364) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +31 -33
  3. package/dist/CHANGELOG-forge-plugin.md +142 -0
  4. package/dist/CHANGELOG-pi.md +24 -1
  5. package/dist/bin/forgecli.d.ts +2 -0
  6. package/dist/bin/forgecli.js +6 -0
  7. package/dist/bin/forgecli.js.map +1 -0
  8. package/dist/extensions/forgecli/add-pipeline.js +1 -1
  9. package/dist/extensions/forgecli/add-pipeline.js.map +1 -1
  10. package/dist/extensions/forgecli/add-task.js +1 -1
  11. package/dist/extensions/forgecli/add-task.js.map +1 -1
  12. package/dist/extensions/forgecli/approve.js +17 -2
  13. package/dist/extensions/forgecli/approve.js.map +1 -1
  14. package/dist/extensions/forgecli/audience-gate.js +1 -1
  15. package/dist/extensions/forgecli/audience-gate.js.map +1 -1
  16. package/dist/extensions/forgecli/calibrate.js +11 -8
  17. package/dist/extensions/forgecli/calibrate.js.map +1 -1
  18. package/dist/extensions/forgecli/collate.js +1 -1
  19. package/dist/extensions/forgecli/collate.js.map +1 -1
  20. package/dist/extensions/forgecli/commit.js +17 -2
  21. package/dist/extensions/forgecli/commit.js.map +1 -1
  22. package/dist/extensions/forgecli/enhance.js +1 -1
  23. package/dist/extensions/forgecli/enhance.js.map +1 -1
  24. package/dist/extensions/forgecli/fix-bug.d.ts +1 -2
  25. package/dist/extensions/forgecli/fix-bug.js +678 -609
  26. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  27. package/dist/extensions/forgecli/forge-artifact-tool.d.ts +6 -8
  28. package/dist/extensions/forgecli/forge-artifact-tool.js +94 -197
  29. package/dist/extensions/forgecli/forge-artifact-tool.js.map +1 -1
  30. package/dist/extensions/forgecli/forge-commands.js +57 -18
  31. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  32. package/dist/extensions/forgecli/forge-init/phase4-register.js +6 -7
  33. package/dist/extensions/forgecli/forge-init/phase4-register.js.map +1 -1
  34. package/dist/extensions/forgecli/forge-init/run-phases.d.ts +4 -0
  35. package/dist/extensions/forgecli/forge-init/run-phases.js +304 -0
  36. package/dist/extensions/forgecli/forge-init/run-phases.js.map +1 -0
  37. package/dist/extensions/forgecli/forge-init/verifiers.d.ts +14 -5
  38. package/dist/extensions/forgecli/forge-init/verifiers.js +79 -62
  39. package/dist/extensions/forgecli/forge-init/verifiers.js.map +1 -1
  40. package/dist/extensions/forgecli/forge-init.js +131 -76
  41. package/dist/extensions/forgecli/forge-init.js.map +1 -1
  42. package/dist/extensions/forgecli/forge-subagent.d.ts +26 -0
  43. package/dist/extensions/forgecli/forge-subagent.js +42 -18
  44. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  45. package/dist/extensions/forgecli/forge-tools.d.ts +34 -4
  46. package/dist/extensions/forgecli/forge-tools.js +191 -79
  47. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  48. package/dist/extensions/forgecli/health-check.js +3 -3
  49. package/dist/extensions/forgecli/health-check.js.map +1 -1
  50. package/dist/extensions/forgecli/hook-dispatcher.d.ts +1 -1
  51. package/dist/extensions/forgecli/hooks/check-update.d.ts +8 -0
  52. package/dist/extensions/forgecli/hooks/check-update.js +29 -1
  53. package/dist/extensions/forgecli/hooks/check-update.js.map +1 -1
  54. package/dist/extensions/forgecli/hooks/post-init-hook.js +6 -6
  55. package/dist/extensions/forgecli/hooks/post-init-hook.js.map +1 -1
  56. package/dist/extensions/forgecli/hooks/post-sprint-hook.js +6 -6
  57. package/dist/extensions/forgecli/hooks/post-sprint-hook.js.map +1 -1
  58. package/dist/extensions/forgecli/hooks/triage-error.js +1 -0
  59. package/dist/extensions/forgecli/hooks/triage-error.js.map +1 -1
  60. package/dist/extensions/forgecli/implement.js +20 -2
  61. package/dist/extensions/forgecli/implement.js.map +1 -1
  62. package/dist/extensions/forgecli/index.js +39 -32
  63. package/dist/extensions/forgecli/index.js.map +1 -1
  64. package/dist/extensions/forgecli/lib/pipeline-guard.d.ts +41 -0
  65. package/dist/extensions/forgecli/lib/pipeline-guard.js +100 -0
  66. package/dist/extensions/forgecli/lib/pipeline-guard.js.map +1 -0
  67. package/dist/extensions/forgecli/loaders/persona-skill-loader.js +2 -2
  68. package/dist/extensions/forgecli/loaders/persona-skill-loader.js.map +1 -1
  69. package/dist/extensions/forgecli/migrate.d.ts +3 -0
  70. package/dist/extensions/forgecli/migrate.js +4 -2
  71. package/dist/extensions/forgecli/migrate.js.map +1 -1
  72. package/dist/extensions/forgecli/plan.js +21 -2
  73. package/dist/extensions/forgecli/plan.js.map +1 -1
  74. package/dist/extensions/forgecli/quiz-agent.js +7 -7
  75. package/dist/extensions/forgecli/quiz-agent.js.map +1 -1
  76. package/dist/extensions/forgecli/regenerate.js +49 -18
  77. package/dist/extensions/forgecli/regenerate.js.map +1 -1
  78. package/dist/extensions/forgecli/remove-command.js +1 -1
  79. package/dist/extensions/forgecli/remove-command.js.map +1 -1
  80. package/dist/extensions/forgecli/report-bug.js +1 -1
  81. package/dist/extensions/forgecli/report-bug.js.map +1 -1
  82. package/dist/extensions/forgecli/retrospective.js +9 -9
  83. package/dist/extensions/forgecli/retrospective.js.map +1 -1
  84. package/dist/extensions/forgecli/review-code.d.ts +13 -0
  85. package/dist/extensions/forgecli/review-code.js +62 -3
  86. package/dist/extensions/forgecli/review-code.js.map +1 -1
  87. package/dist/extensions/forgecli/review-plan.d.ts +13 -0
  88. package/dist/extensions/forgecli/review-plan.js +65 -3
  89. package/dist/extensions/forgecli/review-plan.js.map +1 -1
  90. package/dist/extensions/forgecli/run-task.js +461 -391
  91. package/dist/extensions/forgecli/run-task.js.map +1 -1
  92. package/dist/extensions/forgecli/session-registry.d.ts +12 -0
  93. package/dist/extensions/forgecli/session-registry.js +23 -0
  94. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  95. package/dist/extensions/forgecli/skill-curator-subagent.d.ts +2 -1
  96. package/dist/extensions/forgecli/skill-curator-subagent.js +2 -1
  97. package/dist/extensions/forgecli/skill-curator-subagent.js.map +1 -1
  98. package/dist/extensions/forgecli/sprint-intake.js +6 -6
  99. package/dist/extensions/forgecli/sprint-intake.js.map +1 -1
  100. package/dist/extensions/forgecli/sprint-plan.js +9 -9
  101. package/dist/extensions/forgecli/sprint-plan.js.map +1 -1
  102. package/dist/extensions/forgecli/status-command.js +1 -1
  103. package/dist/extensions/forgecli/status-command.js.map +1 -1
  104. package/dist/extensions/forgecli/store-query.js +11 -11
  105. package/dist/extensions/forgecli/store-query.js.map +1 -1
  106. package/dist/extensions/forgecli/store-repair.js +7 -7
  107. package/dist/extensions/forgecli/store-repair.js.map +1 -1
  108. package/dist/extensions/forgecli/subagent/caller-context.d.ts +35 -11
  109. package/dist/extensions/forgecli/subagent/caller-context.js +49 -21
  110. package/dist/extensions/forgecli/subagent/caller-context.js.map +1 -1
  111. package/dist/extensions/forgecli/subagent/orchestrator-transcript.d.ts +66 -0
  112. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js +66 -0
  113. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js.map +1 -0
  114. package/dist/extensions/forgecli/subagent/phase-guard.d.ts +34 -0
  115. package/dist/extensions/forgecli/subagent/phase-guard.js +139 -0
  116. package/dist/extensions/forgecli/subagent/phase-guard.js.map +1 -0
  117. package/dist/extensions/forgecli/subagent/phase-summary-map.d.ts +1 -0
  118. package/dist/extensions/forgecli/subagent/phase-summary-map.js +22 -0
  119. package/dist/extensions/forgecli/subagent/phase-summary-map.js.map +1 -0
  120. package/dist/extensions/forgecli/thread-switcher.js +2 -2
  121. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  122. package/dist/extensions/forgecli/validate.js +17 -2
  123. package/dist/extensions/forgecli/validate.js.map +1 -1
  124. package/dist/extensions/forgecli/viewport-events.d.ts +4 -0
  125. package/dist/extensions/forgecli/viewport-events.js +18 -1
  126. package/dist/extensions/forgecli/viewport-events.js.map +1 -1
  127. package/dist/extensions/forgecli/viewport-renderer.d.ts +12 -2
  128. package/dist/extensions/forgecli/viewport-renderer.js +8 -6
  129. package/dist/extensions/forgecli/viewport-renderer.js.map +1 -1
  130. package/dist/forge-payload/.base-pack/commands/check-agent.md +22 -0
  131. package/dist/forge-payload/.base-pack/commands/new-sprint.md +22 -0
  132. package/dist/forge-payload/.base-pack/commands/plan-sprint.md +22 -0
  133. package/dist/forge-payload/.base-pack/commands/quiz-agent.md +2 -18
  134. package/dist/forge-payload/.base-pack/commands/retro.md +22 -0
  135. package/dist/forge-payload/.base-pack/commands/retrospective.md +2 -18
  136. package/dist/forge-payload/.base-pack/commands/sprint-intake.md +2 -18
  137. package/dist/forge-payload/.base-pack/commands/sprint-plan.md +2 -18
  138. package/dist/forge-payload/.base-pack/workflows/_fragments/friction-emit.md +2 -2
  139. package/dist/forge-payload/.base-pack/workflows/_fragments/generation-instructions.md +4 -4
  140. package/dist/forge-payload/.base-pack/workflows/_fragments/iron-laws.md +1 -1
  141. package/dist/forge-payload/.base-pack/workflows/architect_approve.md +13 -1
  142. package/dist/forge-payload/.base-pack/workflows/commit_task.md +12 -1
  143. package/dist/forge-payload/.base-pack/workflows/enhance.md +6 -6
  144. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +11 -29
  145. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +14 -2
  146. package/dist/forge-payload/.base-pack/workflows/migrate_structural.md +2 -2
  147. package/dist/forge-payload/.base-pack/workflows/orchestrate_task.md +20 -4
  148. package/dist/forge-payload/.base-pack/workflows/plan_task.md +14 -2
  149. package/dist/forge-payload/.base-pack/workflows/review_code.md +37 -7
  150. package/dist/forge-payload/.base-pack/workflows/review_plan.md +36 -6
  151. package/dist/forge-payload/.base-pack/workflows/run_sprint.md +2 -2
  152. package/dist/forge-payload/.base-pack/workflows/triage.md +190 -0
  153. package/dist/forge-payload/.base-pack/workflows/validate_task.md +37 -7
  154. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  155. package/dist/forge-payload/.schemas/config.schema.json +0 -5
  156. package/dist/forge-payload/.schemas/enum-catalog.json +9 -13
  157. package/dist/forge-payload/.schemas/migrations.json +63 -0
  158. package/dist/forge-payload/agents/tomoshibi.md +150 -6
  159. package/dist/forge-payload/commands/add-pipeline.md +1 -1
  160. package/dist/forge-payload/commands/add-task.md +1 -1
  161. package/dist/forge-payload/commands/calibrate.md +4 -350
  162. package/dist/forge-payload/commands/check-agent.md +38 -0
  163. package/dist/forge-payload/commands/config.md +3 -113
  164. package/dist/forge-payload/commands/enhance.md +5 -32
  165. package/dist/forge-payload/commands/health.md +155 -13
  166. package/dist/forge-payload/commands/init.md +25 -31
  167. package/dist/forge-payload/commands/migrate.md +6 -154
  168. package/dist/forge-payload/commands/quiz-agent.md +2 -34
  169. package/dist/forge-payload/commands/rebuild.md +664 -0
  170. package/dist/forge-payload/commands/regenerate.md +2 -774
  171. package/dist/forge-payload/commands/remove.md +10 -13
  172. package/dist/forge-payload/commands/repair.md +187 -0
  173. package/dist/forge-payload/commands/search.md +73 -0
  174. package/dist/forge-payload/commands/status.md +105 -0
  175. package/dist/forge-payload/commands/store-query.md +2 -69
  176. package/dist/forge-payload/commands/store-repair.md +2 -183
  177. package/dist/forge-payload/commands/update-tools.md +4 -50
  178. package/dist/forge-payload/commands/update.md +64 -58
  179. package/dist/forge-payload/hooks/check-update.cjs +1 -1
  180. package/dist/forge-payload/hooks/post-init.cjs +2 -2
  181. package/dist/forge-payload/hooks/post-sprint.cjs +2 -2
  182. package/dist/forge-payload/hooks/triage-error.cjs +11 -10
  183. package/dist/forge-payload/init/phases/phase-1-collect.md +138 -0
  184. package/dist/forge-payload/init/phases/phase-2-discover.md +127 -0
  185. package/dist/forge-payload/init/phases/phase-3-materialize.md +113 -0
  186. package/dist/forge-payload/init/phases/phase-4-register.md +159 -0
  187. package/dist/forge-payload/integrity.json +21 -24
  188. package/dist/forge-payload/meta/fragments/tool-discipline.md +41 -0
  189. package/dist/forge-payload/meta/templates/meta-retro.md +28 -0
  190. package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +2 -2
  191. package/dist/forge-payload/meta/workflows/_fragments/generation-instructions.md +4 -4
  192. package/dist/forge-payload/meta/workflows/_fragments/iron-laws.md +1 -1
  193. package/dist/forge-payload/meta/workflows/meta-approve.md +13 -1
  194. package/dist/forge-payload/meta/workflows/meta-bug-triage.md +210 -0
  195. package/dist/forge-payload/meta/workflows/meta-check-agent.md +138 -0
  196. package/dist/forge-payload/meta/workflows/meta-commit.md +12 -1
  197. package/dist/forge-payload/meta/workflows/meta-enhance.md +5 -5
  198. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +11 -29
  199. package/dist/forge-payload/meta/workflows/meta-implement.md +13 -1
  200. package/dist/forge-payload/meta/workflows/meta-migrate.md +3 -3
  201. package/dist/forge-payload/meta/workflows/meta-new-sprint.md +84 -0
  202. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +20 -4
  203. package/dist/forge-payload/meta/workflows/meta-plan-sprint.md +152 -0
  204. package/dist/forge-payload/meta/workflows/meta-plan-task.md +13 -1
  205. package/dist/forge-payload/meta/workflows/meta-retro.md +73 -0
  206. package/dist/forge-payload/meta/workflows/meta-review-implementation.md +37 -7
  207. package/dist/forge-payload/meta/workflows/meta-review-plan.md +36 -6
  208. package/dist/forge-payload/meta/workflows/meta-validate.md +37 -7
  209. package/dist/forge-payload/schemas/config.schema.json +0 -5
  210. package/dist/forge-payload/schemas/enum-catalog.json +9 -13
  211. package/dist/forge-payload/schemas/structure-manifest.json +25 -8
  212. package/dist/forge-payload/tools/artifact.cjs +324 -0
  213. package/dist/forge-payload/tools/banners.cjs +3 -4
  214. package/dist/forge-payload/tools/build-context-pack.cjs +1 -1
  215. package/dist/forge-payload/tools/check-structure.cjs +8 -3
  216. package/dist/forge-payload/tools/store-cli.cjs +67 -7
  217. package/dist/forge-payload/tools/substitute-placeholders.cjs +1 -1
  218. package/dist/forge-payload/tools/verify-apply.cjs +75 -0
  219. package/dist/forge-payload/tools/verify-phase.cjs +259 -0
  220. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  221. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +0 -17
  222. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  223. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +21 -38
  224. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
  225. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  226. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +5 -4
  227. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  228. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +2 -1
  229. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  230. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +5 -2
  231. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
  232. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  233. package/node_modules/@earendil-works/pi-coding-agent/CHANGELOG.md +24 -1
  234. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.d.ts.map +1 -1
  235. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.js +2 -3
  236. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.js.map +1 -1
  237. package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.d.ts +1 -0
  238. package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.d.ts.map +1 -1
  239. package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.js +52 -22
  240. package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.js.map +1 -1
  241. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  242. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js +16 -4
  243. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  244. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  245. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js +45 -50
  246. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  247. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  248. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js +43 -81
  249. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  250. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  251. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.js +27 -12
  252. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.js.map +1 -1
  253. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  254. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js +2 -3
  255. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  256. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
  257. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js +3 -3
  258. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  259. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
  260. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js +5 -5
  261. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
  262. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.d.ts +2 -0
  263. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.d.ts.map +1 -1
  264. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js +37 -0
  265. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js.map +1 -1
  266. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  267. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +9 -8
  268. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  269. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  270. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js +20 -35
  271. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  272. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +3 -0
  273. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  274. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js +64 -7
  275. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  276. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  277. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +15 -3
  278. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  279. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.d.ts +3 -1
  280. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.d.ts.map +1 -1
  281. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.js +14 -8
  282. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.js.map +1 -1
  283. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.d.ts +30 -0
  284. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.d.ts.map +1 -0
  285. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.js +124 -0
  286. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.js.map +1 -0
  287. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.d.ts +2 -0
  288. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.d.ts.map +1 -0
  289. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.js +31 -0
  290. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.js.map +1 -0
  291. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.d.ts +7 -27
  292. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.d.ts.map +1 -1
  293. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.js +75 -115
  294. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.js.map +1 -1
  295. package/node_modules/@earendil-works/pi-coding-agent/docs/terminal-setup.md +6 -0
  296. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package.json +1 -1
  297. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  298. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package.json +1 -1
  299. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package.json +1 -1
  300. package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +12 -14
  301. package/node_modules/@earendil-works/pi-coding-agent/package.json +5 -5
  302. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts +3 -0
  303. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts.map +1 -0
  304. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js +53 -0
  305. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js.map +1 -0
  306. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts.map +1 -1
  307. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +4 -1
  308. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js.map +1 -1
  309. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +2 -0
  310. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  311. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +13 -1
  312. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  313. package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
  314. package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
  315. package/node_modules/@earendil-works/pi-tui/package.json +2 -2
  316. package/node_modules/@entelligentsia/forge-compress/dist/compressor.d.ts +6 -0
  317. package/node_modules/@entelligentsia/forge-compress/dist/compressor.js +137 -0
  318. package/node_modules/@entelligentsia/forge-compress/dist/entropy.d.ts +3 -0
  319. package/node_modules/@entelligentsia/forge-compress/dist/entropy.js +99 -0
  320. package/node_modules/@entelligentsia/forge-compress/dist/forge/entity.d.ts +8 -0
  321. package/node_modules/@entelligentsia/forge-compress/dist/forge/entity.js +149 -0
  322. package/node_modules/@entelligentsia/forge-compress/dist/forge/index.d.ts +7 -0
  323. package/node_modules/@entelligentsia/forge-compress/dist/forge/index.js +4 -0
  324. package/node_modules/@entelligentsia/forge-compress/dist/forge/markdown.d.ts +5 -0
  325. package/node_modules/@entelligentsia/forge-compress/dist/forge/markdown.js +92 -0
  326. package/node_modules/@entelligentsia/forge-compress/dist/forge/query.d.ts +7 -0
  327. package/node_modules/@entelligentsia/forge-compress/dist/forge/query.js +60 -0
  328. package/node_modules/@entelligentsia/forge-compress/dist/forge/validate.d.ts +1 -0
  329. package/node_modules/@entelligentsia/forge-compress/dist/forge/validate.js +82 -0
  330. package/node_modules/@entelligentsia/forge-compress/dist/index.d.ts +6 -0
  331. package/node_modules/@entelligentsia/forge-compress/dist/index.js +5 -0
  332. package/node_modules/@entelligentsia/forge-compress/dist/progressive.d.ts +1 -0
  333. package/node_modules/@entelligentsia/forge-compress/dist/progressive.js +108 -0
  334. package/node_modules/@entelligentsia/forge-compress/dist/strip.d.ts +4 -0
  335. package/node_modules/@entelligentsia/forge-compress/dist/strip.js +55 -0
  336. package/node_modules/@entelligentsia/forge-compress/dist/tokens.d.ts +2 -0
  337. package/node_modules/@entelligentsia/forge-compress/dist/tokens.js +17 -0
  338. package/node_modules/@entelligentsia/forge-compress/package.json +45 -0
  339. package/node_modules/@entelligentsia/forge-compress/src/__tests__/compress.test.ts +409 -0
  340. package/node_modules/@entelligentsia/forge-compress/src/compressor.ts +147 -0
  341. package/node_modules/@entelligentsia/forge-compress/src/entropy.ts +105 -0
  342. package/node_modules/@entelligentsia/forge-compress/src/forge/entity.ts +184 -0
  343. package/node_modules/@entelligentsia/forge-compress/src/forge/index.ts +10 -0
  344. package/node_modules/@entelligentsia/forge-compress/src/forge/markdown.ts +122 -0
  345. package/node_modules/@entelligentsia/forge-compress/src/forge/query.ts +105 -0
  346. package/node_modules/@entelligentsia/forge-compress/src/forge/validate.ts +86 -0
  347. package/node_modules/@entelligentsia/forge-compress/src/index.ts +22 -0
  348. package/node_modules/@entelligentsia/forge-compress/src/progressive.ts +123 -0
  349. package/node_modules/@entelligentsia/forge-compress/src/strip.ts +58 -0
  350. package/node_modules/@entelligentsia/forge-compress/src/tokens.ts +19 -0
  351. package/package.json +10 -15
  352. package/dist/extensions/forgecli/forge-init/phase-descriptors.d.ts +0 -72
  353. package/dist/extensions/forgecli/forge-init/phase-descriptors.js +0 -359
  354. package/dist/extensions/forgecli/forge-init/phase-descriptors.js.map +0 -1
  355. package/dist/extensions/forgecli/forge-init/prompts.d.ts +0 -10
  356. package/dist/extensions/forgecli/forge-init/prompts.js +0 -91
  357. package/dist/extensions/forgecli/forge-init/prompts.js.map +0 -1
  358. package/dist/extensions/forgecli/lib/store-error-remediation.d.ts +0 -65
  359. package/dist/extensions/forgecli/lib/store-error-remediation.js +0 -298
  360. package/dist/extensions/forgecli/lib/store-error-remediation.js.map +0 -1
  361. package/dist/forge-payload/hooks/check-update.js +0 -378
  362. package/dist/forge-payload/hooks/forge-permissions.js +0 -164
  363. package/dist/forge-payload/hooks/triage-error.js +0 -77
  364. package/dist/forge-payload/hooks/validate-write.js +0 -250
@@ -0,0 +1,123 @@
1
+ import { countTokens, truncateToTokenBudget } from "./tokens.js";
2
+
3
+ const LAMBDA = 1.35;
4
+
5
+ function expWeights(n: number): number[] {
6
+ return Array.from({ length: n }, (_, i) => Math.exp(LAMBDA * i));
7
+ }
8
+
9
+ function allocateBudget(budgetTokens: number, weights: number[]): number[] {
10
+ const n = weights.length;
11
+ if (n === 0 || budgetTokens === 0) return new Array(n).fill(0);
12
+
13
+ const sumW = Math.max(weights.reduce((a, b) => a + b, 0), Number.EPSILON);
14
+ const base = new Array(n).fill(0);
15
+ const frac = new Array(n).fill(0);
16
+
17
+ for (let i = 0; i < n; i++) {
18
+ const exact = (budgetTokens * weights[i]) / sumW;
19
+ base[i] = Math.floor(exact);
20
+ frac[i] = exact - base[i];
21
+ }
22
+
23
+ const given = base.reduce((a: number, b: number) => a + b, 0);
24
+ const order = Array.from({ length: n }, (_, i) => i).sort(
25
+ (a, b) => frac[b] - frac[a],
26
+ );
27
+
28
+ let extra = budgetTokens - given;
29
+ for (const i of order) {
30
+ if (extra <= 0) break;
31
+ base[i]++;
32
+ extra--;
33
+ }
34
+ return base;
35
+ }
36
+
37
+ function tierForIndex(i: number, n: number): number {
38
+ if (n <= 1) return 2;
39
+ const r = i / (n - 1);
40
+ if (r < 1 / 3) return 0;
41
+ if (r < 2 / 3) return 1;
42
+ return 2;
43
+ }
44
+
45
+ const STRUCTURE_KEYWORDS = [
46
+ "fn ",
47
+ "pub ",
48
+ "struct ",
49
+ "enum ",
50
+ "trait ",
51
+ "impl ",
52
+ "mod ",
53
+ "use ",
54
+ "def ",
55
+ "class ",
56
+ "function ",
57
+ "export ",
58
+ "import ",
59
+ "const ",
60
+ "interface ",
61
+ ];
62
+
63
+ function mapLike(s: string, maxTokens: number): string {
64
+ const picked: string[] = [];
65
+ const lines = s.split("\n");
66
+ for (let i = 0; i < lines.length; i++) {
67
+ if (i === 0 || STRUCTURE_KEYWORDS.some((k) => lines[i].includes(k))) {
68
+ picked.push(lines[i]);
69
+ }
70
+ if (picked.length >= 48) break;
71
+ }
72
+ if (picked.length === 0 && lines.length > 0) {
73
+ picked.push(lines[0]);
74
+ }
75
+ return truncateToTokenBudget(picked.join("\n"), Math.max(4, maxTokens));
76
+ }
77
+
78
+ function oneLineSummary(
79
+ segIdx: number,
80
+ s: string,
81
+ maxTokens: number,
82
+ ): string {
83
+ const preview = s.split("\n")[0]?.slice(0, 120) ?? "";
84
+ const lineCount = s.split("\n").length;
85
+ const draft = `// seg[${segIdx}] ${lineCount} lines, ${s.length} chars | ${preview}`;
86
+ return truncateToTokenBudget(draft, Math.max(8, maxTokens));
87
+ }
88
+
89
+ export function compressProgressive(
90
+ segments: string[],
91
+ budgetTokens: number,
92
+ ): string[] {
93
+ const n = segments.length;
94
+ if (n === 0) return [];
95
+ if (budgetTokens === 0) return segments.map(() => "");
96
+
97
+ const weights = expWeights(n);
98
+ const allocs = allocateBudget(budgetTokens, weights);
99
+ const out: string[] = [];
100
+
101
+ for (let i = 0; i < n; i++) {
102
+ const alloc = allocs[i];
103
+ const tier = tierForIndex(i, n);
104
+ if (alloc === 0) {
105
+ out.push("");
106
+ continue;
107
+ }
108
+ let compressed: string;
109
+ switch (tier) {
110
+ case 2:
111
+ compressed = truncateToTokenBudget(segments[i], alloc);
112
+ break;
113
+ case 1:
114
+ compressed = mapLike(segments[i], alloc);
115
+ break;
116
+ default:
117
+ compressed = oneLineSummary(i, segments[i], alloc);
118
+ break;
119
+ }
120
+ out.push(truncateToTokenBudget(compressed, alloc));
121
+ }
122
+ return out;
123
+ }
@@ -0,0 +1,58 @@
1
+ const ANSI_RE = /\x1b\[[0-9;]*[a-zA-Z]/g;
2
+
3
+ export function stripAnsi(s: string): string {
4
+ if (!s.includes("\x1b")) return s;
5
+ return s.replace(ANSI_RE, "");
6
+ }
7
+
8
+ const TS_RE =
9
+ /\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?/g;
10
+ const HASH_RE = /\b[0-9a-f]{32,64}\b/g;
11
+
12
+ export function stripTimestampsAndHashes(line: string): string {
13
+ return line.replace(TS_RE, "[TS]").replace(HASH_RE, "[HASH]");
14
+ }
15
+
16
+ export function normalizeWhitespace(line: string): string {
17
+ let result = "";
18
+ let prevSpace = false;
19
+ for (const ch of line) {
20
+ if (ch === " " || ch === "\t") {
21
+ if (!prevSpace) {
22
+ result += " ";
23
+ prevSpace = true;
24
+ }
25
+ } else {
26
+ result += ch;
27
+ prevSpace = false;
28
+ }
29
+ }
30
+ return result;
31
+ }
32
+
33
+ const BOILERPLATE_PREFIXES = [
34
+ "copyright",
35
+ "licensed under",
36
+ "license:",
37
+ "all rights reserved",
38
+ "generated by",
39
+ "auto-generated",
40
+ ];
41
+
42
+ const SEPARATOR_CHARS = new Set(["=", "-", "*", "─", "━"]);
43
+
44
+ export function isBoilerplate(line: string): boolean {
45
+ const lower = line.toLowerCase();
46
+ if (BOILERPLATE_PREFIXES.some((p) => lower.startsWith(p))) return true;
47
+ if (line.length >= 4) {
48
+ const first = line[0];
49
+ if (SEPARATOR_CHARS.has(first)) {
50
+ let same = 0;
51
+ for (const c of line) {
52
+ if (c === first) same++;
53
+ }
54
+ if (same / line.length > 0.8) return true;
55
+ }
56
+ }
57
+ return false;
58
+ }
@@ -0,0 +1,19 @@
1
+ const CHARS_PER_TOKEN = 3.7;
2
+
3
+ export function countTokens(text: string): number {
4
+ if (!text) return 0;
5
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
6
+ }
7
+
8
+ export function truncateToTokenBudget(
9
+ text: string,
10
+ maxTokens: number,
11
+ ): string {
12
+ if (maxTokens <= 0) return "";
13
+ if (countTokens(text) <= maxTokens) return text;
14
+ const charBudget = Math.floor(maxTokens * CHARS_PER_TOKEN);
15
+ const truncated = text.slice(0, charBudget);
16
+ const lastNewline = truncated.lastIndexOf("\n");
17
+ const clean = lastNewline > 0 ? truncated.slice(0, lastNewline) : truncated;
18
+ return `${clean} …`;
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@entelligentsia/forgecli",
3
- "version": "0.21.0",
3
+ "version": "1.0.3",
4
4
  "description": "Forge SDLC ported onto @earendil-works/pi-coding-agent \u2014 production launcher with three bin aliases (forge/forgecli/4ge). Bundles a curated fork of pi-coding-agent vendored under earendil-works names.",
5
5
  "license": "MIT",
6
6
  "author": "Entelligentsia",
@@ -71,20 +71,22 @@
71
71
  "@earendil-works/pi-agent-core",
72
72
  "@earendil-works/pi-ai",
73
73
  "@earendil-works/pi-tui",
74
+ "@entelligentsia/forge-compress",
74
75
  "js-yaml"
75
76
  ],
76
77
  "dependencies": {
77
- "@earendil-works/pi-agent-core": "file:./vendor-pi/earendil-works-pi-agent-core-0.75.4.tgz",
78
- "@earendil-works/pi-ai": "file:./vendor-pi/earendil-works-pi-ai-0.75.4.tgz",
79
- "@earendil-works/pi-coding-agent": "file:./vendor-pi/earendil-works-pi-coding-agent-0.75.4-forge.1.tgz",
80
- "@earendil-works/pi-tui": "file:./vendor-pi/earendil-works-pi-tui-0.75.4.tgz",
78
+ "@earendil-works/pi-agent-core": "file:./vendor-pi/earendil-works-pi-agent-core-0.75.5.tgz",
79
+ "@earendil-works/pi-ai": "file:./vendor-pi/earendil-works-pi-ai-0.75.5.tgz",
80
+ "@earendil-works/pi-coding-agent": "file:./vendor-pi/earendil-works-pi-coding-agent-0.75.5-forge.1.tgz",
81
+ "@earendil-works/pi-tui": "file:./vendor-pi/earendil-works-pi-tui-0.75.5.tgz",
81
82
  "ajv": "^8.20.0",
82
83
  "js-yaml": "^4.1.0",
84
+ "@entelligentsia/forge-compress": "file:../forge-compress",
83
85
  "lunr": "2.3.9",
84
86
  "typebox": "^1.1.24"
85
87
  },
86
88
  "peerDependencies": {
87
- "@earendil-works/pi-coding-agent": "0.75.4-forge.1"
89
+ "@earendil-works/pi-coding-agent": "0.75.5-forge.1"
88
90
  },
89
91
  "devDependencies": {
90
92
  "@biomejs/biome": "^2.3.5",
@@ -97,12 +99,5 @@
97
99
  },
98
100
  "engines": {
99
101
  "node": ">=20.6.0"
100
- },
101
- "bundleDependencies": [
102
- "@earendil-works/pi-coding-agent",
103
- "@earendil-works/pi-agent-core",
104
- "@earendil-works/pi-ai",
105
- "@earendil-works/pi-tui",
106
- "js-yaml"
107
- ]
108
- }
102
+ }
103
+ }
@@ -1,72 +0,0 @@
1
- import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
- export interface VerifyResult {
3
- ok: boolean;
4
- missing: string[];
5
- reason?: string;
6
- }
7
- /** Context passed to the `postVerify` hook. */
8
- export interface PostVerifyContext {
9
- cwd: string;
10
- bundleRoot: string;
11
- toolsRoot: string;
12
- projectName: string;
13
- configCache: Record<string, unknown>;
14
- ctx: ExtensionCommandContext;
15
- sendToAgent: (text: string) => void;
16
- isNonInteractive: () => boolean;
17
- }
18
- /**
19
- * Descriptor for a single init phase.
20
- *
21
- * LLM phases (1, 2): `buildPrompt` returns a string; `runLlmPhase` dispatches via
22
- * `sendToAgent` + `waitForIdle` then verifies.
23
- *
24
- * Deterministic phases (3): `buildPrompt` returns `null`; `runDeterministic` runs
25
- * tool calls directly without LLM dispatch.
26
- */
27
- export interface LlmPhaseDescriptor {
28
- phaseNum: 1 | 2 | 3;
29
- label: string;
30
- bannerName: string;
31
- bannerKey: string;
32
- /**
33
- * Build the prompt to send to the agent. Return `null` for deterministic phases
34
- * that run tool calls directly (Phase 3).
35
- */
36
- buildPrompt: (bundleRoot: string, cwd: string, projectName: string, configCache: Record<string, unknown>) => string | null;
37
- /** Direct tool execution for deterministic phases (called when buildPrompt returns null). */
38
- runDeterministic?: (cwd: string, bundleRoot: string, toolsRoot: string, configCache: Record<string, unknown>, ctx: ExtensionCommandContext) => Promise<void>;
39
- /** Optional notification emitted before LLM dispatch (e.g. Phase 1 parallel-scan notice). */
40
- preDispatchNotify?: string;
41
- verify: (cwd: string, configCache: Record<string, unknown>) => VerifyResult;
42
- buildRetrySteer: (result: VerifyResult, bundleRoot: string, cwd: string) => string | null;
43
- nonInteractiveAbortMsg: (result: VerifyResult) => string;
44
- interactiveAbortPrompt: (result: VerifyResult) => {
45
- title: string;
46
- body: string;
47
- };
48
- abortNotify: string;
49
- partialContinueNotify: string;
50
- completeNotify: string;
51
- /** When true, a failed verify aborts immediately with no retry or user confirm. Default: false. */
52
- hardFailOnVerifyError?: boolean;
53
- /**
54
- * Optional async hook invoked after the failure-handling decision completes (both on
55
- * success and on partial-continue). NOT called when the phase returns "abort".
56
- */
57
- postVerify?: (ctx: PostVerifyContext) => Promise<void> | void;
58
- }
59
- /**
60
- * Run a single init phase using its descriptor.
61
- *
62
- * Returns `"ok"` when the phase completes successfully (verify passed, or the
63
- * user chose to continue with partial results).
64
- *
65
- * Returns `"abort"` when the phase should halt the entire init (verify failed
66
- * in hard-fail mode, verify failed twice in non-interactive mode, or the user
67
- * declined to continue).
68
- */
69
- export declare function runLlmPhase(desc: LlmPhaseDescriptor, ctx: ExtensionCommandContext, cwd: string, bundleRoot: string, toolsRoot: string, projectName: string, configCache: Record<string, unknown>, sendToAgent: (text: string) => void, waitForIdle: () => Promise<void>, isNonInteractive: () => boolean): Promise<"ok" | "abort">;
70
- export declare const PHASE_1: LlmPhaseDescriptor;
71
- export declare const PHASE_2: LlmPhaseDescriptor;
72
- export declare const PHASE_3: LlmPhaseDescriptor;
@@ -1,359 +0,0 @@
1
- // forge-init/phase-descriptors.ts — LlmPhaseDescriptor interface + runLlmPhase() runner
2
- // + per-phase descriptor objects (FORGE-S25-T24, B-5)
3
- //
4
- // Centralises the repeated "banner → [LLM dispatch → waitForIdle →] verify → [retry →]
5
- // [user confirm →] writeInitProgress → completeNotify" skeleton that was duplicated
6
- // across the Phase 1, 2, and 3 blocks in forge-init.ts.
7
- //
8
- // Design rules:
9
- // - If `buildPrompt` returns a non-null string, the runner performs LLM dispatch via
10
- // `sendToAgent` + `waitForIdle`. Phase 1 and 2 use this path.
11
- // - If `buildPrompt` returns null, the runner skips LLM dispatch and invokes
12
- // `runDeterministic` instead (Phase 3 path — pure tool calls, no agent).
13
- // - `postVerify` is an optional async hook invoked after the failure-handling decision
14
- // completes (i.e. after verify succeeds OR after user chooses partial-continue).
15
- // Used by Phase 1 for KB folder prompt + marketplace advisory, by Phase 2 for
16
- // project-context.json write and calibration baseline.
17
- // - `hardFailOnVerifyError` (default false): when true, a failed verify causes an
18
- // immediate `"abort"` return with no retry and no user confirm. Phase 3 uses this.
19
- // - `preDispatchNotify` (optional): fired before LLM dispatch — used by Phase 1 to
20
- // emit the "Running 5 discovery scans in parallel..." info notice.
21
- import * as fs from "node:fs";
22
- import * as path from "node:path";
23
- import { buildProjectContext, computeCalibrationBaseline, validateProjectContext, writeProjectContext, } from "../init-context.js";
24
- import { writeInitProgress } from "../init-progress.js";
25
- import { execFileAsync, runToolAdvisory } from "../lib/exec-helpers.js";
26
- import { buildPhase1PromptText, buildPhase2PromptText } from "./prompts.js";
27
- import { verifyPhase1, verifyPhase2, verifyPhase3 } from "./verifiers.js";
28
- // ── Generic runner ─────────────────────────────────────────────────────────
29
- /**
30
- * Run a single init phase using its descriptor.
31
- *
32
- * Returns `"ok"` when the phase completes successfully (verify passed, or the
33
- * user chose to continue with partial results).
34
- *
35
- * Returns `"abort"` when the phase should halt the entire init (verify failed
36
- * in hard-fail mode, verify failed twice in non-interactive mode, or the user
37
- * declined to continue).
38
- */
39
- export async function runLlmPhase(desc, ctx, cwd, bundleRoot, toolsRoot, projectName, configCache, sendToAgent, waitForIdle, isNonInteractive) {
40
- // 1. setStatus
41
- ctx.ui.setStatus?.("forge:init", `Phase ${desc.label}`);
42
- // 2. Banner
43
- const bannersTool = path.join(toolsRoot, "banners.cjs");
44
- if (fs.existsSync(bannersTool)) {
45
- await execFileAsync("node", [bannersTool, "--phase", String(desc.phaseNum), "4", desc.bannerName, desc.bannerKey], { cwd, timeout: 5000 }).catch(() => {
46
- /* non-fatal */
47
- });
48
- }
49
- // 3. Optional pre-dispatch notification
50
- if (desc.preDispatchNotify) {
51
- ctx.ui.notify(desc.preDispatchNotify, "info");
52
- }
53
- // 4. LLM dispatch OR deterministic execution
54
- const prompt = desc.buildPrompt(bundleRoot, cwd, projectName, configCache);
55
- if (prompt !== null) {
56
- // LLM path: send prompt + wait for agent
57
- sendToAgent(prompt);
58
- await waitForIdle();
59
- }
60
- else if (desc.runDeterministic) {
61
- // Deterministic path: run tool calls directly
62
- await desc.runDeterministic(cwd, bundleRoot, toolsRoot, configCache, ctx);
63
- }
64
- // 5. Verify
65
- let result = desc.verify(cwd, configCache);
66
- if (!result.ok && desc.hardFailOnVerifyError) {
67
- // Hard-fail: no retry, no user confirm (Phase 3)
68
- ctx.ui.notify(desc.nonInteractiveAbortMsg(result), "error");
69
- return "abort";
70
- }
71
- // 6. Retry steer (LLM phases only)
72
- if (!result.ok && prompt !== null) {
73
- const retrySteer = desc.buildRetrySteer(result, bundleRoot, cwd);
74
- if (retrySteer) {
75
- ctx.ui.notify(`△ Phase ${desc.phaseNum} deliverable missing: ${result.missing.join(", ")} — retrying with corrective steer.`, "warning");
76
- sendToAgent(retrySteer);
77
- await waitForIdle();
78
- result = desc.verify(cwd, configCache);
79
- }
80
- }
81
- // 7. Handle persistent failure
82
- if (!result.ok) {
83
- if (isNonInteractive()) {
84
- ctx.ui.notify(desc.nonInteractiveAbortMsg(result), "error");
85
- return "abort";
86
- }
87
- const { title, body } = desc.interactiveAbortPrompt(result);
88
- const proceed = await ctx.ui.confirm(title, body);
89
- if (!proceed) {
90
- ctx.ui.notify(desc.abortNotify, "error");
91
- return "abort";
92
- }
93
- ctx.ui.notify(desc.partialContinueNotify, "warning");
94
- }
95
- // 8. Post-verify hook (called on success AND on partial-continue)
96
- if (desc.postVerify) {
97
- await desc.postVerify({
98
- cwd,
99
- bundleRoot,
100
- toolsRoot,
101
- projectName,
102
- configCache,
103
- ctx,
104
- sendToAgent,
105
- isNonInteractive,
106
- });
107
- }
108
- // 9. Write progress marker + completion notify
109
- writeInitProgress(cwd, desc.phaseNum);
110
- ctx.ui.notify(desc.completeNotify, "info");
111
- return "ok";
112
- }
113
- // ── Phase descriptors ──────────────────────────────────────────────────────
114
- export const PHASE_1 = {
115
- phaseNum: 1,
116
- label: "1/4: Collect",
117
- bannerName: "Collect",
118
- bannerKey: "north",
119
- preDispatchNotify: "Running 5 discovery scans in parallel...",
120
- buildPrompt(bundleRoot, _cwd, projectName, _configCache) {
121
- return buildPhase1PromptText(bundleRoot, projectName);
122
- },
123
- verify(cwd, _configCache) {
124
- return verifyPhase1(cwd);
125
- },
126
- buildRetrySteer(result, _bundleRoot, _cwd) {
127
- return (`Phase 1 verification failed. .forge/config.json is missing the following required fields: ${result.missing.join(", ")}.\n\n` +
128
- `Write a complete .forge/config.json now using the \`write\` tool. Do NOT call subagents — analyze the project codebase yourself if needed. ` +
129
- `Use the schema from the original Phase 1 prompt: version, project.{name,prefix}, stack, commands, and paths.{engineering,store,workflows,commands,templates} are all required.`);
130
- },
131
- nonInteractiveAbortMsg(result) {
132
- return `× Phase 1 failed: ${result.missing.join(", ")}. Aborting init in non-interactive mode.`;
133
- },
134
- interactiveAbortPrompt(result) {
135
- return {
136
- title: "Phase 1 failed twice — continue with partial init?",
137
- body: `.forge/config.json is still missing: ${result.missing.join(", ")}.\n\n` +
138
- `Yes = continue (you'll need to /forge:regenerate later).\n` +
139
- `No = abort. Inspect the file manually and re-run /forge:init.`,
140
- };
141
- },
142
- abortNotify: "× /forge:init aborted at Phase 1 verify.",
143
- partialContinueNotify: "△ Continuing with partial Phase 1 — downstream phases may fail.",
144
- completeNotify: "〇 Phase 1 complete.",
145
- async postVerify({ cwd, toolsRoot, configCache, ctx, isNonInteractive }) {
146
- // KB folder prompt (spec §7, F2) — G3: skipped in non-interactive mode (default: "engineering")
147
- // Phrasing chosen so the default-Yes affirmative ("use engineering/") is the
148
- // safe path. Pi's ctx.ui.confirm has no defaultValue option, so the question
149
- // has to align with the highlighted default — earlier "does this conflict?"
150
- // phrasing made the unsafe answer the default.
151
- if (!isNonInteractive()) {
152
- const kbDescription = `Forge will create a folder for architecture docs, sprints, bugs, and features.\n\n` +
153
- `Use "engineering" as the folder name? (Pick No only if your project already has an "engineering/" folder you don't want Forge to touch.)`;
154
- const useDefault = await ctx.ui.confirm("Engineering folder name?", kbDescription);
155
- if (!useDefault) {
156
- const customName = await ctx.ui.input("Engineering folder name? Enter preferred folder name", "e.g. ai-docs, .forge-kb, docs/ai");
157
- if (customName && customName.trim()) {
158
- const manageConfigToolEarly = path.join(toolsRoot, "manage-config.cjs");
159
- if (fs.existsSync(manageConfigToolEarly)) {
160
- await runToolAdvisory(manageConfigToolEarly, ["set", "paths.engineering", customName.trim()], cwd, ctx, "manage-config paths.engineering");
161
- }
162
- }
163
- }
164
- }
165
- // Marketplace skills advisory (sub-decision #1)
166
- ctx.ui.notify("〇 Marketplace skills auto-recommendation is Claude-Code-only. " +
167
- "Pi users install extensions manually. Writing installedSkills: []", "info");
168
- // Write installedSkills: []
169
- const manageConfigTool = path.join(toolsRoot, "manage-config.cjs");
170
- if (fs.existsSync(manageConfigTool)) {
171
- await runToolAdvisory(manageConfigTool, ["set", "installedSkills", "[]"], cwd, ctx, "manage-config installedSkills");
172
- // Write mode = "full"
173
- await runToolAdvisory(manageConfigTool, ["set", "mode", "full"], cwd, ctx, "manage-config mode");
174
- }
175
- void configCache; // used by descriptor runner; accessed here only to satisfy type
176
- },
177
- };
178
- export const PHASE_2 = {
179
- phaseNum: 2,
180
- label: "2/4: Discover",
181
- bannerName: "Discover",
182
- bannerKey: "oracle",
183
- buildPrompt(bundleRoot, cwd, projectName, configCache) {
184
- let kbPath = "engineering";
185
- const cachePaths = configCache.paths;
186
- if (cachePaths && typeof cachePaths.engineering === "string" && cachePaths.engineering) {
187
- kbPath = cachePaths.engineering;
188
- }
189
- // Scaffold dirs before dispatching to ensure they exist
190
- const dirs = [
191
- path.join(cwd, kbPath),
192
- path.join(cwd, kbPath, "architecture"),
193
- path.join(cwd, kbPath, "business-domain"),
194
- path.join(cwd, kbPath, "sprints"),
195
- path.join(cwd, ".forge", "store"),
196
- path.join(cwd, ".forge", "cache"),
197
- ];
198
- for (const dir of dirs) {
199
- try {
200
- fs.mkdirSync(dir, { recursive: true });
201
- const keepPath = path.join(dir, ".gitkeep");
202
- if (!fs.existsSync(keepPath)) {
203
- fs.writeFileSync(keepPath, "", "utf8");
204
- }
205
- }
206
- catch {
207
- // non-fatal
208
- }
209
- }
210
- return buildPhase2PromptText(bundleRoot, kbPath, projectName);
211
- },
212
- verify(cwd, configCache) {
213
- let kbPath = "engineering";
214
- const cachePaths = configCache.paths;
215
- if (cachePaths && typeof cachePaths.engineering === "string" && cachePaths.engineering) {
216
- kbPath = cachePaths.engineering;
217
- }
218
- return verifyPhase2(cwd, kbPath);
219
- },
220
- buildRetrySteer(result, bundleRoot, _cwd) {
221
- return (`Phase 2 verification failed. The following architecture docs are missing:\n${result.missing.map((m) => ` - ${m}`).join("\n")}\n\n` +
222
- `Write the missing files now using the \`write\` tool. Do NOT call subagents — analyze the project codebase yourself. ` +
223
- `Use the rulebook at ${path.join(bundleRoot, ".init", "generation", "generate-kb-doc.md")} for the per-doc shape and confidence-header format.`);
224
- },
225
- nonInteractiveAbortMsg(result) {
226
- return `× Phase 2 failed: ${result.missing.length} doc(s) still missing. Aborting init in non-interactive mode.`;
227
- },
228
- interactiveAbortPrompt(result) {
229
- return {
230
- title: "Phase 2 failed twice — continue with partial init?",
231
- body: `Missing docs:\n${result.missing.map((m) => ` - ${m}`).join("\n")}\n\n` +
232
- `Yes = continue (you'll need to fill these manually).\n` +
233
- `No = abort. Inspect the project and re-run /forge:init.`,
234
- };
235
- },
236
- abortNotify: "× /forge:init aborted at Phase 2 verify.",
237
- partialContinueNotify: "△ Continuing with partial Phase 2.",
238
- completeNotify: "〇 Phase 2 complete.",
239
- async postVerify({ cwd, bundleRoot, toolsRoot, projectName, configCache, ctx }) {
240
- // Construct project-context.json — use configCache (written by Phase 1)
241
- let kbPathResolved = "engineering";
242
- let prefix = "";
243
- {
244
- const cacheProj = configCache.project;
245
- if (cacheProj && typeof cacheProj.prefix === "string")
246
- prefix = cacheProj.prefix;
247
- const cachePaths2 = configCache.paths;
248
- if (cachePaths2 && typeof cachePaths2.engineering === "string")
249
- kbPathResolved = cachePaths2.engineering;
250
- }
251
- const projectCtx = buildProjectContext({
252
- projectName: configCache.project?.name ?? projectName,
253
- prefix,
254
- kbPath: kbPathResolved,
255
- }, configCache);
256
- try {
257
- validateProjectContext(projectCtx);
258
- writeProjectContext(cwd, projectCtx);
259
- ctx.ui.notify("〇 project-context.json written.", "info");
260
- }
261
- catch (err) {
262
- const e = err;
263
- ctx.ui.notify(`△ project-context.json validation failed: ${e.message ?? "unknown"} — proceeding.`, "warning");
264
- }
265
- // Calibration baseline — read bundled version from plugin.json (same pattern as phase4-register.ts step 4-8)
266
- let bundledPluginVersion = "";
267
- try {
268
- const pluginPath = path.join(bundleRoot, ".claude-plugin", "plugin.json");
269
- const plugin = JSON.parse(fs.readFileSync(pluginPath, "utf8"));
270
- bundledPluginVersion = plugin.version ?? "";
271
- }
272
- catch {
273
- // non-fatal — version field stays ""
274
- }
275
- const baseline = computeCalibrationBaseline(cwd, kbPathResolved, bundledPluginVersion);
276
- const manageConfigTool = path.join(toolsRoot, "manage-config.cjs");
277
- if (fs.existsSync(manageConfigTool)) {
278
- await runToolAdvisory(manageConfigTool, ["set", "calibrationBaseline", JSON.stringify(baseline)], cwd, ctx, "manage-config calibrationBaseline");
279
- }
280
- },
281
- };
282
- export const PHASE_3 = {
283
- phaseNum: 3,
284
- label: "3/4: Materialize",
285
- bannerName: "Materialize",
286
- bannerKey: "supervisor",
287
- // Phase 3 is deterministic — no LLM dispatch.
288
- buildPrompt(_bundleRoot, _cwd, _projectName, _configCache) {
289
- return null;
290
- },
291
- async runDeterministic(cwd, bundleRoot, toolsRoot, _configCache, ctx) {
292
- const buildInitContextTool = path.join(toolsRoot, "build-init-context.cjs");
293
- const substituteTool = path.join(toolsRoot, "substitute-placeholders.cjs");
294
- const buildOverlayTool = path.join(toolsRoot, "build-overlay.cjs");
295
- const basePackDir = path.join(bundleRoot, ".base-pack");
296
- // 3a: build-init-context.cjs first build
297
- if (fs.existsSync(buildInitContextTool)) {
298
- await runToolAdvisory(buildInitContextTool, [
299
- "--config",
300
- path.join(cwd, ".forge", "config.json"),
301
- "--personas",
302
- path.join(cwd, ".forge", "personas"),
303
- "--templates",
304
- path.join(cwd, ".forge", "templates"),
305
- "--kb",
306
- cwd,
307
- "--out",
308
- path.join(cwd, ".forge", "init-context.md"),
309
- "--json-out",
310
- path.join(cwd, ".forge", "init-context.json"),
311
- ], cwd, ctx, "build-init-context", 30000);
312
- }
313
- // 3b: substitute-placeholders.cjs — base-pack materialisation
314
- if (fs.existsSync(substituteTool) && fs.existsSync(basePackDir)) {
315
- await runToolAdvisory(substituteTool, [
316
- "--forge-root",
317
- bundleRoot,
318
- "--base-pack",
319
- basePackDir,
320
- "--config",
321
- path.join(cwd, ".forge", "config.json"),
322
- "--context",
323
- path.join(cwd, ".forge", "init-context.json"),
324
- "--out",
325
- cwd,
326
- ], cwd, ctx, "substitute-placeholders", 60000);
327
- }
328
- // 3c: build-overlay.cjs smoke test (exit 1 is advisory)
329
- if (fs.existsSync(buildOverlayTool)) {
330
- await runToolAdvisory(buildOverlayTool, ["--task", "INIT-SMOKE-TEST", "--format", "json"], cwd, ctx, "build-overlay smoke (advisory)", 15000);
331
- }
332
- },
333
- verify(cwd, _configCache) {
334
- return verifyPhase3(cwd);
335
- },
336
- buildRetrySteer(_result, _bundleRoot, _cwd) {
337
- // Phase 3 hard-fails — retry steer is not used.
338
- return null;
339
- },
340
- nonInteractiveAbortMsg(result) {
341
- return (`× Phase 3 failed: ${result.missing.join(", ")}. ` +
342
- `This usually means substitute-placeholders.cjs ran against an incomplete config. ` +
343
- `Fix .forge/config.json and run /forge:regenerate, or restart /forge:init from scratch (delete .forge/init-progress.json).`);
344
- },
345
- interactiveAbortPrompt(result) {
346
- return {
347
- title: "Phase 3 failed — abort init?",
348
- body: `Phase 3 materialization failed: ${result.missing.join(", ")}.\n\n` +
349
- `This usually means substitute-placeholders.cjs ran against an incomplete config.\n` +
350
- `Fix .forge/config.json and run /forge:regenerate.`,
351
- };
352
- },
353
- abortNotify: "× /forge:init aborted at Phase 3 verify.",
354
- partialContinueNotify: "△ Continuing with partial Phase 3.",
355
- completeNotify: "〇 Phase 3 complete.",
356
- // Phase 3 hard-fails on verify error — no retry, no user confirm.
357
- hardFailOnVerifyError: true,
358
- };
359
- //# sourceMappingURL=phase-descriptors.js.map