@entelligentsia/forgecli 1.0.20 → 1.0.25

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 (417) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/README.md +7 -1
  3. package/dist/CHANGELOG-forge-plugin.md +118 -0
  4. package/dist/bin/config.js +4 -4
  5. package/dist/bin/config.js.map +1 -1
  6. package/dist/bin/update-cli.d.ts +1 -1
  7. package/dist/bin/update-cli.js +1 -1
  8. package/dist/bin/update-cli.js.map +1 -1
  9. package/dist/extensions/forgecli/ask-user-tool.js +1 -1
  10. package/dist/extensions/forgecli/ask-user-tool.js.map +1 -1
  11. package/dist/extensions/forgecli/{add-pipeline.js → commands/add-pipeline.js} +1 -1
  12. package/dist/extensions/forgecli/commands/add-pipeline.js.map +1 -0
  13. package/dist/extensions/forgecli/{add-task.js → commands/add-task.js} +1 -1
  14. package/dist/extensions/forgecli/commands/add-task.js.map +1 -0
  15. package/dist/extensions/forgecli/{approve.d.ts → commands/approve.d.ts} +2 -2
  16. package/dist/extensions/forgecli/{approve.js → commands/approve.js} +8 -8
  17. package/dist/extensions/forgecli/commands/approve.js.map +1 -0
  18. package/dist/extensions/forgecli/{collate.d.ts → commands/collate.d.ts} +2 -2
  19. package/dist/extensions/forgecli/{collate.js → commands/collate.js} +6 -6
  20. package/dist/extensions/forgecli/commands/collate.js.map +1 -0
  21. package/dist/extensions/forgecli/{commit.d.ts → commands/commit.d.ts} +2 -2
  22. package/dist/extensions/forgecli/{commit.js → commands/commit.js} +8 -8
  23. package/dist/extensions/forgecli/commands/commit.js.map +1 -0
  24. package/dist/extensions/forgecli/{config-command.js → commands/config-command.js} +3 -3
  25. package/dist/extensions/forgecli/commands/config-command.js.map +1 -0
  26. package/dist/extensions/forgecli/commands/enhance.d.ts +45 -0
  27. package/dist/extensions/forgecli/{enhance.js → commands/enhance.js} +95 -75
  28. package/dist/extensions/forgecli/commands/enhance.js.map +1 -0
  29. package/dist/extensions/forgecli/{implement.d.ts → commands/implement.d.ts} +2 -2
  30. package/dist/extensions/forgecli/{implement.js → commands/implement.js} +8 -8
  31. package/dist/extensions/forgecli/commands/implement.js.map +1 -0
  32. package/dist/extensions/forgecli/{plan.d.ts → commands/plan.d.ts} +2 -2
  33. package/dist/extensions/forgecli/{plan.js → commands/plan.js} +8 -8
  34. package/dist/extensions/forgecli/commands/plan.js.map +1 -0
  35. package/dist/extensions/forgecli/{quiz-agent.js → commands/quiz-agent.js} +1 -1
  36. package/dist/extensions/forgecli/commands/quiz-agent.js.map +1 -0
  37. package/dist/extensions/forgecli/{read-command.js → commands/read-command.js} +2 -2
  38. package/dist/extensions/forgecli/commands/read-command.js.map +1 -0
  39. package/dist/extensions/forgecli/{regenerate.js → commands/regenerate.js} +7 -19
  40. package/dist/extensions/forgecli/commands/regenerate.js.map +1 -0
  41. package/dist/extensions/forgecli/{remove-command.js → commands/remove-command.js} +1 -1
  42. package/dist/extensions/forgecli/commands/remove-command.js.map +1 -0
  43. package/dist/extensions/forgecli/{report-bug.js → commands/report-bug.js} +1 -1
  44. package/dist/extensions/forgecli/commands/report-bug.js.map +1 -0
  45. package/dist/extensions/forgecli/{retrospective.d.ts → commands/retrospective.d.ts} +1 -1
  46. package/dist/extensions/forgecli/{retrospective.js → commands/retrospective.js} +5 -5
  47. package/dist/extensions/forgecli/commands/retrospective.js.map +1 -0
  48. package/dist/extensions/forgecli/{review-code.d.ts → commands/review-code.d.ts} +2 -2
  49. package/dist/extensions/forgecli/{review-code.js → commands/review-code.js} +9 -9
  50. package/dist/extensions/forgecli/commands/review-code.js.map +1 -0
  51. package/dist/extensions/forgecli/{review-plan.d.ts → commands/review-plan.d.ts} +2 -2
  52. package/dist/extensions/forgecli/{review-plan.js → commands/review-plan.js} +9 -9
  53. package/dist/extensions/forgecli/commands/review-plan.js.map +1 -0
  54. package/dist/extensions/forgecli/commands/sprint-intake.js.map +1 -0
  55. package/dist/extensions/forgecli/commands/sprint-plan.js.map +1 -0
  56. package/dist/extensions/forgecli/{status-command.js → commands/status-command.js} +1 -1
  57. package/dist/extensions/forgecli/commands/status-command.js.map +1 -0
  58. package/dist/extensions/forgecli/{store-query.js → commands/store-query.js} +1 -1
  59. package/dist/extensions/forgecli/commands/store-query.js.map +1 -0
  60. package/dist/extensions/forgecli/{store-repair.js → commands/store-repair.js} +1 -1
  61. package/dist/extensions/forgecli/commands/store-repair.js.map +1 -0
  62. package/dist/extensions/forgecli/{test-orchestrate.js → commands/test-orchestrate.js} +1 -1
  63. package/dist/extensions/forgecli/commands/test-orchestrate.js.map +1 -0
  64. package/dist/extensions/forgecli/commands/transcripts-command.d.ts +87 -0
  65. package/dist/extensions/forgecli/commands/transcripts-command.js +418 -0
  66. package/dist/extensions/forgecli/commands/transcripts-command.js.map +1 -0
  67. package/dist/extensions/forgecli/{validate.d.ts → commands/validate.d.ts} +2 -2
  68. package/dist/extensions/forgecli/{validate.js → commands/validate.js} +8 -8
  69. package/dist/extensions/forgecli/commands/validate.js.map +1 -0
  70. package/dist/extensions/forgecli/{config-layer.js → config/config-layer.js} +2 -2
  71. package/dist/extensions/forgecli/config/config-layer.js.map +1 -0
  72. package/dist/extensions/forgecli/{config-writer.js → config/config-writer.js} +2 -2
  73. package/dist/extensions/forgecli/config/config-writer.js.map +1 -0
  74. package/dist/extensions/forgecli/{model-registry.js → config/model-registry.js} +1 -1
  75. package/dist/extensions/forgecli/config/model-registry.js.map +1 -0
  76. package/dist/extensions/forgecli/config/model-resolver.js.map +1 -0
  77. package/dist/extensions/forgecli/config/model-validator.js.map +1 -0
  78. package/dist/extensions/forgecli/config-tui/component.js +1 -1
  79. package/dist/extensions/forgecli/config-tui/component.js.map +1 -1
  80. package/dist/extensions/forgecli/config-tui/handler.js +1 -1
  81. package/dist/extensions/forgecli/config-tui/handler.js.map +1 -1
  82. package/dist/extensions/forgecli/config-tui/screens/override-editor.js +1 -1
  83. package/dist/extensions/forgecli/config-tui/screens/override-editor.js.map +1 -1
  84. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js +1 -1
  85. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js.map +1 -1
  86. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js +1 -1
  87. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js.map +1 -1
  88. package/dist/extensions/forgecli/config-tui/state/buffer.d.ts +2 -2
  89. package/dist/extensions/forgecli/config-tui/state/model.d.ts +1 -1
  90. package/dist/extensions/forgecli/config-tui/state/reducer.js.map +1 -1
  91. package/dist/extensions/forgecli/config-tui/state/selectors.d.ts +2 -2
  92. package/dist/extensions/forgecli/config-tui/state/selectors.js +1 -1
  93. package/dist/extensions/forgecli/config-tui/state/selectors.js.map +1 -1
  94. package/dist/extensions/forgecli/context-governor-compaction.d.ts +13 -2
  95. package/dist/extensions/forgecli/context-governor-compaction.js +66 -41
  96. package/dist/extensions/forgecli/context-governor-compaction.js.map +1 -1
  97. package/dist/extensions/forgecli/context-governor.d.ts +3 -7
  98. package/dist/extensions/forgecli/context-governor.js +43 -69
  99. package/dist/extensions/forgecli/context-governor.js.map +1 -1
  100. package/dist/extensions/forgecli/dashboard/component.d.ts +10 -1
  101. package/dist/extensions/forgecli/dashboard/component.js +84 -18
  102. package/dist/extensions/forgecli/dashboard/component.js.map +1 -1
  103. package/dist/extensions/forgecli/dashboard/register.js +1 -1
  104. package/dist/extensions/forgecli/dashboard/register.js.map +1 -1
  105. package/dist/extensions/forgecli/forge-artifact-tool.js +1 -1
  106. package/dist/extensions/forgecli/forge-commands.js +1 -1
  107. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  108. package/dist/extensions/forgecli/{forge-init.js → forge-init/forge-init.js} +10 -10
  109. package/dist/extensions/forgecli/forge-init/forge-init.js.map +1 -0
  110. package/dist/extensions/forgecli/forge-init/init-context.js.map +1 -0
  111. package/dist/extensions/forgecli/forge-init/init-progress.js.map +1 -0
  112. package/dist/extensions/forgecli/forge-init/phase4-register.js +1 -1
  113. package/dist/extensions/forgecli/forge-init/phase4-register.js.map +1 -1
  114. package/dist/extensions/forgecli/forge-init/run-phases.js +2 -2
  115. package/dist/extensions/forgecli/forge-init/run-phases.js.map +1 -1
  116. package/dist/extensions/forgecli/forge-subagent.d.ts +22 -0
  117. package/dist/extensions/forgecli/forge-subagent.js +42 -15
  118. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  119. package/dist/extensions/forgecli/forge-tools.d.ts +1 -25
  120. package/dist/extensions/forgecli/forge-tools.js +79 -37
  121. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  122. package/dist/extensions/forgecli/governor-config.d.ts +19 -0
  123. package/dist/extensions/forgecli/governor-config.js +58 -0
  124. package/dist/extensions/forgecli/governor-config.js.map +1 -0
  125. package/dist/extensions/forgecli/health-check.js +1 -1
  126. package/dist/extensions/forgecli/health-check.js.map +1 -1
  127. package/dist/extensions/forgecli/hook-dispatcher.js +2 -2
  128. package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
  129. package/dist/extensions/forgecli/hooks/post-init-hook.js +11 -6
  130. package/dist/extensions/forgecli/hooks/post-init-hook.js.map +1 -1
  131. package/dist/extensions/forgecli/hooks/post-sprint-hook.js +11 -6
  132. package/dist/extensions/forgecli/hooks/post-sprint-hook.js.map +1 -1
  133. package/dist/extensions/forgecli/hooks/write-guard.js +1 -1
  134. package/dist/extensions/forgecli/hooks/write-guard.js.map +1 -1
  135. package/dist/extensions/forgecli/index.js +37 -35
  136. package/dist/extensions/forgecli/index.js.map +1 -1
  137. package/dist/extensions/forgecli/kickoff.d.ts +9 -0
  138. package/dist/extensions/forgecli/kickoff.js +15 -0
  139. package/dist/extensions/forgecli/kickoff.js.map +1 -1
  140. package/dist/extensions/forgecli/lib/forge-config.d.ts +1 -1
  141. package/dist/extensions/forgecli/lib/forge-config.js +1 -1
  142. package/dist/extensions/forgecli/lib/forge-config.js.map +1 -1
  143. package/dist/extensions/forgecli/{forge-root.d.ts → lib/forge-root.d.ts} +5 -0
  144. package/dist/extensions/forgecli/{forge-root.js → lib/forge-root.js} +14 -1
  145. package/dist/extensions/forgecli/lib/forge-root.js.map +1 -0
  146. package/dist/extensions/forgecli/lib/run-cjs.d.ts +26 -0
  147. package/dist/extensions/forgecli/lib/run-cjs.js +42 -0
  148. package/dist/extensions/forgecli/lib/run-cjs.js.map +1 -0
  149. package/dist/extensions/forgecli/orchestrator-tree.d.ts +4 -0
  150. package/dist/extensions/forgecli/orchestrator-tree.js +21 -3
  151. package/dist/extensions/forgecli/orchestrator-tree.js.map +1 -1
  152. package/dist/extensions/forgecli/{calibrate.d.ts → orchestrators/calibrate.d.ts} +2 -2
  153. package/dist/extensions/forgecli/{calibrate.js → orchestrators/calibrate.js} +4 -4
  154. package/dist/extensions/forgecli/orchestrators/calibrate.js.map +1 -0
  155. package/dist/extensions/forgecli/{fix-bug.d.ts → orchestrators/fix-bug.d.ts} +14 -5
  156. package/dist/extensions/forgecli/{fix-bug.js → orchestrators/fix-bug.js} +212 -61
  157. package/dist/extensions/forgecli/orchestrators/fix-bug.js.map +1 -0
  158. package/dist/extensions/forgecli/{lib → orchestrators}/halt-advisor.d.ts +1 -1
  159. package/dist/extensions/forgecli/{lib → orchestrators}/halt-advisor.js +1 -1
  160. package/dist/extensions/forgecli/orchestrators/halt-advisor.js.map +1 -0
  161. package/dist/extensions/forgecli/{materialize.js → orchestrators/materialize.js} +1 -1
  162. package/dist/extensions/forgecli/orchestrators/materialize.js.map +1 -0
  163. package/dist/extensions/forgecli/{migrate.d.ts → orchestrators/migrate.d.ts} +1 -1
  164. package/dist/extensions/forgecli/{migrate.js → orchestrators/migrate.js} +5 -5
  165. package/dist/extensions/forgecli/orchestrators/migrate.js.map +1 -0
  166. package/dist/extensions/forgecli/{lib → orchestrators}/orchestrator-preflight.d.ts +2 -2
  167. package/dist/extensions/forgecli/{lib → orchestrators}/orchestrator-preflight.js +2 -2
  168. package/dist/extensions/forgecli/orchestrators/orchestrator-preflight.js.map +1 -0
  169. package/dist/extensions/forgecli/{run-sprint.d.ts → orchestrators/run-sprint.d.ts} +1 -1
  170. package/dist/extensions/forgecli/{run-sprint.js → orchestrators/run-sprint.js} +85 -18
  171. package/dist/extensions/forgecli/orchestrators/run-sprint.js.map +1 -0
  172. package/dist/extensions/forgecli/{run-task.d.ts → orchestrators/run-task.d.ts} +14 -3
  173. package/dist/extensions/forgecli/{run-task.js → orchestrators/run-task.js} +121 -33
  174. package/dist/extensions/forgecli/orchestrators/run-task.js.map +1 -0
  175. package/dist/extensions/forgecli/paths/paths.d.ts +8 -0
  176. package/dist/extensions/forgecli/paths/paths.js +17 -0
  177. package/dist/extensions/forgecli/paths/paths.js.map +1 -1
  178. package/dist/extensions/forgecli/phase-vocab.d.ts +31 -0
  179. package/dist/extensions/forgecli/phase-vocab.js +82 -0
  180. package/dist/extensions/forgecli/phase-vocab.js.map +1 -0
  181. package/dist/extensions/forgecli/session-registry.d.ts +2 -2
  182. package/dist/extensions/forgecli/session-registry.js +6 -2
  183. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  184. package/dist/extensions/forgecli/{friction-emit.d.ts → skill-curation/friction-emit.d.ts} +1 -1
  185. package/dist/extensions/forgecli/{friction-emit.js → skill-curation/friction-emit.js} +2 -2
  186. package/dist/extensions/forgecli/skill-curation/friction-emit.js.map +1 -0
  187. package/dist/extensions/forgecli/{skill-curation-flag.js → skill-curation/skill-curation-flag.js} +1 -1
  188. package/dist/extensions/forgecli/skill-curation/skill-curation-flag.js.map +1 -0
  189. package/dist/extensions/forgecli/{skill-curator-subagent.d.ts → skill-curation/skill-curator-subagent.d.ts} +2 -2
  190. package/dist/extensions/forgecli/{skill-curator-subagent.js → skill-curation/skill-curator-subagent.js} +1 -1
  191. package/dist/extensions/forgecli/skill-curation/skill-curator-subagent.js.map +1 -0
  192. package/dist/extensions/forgecli/{skill-retriever.js → skill-curation/skill-retriever.js} +1 -1
  193. package/dist/extensions/forgecli/skill-curation/skill-retriever.js.map +1 -0
  194. package/dist/extensions/forgecli/{skill-usage-tracker.js → skill-curation/skill-usage-tracker.js} +1 -1
  195. package/dist/extensions/forgecli/skill-curation/skill-usage-tracker.js.map +1 -0
  196. package/dist/extensions/forgecli/store/store-error-remediation.js.map +1 -0
  197. package/dist/extensions/forgecli/{store-resolver.js → store/store-resolver.js} +2 -2
  198. package/dist/extensions/forgecli/store/store-resolver.js.map +1 -0
  199. package/dist/extensions/forgecli/{store-validator.js → store/store-validator.js} +1 -1
  200. package/dist/extensions/forgecli/store/store-validator.js.map +1 -0
  201. package/dist/extensions/forgecli/{transition-guard.js → store/transition-guard.js} +2 -2
  202. package/dist/extensions/forgecli/store/transition-guard.js.map +1 -0
  203. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js +5 -0
  204. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js.map +1 -1
  205. package/dist/extensions/forgecli/transcript-archive-types.d.ts +171 -0
  206. package/dist/extensions/forgecli/transcript-archive-types.js +130 -0
  207. package/dist/extensions/forgecli/transcript-archive-types.js.map +1 -0
  208. package/dist/extensions/forgecli/transcript-archive.d.ts +127 -0
  209. package/dist/extensions/forgecli/transcript-archive.js +656 -0
  210. package/dist/extensions/forgecli/transcript-archive.js.map +1 -0
  211. package/dist/extensions/forgecli/transcript-replay.d.ts +28 -0
  212. package/dist/extensions/forgecli/transcript-replay.js +153 -0
  213. package/dist/extensions/forgecli/transcript-replay.js.map +1 -0
  214. package/dist/extensions/forgecli/transcripts-tui/component.d.ts +36 -0
  215. package/dist/extensions/forgecli/transcripts-tui/component.js +112 -0
  216. package/dist/extensions/forgecli/transcripts-tui/component.js.map +1 -0
  217. package/dist/extensions/forgecli/transcripts-tui/index.d.ts +4 -0
  218. package/dist/extensions/forgecli/transcripts-tui/index.js +5 -0
  219. package/dist/extensions/forgecli/transcripts-tui/index.js.map +1 -0
  220. package/dist/extensions/forgecli/transcripts-tui/screens/browse.d.ts +21 -0
  221. package/dist/extensions/forgecli/transcripts-tui/screens/browse.js +172 -0
  222. package/dist/extensions/forgecli/transcripts-tui/screens/browse.js.map +1 -0
  223. package/dist/extensions/forgecli/transcripts-tui/screens/types.d.ts +22 -0
  224. package/dist/extensions/forgecli/transcripts-tui/screens/types.js +4 -0
  225. package/dist/extensions/forgecli/transcripts-tui/screens/types.js.map +1 -0
  226. package/dist/extensions/forgecli/transcripts-tui/state/index.d.ts +4 -0
  227. package/dist/extensions/forgecli/transcripts-tui/state/index.js +5 -0
  228. package/dist/extensions/forgecli/transcripts-tui/state/index.js.map +1 -0
  229. package/dist/extensions/forgecli/transcripts-tui/state/init.d.ts +8 -0
  230. package/dist/extensions/forgecli/transcripts-tui/state/init.js +18 -0
  231. package/dist/extensions/forgecli/transcripts-tui/state/init.js.map +1 -0
  232. package/dist/extensions/forgecli/transcripts-tui/state/model.d.ts +56 -0
  233. package/dist/extensions/forgecli/transcripts-tui/state/model.js +6 -0
  234. package/dist/extensions/forgecli/transcripts-tui/state/model.js.map +1 -0
  235. package/dist/extensions/forgecli/transcripts-tui/state/reducer.d.ts +2 -0
  236. package/dist/extensions/forgecli/transcripts-tui/state/reducer.js +51 -0
  237. package/dist/extensions/forgecli/transcripts-tui/state/reducer.js.map +1 -0
  238. package/dist/extensions/forgecli/transcripts-tui/state/selectors.d.ts +10 -0
  239. package/dist/extensions/forgecli/transcripts-tui/state/selectors.js +62 -0
  240. package/dist/extensions/forgecli/transcripts-tui/state/selectors.js.map +1 -0
  241. package/dist/extensions/forgecli/transcripts-tui/theme.d.ts +20 -0
  242. package/dist/extensions/forgecli/transcripts-tui/theme.js +47 -0
  243. package/dist/extensions/forgecli/transcripts-tui/theme.js.map +1 -0
  244. package/dist/extensions/forgecli/tui/banner.js.map +1 -0
  245. package/dist/extensions/forgecli/tui/forge-header.js.map +1 -0
  246. package/dist/extensions/forgecli/tui/input-router.js.map +1 -0
  247. package/dist/extensions/forgecli/{orchestrator-status-bar.d.ts → tui/orchestrator-status-bar.d.ts} +1 -1
  248. package/dist/extensions/forgecli/{orchestrator-status-bar.js → tui/orchestrator-status-bar.js} +1 -1
  249. package/dist/extensions/forgecli/tui/orchestrator-status-bar.js.map +1 -0
  250. package/dist/extensions/forgecli/tui/thread-switcher.d.ts +18 -0
  251. package/dist/extensions/forgecli/{thread-switcher.js → tui/thread-switcher.js} +17 -12
  252. package/dist/extensions/forgecli/tui/thread-switcher.js.map +1 -0
  253. package/dist/extensions/forgecli/{forge-update-command.js → update/forge-update-command.js} +3 -3
  254. package/dist/extensions/forgecli/update/forge-update-command.js.map +1 -0
  255. package/dist/extensions/forgecli/{migration-engine.js → update/migration-engine.js} +1 -1
  256. package/dist/extensions/forgecli/update/migration-engine.js.map +1 -0
  257. package/dist/extensions/forgecli/{update-check.js → update/update-check.js} +1 -1
  258. package/dist/extensions/forgecli/update/update-check.js.map +1 -0
  259. package/dist/extensions/forgecli/{update-tools.js → update/update-tools.js} +1 -1
  260. package/dist/extensions/forgecli/update/update-tools.js.map +1 -0
  261. package/dist/extensions/forgecli/{whats-new-widget.js → update/whats-new-widget.js} +2 -2
  262. package/dist/extensions/forgecli/update/whats-new-widget.js.map +1 -0
  263. package/dist/extensions/forgecli/{whats-new.js → update/whats-new.js} +1 -1
  264. package/dist/extensions/forgecli/update/whats-new.js.map +1 -0
  265. package/dist/extensions/forgecli/{viewport-events.d.ts → viewport/events.d.ts} +37 -2
  266. package/dist/extensions/forgecli/{viewport-events.js → viewport/events.js} +70 -23
  267. package/dist/extensions/forgecli/viewport/events.js.map +1 -0
  268. package/dist/extensions/forgecli/{viewport-renderer.d.ts → viewport/renderer.d.ts} +19 -0
  269. package/dist/extensions/forgecli/{viewport-renderer.js → viewport/renderer.js} +46 -2
  270. package/dist/extensions/forgecli/viewport/renderer.js.map +1 -0
  271. package/dist/extensions/forgecli/{viewport-theme.js → viewport/theme.js} +13 -10
  272. package/dist/extensions/forgecli/viewport/theme.js.map +1 -0
  273. package/dist/extensions/forgecli/wf-engine/engine.js +1 -1
  274. package/dist/extensions/forgecli/wf-engine/engine.js.map +1 -1
  275. package/dist/forge-payload/.base-pack/workflows/_fragments/event-emission-schema.md +4 -0
  276. package/dist/forge-payload/.base-pack/workflows/_fragments/event-vocabulary.md +88 -0
  277. package/dist/forge-payload/.base-pack/workflows/commit_task.md +41 -38
  278. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +3 -3
  279. package/dist/forge-payload/.base-pack/workflows-js/wfl-fix-bug.js +42 -6
  280. package/dist/forge-payload/.base-pack/workflows-js/wfl-run-task.js +32 -1
  281. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  282. package/dist/forge-payload/.schemas/enum-catalog.json +2 -2
  283. package/dist/forge-payload/.schemas/event.schema.json +8 -3
  284. package/dist/forge-payload/.schemas/migrations.json +56 -0
  285. package/dist/forge-payload/integrity.json +3 -3
  286. package/dist/forge-payload/meta/store-schema/event.schema.md +7 -0
  287. package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +4 -0
  288. package/dist/forge-payload/meta/workflows/_fragments/event-vocabulary.md +88 -0
  289. package/dist/forge-payload/meta/workflows/meta-commit.md +46 -43
  290. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +7 -2
  291. package/dist/forge-payload/meta/workflows/meta-implement.md +3 -3
  292. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +4 -1
  293. package/dist/forge-payload/schemas/enum-catalog.json +2 -2
  294. package/dist/forge-payload/schemas/event.schema.json +8 -3
  295. package/dist/forge-payload/schemas/structure-manifest.json +4 -2
  296. package/dist/forge-payload/tools/commit-task.cjs +218 -0
  297. package/dist/forge-payload/tools/store-cli.cjs +6 -1
  298. package/node_modules/@mariozechner/clipboard/package.json +2 -1
  299. package/node_modules/@mariozechner/clipboard-linux-x64-musl/README.md +3 -0
  300. package/node_modules/@mariozechner/clipboard-linux-x64-musl/package.json +25 -0
  301. package/package.json +5 -3
  302. package/dist/extensions/forgecli/add-pipeline.js.map +0 -1
  303. package/dist/extensions/forgecli/add-task.js.map +0 -1
  304. package/dist/extensions/forgecli/approve.js.map +0 -1
  305. package/dist/extensions/forgecli/banner.js.map +0 -1
  306. package/dist/extensions/forgecli/calibrate.js.map +0 -1
  307. package/dist/extensions/forgecli/collate.js.map +0 -1
  308. package/dist/extensions/forgecli/commit.js.map +0 -1
  309. package/dist/extensions/forgecli/config-command.js.map +0 -1
  310. package/dist/extensions/forgecli/config-layer.js.map +0 -1
  311. package/dist/extensions/forgecli/config-writer.js.map +0 -1
  312. package/dist/extensions/forgecli/enhance.d.ts +0 -27
  313. package/dist/extensions/forgecli/enhance.js.map +0 -1
  314. package/dist/extensions/forgecli/fix-bug.js.map +0 -1
  315. package/dist/extensions/forgecli/forge-header.js.map +0 -1
  316. package/dist/extensions/forgecli/forge-init.js.map +0 -1
  317. package/dist/extensions/forgecli/forge-root.js.map +0 -1
  318. package/dist/extensions/forgecli/forge-update-command.js.map +0 -1
  319. package/dist/extensions/forgecli/friction-emit.js.map +0 -1
  320. package/dist/extensions/forgecli/implement.js.map +0 -1
  321. package/dist/extensions/forgecli/init-context.js.map +0 -1
  322. package/dist/extensions/forgecli/init-progress.js.map +0 -1
  323. package/dist/extensions/forgecli/input-router.js.map +0 -1
  324. package/dist/extensions/forgecli/lib/halt-advisor.js.map +0 -1
  325. package/dist/extensions/forgecli/lib/orchestrator-preflight.js.map +0 -1
  326. package/dist/extensions/forgecli/materialize.js.map +0 -1
  327. package/dist/extensions/forgecli/migrate.js.map +0 -1
  328. package/dist/extensions/forgecli/migration-engine.js.map +0 -1
  329. package/dist/extensions/forgecli/model-registry.js.map +0 -1
  330. package/dist/extensions/forgecli/model-resolver.js.map +0 -1
  331. package/dist/extensions/forgecli/model-validator.js.map +0 -1
  332. package/dist/extensions/forgecli/orchestrator-status-bar.js.map +0 -1
  333. package/dist/extensions/forgecli/plan.js.map +0 -1
  334. package/dist/extensions/forgecli/quiz-agent.js.map +0 -1
  335. package/dist/extensions/forgecli/read-command.js.map +0 -1
  336. package/dist/extensions/forgecli/regenerate.js.map +0 -1
  337. package/dist/extensions/forgecli/remove-command.js.map +0 -1
  338. package/dist/extensions/forgecli/report-bug.js.map +0 -1
  339. package/dist/extensions/forgecli/retrospective.js.map +0 -1
  340. package/dist/extensions/forgecli/review-code.js.map +0 -1
  341. package/dist/extensions/forgecli/review-plan.js.map +0 -1
  342. package/dist/extensions/forgecli/run-sprint.js.map +0 -1
  343. package/dist/extensions/forgecli/run-task.js.map +0 -1
  344. package/dist/extensions/forgecli/skill-curation-flag.js.map +0 -1
  345. package/dist/extensions/forgecli/skill-curator-subagent.js.map +0 -1
  346. package/dist/extensions/forgecli/skill-retriever.js.map +0 -1
  347. package/dist/extensions/forgecli/skill-usage-tracker.js.map +0 -1
  348. package/dist/extensions/forgecli/sprint-intake.js.map +0 -1
  349. package/dist/extensions/forgecli/sprint-plan.js.map +0 -1
  350. package/dist/extensions/forgecli/status-command.js.map +0 -1
  351. package/dist/extensions/forgecli/store-error-remediation.js.map +0 -1
  352. package/dist/extensions/forgecli/store-query.js.map +0 -1
  353. package/dist/extensions/forgecli/store-repair.js.map +0 -1
  354. package/dist/extensions/forgecli/store-resolver.js.map +0 -1
  355. package/dist/extensions/forgecli/store-validator.js.map +0 -1
  356. package/dist/extensions/forgecli/test-orchestrate.js.map +0 -1
  357. package/dist/extensions/forgecli/thread-switcher.d.ts +0 -5
  358. package/dist/extensions/forgecli/thread-switcher.js.map +0 -1
  359. package/dist/extensions/forgecli/transition-guard.js.map +0 -1
  360. package/dist/extensions/forgecli/update-check.js.map +0 -1
  361. package/dist/extensions/forgecli/update-tools.js.map +0 -1
  362. package/dist/extensions/forgecli/validate.js.map +0 -1
  363. package/dist/extensions/forgecli/viewport-events.js.map +0 -1
  364. package/dist/extensions/forgecli/viewport-renderer.js.map +0 -1
  365. package/dist/extensions/forgecli/viewport-theme.js.map +0 -1
  366. package/dist/extensions/forgecli/whats-new-widget.js.map +0 -1
  367. package/dist/extensions/forgecli/whats-new.js.map +0 -1
  368. /package/dist/extensions/forgecli/{add-pipeline.d.ts → commands/add-pipeline.d.ts} +0 -0
  369. /package/dist/extensions/forgecli/{add-task.d.ts → commands/add-task.d.ts} +0 -0
  370. /package/dist/extensions/forgecli/{config-command.d.ts → commands/config-command.d.ts} +0 -0
  371. /package/dist/extensions/forgecli/{quiz-agent.d.ts → commands/quiz-agent.d.ts} +0 -0
  372. /package/dist/extensions/forgecli/{read-command.d.ts → commands/read-command.d.ts} +0 -0
  373. /package/dist/extensions/forgecli/{regenerate.d.ts → commands/regenerate.d.ts} +0 -0
  374. /package/dist/extensions/forgecli/{remove-command.d.ts → commands/remove-command.d.ts} +0 -0
  375. /package/dist/extensions/forgecli/{report-bug.d.ts → commands/report-bug.d.ts} +0 -0
  376. /package/dist/extensions/forgecli/{sprint-intake.d.ts → commands/sprint-intake.d.ts} +0 -0
  377. /package/dist/extensions/forgecli/{sprint-intake.js → commands/sprint-intake.js} +0 -0
  378. /package/dist/extensions/forgecli/{sprint-plan.d.ts → commands/sprint-plan.d.ts} +0 -0
  379. /package/dist/extensions/forgecli/{sprint-plan.js → commands/sprint-plan.js} +0 -0
  380. /package/dist/extensions/forgecli/{status-command.d.ts → commands/status-command.d.ts} +0 -0
  381. /package/dist/extensions/forgecli/{store-query.d.ts → commands/store-query.d.ts} +0 -0
  382. /package/dist/extensions/forgecli/{store-repair.d.ts → commands/store-repair.d.ts} +0 -0
  383. /package/dist/extensions/forgecli/{test-orchestrate.d.ts → commands/test-orchestrate.d.ts} +0 -0
  384. /package/dist/extensions/forgecli/{config-layer.d.ts → config/config-layer.d.ts} +0 -0
  385. /package/dist/extensions/forgecli/{config-writer.d.ts → config/config-writer.d.ts} +0 -0
  386. /package/dist/extensions/forgecli/{model-registry.d.ts → config/model-registry.d.ts} +0 -0
  387. /package/dist/extensions/forgecli/{model-resolver.d.ts → config/model-resolver.d.ts} +0 -0
  388. /package/dist/extensions/forgecli/{model-resolver.js → config/model-resolver.js} +0 -0
  389. /package/dist/extensions/forgecli/{model-validator.d.ts → config/model-validator.d.ts} +0 -0
  390. /package/dist/extensions/forgecli/{model-validator.js → config/model-validator.js} +0 -0
  391. /package/dist/extensions/forgecli/{forge-init.d.ts → forge-init/forge-init.d.ts} +0 -0
  392. /package/dist/extensions/forgecli/{init-context.d.ts → forge-init/init-context.d.ts} +0 -0
  393. /package/dist/extensions/forgecli/{init-context.js → forge-init/init-context.js} +0 -0
  394. /package/dist/extensions/forgecli/{init-progress.d.ts → forge-init/init-progress.d.ts} +0 -0
  395. /package/dist/extensions/forgecli/{init-progress.js → forge-init/init-progress.js} +0 -0
  396. /package/dist/extensions/forgecli/{materialize.d.ts → orchestrators/materialize.d.ts} +0 -0
  397. /package/dist/extensions/forgecli/{skill-curation-flag.d.ts → skill-curation/skill-curation-flag.d.ts} +0 -0
  398. /package/dist/extensions/forgecli/{skill-retriever.d.ts → skill-curation/skill-retriever.d.ts} +0 -0
  399. /package/dist/extensions/forgecli/{skill-usage-tracker.d.ts → skill-curation/skill-usage-tracker.d.ts} +0 -0
  400. /package/dist/extensions/forgecli/{store-error-remediation.d.ts → store/store-error-remediation.d.ts} +0 -0
  401. /package/dist/extensions/forgecli/{store-error-remediation.js → store/store-error-remediation.js} +0 -0
  402. /package/dist/extensions/forgecli/{store-resolver.d.ts → store/store-resolver.d.ts} +0 -0
  403. /package/dist/extensions/forgecli/{store-validator.d.ts → store/store-validator.d.ts} +0 -0
  404. /package/dist/extensions/forgecli/{transition-guard.d.ts → store/transition-guard.d.ts} +0 -0
  405. /package/dist/extensions/forgecli/{banner.d.ts → tui/banner.d.ts} +0 -0
  406. /package/dist/extensions/forgecli/{banner.js → tui/banner.js} +0 -0
  407. /package/dist/extensions/forgecli/{forge-header.d.ts → tui/forge-header.d.ts} +0 -0
  408. /package/dist/extensions/forgecli/{forge-header.js → tui/forge-header.js} +0 -0
  409. /package/dist/extensions/forgecli/{input-router.d.ts → tui/input-router.d.ts} +0 -0
  410. /package/dist/extensions/forgecli/{input-router.js → tui/input-router.js} +0 -0
  411. /package/dist/extensions/forgecli/{forge-update-command.d.ts → update/forge-update-command.d.ts} +0 -0
  412. /package/dist/extensions/forgecli/{migration-engine.d.ts → update/migration-engine.d.ts} +0 -0
  413. /package/dist/extensions/forgecli/{update-check.d.ts → update/update-check.d.ts} +0 -0
  414. /package/dist/extensions/forgecli/{update-tools.d.ts → update/update-tools.d.ts} +0 -0
  415. /package/dist/extensions/forgecli/{whats-new-widget.d.ts → update/whats-new-widget.d.ts} +0 -0
  416. /package/dist/extensions/forgecli/{whats-new.d.ts → update/whats-new.d.ts} +0 -0
  417. /package/dist/extensions/forgecli/{viewport-theme.d.ts → viewport/theme.d.ts} +0 -0
