@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.
- package/CHANGELOG.md +23 -0
- package/dist/CHANGELOG-forge-plugin.md +24 -0
- package/dist/extensions/forgecli/audience-gate.js +1 -1
- package/dist/extensions/forgecli/audience-gate.js.map +1 -1
- package/dist/extensions/forgecli/fix-bug.d.ts +1 -2
- package/dist/extensions/forgecli/fix-bug.js +678 -609
- package/dist/extensions/forgecli/fix-bug.js.map +1 -1
- package/dist/extensions/forgecli/forge-artifact-tool.js +15 -3
- package/dist/extensions/forgecli/forge-artifact-tool.js.map +1 -1
- package/dist/extensions/forgecli/forge-subagent.d.ts +17 -0
- package/dist/extensions/forgecli/forge-subagent.js +31 -12
- package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
- package/dist/extensions/forgecli/forge-tools.d.ts +6 -0
- package/dist/extensions/forgecli/forge-tools.js +69 -6
- package/dist/extensions/forgecli/forge-tools.js.map +1 -1
- package/dist/extensions/forgecli/run-task.js +461 -391
- package/dist/extensions/forgecli/run-task.js.map +1 -1
- package/dist/extensions/forgecli/session-registry.d.ts +12 -0
- package/dist/extensions/forgecli/session-registry.js +23 -0
- package/dist/extensions/forgecli/session-registry.js.map +1 -1
- package/dist/extensions/forgecli/subagent/caller-context.d.ts +35 -11
- package/dist/extensions/forgecli/subagent/caller-context.js +49 -21
- package/dist/extensions/forgecli/subagent/caller-context.js.map +1 -1
- package/dist/extensions/forgecli/subagent/orchestrator-transcript.d.ts +66 -0
- package/dist/extensions/forgecli/subagent/orchestrator-transcript.js +66 -0
- package/dist/extensions/forgecli/subagent/orchestrator-transcript.js.map +1 -0
- package/dist/extensions/forgecli/subagent/phase-guard.d.ts +34 -0
- package/dist/extensions/forgecli/subagent/phase-guard.js +139 -0
- package/dist/extensions/forgecli/subagent/phase-guard.js.map +1 -0
- package/dist/extensions/forgecli/subagent/phase-summary-map.d.ts +1 -0
- package/dist/extensions/forgecli/subagent/phase-summary-map.js +22 -0
- package/dist/extensions/forgecli/subagent/phase-summary-map.js.map +1 -0
- package/dist/extensions/forgecli/thread-switcher.js +2 -2
- package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
- package/dist/extensions/forgecli/viewport-events.d.ts +4 -0
- package/dist/extensions/forgecli/viewport-events.js +18 -1
- package/dist/extensions/forgecli/viewport-events.js.map +1 -1
- package/dist/extensions/forgecli/viewport-renderer.d.ts +12 -2
- package/dist/extensions/forgecli/viewport-renderer.js +8 -6
- package/dist/extensions/forgecli/viewport-renderer.js.map +1 -1
- package/dist/forge-payload/.base-pack/workflows/fix_bug.md +10 -28
- package/dist/forge-payload/.base-pack/workflows/triage.md +190 -0
- package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
- package/dist/forge-payload/.schemas/enum-catalog.json +1 -1
- package/dist/forge-payload/.schemas/migrations.json +9 -0
- package/dist/forge-payload/integrity.json +3 -3
- package/dist/forge-payload/meta/fragments/tool-discipline.md +21 -2
- package/dist/forge-payload/meta/workflows/meta-bug-triage.md +210 -0
- package/dist/forge-payload/meta/workflows/meta-fix-bug.md +10 -28
- package/dist/forge-payload/schemas/enum-catalog.json +1 -1
- package/dist/forge-payload/schemas/structure-manifest.json +20 -1
- package/dist/forge-payload/tools/artifact.cjs +34 -5
- package/node_modules/@entelligentsia/forge-compress/dist/compressor.d.ts +6 -0
- package/node_modules/@entelligentsia/forge-compress/dist/compressor.js +137 -0
- package/node_modules/@entelligentsia/forge-compress/dist/entropy.d.ts +3 -0
- package/node_modules/@entelligentsia/forge-compress/dist/entropy.js +99 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/entity.d.ts +8 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/entity.js +149 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/index.d.ts +7 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/index.js +4 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/markdown.d.ts +5 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/markdown.js +92 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/query.d.ts +7 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/query.js +60 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/validate.d.ts +1 -0
- package/node_modules/@entelligentsia/forge-compress/dist/forge/validate.js +82 -0
- package/node_modules/@entelligentsia/forge-compress/dist/index.d.ts +6 -0
- package/node_modules/@entelligentsia/forge-compress/dist/index.js +5 -0
- package/node_modules/@entelligentsia/forge-compress/dist/progressive.d.ts +1 -0
- package/node_modules/@entelligentsia/forge-compress/dist/progressive.js +108 -0
- package/node_modules/@entelligentsia/forge-compress/dist/strip.d.ts +4 -0
- package/node_modules/@entelligentsia/forge-compress/dist/strip.js +55 -0
- package/node_modules/@entelligentsia/forge-compress/dist/tokens.d.ts +2 -0
- package/node_modules/@entelligentsia/forge-compress/dist/tokens.js +17 -0
- package/node_modules/@entelligentsia/forge-compress/package.json +45 -0
- package/node_modules/@entelligentsia/forge-compress/src/__tests__/compress.test.ts +409 -0
- package/node_modules/@entelligentsia/forge-compress/src/compressor.ts +147 -0
- package/node_modules/@entelligentsia/forge-compress/src/entropy.ts +105 -0
- package/node_modules/@entelligentsia/forge-compress/src/forge/entity.ts +184 -0
- package/node_modules/@entelligentsia/forge-compress/src/forge/index.ts +10 -0
- package/node_modules/@entelligentsia/forge-compress/src/forge/markdown.ts +122 -0
- package/node_modules/@entelligentsia/forge-compress/src/forge/query.ts +105 -0
- package/node_modules/@entelligentsia/forge-compress/src/forge/validate.ts +86 -0
- package/node_modules/@entelligentsia/forge-compress/src/index.ts +22 -0
- package/node_modules/@entelligentsia/forge-compress/src/progressive.ts +123 -0
- package/node_modules/@entelligentsia/forge-compress/src/strip.ts +58 -0
- package/node_modules/@entelligentsia/forge-compress/src/tokens.ts +19 -0
- 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 |
|
|
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
|
|
96
|
+
### Path A / Path B eligibility
|
|
97
97
|
|
|
98
|
-
Path A
|
|
99
|
-
|
|
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).
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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,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.
|
|
3
|
-
"generated": "2026-05-
|
|
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": "
|
|
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.
|
|
4
|
+
no agent loop. Use them for all Forge-managed data — never bypass with god tools.
|
|
5
5
|
|
|
6
|
-
|
|
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 |
|
|
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
|
|
104
|
+
### Path A / Path B eligibility
|
|
105
105
|
|
|
106
|
-
Path A
|
|
107
|
-
|
|
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).
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
"generatedAt": "2026-05-
|
|
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",
|