@antoneeo/agentic-sdlc-skill 1.36.0 → 1.37.0
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 +7 -0
- package/README.md +205 -204
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/scripts/init.js +6 -6
- package/skills/agentic-sdlc-skill/ENFORCEMENT.md +5 -5
- package/skills/agentic-sdlc-skill/SKILL.md +4 -3
- package/skills/agentic-sdlc-skill/architect.md +215 -215
- package/skills/agentic-sdlc-skill/debugging.md +107 -60
- package/skills/agentic-sdlc-skill/elicitation.md +216 -216
- package/skills/agentic-sdlc-skill/hybrid.md +106 -106
- package/skills/agentic-sdlc-skill/memory.md +88 -88
- package/skills/agentic-sdlc-skill/routing.md +28 -16
- package/skills/agentic-sdlc-skill/scripts/knowledge.py +2089 -2089
- package/skills/agentic-sdlc-skill/scripts/sdlc_check.py +71 -71
- package/skills/agentic-sdlc-skill/scripts/sdlc_core.py +6 -1
- package/skills/agentic-sdlc-skill/templates.md +4 -4
- package/skills/agentic-sdlc-skill/vision.md +245 -245
|
@@ -1,215 +1,215 @@
|
|
|
1
|
-
# The Architect Pass
|
|
2
|
-
|
|
3
|
-
Applies at L3, in phase 3, AFTER the spec elicitation and BEFORE the Impact is
|
|
4
|
-
drafted. It answers the one question the Impact cannot ask: *does the system
|
|
5
|
-
already have the components and services this feature needs?*
|
|
6
|
-
|
|
7
|
-
Why it exists: **a feature is not a unit of construction.** Left alone, an agent
|
|
8
|
-
designs the feature and builds whatever it lacks inside the feature's own code
|
|
9
|
-
path — so no component owns the capability, the next feature that needs it
|
|
10
|
-
rebuilds it differently, and the platform accretes feature-shaped code nobody can
|
|
11
|
-
reuse. That is myopia one level above the file: the change is complete, the tests
|
|
12
|
-
pass, and the architecture is worse.
|
|
13
|
-
|
|
14
|
-
## 1. State the feature as capabilities, not as files
|
|
15
|
-
|
|
16
|
-
Write what the system must be able to DO for this feature to exist — "persist a
|
|
17
|
-
draft across sessions", "notify a third party asynchronously", "authorize per
|
|
18
|
-
tenant". A capability is a verb over a domain noun. It names no file, no class and
|
|
19
|
-
no library: **that** is the decoupling. Files come later, in the Impact.
|
|
20
|
-
|
|
21
|
-
Two or three capabilities is a normal feature. When the list has one obvious entry
|
|
22
|
-
and it plainly exists, say so in one line **under the `## Capability Ledger`
|
|
23
|
-
heading, still naming the component and where it lives**, and move on — this pass
|
|
24
|
-
is a question to answer, not a form to fill. The heading is what makes a cheap
|
|
25
|
-
answer distinguishable from a skipped pass; a bare "everything already exists"
|
|
26
|
-
names nothing and is the **Paper ledger** anti-pattern, not the licence.
|
|
27
|
-
|
|
28
|
-
## 2. Rule each capability against the platform
|
|
29
|
-
|
|
30
|
-
One verdict per capability:
|
|
31
|
-
|
|
32
|
-
| Verdict | Meaning | What the row must carry |
|
|
33
|
-
|---|---|---|
|
|
34
|
-
| **EXISTS** | a component already owns this capability and covers the need | the component, where it lives (path / symbol), and the one guarantee you re-read it to confirm |
|
|
35
|
-
| **INADEQUATE** | a component owns it but does not cover the need | the same, plus the gap in one line |
|
|
36
|
-
| **MISSING** | no component owns it | the terms you searched, the tool, and the areas covered |
|
|
37
|
-
|
|
38
|
-
Read the **`## Component Map`** in `strategic/architecture.md` first — the project's
|
|
39
|
-
inventory of what owns which capability, kept so this pass does not re-derive the
|
|
40
|
-
platform from source every session.
|
|
41
|
-
|
|
42
|
-
**The map is a cache of evidence somebody already paid for. It lowers the COST of a
|
|
43
|
-
verdict, never the STANDARD of one.** Every verdict carries the same evidence
|
|
44
|
-
whether the map answered it or not; a hit means the search is already written down,
|
|
45
|
-
a miss means you pay full price. Reading a row does not excuse you from checking
|
|
46
|
-
that it is still true — the map is the index, the code is the evidence.
|
|
47
|
-
|
|
48
|
-
**Its silence is unread, not empty.** The map covers only the areas `audit/
|
|
49
|
-
audit_plan.md` marks ANALYZED — and that state is a claim someone made, not a fact
|
|
50
|
-
the tooling verified: marking asserts *the area was read closely enough to name the
|
|
51
|
-
capabilities it owns*, so an area marked after two greps is a false ANALYZED and
|
|
52
|
-
the person who wrote it owns the duplicate that follows. In an area still PENDING —
|
|
53
|
-
or SKIPPED, or absent from the plan entirely — **the map can never ground a MISSING
|
|
54
|
-
verdict.** Nothing there has been looked at yet, and "the inventory does not mention
|
|
55
|
-
it" is the reasoning that builds a second copy of a component that already exists.
|
|
56
|
-
|
|
57
|
-
**Searching for an owner** is text search first, symbol-graph second — in that
|
|
58
|
-
order, because you are looking for a name you do not know yet, and a call-hierarchy
|
|
59
|
-
tool needs a resolved symbol as *input*. Grep the repository (minus SKIPPED areas)
|
|
60
|
-
for the domain noun, at least two plausible synonyms, and the verb; then use the
|
|
61
|
-
symbol-graph tool to confirm or dismiss the candidates the search surfaced.
|
|
62
|
-
|
|
63
|
-
**The floor for a MISSING** is about triage, not term count: every hit that lands in
|
|
64
|
-
an unmapped area gets opened, or the MISSING is **provisional** and says so in its
|
|
65
|
-
row. Record what you ran — terms, tool, areas — and stop when the terms are
|
|
66
|
-
exhausted and no candidate remains unopened. A provisional MISSING is honest and
|
|
67
|
-
cheap; an unfalsifiable one is the same defect as an EXISTS with no symbol named.
|
|
68
|
-
|
|
69
|
-
**Understanding is never deferred; only WRITING the map is.** You may leave the rest
|
|
70
|
-
of the repository unmapped and grow the inventory feature by feature — you may not
|
|
71
|
-
leave unexamined anything this change touches or depends on. That blast zone is
|
|
72
|
-
understood now, at full standard, mapped or not. The incremental licence is about
|
|
73
|
-
the artifact, never about the comprehension.
|
|
74
|
-
|
|
75
|
-
Ground every verdict. An EXISTS with no named symbol is an assumption wearing a
|
|
76
|
-
verdict's clothes, and it is the row that breaks in implementation. A MISSING
|
|
77
|
-
declared without a real search is how duplication enters — the component may be
|
|
78
|
-
there under a name you did not guess. This is the DRY check at architecture level.
|
|
79
|
-
|
|
80
|
-
## 3. Design what is missing as a component, not as feature internals
|
|
81
|
-
|
|
82
|
-
INADEQUATE and MISSING produce design work of their own, governed by one rule:
|
|
83
|
-
|
|
84
|
-
**The component's contract is stated in the component's own vocabulary. The feature
|
|
85
|
-
is one consumer, never the owner.**
|
|
86
|
-
|
|
87
|
-
The test is mechanical: write the contract — what it does, what it takes, what it
|
|
88
|
-
guarantees — *without naming the feature*. If you cannot, the contract is
|
|
89
|
-
feature-shaped, and the second consumer will force it open. **Renaming the
|
|
90
|
-
feature's nouns is not stating the contract in the component's vocabulary**:
|
|
91
|
-
`store(ConfirmationPayload) -> id` described as "stores records by id" still fails.
|
|
92
|
-
The question the wording cannot dodge — *would a second plausible consumer have to
|
|
93
|
-
change this signature?* If yes it is feature-shaped, however it is phrased.
|
|
94
|
-
|
|
95
|
-
The opposite error is equally real: this is not a licence to build a framework.
|
|
96
|
-
Build for the need you have, at the size you need. What the rule constrains is the
|
|
97
|
-
contract's **vocabulary and ownership**, not its scope — a five-line component with
|
|
98
|
-
a clean contract satisfies it in full.
|
|
99
|
-
|
|
100
|
-
## 4. Decide the unit of change
|
|
101
|
-
|
|
102
|
-
A capability that needs building becomes **its own ANALYSIS, its own branch and its
|
|
103
|
-
own closure** when ANY of these holds:
|
|
104
|
-
|
|
105
|
-
- it will have more than one consumer, now or in the declared roadmap;
|
|
106
|
-
- **it can ship before this feature does** — merged and adopted on its own cadence,
|
|
107
|
-
with the feature still unfinished. (Not "buildable and testable on its own": §3
|
|
108
|
-
requires that of every component, so reading it that way makes the default branch
|
|
109
|
-
below unreachable and puts every five-line helper through its own L3.) IN: a
|
|
110
|
-
storage layer another team can adopt next sprint while this feature is still in
|
|
111
|
-
design. OUT: a helper nobody can use until the feature that motivated it lands;
|
|
112
|
-
- it carries its own risk surface: security, a public contract, a data model, or a
|
|
113
|
-
new dependency.
|
|
114
|
-
|
|
115
|
-
Otherwise it is a **phase inside this feature's plan** — the first phase, before the
|
|
116
|
-
feature consumes it — and it is still a component: own contract, own tests, never
|
|
117
|
-
inlined into the feature's code path. **The split rule decides the paperwork; it
|
|
118
|
-
never decides whether the component exists.**
|
|
119
|
-
|
|
120
|
-
When it does become its own unit, each document names the other: the feature's
|
|
121
|
-
ANALYSIS points at the component's, and the component's lists its consumers.
|
|
122
|
-
|
|
123
|
-
## 5. Order
|
|
124
|
-
|
|
125
|
-
The component is designed before the feature that consumes it, and normally built
|
|
126
|
-
and tested before it too. A feature blocked on a capability it does not have is not
|
|
127
|
-
"in progress" — it is a component task wearing a feature's name.
|
|
128
|
-
|
|
129
|
-
## Anti-patterns
|
|
130
|
-
|
|
131
|
-
- **Inlining** — the capability is implemented inside the feature's code path and no
|
|
132
|
-
component owns it. Symptom: the next feature that needs it must copy it or
|
|
133
|
-
refactor yours. This is the failure the pass exists to prevent.
|
|
134
|
-
- **Feature-shaped platform** — the component exists, but its contract speaks the
|
|
135
|
-
feature's vocabulary. Symptom: the second consumer forces a contract change.
|
|
136
|
-
- **Silent degradation** — a capability comes out MISSING, nobody wants to build it,
|
|
137
|
-
so the feature is quietly reshaped around what exists and ships as less than what
|
|
138
|
-
was asked. The reduced benefit must be surfaced to the user as a scope change and
|
|
139
|
-
recorded in the ANALYSIS; absorbing it silently is the Vision-divergence rule
|
|
140
|
-
broken one level down.
|
|
141
|
-
- **Speculative platform** — a general framework built for a single known need.
|
|
142
|
-
- **Paper ledger** — every row EXISTS, nothing named. Unfalsifiable, exactly like a
|
|
143
|
-
review that reports "I checked".
|
|
144
|
-
- **Empty-map MISSING** — ruling a capability MISSING because the Component Map is
|
|
145
|
-
silent about it, in an area nobody has analyzed yet. The map's silence is
|
|
146
|
-
*unread*, not *empty*. On a project the methodology has just arrived in, the map
|
|
147
|
-
is nearly all silence, and this is the anti-pattern that duplicates the existing
|
|
148
|
-
codebase one component at a time.
|
|
149
|
-
|
|
150
|
-
## Where the output is recorded
|
|
151
|
-
|
|
152
|
-
Standalone: the `## Capability Ledger` section of the ANALYSIS (`templates.md`),
|
|
153
|
-
immediately before `## Impact`, which it feeds — every INADEQUATE or MISSING row
|
|
154
|
-
lands there as files to create or change. The closure review maps the ledger row by
|
|
155
|
-
row (`review.md`).
|
|
156
|
-
|
|
157
|
-
**A component that gets built lands in the `## Component Map`** of
|
|
158
|
-
`strategic/architecture.md`, in the same closure — capability owned, contract,
|
|
159
|
-
where it lives. This is the loop that makes the pass repeatable instead of
|
|
160
|
-
per-session: the ledger asks the map what exists, so a component the map never
|
|
161
|
-
learned about is one the next feature rules MISSING and builds a second time. The
|
|
162
|
-
trigger is the component's birth, not a stack change (Write Triggers).
|
|
163
|
-
|
|
164
|
-
**So does a component you merely discovered.** When the pass searches an unmapped
|
|
165
|
-
area and finds an existing owner, write that row too, then `sdlc_check.py mark` the
|
|
166
|
-
area you covered — **in that order, and never the mark without the rows.** Marking
|
|
167
|
-
an area ANALYZED while its owners stay unwritten is the worst of both states: the
|
|
168
|
-
area now looks read, so the map's silence there becomes groundable, and the next
|
|
169
|
-
feature rules MISSING and builds a duplicate — lawfully. What a mark asserts is
|
|
170
|
-
exactly this: *the area was read closely enough to name the capabilities it owns.*
|
|
171
|
-
The map then grows by the feature that needed the knowledge instead of by an
|
|
172
|
-
up-front sweep — the understanding was paid for either way, and this is the step
|
|
173
|
-
that stops the next session paying for it again.
|
|
174
|
-
|
|
175
|
-
Hybrid: the ledger goes in the `E-ISP`, above its Impacted Components map. A
|
|
176
|
-
capability split out as its own unit of change gets its own `E-ISP`/`E-TDD`, and the
|
|
177
|
-
feature's `E-ISP` names it as a dependency.
|
|
178
|
-
|
|
179
|
-
## Mechanical backstops
|
|
180
|
-
|
|
181
|
-
Prose is not enforcement; these are the checks that notice when the pass did not
|
|
182
|
-
run or its output rotted. Both are **advisories** — printed as `[note]`, never
|
|
183
|
-
counted as warnings, and never failing a build, **not even under `--strict`**. That
|
|
184
|
-
is deliberate: the ceremony budget accepted for this pass was a signal, and a
|
|
185
|
-
warning that reddens a pipeline is a gate under another name.
|
|
186
|
-
|
|
187
|
-
- **Skipped pass**: `validate` notes an L3 ANALYSIS started on/after 2026-07-28
|
|
188
|
-
that lacks `## Capability Ledger`. Grandfathered by `start_date` alone —
|
|
189
|
-
analyses born before the pass existed never nag — and deliberately NOT by
|
|
190
|
-
status: closure flips the ANALYSIS to COMPLETED *before* `check` runs, so a
|
|
191
|
-
status filter would silence the backstop at the exact moment the process
|
|
192
|
-
mandates the validator.
|
|
193
|
-
- **Rotting map**: `validate` resolves every path-shaped ref in the Component
|
|
194
|
-
Map's `Where` column — a path that no longer exists, or a `#symbol` no longer
|
|
195
|
-
present as a whole word in the file, is flagged; so is a map whose rows carry
|
|
196
|
-
no checkable path at all, or whose header has no `Where` column (an inert check
|
|
197
|
-
reported as a clean one is the same defect as an unread map reported as empty).
|
|
198
|
-
This is the map's equivalent of the guides' `source_hash`, with the same honest
|
|
199
|
-
limit: it proves the ref resolves, never that the row still describes the
|
|
200
|
-
component correctly.
|
|
201
|
-
- **A mark nobody paid for**: `validate` notes an area the audit plan marks
|
|
202
|
-
ANALYZED that owns no Component Map row. Marking is one cheap command and it is
|
|
203
|
-
what converts the map's silence into a groundable MISSING — so this is the other
|
|
204
|
-
half of the loop, the check that a mark asserted something real.
|
|
205
|
-
- **Adherence** (non-gating, **skill development only** — `evals/` is not shipped
|
|
206
|
-
in the installed package): `architect_rules_before_impact.md` runs the pass
|
|
207
|
-
cold; `unmapped_never_grounds_missing.md` sets the brownfield trap — an existing
|
|
208
|
-
component in a PENDING area, where ruling MISSING from the map's silence is the
|
|
209
|
-
failure.
|
|
210
|
-
|
|
211
|
-
## Below L3
|
|
212
|
-
|
|
213
|
-
L1 and L2 do not run this pass. A capability discovered MISSING during L2 work is
|
|
214
|
-
itself an escalation trigger: stop, reclassify to L3, declare it (Rule Zero). "The
|
|
215
|
-
component was not there" is never a reason to build it inside an L2.
|
|
1
|
+
# The Architect Pass
|
|
2
|
+
|
|
3
|
+
Applies at L3, in phase 3, AFTER the spec elicitation and BEFORE the Impact is
|
|
4
|
+
drafted. It answers the one question the Impact cannot ask: *does the system
|
|
5
|
+
already have the components and services this feature needs?*
|
|
6
|
+
|
|
7
|
+
Why it exists: **a feature is not a unit of construction.** Left alone, an agent
|
|
8
|
+
designs the feature and builds whatever it lacks inside the feature's own code
|
|
9
|
+
path — so no component owns the capability, the next feature that needs it
|
|
10
|
+
rebuilds it differently, and the platform accretes feature-shaped code nobody can
|
|
11
|
+
reuse. That is myopia one level above the file: the change is complete, the tests
|
|
12
|
+
pass, and the architecture is worse.
|
|
13
|
+
|
|
14
|
+
## 1. State the feature as capabilities, not as files
|
|
15
|
+
|
|
16
|
+
Write what the system must be able to DO for this feature to exist — "persist a
|
|
17
|
+
draft across sessions", "notify a third party asynchronously", "authorize per
|
|
18
|
+
tenant". A capability is a verb over a domain noun. It names no file, no class and
|
|
19
|
+
no library: **that** is the decoupling. Files come later, in the Impact.
|
|
20
|
+
|
|
21
|
+
Two or three capabilities is a normal feature. When the list has one obvious entry
|
|
22
|
+
and it plainly exists, say so in one line **under the `## Capability Ledger`
|
|
23
|
+
heading, still naming the component and where it lives**, and move on — this pass
|
|
24
|
+
is a question to answer, not a form to fill. The heading is what makes a cheap
|
|
25
|
+
answer distinguishable from a skipped pass; a bare "everything already exists"
|
|
26
|
+
names nothing and is the **Paper ledger** anti-pattern, not the licence.
|
|
27
|
+
|
|
28
|
+
## 2. Rule each capability against the platform
|
|
29
|
+
|
|
30
|
+
One verdict per capability:
|
|
31
|
+
|
|
32
|
+
| Verdict | Meaning | What the row must carry |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| **EXISTS** | a component already owns this capability and covers the need | the component, where it lives (path / symbol), and the one guarantee you re-read it to confirm |
|
|
35
|
+
| **INADEQUATE** | a component owns it but does not cover the need | the same, plus the gap in one line |
|
|
36
|
+
| **MISSING** | no component owns it | the terms you searched, the tool, and the areas covered |
|
|
37
|
+
|
|
38
|
+
Read the **`## Component Map`** in `strategic/architecture.md` first — the project's
|
|
39
|
+
inventory of what owns which capability, kept so this pass does not re-derive the
|
|
40
|
+
platform from source every session.
|
|
41
|
+
|
|
42
|
+
**The map is a cache of evidence somebody already paid for. It lowers the COST of a
|
|
43
|
+
verdict, never the STANDARD of one.** Every verdict carries the same evidence
|
|
44
|
+
whether the map answered it or not; a hit means the search is already written down,
|
|
45
|
+
a miss means you pay full price. Reading a row does not excuse you from checking
|
|
46
|
+
that it is still true — the map is the index, the code is the evidence.
|
|
47
|
+
|
|
48
|
+
**Its silence is unread, not empty.** The map covers only the areas `audit/
|
|
49
|
+
audit_plan.md` marks ANALYZED — and that state is a claim someone made, not a fact
|
|
50
|
+
the tooling verified: marking asserts *the area was read closely enough to name the
|
|
51
|
+
capabilities it owns*, so an area marked after two greps is a false ANALYZED and
|
|
52
|
+
the person who wrote it owns the duplicate that follows. In an area still PENDING —
|
|
53
|
+
or SKIPPED, or absent from the plan entirely — **the map can never ground a MISSING
|
|
54
|
+
verdict.** Nothing there has been looked at yet, and "the inventory does not mention
|
|
55
|
+
it" is the reasoning that builds a second copy of a component that already exists.
|
|
56
|
+
|
|
57
|
+
**Searching for an owner** is text search first, symbol-graph second — in that
|
|
58
|
+
order, because you are looking for a name you do not know yet, and a call-hierarchy
|
|
59
|
+
tool needs a resolved symbol as *input*. Grep the repository (minus SKIPPED areas)
|
|
60
|
+
for the domain noun, at least two plausible synonyms, and the verb; then use the
|
|
61
|
+
symbol-graph tool to confirm or dismiss the candidates the search surfaced.
|
|
62
|
+
|
|
63
|
+
**The floor for a MISSING** is about triage, not term count: every hit that lands in
|
|
64
|
+
an unmapped area gets opened, or the MISSING is **provisional** and says so in its
|
|
65
|
+
row. Record what you ran — terms, tool, areas — and stop when the terms are
|
|
66
|
+
exhausted and no candidate remains unopened. A provisional MISSING is honest and
|
|
67
|
+
cheap; an unfalsifiable one is the same defect as an EXISTS with no symbol named.
|
|
68
|
+
|
|
69
|
+
**Understanding is never deferred; only WRITING the map is.** You may leave the rest
|
|
70
|
+
of the repository unmapped and grow the inventory feature by feature — you may not
|
|
71
|
+
leave unexamined anything this change touches or depends on. That blast zone is
|
|
72
|
+
understood now, at full standard, mapped or not. The incremental licence is about
|
|
73
|
+
the artifact, never about the comprehension.
|
|
74
|
+
|
|
75
|
+
Ground every verdict. An EXISTS with no named symbol is an assumption wearing a
|
|
76
|
+
verdict's clothes, and it is the row that breaks in implementation. A MISSING
|
|
77
|
+
declared without a real search is how duplication enters — the component may be
|
|
78
|
+
there under a name you did not guess. This is the DRY check at architecture level.
|
|
79
|
+
|
|
80
|
+
## 3. Design what is missing as a component, not as feature internals
|
|
81
|
+
|
|
82
|
+
INADEQUATE and MISSING produce design work of their own, governed by one rule:
|
|
83
|
+
|
|
84
|
+
**The component's contract is stated in the component's own vocabulary. The feature
|
|
85
|
+
is one consumer, never the owner.**
|
|
86
|
+
|
|
87
|
+
The test is mechanical: write the contract — what it does, what it takes, what it
|
|
88
|
+
guarantees — *without naming the feature*. If you cannot, the contract is
|
|
89
|
+
feature-shaped, and the second consumer will force it open. **Renaming the
|
|
90
|
+
feature's nouns is not stating the contract in the component's vocabulary**:
|
|
91
|
+
`store(ConfirmationPayload) -> id` described as "stores records by id" still fails.
|
|
92
|
+
The question the wording cannot dodge — *would a second plausible consumer have to
|
|
93
|
+
change this signature?* If yes it is feature-shaped, however it is phrased.
|
|
94
|
+
|
|
95
|
+
The opposite error is equally real: this is not a licence to build a framework.
|
|
96
|
+
Build for the need you have, at the size you need. What the rule constrains is the
|
|
97
|
+
contract's **vocabulary and ownership**, not its scope — a five-line component with
|
|
98
|
+
a clean contract satisfies it in full.
|
|
99
|
+
|
|
100
|
+
## 4. Decide the unit of change
|
|
101
|
+
|
|
102
|
+
A capability that needs building becomes **its own ANALYSIS, its own branch and its
|
|
103
|
+
own closure** when ANY of these holds:
|
|
104
|
+
|
|
105
|
+
- it will have more than one consumer, now or in the declared roadmap;
|
|
106
|
+
- **it can ship before this feature does** — merged and adopted on its own cadence,
|
|
107
|
+
with the feature still unfinished. (Not "buildable and testable on its own": §3
|
|
108
|
+
requires that of every component, so reading it that way makes the default branch
|
|
109
|
+
below unreachable and puts every five-line helper through its own L3.) IN: a
|
|
110
|
+
storage layer another team can adopt next sprint while this feature is still in
|
|
111
|
+
design. OUT: a helper nobody can use until the feature that motivated it lands;
|
|
112
|
+
- it carries its own risk surface: security, a public contract, a data model, or a
|
|
113
|
+
new dependency.
|
|
114
|
+
|
|
115
|
+
Otherwise it is a **phase inside this feature's plan** — the first phase, before the
|
|
116
|
+
feature consumes it — and it is still a component: own contract, own tests, never
|
|
117
|
+
inlined into the feature's code path. **The split rule decides the paperwork; it
|
|
118
|
+
never decides whether the component exists.**
|
|
119
|
+
|
|
120
|
+
When it does become its own unit, each document names the other: the feature's
|
|
121
|
+
ANALYSIS points at the component's, and the component's lists its consumers.
|
|
122
|
+
|
|
123
|
+
## 5. Order
|
|
124
|
+
|
|
125
|
+
The component is designed before the feature that consumes it, and normally built
|
|
126
|
+
and tested before it too. A feature blocked on a capability it does not have is not
|
|
127
|
+
"in progress" — it is a component task wearing a feature's name.
|
|
128
|
+
|
|
129
|
+
## Anti-patterns
|
|
130
|
+
|
|
131
|
+
- **Inlining** — the capability is implemented inside the feature's code path and no
|
|
132
|
+
component owns it. Symptom: the next feature that needs it must copy it or
|
|
133
|
+
refactor yours. This is the failure the pass exists to prevent.
|
|
134
|
+
- **Feature-shaped platform** — the component exists, but its contract speaks the
|
|
135
|
+
feature's vocabulary. Symptom: the second consumer forces a contract change.
|
|
136
|
+
- **Silent degradation** — a capability comes out MISSING, nobody wants to build it,
|
|
137
|
+
so the feature is quietly reshaped around what exists and ships as less than what
|
|
138
|
+
was asked. The reduced benefit must be surfaced to the user as a scope change and
|
|
139
|
+
recorded in the ANALYSIS; absorbing it silently is the Vision-divergence rule
|
|
140
|
+
broken one level down.
|
|
141
|
+
- **Speculative platform** — a general framework built for a single known need.
|
|
142
|
+
- **Paper ledger** — every row EXISTS, nothing named. Unfalsifiable, exactly like a
|
|
143
|
+
review that reports "I checked".
|
|
144
|
+
- **Empty-map MISSING** — ruling a capability MISSING because the Component Map is
|
|
145
|
+
silent about it, in an area nobody has analyzed yet. The map's silence is
|
|
146
|
+
*unread*, not *empty*. On a project the methodology has just arrived in, the map
|
|
147
|
+
is nearly all silence, and this is the anti-pattern that duplicates the existing
|
|
148
|
+
codebase one component at a time.
|
|
149
|
+
|
|
150
|
+
## Where the output is recorded
|
|
151
|
+
|
|
152
|
+
Standalone: the `## Capability Ledger` section of the ANALYSIS (`templates.md`),
|
|
153
|
+
immediately before `## Impact`, which it feeds — every INADEQUATE or MISSING row
|
|
154
|
+
lands there as files to create or change. The closure review maps the ledger row by
|
|
155
|
+
row (`review.md`).
|
|
156
|
+
|
|
157
|
+
**A component that gets built lands in the `## Component Map`** of
|
|
158
|
+
`strategic/architecture.md`, in the same closure — capability owned, contract,
|
|
159
|
+
where it lives. This is the loop that makes the pass repeatable instead of
|
|
160
|
+
per-session: the ledger asks the map what exists, so a component the map never
|
|
161
|
+
learned about is one the next feature rules MISSING and builds a second time. The
|
|
162
|
+
trigger is the component's birth, not a stack change (Write Triggers).
|
|
163
|
+
|
|
164
|
+
**So does a component you merely discovered.** When the pass searches an unmapped
|
|
165
|
+
area and finds an existing owner, write that row too, then `sdlc_check.py mark` the
|
|
166
|
+
area you covered — **in that order, and never the mark without the rows.** Marking
|
|
167
|
+
an area ANALYZED while its owners stay unwritten is the worst of both states: the
|
|
168
|
+
area now looks read, so the map's silence there becomes groundable, and the next
|
|
169
|
+
feature rules MISSING and builds a duplicate — lawfully. What a mark asserts is
|
|
170
|
+
exactly this: *the area was read closely enough to name the capabilities it owns.*
|
|
171
|
+
The map then grows by the feature that needed the knowledge instead of by an
|
|
172
|
+
up-front sweep — the understanding was paid for either way, and this is the step
|
|
173
|
+
that stops the next session paying for it again.
|
|
174
|
+
|
|
175
|
+
Hybrid: the ledger goes in the `E-ISP`, above its Impacted Components map. A
|
|
176
|
+
capability split out as its own unit of change gets its own `E-ISP`/`E-TDD`, and the
|
|
177
|
+
feature's `E-ISP` names it as a dependency.
|
|
178
|
+
|
|
179
|
+
## Mechanical backstops
|
|
180
|
+
|
|
181
|
+
Prose is not enforcement; these are the checks that notice when the pass did not
|
|
182
|
+
run or its output rotted. Both are **advisories** — printed as `[note]`, never
|
|
183
|
+
counted as warnings, and never failing a build, **not even under `--strict`**. That
|
|
184
|
+
is deliberate: the ceremony budget accepted for this pass was a signal, and a
|
|
185
|
+
warning that reddens a pipeline is a gate under another name.
|
|
186
|
+
|
|
187
|
+
- **Skipped pass**: `validate` notes an L3 ANALYSIS started on/after 2026-07-28
|
|
188
|
+
that lacks `## Capability Ledger`. Grandfathered by `start_date` alone —
|
|
189
|
+
analyses born before the pass existed never nag — and deliberately NOT by
|
|
190
|
+
status: closure flips the ANALYSIS to COMPLETED *before* `check` runs, so a
|
|
191
|
+
status filter would silence the backstop at the exact moment the process
|
|
192
|
+
mandates the validator.
|
|
193
|
+
- **Rotting map**: `validate` resolves every path-shaped ref in the Component
|
|
194
|
+
Map's `Where` column — a path that no longer exists, or a `#symbol` no longer
|
|
195
|
+
present as a whole word in the file, is flagged; so is a map whose rows carry
|
|
196
|
+
no checkable path at all, or whose header has no `Where` column (an inert check
|
|
197
|
+
reported as a clean one is the same defect as an unread map reported as empty).
|
|
198
|
+
This is the map's equivalent of the guides' `source_hash`, with the same honest
|
|
199
|
+
limit: it proves the ref resolves, never that the row still describes the
|
|
200
|
+
component correctly.
|
|
201
|
+
- **A mark nobody paid for**: `validate` notes an area the audit plan marks
|
|
202
|
+
ANALYZED that owns no Component Map row. Marking is one cheap command and it is
|
|
203
|
+
what converts the map's silence into a groundable MISSING — so this is the other
|
|
204
|
+
half of the loop, the check that a mark asserted something real.
|
|
205
|
+
- **Adherence** (non-gating, **skill development only** — `evals/` is not shipped
|
|
206
|
+
in the installed package): `architect_rules_before_impact.md` runs the pass
|
|
207
|
+
cold; `unmapped_never_grounds_missing.md` sets the brownfield trap — an existing
|
|
208
|
+
component in a PENDING area, where ruling MISSING from the map's silence is the
|
|
209
|
+
failure.
|
|
210
|
+
|
|
211
|
+
## Below L3
|
|
212
|
+
|
|
213
|
+
L1 and L2 do not run this pass. A capability discovered MISSING during L2 work is
|
|
214
|
+
itself an escalation trigger: stop, reclassify to L3, declare it (Rule Zero). "The
|
|
215
|
+
component was not there" is never a reason to build it inside an L2.
|
|
@@ -1,71 +1,118 @@
|
|
|
1
1
|
# Systematic Debugging
|
|
2
2
|
|
|
3
|
-
Applies to bugs classified L2 or L3
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Applies to bugs classified L2 or L3, from the start of their analysis, including
|
|
4
|
+
defects discovered during implementation. Investigate the observed failure before
|
|
5
|
+
proposing a definitive fix. A suspicious source-code pattern is a hypothesis, not
|
|
6
|
+
proof that it caused this incident.
|
|
6
7
|
|
|
7
8
|
## Method
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
3. **Root cause — name the mechanism.** State in one sentence why the
|
|
19
|
-
observed behavior happens, tracing the actual execution path. Trace it by
|
|
20
|
-
enumerating the real callers/consumers of each suspect symbol with the best
|
|
21
|
-
symbol-graph tool your toolchain offers — an IDE/LSP call hierarchy or a
|
|
22
|
-
find-usages / call-graph capability — not text search; `grep`
|
|
23
|
-
under-enumerates and hides the very consumer that breaks. **MUST NOT
|
|
24
|
-
patch a symptom without naming the mechanism; why: symptom patches recur
|
|
25
|
-
and stack** — the same underlying defect resurfaces elsewhere, and each
|
|
26
|
-
unexplained patch makes the next investigation harder, not easier.
|
|
27
|
-
4. **Fix at the cause**, not at the symptom identified in step 1.
|
|
28
|
-
5. **Write a regression test that FAILS on the old code** (verify this
|
|
29
|
-
before applying the fix, or by temporarily reverting it) and passes after.
|
|
30
|
-
A regression test that was never confirmed to fail proves nothing.
|
|
31
|
-
6. **Run the relevant suite for collateral.** A root-cause fix can change
|
|
32
|
-
behavior other callers depend on; enumerate those callers with the
|
|
33
|
-
symbol-graph (step 3), not from memory, and check them before closing.
|
|
34
|
-
|
|
35
|
-
**Capture the model you had to rebuild.** If naming the mechanism (step 3) forced
|
|
36
|
-
you to reconstruct the mental model of a complex component that no guide documents —
|
|
37
|
-
tracing it across files because it was written down nowhere — that is the
|
|
38
|
-
comprehension trigger (`guides.md` §1): it is your duty to write the `source_kind:
|
|
39
|
-
code` guide, so the next debugger starts with the map you just paid to build.
|
|
40
|
-
|
|
41
|
-
**Chronic fragility is a signal, not a task to grind.** If a component breaks
|
|
42
|
-
*repeatedly across sessions* and its complexity is no longer under control, stop
|
|
43
|
-
treating each break as an isolated bug — that pattern has two duties, not one:
|
|
44
|
-
1. **Understand** — write the `source_kind: code` comprehension guide (above) so the
|
|
45
|
-
understanding stops evaporating between sessions.
|
|
46
|
-
2. **Escalate the complexity itself** — STOP stacking patches on a component nobody
|
|
47
|
-
fully understands. Flag the fragility as tech debt and propose a dedicated
|
|
48
|
-
**refactor as its own L3** (Vision-gated), instead of a fourth fix. Continuing to
|
|
49
|
-
patch a component you keep breaking is the anti-pattern, not the fix.
|
|
10
|
+
1. **Establish the facts.** State expected versus observed behavior, affected
|
|
11
|
+
environment, timing and last known working state. Read available local incident
|
|
12
|
+
evidence first: relevant logs, stack traces, request/response, effective
|
|
13
|
+
configuration and service state. Preserve evidence before restarts or changes
|
|
14
|
+
erase it; urgent containment may come first, but label it temporary and record
|
|
15
|
+
what evidence could not be preserved. Logs may be partial or misleading: check
|
|
16
|
+
their scope and time window. Do not exhaust every log or wait for nonexistent
|
|
17
|
+
logs when a direct observation is available. Read only what is needed, redact
|
|
18
|
+
secrets/personal data in reports, and keep sensitive raw logs out of project docs.
|
|
50
19
|
|
|
51
|
-
|
|
20
|
+
2. **Maintain the hypotheses.** Keep a small register in the existing L2
|
|
21
|
+
mini-analysis or L3 ANALYSIS/Action Plan, not a new mandatory document:
|
|
22
|
+
|
|
23
|
+
| Cause hypothesis | Evidence for/against | Likelihood and basis | Verification cost | Check and result | Current hypothesis status |
|
|
24
|
+
|---|---|---|---|---|---|
|
|
25
|
+
|
|
26
|
+
Use high/medium/low or unknown likelihood and rough costs, with reasons; do not
|
|
27
|
+
invent numerical probabilities. Prefer hypotheses that are both more likely
|
|
28
|
+
and cheaper to verify. When those criteria conflict, choose a check with useful
|
|
29
|
+
discrimination between the remaining explanations and justify that choice.
|
|
30
|
+
State what observation would support or invalidate the hypothesis before the
|
|
31
|
+
check. Record each result, update evidence/status and reorder after every check.
|
|
32
|
+
An inconclusive check leaves the hypothesis open; distinguish a check's outcome
|
|
33
|
+
from the hypothesis's accumulated status (open, confirmed, invalidated).
|
|
34
|
+
Do not repeat an invalidated hypothesis unless new evidence reopens it.
|
|
35
|
+
|
|
36
|
+
3. **Test and trace the mechanism.** Reproduce and isolate the smallest faithful
|
|
37
|
+
failing case when feasible; bisect inputs, paths or changes when informative.
|
|
38
|
+
Skip a reproduction already known to omit the incident's causal conditions;
|
|
39
|
+
choose a faithful alternative or disclose the gap. Stop diagnostic checks when
|
|
40
|
+
further results cannot change the causal or fix decision; this does not replace
|
|
41
|
+
the regression and recovery verification in step 5.
|
|
42
|
+
If the incident is intermittent or inaccessible, use captured traces and
|
|
43
|
+
targeted diagnostic observations instead of declaring investigation impossible.
|
|
44
|
+
Add minimal instrumentation when evidence is insufficient. Prefer read-only
|
|
45
|
+
checks; run state-changing experiments in a controlled environment under the
|
|
46
|
+
existing authorization boundaries. Read source to answer a concrete question
|
|
47
|
+
arising from evidence, then check its predictions against actual execution.
|
|
48
|
+
A static call graph identifies possible consumers, not the executed path.
|
|
49
|
+
|
|
50
|
+
Use the **five whys** to deepen supported causal links, not to force five
|
|
51
|
+
answers or a single linear cause. Each unsupported answer becomes a hypothesis
|
|
52
|
+
in the register. Allow interacting causes; distinguish why the failure happened
|
|
53
|
+
from why prevention or detection missed it. Stop when the actionable causal
|
|
54
|
+
mechanism is supported, or state the evidence gap instead of inventing a cause.
|
|
55
|
+
Before a definitive fix, name the mechanism and evidence connecting it to this
|
|
56
|
+
failure; explain which alternatives were invalidated and which remain open.
|
|
57
|
+
Missing logs or a passing unrelated test do not invalidate a hypothesis.
|
|
58
|
+
|
|
59
|
+
4. **Correct the design with Poka-Yoke.** Fix the responsible code, configuration
|
|
60
|
+
or infrastructure; do not force a code edit for an environmental cause.
|
|
61
|
+
Enforce the invariant where the responsibility belongs: prevent the invalid
|
|
62
|
+
condition, or detect and reject it immediately with an explicit outcome when
|
|
63
|
+
prevention is infeasible. Preserve legitimate behavior; a blanket rejection or
|
|
64
|
+
crash is not universally appropriate. Prefer the smallest coherent correction
|
|
65
|
+
over a case-specific exception, duplicated guard, silent fallback or speculative
|
|
66
|
+
broad refactor. Temporary containment is not a definitive fix.
|
|
67
|
+
|
|
68
|
+
Before editing, enumerate affected consumers using the available symbol graph
|
|
69
|
+
and a text coverage probe; reconcile differences and state coverage limits.
|
|
70
|
+
With no graph available, use text/targeted reads and disclose incomplete coverage
|
|
71
|
+
rather than guessing completeness. Apply existing triage/design gates if scope
|
|
72
|
+
expands. Mandatory design verification, preserving this wording verbatim:
|
|
52
73
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
> Dopo la correzione il software deve essere fatto come se fosse stato progettato senza quel difetto
|
|
75
|
+
|
|
76
|
+
Explain how the fix satisfies it: the correct owner enforces the invariant,
|
|
77
|
+
the same failure is prevented or detected at origin, no ad hoc exception is
|
|
78
|
+
needed, and valid consumer behavior is preserved. Disclose residual compromises;
|
|
79
|
+
the sentence does not authorize redesign beyond the confirmed defect's scope.
|
|
80
|
+
|
|
81
|
+
5. **Verify the correction and collateral.** Follow `tdd.md` for implementation:
|
|
82
|
+
confirm a regression test fails for this mechanism on the old implementation
|
|
83
|
+
and passes after the fix. Verify the Poka-Yoke against invalid and valid cases,
|
|
84
|
+
relevant neighboring cases, and concurrency/retry/order where the mechanism
|
|
85
|
+
involves them. Run the relevant consumer suite after the final change.
|
|
86
|
+
If the original incident cannot be replayed, distinguish controlled mechanism
|
|
87
|
+
tests from incident recovery evidence and report remaining uncertainty; do not
|
|
88
|
+
waive available regression tests or claim an unperformed verification.
|
|
89
|
+
|
|
90
|
+
**Capture the model you had to rebuild.** If tracing the cause reconstructed a
|
|
91
|
+
complex component with no CURRENT comprehension guide, write its `source_kind:
|
|
92
|
+
code` guide under `guides.md` §1. Keep evidence and invariants, not sensitive logs.
|
|
93
|
+
|
|
94
|
+
**Chronic fragility is a signal, not a task to grind.** If the component repeatedly
|
|
95
|
+
breaks across sessions and complexity is no longer controlled, preserve its model
|
|
96
|
+
in that guide and surface the debt. Propose a dedicated Vision-gated L3 refactor
|
|
97
|
+
instead of stacking patches; do not silently expand the current fix into it.
|
|
98
|
+
|
|
99
|
+
## Circuit breaker integration
|
|
58
100
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
101
|
+
After three consecutive attempts without new diagnostic information or progress,
|
|
102
|
+
STOP varying the same guess. Audit the evidence, register and checks: did a result
|
|
103
|
+
actually invalidate the hypothesis, did the test reproduce the relevant conditions,
|
|
104
|
+
and was the mechanism confirmed rather than merely plausible? Restart from the
|
|
105
|
+
earliest unsupported step. If still stuck after that restart, ask the user for
|
|
106
|
+
instructions with observed facts, checks/results, invalidated and open hypotheses,
|
|
107
|
+
the evidence gap and any temporary containment. More guesses are not progress.
|
|
62
108
|
|
|
63
109
|
## Anti-patterns
|
|
64
110
|
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
111
|
+
- Source-first speculation: patching a plausible defect without tying it to the incident.
|
|
112
|
+
- Shotgun debugging: changing several things at once without a discriminating check.
|
|
113
|
+
- Guess stacking: retaining an unverified fix while adding another.
|
|
114
|
+
- Register theater: invented likelihoods, repeated cheap but uninformative checks,
|
|
115
|
+
or check failure presented as hypothesis falsification without adequate coverage.
|
|
116
|
+
- Five invented whys: unsupported causal links, or forcing one root on interacting causes.
|
|
117
|
+
- Symptom exceptions: suppressing one event or input instead of correcting its invariant.
|
|
118
|
+
- "Fixed but can't say why": closure without causal evidence and the mandatory design check.
|