@entelligentsia/forgecli 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/CHANGELOG-forge-plugin.md +24 -0
  3. package/dist/extensions/forgecli/audience-gate.js +1 -1
  4. package/dist/extensions/forgecli/audience-gate.js.map +1 -1
  5. package/dist/extensions/forgecli/fix-bug.d.ts +1 -2
  6. package/dist/extensions/forgecli/fix-bug.js +678 -609
  7. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  8. package/dist/extensions/forgecli/forge-artifact-tool.js +15 -3
  9. package/dist/extensions/forgecli/forge-artifact-tool.js.map +1 -1
  10. package/dist/extensions/forgecli/forge-subagent.d.ts +17 -0
  11. package/dist/extensions/forgecli/forge-subagent.js +31 -12
  12. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  13. package/dist/extensions/forgecli/forge-tools.d.ts +6 -0
  14. package/dist/extensions/forgecli/forge-tools.js +69 -6
  15. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  16. package/dist/extensions/forgecli/run-task.js +461 -391
  17. package/dist/extensions/forgecli/run-task.js.map +1 -1
  18. package/dist/extensions/forgecli/session-registry.d.ts +12 -0
  19. package/dist/extensions/forgecli/session-registry.js +23 -0
  20. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  21. package/dist/extensions/forgecli/subagent/caller-context.d.ts +35 -11
  22. package/dist/extensions/forgecli/subagent/caller-context.js +49 -21
  23. package/dist/extensions/forgecli/subagent/caller-context.js.map +1 -1
  24. package/dist/extensions/forgecli/subagent/orchestrator-transcript.d.ts +66 -0
  25. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js +66 -0
  26. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js.map +1 -0
  27. package/dist/extensions/forgecli/subagent/phase-guard.d.ts +34 -0
  28. package/dist/extensions/forgecli/subagent/phase-guard.js +139 -0
  29. package/dist/extensions/forgecli/subagent/phase-guard.js.map +1 -0
  30. package/dist/extensions/forgecli/subagent/phase-summary-map.d.ts +1 -0
  31. package/dist/extensions/forgecli/subagent/phase-summary-map.js +22 -0
  32. package/dist/extensions/forgecli/subagent/phase-summary-map.js.map +1 -0
  33. package/dist/extensions/forgecli/thread-switcher.js +2 -2
  34. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  35. package/dist/extensions/forgecli/viewport-events.d.ts +4 -0
  36. package/dist/extensions/forgecli/viewport-events.js +18 -1
  37. package/dist/extensions/forgecli/viewport-events.js.map +1 -1
  38. package/dist/extensions/forgecli/viewport-renderer.d.ts +12 -2
  39. package/dist/extensions/forgecli/viewport-renderer.js +8 -6
  40. package/dist/extensions/forgecli/viewport-renderer.js.map +1 -1
  41. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +10 -28
  42. package/dist/forge-payload/.base-pack/workflows/triage.md +190 -0
  43. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  44. package/dist/forge-payload/.schemas/enum-catalog.json +1 -1
  45. package/dist/forge-payload/.schemas/migrations.json +9 -0
  46. package/dist/forge-payload/integrity.json +3 -3
  47. package/dist/forge-payload/meta/fragments/tool-discipline.md +21 -2
  48. package/dist/forge-payload/meta/workflows/meta-bug-triage.md +210 -0
  49. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +10 -28
  50. package/dist/forge-payload/schemas/enum-catalog.json +1 -1
  51. package/dist/forge-payload/schemas/structure-manifest.json +20 -1
  52. package/dist/forge-payload/tools/artifact.cjs +34 -5
  53. package/node_modules/@entelligentsia/forge-compress/dist/compressor.d.ts +6 -0
  54. package/node_modules/@entelligentsia/forge-compress/dist/compressor.js +137 -0
  55. package/node_modules/@entelligentsia/forge-compress/dist/entropy.d.ts +3 -0
  56. package/node_modules/@entelligentsia/forge-compress/dist/entropy.js +99 -0
  57. package/node_modules/@entelligentsia/forge-compress/dist/forge/entity.d.ts +8 -0
  58. package/node_modules/@entelligentsia/forge-compress/dist/forge/entity.js +149 -0
  59. package/node_modules/@entelligentsia/forge-compress/dist/forge/index.d.ts +7 -0
  60. package/node_modules/@entelligentsia/forge-compress/dist/forge/index.js +4 -0
  61. package/node_modules/@entelligentsia/forge-compress/dist/forge/markdown.d.ts +5 -0
  62. package/node_modules/@entelligentsia/forge-compress/dist/forge/markdown.js +92 -0
  63. package/node_modules/@entelligentsia/forge-compress/dist/forge/query.d.ts +7 -0
  64. package/node_modules/@entelligentsia/forge-compress/dist/forge/query.js +60 -0
  65. package/node_modules/@entelligentsia/forge-compress/dist/forge/validate.d.ts +1 -0
  66. package/node_modules/@entelligentsia/forge-compress/dist/forge/validate.js +82 -0
  67. package/node_modules/@entelligentsia/forge-compress/dist/index.d.ts +6 -0
  68. package/node_modules/@entelligentsia/forge-compress/dist/index.js +5 -0
  69. package/node_modules/@entelligentsia/forge-compress/dist/progressive.d.ts +1 -0
  70. package/node_modules/@entelligentsia/forge-compress/dist/progressive.js +108 -0
  71. package/node_modules/@entelligentsia/forge-compress/dist/strip.d.ts +4 -0
  72. package/node_modules/@entelligentsia/forge-compress/dist/strip.js +55 -0
  73. package/node_modules/@entelligentsia/forge-compress/dist/tokens.d.ts +2 -0
  74. package/node_modules/@entelligentsia/forge-compress/dist/tokens.js +17 -0
  75. package/node_modules/@entelligentsia/forge-compress/package.json +45 -0
  76. package/node_modules/@entelligentsia/forge-compress/src/__tests__/compress.test.ts +409 -0
  77. package/node_modules/@entelligentsia/forge-compress/src/compressor.ts +147 -0
  78. package/node_modules/@entelligentsia/forge-compress/src/entropy.ts +105 -0
  79. package/node_modules/@entelligentsia/forge-compress/src/forge/entity.ts +184 -0
  80. package/node_modules/@entelligentsia/forge-compress/src/forge/index.ts +10 -0
  81. package/node_modules/@entelligentsia/forge-compress/src/forge/markdown.ts +122 -0
  82. package/node_modules/@entelligentsia/forge-compress/src/forge/query.ts +105 -0
  83. package/node_modules/@entelligentsia/forge-compress/src/forge/validate.ts +86 -0
  84. package/node_modules/@entelligentsia/forge-compress/src/index.ts +22 -0
  85. package/node_modules/@entelligentsia/forge-compress/src/progressive.ts +123 -0
  86. package/node_modules/@entelligentsia/forge-compress/src/strip.ts +58 -0
  87. package/node_modules/@entelligentsia/forge-compress/src/tokens.ts +19 -0
  88. package/package.json +5 -10
