@entelligentsia/forgecli 0.21.0 → 1.0.2

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 (297) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +31 -33
  3. package/dist/CHANGELOG-forge-plugin.md +118 -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/calibrate.js +11 -8
  15. package/dist/extensions/forgecli/calibrate.js.map +1 -1
  16. package/dist/extensions/forgecli/collate.js +1 -1
  17. package/dist/extensions/forgecli/collate.js.map +1 -1
  18. package/dist/extensions/forgecli/commit.js +17 -2
  19. package/dist/extensions/forgecli/commit.js.map +1 -1
  20. package/dist/extensions/forgecli/enhance.js +1 -1
  21. package/dist/extensions/forgecli/enhance.js.map +1 -1
  22. package/dist/extensions/forgecli/forge-artifact-tool.d.ts +6 -8
  23. package/dist/extensions/forgecli/forge-artifact-tool.js +80 -195
  24. package/dist/extensions/forgecli/forge-artifact-tool.js.map +1 -1
  25. package/dist/extensions/forgecli/forge-commands.js +57 -18
  26. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  27. package/dist/extensions/forgecli/forge-init/phase4-register.js +6 -7
  28. package/dist/extensions/forgecli/forge-init/phase4-register.js.map +1 -1
  29. package/dist/extensions/forgecli/forge-init/run-phases.d.ts +4 -0
  30. package/dist/extensions/forgecli/forge-init/run-phases.js +304 -0
  31. package/dist/extensions/forgecli/forge-init/run-phases.js.map +1 -0
  32. package/dist/extensions/forgecli/forge-init/verifiers.d.ts +14 -5
  33. package/dist/extensions/forgecli/forge-init/verifiers.js +79 -62
  34. package/dist/extensions/forgecli/forge-init/verifiers.js.map +1 -1
  35. package/dist/extensions/forgecli/forge-init.js +131 -76
  36. package/dist/extensions/forgecli/forge-init.js.map +1 -1
  37. package/dist/extensions/forgecli/forge-subagent.d.ts +9 -0
  38. package/dist/extensions/forgecli/forge-subagent.js +11 -6
  39. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  40. package/dist/extensions/forgecli/forge-tools.d.ts +28 -4
  41. package/dist/extensions/forgecli/forge-tools.js +122 -73
  42. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  43. package/dist/extensions/forgecli/health-check.js +3 -3
  44. package/dist/extensions/forgecli/health-check.js.map +1 -1
  45. package/dist/extensions/forgecli/hook-dispatcher.d.ts +1 -1
  46. package/dist/extensions/forgecli/hooks/check-update.d.ts +8 -0
  47. package/dist/extensions/forgecli/hooks/check-update.js +29 -1
  48. package/dist/extensions/forgecli/hooks/check-update.js.map +1 -1
  49. package/dist/extensions/forgecli/hooks/post-init-hook.js +6 -6
  50. package/dist/extensions/forgecli/hooks/post-init-hook.js.map +1 -1
  51. package/dist/extensions/forgecli/hooks/post-sprint-hook.js +6 -6
  52. package/dist/extensions/forgecli/hooks/post-sprint-hook.js.map +1 -1
  53. package/dist/extensions/forgecli/hooks/triage-error.js +1 -0
  54. package/dist/extensions/forgecli/hooks/triage-error.js.map +1 -1
  55. package/dist/extensions/forgecli/implement.js +20 -2
  56. package/dist/extensions/forgecli/implement.js.map +1 -1
  57. package/dist/extensions/forgecli/index.js +39 -32
  58. package/dist/extensions/forgecli/index.js.map +1 -1
  59. package/dist/extensions/forgecli/lib/pipeline-guard.d.ts +41 -0
  60. package/dist/extensions/forgecli/lib/pipeline-guard.js +100 -0
  61. package/dist/extensions/forgecli/lib/pipeline-guard.js.map +1 -0
  62. package/dist/extensions/forgecli/loaders/persona-skill-loader.js +2 -2
  63. package/dist/extensions/forgecli/loaders/persona-skill-loader.js.map +1 -1
  64. package/dist/extensions/forgecli/migrate.d.ts +3 -0
  65. package/dist/extensions/forgecli/migrate.js +4 -2
  66. package/dist/extensions/forgecli/migrate.js.map +1 -1
  67. package/dist/extensions/forgecli/plan.js +21 -2
  68. package/dist/extensions/forgecli/plan.js.map +1 -1
  69. package/dist/extensions/forgecli/quiz-agent.js +7 -7
  70. package/dist/extensions/forgecli/quiz-agent.js.map +1 -1
  71. package/dist/extensions/forgecli/regenerate.js +49 -18
  72. package/dist/extensions/forgecli/regenerate.js.map +1 -1
  73. package/dist/extensions/forgecli/remove-command.js +1 -1
  74. package/dist/extensions/forgecli/remove-command.js.map +1 -1
  75. package/dist/extensions/forgecli/report-bug.js +1 -1
  76. package/dist/extensions/forgecli/report-bug.js.map +1 -1
  77. package/dist/extensions/forgecli/retrospective.js +9 -9
  78. package/dist/extensions/forgecli/retrospective.js.map +1 -1
  79. package/dist/extensions/forgecli/review-code.d.ts +13 -0
  80. package/dist/extensions/forgecli/review-code.js +62 -3
  81. package/dist/extensions/forgecli/review-code.js.map +1 -1
  82. package/dist/extensions/forgecli/review-plan.d.ts +13 -0
  83. package/dist/extensions/forgecli/review-plan.js +65 -3
  84. package/dist/extensions/forgecli/review-plan.js.map +1 -1
  85. package/dist/extensions/forgecli/skill-curator-subagent.d.ts +2 -1
  86. package/dist/extensions/forgecli/skill-curator-subagent.js +2 -1
  87. package/dist/extensions/forgecli/skill-curator-subagent.js.map +1 -1
  88. package/dist/extensions/forgecli/sprint-intake.js +6 -6
  89. package/dist/extensions/forgecli/sprint-intake.js.map +1 -1
  90. package/dist/extensions/forgecli/sprint-plan.js +9 -9
  91. package/dist/extensions/forgecli/sprint-plan.js.map +1 -1
  92. package/dist/extensions/forgecli/status-command.js +1 -1
  93. package/dist/extensions/forgecli/status-command.js.map +1 -1
  94. package/dist/extensions/forgecli/store-query.js +11 -11
  95. package/dist/extensions/forgecli/store-query.js.map +1 -1
  96. package/dist/extensions/forgecli/store-repair.js +7 -7
  97. package/dist/extensions/forgecli/store-repair.js.map +1 -1
  98. package/dist/extensions/forgecli/validate.js +17 -2
  99. package/dist/extensions/forgecli/validate.js.map +1 -1
  100. package/dist/forge-payload/.base-pack/commands/check-agent.md +22 -0
  101. package/dist/forge-payload/.base-pack/commands/new-sprint.md +22 -0
  102. package/dist/forge-payload/.base-pack/commands/plan-sprint.md +22 -0
  103. package/dist/forge-payload/.base-pack/commands/quiz-agent.md +2 -18
  104. package/dist/forge-payload/.base-pack/commands/retro.md +22 -0
  105. package/dist/forge-payload/.base-pack/commands/retrospective.md +2 -18
  106. package/dist/forge-payload/.base-pack/commands/sprint-intake.md +2 -18
  107. package/dist/forge-payload/.base-pack/commands/sprint-plan.md +2 -18
  108. package/dist/forge-payload/.base-pack/workflows/_fragments/friction-emit.md +2 -2
  109. package/dist/forge-payload/.base-pack/workflows/_fragments/generation-instructions.md +4 -4
  110. package/dist/forge-payload/.base-pack/workflows/_fragments/iron-laws.md +1 -1
  111. package/dist/forge-payload/.base-pack/workflows/architect_approve.md +13 -1
  112. package/dist/forge-payload/.base-pack/workflows/commit_task.md +12 -1
  113. package/dist/forge-payload/.base-pack/workflows/enhance.md +6 -6
  114. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +1 -1
  115. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +14 -2
  116. package/dist/forge-payload/.base-pack/workflows/migrate_structural.md +2 -2
  117. package/dist/forge-payload/.base-pack/workflows/orchestrate_task.md +20 -4
  118. package/dist/forge-payload/.base-pack/workflows/plan_task.md +14 -2
  119. package/dist/forge-payload/.base-pack/workflows/review_code.md +37 -7
  120. package/dist/forge-payload/.base-pack/workflows/review_plan.md +36 -6
  121. package/dist/forge-payload/.base-pack/workflows/run_sprint.md +2 -2
  122. package/dist/forge-payload/.base-pack/workflows/validate_task.md +37 -7
  123. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  124. package/dist/forge-payload/.schemas/config.schema.json +0 -5
  125. package/dist/forge-payload/.schemas/enum-catalog.json +9 -13
  126. package/dist/forge-payload/.schemas/migrations.json +54 -0
  127. package/dist/forge-payload/agents/tomoshibi.md +150 -6
  128. package/dist/forge-payload/commands/add-pipeline.md +1 -1
  129. package/dist/forge-payload/commands/add-task.md +1 -1
  130. package/dist/forge-payload/commands/calibrate.md +4 -350
  131. package/dist/forge-payload/commands/check-agent.md +38 -0
  132. package/dist/forge-payload/commands/config.md +3 -113
  133. package/dist/forge-payload/commands/enhance.md +5 -32
  134. package/dist/forge-payload/commands/health.md +155 -13
  135. package/dist/forge-payload/commands/init.md +25 -31
  136. package/dist/forge-payload/commands/migrate.md +6 -154
  137. package/dist/forge-payload/commands/quiz-agent.md +2 -34
  138. package/dist/forge-payload/commands/rebuild.md +664 -0
  139. package/dist/forge-payload/commands/regenerate.md +2 -774
  140. package/dist/forge-payload/commands/remove.md +10 -13
  141. package/dist/forge-payload/commands/repair.md +187 -0
  142. package/dist/forge-payload/commands/search.md +73 -0
  143. package/dist/forge-payload/commands/status.md +105 -0
  144. package/dist/forge-payload/commands/store-query.md +2 -69
  145. package/dist/forge-payload/commands/store-repair.md +2 -183
  146. package/dist/forge-payload/commands/update-tools.md +4 -50
  147. package/dist/forge-payload/commands/update.md +64 -58
  148. package/dist/forge-payload/hooks/check-update.cjs +1 -1
  149. package/dist/forge-payload/hooks/post-init.cjs +2 -2
  150. package/dist/forge-payload/hooks/post-sprint.cjs +2 -2
  151. package/dist/forge-payload/hooks/triage-error.cjs +11 -10
  152. package/dist/forge-payload/init/phases/phase-1-collect.md +138 -0
  153. package/dist/forge-payload/init/phases/phase-2-discover.md +127 -0
  154. package/dist/forge-payload/init/phases/phase-3-materialize.md +113 -0
  155. package/dist/forge-payload/init/phases/phase-4-register.md +159 -0
  156. package/dist/forge-payload/integrity.json +21 -24
  157. package/dist/forge-payload/meta/fragments/tool-discipline.md +22 -0
  158. package/dist/forge-payload/meta/templates/meta-retro.md +28 -0
  159. package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +2 -2
  160. package/dist/forge-payload/meta/workflows/_fragments/generation-instructions.md +4 -4
  161. package/dist/forge-payload/meta/workflows/_fragments/iron-laws.md +1 -1
  162. package/dist/forge-payload/meta/workflows/meta-approve.md +13 -1
  163. package/dist/forge-payload/meta/workflows/meta-check-agent.md +138 -0
  164. package/dist/forge-payload/meta/workflows/meta-commit.md +12 -1
  165. package/dist/forge-payload/meta/workflows/meta-enhance.md +5 -5
  166. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +1 -1
  167. package/dist/forge-payload/meta/workflows/meta-implement.md +13 -1
  168. package/dist/forge-payload/meta/workflows/meta-migrate.md +3 -3
  169. package/dist/forge-payload/meta/workflows/meta-new-sprint.md +84 -0
  170. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +20 -4
  171. package/dist/forge-payload/meta/workflows/meta-plan-sprint.md +152 -0
  172. package/dist/forge-payload/meta/workflows/meta-plan-task.md +13 -1
  173. package/dist/forge-payload/meta/workflows/meta-retro.md +73 -0
  174. package/dist/forge-payload/meta/workflows/meta-review-implementation.md +37 -7
  175. package/dist/forge-payload/meta/workflows/meta-review-plan.md +36 -6
  176. package/dist/forge-payload/meta/workflows/meta-validate.md +37 -7
  177. package/dist/forge-payload/schemas/config.schema.json +0 -5
  178. package/dist/forge-payload/schemas/enum-catalog.json +9 -13
  179. package/dist/forge-payload/schemas/structure-manifest.json +6 -8
  180. package/dist/forge-payload/tools/artifact.cjs +295 -0
  181. package/dist/forge-payload/tools/banners.cjs +3 -4
  182. package/dist/forge-payload/tools/build-context-pack.cjs +1 -1
  183. package/dist/forge-payload/tools/check-structure.cjs +8 -3
  184. package/dist/forge-payload/tools/store-cli.cjs +67 -7
  185. package/dist/forge-payload/tools/substitute-placeholders.cjs +1 -1
  186. package/dist/forge-payload/tools/verify-apply.cjs +75 -0
  187. package/dist/forge-payload/tools/verify-phase.cjs +259 -0
  188. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  189. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +0 -17
  190. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  191. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +21 -38
  192. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
  193. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  194. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +5 -4
  195. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  196. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +2 -1
  197. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
  198. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +5 -2
  199. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
  200. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  201. package/node_modules/@earendil-works/pi-coding-agent/CHANGELOG.md +24 -1
  202. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.d.ts.map +1 -1
  203. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.js +2 -3
  204. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.js.map +1 -1
  205. package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.d.ts +1 -0
  206. package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.d.ts.map +1 -1
  207. package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.js +52 -22
  208. package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.js.map +1 -1
  209. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  210. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js +16 -4
  211. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  212. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  213. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js +45 -50
  214. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  215. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  216. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js +43 -81
  217. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  218. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  219. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.js +27 -12
  220. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.js.map +1 -1
  221. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  222. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js +2 -3
  223. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  224. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
  225. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js +3 -3
  226. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  227. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
  228. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js +5 -5
  229. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
  230. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.d.ts +2 -0
  231. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.d.ts.map +1 -1
  232. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js +37 -0
  233. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js.map +1 -1
  234. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  235. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +9 -8
  236. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  237. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  238. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js +20 -35
  239. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  240. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +3 -0
  241. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  242. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js +64 -7
  243. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  244. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  245. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +15 -3
  246. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  247. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.d.ts +3 -1
  248. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.d.ts.map +1 -1
  249. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.js +14 -8
  250. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.js.map +1 -1
  251. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.d.ts +30 -0
  252. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.d.ts.map +1 -0
  253. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.js +124 -0
  254. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.js.map +1 -0
  255. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.d.ts +2 -0
  256. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.d.ts.map +1 -0
  257. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.js +31 -0
  258. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.js.map +1 -0
  259. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.d.ts +7 -27
  260. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.d.ts.map +1 -1
  261. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.js +75 -115
  262. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.js.map +1 -1
  263. package/node_modules/@earendil-works/pi-coding-agent/docs/terminal-setup.md +6 -0
  264. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package.json +1 -1
  265. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  266. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package.json +1 -1
  267. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package.json +1 -1
  268. package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +12 -14
  269. package/node_modules/@earendil-works/pi-coding-agent/package.json +5 -5
  270. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts +3 -0
  271. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts.map +1 -0
  272. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js +53 -0
  273. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js.map +1 -0
  274. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts.map +1 -1
  275. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +4 -1
  276. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js.map +1 -1
  277. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +2 -0
  278. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  279. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +13 -1
  280. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  281. package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
  282. package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
  283. package/node_modules/@earendil-works/pi-tui/package.json +2 -2
  284. package/package.json +6 -6
  285. package/dist/extensions/forgecli/forge-init/phase-descriptors.d.ts +0 -72
  286. package/dist/extensions/forgecli/forge-init/phase-descriptors.js +0 -359
  287. package/dist/extensions/forgecli/forge-init/phase-descriptors.js.map +0 -1
  288. package/dist/extensions/forgecli/forge-init/prompts.d.ts +0 -10
  289. package/dist/extensions/forgecli/forge-init/prompts.js +0 -91
  290. package/dist/extensions/forgecli/forge-init/prompts.js.map +0 -1
  291. package/dist/extensions/forgecli/lib/store-error-remediation.d.ts +0 -65
  292. package/dist/extensions/forgecli/lib/store-error-remediation.js +0 -298
  293. package/dist/extensions/forgecli/lib/store-error-remediation.js.map +0 -1
  294. package/dist/forge-payload/hooks/check-update.js +0 -378
  295. package/dist/forge-payload/hooks/forge-permissions.js +0 -164
  296. package/dist/forge-payload/hooks/triage-error.js +0 -77
  297. package/dist/forge-payload/hooks/validate-write.js +0 -250
