@entelligentsia/forgecli 1.0.21 → 1.0.36

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 (218) hide show
  1. package/CHANGELOG.md +346 -0
  2. package/README.md +2 -0
  3. package/dist/CHANGELOG-forge-plugin.md +281 -0
  4. package/dist/bin/argv.d.ts +2 -2
  5. package/dist/bin/argv.js +25 -0
  6. package/dist/bin/argv.js.map +1 -1
  7. package/dist/bin/forge.js +12 -0
  8. package/dist/bin/forge.js.map +1 -1
  9. package/dist/bin/init.d.ts +23 -0
  10. package/dist/bin/init.js +123 -0
  11. package/dist/bin/init.js.map +1 -0
  12. package/dist/bin/uninstall.d.ts +20 -0
  13. package/dist/bin/uninstall.js +141 -0
  14. package/dist/bin/uninstall.js.map +1 -0
  15. package/dist/extensions/forgecli/claude-bootstrap/bootstrap.d.ts +40 -0
  16. package/dist/extensions/forgecli/claude-bootstrap/bootstrap.js +593 -0
  17. package/dist/extensions/forgecli/claude-bootstrap/bootstrap.js.map +1 -0
  18. package/dist/extensions/forgecli/claude-bootstrap/settings-merge.d.ts +46 -0
  19. package/dist/extensions/forgecli/claude-bootstrap/settings-merge.js +245 -0
  20. package/dist/extensions/forgecli/claude-bootstrap/settings-merge.js.map +1 -0
  21. package/dist/extensions/forgecli/claude-bootstrap/uninstall.d.ts +23 -0
  22. package/dist/extensions/forgecli/claude-bootstrap/uninstall.js +215 -0
  23. package/dist/extensions/forgecli/claude-bootstrap/uninstall.js.map +1 -0
  24. package/dist/extensions/forgecli/dashboard/component.js +10 -7
  25. package/dist/extensions/forgecli/dashboard/component.js.map +1 -1
  26. package/dist/extensions/forgecli/forge-tools.d.ts +1 -0
  27. package/dist/extensions/forgecli/forge-tools.js +73 -0
  28. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  29. package/dist/extensions/forgecli/lib/forge-root.d.ts +5 -0
  30. package/dist/extensions/forgecli/lib/forge-root.js +14 -1
  31. package/dist/extensions/forgecli/lib/forge-root.js.map +1 -1
  32. package/dist/extensions/forgecli/orchestrators/bug/bug-body.d.ts +1 -0
  33. package/dist/extensions/forgecli/orchestrators/bug/bug-body.js +65 -0
  34. package/dist/extensions/forgecli/orchestrators/bug/bug-body.js.map +1 -0
  35. package/dist/extensions/forgecli/orchestrators/bug/bug-id.d.ts +23 -0
  36. package/dist/extensions/forgecli/orchestrators/bug/bug-id.js +140 -0
  37. package/dist/extensions/forgecli/orchestrators/bug/bug-id.js.map +1 -0
  38. package/dist/extensions/forgecli/orchestrators/bug/bug-phase-dispatch.d.ts +54 -0
  39. package/dist/extensions/forgecli/orchestrators/bug/bug-phase-dispatch.js +349 -0
  40. package/dist/extensions/forgecli/orchestrators/bug/bug-phase-dispatch.js.map +1 -0
  41. package/dist/extensions/forgecli/orchestrators/bug/bug-phases.d.ts +8 -0
  42. package/dist/extensions/forgecli/orchestrators/bug/bug-phases.js +60 -0
  43. package/dist/extensions/forgecli/orchestrators/bug/bug-phases.js.map +1 -0
  44. package/dist/extensions/forgecli/orchestrators/bug/bug-state.d.ts +14 -0
  45. package/dist/extensions/forgecli/orchestrators/bug/bug-state.js +100 -0
  46. package/dist/extensions/forgecli/orchestrators/bug/bug-state.js.map +1 -0
  47. package/dist/extensions/forgecli/orchestrators/bug/bug-triage-routing.d.ts +72 -0
  48. package/dist/extensions/forgecli/orchestrators/bug/bug-triage-routing.js +204 -0
  49. package/dist/extensions/forgecli/orchestrators/bug/bug-triage-routing.js.map +1 -0
  50. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict-loop.d.ts +38 -0
  51. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict-loop.js +166 -0
  52. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict-loop.js.map +1 -0
  53. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict.d.ts +3 -0
  54. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict.js +55 -0
  55. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict.js.map +1 -0
  56. package/dist/extensions/forgecli/orchestrators/bug/run-bug-command.d.ts +7 -0
  57. package/dist/extensions/forgecli/orchestrators/bug/run-bug-command.js +293 -0
  58. package/dist/extensions/forgecli/orchestrators/bug/run-bug-command.js.map +1 -0
  59. package/dist/extensions/forgecli/orchestrators/bug/run-bug-pipeline.d.ts +2 -0
  60. package/dist/extensions/forgecli/orchestrators/bug/run-bug-pipeline.js +501 -0
  61. package/dist/extensions/forgecli/orchestrators/bug/run-bug-pipeline.js.map +1 -0
  62. package/dist/extensions/forgecli/orchestrators/bug/run-bug-types.d.ts +41 -0
  63. package/dist/extensions/forgecli/orchestrators/bug/run-bug-types.js +5 -0
  64. package/dist/extensions/forgecli/orchestrators/bug/run-bug-types.js.map +1 -0
  65. package/dist/extensions/forgecli/orchestrators/common/orchestrator-entry.d.ts +43 -0
  66. package/dist/extensions/forgecli/orchestrators/common/orchestrator-entry.js +85 -0
  67. package/dist/extensions/forgecli/orchestrators/common/orchestrator-entry.js.map +1 -0
  68. package/dist/extensions/forgecli/orchestrators/common/orchestrator-misc.d.ts +8 -0
  69. package/dist/extensions/forgecli/orchestrators/common/orchestrator-misc.js +37 -0
  70. package/dist/extensions/forgecli/orchestrators/common/orchestrator-misc.js.map +1 -0
  71. package/dist/extensions/forgecli/orchestrators/common/orchestrator-notify.d.ts +28 -0
  72. package/dist/extensions/forgecli/orchestrators/common/orchestrator-notify.js +45 -0
  73. package/dist/extensions/forgecli/orchestrators/common/orchestrator-notify.js.map +1 -0
  74. package/dist/extensions/forgecli/orchestrators/common/orchestrator-transcript-session.d.ts +26 -0
  75. package/dist/extensions/forgecli/orchestrators/common/orchestrator-transcript-session.js +75 -0
  76. package/dist/extensions/forgecli/orchestrators/common/orchestrator-transcript-session.js.map +1 -0
  77. package/dist/extensions/forgecli/orchestrators/common/summary-recovery.d.ts +24 -0
  78. package/dist/extensions/forgecli/orchestrators/common/summary-recovery.js +37 -0
  79. package/dist/extensions/forgecli/orchestrators/common/summary-recovery.js.map +1 -0
  80. package/dist/extensions/forgecli/orchestrators/fix-bug.d.ts +9 -92
  81. package/dist/extensions/forgecli/orchestrators/fix-bug.js +23 -1695
  82. package/dist/extensions/forgecli/orchestrators/fix-bug.js.map +1 -1
  83. package/dist/extensions/forgecli/orchestrators/run-sprint.d.ts +3 -12
  84. package/dist/extensions/forgecli/orchestrators/run-sprint.js +97 -270
  85. package/dist/extensions/forgecli/orchestrators/run-sprint.js.map +1 -1
  86. package/dist/extensions/forgecli/orchestrators/run-task.d.ts +10 -214
  87. package/dist/extensions/forgecli/orchestrators/run-task.js +31 -1481
  88. package/dist/extensions/forgecli/orchestrators/run-task.js.map +1 -1
  89. package/dist/extensions/forgecli/orchestrators/sprint/sprint-ceremony.d.ts +33 -0
  90. package/dist/extensions/forgecli/orchestrators/sprint/sprint-ceremony.js +135 -0
  91. package/dist/extensions/forgecli/orchestrators/sprint/sprint-ceremony.js.map +1 -0
  92. package/dist/extensions/forgecli/orchestrators/sprint/sprint-state.d.ts +18 -0
  93. package/dist/extensions/forgecli/orchestrators/sprint/sprint-state.js +55 -0
  94. package/dist/extensions/forgecli/orchestrators/sprint/sprint-state.js.map +1 -0
  95. package/dist/extensions/forgecli/orchestrators/task/run-task-command.d.ts +9 -0
  96. package/dist/extensions/forgecli/orchestrators/task/run-task-command.js +174 -0
  97. package/dist/extensions/forgecli/orchestrators/task/run-task-command.js.map +1 -0
  98. package/dist/extensions/forgecli/orchestrators/task/run-task-pipeline.d.ts +2 -0
  99. package/dist/extensions/forgecli/orchestrators/task/run-task-pipeline.js +494 -0
  100. package/dist/extensions/forgecli/orchestrators/task/run-task-pipeline.js.map +1 -0
  101. package/dist/extensions/forgecli/orchestrators/task/run-task-types.d.ts +62 -0
  102. package/dist/extensions/forgecli/orchestrators/task/run-task-types.js +5 -0
  103. package/dist/extensions/forgecli/orchestrators/task/run-task-types.js.map +1 -0
  104. package/dist/extensions/forgecli/orchestrators/task/task-body.d.ts +4 -0
  105. package/dist/extensions/forgecli/orchestrators/task/task-body.js +48 -0
  106. package/dist/extensions/forgecli/orchestrators/task/task-body.js.map +1 -0
  107. package/dist/extensions/forgecli/orchestrators/task/task-events.d.ts +63 -0
  108. package/dist/extensions/forgecli/orchestrators/task/task-events.js +185 -0
  109. package/dist/extensions/forgecli/orchestrators/task/task-events.js.map +1 -0
  110. package/dist/extensions/forgecli/orchestrators/task/task-gates.d.ts +34 -0
  111. package/dist/extensions/forgecli/orchestrators/task/task-gates.js +78 -0
  112. package/dist/extensions/forgecli/orchestrators/task/task-gates.js.map +1 -0
  113. package/dist/extensions/forgecli/orchestrators/task/task-phase-dispatch.d.ts +42 -0
  114. package/dist/extensions/forgecli/orchestrators/task/task-phase-dispatch.js +370 -0
  115. package/dist/extensions/forgecli/orchestrators/task/task-phase-dispatch.js.map +1 -0
  116. package/dist/extensions/forgecli/orchestrators/task/task-phases.d.ts +14 -0
  117. package/dist/extensions/forgecli/orchestrators/task/task-phases.js +26 -0
  118. package/dist/extensions/forgecli/orchestrators/task/task-phases.js.map +1 -0
  119. package/dist/extensions/forgecli/orchestrators/task/task-record.d.ts +9 -0
  120. package/dist/extensions/forgecli/orchestrators/task/task-record.js +58 -0
  121. package/dist/extensions/forgecli/orchestrators/task/task-record.js.map +1 -0
  122. package/dist/extensions/forgecli/orchestrators/task/task-state.d.ts +14 -0
  123. package/dist/extensions/forgecli/orchestrators/task/task-state.js +35 -0
  124. package/dist/extensions/forgecli/orchestrators/task/task-state.js.map +1 -0
  125. package/dist/extensions/forgecli/orchestrators/task/task-verdict-loop.d.ts +36 -0
  126. package/dist/extensions/forgecli/orchestrators/task/task-verdict-loop.js +152 -0
  127. package/dist/extensions/forgecli/orchestrators/task/task-verdict-loop.js.map +1 -0
  128. package/dist/extensions/forgecli/update/forge-update-command.js +10 -7
  129. package/dist/extensions/forgecli/update/forge-update-command.js.map +1 -1
  130. package/dist/forge-payload/.base-pack/commands/approve.md +2 -2
  131. package/dist/forge-payload/.base-pack/commands/check-agent.md +2 -2
  132. package/dist/forge-payload/.base-pack/commands/collate.md +2 -2
  133. package/dist/forge-payload/.base-pack/commands/commit.md +2 -2
  134. package/dist/forge-payload/.base-pack/commands/enhance.md +2 -2
  135. package/dist/forge-payload/.base-pack/commands/fix-bug.md +2 -2
  136. package/dist/forge-payload/.base-pack/commands/implement.md +2 -2
  137. package/dist/forge-payload/.base-pack/commands/init.md +278 -0
  138. package/dist/forge-payload/.base-pack/commands/new-sprint.md +2 -2
  139. package/dist/forge-payload/.base-pack/commands/plan-sprint.md +2 -2
  140. package/dist/forge-payload/.base-pack/commands/plan.md +2 -2
  141. package/dist/forge-payload/.base-pack/commands/retro.md +2 -2
  142. package/dist/forge-payload/.base-pack/commands/review-code.md +2 -2
  143. package/dist/forge-payload/.base-pack/commands/review-plan.md +2 -2
  144. package/dist/forge-payload/.base-pack/commands/run-sprint.md +2 -2
  145. package/dist/forge-payload/.base-pack/commands/run-task.md +2 -2
  146. package/dist/forge-payload/.base-pack/commands/validate.md +2 -2
  147. package/dist/forge-payload/.base-pack/workflows/_fragments/event-emission-schema.md +4 -0
  148. package/dist/forge-payload/.base-pack/workflows/_fragments/event-vocabulary.md +88 -0
  149. package/dist/forge-payload/.base-pack/workflows/collator_agent.md +5 -6
  150. package/dist/forge-payload/.base-pack/workflows/commit_task.md +41 -38
  151. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +3 -3
  152. package/dist/forge-payload/.base-pack/workflows/migrate_structural.md +1 -1
  153. package/dist/forge-payload/.base-pack/workflows-js/wfl-fix-bug.js +42 -6
  154. package/dist/forge-payload/.base-pack/workflows-js/wfl-init.js +449 -0
  155. package/dist/forge-payload/.base-pack/workflows-js/wfl-run-task.js +32 -1
  156. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  157. package/dist/forge-payload/.schemas/enum-catalog.json +2 -2
  158. package/dist/forge-payload/.schemas/event.schema.json +8 -3
  159. package/dist/forge-payload/.schemas/migrations.json +141 -0
  160. package/dist/forge-payload/commands/add-pipeline.md +1 -1
  161. package/dist/forge-payload/commands/add-task.md +3 -3
  162. package/dist/forge-payload/commands/ask.md +1 -1
  163. package/dist/forge-payload/commands/check-agent.md +1 -1
  164. package/dist/forge-payload/commands/config.md +1 -1
  165. package/dist/forge-payload/commands/health.md +1 -1
  166. package/dist/forge-payload/commands/init.md +62 -7
  167. package/dist/forge-payload/commands/rebuild.md +3 -3
  168. package/dist/forge-payload/commands/remove.md +1 -1
  169. package/dist/forge-payload/commands/repair.md +1 -1
  170. package/dist/forge-payload/commands/report-bug.md +1 -1
  171. package/dist/forge-payload/commands/status.md +1 -1
  172. package/dist/forge-payload/commands/update.md +3 -3
  173. package/dist/forge-payload/hooks/lib/common.cjs +228 -0
  174. package/dist/forge-payload/hooks/lib/plugin-detection.cjs +106 -0
  175. package/dist/forge-payload/hooks/lib/update-msg.cjs +23 -0
  176. package/dist/forge-payload/hooks/lib/update-url.cjs +46 -0
  177. package/dist/forge-payload/hooks/lib/write-registry.js +53 -0
  178. package/dist/forge-payload/init/discovery/discover-database.md +32 -0
  179. package/dist/forge-payload/init/discovery/discover-processes.md +31 -0
  180. package/dist/forge-payload/init/discovery/discover-routing.md +31 -0
  181. package/dist/forge-payload/init/discovery/discover-stack.md +33 -0
  182. package/dist/forge-payload/init/discovery/discover-testing.md +34 -0
  183. package/dist/forge-payload/init/generation/generate-commands.md +171 -0
  184. package/dist/forge-payload/init/generation/generate-kb-doc.md +60 -0
  185. package/dist/forge-payload/init/generation/generate-knowledge-base.md +56 -0
  186. package/dist/forge-payload/init/generation/generate-persona.md +73 -0
  187. package/dist/forge-payload/init/generation/generate-personas.md +54 -0
  188. package/dist/forge-payload/init/generation/generate-skill.md +66 -0
  189. package/dist/forge-payload/init/generation/generate-skills.md +36 -0
  190. package/dist/forge-payload/init/generation/generate-template.md +60 -0
  191. package/dist/forge-payload/init/generation/generate-templates.md +39 -0
  192. package/dist/forge-payload/init/generation/generate-tools.md +133 -0
  193. package/dist/forge-payload/init/generation/generate-workflows.md +78 -0
  194. package/dist/forge-payload/init/phases/phase-1-collect.md +10 -2
  195. package/dist/forge-payload/init/phases/phase-3-materialize.md +1 -1
  196. package/dist/forge-payload/init/phases/phase-4-register.md +8 -0
  197. package/dist/forge-payload/init/workflow-gen-plan.json +17 -0
  198. package/dist/forge-payload/integrity.json +16 -16
  199. package/dist/forge-payload/meta/store-schema/event.schema.md +7 -0
  200. package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +4 -0
  201. package/dist/forge-payload/meta/workflows/_fragments/event-vocabulary.md +88 -0
  202. package/dist/forge-payload/meta/workflows/meta-collate.md +5 -6
  203. package/dist/forge-payload/meta/workflows/meta-commit.md +46 -43
  204. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +7 -2
  205. package/dist/forge-payload/meta/workflows/meta-implement.md +3 -3
  206. package/dist/forge-payload/meta/workflows/meta-migrate.md +1 -1
  207. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +4 -1
  208. package/dist/forge-payload/schemas/enum-catalog.json +2 -2
  209. package/dist/forge-payload/schemas/event.schema.json +8 -3
  210. package/dist/forge-payload/schemas/structure-manifest.json +5 -12
  211. package/dist/forge-payload/tools/commit-task.cjs +218 -0
  212. package/dist/forge-payload/tools/forge-preflight.cjs +268 -0
  213. package/dist/forge-payload/tools/lib/paths.cjs +12 -11
  214. package/dist/forge-payload/tools/lib/pricing.cjs +31 -11
  215. package/dist/forge-payload/tools/query-logger.cjs +34 -0
  216. package/dist/forge-payload/tools/store-cli.cjs +6 -1
  217. package/dist/forge-payload/tools/substitute-placeholders.cjs +5 -6
  218. package/package.json +2 -2