@@ -33,35 +33,37 @@
33
33
  // Evaluates declarative gate conditions from the workflow's gate block.
34
34
  // This two-level design ensures both structural validity (model/persona config) and
35
35
  // store-state validity (predecessor verdicts, status guards) are checked.
36
- // Reference: lib/orchestrator-preflight.ts (N-H-H, FORGE-S25-T17).
36
+ // Reference: orchestrator-preflight.ts (N-H-H, FORGE-S25-T17).
37
37
  //
38
38
  // N-H-E tag: see inline comment at the materialization skip (~line 707 / checkMaterialization).
39
39
  import { spawnSync } from "node:child_process";
40
40
  import * as fs from "node:fs";
41
41
  import * as path from "node:path";
42
42
  import { fileURLToPath } from "node:url";
43
- import { assertAudience, CallerContextStore } from "./audience-gate.js";
43
+ import { assertAudience, CallerContextStore } from "../audience-gate.js";
44
44
  // ModelRegistry/AuthStorage no longer instantiated here — use ctx.modelRegistry
45
45
  // so extension-registered providers (registered against the live session) are
46
46
  // visible to validateModelConfig. Creating a fresh registry here would miss
47
47
  // them and produce spurious MODEL_UNAVAILABLE warnings (FORGE-BUG-001).