@@ -23,7 +23,7 @@ Phases`):
23
23
 
24
24
  | Phase | Role | Persona | Workflow | Path A | Path B |
25
25
  |---|---|---|---|---|---|
26
- | triage | `triage` | bug-fixer | (inline algorithm) | yes | yes |
26
+ | triage | `triage` | bug-fixer | `triage.md` | yes | yes |
27
27
  | plan-fix | `plan` | engineer | `plan_task.md` (bug-mode) | no | yes |
28
28
  | review-plan | `review-plan` | supervisor | `review_plan.md` | no | yes |
29
29
  | implement | `implement` | engineer | `implement_plan.md` (bug-mode) | yes | yes |
@@ -93,24 +93,11 @@ The `route` field is required. Allowed values: `"A"` or `"B"`.
93
93
  > Triage subagents MUST NOT touch `bug.path` — that field is set at bug
94
94
  > creation and never modified by triage.
95
95
 
96
- ### Path A short-circuit (eligibility)
96
+ ### Path A / Path B eligibility
97
97
 
98
- Path A is **eligible only when ALL** of the following hold. Triage subagent
99
- must enumerate each in its findings:
100
-
101
- - `bug.severity ∈ {minor}`
102
- - Fix is contained in a single file
103
- - Estimated diff ≤ ~20 lines (judgement call; one screen)
104
- - No schema, API, migration, security, or build-system change
105
- - A regression test is obvious from the reproduction script (single short
106
- test case, no new fixtures, no test-harness change)
107
-
108
- If any criterion fails, the triage subagent MUST select Path B.
109
-
110
- ### Path B — full loop (default)
111
-
112
- Path B runs the same plan/review/implement/review/approve/commit shape as
113
- `meta-orchestrate.md`. It is the default. Any uncertainty defaults Path B.
98
+ See `triage.md § Path A / Path B Eligibility` for the criteria the triage
99
+ subagent applies. The criteria are single-sourced in the triage workflow;
100
+ this orchestrator only reads the resulting `summaries.triage.route` value.
114
101
 
115
102
  ### Pipeline selection by path
116
103
 
@@ -156,16 +143,11 @@ Differences are confined to the **triage** step and the **path branch**.
156
143
  b. If .forge/store/bugs/{BUG_ID}.json does NOT exist, write a fresh record
157
144
  via store-cli with status="reported".
158
145
  c. Read the now-guaranteed record.
159
- - Spawn the triage subagent (persona: bug-fixer). It MUST:
160
- Reproduce the bug (failing test or reproduction script).
161
- Confirm the root cause via codebase research.
162
- Decide Path A vs Path B by the criteria above.
163
- Write triage artifact:
164
- forge_artifact({ command:"write", entity:"bug", entityId:"{bugId}", artifact:"triage", content:"<markdown>" })
165
- • Write triage-summary artifact (JSON shape documented in § Triage Judgement):
166
- forge_artifact({ command:"write", entity:"bug", entityId:"{bugId}", artifact:"triage-summary", content:"<JSON>" })
167
- • Call set-bug-summary {bugId} triage via forge_store:
168
- forge_store({ command:"set-bug-summary", bugId:"{bugId}", phase:"triage", file:"TRIAGE-SUMMARY.json" })
146
+ - Spawn the triage subagent (workflow: `triage.md`, persona: bug-fixer).
147
+ It MUST write `TRIAGE.md` + `TRIAGE-SUMMARY.json` with a `route` field
148
+ (`"A"` or `"B"`) and call `set-bug-summary {bugId} triage` per
149
+ `triage.md`. The triage workflow is `audience: subagent`, `phase: triage`;
150
+ the orchestrator MUST NOT pass any other workflow body to this subagent.
169
151
  - On return, orchestrator transitions status:
170
152
  store-cli update-status bug {bugId} status triaged
171
153
  store-cli update-status bug {bugId} status in-progress
@@ -0,0 +1,190 @@
1
+ ---
2
+ requirements:
3
+ reasoning: High
4
+ context: Medium
5
+ speed: Medium
6
+ audience: subagent
7
+ phase: triage
8
+ context:
9
+ architecture: false
10
+ prior_summaries: delta
11
+ persona: summary
12
+ master_index: false
13
+ diff_mode: false
14
+ deps:
15
+ personas: [bug-fixer]
16
+ skills: [bug-fixer, generic]
17
+ templates: []
18
+ sub_workflows: []
19
+ kb_docs: [architecture/stack.md]
20
+ config_fields: [commands.test, paths.engineering]
21
+ ---
22
+
23
+
24
+ # Bug Triage
25
+ ## Iron Laws
26
+
27
+ - Reproduce the bug before deciding anything. A bug without a confirmed
28
+ reproduction has no business going to plan-fix or implement.
29
+ - Read `.forge/personas/bug-fixer.md` first; print the persona identity
30
+ line (emoji, name, tagline) to stdout before any other tool use.
31
+ - All store I/O via `forge_store` (or `node "$FORGE_ROOT/tools/store-cli.cjs"`).
32
+ Never edit `.forge/store/*.json` directly.
33
+ - **Triage NEVER writes `bug.status`.** The orchestrator (`meta-fix-bug.md`)
34
+ owns the `reported → triaged` and `triaged → in-progress` transitions.
35
+ Writing `bug.status` from this workflow violates `meta-fix-bug.md
36
+ § Iron Laws #2` (parallel to `meta-review-plan.md`'s "Supervisor NEVER
37
+ writes entity status" rule).
38
+ - Triage is a **single phase**. Do NOT call `forge_preflight` with any
39
+ other `--phase` value. Do NOT call `forge_store update-status`,
40
+ `set-bug-summary` for any non-triage phase, or `forge_store emit`.
41
+ These are orchestrator-owned or other-phase-owned actions. The
42
+ phase-ownership guard in forge-cli will reject violations at the tool
43
+ layer, but the Iron Law names the rule.
44
+
45
+ ## Store-Write Verification
46
+
47
+ <!-- See _fragments/store-write-verification.md for the canonical block content -->
48
+
49
+ ## Algorithm
50
+
51
+ ```
52
+
53
+ 0. Pre-flight Gate Check:
54
+ - Resolve FORGE_ROOT (`node -e "console.log(require('./.forge/config.json').paths.forgeRoot)"`).
55
+ - Run: `node "$FORGE_ROOT/tools/preflight-gate.cjs" --phase triage --bug {bugId}`
56
+ - Exit 1 (gate failed) → print stderr and HALT. Do not proceed.
57
+ - Exit 2 (misconfiguration) → print stderr and HALT.
58
+ - Exit 0 → continue.
59
+
60
+ 1. Load Context:
61
+ - Read `.forge/personas/bug-fixer.md` first; print the persona identity
62
+ line to stdout before any other tool use.
63
+ - Read the bug record:
64
+ `forge_store({ command:"read", entity:"bug", id:"{bugId}" })`
65
+ - Read business domain docs relevant to the reported symptom.
66
+ - store-cli verbs: `read` | `list` | `write` | `emit` |
67
+ `update-status` | `set-summary` | `set-bug-summary` | `describe` |
68
+ `nlp` | `query` | `delete` — there is no `get`/`set`/`find`. See
69
+ `_fragments/store-cli-verbs.md` for full notes.
70
+
71
+ 2. Reproduce:
72
+ - Construct a minimal reproduction: a failing test, a short script,
73
+ or a documented manual sequence that triggers the reported symptom.
74
+ - If reproduction cannot be achieved with the information in the bug
75
+ record, write what was tried in TRIAGE.md, set the route to "B"
76
+ (any uncertainty defaults to Path B), and continue to root-cause
77
+ research with the reporter's narrative as the working hypothesis.
78
+
79
+ 3. Root-Cause Research:
80
+ - Read the code paths implicated by the reproduction.
81
+ - Confirm (or revise) the reporter's stated root cause via direct
82
+ inspection of source files and tests.
83
+ - Note collateral damage: which other call sites, schemas, or
84
+ workflows share the defective shape.
85
+
86
+ 4. Path A / Path B Eligibility:
87
+ - Apply the criteria in § "Path A / Path B Eligibility" below.
88
+ - Record the route decision and the explicit enumeration of each
89
+ criterion in the findings section of the triage summary.
90
+
91
+ 5. Write Triage Artifacts:
92
+ - Write the triage artifact (markdown narrative):
93
+ `forge_artifact({ command:"write", entity:"bug", entityId:"{bugId}",
94
+ artifact:"triage", content:"<markdown>" })`
95
+ - Write the triage-summary sidecar (JSON shape below):
96
+ `forge_artifact({ command:"write", entity:"bug", entityId:"{bugId}",
97
+ artifact:"triage-summary", content:"<JSON>" })`
98
+
99
+ 6. Finalize:
100
+ - **No status write.** The orchestrator (`meta-fix-bug.md`) writes the
101
+ `reported → triaged` and `triaged → in-progress` transitions on
102
+ return. Writing `bug.status` from this workflow is forbidden by
103
+ Iron Laws above and is rejected by the phase-ownership guard.
104
+ - **Do NOT emit a phase event yourself.** The orchestrator owns event
105
+ emission — it composes the canonical event from runtime telemetry
106
+ (model, provider, tokens, wall times) plus the SUMMARY you write
107
+ in the next step.
108
+
109
+ 7. Emit Summary Sidecar:
110
+ - The JSON written in step 5 MUST have this shape (the `route` field
111
+ is required; allowed values: `"A"` or `"B"`):
112
+
113
+ ```json
114
+ {
115
+ "objective": "Triage FORGE-BUG-NNN — reproduce, locate, decide route.",
116
+ "key_changes": ["<up to 12 bullets, 200 chars each — findings or actions>"],
117
+ "findings": [
118
+ "Root cause: <one line>",
119
+ "Reproduction: <one line>",
120
+ "Route decision: A | B",
121
+ "Rationale: <one line>"
122
+ ],
123
+ "verdict": "n/a",
124
+ "written_at": "<current ISO 8601 timestamp>",
125
+ "artifact_ref":"TRIAGE.md",
126
+ "route": "A"
127
+ }
128
+ ```
129
+
130
+ - Call:
131
+ ```
132
+ forge_store({ command:"set-bug-summary", entity:"bug",
133
+ id:"{bugId}", phase:"triage",
134
+ file:"engineering/bugs/{bugDir}/TRIAGE-SUMMARY.json" })
135
+ ```
136
+ - If the set-bug-summary call exits non-zero, fix the sidecar JSON
137
+ and retry (up to 3 attempts per the Store-Write Verification rule).
138
+ Do not proceed without a valid summary.
139
+
140
+ > **Field-naming caution — runtime-tested.** The route field is named
141
+ > `route`, never `path`. The bug schema's top-level `path` field is the
142
+ > bug's **artifact directory** (e.g. `engineering/bugs/EMG-BUG-001-...`).
143
+ > Conflating the two caused EMBERGLOW-BUG-001 (v0.44.0 first run) to land
144
+ > its `TRIAGE.md` under `.forge/store/bugs/` instead of `engineering/bugs/`.
145
+ > Triage MUST NOT touch `bug.path` — that field is set at bug creation
146
+ > and never modified by triage.
147
+ ```
148
+
149
+ ## Path A / Path B Eligibility
150
+
151
+ Path A is **eligible only when ALL** of the following hold. The triage
152
+ summary `findings` array MUST enumerate each criterion explicitly with a
153
+ pass/fail mark, so reviewers can audit the decision:
154
+
155
+ - `bug.severity ∈ {minor}`
156
+ - Fix is contained in a single file
157
+ - Estimated diff ≤ ~20 lines (judgement call; one screen)
158
+ - No schema, API, migration, security, or build-system change
159
+ - A regression test is obvious from the reproduction script (single short
160
+ test case, no new fixtures, no test-harness change)
161
+
162
+ If any criterion fails, the triage subagent MUST select Path B.
163
+
164
+ **Path B is the default.** Any uncertainty resolves to Path B. It runs the
165
+ same plan/review/implement/review/approve/commit shape as
166
+ `meta-orchestrate.md`. Picking Path A under uncertainty is the documented
167
+ failure mode (over-eager short-circuit).
168
+
169
+ ## Triage Artifact Contents (TRIAGE.md)
170
+
171
+ The narrative artifact MUST contain:
172
+
173
+ 1. **Reported symptom** — one paragraph summarising the bug report.
174
+ 2. **Reproduction** — exact steps, commands, or test case that triggers
175
+ the symptom; copy of the failing output.
176
+ 3. **Root cause** — one or two paragraphs naming the defective code path,
177
+ schema, or workflow. Cite file paths and line numbers.
178
+ 4. **Path A / Path B enumeration** — for each criterion above, mark
179
+ pass/fail with one-line evidence.
180
+ 5. **Route decision and rationale** — the chosen route and the
181
+ single-sentence justification.
182
+ 6. **Collateral findings** — any related shapes, call sites, or
183
+ workflows that share the defective pattern (filed as follow-ups in
184
+ the commit phase, not fixed here).
185
+
186
+ <!-- See _fragments/generation-instructions.md for Generation Instructions template -->
187
+ ## Friction Emit
188
+
189
+ Emit `type:friction` `{workflow:triage, persona:bug-fixer, issue}` per
190
+ `_fragments/friction-emit.md`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Self-enhancing AI software development lifecycle — generates project-specific SDLC instances from meta-definitions",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "1.0.2",
3
- "generated": "2026-05-27",
3
+ "generated": "2026-05-28",
4
4
  "note": "Authoritative enum catalog. Source: build-enum-catalog.cjs. Regenerate via node forge/tools/build-manifest.cjs.",
5
5
  "enums": {
6
6
  "task.status": [
@@ -1,4 +1,13 @@
1
1
  {
2
+ "1.0.2": {
3
+ "version": "1.0.3",
4
+ "date": "2026-05-28",
5
+ "notes": "v1.0.3 — FORGE-BUG-040 (GH-110) fix. /forge:fix-bug now runs each phase as a phase-scoped subagent: triage uses the new triage.md workflow, plan-fix uses plan_task.md (bug-mode), implement uses implement_plan.md (bug-mode). Previously all three pointed at fix_bug.md (orchestrator-only body), causing the triage subagent to execute the entire lifecycle in one phase. Bug schema, transitions, and store layout are unchanged.",
6
+ "target": "workflows:triage,workflows:fix_bug",
7
+ "regenerate": ["workflows:triage", "workflows:fix_bug"],
8
+ "breaking": false,
9
+ "manual": []
10
+ },
2
11
  "1.0.1": {
3
12
  "version": "1.0.2",
4
13
  "date": "2026-05-27",
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.0.2",
3
- "generated": "2026-05-27",
2
+ "version": "1.0.3",
3
+ "generated": "2026-05-28",
4
4
  "note": "Tamper-evident only. Authoritative source: /forge:update from remote.",
5
5
  "files": {
6
6
  "commands/add-pipeline.md": "529a2fc01be49815efa2cf1147528827ff1bfc12ce2ac8663b5a3a9781f8682e",
@@ -29,7 +29,7 @@
29
29
  "schemas/transitions/bug.json": "27b17da42d1cebffbd4f61ab3dcd432a0017aa71997d548ed80d22c2fc3fad6a",
30
30
  "schemas/transitions/sprint.json": "2e0a629396e687b0ca88e1814ac3e35d84533a5d55b25237ab67feddce3c9deb",
31
31
  "schemas/transitions/task.json": "4c71849747baa0d585756e57c56325ff6219c078178374e60815dff91e25e3e7",
32
- "schemas/enum-catalog.json": "af954fc219984ba9944de123867590c90c09c532b8d3d40859648a75e9010e5c",
32
+ "schemas/enum-catalog.json": "93dc3d1656d9d638c8eaecc14ce66554b63149a4779869e6536cf0e620e5b37b",
33
33
  "tools/verify-integrity.cjs": "3ec3c970dd3d7c3001f8f373bcc40556803eadd2fc2afafb14f1c232cba4cc3f"
34
34
  }
35
35
  }
@@ -1,9 +1,28 @@
1
1
  ## Forge Tool Discipline
2
2
 
3
3
  All forge_* tools wrap local .cjs scripts via direct exec — deterministic, no LLM,
4
- no agent loop. Prefer them over shelling out.
4
+ no agent loop. Use them for all Forge-managed data — never bypass with god tools.
5
5
 
6
- - Store CRUD: call `forge_store` (named tool). Canonical write is 2-positional:
6
+ ### Data boundaries off-limits to `read`, `cat`, `bash`, `grep`
7
+
8
+ These paths contain Forge-managed data. Never access them with generic tools.
9
+
10
+ | Path | Owned by | Use instead |
11
+ |------|----------|-------------|
12
+ | `.forge/store/**` | Store | `forge_store`, `forge_store_query` |
13
+ | `{paths.engineering}/**/` task/bug/sprint dirs | Artifacts | `forge_artifact read` (covers all 15 artifact types) |
14
+ | `{paths.engineering}/**/INDEX.md` | KB | `forge_store_query` or `forge_collate` |
15
+ | `{paths.engineering}/MASTER_INDEX.md` | KB | `forge_store_query` or `forge_collate` |
16
+
17
+ `{paths.engineering}` is the project's KB folder name from `.forge/config.json`
18
+ (default: `engineering`). Never hardcode it.
19
+
20
+ Source files (`.py`, `.ts`, `.js`, etc.), persona `.md`, workflow `.md`, and
21
+ project config outside `.forge/store/` are fine to `read`/`grep` directly.
22
+
23
+ ### Tool routing
24
+
25
+ - **Store CRUD:** call `forge_store` (named tool). Canonical write is 2-positional:
7
26
  `{command:"write", args:["<entity>","<json>"]}`. The id lives INSIDE the json
8
27
  (e.g. `{"sprintId":"X-S01","title":"...","status":"planning","taskIds":[],"createdAt":"..."}`).
9
28
  DO NOT pass id as a separate arg — `["sprint","X-S01","<json>"]` (3-arg) FAILS.
@@ -0,0 +1,210 @@
1
+ ---
2
+ requirements:
3
+ reasoning: High
4
+ context: Medium
5
+ speed: Medium
6
+ audience: subagent
7
+ phase: triage
8
+ context:
9
+ architecture: false
10
+ prior_summaries: delta
11
+ persona: summary
12
+ master_index: false
13
+ diff_mode: false
14
+ deps:
15
+ personas: [bug-fixer]
16
+ skills: [bug-fixer, generic]
17
+ templates: []
18
+ sub_workflows: []
19
+ kb_docs: [architecture/stack.md]
20
+ config_fields: [commands.test, paths.engineering]
21
+ ---
22
+
23
+ # 🍂 Meta-Workflow: Bug Triage
24
+
25
+ ## Purpose
26
+
27
+ The Bug Fixer reproduces a reported bug, confirms root cause, decides the
28
+ fix route (Path A short-circuit vs Path B full loop), and writes the
29
+ triage artifact + summary. This is the **first phase** of `/forge:fix-bug`
30
+ and the only phase that records the route decision read by the orchestrator
31
+ (`meta-fix-bug.md`) to select `phases_A` vs `phases_B`.
32
+
33
+ <!-- See _fragments/iron-laws.md for Iron Laws section structure guidance -->
34
+ ## Iron Laws
35
+
36
+ - Reproduce the bug before deciding anything. A bug without a confirmed
37
+ reproduction has no business going to plan-fix or implement.
38
+ - Read `.forge/personas/bug-fixer.md` first; print the persona identity
39
+ line (emoji, name, tagline) to stdout before any other tool use.
40
+ - All store I/O via `forge_store` (or `node "$FORGE_ROOT/tools/store-cli.cjs"`).
41
+ Never edit `.forge/store/*.json` directly.
42
+ - **Triage NEVER writes `bug.status`.** The orchestrator (`meta-fix-bug.md`)
43
+ owns the `reported → triaged` and `triaged → in-progress` transitions.
44
+ Writing `bug.status` from this workflow violates `meta-fix-bug.md
45
+ § Iron Laws #2` (parallel to `meta-review-plan.md`'s "Supervisor NEVER
46
+ writes entity status" rule).
47
+ - Triage is a **single phase**. Do NOT call `forge_preflight` with any
48
+ other `--phase` value. Do NOT call `forge_store update-status`,
49
+ `set-bug-summary` for any non-triage phase, or `forge_store emit`.
50
+ These are orchestrator-owned or other-phase-owned actions. The
51
+ phase-ownership guard in forge-cli will reject violations at the tool
52
+ layer, but the Iron Law names the rule.
53
+
54
+ ## Store-Write Verification
55
+
56
+ <!-- See _fragments/store-write-verification.md for the canonical block content -->
57
+
58
+ ## Algorithm
59
+
60
+ ```
61
+
62
+ 0. Pre-flight Gate Check:
63
+ - Resolve FORGE_ROOT (`node -e "console.log(require('./.forge/config.json').paths.forgeRoot)"`).
64
+ - Run: `node "$FORGE_ROOT/tools/preflight-gate.cjs" --phase triage --bug {bugId}`
65
+ - Exit 1 (gate failed) → print stderr and HALT. Do not proceed.
66
+ - Exit 2 (misconfiguration) → print stderr and HALT.
67
+ - Exit 0 → continue.
68
+
69
+ 1. Load Context:
70
+ - Read `.forge/personas/bug-fixer.md` first; print the persona identity
71
+ line to stdout before any other tool use.
72
+ - Read the bug record:
73
+ `forge_store({ command:"read", entity:"bug", id:"{bugId}" })`
74
+ - Read business domain docs relevant to the reported symptom.
75
+ - store-cli verbs: `read` | `list` | `write` | `emit` |
76
+ `update-status` | `set-summary` | `set-bug-summary` | `describe` |
77
+ `nlp` | `query` | `delete` — there is no `get`/`set`/`find`. See
78
+ `_fragments/store-cli-verbs.md` for full notes.
79
+
80
+ 2. Reproduce:
81
+ - Construct a minimal reproduction: a failing test, a short script,
82
+ or a documented manual sequence that triggers the reported symptom.
83
+ - If reproduction cannot be achieved with the information in the bug
84
+ record, write what was tried in TRIAGE.md, set the route to "B"
85
+ (any uncertainty defaults to Path B), and continue to root-cause
86
+ research with the reporter's narrative as the working hypothesis.
87
+
88
+ 3. Root-Cause Research:
89
+ - Read the code paths implicated by the reproduction.
90
+ - Confirm (or revise) the reporter's stated root cause via direct
91
+ inspection of source files and tests.
92
+ - Note collateral damage: which other call sites, schemas, or
93
+ workflows share the defective shape.
94
+
95
+ 4. Path A / Path B Eligibility:
96
+ - Apply the criteria in § "Path A / Path B Eligibility" below.
97
+ - Record the route decision and the explicit enumeration of each
98
+ criterion in the findings section of the triage summary.
99
+
100
+ 5. Write Triage Artifacts:
101
+ - Write the triage artifact (markdown narrative):
102
+ `forge_artifact({ command:"write", entity:"bug", entityId:"{bugId}",
103
+ artifact:"triage", content:"<markdown>" })`
104
+ - Write the triage-summary sidecar (JSON shape below):
105
+ `forge_artifact({ command:"write", entity:"bug", entityId:"{bugId}",
106
+ artifact:"triage-summary", content:"<JSON>" })`
107
+
108
+ 6. Finalize:
109
+ - **No status write.** The orchestrator (`meta-fix-bug.md`) writes the
110
+ `reported → triaged` and `triaged → in-progress` transitions on
111
+ return. Writing `bug.status` from this workflow is forbidden by
112
+ Iron Laws above and is rejected by the phase-ownership guard.
113
+ - **Do NOT emit a phase event yourself.** The orchestrator owns event
114
+ emission — it composes the canonical event from runtime telemetry
115
+ (model, provider, tokens, wall times) plus the SUMMARY you write
116
+ in the next step.
117
+
118
+ 7. Emit Summary Sidecar:
119
+ - The JSON written in step 5 MUST have this shape (the `route` field
120
+ is required; allowed values: `"A"` or `"B"`):
121
+
122
+ ```json
123
+ {
124
+ "objective": "Triage FORGE-BUG-NNN — reproduce, locate, decide route.",
125
+ "key_changes": ["<up to 12 bullets, 200 chars each — findings or actions>"],
126
+ "findings": [
127
+ "Root cause: <one line>",
128
+ "Reproduction: <one line>",
129
+ "Route decision: A | B",
130
+ "Rationale: <one line>"
131
+ ],
132
+ "verdict": "n/a",
133
+ "written_at": "<current ISO 8601 timestamp>",
134
+ "artifact_ref":"TRIAGE.md",
135
+ "route": "A"
136
+ }
137
+ ```
138
+
139
+ - Call:
140
+ ```
141
+ forge_store({ command:"set-bug-summary", entity:"bug",
142
+ id:"{bugId}", phase:"triage",
143
+ file:"engineering/bugs/{bugDir}/TRIAGE-SUMMARY.json" })
144
+ ```
145
+ - If the set-bug-summary call exits non-zero, fix the sidecar JSON
146
+ and retry (up to 3 attempts per the Store-Write Verification rule).
147
+ Do not proceed without a valid summary.
148
+
149
+ > **Field-naming caution — runtime-tested.** The route field is named
150
+ > `route`, never `path`. The bug schema's top-level `path` field is the
151
+ > bug's **artifact directory** (e.g. `engineering/bugs/EMG-BUG-001-...`).
152
+ > Conflating the two caused EMBERGLOW-BUG-001 (v0.44.0 first run) to land
153
+ > its `TRIAGE.md` under `.forge/store/bugs/` instead of `engineering/bugs/`.
154
+ > Triage MUST NOT touch `bug.path` — that field is set at bug creation
155
+ > and never modified by triage.
156
+ ```
157
+
158
+ ## Path A / Path B Eligibility
159
+
160
+ Path A is **eligible only when ALL** of the following hold. The triage
161
+ summary `findings` array MUST enumerate each criterion explicitly with a
162
+ pass/fail mark, so reviewers can audit the decision:
163
+
164
+ - `bug.severity ∈ {minor}`
165
+ - Fix is contained in a single file
166
+ - Estimated diff ≤ ~20 lines (judgement call; one screen)
167
+ - No schema, API, migration, security, or build-system change
168
+ - A regression test is obvious from the reproduction script (single short
169
+ test case, no new fixtures, no test-harness change)
170
+
171
+ If any criterion fails, the triage subagent MUST select Path B.
172
+
173
+ **Path B is the default.** Any uncertainty resolves to Path B. It runs the
174
+ same plan/review/implement/review/approve/commit shape as
175
+ `meta-orchestrate.md`. Picking Path A under uncertainty is the documented
176
+ failure mode (over-eager short-circuit).
177
+
178
+ ## Triage Artifact Contents (TRIAGE.md)
179
+
180
+ The narrative artifact MUST contain:
181
+
182
+ 1. **Reported symptom** — one paragraph summarising the bug report.
183
+ 2. **Reproduction** — exact steps, commands, or test case that triggers
184
+ the symptom; copy of the failing output.
185
+ 3. **Root cause** — one or two paragraphs naming the defective code path,
186
+ schema, or workflow. Cite file paths and line numbers.
187
+ 4. **Path A / Path B enumeration** — for each criterion above, mark
188
+ pass/fail with one-line evidence.
189
+ 5. **Route decision and rationale** — the chosen route and the
190
+ single-sentence justification.
191
+ 6. **Collateral findings** — any related shapes, call sites, or
192
+ workflows that share the defective pattern (filed as follow-ups in
193
+ the commit phase, not fixed here).
194
+
195
+ <!-- See _fragments/generation-instructions.md for Generation Instructions template -->
196
+ ## Generation Instructions
197
+
198
+ - The generated `triage.md` MUST include all four markers required by
199
+ `forge-cli/src/extensions/forgecli/lib/manifest-checker.ts §
200
+ checkMaterialization`: (1) `## Store-Write Verification` heading;
201
+ (2) `## Iron Laws` heading; (3) literal `forge_store` token in body;
202
+ (4) `.forge/personas/bug-fixer.md` referenced in body.
203
+ - Token Reporting: `_fragments/finalize.md` — wire via `file_ref:`.
204
+ - Event Emission: orchestrator-owned; this workflow MUST NOT call
205
+ `forge_store emit` for phase events.
206
+
207
+ ## Friction Emit
208
+
209
+ Emit `type:friction` `{workflow:triage, persona:bug-fixer, issue}` per
210
+ `_fragments/friction-emit.md`.
@@ -31,7 +31,7 @@ Phases`):
31
31
 
32
32
  | Phase | Role | Persona | Workflow | Path A | Path B |
33
33
  |---|---|---|---|---|---|
34
- | triage | `triage` | bug-fixer | (inline algorithm) | yes | yes |
34
+ | triage | `triage` | bug-fixer | `triage.md` | yes | yes |
35
35
  | plan-fix | `plan` | engineer | `plan_task.md` (bug-mode) | no | yes |
36
36
  | review-plan | `review-plan` | supervisor | `review_plan.md` | no | yes |
37
37
  | implement | `implement` | engineer | `implement_plan.md` (bug-mode) | yes | yes |
@@ -101,24 +101,11 @@ The `route` field is required. Allowed values: `"A"` or `"B"`.
101
101
  > Triage subagents MUST NOT touch `bug.path` — that field is set at bug
102
102
  > creation and never modified by triage.
103
103
 
104
- ### Path A short-circuit (eligibility)
104
+ ### Path A / Path B eligibility
105
105
 
106
- Path A is **eligible only when ALL** of the following hold. Triage subagent
107
- must enumerate each in its findings:
108
-
109
- - `bug.severity ∈ {minor}`
110
- - Fix is contained in a single file
111
- - Estimated diff ≤ ~20 lines (judgement call; one screen)
112
- - No schema, API, migration, security, or build-system change
113
- - A regression test is obvious from the reproduction script (single short
114
- test case, no new fixtures, no test-harness change)
115
-
116
- If any criterion fails, the triage subagent MUST select Path B.
117
-
118
- ### Path B — full loop (default)
119
-
120
- Path B runs the same plan/review/implement/review/approve/commit shape as
121
- `meta-orchestrate.md`. It is the default. Any uncertainty defaults Path B.
106
+ See `triage.md § Path A / Path B Eligibility` for the criteria the triage
107
+ subagent applies. The criteria are single-sourced in the triage workflow;
108
+ this orchestrator only reads the resulting `summaries.triage.route` value.
122
109
 
123
110
  ### Pipeline selection by path
124
111
 
@@ -164,16 +151,11 @@ Differences are confined to the **triage** step and the **path branch**.
164
151
  b. If .forge/store/bugs/{BUG_ID}.json does NOT exist, write a fresh record
165
152
  via store-cli with status="reported".
166
153
  c. Read the now-guaranteed record.
167
- - Spawn the triage subagent (persona: bug-fixer). It MUST:
168
- Reproduce the bug (failing test or reproduction script).
169
- Confirm the root cause via codebase research.
170
- Decide Path A vs Path B by the criteria above.
171
- Write triage artifact:
172
- forge_artifact({ command:"write", entity:"bug", entityId:"{bugId}", artifact:"triage", content:"<markdown>" })
173
- • Write triage-summary artifact (JSON shape documented in § Triage Judgement):
174
- forge_artifact({ command:"write", entity:"bug", entityId:"{bugId}", artifact:"triage-summary", content:"<JSON>" })
175
- • Call set-bug-summary {bugId} triage via forge_store:
176
- forge_store({ command:"set-bug-summary", bugId:"{bugId}", phase:"triage", file:"TRIAGE-SUMMARY.json" })
154
+ - Spawn the triage subagent (workflow: `triage.md`, persona: bug-fixer).
155
+ It MUST write `TRIAGE.md` + `TRIAGE-SUMMARY.json` with a `route` field
156
+ (`"A"` or `"B"`) and call `set-bug-summary {bugId} triage` per
157
+ `triage.md`. The triage workflow is `audience: subagent`, `phase: triage`;
158
+ the orchestrator MUST NOT pass any other workflow body to this subagent.
177
159
  - On return, orchestrator transitions status:
178
160
  store-cli update-status bug {bugId} status triaged
179
161
  store-cli update-status bug {bugId} status in-progress
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "1.0.2",
3
- "generated": "2026-05-27",
3
+ "generated": "2026-05-28",
4
4
  "note": "Authoritative enum catalog. Source: build-enum-catalog.cjs. Regenerate via node forge/tools/build-manifest.cjs.",
5
5
  "enums": {
6
6
  "task.status": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "1.0.2",
3
- "generatedAt": "2026-05-27T08:59:39.257Z",
3
+ "generatedAt": "2026-05-28T05:59:32.606Z",
4
4
  "generatedByTool": "build-manifest.cjs",
5
5
  "namespaces": {
6
6
  "personas": {
@@ -48,6 +48,7 @@
48
48
  "review_plan.md",
49
49
  "run_sprint.md",
50
50
  "sprint_retrospective.md",
51
+ "triage.md",
51
52
  "update_implementation.md",
52
53
  "update_plan.md",
53
54
  "validate_task.md"
@@ -180,6 +181,24 @@
180
181
  "paths.engineering"
181
182
  ]
182
183
  },
184
+ "triage": {
185
+ "personas": [
186
+ ".forge/personas/bug-fixer.md"
187
+ ],
188
+ "skills": [
189
+ ".forge/skills/bug-fixer-skills.md",
190
+ ".forge/skills/generic-skills.md"
191
+ ],
192
+ "templates": [],
193
+ "sub_workflows": [],
194
+ "kb_docs": [
195
+ "{KB_PATH}/architecture/stack.md"
196
+ ],
197
+ "config_fields": [
198
+ "commands.test",
199
+ "paths.engineering"
200
+ ]
201
+ },
183
202
  "fix_bug": {
184
203
  "personas": [
185
204
  ".forge/personas/bug-fixer.md",