@@ -0,0 +1,295 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ // Forge tool: artifact
5
+ // Read, write, or list phase artifacts (PLAN.md, PROGRESS.md, *-SUMMARY.json, etc.)
6
+ // for a task, bug, or sprint. Resolves paths from entity store record.
7
+ //
8
+ // Usage:
9
+ // node artifact.cjs read <entity> <entityId> <artifact>
10
+ // node artifact.cjs write <entity> <entityId> <artifact> <content|@file>
11
+ // node artifact.cjs list <entity> <entityId>
12
+ //
13
+ // Exit codes: 0 = success, 1 = usage/validation error, 2 = not found
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+ const { execFileSync } = require('child_process');
18
+ const { findProjectRoot } = require('./lib/project-root.cjs');
19
+
20
+ // ── Artifact catalog ─────────────────────────────────────────────────────────
21
+
22
+ const ARTIFACT_CATALOG = {
23
+ 'plan': { filename: 'PLAN.md', type: 'md' },
24
+ 'plan-review': { filename: 'PLAN_REVIEW.md', type: 'md' },
25
+ 'progress': { filename: 'PROGRESS.md', type: 'md' },
26
+ 'code-review': { filename: 'CODE_REVIEW.md', type: 'md' },
27
+ 'validation-report': { filename: 'VALIDATION_REPORT.md', type: 'md' },
28
+ 'architect-approval': { filename: 'ARCHITECT_APPROVAL.md', type: 'md' },
29
+ 'triage': { filename: 'TRIAGE.md', type: 'md' },
30
+ 'bug-report': { filename: 'BUG_REPORT.md', type: 'md' },
31
+ 'index': { filename: 'INDEX.md', type: 'md' },
32
+ 'cost-report': { filename: 'COST_REPORT.md', type: 'md' },
33
+ 'timesheet': { filename: 'TIMESHEET.md', type: 'md' },
34
+ 'plan-summary': { filename: 'PLAN-SUMMARY.json', type: 'json' },
35
+ 'review-plan-summary': { filename: 'REVIEW-PLAN-SUMMARY.json', type: 'json' },
36
+ 'implementation-summary': { filename: 'IMPLEMENTATION-SUMMARY.json', type: 'json' },
37
+ 'review-code-summary': { filename: 'REVIEW-CODE-SUMMARY.json', type: 'json' },
38
+ 'review-impl-summary': { filename: 'REVIEW-IMPL-SUMMARY.json', type: 'json' },
39
+ 'validation-summary': { filename: 'VALIDATION-SUMMARY.json', type: 'json' },
40
+ 'approve-summary': { filename: 'APPROVE-SUMMARY.json', type: 'json' },
41
+ 'commit-summary': { filename: 'COMMIT-SUMMARY.json', type: 'json' },
42
+ 'triage-summary': { filename: 'TRIAGE-SUMMARY.json', type: 'json' },
43
+ 'writeback-summary': { filename: 'WRITEBACK-SUMMARY.json', type: 'json' },
44
+ 'collation-summary': { filename: 'COLLATION-SUMMARY.json', type: 'json' },
45
+ };
46
+
47
+ const ARTIFACT_NAMES = Object.keys(ARTIFACT_CATALOG).sort();
48
+
49
+ // ── Summary JSON validation ──────────────────────────────────────────────────
50
+
51
+ const SUMMARY_REQUIRED = ['objective', 'key_changes', 'verdict', 'written_at'];
52
+
53
+ function validateSummaryJson(content) {
54
+ let obj;
55
+ try {
56
+ obj = JSON.parse(content);
57
+ } catch (e) {
58
+ return `Invalid JSON: ${e.message}`;
59
+ }
60
+ const missing = SUMMARY_REQUIRED.filter((f) => !(f in obj));
61
+ if (missing.length > 0) return `Missing required fields: ${missing.join(', ')}`;
62
+ if (typeof obj.objective !== 'string') return `"objective" must be a string`;
63
+ if (!Array.isArray(obj.key_changes)) return `"key_changes" must be an array`;
64
+ if (typeof obj.verdict !== 'string') return `"verdict" must be a string`;
65
+ if (typeof obj.written_at !== 'string') return `"written_at" must be a string`;
66
+ return null;
67
+ }
68
+
69
+ // ── Entity path resolution ───────────────────────────────────────────────────
70
+
71
+ /** Read a store record via store-cli and return its `path` field, or null on failure. */
72
+ function readStorePath(entity, entityId, toolDir, projectRoot) {
73
+ const cliPath = path.join(toolDir, 'store-cli.cjs');
74
+ try {
75
+ const result = execFileSync('node', [cliPath, 'read', entity, entityId, '--json'], {
76
+ cwd: projectRoot,
77
+ encoding: 'utf8',
78
+ timeout: 10_000,
79
+ });
80
+ const record = JSON.parse(result);
81
+ if (typeof record.path === 'string' && record.path.length > 0) {
82
+ // Defensive: if the path ends with a file extension, the store record
83
+ // was written with a filename (e.g. "…/PROGRESS.md") instead of the
84
+ // directory. Strip the trailing filename to get the entity directory.
85
+ const p = record.path;
86
+ if (/\.(md|json)$/i.test(p)) return path.dirname(p);
87
+ return p;
88
+ }
89
+ } catch (_) {
90
+ // Store unavailable or record not found — fall through.
91
+ }
92
+ return null;
93
+ }
94
+
95
+ /**
96
+ * Resolve entity directory using the store record's `path` field when available,
97
+ * falling back to ID-only construction.
98
+ */
99
+ function resolveEntityDir(entity, entityId, engineeringPath, toolDir, projectRoot) {
100
+ switch (entity) {
101
+ case 'bug': {
102
+ const storePath = readStorePath('bug', entityId, toolDir, projectRoot);
103
+ if (storePath) return storePath;
104
+ return path.join(engineeringPath, 'bugs', entityId);
105
+ }
106
+ case 'sprint': {
107
+ const storePath = readStorePath('sprint', entityId, toolDir, projectRoot);
108
+ if (storePath) return storePath;
109
+ return path.join(engineeringPath, 'sprints', entityId);
110
+ }
111
+ case 'task': {
112
+ const storePath = readStorePath('task', entityId, toolDir, projectRoot);
113
+ if (storePath) return storePath;
114
+ // Fallback: derive from sprint prefix + sprint record path.
115
+ const match = entityId.match(/^(.+-S\d+)-T\d+$/);
116
+ if (!match) return null;
117
+ const sprintId = match[1];
118
+ const sprintPath = readStorePath('sprint', sprintId, toolDir, projectRoot);
119
+ if (sprintPath) {
120
+ return path.join(sprintPath, entityId);
121
+ }
122
+ return path.join(engineeringPath, 'sprints', sprintId, entityId);
123
+ }
124
+ default:
125
+ return null;
126
+ }
127
+ }
128
+
129
+ // ── CLI ───────────────────────────────────────────────────────────────────────
130
+
131
+ if (require.main === module) {
132
+
133
+ const argv = process.argv.slice(2);
134
+
135
+ if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
136
+ process.stderr.write([
137
+ 'Usage: node artifact.cjs <subcommand> <entity> <entityId> [artifact] [content|@file]',
138
+ '',
139
+ 'Subcommands:',
140
+ ' list <entity> <entityId> List existing artifacts',
141
+ ' read <entity> <entityId> <artifact> Read artifact content',
142
+ ' write <entity> <entityId> <artifact> <content|@file>',
143
+ ' Write artifact (content or @/path/to/file)',
144
+ '',
145
+ 'Entities: task, bug, sprint',
146
+ `Known artifacts: ${ARTIFACT_NAMES.join(', ')}`,
147
+ '',
148
+ 'Exit codes: 0=success, 1=usage/validation error, 2=not found',
149
+ ].join('\n') + '\n');
150
+ process.exit(1);
151
+ }
152
+
153
+ const [subcmd, entity, entityId] = argv;
154
+
155
+ if (!subcmd || !entity || !entityId) {
156
+ process.stderr.write('Usage: artifact.cjs <list|read|write> <entity> <entityId> [artifact] [content]\n');
157
+ process.exit(1);
158
+ }
159
+
160
+ const VALID_ENTITIES = ['task', 'bug', 'sprint'];
161
+ if (!VALID_ENTITIES.includes(entity)) {
162
+ process.stderr.write(`Unknown entity type: ${entity}. Valid: ${VALID_ENTITIES.join(', ')}\n`);
163
+ process.exit(1);
164
+ }
165
+
166
+ const projectRoot = findProjectRoot();
167
+ if (!projectRoot) {
168
+ process.stderr.write('Cannot find project root (.forge/config.json not found)\n');
169
+ process.exit(1);
170
+ }
171
+
172
+ // Read engineering path from config
173
+ let engineeringPath = 'engineering';
174
+ try {
175
+ const cfg = JSON.parse(fs.readFileSync(path.join(projectRoot, '.forge', 'config.json'), 'utf8'));
176
+ if (typeof cfg.paths?.engineering === 'string') engineeringPath = cfg.paths.engineering;
177
+ } catch (_) { /* default */ }
178
+
179
+ const toolDir = __dirname;
180
+
181
+ const entityDir = resolveEntityDir(entity, entityId, engineeringPath, toolDir, projectRoot);
182
+ if (!entityDir) {
183
+ process.stderr.write(
184
+ `Cannot resolve ${entity} directory for "${entityId}". ` +
185
+ `Expected ID pattern: task=PREFIX-SNN-TNN, bug=PREFIX-BNN[-slug], sprint=PREFIX-SNN.\n`
186
+ );
187
+ process.exit(1);
188
+ }
189
+
190
+ const absDir = path.resolve(projectRoot, entityDir);
191
+
192
+ // ── list ────────────────────────────────────────────────────────────────────
193
+
194
+ if (subcmd === 'list') {
195
+ if (!fs.existsSync(absDir)) {
196
+ process.stdout.write(`No artifacts found — directory does not exist: ${entityDir}/\n`);
197
+ process.exit(0);
198
+ }
199
+ const files = fs.readdirSync(absDir).filter((f) => f.endsWith('.md') || f.endsWith('.json'));
200
+ const known = [];
201
+ const other = [];
202
+ for (const f of files) {
203
+ const catalogEntry = Object.entries(ARTIFACT_CATALOG).find(([, v]) => v.filename === f);
204
+ if (catalogEntry) {
205
+ known.push(` ${catalogEntry[0]} → ${f}`);
206
+ } else {
207
+ other.push(` (unlisted) ${f}`);
208
+ }
209
+ }
210
+ const lines = [`Artifacts in ${entityDir}/:`];
211
+ if (known.length > 0) lines.push(...known);
212
+ if (other.length > 0) lines.push(...other);
213
+ if (known.length === 0 && other.length === 0) lines.push(' (empty)');
214
+ process.stdout.write(lines.join('\n') + '\n');
215
+ process.exit(0);
216
+ }
217
+
218
+ // ── read / write — need artifact name ───────────────────────────────────────
219
+
220
+ const artifactName = argv[3];
221
+ if (!artifactName) {
222
+ process.stderr.write(`"artifact" is required for ${subcmd}. Known: ${ARTIFACT_NAMES.join(', ')}\n`);
223
+ process.exit(1);
224
+ }
225
+
226
+ const catalogEntry = ARTIFACT_CATALOG[artifactName];
227
+ if (!catalogEntry) {
228
+ const suggestions = ARTIFACT_NAMES.filter((n) => n.includes(artifactName.toLowerCase()));
229
+ process.stderr.write(
230
+ `Unknown artifact "${artifactName}". Known: ${ARTIFACT_NAMES.join(', ')}.` +
231
+ (suggestions.length > 0 ? ` Did you mean: ${suggestions.join(', ')}?` : '') + '\n'
232
+ );
233
+ process.exit(1);
234
+ }
235
+
236
+ const filePath = path.join(absDir, catalogEntry.filename);
237
+
238
+ // ── read ─────────────────────────────────────────────────────────────────────
239
+
240
+ if (subcmd === 'read') {
241
+ if (!fs.existsSync(filePath)) {
242
+ process.stderr.write(`Artifact not found: ${path.join(entityDir, catalogEntry.filename)}\n`);
243
+ process.exit(2);
244
+ }
245
+ process.stdout.write(fs.readFileSync(filePath, 'utf8'));
246
+ process.exit(0);
247
+ }
248
+
249
+ // ── write ─────────────────────────────────────────────────────────────────────
250
+
251
+ if (subcmd === 'write') {
252
+ let rawContent = argv[4];
253
+ if (!rawContent) {
254
+ process.stderr.write('"content" is required for write. Pass inline or use @/path/to/file for large content.\n');
255
+ process.exit(1);
256
+ }
257
+
258
+ // @-prefix convention: read content from file when arg starts with @
259
+ let content;
260
+ if (rawContent.startsWith('@')) {
261
+ const contentFile = rawContent.slice(1);
262
+ if (!fs.existsSync(contentFile)) {
263
+ process.stderr.write(`@-file not found: ${contentFile}\n`);
264
+ process.exit(1);
265
+ }
266
+ content = fs.readFileSync(contentFile, 'utf8');
267
+ } else {
268
+ content = rawContent;
269
+ }
270
+
271
+ if (catalogEntry.type === 'json') {
272
+ const validationError = validateSummaryJson(content);
273
+ if (validationError) {
274
+ process.stderr.write(
275
+ `Summary validation failed for ${catalogEntry.filename}: ${validationError}. ` +
276
+ `Required fields: ${SUMMARY_REQUIRED.join(', ')}.\n`
277
+ );
278
+ process.exit(1);
279
+ }
280
+ }
281
+
282
+ fs.mkdirSync(absDir, { recursive: true });
283
+ fs.writeFileSync(filePath, content, 'utf8');
284
+ process.stdout.write(
285
+ `Wrote ${Buffer.byteLength(content, 'utf8')} bytes to ${path.join(entityDir, catalogEntry.filename)}\n`
286
+ );
287
+ process.exit(0);
288
+ }
289
+
290
+ process.stderr.write(`Unknown subcommand: ${subcmd}. Valid: list, read, write\n`);
291
+ process.exit(1);
292
+
293
+ } // end if (require.main === module)
294
+
295
+ module.exports = { ARTIFACT_CATALOG, ARTIFACT_NAMES, validateSummaryJson, resolveEntityDir };
@@ -31,7 +31,7 @@
31
31
  // node banners.cjs --plain forge