48
- import { loadLayeredConfig } from "./config-layer.js";
49
- import { loadForgePersona, runForgeSubagent } from "./forge-subagent.js";
50
- import { getSubagentTools } from "./forge-tools.js";
51
- import { readPersonaDir as readPersonaDirBug, readPipelineNames as readPipelineNamesBug, } from "./lib/catalog-helpers.js";
52
- import { discoverForgeConfigCached } from "./lib/forge-config.js";
53
- import { resolveAdvisorModel, runHaltAdvisor } from "./lib/halt-advisor.js";
54
- import { checkMaterialization } from "./lib/manifest-checker.js";
55
- import { runOrchestratorPreflight } from "./lib/orchestrator-preflight.js";
56
- import { resolveModelForPhase } from "./model-resolver.js";
57
- import { loadWorkflow } from "./parsers/workflow-loader.js";
58
- import { buildPhaseEvent, buildSummariesBlock, drainFrictionFile, emitEvent, emitIncompletePhaseEvent, findPredecessorIndex, formatLocalTime, isNonInteractive, judgementFromSummary, runPreflightGateWithData, validateId, } from "./run-task.js";
59
- import { getSessionRegistry } from "./session-registry.js";
60
- import { getOrchestratorTree } from "./orchestrator-tree.js";
61
- import { OrchestratorTranscriptWriter } from "./subagent/orchestrator-transcript.js";
62
- import { resolveToCanonicalId, resolveToolDir } from "./store-resolver.js";
63
- import { attachViewportObserver } from "./viewport-events.js";
64
- import { fmtPhaseSummary } from "./viewport-renderer.js";
48
+ import { loadLayeredConfig } from "../config/config-layer.js";
49
+ import { resolveModelForPhase } from "../config/model-resolver.js";
50
+ import { loadForgePersona, runForgeSubagent } from "../forge-subagent.js";
51
+ import { getSubagentTools } from "../forge-tools.js";
52
+ import { loadGovernorProjectConfig } from "../governor-config.js";
53
+ import { readPersonaDir as readPersonaDirBug, readPipelineNames as readPipelineNamesBug, } from "../lib/catalog-helpers.js";
54
+ import { discoverForgeConfigCached } from "../lib/forge-config.js";
55
+ import { checkMaterialization } from "../lib/manifest-checker.js";
56
+ import { getOrchestratorTree } from "../orchestrator-tree.js";
57
+ import { loadWorkflow } from "../parsers/workflow-loader.js";
58
+ import { getSessionRegistry } from "../session-registry.js";
59
+ import { resolveToCanonicalId, resolveToolDir } from "../store/store-resolver.js";
60
+ import { OrchestratorTranscriptWriter } from "../subagent/orchestrator-transcript.js";
61
+ import { archiveRun, sweepProjectTranscripts } from "../transcript-archive.js";
62
+ import { attachViewportObserver } from "../viewport/events.js";
63
+ import { fmtPhaseSummary } from "../viewport/renderer.js";
64
+ import { resolveAdvisorModel, runHaltAdvisor } from "./halt-advisor.js";
65
+ import { runOrchestratorPreflight } from "./orchestrator-preflight.js";
66
+ import { buildPhaseEvent, buildSummariesBlock, drainFrictionFile, emitEvent, emitIncompletePhaseEvent, findPredecessorIndex, formatLocalTime, isNonInteractive, judgementFromSummary, runPreflightGateWithData, transcriptOutcomeFor, validateId, } from "./run-task.js";
65
67
  // ── Bug phase descriptor table ──────────────────────────────────────────────
