@dzhechkov/skills-feature-adr 1.3.41 → 1.3.42
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 +21 -0
- package/package.json +1 -1
- package/templates/.claude/skills/feature-adr/SKILL.md +3 -1
- package/templates/.claude/skills/feature-adr/modules/00-complexity-router.md +8 -1
- package/templates/.claude/skills/feature-adr/modules/03-adr.md +150 -60
- package/templates/.claude/skills/feature-adr/modules/08-qe.md +35 -0
- package/templates/.claude/skills/feature-adr/references/adr-template.md +112 -56
- package/templates/.claude/skills/feature-adr/references/complexity-matrix.md +6 -2
- package/templates/.claude/workflows/feature-adr.js +45 -10
package/README.md
CHANGED
|
@@ -347,6 +347,27 @@ gate — not discovered in production.
|
|
|
347
347
|
|
|
348
348
|
*\* Extended skills (marked with \*) are only available with `--full-qe-extended`*
|
|
349
349
|
|
|
350
|
+
### ADR quality gate (Step 3 generates → Step 8 enforces)
|
|
351
|
+
|
|
352
|
+
Step 3 and Step 8 share an ADR best-practices contract distilled from the
|
|
353
|
+
[architecture-decision-record monograph](https://github.com/architecture-decision-record/architecture-decision-record):
|
|
354
|
+
|
|
355
|
+
- **Step 3** emits a **MADR-structured** ADR — invariant core (Title/Status/Context/Decision/Consequences),
|
|
356
|
+
ranked **Decision Drivers**, **Considered Options** (the chosen approach framed as an option alongside the
|
|
357
|
+
rejected ones, symmetric pros/cons), **Rationale** mapped to drivers, negative consequences + follow-up
|
|
358
|
+
links + after-action review, a **`## Confirmation`** stanza (method, monitoring, success metric, owner)
|
|
359
|
+
naming the load-bearing property, and a **`## Links`** traceability block. Template weight is tier-mapped:
|
|
360
|
+
S/M → Nygard/ITD-lightweight, L/XL → MADR + Confirmation.
|
|
361
|
+
- **Step 8** runs a **13-point ADR fitness checklist** (`qe-code-reviewer`) against every generated ADR and
|
|
362
|
+
**fails the gate** on any miss — decision-shaped title, controlled-vocabulary Status + reversibility,
|
|
363
|
+
neutral Context-before-Decision, symmetric options, driver-mapped rationale, concrete/testable decision,
|
|
364
|
+
negative consequences, traceability links, no placeholder, and **rejects explainer-masquerading-as-ADR**.
|
|
365
|
+
The **Confirmation→test link is load-bearing**: if the named safety property has no automated test the ADR
|
|
366
|
+
grades no better than C.
|
|
367
|
+
|
|
368
|
+
The pipeline **dog-foods** this: a harness test runs the gate against feature-adr's own generated ADR, so a
|
|
369
|
+
Step-3↔Step-8 drift fails CI rather than shipping.
|
|
370
|
+
|
|
350
371
|
### The `Model` / `Fable?` columns — read this before swapping models
|
|
351
372
|
|
|
352
373
|
The `Model` column is the **default recommendation, fully overridable** — the routing rule is
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dzhechkov/skills-feature-adr",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.42",
|
|
4
4
|
"description": "Adaptive Feature Development skill pack for Claude Code — 11-step pipeline with Complexity Router (S/M/L/XL), ADR-driven architecture, 15 agentic-qe skills, multi-agent fleet QE. Supports --full-qe, --full-qe-extended, --with-learning, and --knowledge-extractor modes.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"skills-feature-adr": "./bin/cli.js"
|
|
@@ -132,7 +132,7 @@ Step | S | M | L | XL | Model | Agentic QE Skill
|
|
|
132
132
|
0 Complexity Router | ✓ | ✓ | ✓ | ✓ | haiku | — |
|
|
133
133
|
1 Requirements | ✓ | ✓ | ✓ | ✓ | sonnet | — |
|
|
134
134
|
2 Research | - | - | ✓ | ✓ | sonnet | — |
|
|
135
|
-
3 ADR + Shift-Left | - | ✓ | ✓ | ✓
|
|
135
|
+
3 ADR + Shift-Left | - | ✓ Nygard/ITD | ✓ MADR+Confirmation | ✓ MADR+Confirmation | opus | shift-left-testing |
|
|
136
136
|
3.5 QCSD Ideation Swarm | - | ✓ | ✓ | ✓ | sonnet | qcsd-ideation-swarm |
|
|
137
137
|
4 DDD | - | - | ✓ | ✓ | opus | — |
|
|
138
138
|
5 Architecture | - | ✓ | ✓ | ✓ | opus | — |
|
|
@@ -205,6 +205,8 @@ Execute protocol
|
|
|
205
205
|
After Step 8 (or Step 9 for L/XL) completes, verify:
|
|
206
206
|
- All mandatory artifacts exist per tier
|
|
207
207
|
- QE checks passed
|
|
208
|
+
- Every generated ADR passes the Step-8 ADR fitness checklist
|
|
209
|
+
- Every ADR Confirmation load-bearing property has a named automated test/fitness check
|
|
208
210
|
- ADR decisions are traceable to code (L/XL)
|
|
209
211
|
- QCSD quality risks are mitigated (M+)
|
|
210
212
|
- Gap detection loop closed with zero remaining gaps
|
|
@@ -57,7 +57,7 @@ Load `references/complexity-matrix.md` for the full matrix. Summary:
|
|
|
57
57
|
| 0 Complexity Router | ✓ | ✓ | ✓ | ✓ |
|
|
58
58
|
| 1 Requirements | ✓ light | ✓ | ✓ | ✓ |
|
|
59
59
|
| 2 Research | - | - | ✓ | ✓ |
|
|
60
|
-
| 3 ADR + Shift-Left | - | ✓ (1 ADR) | ✓ (N ADRs) | ✓ (N ADRs) |
|
|
60
|
+
| 3 ADR + Shift-Left | - | ✓ (1 ADR, Nygard/ITD-light) | ✓ (N ADRs, MADR+Confirmation) | ✓ (N ADRs, MADR+Confirmation) |
|
|
61
61
|
| 3.5 QCSD Ideation Swarm | - | ✓ | ✓ | ✓ |
|
|
62
62
|
| 4 DDD | - | - | ✓ | ✓ |
|
|
63
63
|
| 5 Architecture | - | ✓ light | ✓ | ✓ |
|
|
@@ -68,6 +68,13 @@ Load `references/complexity-matrix.md` for the full matrix. Summary:
|
|
|
68
68
|
|
|
69
69
|
> Steps 3.5 (M+) and 9 (L/XL) are mandatory — skipping them is a BLOCK per the shard Anti-Patterns.
|
|
70
70
|
|
|
71
|
+
ADR template weight is part of routing:
|
|
72
|
+
- Summary: S/M -> Nygard/ITD-light; L/XL -> MADR+Confirmation.
|
|
73
|
+
- S: normally skip Step 3; if an ADR is explicitly forced, use Nygard as the lightweight fallback.
|
|
74
|
+
- M: use Nygard/ITD-lightweight ADRs with the invariant core plus drivers, options, rationale, consequences, and Confirmation.
|
|
75
|
+
- L/XL: use full MADR structure with an NHS Wales Confirmation stanza for each significant decision.
|
|
76
|
+
- All generated ADRs must keep the invariant core: Title, Status, Context, Decision, Consequences; one decision per ADR.
|
|
77
|
+
|
|
71
78
|
### 5. Calculate Time Budget
|
|
72
79
|
|
|
73
80
|
| Tier | Total Budget | Distribution |
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Step 3: Architecture Decision Records
|
|
2
2
|
|
|
3
|
-
> Document each significant architectural decision with context,
|
|
3
|
+
> Document each significant architectural decision with context, rejected options, consequences, and a named verification method before implementation begins.
|
|
4
4
|
|
|
5
5
|
## When
|
|
6
6
|
|
|
7
7
|
M+ tiers. Depth varies:
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
8
|
+
- **S:** skipped by default; if explicitly forced, use Nygard as the lightweight fallback.
|
|
9
|
+
- **M:** 1 Nygard/ITD-light ADR for the main decision, with the invariant core plus drivers, options, rationale, consequences, and Confirmation.
|
|
10
|
+
- **L/XL:** N MADR+Confirmation ADRs, one per significant decision.
|
|
10
11
|
|
|
11
12
|
Can run **in parallel** with Step 2 (Research) for L/XL tiers.
|
|
12
13
|
|
|
@@ -36,94 +37,164 @@ Scan requirements for decision points:
|
|
|
36
37
|
| Trade-off | "Consistency vs. availability?" |
|
|
37
38
|
|
|
38
39
|
For M-tier: pick the SINGLE most impactful decision.
|
|
39
|
-
For L/XL: identify ALL decisions, prioritize by impact.
|
|
40
|
+
For L/XL: identify ALL significant decisions, prioritize by architectural impact, and split them into separate ADRs.
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
Reject explainer-masquerading-as-ADR: a document that describes a space but makes no concrete decision is not an ADR.
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
### 2. Choose Template Weight
|
|
45
|
+
|
|
46
|
+
All ADRs must emit the invariant core:
|
|
47
|
+
- Title
|
|
48
|
+
- Status
|
|
49
|
+
- Context
|
|
50
|
+
- Decision
|
|
51
|
+
- Consequences
|
|
52
|
+
|
|
53
|
+
Template routing:
|
|
54
|
+
- S forced ADR: Nygard fallback.
|
|
55
|
+
- M: Nygard/ITD-light form with drivers, options, rationale, consequences, and Confirmation.
|
|
56
|
+
- L/XL: MADR structure plus an NHS Wales Confirmation stanza.
|
|
57
|
+
|
|
58
|
+
The chosen template may be short, but it must still satisfy the Step-8 ADR fitness checklist.
|
|
59
|
+
|
|
60
|
+
### 3. Enforce File Naming
|
|
61
|
+
|
|
62
|
+
Create ADRs in `features/<slug>/03_adr/` as:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
NNN-{decision-slug}.md
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Slug rules:
|
|
69
|
+
- lowercase kebab-case
|
|
70
|
+
- present-tense imperative verb phrase
|
|
71
|
+
- no dates
|
|
72
|
+
- no ticket numbers
|
|
73
|
+
- no camelCase, snake_case, or spaces
|
|
74
|
+
|
|
75
|
+
Good examples: `001-choose-event-store.md`, `002-enforce-adr-fitness.md`, `003-format-timestamps.md`.
|
|
76
|
+
|
|
77
|
+
### 4. Draft ADR per Decision
|
|
78
|
+
|
|
79
|
+
Use `references/adr-template.md`.
|
|
80
|
+
|
|
81
|
+
Minimum structure:
|
|
44
82
|
|
|
45
83
|
```markdown
|
|
46
|
-
# ADR-{NNN}: {
|
|
84
|
+
# ADR-{NNN}: {decision-shaped title}
|
|
47
85
|
|
|
48
86
|
## Status
|
|
49
|
-
|
|
87
|
+
proposed - Reversible until {condition}; revisit when {trigger}.
|
|
50
88
|
|
|
51
89
|
## Context
|
|
52
|
-
|
|
90
|
+
{Neutral problem context written before the decision. State forces and constraints without selling the chosen option.}
|
|
53
91
|
|
|
54
92
|
## Decision Drivers
|
|
55
|
-
|
|
56
|
-
|
|
93
|
+
1. {Driver D1} (weight: high|medium|low)
|
|
94
|
+
2. {Driver D2} (weight: high|medium|low)
|
|
57
95
|
|
|
58
96
|
## Considered Options
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
97
|
+
### {Option A}
|
|
98
|
+
Pros:
|
|
99
|
+
- {real strength}
|
|
100
|
+
Cons:
|
|
101
|
+
- {real weakness}
|
|
102
|
+
|
|
103
|
+
### {Option B}
|
|
104
|
+
Pros:
|
|
105
|
+
- {real strength}
|
|
106
|
+
Cons:
|
|
107
|
+
- {real weakness}
|
|
62
108
|
|
|
63
109
|
## Decision
|
|
64
|
-
We
|
|
110
|
+
We will {concrete choice with exact names, versions, formats, paths, commands, APIs, or conventions}.
|
|
111
|
+
|
|
112
|
+
## Rationale
|
|
113
|
+
- D1: {why the chosen option satisfies the driver}
|
|
114
|
+
- D2: {why rejected options lost despite their strengths}
|
|
65
115
|
|
|
66
116
|
## Consequences
|
|
67
117
|
### Positive
|
|
68
|
-
-
|
|
69
|
-
### Negative
|
|
70
|
-
- ...
|
|
71
|
-
### Risks
|
|
72
|
-
- ...
|
|
73
|
-
```
|
|
118
|
+
- {benefit}
|
|
74
119
|
|
|
75
|
-
###
|
|
120
|
+
### Negative / Accepted Downsides
|
|
121
|
+
- {cost or risk} - Mitigation: {mitigation}
|
|
76
122
|
|
|
77
|
-
|
|
123
|
+
### Follow-up ADRs
|
|
124
|
+
- {ADR-NNN or "None required now"} - {why}
|
|
78
125
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
| Performance | 2 | ⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
|
|
83
|
-
| Maintainability | 3 | ⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
|
|
84
|
-
| Team familiarity | 2 | ⭐⭐⭐ | ⭐ | ⭐⭐ |
|
|
126
|
+
### After-action Review
|
|
127
|
+
- Owner: {person/team}
|
|
128
|
+
- Schedule: {about one month after acceptance, or a concrete date if known}
|
|
85
129
|
|
|
86
|
-
|
|
130
|
+
## Confirmation
|
|
131
|
+
- Method: {test, review, demo, audit, or fitness function}
|
|
132
|
+
- Monitoring: {ongoing automated check/audit/training}
|
|
133
|
+
- Success metric: {objective pass/fail or numeric metric}
|
|
134
|
+
- Owner: {responsible person/team}
|
|
135
|
+
- Load-bearing property: {the safety property Step 8 must assert has a test}
|
|
136
|
+
- Required automated check: {test file/name, command, or ArchUnit/ArchUnitTS suggestion}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
For L/XL ADRs, add a decision matrix or comparison table after Considered Options. Keep per-option pros/cons symmetric.
|
|
87
140
|
|
|
88
|
-
###
|
|
141
|
+
### 5. Validate Against Requirements
|
|
89
142
|
|
|
90
143
|
Each ADR must trace back to specific requirements:
|
|
91
144
|
- Which FR-{N} does this decision support?
|
|
92
|
-
-
|
|
93
|
-
-
|
|
145
|
+
- Which NFRs does it satisfy?
|
|
146
|
+
- Which constraints does it respect?
|
|
147
|
+
- Which safety property must be tested because the ADR's Confirmation names it?
|
|
148
|
+
|
|
149
|
+
### 6. Lifecycle Discipline
|
|
150
|
+
|
|
151
|
+
- Status vocabulary is controlled: `proposed`, `accepted`, `rejected`, `deprecated`, `superseded`.
|
|
152
|
+
- Status must include a reversibility or revisit clause.
|
|
153
|
+
- Supersession mints a NEW ADR and sets the old ADR to `superseded by ADR-{NNN}`; do not edit accepted/rejected ADR content in place.
|
|
154
|
+
- If a living-document amendment is unavoidable, add a dated "arrived after the decision" note instead of silently rewriting the original reasoning.
|
|
94
155
|
|
|
95
156
|
## Anti-Patterns
|
|
96
157
|
|
|
97
158
|
| Anti-Pattern | Detection | Fix |
|
|
98
159
|
|-------------|-----------|-----|
|
|
99
|
-
|
|
|
160
|
+
| Explainer masquerading as ADR | Describes a domain but has no concrete Decision | BLOCK; write a decision-shaped ADR |
|
|
161
|
+
| Only one alternative | Less than 2 options considered | Require chosen plus rejected options |
|
|
162
|
+
| Strawman rejected option | Loser has only cons | Add real strengths and fair trade-offs |
|
|
100
163
|
| No consequences | Missing positive/negative analysis | BLOCK until filled |
|
|
101
|
-
|
|
|
102
|
-
|
|
|
164
|
+
| Benefits-only consequences | No accepted downside | Add negative outcomes and mitigations |
|
|
165
|
+
| Decision without context | Why is unclear | Add neutral Context before Decision |
|
|
166
|
+
| Vague decision | "use a modern database" | Name exact product/version/format/path/API |
|
|
167
|
+
| Placeholder text | Template hints or TODOs remain | Remove or fill before checkpoint |
|
|
168
|
+
| Supersession in-place | Existing ADR rewritten | Mint a new ADR and link it |
|
|
103
169
|
|
|
104
170
|
## Output
|
|
105
171
|
|
|
106
172
|
Create `features/<slug>/03_adr/` directory with:
|
|
107
|
-
- `
|
|
108
|
-
- Each ADR follows the template
|
|
173
|
+
- `NNN-{decision-slug}.md` for each ADR
|
|
174
|
+
- Each ADR follows the template and satisfies the fitness checklist
|
|
109
175
|
|
|
110
|
-
Set `{ADR_DECISIONS}` variable with list of decisions.
|
|
176
|
+
Set `{ADR_DECISIONS}` variable with list of decisions and their Confirmation load-bearing properties.
|
|
111
177
|
|
|
112
178
|
## Checkpoint Format
|
|
113
179
|
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
|
|
180
|
+
```text
|
|
181
|
+
=======================================================
|
|
182
|
+
STEP 3/8: ADR Complete
|
|
117
183
|
Tier: {COMPLEXITY_TIER}
|
|
118
184
|
|
|
119
185
|
{N} architectural decisions documented:
|
|
120
|
-
1. ADR-001: {title}
|
|
121
|
-
2. ADR-002: {title}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
186
|
+
1. ADR-001: {title} -> chose {option}; Confirmation: {method}, {metric}, owner {owner}
|
|
187
|
+
2. ADR-002: {title} -> chose {option}; Confirmation: {method}, {metric}, owner {owner}
|
|
188
|
+
|
|
189
|
+
Fitness readiness:
|
|
190
|
+
- Invariant core present: PASS|FAIL
|
|
191
|
+
- Concrete/testable decisions: PASS|FAIL
|
|
192
|
+
- Confirmation properties named for Step 8: PASS|FAIL
|
|
193
|
+
|
|
194
|
+
- "ok" - proceed
|
|
195
|
+
- "revise ADR-{N}" - reconsider decision
|
|
196
|
+
- "add ADR for [topic]" - add new decision
|
|
197
|
+
=======================================================
|
|
127
198
|
```
|
|
128
199
|
|
|
129
200
|
## Shift-Left Validation (after ADR creation)
|
|
@@ -136,8 +207,14 @@ After all ADRs are drafted, apply **shift-left-testing** protocol (Level 4: Risk
|
|
|
136
207
|
|
|
137
208
|
For each ADR decision, run risk analysis:
|
|
138
209
|
|
|
139
|
-
```
|
|
210
|
+
```text
|
|
140
211
|
ADR-{NNN}: {Title}
|
|
212
|
+
Confirmation:
|
|
213
|
+
Method: {verification method}
|
|
214
|
+
Monitoring: {ongoing monitoring}
|
|
215
|
+
Success metric: {metric}
|
|
216
|
+
Owner: {owner}
|
|
217
|
+
Load-bearing property: {property}
|
|
141
218
|
Testability Questions:
|
|
142
219
|
1. What happens when {chosen option} fails under load?
|
|
143
220
|
2. How do we handle {alternative failure modes}?
|
|
@@ -147,6 +224,8 @@ ADR-{NNN}: {Title}
|
|
|
147
224
|
Given {precondition from ADR context}
|
|
148
225
|
When {action that exercises the decision}
|
|
149
226
|
Then {expected outcome per ADR consequences}
|
|
227
|
+
Required Automated Check:
|
|
228
|
+
{test file/name/command or ArchUnit/ArchUnitTS fitness function}
|
|
150
229
|
Risk Level: LOW | MEDIUM | HIGH
|
|
151
230
|
```
|
|
152
231
|
|
|
@@ -155,24 +234,35 @@ ADR-{NNN}: {Title}
|
|
|
155
234
|
| Check | Threshold |
|
|
156
235
|
|-------|-----------|
|
|
157
236
|
| All ADRs have testability questions answered | 100% |
|
|
158
|
-
|
|
|
237
|
+
| Each ADR has a Confirmation stanza | 100% |
|
|
238
|
+
| Each Confirmation names method, monitoring, success metric, owner | 100% |
|
|
239
|
+
| Each load-bearing property has a proposed automated check | 100% |
|
|
240
|
+
| BDD scenarios generated for non-trivial decisions | >=1 per ADR |
|
|
159
241
|
| No HIGH risk without mitigation documented | 0 unmitigated |
|
|
160
242
|
|
|
161
|
-
If any ADR has HIGH risk without mitigation
|
|
243
|
+
If any ADR has HIGH risk without mitigation, or a Confirmation property with no proposed automated check, flag at checkpoint for user decision.
|
|
162
244
|
|
|
163
|
-
### Integration with Step 3.5
|
|
245
|
+
### Integration with Step 3.5 and Step 8
|
|
164
246
|
|
|
165
247
|
The shift-left validation output feeds directly into Step 3.5 (QCSD Ideation Swarm):
|
|
166
248
|
- BDD scenarios become input for the requirements-validator agent
|
|
167
249
|
- Risk analysis feeds the risk-assessor agent
|
|
168
250
|
- Testability questions inform the quality-criteria-recommender
|
|
169
251
|
|
|
252
|
+
Step 8 must read the Confirmation stanza and assert that the named load-bearing property has a real automated test or fitness function in the shipped code. For architecture dependency/layering/interface rules, suggest ArchUnit or ArchUnitTS.
|
|
253
|
+
|
|
170
254
|
## Quality Gates
|
|
171
255
|
|
|
172
|
-
- [ ] Every ADR has
|
|
173
|
-
- [ ] Every ADR
|
|
174
|
-
- [ ]
|
|
175
|
-
- [ ]
|
|
176
|
-
- [ ]
|
|
177
|
-
- [ ]
|
|
178
|
-
- [ ]
|
|
256
|
+
- [ ] Every ADR has the invariant core: Title, Status, Context, Decision, Consequences
|
|
257
|
+
- [ ] Every ADR records exactly one decision
|
|
258
|
+
- [ ] Filename slug is kebab-case, imperative, dateless, and ticketless
|
|
259
|
+
- [ ] Status uses controlled vocabulary plus a reversibility clause
|
|
260
|
+
- [ ] Context is neutral and appears before Decision
|
|
261
|
+
- [ ] Decision drivers are ranked or weighted
|
|
262
|
+
- [ ] Considered options include rejected options with symmetric pros/cons
|
|
263
|
+
- [ ] Rationale maps each point to a driver and explains why losers were rejected
|
|
264
|
+
- [ ] Decision is concrete/testable with exact names/versions/formats/paths/APIs
|
|
265
|
+
- [ ] Consequences include positive and negative outcomes/accepted downsides
|
|
266
|
+
- [ ] Consequences link follow-up ADRs and schedule an after-action review
|
|
267
|
+
- [ ] Confirmation names method, monitoring, success metric, owner, load-bearing property, and required automated check
|
|
268
|
+
- [ ] No placeholder text or generation scaffolding remains
|
|
@@ -129,6 +129,35 @@ Choose review mode based on context:
|
|
|
129
129
|
- 🟡 **WARNING** — should fix, but not blocking (Ramsay mode: "This is RAW")
|
|
130
130
|
- 🔵 **SUGGESTION** — nice to have improvement
|
|
131
131
|
|
|
132
|
+
### 3.1 ADR Fitness Checklist Gate (M+)
|
|
133
|
+
|
|
134
|
+
Before final grading, read every generated ADR in `features/<slug>/03_adr/NNN-*.md`.
|
|
135
|
+
|
|
136
|
+
Fail the ADR gate for any miss:
|
|
137
|
+
|
|
138
|
+
| Check | Required Evidence |
|
|
139
|
+
|-------|-------------------|
|
|
140
|
+
| Decision-shaped title | Title names one concrete decision, not a vague topic |
|
|
141
|
+
| One decision per ADR | No bundled independent decisions |
|
|
142
|
+
| Filename discipline | `03_adr/NNN-{decision-slug}.md`; slug is lowercase kebab-case, imperative, dateless, ticketless |
|
|
143
|
+
| Status vocabulary | `proposed`, `accepted`, `rejected`, `deprecated`, or `superseded` |
|
|
144
|
+
| Reversibility clause | Status states when/how to revisit or why it is irreversible |
|
|
145
|
+
| Neutral Context before Decision | Context states problem/forces without advocating the chosen solution |
|
|
146
|
+
| Drivers ranked or weighted | Decision Drivers are explicit and prioritized |
|
|
147
|
+
| Considered Options | Chosen and rejected options are present |
|
|
148
|
+
| Symmetric pros/cons | Each option has real strengths and weaknesses; no strawman loser |
|
|
149
|
+
| Rationale maps to drivers | Every rationale point names the driver it satisfies and why rejected options lost |
|
|
150
|
+
| Concrete/testable Decision | Exact names, versions, formats, paths, commands, APIs, or conventions |
|
|
151
|
+
| Negative consequences | Consequences include accepted downsides/risks, not only benefits |
|
|
152
|
+
| Follow-up discipline | Consequences link follow-up ADRs or state none; after-action review is scheduled |
|
|
153
|
+
| Confirmation stanza | Names verification method, monitoring, success metric, and owner |
|
|
154
|
+
| Confirmation-to-test link | The named load-bearing property has a real automated test/fitness check by file/name |
|
|
155
|
+
| No placeholders | No TODO, template hint text, raw prompt/generation scaffold, or empty tail sections |
|
|
156
|
+
|
|
157
|
+
Reject explainer-masquerading-as-ADR: if the document describes a problem space or technology landscape but has no concrete `Decision`, record a BLOCKER.
|
|
158
|
+
|
|
159
|
+
The Confirmation-to-test link is load-bearing. If absent, grade no better than C and record a blocker gap; for architecture dependency/layering/interface rules, recommend an ArchUnit or ArchUnitTS fitness function.
|
|
160
|
+
|
|
132
161
|
### 4. Multi-Agent Review Panel (L/XL)
|
|
133
162
|
|
|
134
163
|
For L/XL features, spawn 3 parallel review agents using brutal-honesty modes:
|
|
@@ -150,6 +179,7 @@ After review findings are compiled, run a gap check:
|
|
|
150
179
|
ITERATION {N}:
|
|
151
180
|
1. Check: Every FR-{N} from requirements → has passing test or verification
|
|
152
181
|
2. Check: Every ADR decision → reflected in code
|
|
182
|
+
2a. Check: Every ADR Confirmation load-bearing property → has a named automated test/fitness check
|
|
153
183
|
3. Check: Every critical risk from QCSD → has mitigation in code
|
|
154
184
|
4. Check: Every 🔴 BLOCKER → has fix plan
|
|
155
185
|
|
|
@@ -199,6 +229,11 @@ Compile all findings into a structured report:
|
|
|
199
229
|
## Review Findings
|
|
200
230
|
{list of findings with severity}
|
|
201
231
|
|
|
232
|
+
## ADR Fitness Checklist
|
|
233
|
+
| ADR | Fitness | Confirmation Test Evidence | Gaps |
|
|
234
|
+
|-----|---------|----------------------------|------|
|
|
235
|
+
| ADR-001 | PASS/FAIL | {test file/name or missing} | {none or blocker} |
|
|
236
|
+
|
|
202
237
|
## Acceptance Criteria
|
|
203
238
|
{FR-N status table}
|
|
204
239
|
|
|
@@ -1,102 +1,158 @@
|
|
|
1
1
|
# ADR Template
|
|
2
2
|
|
|
3
|
-
Use this template for every Architecture Decision Record.
|
|
3
|
+
Use this template for every Architecture Decision Record generated by feature-adr.
|
|
4
|
+
|
|
5
|
+
Template weight:
|
|
6
|
+
- S forced ADR: Nygard fallback.
|
|
7
|
+
- M: Nygard/ITD-light with drivers, options, rationale, consequences, and Confirmation.
|
|
8
|
+
- L/XL: MADR structure plus NHS Wales Confirmation.
|
|
9
|
+
|
|
10
|
+
Every ADR must keep the invariant core: Title, Status, Context, Decision, Consequences. Record exactly one decision per ADR.
|
|
4
11
|
|
|
5
12
|
---
|
|
6
13
|
|
|
7
14
|
```markdown
|
|
8
|
-
# ADR-{NNN}: {
|
|
15
|
+
# ADR-{NNN}: {Decision-shaped title}
|
|
9
16
|
|
|
10
17
|
## Status
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
proposed - Reversible until {condition}; revisit when {trigger}.
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{YYYY-MM-DD}
|
|
21
|
+
Allowed status values: `proposed`, `accepted`, `rejected`, `deprecated`, `superseded`.
|
|
17
22
|
|
|
18
23
|
## Context
|
|
19
24
|
|
|
20
|
-
{
|
|
21
|
-
Describe the forces at play — technical, business, political, social.
|
|
22
|
-
Describe the problem space, not the solution.}
|
|
25
|
+
{Neutral problem statement written before the decision. Describe the forces, constraints, requirements, team context, and trade-offs without advocating the chosen option.}
|
|
23
26
|
|
|
24
27
|
## Decision Drivers
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
1. {Driver D1} (weight: high|medium|low; traces to FR/NFR/constraint)
|
|
30
|
+
2. {Driver D2} (weight: high|medium|low; traces to FR/NFR/constraint)
|
|
31
|
+
3. {Driver D3} (weight: high|medium|low; traces to FR/NFR/constraint)
|
|
29
32
|
|
|
30
33
|
## Considered Options
|
|
31
34
|
|
|
32
|
-
### Option
|
|
35
|
+
### {Option A}
|
|
36
|
+
|
|
37
|
+
{Short description.}
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
Pros:
|
|
40
|
+
- {Real strength}
|
|
41
|
+
- {Real strength}
|
|
35
42
|
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
- ❌ {Con 2}
|
|
43
|
+
Cons:
|
|
44
|
+
- {Real weakness}
|
|
45
|
+
- {Real weakness}
|
|
40
46
|
|
|
41
|
-
### Option
|
|
47
|
+
### {Option B}
|
|
42
48
|
|
|
43
|
-
{
|
|
49
|
+
{Short description.}
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
-
|
|
51
|
+
Pros:
|
|
52
|
+
- {Real strength}
|
|
53
|
+
- {Real strength}
|
|
47
54
|
|
|
48
|
-
|
|
55
|
+
Cons:
|
|
56
|
+
- {Real weakness}
|
|
57
|
+
- {Real weakness}
|
|
49
58
|
|
|
50
|
-
{
|
|
59
|
+
### {Option C, optional}
|
|
51
60
|
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
{Short description.}
|
|
62
|
+
|
|
63
|
+
Pros:
|
|
64
|
+
- {Real strength}
|
|
65
|
+
|
|
66
|
+
Cons:
|
|
67
|
+
- {Real weakness}
|
|
54
68
|
|
|
55
69
|
## Decision Matrix
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
|
60
|
-
|
|
61
|
-
|
|
|
62
|
-
|
|
|
71
|
+
Use for non-trivial M decisions and all L/XL decisions.
|
|
72
|
+
|
|
73
|
+
| Driver | Weight | Option A | Option B | Option C |
|
|
74
|
+
|--------|--------|----------|----------|----------|
|
|
75
|
+
| D1 | high | {score/rationale} | {score/rationale} | {score/rationale} |
|
|
76
|
+
| D2 | medium | {score/rationale} | {score/rationale} | {score/rationale} |
|
|
77
|
+
| D3 | low | {score/rationale} | {score/rationale} | {score/rationale} |
|
|
63
78
|
|
|
64
79
|
## Decision
|
|
65
80
|
|
|
66
|
-
We
|
|
81
|
+
We will {concrete, testable choice with exact names, versions, formats, paths, commands, APIs, or conventions}.
|
|
82
|
+
|
|
83
|
+
## Rationale
|
|
84
|
+
|
|
85
|
+
- D1: {Why the chosen option best satisfies this driver.}
|
|
86
|
+
- D2: {Why the chosen option best satisfies this driver.}
|
|
87
|
+
- Rejected {Option B}: {Why it lost despite its real strengths.}
|
|
67
88
|
|
|
68
89
|
## Consequences
|
|
69
90
|
|
|
70
91
|
### Positive
|
|
71
|
-
- {Positive consequence
|
|
72
|
-
- {Positive consequence
|
|
92
|
+
- {Positive consequence}
|
|
93
|
+
- {Positive consequence}
|
|
73
94
|
|
|
74
|
-
### Negative
|
|
75
|
-
- {Negative consequence
|
|
95
|
+
### Negative / Accepted Downsides
|
|
96
|
+
- {Negative consequence or accepted downside} - Mitigation: {mitigation}
|
|
97
|
+
- {Risk with likelihood/impact if relevant} - Mitigation: {mitigation}
|
|
76
98
|
|
|
77
|
-
###
|
|
78
|
-
- {
|
|
79
|
-
- {Risk 2} — Mitigation: {how to mitigate}
|
|
99
|
+
### Follow-up ADRs
|
|
100
|
+
- {ADR-NNN: title, or "None required now"} - {why}
|
|
80
101
|
|
|
81
|
-
|
|
102
|
+
### After-action Review
|
|
103
|
+
- Owner: {person/team}
|
|
104
|
+
- Schedule: {about one month after acceptance, or a concrete date if known}
|
|
105
|
+
- Review question: Did the expected benefits and accepted downsides match reality?
|
|
82
106
|
|
|
83
|
-
|
|
84
|
-
- Related: ADR-{M} (if any)
|
|
85
|
-
```
|
|
107
|
+
## Confirmation
|
|
86
108
|
|
|
87
|
-
|
|
109
|
+
- Method: {How the decision is verified: automated test, fitness function, review, demo, audit}
|
|
110
|
+
- Monitoring: {How compliance is monitored over time}
|
|
111
|
+
- Success metric: {Objective pass/fail or numeric metric}
|
|
112
|
+
- Owner: {responsible person/team}
|
|
113
|
+
- Load-bearing property: {The safety property Step 8 must assert has a test}
|
|
114
|
+
- Required automated check: {test file/name, command, or ArchUnit/ArchUnitTS suggestion}
|
|
88
115
|
|
|
89
|
-
##
|
|
116
|
+
## Links
|
|
90
117
|
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
118
|
+
- Requirement: FR-{N} / NFR-{N}
|
|
119
|
+
- Related ADRs: {ADR links, typed if relevant: Refines, Supersedes, Superseded by, Follow-up}
|
|
120
|
+
- Evidence: {research, code path, benchmark, external source}
|
|
121
|
+
```
|
|
94
122
|
|
|
95
|
-
|
|
123
|
+
---
|
|
96
124
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
125
|
+
## ADR Numbering and Slugs
|
|
126
|
+
|
|
127
|
+
- Start from 001 for each feature.
|
|
128
|
+
- Keep numbers sequential within a feature, no gaps.
|
|
129
|
+
- Use `NNN-{decision-slug}.md`.
|
|
130
|
+
- The slug must be lowercase kebab-case, present-tense imperative, dateless, and ticketless.
|
|
131
|
+
- Good: `001-choose-database-engine.md`, `002-enforce-adr-fitness.md`, `003-format-timestamps.md`.
|
|
132
|
+
- Bad: `001-database.md`, `001-ADR-1234-database.md`, `001-2026-07-08-database.md`.
|
|
133
|
+
|
|
134
|
+
## ADR Fitness Checklist
|
|
135
|
+
|
|
136
|
+
- [ ] Title is decision-shaped and records one decision only
|
|
137
|
+
- [ ] Status is one of `proposed`, `accepted`, `rejected`, `deprecated`, `superseded`
|
|
138
|
+
- [ ] Status includes a reversibility or revisit clause
|
|
139
|
+
- [ ] Context is neutral and appears before Decision
|
|
140
|
+
- [ ] Decision drivers are ranked/weighted
|
|
141
|
+
- [ ] Considered options include chosen and rejected options
|
|
142
|
+
- [ ] Every option has symmetric pros and cons
|
|
143
|
+
- [ ] Rationale maps each point to a stated driver
|
|
144
|
+
- [ ] Rationale explains why rejected options lost
|
|
145
|
+
- [ ] Decision is concrete/testable with exact names, versions, formats, paths, commands, APIs, or conventions
|
|
146
|
+
- [ ] Consequences include positive and negative outcomes/accepted downsides
|
|
147
|
+
- [ ] Consequences link follow-up ADRs or explicitly say none
|
|
148
|
+
- [ ] Consequences schedule an after-action review
|
|
149
|
+
- [ ] Confirmation names verification method, monitoring, success metric, and owner
|
|
150
|
+
- [ ] Confirmation names the load-bearing property and required automated check
|
|
151
|
+
- [ ] No placeholder text, raw prompt text, or template hints remain
|
|
152
|
+
- [ ] The document is not an explainer masquerading as an ADR
|
|
153
|
+
|
|
154
|
+
## Lifecycle
|
|
155
|
+
|
|
156
|
+
- Supersession mints a new ADR and links it; do not edit accepted/rejected ADR content in place.
|
|
157
|
+
- If an amendment is unavoidable, add a dated note that the information arrived after the decision.
|
|
158
|
+
- Rejected ADRs must record why the option was rejected to avoid re-litigating it.
|
|
@@ -64,6 +64,8 @@
|
|
|
64
64
|
|
|
65
65
|
## Step Activation by Tier
|
|
66
66
|
|
|
67
|
+
ADR template weight: S/M -> Nygard/ITD-light; L/XL -> MADR+Confirmation.
|
|
68
|
+
|
|
67
69
|
### Tier S (Score 6-8)
|
|
68
70
|
|
|
69
71
|
```
|
|
@@ -73,6 +75,7 @@ Skipped: 2, 3, 4, 5
|
|
|
73
75
|
|
|
74
76
|
**Step adaptations:**
|
|
75
77
|
- Step 1: 3-5 bullet requirements, no formal document
|
|
78
|
+
- Step 3: skipped by default; if explicitly forced, use Nygard as the lightweight fallback
|
|
76
79
|
- Step 6: Inline in conversation, no separate file
|
|
77
80
|
- Step 8: Smoke tests only — does it compile? Do existing tests pass?
|
|
78
81
|
|
|
@@ -84,7 +87,7 @@ Skipped: 2, 4, 9
|
|
|
84
87
|
```
|
|
85
88
|
|
|
86
89
|
**Step adaptations:**
|
|
87
|
-
- Step 3: Single ADR for the main architectural decision
|
|
90
|
+
- Step 3: Single Nygard/ITD-light ADR for the main architectural decision; keep the invariant core plus drivers, options, rationale, consequences, and Confirmation
|
|
88
91
|
- Step 3.5: QCSD ideation swarm — 3 core agents + GO/CONDITIONAL/NO-GO verdict (mandatory for M+ — skipping is a BLOCK)
|
|
89
92
|
- Step 5: Component diagram only, no full C4
|
|
90
93
|
|
|
@@ -97,7 +100,7 @@ Parallel groups: (2,3) and (4,5); Step 3.5 runs after Step 3, Step 9 after Step
|
|
|
97
100
|
|
|
98
101
|
**Step adaptations:**
|
|
99
102
|
- Step 2: Research analogues in codebase and external patterns
|
|
100
|
-
- Step 3: Multiple ADRs for each significant decision
|
|
103
|
+
- Step 3: Multiple MADR+Confirmation ADRs for each significant decision
|
|
101
104
|
- Step 3.5: QCSD ideation swarm — 3-9 parallel agents + GO/CONDITIONAL/NO-GO verdict (mandatory for M+ — skipping is a BLOCK)
|
|
102
105
|
- Step 4: Bounded contexts + ubiquitous language
|
|
103
106
|
- Step 5: Full C4 (Context + Container + Component)
|
|
@@ -113,6 +116,7 @@ Parallel groups: (2,3), (4,5 — after 3.5), (7 per module)
|
|
|
113
116
|
|
|
114
117
|
**Step adaptations:**
|
|
115
118
|
- All steps at full depth
|
|
119
|
+
- Step 3: Full MADR+Confirmation ADRs; one decision per ADR with typed follow-up links
|
|
116
120
|
- Step 3.5: QCSD ideation swarm — 3-9 parallel agents + GO/CONDITIONAL/NO-GO verdict (mandatory for M+ — skipping is a BLOCK)
|
|
117
121
|
- Step 7: Multiple parallel agents, one per module/domain
|
|
118
122
|
- Step 8: Full QE — unit + integration + e2e + performance + security review
|
|
@@ -226,14 +226,46 @@ function modelLabel(opts) {
|
|
|
226
226
|
return 'session'
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
// needsLandedBarrier — mirror of harness-core's pure gate (feature-adr-routing.ts). TRUE only when a
|
|
230
|
+
// stage resolved to Codex. A Claude stage is synchronous (artifact on disk when agent() returns), so
|
|
231
|
+
// this is FALSE and the barrier below is never constructed → an all-Claude run, and a Claude-design +
|
|
232
|
+
// Codex-QE run, do ZERO extra work (byte-identical to today).
|
|
233
|
+
function needsLandedBarrier(opts) { return !!(opts && opts.agentType === 'codex:codex-rescue') }
|
|
234
|
+
|
|
235
|
+
// A Bash one-liner that waits for a Codex OUT-OF-BAND artifact write to LAND: polls up to ~40s until
|
|
236
|
+
// the file exists, is non-empty, AND its size is stable across two reads (write finished). Assumes a
|
|
237
|
+
// fresh feature slug (no stale same-path artifact) — true for a normal /feature-adr run.
|
|
238
|
+
function landedProbeCmd(f) {
|
|
239
|
+
return 'f="' + f + '"; last=-1; for i in 1 2 3 4 5 6 7 8; do if [ -s "$f" ]; then s=$(wc -c < "$f"); if [ "$s" = "$last" ]; then break; fi; last=$s; fi; sleep 5; done; [ -s "$f" ] && echo "landed=$(wc -c < "$f")" || echo "absent"'
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// designStage — run a DESIGN artifact-writing stage with a Codex-landed barrier (Step-7.5 pattern,
|
|
243
|
+
// extended to the design stages). GATED on codex (see needsLandedBarrier): Claude stages run exactly
|
|
244
|
+
// as before (schema-validated, synchronous, zero barrier). For codex we (a) drop the ARTIFACT schema —
|
|
245
|
+
// codex-rescue returns finalMessage text, not StructuredOutput; success is proven by the file landing —
|
|
246
|
+
// (b) add a FOREGROUND hint so the codex runtime blocks until the write completes, (c) poll the
|
|
247
|
+
// artifact, and (d) fall back to a Claude agent if it never lands (never blocks the pipeline).
|
|
248
|
+
async function designStage(promptText, opts, artifactPath) {
|
|
249
|
+
if (!needsLandedBarrier(opts)) return await agent(promptText, opts)
|
|
250
|
+
const codexOpts = {}
|
|
251
|
+
for (const k in opts) if (k !== 'schema') codexOpts[k] = opts[k]
|
|
252
|
+
const res = await agent(promptText + ' IMPORTANT: run the Codex task in FOREGROUND (synchronous — do NOT pass --background) so this call blocks until the file is fully written to disk.', codexOpts)
|
|
253
|
+
const probe = await agent('Confirm a Codex OUT-OF-BAND artifact write has LANDED before the next stage reads it. Run EXACTLY this via Bash and return its stdout verbatim, nothing else:\n' + landedProbeCmd(artifactPath), { label: 'design:confirm-landed', phase: 'Design', effort: 'low' })
|
|
254
|
+
if (res && probe && /landed=/.test(String(probe))) return { wrote: [artifactPath], summary: String(res).slice(0, 300) }
|
|
255
|
+
log('design artifact did not land on codex (' + artifactPath + ') — falling back to Claude')
|
|
256
|
+
return await agent(promptText, mergeOpts({ label: (opts.label || 'design') + ':claude-fb', phase: 'Design', schema: ARTIFACT }, {}))
|
|
257
|
+
}
|
|
258
|
+
|
|
229
259
|
const ROUTER = { type: 'object', additionalProperties: false, required: ['tier', 'activeSteps', 'rationale'], properties: { tier: { type: 'string', enum: ['S', 'M', 'L', 'XL'] }, activeSteps: { type: 'array', items: { type: 'number' } }, rationale: { type: 'string' } } }
|
|
230
260
|
const ARTIFACT = { type: 'object', additionalProperties: false, required: ['wrote', 'summary'], properties: { wrote: { type: 'array', items: { type: 'string' } }, summary: { type: 'string' } } }
|
|
231
261
|
const QE = { type: 'object', additionalProperties: false, required: ['grade', 'gaps', 'codeTestsAdequate', 'docTestsPresent'], properties: { grade: { type: 'string' }, codeTestsAdequate: { type: 'boolean' }, docTestsPresent: { type: 'boolean' }, gaps: { type: 'array', items: { type: 'object', additionalProperties: false, required: ['sev', 'what'], properties: { sev: { type: 'string' }, what: { type: 'string' } } } } } }
|
|
262
|
+
const ADR_TEMPLATE_GUIDE = 'ADR best-practices for Step 3: emit exactly one decision per ADR with the invariant core Title, Status, Context, Decision, Consequences. Template weight is tier-routed: S/M use Nygard/ITD-lightweight form but still include decision drivers, considered options, rationale, consequences, and Confirmation; L/XL use MADR structure plus an NHS Wales Confirmation stanza. Confirmation MUST name verification method, monitoring, success metric, and owner, and its load-bearing safety property MUST be tied to a Step-8 automated test/fitness function. Use status vocabulary proposed/accepted/rejected/deprecated/superseded plus a reversibility clause. Context must be neutral and appear before Decision. Considered Options must include rejected options with symmetric pros/cons. Rationale points must map to stated drivers and explain why losers were rejected. Consequences must include positive and negative outcomes/accepted downsides, follow-up ADR links, an after-action review schedule, and supersession discipline: supersession mints a new ADR and never edits accepted/rejected ADR content in place. Decision must be concrete/testable with exact names, versions, formats, paths, commands, or APIs. Reject explainer-masquerading-as-ADR: a domain overview with no concrete Decision is not an ADR. File names under 03_adr MUST be sequential NNN-{decision-slug}.md with lowercase kebab-case, dateless, ticketless slugs (the auto-001 ADR tracks the feature slug, so the present-tense imperative signal lives in the ADR Title; model-named additional ADRs use imperative slugs). Add a ## Links traceability block (requirements, driving use case, related ADRs) and a one-line provenance note (model-generated, edited for clarity); for a long ADR include a top-of-file table of contents.'
|
|
263
|
+
const ADR_FITNESS_CHECKLIST = 'ADR fitness checklist for Step 8: read every ' + FDIR + '/03_adr/NNN-*.md ADR and fail the QE gate for any miss. Required checks: (1) filename is 03_adr/NNN-{decision-slug}.md where the slug is lowercase kebab-case, imperative, dateless, and ticketless; (2) title is decision-shaped and the ADR records one decision only; (3) Status is non-empty controlled vocabulary proposed/accepted/rejected/deprecated/superseded and includes a reversibility/revisit clause; (4) Context is neutral, problem-first, and appears before Decision; (5) Decision Drivers are stated and ranked/weighted; (6) Considered Options include the chosen and rejected options, each with symmetric pros and cons; (7) Rationale maps each point back to a driver and explains why rejected options lost; (8) Decision is concrete/testable with exact names, versions, formats, paths, commands, or APIs; (9) Consequences include positive and negative outcomes/accepted downsides, follow-up ADR links, and an after-action review schedule; (10) Confirmation names verification method, monitoring, success metric, and owner, then links the load-bearing safety property to an automated test/fitness function; (11) no placeholder text, template hints, raw generation scaffolding, or fake Markdown structure; (12) reject explainer-masquerading-as-ADR: describing a space with no concrete Decision is a blocker; (13) a Related/Links traceability block maps the ADR to its requirements, driving use case, and related ADRs. The ADR Confirmation check is load-bearing: assert the named safety property has a real test by file/name; if absent, grade no better than C and record a blocker gap.'
|
|
232
264
|
|
|
233
265
|
// Step 0: Router + MANDATORY self-learning recall
|
|
234
266
|
phase('Router')
|
|
235
267
|
await usageProbe('Router')
|
|
236
|
-
const routerPrompt = 'You are Step 0 (Complexity Router) of the /feature-adr pipeline. TWO jobs. (1) MANDATORY SELF-LEARNING RECALL (never skip — run BOTH Bash commands VERBATIM, do not summarize instead of running them): the learned patterns live in the CANONICAL BRAIN store at `' + BRAIN + '` — pin every recall to it. Via your Bash tool run EXACTLY `' + DZ_RECALL('<the key domain terms of this feature>') + '` (and `' + DZ_RECALL('<the key domain terms of this feature>') + ' --all` if narrow) to load relevant LEARNED PATTERNS from the brain. Preserve recalled pattern TEXT, reward, domain, and any visible id in the rationale as a concrete list so Step 8 can compare candidate lessons against it. Then run `dz statusline --fa-record --slug ' + SLUG + ' --step "Step 0 recall" --recalled <count> --mode ' + MODE + ' --project ' + REPO + '`. Summarize the top 3 applicable patterns in the rationale. (2) Classify S/M/L/XL + active steps. Feature: "' + DESC + '". Code: ' + CODE_HINT + '. S=1-3 files (0,1,6,7,8); M=4-10 (0,1,3,3.5,5,6,7,8); L=11-30 (all+9); XL=30+ (full+9). Return {tier, activeSteps, rationale} with the recalled patterns folded into rationale.'
|
|
268
|
+
const routerPrompt = 'You are Step 0 (Complexity Router) of the /feature-adr pipeline. TWO jobs. (1) MANDATORY SELF-LEARNING RECALL (never skip — run BOTH Bash commands VERBATIM, do not summarize instead of running them): the learned patterns live in the CANONICAL BRAIN store at `' + BRAIN + '` — pin every recall to it. Via your Bash tool run EXACTLY `' + DZ_RECALL('<the key domain terms of this feature>') + '` (and `' + DZ_RECALL('<the key domain terms of this feature>') + ' --all` if narrow) to load relevant LEARNED PATTERNS from the brain. Preserve recalled pattern TEXT, reward, domain, and any visible id in the rationale as a concrete list so Step 8 can compare candidate lessons against it. Then run `dz statusline --fa-record --slug ' + SLUG + ' --step "Step 0 recall" --recalled <count> --mode ' + MODE + ' --project ' + REPO + '`. Summarize the top 3 applicable patterns in the rationale. (2) Classify S/M/L/XL + active steps. Feature: "' + DESC + '". Code: ' + CODE_HINT + '. S=1-3 files (0,1,6,7,8; if an ADR is explicitly forced, use Nygard as the lightweight fallback); M=4-10 (0,1,3,3.5,5,6,7,8; Nygard/ITD-light ADR); L=11-30 (all+9; MADR+Confirmation ADRs); XL=30+ (full+9; MADR+Confirmation ADRs). ADR template-weight rule: S/M -> Nygard/ITD-light; L/XL -> MADR + NHS Wales Confirmation, while every generated ADR still carries the invariant core. Return {tier, activeSteps, rationale} with the recalled patterns folded into rationale.'
|
|
237
269
|
const routerOpts = mergeOpts({ label: 'router+recall', phase: 'Router', schema: ROUTER, effort: 'low' }, resolveStageModel('router'))
|
|
238
270
|
modelsUsed.router = modelLabel(routerOpts)
|
|
239
271
|
const router = await agent(routerPrompt, routerOpts)
|
|
@@ -265,12 +297,12 @@ modelsUsed.adr = modelLabel(adrOpts)
|
|
|
265
297
|
modelsUsed.ideation = modelLabel(qcsdOpts)
|
|
266
298
|
modelsUsed.architecture = modelLabel(archOpts)
|
|
267
299
|
modelsUsed.ddd = modelLabel(archOpts)
|
|
268
|
-
designThunks.push(() =>
|
|
300
|
+
designThunks.push(() => designStage('Step 1 (Requirements)' + (isLplus ? ' + Step 2 (Research)' : '') + ' of /feature-adr for "' + DESC + '" (tier ' + tier + ', slug ' + SLUG + '). Code: ' + CODE_HINT + '. APPLY these Step-0 recalled LEARNED PATTERNS (fold the applicable ones into requirements/constraints - the loop paying off): ' + LEARNED + '. Write ' + FDIR + '/01_requirements.md (functional + non-functional requirements, acceptance criteria, constraints, and an "Applied learned patterns" note).' + reqExtra + ' Return wrote[] + a 1-line summary.', reqOpts, FDIR + '/01_requirements.md'))
|
|
269
301
|
if (isMplus) {
|
|
270
|
-
designThunks.push(() =>
|
|
271
|
-
designThunks.push(() =>
|
|
302
|
+
designThunks.push(() => designStage('Step 3 (ADR + shift-left testability) of /feature-adr for "' + DESC + '" (' + SLUG + '). READ the actual code (' + CODE_HINT + ') to ground it. ' + ADR_TEMPLATE_GUIDE + ' Write ' + FDIR + '/03_adr/001-' + SLUG + '.md as a MADR-structured ADR that PASSES the Step-8 ADR fitness checklist (do NOT emit the legacy shape). Emit ALL of these sections, in order: a decision-shaped # Title (present-tense imperative verb — the auto-filename tracks the feature slug, so the IMPERATIVE signal lives in the title); ## Status (proposed/accepted/rejected/deprecated/superseded + a reversibility/revisit clause); ## Context (neutral, problem-first, BEFORE the Decision); ## Decision Drivers (ranked/weighted D1, D2, …); ## Considered Options (frame the CHOSEN approach as one option ALONGSIDE the rejected ones, each with symmetric Pros:/Cons:); ## Decision (concrete/testable — exact names, versions, paths, commands); ## Rationale (map each point to a driver Dn + why the losers lost); ## Consequences (Positive + Negative/Accepted Downsides + Follow-up ADRs + After-action Review with owner + date); a REQUIRED ## Confirmation stanza with Method:, Monitoring:, Success metric:, Owner:, Load-bearing property:, and Required automated check: `<test file>` NAMING the load-bearing property that MUST have a Step-8 test (the recurring lesson: the key safety property is often the untested one); and a ## Links traceability block (requirements, driving use case, related ADRs). Add a one-line provenance note (model-generated, edited for clarity) and, for a long ADR, a top-of-file table of contents. Do NOT use an "Alternatives considered" or "Testability/shift-left" heading in place of Considered Options / Confirmation. When creating ADDITIONAL ADRs, name them 03_adr/NNN-{decision-slug}.md with a lowercase-kebab, present-tense imperative, dateless, ticketless slug. Return wrote[] + summary.', adrOpts, FDIR + '/03_adr/001-' + SLUG + '.md'))
|
|
303
|
+
designThunks.push(() => designStage('Step 3.5 (QCSD ideation swarm - HTSM quality criteria + SFDIPOT risk) of /feature-adr for "' + DESC + '" (' + SLUG + '). Assess quality criteria + product-factors risk. Write ' + FDIR + '/03.5_ideation_report.md with a GO/CONDITIONAL/NO-GO verdict + top quality risks for QE. Return wrote[] + summary.', qcsdOpts, FDIR + '/03.5_ideation_report.md'))
|
|
272
304
|
const archExtra = isLplus ? ' Also ' + FDIR + '/04_domain_model.md (DDD).' : ''
|
|
273
|
-
designThunks.push(() =>
|
|
305
|
+
designThunks.push(() => designStage((isLplus ? 'Step 4 (DDD) + ' : '') + 'Step 5 (Architecture) of /feature-adr for "' + DESC + '" (' + SLUG + '). READ the code. Write ' + FDIR + '/05_architecture.md (components, data flow, integration points, the emit/merge/wiring shape).' + archExtra + ' Return wrote[] + summary.', archOpts, FDIR + '/05_architecture.md'))
|
|
274
306
|
}
|
|
275
307
|
const design = await parallel(designThunks)
|
|
276
308
|
|
|
@@ -289,12 +321,15 @@ let plan = null
|
|
|
289
321
|
if (planIsCodex) {
|
|
290
322
|
modelsUsed.plan = (planModel.agentType === 'codex:codex-rescue') ? modelLabel(planModel) : ('codex:' + CODEX_MODEL + ':high')
|
|
291
323
|
const codexPlanOpts = mergeOpts({ label: 'plan:codex', phase: 'Plan', agentType: 'codex:codex-rescue' }, planModel.agentType ? planModel : {})
|
|
292
|
-
const codexPlan = await agent(planPrompt, codexPlanOpts)
|
|
293
|
-
|
|
324
|
+
const codexPlan = await agent(planPrompt + ' IMPORTANT: run the Codex task in FOREGROUND (synchronous — do NOT pass --background) so this call blocks until 06_implementation_plan.md is fully written to disk.', codexPlanOpts)
|
|
325
|
+
// Codex-landed barrier for the plan artifact: a stub return is NOT proof the file was written
|
|
326
|
+
// (codex writes out-of-band). Require the artifact to LAND; otherwise fall through to the Claude planner.
|
|
327
|
+
const planLanded = codexPlan ? await agent('Confirm the Codex plan write has LANDED. Run EXACTLY this via Bash and return its stdout verbatim, nothing else:\n' + landedProbeCmd(FDIR + '/06_implementation_plan.md'), { label: 'plan:confirm-landed', phase: 'Plan', effort: 'low' }) : null
|
|
328
|
+
if (codexPlan && planLanded && /landed=/.test(String(planLanded))) {
|
|
294
329
|
plan = { wrote: [FDIR + '/06_implementation_plan.md'], summary: String(codexPlan).slice(0, 500), planner: 'codex' }
|
|
295
|
-
log('Plan: Codex (top model)')
|
|
330
|
+
log('Plan: Codex (top model) — artifact landed')
|
|
296
331
|
} else {
|
|
297
|
-
log('Plan: Codex
|
|
332
|
+
log('Plan: Codex plan did not land — falling back to the default planner')
|
|
298
333
|
}
|
|
299
334
|
}
|
|
300
335
|
if (plan === null && planIsCodex) reactiveBelt('Plan')
|
|
@@ -358,7 +393,7 @@ if (coderUsed === 'codex' || coderUsed === 'codex-fallback') {
|
|
|
358
393
|
// Step 8: QE (brutal-honesty, agentic-qe) + MANDATORY teach
|
|
359
394
|
phase('QE')
|
|
360
395
|
await usageProbe('QE')
|
|
361
|
-
const qePrompt = 'Step 8 (QE - brutal-honesty review, agentic-qe) of /feature-adr for "' + DESC + '" (' + SLUG + '). Adversarially review the SHIPPED code (read it): correctness, edge cases, error handling, and the LOAD-BEARING property the ADR named (ASSERT it has a test - the recurring lesson). Grade A/B/C/D honestly. Assess code-test adequacy + doc-test presence. List CONFIRMED gaps with severity. Write ' + FDIR + '/08_qe_report.md. MANDATORY SELF-LEARNING STORE (close the loop, never skip): compare every candidate lesson against the Step-0 recalled LEARNED patterns above. Teach ONLY lessons NOT covered by Step-0 recall. On overlap, run `dz teach --reinforce "<recalled pattern id or exact text>" --project ' + BRAIN + '` instead of minting a near-duplicate; if --reinforce is unavailable, skip the duplicate teach and report `reinforced existing pattern <id>` in the QE report. Store every genuinely new lesson in the CANONICAL BRAIN store at `' + BRAIN + '` so it is NOT lost to a target repo you may have cd`d into. Via Bash run EXACTLY `' + DZ_TEACH('<a durable reusable lesson from this feature - a rule/pattern/pitfall, NOT a checkpoint echo>', '<0.7-0.95>', '<area>') + '` for each genuine NEW lesson (1-3 max, high-signal) — the `cd ' + BRAIN + ' &&` prefix + `--project ' + BRAIN + '` pin guarantee the lesson lands in the brain regardless of your CWD. Then run `' + DZ + ' statusline --fa-record --slug ' + SLUG + ' --step "Step 8 QE" --recalled 3 --stored <count taught> --reinforced <count reinforced> --mode ' + MODE + ' --project ' + REPO + '` (run it verbatim via Bash, do not skip). Do NOT teach trivia or invent gaps. Return {grade, gaps, codeTestsAdequate, docTestsPresent}.' + landedNote
|
|
396
|
+
const qePrompt = 'Step 8 (QE - brutal-honesty review, agentic-qe) of /feature-adr for "' + DESC + '" (' + SLUG + '). Adversarially review the SHIPPED code (read it): correctness, edge cases, error handling, and the LOAD-BEARING property the ADR named (ASSERT it has a test - the recurring lesson). Run this ADR gate before final grading: ' + ADR_FITNESS_CHECKLIST + ' Grade A/B/C/D honestly. Assess code-test adequacy + doc-test presence. List CONFIRMED gaps with severity. Write ' + FDIR + '/08_qe_report.md with an ADR Fitness Checklist section showing PASS/FAIL per ADR and evidence for the Confirmation-linked test. MANDATORY SELF-LEARNING STORE (close the loop, never skip): compare every candidate lesson against the Step-0 recalled LEARNED patterns above. Teach ONLY lessons NOT covered by Step-0 recall. On overlap, run `dz teach --reinforce "<recalled pattern id or exact text>" --project ' + BRAIN + '` instead of minting a near-duplicate; if --reinforce is unavailable, skip the duplicate teach and report `reinforced existing pattern <id>` in the QE report. Store every genuinely new lesson in the CANONICAL BRAIN store at `' + BRAIN + '` so it is NOT lost to a target repo you may have cd`d into. Via Bash run EXACTLY `' + DZ_TEACH('<a durable reusable lesson from this feature - a rule/pattern/pitfall, NOT a checkpoint echo>', '<0.7-0.95>', '<area>') + '` for each genuine NEW lesson (1-3 max, high-signal) — the `cd ' + BRAIN + ' &&` prefix + `--project ' + BRAIN + '` pin guarantee the lesson lands in the brain regardless of your CWD. Then run `' + DZ + ' statusline --fa-record --slug ' + SLUG + ' --step "Step 8 QE" --recalled 3 --stored <count taught> --reinforced <count reinforced> --mode ' + MODE + ' --project ' + REPO + '` (run it verbatim via Bash, do not skip). Do NOT teach trivia or invent gaps. Return {grade, gaps, codeTestsAdequate, docTestsPresent}.' + landedNote
|
|
362
397
|
// CROSS-MODEL QE (load-bearing): resolveStageModel('qe') derives the OTHER family than the resolved
|
|
363
398
|
// coder when args.models.qe is unset (coder-codex ⇒ opus; coder-Claude ⇒ codex, or opus if codex absent).
|
|
364
399
|
// An explicit args.models.qe wins. A Claude qe spec is merged onto the qe-code-reviewer base (role
|