32
32
  // node banners.cjs --subtitle "Forging your SDLC"
33
33
  // node banners.cjs --progress 5 12 "Templates"
34
- // node banners.cjs --phase 7 12 "Workflows" ember fast
34
+ // node banners.cjs --phase 7 12 "Workflows" ember
35
35
 
36
36
  // ─── Plain-mode detection ─────────────────────────────────────────────────────
37
37
  // Resolved at call-time so tests can flip env vars dynamically.
@@ -61,14 +61,13 @@ const f = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
61
61
  // ─── Mode tints ───────────────────────────────────────────────────────────────
62
62
  // Mode-aware accent colour for progress bars and subtitles. Used by phaseHeader.
63
63
  const MODE_TINTS = {
64
- fast: [255, 208, 122], // lantern yellow
65
64
  full: [255, 138, 60], // ember orange
66
65
  };
67
66
 
68
67
  // ─── Zen blue ─────────────────────────────────────────────────────────────────
69
68
  // System-wide horizontal-rule tint. Applied to em-dash separators in
70
- // phaseHeader, ruleLine, and ensure-ready.cjs --announce framing. Picked to
71
- // read calm and cool without competing with banner colours.
69
+ // phaseHeader and ruleLine. Picked to read calm and cool without competing
70
+ // with banner colours.
72
71
  const ZEN_BLUE = [100, 140, 200];
