wdi-method 0.4.6 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +271 -252
- package/bin/wdi-method.js +1221 -1030
- package/kit/.constitution/method/README.md +73 -169
- package/kit/.constitution/{constitution.md → method/constitution.md} +10 -56
- package/kit/.constitution/{document → method/document}/architecture-guide.md +209 -209
- package/kit/.constitution/{document → method/document}/corpus-guide.md +4 -4
- package/kit/.constitution/{document → method/document}/delivery-flow-guide.md +338 -338
- package/kit/.constitution/{document → method/document}/sdd-guide.md +1 -1
- package/kit/.constitution/{document → method/document}/templates/cross-cutting.md +2 -2
- package/kit/.constitution/{document → method/document}/templates/design-system.md +67 -67
- package/kit/.constitution/{document → method/document}/templates/inventory.md +69 -69
- package/kit/.constitution/{document → method/document}/templates/sdd.md +1 -1
- package/kit/.constitution/{document → method/document}/templates/structure-codebase.md +129 -129
- package/kit/.constitution/{document → method/document}/templates/structure-document.md +90 -90
- package/kit/.constitution/{language-guide.md → method/language-guide.md} +2 -2
- package/kit/.constitution/{method-glossary.md → method/method-glossary.md} +169 -169
- package/kit/.constitution/{repo-guide.md → method/repo-guide.md} +120 -97
- package/kit/.constitution/method/scripts/__pycache__/validate.cpython-314.pyc +0 -0
- package/kit/.constitution/{scripts → method/scripts}/timeline.py +2 -2
- package/kit/.constitution/{scripts → method/scripts}/validate.py +1648 -1581
- package/kit/.constitution/{structure-guide.md → method/structure-guide.md} +3 -3
- package/kit/.constitution/method/why/README.md +169 -0
- package/kit/.constitution/method/{artifact-map.md → why/artifact-map.md} +5 -5
- package/kit/.constitution/method/{portability.md → why/portability.md} +6 -6
- package/kit/.constitution/method/{rationale.md → why/rationale.md} +5 -5
- package/kit/.constitution/project/README.md +68 -68
- package/kit/.constitution/project/constitution.md +64 -0
- package/kit/assets/bmad-custom/bmad-advanced-elicitation.toml +15 -15
- package/kit/assets/bmad-custom/bmad-architecture.toml +33 -33
- package/kit/assets/bmad-custom/bmad-code-review.toml +13 -13
- package/kit/assets/bmad-custom/bmad-correct-course.toml +28 -28
- package/kit/assets/bmad-custom/bmad-prd.toml +42 -42
- package/kit/assets/bmad-custom/bmad-product-brief.toml +34 -34
- package/kit/assets/bmad-custom/bmad-retrospective.toml +9 -9
- package/kit/assets/bmad-custom/bmad-spec.toml +16 -16
- package/kit/assets/bmad-custom/bmad-ux.toml +19 -19
- package/kit/skills/wdi-blueprint/SKILL.md +203 -203
- package/kit/skills/wdi-build/SKILL.md +244 -244
- package/kit/skills/wdi-component/SKILL.md +1 -1
- package/kit/skills/wdi-help/SKILL.md +98 -98
- package/kit/skills/wdi-init/SKILL.md +1 -1
- package/kit/skills/wdi-problem/SKILL.md +90 -90
- package/kit/skills/wdi-product/SKILL.md +127 -127
- package/kit/skills/wdi-reconcile/SKILL.md +2 -2
- package/kit/skills/wdi-report/SKILL.md +205 -205
- package/kit/skills/wdi-systematic-debugging/SKILL.md +193 -193
- package/kit/skills/wdi-ux/SKILL.md +145 -145
- package/kit-overlay/AGENTS.md +215 -212
- package/kit-overlay/README.md +24 -17
- package/kit-overlay/constitution.md +10 -56
- package/kit-overlay/portability.md +6 -6
- package/kit-overlay/repo-guide.md +120 -97
- package/package.json +4 -2
- package/scaffold/.control/questions/blocking.md +1 -1
- package/kit/.constitution/README.md +0 -66
- /package/kit/.constitution/{document → method/document}/bmad-guide.md +0 -0
- /package/kit/.constitution/{document → method/document}/bmad-skill-register.md +0 -0
- /package/kit/.constitution/{document → method/document}/brief-guide.md +0 -0
- /package/kit/.constitution/{document → method/document}/decision-guide.md +0 -0
- /package/kit/.constitution/{document → method/document}/prd-guide.md +0 -0
- /package/kit/.constitution/{document → method/document}/srs-guide.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/addendum.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/architecture-spine.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/brief.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/c4.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/contract.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/decision.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/flow.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/integration.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/lc.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/lifecycle.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/meeting.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/model.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/oq.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/prd.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/questions.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/rtr.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/rules.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/scn.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/srs.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/uc.md +0 -0
- /package/kit/.constitution/{document → method/document}/templates/ux.md +0 -0
- /package/kit/.constitution/{document → method/document}/ux-guide.md +0 -0
- /package/kit/.constitution/{scripts → method/scripts}/inventory.py +0 -0
- /package/kit/.constitution/{codebase/brownfield-guide.md → project/codebase-brownfield-guide.md} +0 -0
- /package/kit/.constitution/{codebase/conventions-guide.md → project/codebase-conventions-guide.md} +0 -0
- /package/kit/.constitution/{codebase/stack-guide.md → project/codebase-stack-guide.md} +0 -0
|
@@ -1,193 +1,193 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wdi-systematic-debugging
|
|
3
|
-
description: Use when encountering any bug, test failure, build failure, or unexpected behavior, before proposing any fix. Covers root-cause investigation, hypothesis testing, and the escalation rule when repeated fixes fail.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Systematic Debugging
|
|
7
|
-
|
|
8
|
-
BMad has no debugging workflow — `bmad-build` assumes you already know what to build. This skill
|
|
9
|
-
covers the gap: something is broken and the cause is unknown.
|
|
10
|
-
|
|
11
|
-
## The Iron Law
|
|
12
|
-
|
|
13
|
-
**NO FIX WITHOUT ROOT CAUSE INVESTIGATION FIRST.**
|
|
14
|
-
|
|
15
|
-
You MUST complete Phase 1 before proposing any fix. A fix that treats a symptom is a failure even
|
|
16
|
-
when the symptom disappears.
|
|
17
|
-
|
|
18
|
-
## When to use
|
|
19
|
-
|
|
20
|
-
Use for any technical issue: test failure, production bug, unexpected behavior, performance problem,
|
|
21
|
-
build failure, integration failure.
|
|
22
|
-
|
|
23
|
-
**Its home is G5, but its trigger is not positional.** Most invocations happen while coding, and
|
|
24
|
-
that is why `AGENTS.md`, `bmad-build`, and the ship-story orchestration carry this rule in their
|
|
25
|
-
worker context. What actually fires it is a pair of conditions — *something is broken* **and** *the
|
|
26
|
-
cause is unknown* — so it MAY be invoked in any stage, by anyone, to investigate: a red
|
|
27
|
-
`validate.py` while writing an SRS at G3, a `wdi-reconcile` report that makes no sense, a
|
|
28
|
-
generator producing an empty timeline. None of those wait for G5, and none of them are a
|
|
29
|
-
misuse of this skill.
|
|
30
|
-
|
|
31
|
-
The second condition matters as much as the first. A test failing because of a missing import is not
|
|
32
|
-
a trigger — you already know the cause. A test failing for a reason you cannot name is.
|
|
33
|
-
|
|
34
|
-
Nor does the finding always land in code: three of the four `root_cause` categories send it back to
|
|
35
|
-
`.what/` or `.how/` — see [Where the finding lands](#where-the-finding-lands).
|
|
36
|
-
|
|
37
|
-
Use it *especially* when the pressure argues against it — an emergency, an "obvious one-line fix", a
|
|
38
|
-
previous fix that did not hold. Systematic debugging is faster than guess-and-check, and the
|
|
39
|
-
pressure cases are exactly where guessing costs the most.
|
|
40
|
-
|
|
41
|
-
A simple-looking bug has a root cause too. You MUST NOT skip phases because the issue looks small.
|
|
42
|
-
|
|
43
|
-
## Phase 1 — Root cause investigation
|
|
44
|
-
|
|
45
|
-
1. **Read the error completely.** Full stack trace, line numbers, file paths, error codes. The
|
|
46
|
-
answer is often already in it.
|
|
47
|
-
2. **Reproduce it.** Exact steps, every time. If it is not reproducible, gather more data — you
|
|
48
|
-
MUST NOT proceed on a guess.
|
|
49
|
-
3. **Check what changed.** `git diff`, recent commits, new dependencies, config, environment.
|
|
50
|
-
4. **Instrument the boundaries.** When more than one component is involved (browser → API →
|
|
51
|
-
service → database; CI → build → deploy), add logging at *each* boundary before proposing
|
|
52
|
-
anything: what enters, what exits, what config propagated. Run once to find *which* boundary
|
|
53
|
-
fails, then investigate only that one.
|
|
54
|
-
5. **Trace the bad value backward** to where it originates — see
|
|
55
|
-
[references/root-cause-tracing.md](references/root-cause-tracing.md). Fix at the source, never
|
|
56
|
-
where the symptom surfaced.
|
|
57
|
-
|
|
58
|
-
## Phase 2 — Pattern analysis
|
|
59
|
-
|
|
60
|
-
1. Find working code in this repo that does the same kind of thing.
|
|
61
|
-
2. Read the reference implementation **completely**. Skimming produces partial understanding, and
|
|
62
|
-
partial understanding produces the next bug.
|
|
63
|
-
3. List every difference between working and broken, however small. You MUST NOT dismiss a
|
|
64
|
-
difference as irrelevant before testing it.
|
|
65
|
-
4. Name the dependencies the broken path assumes: config, environment, state, ordering.
|
|
66
|
-
|
|
67
|
-
## Phase 3 — Hypothesis
|
|
68
|
-
|
|
69
|
-
1. State one hypothesis in writing: "X is the root cause because Y."
|
|
70
|
-
2. Test it with the **smallest possible change**. One variable at a time.
|
|
71
|
-
3. Worked → Phase 4. Did not work → form a *new* hypothesis. You MUST NOT stack a second fix on
|
|
72
|
-
top of a failed one.
|
|
73
|
-
4. If you do not understand something, say so plainly and investigate further. Pretending to know
|
|
74
|
-
is what produces fix #4.
|
|
75
|
-
|
|
76
|
-
## Phase 4 — Implementation
|
|
77
|
-
|
|
78
|
-
1. **Write the failing test first.** Simplest reproduction that fails for the right reason. Run it
|
|
79
|
-
and confirm it fails before writing any fix. A fix without a test that failed first does not
|
|
80
|
-
stick and cannot be proven.
|
|
81
|
-
2. **One fix, addressing the root cause.** No bundled refactoring, no "while I'm here" improvements.
|
|
82
|
-
3. **Verify with evidence.** The test passes, no other test broke, and you have the command output
|
|
83
|
-
to show it. Claiming success without the output is prohibited.
|
|
84
|
-
4. **If the fix fails, count your attempts.**
|
|
85
|
-
- Fewer than 3 → return to Phase 1 with what you now know.
|
|
86
|
-
- **3 or more → STOP. Do not attempt fix #4.**
|
|
87
|
-
|
|
88
|
-
## Phase 5 — Record the finding
|
|
89
|
-
|
|
90
|
-
An investigation that ends in chat has to be repeated. Before you close out — whether the fix landed
|
|
91
|
-
or the three-fix rule stopped you — record what you found in `.control/registry/defects.yaml`. This
|
|
92
|
-
is the only registry write this skill owns, and it exists so one question can be answered with a
|
|
93
|
-
number rather than a memory: **how many of our defects turned out to be a wrong requirement rather
|
|
94
|
-
than wrong code.**
|
|
95
|
-
|
|
96
|
-
### Find the row, or open one
|
|
97
|
-
|
|
98
|
-
A defect found by a tester is usually already there, carrying only `id`, `title`, `found_in`, and
|
|
99
|
-
`reported`. Anyone MAY open such a row without running any skill, and an empty `root_cause` is a
|
|
100
|
-
legitimate state meaning *not yet diagnosed* — you are the step that fills it, not the step that
|
|
101
|
-
guards it. When no row exists, open one yourself, taking the next number in the `BUG-` sequence
|
|
102
|
-
(`HOT-` when it arrived through the hotfix path).
|
|
103
|
-
|
|
104
|
-
You MUST NOT require a row to exist before investigating. A defect nobody recorded is still a
|
|
105
|
-
defect; refusing to work until the paperwork is right is how the file becomes a formality.
|
|
106
|
-
|
|
107
|
-
### Write three fields, and only these three
|
|
108
|
-
|
|
109
|
-
| Field | Where it comes from |
|
|
110
|
-
|---|---|
|
|
111
|
-
| `root_cause` | Your Phase 1–3 conclusion, in the four categories of the table above |
|
|
112
|
-
| `violates` | The `FR-` or `UC-` the defect breaks. MUST be filled for `requirement` and `architecture`: a defect that violates something without naming what cannot be traced back to the corpus, and V20 fails it |
|
|
113
|
-
| `fix` | `fastpath` for a pure code defect, the wave id otherwise. The table above already decides this — `requirement` and `architecture` MUST NOT be `fastpath` |
|
|
114
|
-
|
|
115
|
-
You MUST NOT write a closure date. It is derived from the history of `defects.yaml` itself by
|
|
116
|
-
`.constitution/scripts/timeline.py`, and a hand-written date would be a second home for one fact —
|
|
117
|
-
the stored copy being the one that goes wrong.
|
|
118
|
-
|
|
119
|
-
You MUST NOT edit `title`, `found_in`, or `reported`. Whoever opened the row owns those; correcting
|
|
120
|
-
them silently erases what was actually reported.
|
|
121
|
-
|
|
122
|
-
### `status: fixed` follows the route, not the merge
|
|
123
|
-
|
|
124
|
-
The moment the patch merges is not the moment the defect closes. What closes it depends on the row's
|
|
125
|
-
own `root_cause`:
|
|
126
|
-
|
|
127
|
-
| `root_cause` | Closes when |
|
|
128
|
-
|---|---|
|
|
129
|
-
| `code` | The failing test from Phase 4 passes and the fix is merged |
|
|
130
|
-
| `requirement` | The `FR-` or `UC-` in `violates` has actually changed — the code alone MUST NOT close it |
|
|
131
|
-
| `architecture` | The `DEC-` is `accepted` and named on the row. V20 fails a `fixed` row without one |
|
|
132
|
-
| `environment` | The handling is in place and the monitoring exists |
|
|
133
|
-
|
|
134
|
-
Setting `fixed` before its row's condition is met is the failure this whole registry exists to
|
|
135
|
-
prevent: it turns "we patched the code" into "the requirement was right all along".
|
|
136
|
-
|
|
137
|
-
### When the three-fix rule stopped you
|
|
138
|
-
|
|
139
|
-
You MUST still record. The rule triggering *is* the finding — `root_cause: architecture`, `violates`
|
|
140
|
-
naming what the architecture broke, and the row left `open` until the `DEC-` exists. An escalation that
|
|
141
|
-
leaves no trace looks identical to a bug that was never investigated.
|
|
142
|
-
|
|
143
|
-
## The three-fix rule
|
|
144
|
-
|
|
145
|
-
Three failed fixes is not three failed hypotheses — it is a signal that the architecture is wrong.
|
|
146
|
-
|
|
147
|
-
Symptoms: each fix uncovers new coupling or shared state somewhere else; each fix needs "a bit of
|
|
148
|
-
refactoring" to land; each fix creates a new symptom elsewhere.
|
|
149
|
-
|
|
150
|
-
When this happens you MUST stop and raise it with the owner rather than continue. In this project's
|
|
151
|
-
terms, the outcome is a `DEC-` — a correction of course is one too — not another patch.
|
|
152
|
-
|
|
153
|
-
## Where the finding lands
|
|
154
|
-
|
|
155
|
-
| What the root cause turns out to be | Where it goes |
|
|
156
|
-
|---|---|
|
|
157
|
-
| Genuine code defect, no artifact was wrong | Fast Path — fix, test, done |
|
|
158
|
-
| A requirement was missing or wrong | Back to the Impact Matrix in `.constitution/document/delivery-flow-guide.md`; the FR/UC changes before the code does |
|
|
159
|
-
| An architecture decision was wrong | `wdi-decision`, which wraps `bmad-correct-course`; MUST NOT be absorbed as a code patch |
|
|
160
|
-
| Environmental, timing-dependent, or external | Document the investigation, implement handling (retry, timeout, clear error), add monitoring |
|
|
161
|
-
|
|
162
|
-
These four categories are exactly the values of `root_cause` in `.control/registry/defects.yaml`.
|
|
163
|
-
Phase 5 is where your verdict lands in that file.
|
|
164
|
-
|
|
165
|
-
The last row is real but rare. Most "no root cause" conclusions are incomplete investigations —
|
|
166
|
-
treat that verdict with suspicion in yourself.
|
|
167
|
-
|
|
168
|
-
## Red flags — stop and return to Phase 1
|
|
169
|
-
|
|
170
|
-
If you catch yourself thinking any of these, the process has already broken down:
|
|
171
|
-
|
|
172
|
-
| Thought | Reality |
|
|
173
|
-
|---|---|
|
|
174
|
-
| "Quick fix now, investigate later" | The first fix sets the pattern. There is no later. |
|
|
175
|
-
| "Just change X and see if it works" | That is guessing with extra steps. |
|
|
176
|
-
| "It's probably X, let me fix that" | Seeing a symptom is not understanding a cause. |
|
|
177
|
-
| "I'll skip the test and verify manually" | Untested fixes regress silently. |
|
|
178
|
-
| "Several changes at once saves time" | You will not know which one worked, or what else broke. |
|
|
179
|
-
| "The reference is long, I'll adapt the pattern" | Partial reading guarantees the next bug. |
|
|
180
|
-
| "One more fix attempt" (after 2+) | Three failures means the architecture is the problem. |
|
|
181
|
-
| "Emergency — no time for process" | Thrashing is slower. Always. |
|
|
182
|
-
|
|
183
|
-
Signals from the owner that mean the same thing: *"stop guessing"*, *"is that actually
|
|
184
|
-
happening?"*, *"will that show us anything?"*, *"we're stuck?"*
|
|
185
|
-
|
|
186
|
-
## Supporting techniques
|
|
187
|
-
|
|
188
|
-
| File | Use when |
|
|
189
|
-
|---|---|
|
|
190
|
-
| [references/root-cause-tracing.md](references/root-cause-tracing.md) | The error surfaces deep in a call stack and you must trace backward to the origin |
|
|
191
|
-
| [references/defense-in-depth.md](references/defense-in-depth.md) | Root cause is found and you are deciding where validation belongs |
|
|
192
|
-
| [references/condition-based-waiting.md](references/condition-based-waiting.md) | Flaky timing, arbitrary sleeps, race conditions |
|
|
193
|
-
| [references/find-polluter.sh](references/find-polluter.sh) | A test passes alone but fails in the suite — bisects to find the polluting test |
|
|
1
|
+
---
|
|
2
|
+
name: wdi-systematic-debugging
|
|
3
|
+
description: Use when encountering any bug, test failure, build failure, or unexpected behavior, before proposing any fix. Covers root-cause investigation, hypothesis testing, and the escalation rule when repeated fixes fail.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Systematic Debugging
|
|
7
|
+
|
|
8
|
+
BMad has no debugging workflow — `bmad-build` assumes you already know what to build. This skill
|
|
9
|
+
covers the gap: something is broken and the cause is unknown.
|
|
10
|
+
|
|
11
|
+
## The Iron Law
|
|
12
|
+
|
|
13
|
+
**NO FIX WITHOUT ROOT CAUSE INVESTIGATION FIRST.**
|
|
14
|
+
|
|
15
|
+
You MUST complete Phase 1 before proposing any fix. A fix that treats a symptom is a failure even
|
|
16
|
+
when the symptom disappears.
|
|
17
|
+
|
|
18
|
+
## When to use
|
|
19
|
+
|
|
20
|
+
Use for any technical issue: test failure, production bug, unexpected behavior, performance problem,
|
|
21
|
+
build failure, integration failure.
|
|
22
|
+
|
|
23
|
+
**Its home is G5, but its trigger is not positional.** Most invocations happen while coding, and
|
|
24
|
+
that is why `AGENTS.md`, `bmad-build`, and the ship-story orchestration carry this rule in their
|
|
25
|
+
worker context. What actually fires it is a pair of conditions — *something is broken* **and** *the
|
|
26
|
+
cause is unknown* — so it MAY be invoked in any stage, by anyone, to investigate: a red
|
|
27
|
+
`validate.py` while writing an SRS at G3, a `wdi-reconcile` report that makes no sense, a
|
|
28
|
+
generator producing an empty timeline. None of those wait for G5, and none of them are a
|
|
29
|
+
misuse of this skill.
|
|
30
|
+
|
|
31
|
+
The second condition matters as much as the first. A test failing because of a missing import is not
|
|
32
|
+
a trigger — you already know the cause. A test failing for a reason you cannot name is.
|
|
33
|
+
|
|
34
|
+
Nor does the finding always land in code: three of the four `root_cause` categories send it back to
|
|
35
|
+
`.what/` or `.how/` — see [Where the finding lands](#where-the-finding-lands).
|
|
36
|
+
|
|
37
|
+
Use it *especially* when the pressure argues against it — an emergency, an "obvious one-line fix", a
|
|
38
|
+
previous fix that did not hold. Systematic debugging is faster than guess-and-check, and the
|
|
39
|
+
pressure cases are exactly where guessing costs the most.
|
|
40
|
+
|
|
41
|
+
A simple-looking bug has a root cause too. You MUST NOT skip phases because the issue looks small.
|
|
42
|
+
|
|
43
|
+
## Phase 1 — Root cause investigation
|
|
44
|
+
|
|
45
|
+
1. **Read the error completely.** Full stack trace, line numbers, file paths, error codes. The
|
|
46
|
+
answer is often already in it.
|
|
47
|
+
2. **Reproduce it.** Exact steps, every time. If it is not reproducible, gather more data — you
|
|
48
|
+
MUST NOT proceed on a guess.
|
|
49
|
+
3. **Check what changed.** `git diff`, recent commits, new dependencies, config, environment.
|
|
50
|
+
4. **Instrument the boundaries.** When more than one component is involved (browser → API →
|
|
51
|
+
service → database; CI → build → deploy), add logging at *each* boundary before proposing
|
|
52
|
+
anything: what enters, what exits, what config propagated. Run once to find *which* boundary
|
|
53
|
+
fails, then investigate only that one.
|
|
54
|
+
5. **Trace the bad value backward** to where it originates — see
|
|
55
|
+
[references/root-cause-tracing.md](references/root-cause-tracing.md). Fix at the source, never
|
|
56
|
+
where the symptom surfaced.
|
|
57
|
+
|
|
58
|
+
## Phase 2 — Pattern analysis
|
|
59
|
+
|
|
60
|
+
1. Find working code in this repo that does the same kind of thing.
|
|
61
|
+
2. Read the reference implementation **completely**. Skimming produces partial understanding, and
|
|
62
|
+
partial understanding produces the next bug.
|
|
63
|
+
3. List every difference between working and broken, however small. You MUST NOT dismiss a
|
|
64
|
+
difference as irrelevant before testing it.
|
|
65
|
+
4. Name the dependencies the broken path assumes: config, environment, state, ordering.
|
|
66
|
+
|
|
67
|
+
## Phase 3 — Hypothesis
|
|
68
|
+
|
|
69
|
+
1. State one hypothesis in writing: "X is the root cause because Y."
|
|
70
|
+
2. Test it with the **smallest possible change**. One variable at a time.
|
|
71
|
+
3. Worked → Phase 4. Did not work → form a *new* hypothesis. You MUST NOT stack a second fix on
|
|
72
|
+
top of a failed one.
|
|
73
|
+
4. If you do not understand something, say so plainly and investigate further. Pretending to know
|
|
74
|
+
is what produces fix #4.
|
|
75
|
+
|
|
76
|
+
## Phase 4 — Implementation
|
|
77
|
+
|
|
78
|
+
1. **Write the failing test first.** Simplest reproduction that fails for the right reason. Run it
|
|
79
|
+
and confirm it fails before writing any fix. A fix without a test that failed first does not
|
|
80
|
+
stick and cannot be proven.
|
|
81
|
+
2. **One fix, addressing the root cause.** No bundled refactoring, no "while I'm here" improvements.
|
|
82
|
+
3. **Verify with evidence.** The test passes, no other test broke, and you have the command output
|
|
83
|
+
to show it. Claiming success without the output is prohibited.
|
|
84
|
+
4. **If the fix fails, count your attempts.**
|
|
85
|
+
- Fewer than 3 → return to Phase 1 with what you now know.
|
|
86
|
+
- **3 or more → STOP. Do not attempt fix #4.**
|
|
87
|
+
|
|
88
|
+
## Phase 5 — Record the finding
|
|
89
|
+
|
|
90
|
+
An investigation that ends in chat has to be repeated. Before you close out — whether the fix landed
|
|
91
|
+
or the three-fix rule stopped you — record what you found in `.control/registry/defects.yaml`. This
|
|
92
|
+
is the only registry write this skill owns, and it exists so one question can be answered with a
|
|
93
|
+
number rather than a memory: **how many of our defects turned out to be a wrong requirement rather
|
|
94
|
+
than wrong code.**
|
|
95
|
+
|
|
96
|
+
### Find the row, or open one
|
|
97
|
+
|
|
98
|
+
A defect found by a tester is usually already there, carrying only `id`, `title`, `found_in`, and
|
|
99
|
+
`reported`. Anyone MAY open such a row without running any skill, and an empty `root_cause` is a
|
|
100
|
+
legitimate state meaning *not yet diagnosed* — you are the step that fills it, not the step that
|
|
101
|
+
guards it. When no row exists, open one yourself, taking the next number in the `BUG-` sequence
|
|
102
|
+
(`HOT-` when it arrived through the hotfix path).
|
|
103
|
+
|
|
104
|
+
You MUST NOT require a row to exist before investigating. A defect nobody recorded is still a
|
|
105
|
+
defect; refusing to work until the paperwork is right is how the file becomes a formality.
|
|
106
|
+
|
|
107
|
+
### Write three fields, and only these three
|
|
108
|
+
|
|
109
|
+
| Field | Where it comes from |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `root_cause` | Your Phase 1–3 conclusion, in the four categories of the table above |
|
|
112
|
+
| `violates` | The `FR-` or `UC-` the defect breaks. MUST be filled for `requirement` and `architecture`: a defect that violates something without naming what cannot be traced back to the corpus, and V20 fails it |
|
|
113
|
+
| `fix` | `fastpath` for a pure code defect, the wave id otherwise. The table above already decides this — `requirement` and `architecture` MUST NOT be `fastpath` |
|
|
114
|
+
|
|
115
|
+
You MUST NOT write a closure date. It is derived from the history of `defects.yaml` itself by
|
|
116
|
+
`.constitution/method/scripts/timeline.py`, and a hand-written date would be a second home for one fact —
|
|
117
|
+
the stored copy being the one that goes wrong.
|
|
118
|
+
|
|
119
|
+
You MUST NOT edit `title`, `found_in`, or `reported`. Whoever opened the row owns those; correcting
|
|
120
|
+
them silently erases what was actually reported.
|
|
121
|
+
|
|
122
|
+
### `status: fixed` follows the route, not the merge
|
|
123
|
+
|
|
124
|
+
The moment the patch merges is not the moment the defect closes. What closes it depends on the row's
|
|
125
|
+
own `root_cause`:
|
|
126
|
+
|
|
127
|
+
| `root_cause` | Closes when |
|
|
128
|
+
|---|---|
|
|
129
|
+
| `code` | The failing test from Phase 4 passes and the fix is merged |
|
|
130
|
+
| `requirement` | The `FR-` or `UC-` in `violates` has actually changed — the code alone MUST NOT close it |
|
|
131
|
+
| `architecture` | The `DEC-` is `accepted` and named on the row. V20 fails a `fixed` row without one |
|
|
132
|
+
| `environment` | The handling is in place and the monitoring exists |
|
|
133
|
+
|
|
134
|
+
Setting `fixed` before its row's condition is met is the failure this whole registry exists to
|
|
135
|
+
prevent: it turns "we patched the code" into "the requirement was right all along".
|
|
136
|
+
|
|
137
|
+
### When the three-fix rule stopped you
|
|
138
|
+
|
|
139
|
+
You MUST still record. The rule triggering *is* the finding — `root_cause: architecture`, `violates`
|
|
140
|
+
naming what the architecture broke, and the row left `open` until the `DEC-` exists. An escalation that
|
|
141
|
+
leaves no trace looks identical to a bug that was never investigated.
|
|
142
|
+
|
|
143
|
+
## The three-fix rule
|
|
144
|
+
|
|
145
|
+
Three failed fixes is not three failed hypotheses — it is a signal that the architecture is wrong.
|
|
146
|
+
|
|
147
|
+
Symptoms: each fix uncovers new coupling or shared state somewhere else; each fix needs "a bit of
|
|
148
|
+
refactoring" to land; each fix creates a new symptom elsewhere.
|
|
149
|
+
|
|
150
|
+
When this happens you MUST stop and raise it with the owner rather than continue. In this project's
|
|
151
|
+
terms, the outcome is a `DEC-` — a correction of course is one too — not another patch.
|
|
152
|
+
|
|
153
|
+
## Where the finding lands
|
|
154
|
+
|
|
155
|
+
| What the root cause turns out to be | Where it goes |
|
|
156
|
+
|---|---|
|
|
157
|
+
| Genuine code defect, no artifact was wrong | Fast Path — fix, test, done |
|
|
158
|
+
| A requirement was missing or wrong | Back to the Impact Matrix in `.constitution/method/document/delivery-flow-guide.md`; the FR/UC changes before the code does |
|
|
159
|
+
| An architecture decision was wrong | `wdi-decision`, which wraps `bmad-correct-course`; MUST NOT be absorbed as a code patch |
|
|
160
|
+
| Environmental, timing-dependent, or external | Document the investigation, implement handling (retry, timeout, clear error), add monitoring |
|
|
161
|
+
|
|
162
|
+
These four categories are exactly the values of `root_cause` in `.control/registry/defects.yaml`.
|
|
163
|
+
Phase 5 is where your verdict lands in that file.
|
|
164
|
+
|
|
165
|
+
The last row is real but rare. Most "no root cause" conclusions are incomplete investigations —
|
|
166
|
+
treat that verdict with suspicion in yourself.
|
|
167
|
+
|
|
168
|
+
## Red flags — stop and return to Phase 1
|
|
169
|
+
|
|
170
|
+
If you catch yourself thinking any of these, the process has already broken down:
|
|
171
|
+
|
|
172
|
+
| Thought | Reality |
|
|
173
|
+
|---|---|
|
|
174
|
+
| "Quick fix now, investigate later" | The first fix sets the pattern. There is no later. |
|
|
175
|
+
| "Just change X and see if it works" | That is guessing with extra steps. |
|
|
176
|
+
| "It's probably X, let me fix that" | Seeing a symptom is not understanding a cause. |
|
|
177
|
+
| "I'll skip the test and verify manually" | Untested fixes regress silently. |
|
|
178
|
+
| "Several changes at once saves time" | You will not know which one worked, or what else broke. |
|
|
179
|
+
| "The reference is long, I'll adapt the pattern" | Partial reading guarantees the next bug. |
|
|
180
|
+
| "One more fix attempt" (after 2+) | Three failures means the architecture is the problem. |
|
|
181
|
+
| "Emergency — no time for process" | Thrashing is slower. Always. |
|
|
182
|
+
|
|
183
|
+
Signals from the owner that mean the same thing: *"stop guessing"*, *"is that actually
|
|
184
|
+
happening?"*, *"will that show us anything?"*, *"we're stuck?"*
|
|
185
|
+
|
|
186
|
+
## Supporting techniques
|
|
187
|
+
|
|
188
|
+
| File | Use when |
|
|
189
|
+
|---|---|
|
|
190
|
+
| [references/root-cause-tracing.md](references/root-cause-tracing.md) | The error surfaces deep in a call stack and you must trace backward to the origin |
|
|
191
|
+
| [references/defense-in-depth.md](references/defense-in-depth.md) | Root cause is found and you are deciding where validation belongs |
|
|
192
|
+
| [references/condition-based-waiting.md](references/condition-based-waiting.md) | Flaky timing, arbitrary sleeps, race conditions |
|
|
193
|
+
| [references/find-polluter.sh](references/find-polluter.sh) | A test passes alone but fails in the suite — bisects to find the polluting test |
|