@@ -0,0 +1,140 @@
1
+ // bug-id.ts — bug record read helper plus the bug-ID minting / capture
2
+ // utilities (computeNextBugId, assignNextBugId, extractBugIdFromReportText,
3
+ // preCreateBug, extractBugIdFromEvents). Extracted VERBATIM from fix-bug.ts
4
+ // (FORGE-S31 file-size refactor); no logic changes.
5
+ import { spawnSync } from "node:child_process";
6
+ export function readBugRecord(bugId, storeCli, cwd) {
7
+ const result = spawnSync("node", [storeCli, "read", "bug", bugId], { cwd, encoding: "utf8" });
8
+ if (result.status !== 0)
9
+ return null;
10
+ try {
11
+ const raw = typeof result.stdout === "string" ? result.stdout : String(result.stdout);
12
+ return JSON.parse(raw);
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ // Pure helper: next <PREFIX>-BUG-NNN ID given the existing bug IDs.
19
+ // Only same-prefix bugs participate in the increment — exported for tests.
20
+ // The prefix is config-owned (project.prefix) and identifier-validated by
21
+ // loadGovernorProjectConfig, so it is safe to splice into a RegExp.
22
+ export function computeNextBugId(bugIds, prefix) {
23
+ const idPattern = new RegExp(`^${prefix}-BUG-(\\d+)$`);
24
+ let maxNum = 0;
25
+ for (const id of bugIds) {
26
+ const m = idPattern.exec(id);
27
+ if (m) {
28
+ const n = parseInt(m[1], 10);
29
+ if (n > maxNum)
30
+ maxNum = n;
31
+ }
32
+ }
33
+ return `${prefix}-BUG-${String(maxNum + 1).padStart(3, "0")}`;
34
+ }
35
+ // Pre-assigns a real <PREFIX>-BUG-NNN ID by listing existing bugs and
36
+ // incrementing. Prefix comes from .forge/config.json project.prefix — the
37
+ // hardcoded FORGE prefix minted phantom FORGE-BUG-* records in any project
38
+ // with a different prefix (CART testbench incident, FORGE-BUG-043 class).
39
+ export function assignNextBugId(storeCli, cwd, prefix = "FORGE") {
40
+ const result = spawnSync("node", [storeCli, "list", "bug", "--json"], { cwd, encoding: "utf8" });
41
+ let bugIds = [];
42
+ if (result.status === 0 && result.stdout) {
43
+ try {
44
+ const bugs = JSON.parse(result.stdout);
45
+ if (Array.isArray(bugs)) {
46
+ bugIds = bugs.map((b) => String(b.bugId ?? ""));
47
+ }
48
+ }
49
+ catch {
50
+ /* empty store — start from 1 */
51
+ }
52
+ }
53
+ return computeNextBugId(bugIds, prefix);
54
+ }
55
+ // Extracts the first canonical <PREFIX>-BUG-NNN referenced in a bug-report
56
+ // text (e.g. the "**Bug ID**: CART-BUG-001" header line BUG_REPORT.md files
57
+ // carry). Used by the @file intake path so /forge:fix-bug @BUG_REPORT.md
58
+ // operates on the referenced store record instead of minting a duplicate.
59
+ // Prefix is config-owned and identifier-validated (safe in a RegExp).
60
+ export function extractBugIdFromReportText(text, prefix) {
61
+ const m = text.match(new RegExp(`\\b${prefix}-BUG-\\d+\\b`));
62
+ return m ? m[0] : null;
63
+ }
64
+ // Pre-creates a minimal bug record so the subagent has a real ID to work with.
65
+ export function preCreateBug(bugId, title, storeCli, cwd) {
66
+ const data = {
67
+ bugId,
68
+ title,
69
+ severity: "minor",
70
+ status: "reported",
71
+ path: `engineering/bugs/${bugId}`,
72
+ reportedAt: new Date().toISOString(),
73
+ };
74
+ const result = spawnSync("node", [storeCli, "write", "bug", JSON.stringify(data)], { cwd, encoding: "utf8" });
75
+ return result.status === 0;
76
+ }
77
+ // ── BugId capture via tool_execution_end ──────────────────────────────────
78
+ /**
79
+ * Scan tool_execution_end events to extract the bugId written by a triage
80
+ * subagent. Returns the LAST matching tool call's bugId, or null if none found.
81
+ *
82
+ * In pi runtime, the forge_store tool is registered as "forge_store" (not
83
+ * "store-cli"). In Claude Code runtime, subagents may shell out via Bash.
84
+ * This function covers all three paths.
85
+ */
86
+ export function extractBugIdFromEvents(events, prefix = "FORGE") {
87
+ // Prefix is config-owned (project.prefix) and identifier-validated by
88
+ // loadGovernorProjectConfig — the previous hardcoded FORGE-BUG- pattern
89
+ // missed every capture in differently-prefixed projects (CART incident).
90
+ const idPattern = new RegExp(`${prefix}-BUG-\\d+`);
91
+ const idPrefix = `${prefix}-BUG-`;
92
+ let lastBugId = null;
93
+ for (const event of events) {
94
+ if (!event.toolName)
95
+ continue;
96
+ // Check for store-cli write bug calls (Claude Code runtime)
97
+ if (event.toolName === "store-cli") {
98
+ const result = event.result;
99
+ if (typeof result === "string") {
100
+ const match = result.match(idPattern);
101
+ if (match)
102
+ lastBugId = match[0];
103
+ }
104
+ else if (result && typeof result === "object") {
105
+ const obj = result;
106
+ if (typeof obj.bugId === "string" && obj.bugId.startsWith(idPrefix)) {
107
+ lastBugId = obj.bugId;
108
+ }
109
+ }
110
+ }
111
+ // Check for forge_store tool calls (pi runtime)
112
+ // The pi extension registers the tool as "forge_store", not "store-cli".
113
+ if (event.toolName === "forge_store" && event.result != null) {
114
+ const output = typeof event.result === "string" ? event.result : JSON.stringify(event.result);
115
+ const match = output.match(idPattern);
116
+ if (match)
117
+ lastBugId = match[0];
118
+ }
119
+ // Also check for write operations to .forge/store/bugs/
120
+ if (event.toolName === "write" && typeof event.result === "string") {
121
+ const match = event.result.match(idPattern);
122
+ if (match)
123
+ lastBugId = match[0];
124
+ }
125
+ // Bash events: subagents shelling out via Bash may run "store-cli write bug".
126
+ // Only match when output includes store-cli, write, and bug together
127
+ // to avoid false positives from unrelated Bash commands that happen to
128
+ // mention a bug ID in a different context.
129
+ if (event.toolName === "bash" && event.result != null) {
130
+ const output = typeof event.result === "string" ? event.result : JSON.stringify(event.result);
131
+ if (output.includes("store-cli") && output.includes("write") && output.includes("bug")) {
132
+ const match = output.match(idPattern);
133
+ if (match)
134
+ lastBugId = match[0];
135
+ }
136
+ }
137
+ }
138
+ return lastBugId;
139
+ }
140
+ //# sourceMappingURL=bug-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bug-id.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/orchestrators/bug/bug-id.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
+ import type { MergedConfig } from "../../config/config-layer.js";
3
+ import { type SubagentResult } from "../../forge-subagent.js";
4
+ import { attachViewportObserver } from "../../viewport/events.js";
5
+ import { type PhaseDescriptor } from "../run-task.js";
6
+ import type { BugRecord } from "./bug-id.js";
7
+ import type { RunBugPipelineOptions, RunBugPipelineResult } from "./run-bug-types.js";
8
+ export interface BugPhaseDispatchParams {
9
+ opts: RunBugPipelineOptions;
10
+ phase: PhaseDescriptor;
11
+ bugId: string;
12
+ cwd: string;
13
+ ctx: ExtensionCommandContext;
14
+ storeCli: string;
15
+ currentPhaseIndex: number;
16
+ iterationCounts: Record<string, number>;
17
+ dispatchCounts: Record<string, number>;
18
+ modelRoutingConfig: MergedConfig;
19
+ registry: RunBugPipelineOptions["registry"];
20
+ /** Whether this is a new bug — only used to decide the triage-prefix body. */
21
+ isNewBug: boolean | undefined;
22
+ originalArg: string | undefined;
23
+ /** Raw sub-workflow markdown already loaded + marker/audience-checked by the caller. */
24
+ subWorkflowMd: string;
25
+ /** Bug record read before this phase (status used for compose + cache key). */
26
+ bugRecordBefore: BugRecord | null;
27
+ bugStatusBeforePhase: string | undefined;
28
+ /** True when bugId is still a PENDING- placeholder (triage of a new bug). */
29
+ pendingBugId: boolean;
30
+ }
31
+ export type BugPhaseDispatchOutcome = {
32
+ kind: "return";
33
+ result: RunBugPipelineResult;
34
+ } | {
35
+ kind: "ok";
36
+ result: SubagentResult;
37
+ finishPhaseNode: (status: "completed" | "failed" | "escalated") => void;
38
+ observer: ReturnType<typeof attachViewportObserver>;
39
+ phaseStart: number;
40
+ writeDebug: (rec: Record<string, unknown>) => void;
41
+ toolExecutionEvents: Array<{
42
+ toolName?: string;
43
+ result?: unknown;
44
+ }>;
45
+ debugLogPath: string | null;
46
+ debugLogDisabled: boolean;
47
+ };
48
+ /**
49
+ * Run a single bug phase's subagent dispatch and classify the immediate outcome
50
+ * (persona-load failure, subagent throw, cancellation, or non-zero exit) into a
51
+ * discriminated result. On success returns `kind: "ok"` with the live locals the
52
+ * caller's loop needs for bugId capture / verdict / advance handling.
53
+ */
54
+ export declare function dispatchBugPhase(p: BugPhaseDispatchParams): Promise<BugPhaseDispatchOutcome>;
@@ -0,0 +1,349 @@
1
+ // bug-phase-dispatch.ts — per-phase subagent dispatch for the fix-bug pipeline:
2
+ // persona load → bug-body compose → debug-log setup → viewport observer attach
3
+ // → model resolution → runForgeSubagent (IL10) → post-subagent abort /
4
+ // halt-on-failure detection. Extracted VERBATIM from fix-bug.ts's phase loop
5
+ // (FORGE-S31 file-size refactor) with no logic changes — the inline
6
+ // `return {...}` paths now return `{ kind: "return"; result }`, and the success
7
+ // path returns `{ kind: "ok"; ... }` carrying the live locals the loop needs
8
+ // (subagent result, finishPhaseNode closure, observer, phaseStart, writeDebug,
9
+ // the captured tool_execution_end events, and the debug-log handle/flags so the
10
+ // post-triage bugId-capture block can re-initialize the log under the real ID).
11
+ //
12
+ // IL10 — ALL LLM dispatch goes through runForgeSubagent (NO sendKickoff here).
13
+ import * as fs from "node:fs";
14
+ import * as path from "node:path";
15
+ import { CallerContextStore } from "../../audience-gate.js";
16
+ import { resolveModelForPhase } from "../../config/model-resolver.js";
17
+ import { loadForgePersona, runForgeSubagent } from "../../forge-subagent.js";
18
+ import { getSubagentTools } from "../../forge-tools.js";
19
+ import { getOrchestratorTree } from "../../orchestrator-tree.js";
20
+ import { attachViewportObserver } from "../../viewport/events.js";
21
+ import { buildSummariesBlock, emitIncompletePhaseEvent } from "../run-task.js";
22
+ import { composeBugBody } from "./bug-body.js";
23
+ import { writeBugState } from "./bug-state.js";
24
+ const STATUS_KEY = "forge:fix-bug";
25
+ /**
26
+ * Run a single bug phase's subagent dispatch and classify the immediate outcome
27
+ * (persona-load failure, subagent throw, cancellation, or non-zero exit) into a
28
+ * discriminated result. On success returns `kind: "ok"` with the live locals the
29
+ * caller's loop needs for bugId capture / verdict / advance handling.
30
+ */
31
+ export async function dispatchBugPhase(p) {
32
+ const { opts, phase, bugId, cwd, ctx, storeCli, currentPhaseIndex, iterationCounts, dispatchCounts, modelRoutingConfig, registry, isNewBug, originalArg, subWorkflowMd, bugRecordBefore, bugStatusBeforePhase, pendingBugId, } = p;
33
+ const tree = getOrchestratorTree();
34
+ // ── Persona load ──────────────────────────────────────────────
35
+ let persona;
36
+ try {
37
+ persona = loadForgePersona(phase.personaNoun, cwd);
38
+ }
39
+ catch (err) {
40
+ const e = err;
41
+ ctx.ui.notify(`× forge:fix-bug — persona '${phase.personaNoun}' not found for phase ${phase.role}: ${e.message ?? "unknown"}. ` +
42
+ "Run /forge:regenerate to materialize persona files.", "error");
43
+ writeBugState(cwd, {
44
+ bugId,
45
+ phaseIndex: currentPhaseIndex,
46
+ iterationCounts,
47
+ halted: true,
48
+ lastError: `persona load failed: ${e.message ?? "unknown"}`,
49
+ savedAt: new Date().toISOString(),
50
+ });
51
+ return {
52
+ kind: "return",
53
+ result: {
54
+ status: "failed",
55
+ lastPhaseIndex: currentPhaseIndex,
56
+ iterationCounts,
57
+ lastError: `persona load failed: ${e.message ?? "unknown"}`,
58
+ },
59
+ };
60
+ }
61
+ // ── 4. Dispatch via runForgeSubagent (IL10) ───────────────────
62
+ // NEVER sendKickoff here — that would reproduce issue #30.
63
+ // Carry forward prior phase summaries (forge-cli#19).
64
+ const bugSummariesBlock = currentPhaseIndex > 0 ? buildSummariesBlock(bugRecordBefore?.summaries) || undefined : undefined;
65
+ let bugBody = composeBugBody(subWorkflowMd, bugId, phase.role, bugStatusBeforePhase, bugSummariesBlock);
66
+ // For new bugs in triage, prepend the original free-form text so the
67
+ // subagent knows the user-provided bug description to triage.
68
+ // The bug record already exists (pre-created with status "reported"),
69
+ // so the subagent should update it, not create a new one.
70
+ if (phase.role === "triage" && isNewBug && originalArg) {
71
+ bugBody = `Bug description: ${originalArg}\n\n---\n\n${bugBody}`;
72
+ }
73
+ // Phase-scoped progress counters
74
+ const phaseStart = Date.now();
75
+ // Track tool_execution_end events for bugId capture (Findings #1, #2).
76
+ const toolExecutionEvents = [];
77
+ // Stabilization debug log
78
+ // Skip for PENDING bugIds — create after real bugId is captured.
79
+ // Disable entirely with FORGE_DEBUG_LOG=0.
80
+ const debugLogDisabled = process.env.FORGE_DEBUG_LOG === "0";
81
+ let debugLogPath = null;
82
+ let writeDebug = () => { };
83
+ if (!pendingBugId && !debugLogDisabled) {
84
+ debugLogPath = path.join(cwd, ".forge", "cache", `fix-bug-debug-${bugId}.jsonl`);
85
+ writeDebug = (rec) => {
86
+ try {
87
+ fs.mkdirSync(path.dirname(debugLogPath), { recursive: true });
88
+ // Cap at 10 MB: truncate head when size exceeds the cap.
89
+ try {
90
+ const st = fs.statSync(debugLogPath);
91
+ if (st.size > 10 * 1024 * 1024) {
92
+ const all = fs.readFileSync(debugLogPath, "utf8");
93
+ const lines = all.split("\n");
94
+ // Keep last 80% of lines
95
+ const keep = Math.floor(lines.length * 0.8);
96
+ fs.writeFileSync(debugLogPath, lines.slice(-keep).join("\n"), "utf8");
97
+ }
98
+ }
99
+ catch {
100
+ /* file may not exist yet */
101
+ }
102
+ fs.appendFileSync(debugLogPath, `${JSON.stringify({ ts: new Date().toISOString(), phase: phase.role, ...rec })}\n`, "utf8");
103
+ }
104
+ catch {
105
+ // non-fatal; debug log is best-effort
106
+ }
107
+ };
108
+ }
109
+ writeDebug({ kind: "phase_start", phaseIndex: currentPhaseIndex });
110
+ registry.startPhase(bugId, phase.role, currentPhaseIndex);
111
+ // Bridge: register phase in OrchestratorTree. Node identity is
112
+ // per-dispatch (see dispatchCounts above) — never reuse an ID for
113
+ // a re-dispatched role.
114
+ const iteration = (dispatchCounts[phase.role] = (dispatchCounts[phase.role] ?? 0) + 1);
115
+ const phaseNodeId = `${bugId}:${phase.role}:${iteration}`;
116
+ tree.startNode(phaseNodeId, {
117
+ parentId: bugId,
118
+ label: `${phase.role}:${iteration}`,
119
+ kind: "leaf",
120
+ // Full body — display clamping/expansion is the view's decision
121
+ // (the tree applies only a storage cap).
122
+ promptPreview: bugBody,
123
+ });
124
+ const refreshStatus = () => {
125
+ if (process.env.FORGE_VERBOSE !== "1")
126
+ return;
127
+ const elapsed = Math.floor((Date.now() - phaseStart) / 1000);
128
+ const tail = observer.state.lastTool ? ` · ${observer.state.lastTool}` : "";
129
+ ctx.ui.setStatus?.(STATUS_KEY, `fix-bug ${bugId}: ${phase.role} · t${observer.state.turn} · tools ${observer.state.toolCount}${observer.state.errCount ? ` · err ${observer.state.errCount}` : ""} · ${elapsed}s${tail}`);
130
+ };
131
+ const observer = attachViewportObserver({
132
+ registry,
133
+ sessionId: bugId,
134
+ phaseRole: phase.role,
135
+ nodeId: phaseNodeId,
136
+ beginHeader: `─── phase ${phase.role} begin ───`,
137
+ writeDebug,
138
+ notify: (msg, level) => ctx.ui.notify(msg, level),
139
+ setStatusVerbose: process.env.FORGE_VERBOSE === "1" ? (k, v) => ctx.ui.setStatus?.(k, v) : undefined,
140
+ verboseKeys: { messageKey: `${STATUS_KEY}:message` },
141
+ afterEach: refreshStatus,
142
+ });
143
+ // Wrap the observer's onEvent to also capture tool_execution_end events
144
+ // for bugId capture downstream (findings #1, #2), plus the first turn_end
145
+ // per phase (IL10 visibility — stream-observed model id).
146
+ let modelObservedLogged = false;
147
+ const onSubagentEvent = (event) => {
148
+ if (event?.type === "tool_execution_end") {
149
+ toolExecutionEvents.push({ toolName: event.toolName, result: event.result });
150
+ }
151
+ if (!modelObservedLogged && event?.type === "turn_end" && event.message?.model) {
152
+ modelObservedLogged = true;
153
+ writeDebug({
154
+ kind: "model_observed",
155
+ provider: event.message.provider ?? null,
156
+ model: event.message.model,
157
+ });
158
+ }
159
+ observer.onEvent(event);
160
+ };
161
+ // Per-phase model resolution. When config is absent or cascade bottoms
162
+ // out, resolves to inherit (model: undefined) — setModel is skipped and
163
+ // pi's current model is used. IL10 still holds: result.model below is
164
+ // the stream-observed runtime model, not whatever we requested here.
165
+ const modelResolution = resolveModelForPhase("fix-bug", phase.role, phase.personaNoun, modelRoutingConfig);
166
+ writeDebug({
167
+ kind: "requested_model",
168
+ requested: modelResolution.model ?? null,
169
+ source: modelResolution.source,
170
+ persona: phase.personaNoun,
171
+ });
172
+ let result;
173
+ try {
174
+ // FORGE-BUG-040: wrap the runForgeSubagent dispatch in the phase
175
+ // caller context so downstream tool calls (forge_preflight,
176
+ // forge_store update-status / set-bug-summary / set-summary / emit)
177
+ // can verify the caller's phase matches the phase named in the
178
+ // tool's arguments. This is the single setter of phase context
179
+ // for the bug pipeline; the audience-test wrap above is a
180
+ // short-lived test, not the canonical dispatch context.
181
+ result = await CallerContextStore.asSubagent(phase.role, () => runForgeSubagent({
182
+ persona,
183
+ task: bugBody,
184
+ cwd,
185
+ exportTag: `${bugId}__${phase.role}`,
186
+ tailLog: observer.state.tailLog,
187
+ // Sprint-scoped if the bug is attached to one, else bug-scoped.
188
+ // Keeps every phase of this bug-fix pipeline in a single cache
189
+ // namespace so the system-prompt + persona prefix stays warm
190
+ // across the ~10-minute phases.
191
+ cacheSessionId: typeof bugRecordBefore?.sprintId === "string"
192
+ ? `forge:${bugRecordBefore.sprintId}`
193
+ : `forge:bug:${bugId}`,
194
+ onEvent: onSubagentEvent,
195
+ requestedModel: modelResolution.model,
196
+ modelRegistry: ctx.modelRegistry,
197
+ signal: opts.signal,
198
+ customTools: opts.forgeToolDefs ? getSubagentTools(opts.forgeToolDefs, persona.name) : undefined,
199
+ }));
200
+ }
201
+ catch (err) {
202
+ const e = err;
203
+ ctx.ui.notify(`× forge:fix-bug — runForgeSubagent threw for phase ${phase.role}: ${e.message ?? "unknown"}`, "error");
204
+ tree.completeNode(phaseNodeId, "failed");
205
+ writeBugState(cwd, {
206
+ bugId,
207
+ phaseIndex: currentPhaseIndex,
208
+ iterationCounts,
209
+ halted: true,
210
+ lastError: `runForgeSubagent threw: ${e.message ?? "unknown"}`,
211
+ savedAt: new Date().toISOString(),
212
+ });
213
+ return {
214
+ kind: "return",
215
+ result: {
216
+ status: "failed",
217
+ lastPhaseIndex: currentPhaseIndex,
218
+ iterationCounts,
219
+ lastError: `runForgeSubagent threw: ${e.message ?? "unknown"}`,
220
+ },
221
+ };
222
+ }
223
+ // Close this dispatch's tree node with final usage/model — MUST be
224
+ // called on every exit path below (failure, halt, escalation,
225
+ // loopback, advance). A node left `running` keeps a live spinner
226
+ // in the dashboard forever AND absorbs the next same-role
227
+ // dispatch's telemetry via the observer's legacy role-prefix scan.
228
+ const finishPhaseNode = (status) => {
229
+ tree.setNodeUsage(phaseNodeId, {
230
+ input: result.usage.input,
231
+ output: result.usage.output,
232
+ cacheRead: result.usage.cacheRead,
233
+ });
234
+ if (result.model)
235
+ tree.setNodeModel(phaseNodeId, result.model, result.provider ?? "");
236
+ tree.completeNode(phaseNodeId, status);
237
+ };
238
+ // ── Post-subagent abort detection ─────────────────────────────────
239
+ if (result.stopReason === "aborted" || opts.signal?.aborted) {
240
+ ctx.ui.notify(`⊘ forge:fix-bug — ${bugId} phase ${phase.role} cancelled.`, "info");
241
+ registry.completePhase(bugId, phase.role, "cancelled");
242
+ tree.completeNode(phaseNodeId, "cancelled");
243
+ registry.confirmCancelled(bugId);
244
+ // Bug B parity with run-task: account billed tokens of the aborted attempt.
245
+ // sprintId "bugs" = routing key for bug events (matches success path).
246
+ // The optional `type` token is omitted — verdict carries the outcome.
247
+ emitIncompletePhaseEvent({
248
+ emitCtx: {
249
+ entityType: "bug",
250
+ bugId,
251
+ sprintId: "bugs",
252
+ phase,
253
+ iteration: (iterationCounts[phase.role] ?? 0) + 1,
254
+ startMs: phaseStart,
255
+ endMs: Date.now(),
256
+ model: result.model ?? "unknown",
257
+ provider: result.provider ?? "unknown",
258
+ usage: {
259
+ input: result.usage.input,
260
+ output: result.usage.output,
261
+ cacheRead: result.usage.cacheRead,
262
+ cacheWrite: result.usage.cacheWrite,
263
+ },
264
+ judgement: undefined,
265
+ storeCli,
266
+ cwd,
267
+ },
268
+ outcome: "aborted",
269
+ notes: result.errorMessage ?? result.stopReason ?? undefined,
270
+ onDebug: writeDebug,
271
+ });
272
+ // ADR-S21-01: preserve state file so cancelled runs are resumable
273
+ writeBugState(cwd, {
274
+ bugId,
275
+ phaseIndex: currentPhaseIndex,
276
+ iterationCounts,
277
+ halted: false,
278
+ status: "cancelled",
279
+ lastError: undefined,
280
+ savedAt: new Date().toISOString(),
281
+ });
282
+ return {
283
+ kind: "return",
284
+ result: { status: "cancelled", lastPhaseIndex: currentPhaseIndex, iterationCounts },
285
+ };
286
+ }
287
+ // ── Halt-on-failure ───────────────────────────────────────────
288
+ if (result.exitCode !== 0) {
289
+ ctx.ui.notify(`× forge:fix-bug — phase ${phase.role} failed (exit ${result.exitCode})` +
290
+ (result.errorMessage ? `: ${result.errorMessage}` : "") +
291
+ (result.stopReason ? ` [${result.stopReason}]` : ""), "error");
292
+ finishPhaseNode("failed");
293
+ // Bug B parity with run-task: account billed tokens of the failed attempt.
294
+ emitIncompletePhaseEvent({
295
+ emitCtx: {
296
+ entityType: "bug",
297
+ bugId,
298
+ sprintId: "bugs",
299
+ phase,
300
+ iteration: (iterationCounts[phase.role] ?? 0) + 1,
301
+ startMs: phaseStart,
302
+ endMs: Date.now(),
303
+ model: result.model ?? "unknown",
304
+ provider: result.provider ?? "unknown",
305
+ usage: {
306
+ input: result.usage.input,
307
+ output: result.usage.output,
308
+ cacheRead: result.usage.cacheRead,
309
+ cacheWrite: result.usage.cacheWrite,
310
+ },
311
+ judgement: undefined,
312
+ storeCli,
313
+ cwd,
314
+ },
315
+ outcome: "failed",
316
+ notes: result.errorMessage ?? result.stopReason ?? undefined,
317
+ onDebug: writeDebug,
318
+ });
319
+ writeBugState(cwd, {
320
+ bugId,
321
+ phaseIndex: currentPhaseIndex,
322
+ iterationCounts,
323
+ halted: true,
324
+ lastError: result.errorMessage ?? result.stopReason ?? "subagent exit non-zero",
325
+ savedAt: new Date().toISOString(),
326
+ });
327
+ return {
328
+ kind: "return",
329
+ result: {
330
+ status: "failed",
331
+ lastPhaseIndex: currentPhaseIndex,
332
+ iterationCounts,
333
+ lastError: result.errorMessage ?? result.stopReason ?? "subagent exit non-zero",
334
+ },
335
+ };
336
+ }
337
+ return {
338
+ kind: "ok",
339
+ result,
340
+ finishPhaseNode,
341
+ observer,
342
+ phaseStart,
343
+ writeDebug,
344
+ toolExecutionEvents,
345
+ debugLogPath,
346
+ debugLogDisabled,
347
+ };
348
+ }
349
+ //# sourceMappingURL=bug-phase-dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bug-phase-dispatch.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/orchestrators/bug/bug-phase-dispatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { PhaseDescriptor } from "../task/task-phases.js";
2
+ export declare const BUG_PHASES: PhaseDescriptor[];
3
+ export declare const BUG_TYPE_TOKENS: Record<string, {
4
+ pass: string;
5
+ fail: string;
6
+ }>;
7
+ export declare const BUG_TERMINAL_STATES: Set<string>;
8
+ export declare function postTriageTransitions(status: string | undefined): string[];
@@ -0,0 +1,60 @@
1
+ // bug-phases.ts — bug phase descriptor table, bug-event type tokens, terminal
2
+ // states, and the orchestrator-owned post-triage status transitions. Extracted
3
+ // VERBATIM from fix-bug.ts (FORGE-S31 file-size refactor); no logic changes.
4
+ // ── Bug phase descriptor table ──────────────────────────────────────────────
5
+ //
6
+ // Decoded from .forge/workflows/fix_bug.md and the task prompt's BUG_PHASES.
7
+ // triage / plan-fix / implement all read the same fix_bug.md body — the
8
+ // workflow handles all three phases through prose.
9
+ // FORGE-S25-T16: readPersonaDirBug / readPipelineNamesBug extracted to
10
+ // lib/catalog-helpers.ts and imported above with aliases (H-4, N-H-G).
11
+ export const BUG_PHASES = [
12
+ // FORGE-BUG-040: each phase points at its own phase-scoped subagent workflow.
13
+ // Previously triage/plan-fix/implement all pointed at fix_bug.md (the
14
+ // orchestrator-only body), which caused the triage subagent to execute
15
+ // the full lifecycle in a single invocation. plan-fix and implement reuse
16
+ // plan_task.md / implement_plan.md (bug-mode) per meta-fix-bug.md
17
+ // § Pipeline Phases — the bug-mode entity-kind detection is built into
18
+ // those workflows already.
19
+ { role: "triage", workflowFile: "triage", personaNoun: "bug-fixer", isReview: false, maxIterations: 1 },
20
+ { role: "plan-fix", workflowFile: "plan_task", personaNoun: "engineer", isReview: false, maxIterations: 1 },
21
+ { role: "review-plan", workflowFile: "review_plan", personaNoun: "supervisor", isReview: true, maxIterations: 3 },
22
+ { role: "implement", workflowFile: "implement_plan", personaNoun: "engineer", isReview: false, maxIterations: 1 },
23
+ { role: "review-code", workflowFile: "review_code", personaNoun: "supervisor", isReview: true, maxIterations: 3 },
24
+ { role: "approve", workflowFile: "architect_approve", personaNoun: "architect", isReview: true, maxIterations: 3 },
25
+ { role: "commit", workflowFile: "commit_task", personaNoun: "engineer", isReview: false, maxIterations: 1 },
26
+ ];
27
+ // ── Bug-event type tokens ──────────────────────────────────────────────────
28
+ // Explicit mapping per review finding #3. Non-review phases always emit the
29
+ // pass token. Review phases select pass or fail based on ec.judgement.verdict.
30
+ // The event-vocabulary contract test scans this literal block here.
31
+ export const BUG_TYPE_TOKENS = {
32
+ triage: { pass: "bug-triaged", fail: "bug-triaged" },
33
+ "plan-fix": { pass: "fix-planned", fail: "fix-planned" },
34
+ "review-plan": { pass: "fix-review-passed", fail: "fix-review-failed" },
35
+ implement: { pass: "fix-implemented", fail: "fix-implemented" },
36
+ "review-code": { pass: "fix-code-review-passed", fail: "fix-code-review-failed" },
37
+ approve: { pass: "fix-approved", fail: "fix-revision-requested" },
38
+ commit: { pass: "bug-committed", fail: "bug-commit-failed" },
39
+ };
40
+ // ── Bug FSM transitions ────────────────────────────────────────────────────
41
+ // Mirrors store-cli BUG_TRANSITIONS. Terminal: `fixed`.
42
+ // `approved` and `verified` enum values were dropped in forge v0.44.0
43
+ // (FORGE-BUG-002 trap). The canonical source is store-cli.cjs.
44
+ export const BUG_TERMINAL_STATES = new Set(["fixed"]);
45
+ // Post-triage status transitions the ORCHESTRATOR owns (meta-fix-bug.md
46
+ // step 2: "On return, orchestrator transitions status: triaged then
47
+ // in-progress" — a required two-step state-machine contract; the FSM
48
+ // forbids the one-step reported → in-progress jump). First live firing of
49
+ // commit-task.cjs exposed this as unimplemented: bugs reached the commit
50
+ // phase still 'reported' and the terminal-status guard fired every run.
51
+ // Returns the ordered list of statuses to write from the given status —
52
+ // idempotent on resume (already in-progress / terminal → no-op).
53
+ export function postTriageTransitions(status) {
54
+ if (status === "reported")
55
+ return ["triaged", "in-progress"];
56
+ if (status === "triaged")
57
+ return ["in-progress"];
58
+ return [];
59
+ }
60
+ //# sourceMappingURL=bug-phases.js.map