66
68
  //
67
69
  // Decoded from .forge/workflows/fix_bug.md and the task prompt's BUG_PHASES.
@@ -89,8 +91,8 @@ export const BUG_PHASES = [
89
91
  // subagent/phase-summary-map.ts so the new phase-guard.ts can import
90
92
  // it without dragging fix-bug.ts into a forge-tools import cycle.
91
93
  // Re-exported here for backwards-compatibility with existing call sites.
92
- export { BUG_SUMMARY_KEY_BY_ROLE } from "./subagent/phase-summary-map.js";
93
- import { BUG_SUMMARY_KEY_BY_ROLE } from "./subagent/phase-summary-map.js";
94
+ export { BUG_SUMMARY_KEY_BY_ROLE } from "../subagent/phase-summary-map.js";
95
+ import { BUG_SUMMARY_KEY_BY_ROLE } from "../subagent/phase-summary-map.js";
94
96
  // Bug-event type tokens — explicit mapping per review finding #3.
95
97
  // Non-review phases always emit the pass token. Review phases select
96
98
  // pass or fail based on ec.judgement.verdict.
@@ -108,6 +110,21 @@ export const BUG_TYPE_TOKENS = {
108
110
  // `approved` and `verified` enum values were dropped in forge v0.44.0
109
111
  // (FORGE-BUG-002 trap). The canonical source is store-cli.cjs.
110
112
  const BUG_TERMINAL_STATES = new Set(["fixed"]);
113
+ // Post-triage status transitions the ORCHESTRATOR owns (meta-fix-bug.md
114
+ // step 2: "On return, orchestrator transitions status: triaged then
115
+ // in-progress" — a required two-step state-machine contract; the FSM
116
+ // forbids the one-step reported → in-progress jump). First live firing of
117
+ // commit-task.cjs exposed this as unimplemented: bugs reached the commit
118
+ // phase still 'reported' and the terminal-status guard fired every run.
119
+ // Returns the ordered list of statuses to write from the given status —
120
+ // idempotent on resume (already in-progress / terminal → no-op).
121
+ export function postTriageTransitions(status) {
122
+ if (status === "reported")
123
+ return ["triaged", "in-progress"];
124
+ if (status === "triaged")
125
+ return ["in-progress"];
126
+ return [];
127
+ }
111
128
  function bugStateFilePath(cwd, bugId, sessionId) {
112
129
  if (!validateId(bugId)) {
113
130
  throw new Error(`Invalid bugId for state file path: ${bugId}`);
@@ -213,31 +230,51 @@ export function readBugRecord(bugId, storeCli, cwd) {
213
230
  return null;
214
231
  }
215
232
  }
216
- // Pre-assigns a real FORGE-BUG-NNN ID by listing existing bugs and incrementing.
217
- // Returns the next ID in sequence, e.g. "FORGE-BUG-003" if bugs 001 and 002 exist.
218
- export function assignNextBugId(storeCli, cwd) {
219
- const result = spawnSync("node", [storeCli, "list", "bug", "--json"], { cwd, encoding: "utf8" });
233
+ // Pure helper: next <PREFIX>-BUG-NNN ID given the existing bug IDs.
234
+ // Only same-prefix bugs participate in the increment exported for tests.
235
+ // The prefix is config-owned (project.prefix) and identifier-validated by
236
+ // loadGovernorProjectConfig, so it is safe to splice into a RegExp.
237
+ export function computeNextBugId(bugIds, prefix) {
238
+ const idPattern = new RegExp(`^${prefix}-BUG-(\\d+)$`);
220
239
  let maxNum = 0;
240
+ for (const id of bugIds) {
241
+ const m = idPattern.exec(id);
242
+ if (m) {
243
+ const n = parseInt(m[1], 10);
244
+ if (n > maxNum)
245
+ maxNum = n;
246
+ }
247
+ }
248
+ return `${prefix}-BUG-${String(maxNum + 1).padStart(3, "0")}`;
249
+ }
250
+ // Pre-assigns a real <PREFIX>-BUG-NNN ID by listing existing bugs and
251
+ // incrementing. Prefix comes from .forge/config.json project.prefix — the
252
+ // hardcoded FORGE prefix minted phantom FORGE-BUG-* records in any project
253
+ // with a different prefix (CART testbench incident, FORGE-BUG-043 class).
254
+ export function assignNextBugId(storeCli, cwd, prefix = "FORGE") {
255
+ const result = spawnSync("node", [storeCli, "list", "bug", "--json"], { cwd, encoding: "utf8" });
256
+ let bugIds = [];
221
257
  if (result.status === 0 && result.stdout) {
222
258
  try {
223
259
  const bugs = JSON.parse(result.stdout);
224
260
  if (Array.isArray(bugs)) {
225
- for (const b of bugs) {
226
- const m = String(b.bugId ?? "").match(/FORGE-BUG-(\d+)/);
227
- if (m) {
228
- const n = parseInt(m[1], 10);
229
- if (n > maxNum)
230
- maxNum = n;
231
- }
232
- }
261
+ bugIds = bugs.map((b) => String(b.bugId ?? ""));
233
262
  }
234
263
  }
235
264
  catch {
236
265
  /* empty store — start from 1 */
237
266
  }
238
267
  }
239
- const next = maxNum + 1;
240
- return `FORGE-BUG-${String(next).padStart(3, "0")}`;
268
+ return computeNextBugId(bugIds, prefix);
269
+ }
270
+ // Extracts the first canonical <PREFIX>-BUG-NNN referenced in a bug-report
271
+ // text (e.g. the "**Bug ID**: CART-BUG-001" header line BUG_REPORT.md files
272
+ // carry). Used by the @file intake path so /forge:fix-bug @BUG_REPORT.md
273
+ // operates on the referenced store record instead of minting a duplicate.
274
+ // Prefix is config-owned and identifier-validated (safe in a RegExp).
275
+ export function extractBugIdFromReportText(text, prefix) {
276
+ const m = text.match(new RegExp(`\\b${prefix}-BUG-\\d+\\b`));
277
+ return m ? m[0] : null;
241
278
  }
242
279
  // Pre-creates a minimal bug record so the subagent has a real ID to work with.
243
280
  export function preCreateBug(bugId, title, storeCli, cwd) {
@@ -374,7 +411,12 @@ const BUG_WRITE_TOOL_NAMES = new Set(["write", "store-cli", "bash", "forge_store
374
411
  * "store-cli"). In Claude Code runtime, subagents may shell out via Bash.
375
412
  * This function covers all three paths.
376
413
  */
377
- export function extractBugIdFromEvents(events) {
414
+ export function extractBugIdFromEvents(events, prefix = "FORGE") {
415
+ // Prefix is config-owned (project.prefix) and identifier-validated by
416
+ // loadGovernorProjectConfig — the previous hardcoded FORGE-BUG- pattern
417
+ // missed every capture in differently-prefixed projects (CART incident).
418
+ const idPattern = new RegExp(`${prefix}-BUG-\\d+`);
419
+ const idPrefix = `${prefix}-BUG-`;
378
420
  let lastBugId = null;
379
421
  for (const event of events) {
380
422
  if (!event.toolName)
@@ -383,13 +425,13 @@ export function extractBugIdFromEvents(events) {
383
425
  if (event.toolName === "store-cli") {
384
426
  const result = event.result;
385
427
  if (typeof result === "string") {
386
- const match = result.match(/FORGE-BUG-\d+/);
428
+ const match = result.match(idPattern);
387
429
  if (match)
388
430
  lastBugId = match[0];
389
431
  }
390
432
  else if (result && typeof result === "object") {
391
433
  const obj = result;
392
- if (typeof obj.bugId === "string" && obj.bugId.startsWith("FORGE-BUG-")) {
434
+ if (typeof obj.bugId === "string" && obj.bugId.startsWith(idPrefix)) {
393
435
  lastBugId = obj.bugId;
394
436
  }
395
437
  }
@@ -398,13 +440,13 @@ export function extractBugIdFromEvents(events) {
398
440
  // The pi extension registers the tool as "forge_store", not "store-cli".
399
441
  if (event.toolName === "forge_store" && event.result != null) {
400
442
  const output = typeof event.result === "string" ? event.result : JSON.stringify(event.result);
401
- const match = output.match(/FORGE-BUG-\d+/);
443
+ const match = output.match(idPattern);
402
444
  if (match)
403
445
  lastBugId = match[0];
404
446
  }
405
447
  // Also check for write operations to .forge/store/bugs/
406
448
  if (event.toolName === "write" && typeof event.result === "string") {
407
- const match = event.result.match(/(FORGE-BUG-\d+)/);
449
+ const match = event.result.match(idPattern);
408
450
  if (match)
409
451
  lastBugId = match[0];
410
452
  }
@@ -415,7 +457,7 @@ export function extractBugIdFromEvents(events) {
415
457
  if (event.toolName === "bash" && event.result != null) {
416
458
  const output = typeof event.result === "string" ? event.result : JSON.stringify(event.result);
417
459
  if (output.includes("store-cli") && output.includes("write") && output.includes("bug")) {
418
- const match = output.match(/FORGE-BUG-\d+/);
460
+ const match = output.match(idPattern);
419
461
  if (match)
420
462
  lastBugId = match[0];
421
463
  }
@@ -426,6 +468,22 @@ export function extractBugIdFromEvents(events) {
426
468
  const STATUS_KEY = "forge:fix-bug";
427
469
  const MESSAGE_KEY = "forge:fix-bug:message";
428
470
  export async function runBugPipeline(opts) {
471
+ // Thin wrapper: capture the orchestrator transcript writer the inner
472
+ // pipeline creates, surface its path on the result (so callers can
473
+ // archive the run), and GUARANTEE a pipeline-end on every outcome —
474
+ // cancel/halt/failure paths that return without recording one left runs
475
+ // archived as "incomplete" instead of their true outcome.
476
+ let orchTranscript;
477
+ const result = await runBugPipelineInner(opts, (writer) => {
478
+ orchTranscript = writer;
479
+ });
480
+ if (orchTranscript) {
481
+ orchTranscript.close(transcriptOutcomeFor(result.status), result.lastError);
482
+ result.orchestratorTranscriptPath = orchTranscript.filePath;
483
+ }
484
+ return result;
485
+ }
486
+ async function runBugPipelineInner(opts, onOrchestratorTranscript) {
429
487
  const { bugId: initialBugId, originalArg, isNewBug, cwd, ctx, forgeRoot, storeCli, preflightGate, registry, resumeFromState, } = opts;
430
488
  const tree = getOrchestratorTree();
431
489
  // Mutable bugId — for new bugs, pre-assign a real FORGE-BUG-NNN ID
@@ -435,6 +493,14 @@ export async function runBugPipeline(opts) {
435
493
  let bugId = initialBugId;
436
494
  let currentPhaseIndex = resumeFromState?.phaseIndex ?? 0;
437
495
  const iterationCounts = resumeFromState?.iterationCounts ?? {};
496
+ // Per-role dispatch counter for OrchestratorTree node identity. Distinct
497
+ // from iterationCounts (which only tracks review-verdict revisions): every
498
+ // dispatch of a role — including a plan-fix re-run after a review
499
+ // loopback — gets its own `<bugId>:<role>:<attempt>` node, so the
500
+ // dashboard renders one leaf per run in dispatch order instead of merging
501
+ // attempts into one node (CART-BUG-003 dashboard regression). Seeded from
502
+ // resume state so resumed runs continue numbering past prior attempts.
503
+ const dispatchCounts = { ...(resumeFromState?.iterationCounts ?? {}) };
438
504
  let lastModel;
439
505
  let lastProvider;
440
506
  // ── Per-persona model routing (Plan 16) ─────────────────────────────────
@@ -457,9 +523,9 @@ export async function runBugPipeline(opts) {
457
523
  };
458
524
  }
459
525
  // Pre-flight validation — same shape as run-task / run-sprint.
460
- // FORGE-S25-T17: delegated to lib/orchestrator-preflight.ts (H-13).
526
+ // FORGE-S25-T17: delegated to orchestrator-preflight.ts (H-13).
461
527
  {
462
- const personasDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "forge-payload", ".base-pack", "personas");
528
+ const personasDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "forge-payload", ".base-pack", "personas");
463
529
  const personaCatalogue = readPersonaDirBug(personasDir);
464
530
  const forgeCfgPath = path.join(cwd, ".forge", "config.json");
465
531
  const pipelineCatalogue = readPipelineNamesBug(forgeCfgPath);
@@ -491,6 +557,7 @@ export async function runBugPipeline(opts) {
491
557
  entityKind: "bug",
492
558
  entityId: bugId,
493
559
  });
560
+ onOrchestratorTranscript(orchTranscript);
494
561
  const __origNotify = ctx.ui.notify.bind(ctx.ui);
495
562
  ctx.ui.notify = ((msg, level) => {
496
563
  __origNotify(msg, level);
@@ -762,9 +829,7 @@ export async function runBugPipeline(opts) {
762
829
  // ── 4. Dispatch via runForgeSubagent (IL10) ───────────────────
763
830
  // NEVER sendKickoff here — that would reproduce issue #30.
764
831
  // Carry forward prior phase summaries (forge-cli#19).
765
- const bugSummariesBlock = currentPhaseIndex > 0
766
- ? buildSummariesBlock(bugRecordBefore?.summaries) || undefined
767
- : undefined;
832
+ const bugSummariesBlock = currentPhaseIndex > 0 ? buildSummariesBlock(bugRecordBefore?.summaries) || undefined : undefined;
768
833
  let bugBody = composeBugBody(subWorkflowMd, bugId, phase.role, bugStatusBeforePhase, bugSummariesBlock);
769
834
  // For new bugs in triage, prepend the original free-form text so the
770
835
  // subagent knows the user-provided bug description to triage.
@@ -811,14 +876,18 @@ export async function runBugPipeline(opts) {
811
876
  }
812
877
  writeDebug({ kind: "phase_start", phaseIndex: currentPhaseIndex });
813
878
  registry.startPhase(bugId, phase.role, currentPhaseIndex);
814
- // Bridge: register phase in OrchestratorTree
815
- const iteration = (iterationCounts[phase.role] ?? 0) + 1;
879
+ // Bridge: register phase in OrchestratorTree. Node identity is
880
+ // per-dispatch (see dispatchCounts above) never reuse an ID for
881
+ // a re-dispatched role.
882
+ const iteration = (dispatchCounts[phase.role] = (dispatchCounts[phase.role] ?? 0) + 1);
816
883
  const phaseNodeId = `${bugId}:${phase.role}:${iteration}`;
817
884
  tree.startNode(phaseNodeId, {
818
885
  parentId: bugId,
819
886
  label: `${phase.role}:${iteration}`,
820
887
  kind: "leaf",
821
- promptPreview: bugBody.slice(0, 200),
888
+ // Full body — display clamping/expansion is the view's decision
889
+ // (the tree applies only a storage cap).
890
+ promptPreview: bugBody,
822
891
  });
823
892
  const refreshStatus = () => {
824
893
  if (process.env.FORGE_VERBOSE !== "1")
@@ -831,6 +900,7 @@ export async function runBugPipeline(opts) {
831
900
  registry,
832
901
  sessionId: bugId,
833
902
  phaseRole: phase.role,
903
+ nodeId: phaseNodeId,
834
904
  beginHeader: `─── phase ${phase.role} begin ───`,
835
905
  writeDebug,
836
906
  notify: (msg, level) => ctx.ui.notify(msg, level),
@@ -881,6 +951,7 @@ export async function runBugPipeline(opts) {
881
951
  task: bugBody,
882
952
  cwd,
883
953
  exportTag: `${bugId}__${phase.role}`,
954
+ tailLog: observer.state.tailLog,
884
955
  // Sprint-scoped if the bug is attached to one, else bug-scoped.
885
956
  // Keeps every phase of this bug-fix pipeline in a single cache
886
957
  // namespace so the system-prompt + persona prefix stays warm
@@ -898,6 +969,7 @@ export async function runBugPipeline(opts) {
898
969
  catch (err) {
899
970
  const e = err;
900
971
  ctx.ui.notify(`× forge:fix-bug — runForgeSubagent threw for phase ${phase.role}: ${e.message ?? "unknown"}`, "error");
972
+ tree.completeNode(phaseNodeId, "failed");
901
973
  writeBugState(cwd, {
902
974
  bugId,
903
975
  phaseIndex: currentPhaseIndex,
@@ -913,6 +985,21 @@ export async function runBugPipeline(opts) {
913
985
  lastError: `runForgeSubagent threw: ${e.message ?? "unknown"}`,
914
986
  };
915
987
  }
988
+ // Close this dispatch's tree node with final usage/model — MUST be
989
+ // called on every exit path below (failure, halt, escalation,
990
+ // loopback, advance). A node left `running` keeps a live spinner
991
+ // in the dashboard forever AND absorbs the next same-role
992
+ // dispatch's telemetry via the observer's legacy role-prefix scan.
993
+ const finishPhaseNode = (status) => {
994
+ tree.setNodeUsage(phaseNodeId, {
995
+ input: result.usage.input,
996
+ output: result.usage.output,
997
+ cacheRead: result.usage.cacheRead,
998
+ });
999
+ if (result.model)
1000
+ tree.setNodeModel(phaseNodeId, result.model, result.provider ?? "");
1001
+ tree.completeNode(phaseNodeId, status);
1002
+ };
916
1003
  // ── Post-subagent abort detection ─────────────────────────────────
917
1004
  if (result.stopReason === "aborted" || opts.signal?.aborted) {
918
1005
  ctx.ui.notify(`⊘ forge:fix-bug — ${bugId} phase ${phase.role} cancelled.`, "info");
@@ -964,6 +1051,7 @@ export async function runBugPipeline(opts) {
964
1051
  ctx.ui.notify(`× forge:fix-bug — phase ${phase.role} failed (exit ${result.exitCode})` +
965
1052
  (result.errorMessage ? `: ${result.errorMessage}` : "") +
966
1053
  (result.stopReason ? ` [${result.stopReason}]` : ""), "error");
1054
+ finishPhaseNode("failed");
967
1055
  // Bug B parity with run-task: account billed tokens of the failed attempt.
968
1056
  emitIncompletePhaseEvent({
969
1057
  emitCtx: {
@@ -1014,7 +1102,7 @@ export async function runBugPipeline(opts) {
1014
1102
  // For new bugs, the triage subagent creates the bug record via store-cli.
1015
1103
  // We capture the bugId by scanning tool_execution_end events.
1016
1104
  if (phase.role === "triage" && isNewBug && bugId.startsWith("PENDING-")) {
1017
- const capturedBugId = extractBugIdFromEvents(toolExecutionEvents);
1105
+ const capturedBugId = extractBugIdFromEvents(toolExecutionEvents, loadGovernorProjectConfig(cwd).prefix);
1018
1106
  if (capturedBugId) {
1019
1107
  ctx.ui.notify(`forge:fix-bug — captured bug ID: ${capturedBugId}`, "info");
1020
1108
  bugId = capturedBugId;
@@ -1098,6 +1186,7 @@ export async function runBugPipeline(opts) {
1098
1186
  turns: turn,
1099
1187
  toolCount,
1100
1188
  errCount,
1189
+ subagentTranscriptPath: result.subagentTranscriptPath,
1101
1190
  });
1102
1191
  registry.appendTail(bugId, phase.role, fmtPhaseSummary({
1103
1192
  role: phase.role,
@@ -1191,6 +1280,7 @@ export async function runBugPipeline(opts) {
1191
1280
  const verdict = readBugVerdict(updatedBugRecord, phase.role, BUG_SUMMARY_KEY_BY_ROLE);
1192
1281
  if (verdict === "missing") {
1193
1282
  ctx.ui.notify(`× forge:fix-bug — verdict missing for phase ${phase.role} after subagent completed. Halting for advisory.`, "error");
1283
+ finishPhaseNode("failed");
1194
1284
  writeBugState(cwd, {
1195
1285
  bugId,
1196
1286
  phaseIndex: currentPhaseIndex,
@@ -1234,6 +1324,7 @@ export async function runBugPipeline(opts) {
1234
1324
  if (iterationCounts[phase.role] >= phase.maxIterations) {
1235
1325
  ctx.ui.notify(`× forge:fix-bug — revision cap reached for phase ${phase.role} ` +
1236
1326
  `(${iterationCounts[phase.role]}/${phase.maxIterations} iterations). Escalating.`, "error");
1327
+ finishPhaseNode("escalated");
1237
1328
  writeBugState(cwd, {
1238
1329
  bugId,
1239
1330
  phaseIndex: currentPhaseIndex,
@@ -1261,6 +1352,11 @@ export async function runBugPipeline(opts) {
1261
1352
  ctx.ui.notify(`⟳ forge:fix-bug — transitioned bug ${bugId}: ${currentBugStatus} → in-progress`, "info");
1262
1353
  }
1263
1354
  }
1355
+ // The review subagent itself finished cleanly — `revision`
1356
+ // is its verdict, not a failure — so its node closes as
1357
+ // completed before the predecessor re-dispatches under a
1358
+ // fresh node ID.
1359
+ finishPhaseNode("completed");
1264
1360
  const predIndex = findPredecessorIndex(BUG_PHASES, currentPhaseIndex);
1265
1361
  ctx.ui.notify(`⟳ forge:fix-bug — ${phase.role} returned revision; looping to ${BUG_PHASES[predIndex]?.role ?? predIndex} ` +
1266
1362
  `(attempt ${iterationCounts[phase.role]}/${phase.maxIterations})`, "info");
@@ -1287,10 +1383,7 @@ export async function runBugPipeline(opts) {
1287
1383
  }
1288
1384
  // ── Advance to next phase ─────────────────────────────────────
1289
1385
  registry.completePhase(bugId, phase.role, "completed");
1290
- tree.completeNode(phaseNodeId, "completed");
1291
- tree.setNodeUsage(phaseNodeId, { input: result.usage.input, output: result.usage.output, cacheRead: result.usage.cacheRead });
1292
- if (result.model)
1293
- tree.setNodeModel(phaseNodeId, result.model, result.provider ?? "");
1386
+ finishPhaseNode("completed");
1294
1387
  writeBugState(cwd, {
1295
1388
  bugId,
1296
1389
  phaseIndex: currentPhaseIndex,
@@ -1313,6 +1406,17 @@ export async function runBugPipeline(opts) {
1313
1406
  // bug status proves the work happened.
1314
1407
  if (phase.role === "triage") {
1315
1408
  const bugAfterTriage = readBugRecord(bugId, storeCli, cwd);
1409
+ // Orchestrator-owned post-triage transitions (meta-fix-bug.md
1410
+ // step 2). Two sequential writes through store-cli (the FSM
1411
+ // authority); failure warns but does not halt — the commit
1412
+ // phase's status guard is the backstop.
1413
+ for (const target of postTriageTransitions(bugAfterTriage?.status)) {
1414
+ const upd = spawnSync("node", [storeCli, "update-status", "bug", bugId, "status", target], { cwd, encoding: "utf8" });
1415
+ if (upd.status !== 0) {
1416
+ ctx.ui.notify(`⚠ forge:fix-bug — post-triage transition to '${target}' failed: ${(upd.stderr ?? "").toString().trim()}`, "warning");
1417
+ break;
1418
+ }
1419
+ }
1316
1420
  const triageSummary = bugAfterTriage?.summaries?.triage;
1317
1421
  const route = triageSummary?.route;
1318
1422
  if (route === "A") {
@@ -1369,6 +1473,11 @@ export function registerFixBug(pi, options = {}) {
1369
1473
  return;
1370
1474
  }
1371
1475
  const forgeRoot = forgeConfig.forgeRoot;
1476
+ // Best-effort transcript-archive sweep: adopt any project-local runs
1477
+ // not yet in the central index (crash recovery + pre-existing
1478
+ // history). Runs BEFORE this pipeline creates its own transcript
1479
+ // writer, so the in-flight run is never swept half-written.
1480
+ sweepProjectTranscripts(cwd);
1372
1481
  // Tool paths
1373
1482
  const storeCli = path.join(forgeRoot, "tools", "store-cli.cjs");
1374
1483
  const preflightGate = path.join(forgeRoot, "tools", "preflight-gate.cjs");
@@ -1378,8 +1487,10 @@ export function registerFixBug(pi, options = {}) {
1378
1487
  // Check if arg looks like it could be a bug ID (prefixed or unprefixed).
1379
1488
  // Covers: FORGE-BUG-042, BUG-042, B042.
1380
1489
  const looksLikeBugId = /^(?:[A-Z0-9]+-)?(?:BUG-?\d+|B\d+)$/i.test(rawArg) || /^BUG-\d+$/i.test(rawArg);
1381
- if (/^FORGE-BUG-\d+$/.test(rawArg)) {
1382
- // Canonical bug ID verify it exists
1490
+ if (/^[A-Z][A-Z0-9]*-BUG-\d+$/.test(rawArg)) {
1491
+ // Canonical prefixed bug ID (any project prefix, e.g. FORGE-BUG-042,
1492
+ // CART-BUG-001) — verify it exists. Previously hardcoded to FORGE-,
1493
+ // which pushed other-prefix canonical IDs through the resolver.
1383
1494
  bugId = rawArg;
1384
1495
  const bugRecord = readBugRecord(bugId, storeCli, cwd);
1385
1496
  if (!bugRecord) {
@@ -1423,10 +1534,42 @@ export function registerFixBug(pi, options = {}) {
1423
1534
  }
1424
1535
  }
1425
1536
  else {
1426
- // Free-form text defer bug creation to triage-phase subagent
1427
- // Use a temporary bugId placeholder; will be captured from subagent events
1428
- bugId = `PENDING-${Date.now()}`;
1429
- isNewBug = true;
1537
+ // @file or free-form text. If an @file report references a canonical
1538
+ // <PREFIX>-BUG-NNN that already exists in the store, fix THAT record
1539
+ // minting a new bug here duplicated CART-BUG-001 as a phantom in the
1540
+ // CART incident (the report header carried the real ID all along).
1541
+ let reportBugId = null;
1542
+ if (rawArg.startsWith("@")) {
1543
+ const rel = rawArg.slice(1).trim();
1544
+ const reportPath = path.isAbsolute(rel) ? rel : path.join(cwd, rel);
1545
+ try {
1546
+ // 256 KB cap — bug reports are small; never slurp arbitrary files.
1547
+ if (fs.existsSync(reportPath) && fs.statSync(reportPath).size <= 262144) {
1548
+ const projectPrefix = loadGovernorProjectConfig(cwd).prefix;
1549
+ reportBugId = extractBugIdFromReportText(fs.readFileSync(reportPath, "utf8"), projectPrefix);
1550
+ }
1551
+ }
1552
+ catch {
1553
+ /* unreadable report — fall through to new-bug intake */
1554
+ }
1555
+ }
1556
+ const reportRecord = reportBugId ? readBugRecord(reportBugId, storeCli, cwd) : null;
1557
+ if (reportBugId && reportRecord) {
1558
+ if (BUG_TERMINAL_STATES.has(reportRecord.status ?? "")) {
1559
+ ctx.ui.notify(`× forge:fix-bug — ${rawArg} references ${reportBugId}, which is already in terminal state ` +
1560
+ `'${reportRecord.status}'. No further processing.`, "error");
1561
+ ctx.ui.setStatus?.(STATUS_KEY, undefined);
1562
+ return;
1563
+ }
1564
+ bugId = reportBugId;
1565
+ ctx.ui.notify(`forge:fix-bug — ${rawArg} references existing bug ${bugId}; fixing it (no new record minted).`, "info");
1566
+ }
1567
+ else {
1568
+ // Free-form text (or report with no resolvable ID) — defer bug
1569
+ // creation to the triage-phase subagent via a PENDING placeholder.
1570
+ bugId = `PENDING-${Date.now()}`;
1571
+ isNewBug = true;
1572
+ }
1430
1573
  }
1431
1574
  // ── Pre-flight confirm ───────────────────────────────────────────
1432
1575
  if (!isNonInteractive()) {
@@ -1526,7 +1669,7 @@ export function registerFixBug(pi, options = {}) {
1526
1669
  // Previously this was done inside runBugPipeline, but the session registry
1527
1670
  // needs the real ID before startSession is called.
1528
1671
  if (isNewBug && bugId.startsWith("PENDING-")) {
1529
- const realBugId = assignNextBugId(storeCli, cwd);
1672
+ const realBugId = assignNextBugId(storeCli, cwd, loadGovernorProjectConfig(cwd).prefix);
1530
1673
  const title = rawArg && !rawArg.startsWith("@") ? rawArg.slice(0, 120) : "New bug (pending triage)";
1531
1674
  if (preCreateBug(realBugId, title, storeCli, cwd)) {
1532
1675
  ctx.ui.notify(`forge:fix-bug — pre-assigned bug ID: ${realBugId}`, "info");
@@ -1572,6 +1715,14 @@ export function registerFixBug(pi, options = {}) {
1572
1715
  registry.completeSession(bugId, "failed");
1573
1716
  tree.completeNode(bugId, "failed");
1574
1717
  }
1718
+ // Mirror this run into the central transcript archive (best-effort —
1719
+ // archiveRun never throws).
1720
+ if (pipelineResult.orchestratorTranscriptPath) {
1721
+ archiveRun({
1722
+ cwd,
1723
+ orchestratorJsonlPath: pipelineResult.orchestratorTranscriptPath,
1724
+ });
1725
+ }
1575
1726
  ctx.ui.setStatus?.(STATUS_KEY, undefined);
1576
1727
  ctx.ui.setStatus?.(MESSAGE_KEY, undefined);
1577
1728
  },