73
72
 
74
73
  // ─── Banner registry ───────────────────────────────────────────────────────────
@@ -196,7 +196,7 @@ function buildContextPack({ archDir, existingPackPath }) {
196
196
  if (realLineCount > PACK_LINE_LIMIT) {
197
197
  // Keep PACK_LINE_LIMIT - 1 lines so the marker fits within the cap
198
198
  const truncated = splitLines.slice(0, PACK_LINE_LIMIT - 1);
199
- truncated.push('<!-- TRUNCATED: pack exceeded 400 lines. Architecture KB has grown beyond summary capacity. Run /forge:regenerate after pruning docs. -->');
199
+ truncated.push('<!-- TRUNCATED: pack exceeded 400 lines. Architecture KB has grown beyond summary capacity. Run /forge:rebuild after pruning docs. -->');
200
200
  markdown = truncated.join('\n') + '\n';
201
201
  }
202
202
 
@@ -59,11 +59,16 @@ function checkNamespaces(manifest, projectRoot, options = {}) {
59
59
 
60
60
  for (const [nsKey, ns] of Object.entries(manifest.namespaces)) {
61
61
  const logicalKey = ns.logicalKey || nsKey;
62
- let resolvedDir = (resolvedConfigPaths[logicalKey] && typeof resolvedConfigPaths[logicalKey] === 'string')
62
+ const configHasPath = resolvedConfigPaths[logicalKey] && typeof resolvedConfigPaths[logicalKey] === 'string';
63
+ let resolvedDir = configHasPath
63
64
  ? resolvedConfigPaths[logicalKey]
64
65
  : ns.dir;
65
- if (ns.prefixed && projectPrefix) {
66
- resolvedDir = resolvedDir + '/' + projectPrefix;
66
+ // When config provides the path, use it verbatim (it already includes any
67
+ // prefix subdirectory). Only apply the prefixed append when falling back
68
+ // to the manifest's base dir.
69
+ if (ns.prefixed && !configHasPath) {
70
+ const suffix = projectPrefix || getCommandsSubdir('forge');
71
+ resolvedDir = resolvedDir + '/' + suffix;
67
72
  }
68
73
  const absDir = path.join(projectRoot, resolvedDir);
69
74
 
@@ -558,10 +558,17 @@ function cmdWrite() {
558
558
  function cmdRead() {
559
559
  const entity = args[1];
560
560
  const id = args[2];
561
- const asJson = args.includes('--json');
561
+ const asJson = args.includes('--json');
562
+ const noSummaries = args.includes('--no-summaries');
563
+
564
+ let fieldsProjection = null;
565
+ const fieldsIdx = args.indexOf('--fields');
566
+ if (fieldsIdx !== -1 && args[fieldsIdx + 1] && !args[fieldsIdx + 1].startsWith('--')) {
567
+ fieldsProjection = args[fieldsIdx + 1].split(',').map((f) => f.trim()).filter(Boolean);
568
+ }
562
569
 
563
570
  if (!entity || !id) {
564
- console.error('Usage: store-cli.cjs read <entity> <id> [--json]');
571
+ console.error('Usage: store-cli.cjs read <entity> <id> [--json] [--no-summaries] [--fields <comma-list>]');
565
572
  process.exit(1);
566
573
  }
567
574
 
@@ -590,10 +597,19 @@ function cmdRead() {
590
597
  process.exit(1);
591
598
  }
592
599
 
600
+ // Apply projection before formatting
601
+ let projected = record;
602
+ if (noSummaries) {
603
+ projected = Object.fromEntries(Object.entries(projected).filter(([k]) => k !== 'summaries'));
604
+ }
605
+ if (fieldsProjection) {
606
+ projected = Object.fromEntries(fieldsProjection.map((f) => [f, projected[f]]).filter(([, v]) => v !== undefined));
607
+ }
608
+
593
609
  if (asJson) {
594
- console.log(JSON.stringify(record));
610
+ console.log(JSON.stringify(projected));
595
611
  } else {
596
- console.log(JSON.stringify(record, null, 2));
612
+ console.log(JSON.stringify(projected, null, 2));
597
613
  }
598
614
  }
599
615
 
@@ -601,7 +617,7 @@ function cmdList() {
601
617
  const entity = args[1];
602
618
 
603
619
  if (!entity) {
604
- console.error('Usage: store-cli.cjs list <entity> [key=value ...]');
620
+ console.error('Usage: store-cli.cjs list <entity> [key=value ...] [--no-summaries] [--fields <comma-list>] [--limit N] [--count]');
605
621
  process.exit(1);
606
622
  }
607
623
 
@@ -610,9 +626,27 @@ function cmdList() {
610
626
  process.exit(1);
611
627
  }
612
628
 
613
- // Parse key=value filter pairs from remaining args
629
+ // Parse projection flags and key=value filter pairs from remaining args
630
+ const noSummaries = args.includes('--no-summaries');
631
+ const countOnly = args.includes('--count');
632
+
633
+ let fieldsProjection = null;
634
+ const fieldsIdx = args.indexOf('--fields');
635
+ if (fieldsIdx !== -1 && args[fieldsIdx + 1] && !args[fieldsIdx + 1].startsWith('--')) {
636
+ fieldsProjection = args[fieldsIdx + 1].split(',').map((f) => f.trim()).filter(Boolean);
637
+ }
638
+
639
+ let limitN = null;
640
+ const limitIdx = args.indexOf('--limit');
641
+ if (limitIdx !== -1 && args[limitIdx + 1] && !args[limitIdx + 1].startsWith('--')) {
642
+ const n = parseInt(args[limitIdx + 1], 10);
643
+ if (!isNaN(n) && n >= 0) limitN = n;
644
+ }
645
+
614
646
  const filter = {};
615
647
  for (let i = 2; i < args.length; i++) {
648
+ // Skip flag arguments and their value arguments
649
+ if (args[i].startsWith('--')) { i++; continue; }
616
650
  const eqIdx = args[i].indexOf('=');
617
651
  if (eqIdx > 0) {
618
652
  const key = args[i].slice(0, eqIdx);
@@ -623,7 +657,33 @@ function cmdList() {
623
657
  }
624
658
  }
625
659
 
626
- const records = listEntities(entity, Object.keys(filter).length > 0 ? filter : undefined);
660
+ let records = listEntities(entity, Object.keys(filter).length > 0 ? filter : undefined);
661
+
662
+ // --count: emit bare integer and exit (mutually exclusive with other flags)
663
+ if (countOnly) {
664
+ console.log(String(records.length));
665
+ return;
666
+ }
667
+
668
+ // --limit: truncate after filtering
669
+ if (limitN !== null) {
670
+ records = records.slice(0, limitN);
671
+ }
672
+
673
+ // Apply projection
674
+ if (fieldsProjection || noSummaries) {
675
+ records = records.map((rec) => {
676
+ let projected = rec;
677
+ if (noSummaries) {
678
+ projected = Object.fromEntries(Object.entries(projected).filter(([k]) => k !== 'summaries'));
679
+ }
680
+ if (fieldsProjection) {
681
+ projected = Object.fromEntries(fieldsProjection.map((f) => [f, projected[f]]).filter(([, v]) => v !== undefined));
682
+ }
683
+ return projected;
684
+ });
685
+ }
686
+
627
687
  console.log(JSON.stringify(records, null, 2));
628
688
  }
629
689
 
@@ -9,7 +9,7 @@
9
9
  * output to the appropriate output directories.
10
10
  *
11
11
  * Output path mapping (--target claude-code, default):
12
- * base-pack/commands/ → <outRoot>/.claude/commands/forge/
12
+ * base-pack/commands/ → <outRoot>/.claude/commands/<prefix>/
13
13
  * base-pack/personas/ → <outRoot>/.forge/personas/
14
14
  * base-pack/skills/ → <outRoot>/.forge/skills/
15
15
  * base-pack/workflows/ → <outRoot>/.forge/workflows/
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ // Forge tool: verify-apply
5
+ // Verify that claimed file modifications actually landed on disk by checking
6
+ // each path against the generation-manifest baseline.
7
+ //
8
+ // Usage: node verify-apply.cjs <path1> [<path2> ...]
9
+ //
10
+ // Output: JSON to stdout:
11
+ // { "modified": [...], "unchanged": [...], "untracked": [...], "missing": [...] }
12
+ //
13
+ // Exit codes:
14
+ // 0 = all paths verified modified (success — agent claim was correct)
15
+ // 1 = any unchanged paths present (agent claim was wrong — re-apply needed)
16
+ // 2 = usage error (no paths provided)
17
+
18
+ const { spawnSync } = require('child_process');
19
+ const path = require('path');
20
+ const { findProjectRoot } = require('./lib/project-root.cjs');
21
+
22
+ if (require.main === module) {
23
+
24
+ const claimedPaths = process.argv.slice(2);
25
+
26
+ if (claimedPaths.length === 0) {
27
+ process.stderr.write('Usage: node verify-apply.cjs <path1> [<path2> ...]\n');
28
+ process.exit(2);
29
+ }
30
+
31
+ const projectRoot = findProjectRoot() || process.cwd();
32
+ const toolDir = __dirname;
33
+ const manifestTool = path.join(toolDir, 'generation-manifest.cjs');
34
+
35
+ const result = {
36
+ modified: [],
37
+ unchanged: [],
38
+ untracked: [],
39
+ missing: [],
40
+ };
41
+
42
+ for (const claimedPath of claimedPaths) {
43
+ const r = spawnSync('node', [manifestTool, 'check', claimedPath], {
44
+ cwd: projectRoot,
45
+ encoding: 'utf8',
46
+ timeout: 5_000,
47
+ });
48
+ switch (r.status) {
49
+ case 0:
50
+ result.unchanged.push(claimedPath);
51
+ break;
52
+ case 1:
53
+ result.modified.push(claimedPath);
54
+ break;
55
+ case 2:
56
+ result.untracked.push(claimedPath);
57
+ break;
58
+ case 3:
59
+ result.missing.push(claimedPath);
60
+ break;
61
+ default:
62
+ // Spawn error, timeout, or unrecognized exit code — safety default: missing
63
+ result.missing.push(claimedPath);
64
+ }
65
+ }
66
+
67
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
68
+
69
+ // Exit 1 if any unchanged paths (agent claim was wrong)
70
+ if (result.unchanged.length > 0) {
71
+ process.exit(1);
72
+ }
73
+ process.exit(0);
74
+
75
+ } // end if (require.main === module)