@@ -35,18 +35,25 @@ Each step has a designated agent and a specific deliverable. No step is skipped.
3535│ │
3636│ Phase 1 — Project Discovery (once per project) │
3737│ PO asks stakeholder 7 questions → silent pre-mortem │
38- │ → baseline → create backlog/<name>.feature stubs │
38+ │ → paraphrase + clarify + summarize → stakeholder confirms │
39+ │ → baseline docs/features/discovery.md │
40+ │ → create backlog/<name>.feature stubs (discovery section only) │
3941│ │
4042│ Phase 2 — Feature Discovery (per feature) │
41- │ PO populates Entities table → generates questions from gaps │
42- │ → interview rounds → stakeholder says "baseline" │
43+ │ PO populates Entities table in .feature file description │
44+ │ → generates questions from gaps, ambiguities, boundaries │
45+ │ → interview rounds → after each round: │
46+ │ paraphrase + clarify + summarize → stakeholder confirms │
47+ │ → stakeholder says "baseline" to freeze discovery │
4348│ → decomposition check (>2 concerns or >8 examples → split) │
49+ │ → Status: BASELINED written into .feature file description │
4450│ │
4551│ Phase 3 — Stories (PO alone) │
4652│ Write Rule: blocks with user story headers (no Examples yet) │
4753│ commit: feat(stories): write user stories for <name> │
4854│ │
4955│ Phase 4 — Criteria (PO alone) │
56+ │ Silent pre-mortem per Rule │
5057│ Write @id-tagged Example: blocks under each Rule: │
5158│ commit: feat(criteria): write acceptance criteria for <name> │
5259│ ★ FROZEN — changes require @deprecated + new Example │
@@ -58,11 +65,14 @@ Each step has a designated agent and a specific deliverable. No step is skipped.
5865├─────────────────────────────────────────────────────────────────────┤
5966│ │
6067│ mv backlog/<name>.feature → in-progress/<name>.feature │
61- │ Read discovery + feature file │
68+ │ Read docs/features/discovery.md (project-level) │
69+ │ Read ALL backlog .feature files (discovery + entities sections) │
70+ │ Read in-progress .feature file (full) │
71+ │ Identify cross-feature entities, shared interfaces, extension pts │
6272│ Silent pre-mortem (YAGNI/KISS/DRY/SOLID/OC/patterns) │
63- │ Append Architecture section to feature file description │
73+ │ Append Architecture section to in-progress . feature description │
6474│ (Module Structure + ADRs + Build Changes) │
65- │ Architecture contradiction check → PO acknowledges │
75+ │ Architecture contradiction check — resolve with PO if needed │
6676│ commit: feat(<name>): add architecture │
6777│ │
6878└─────────────────────────────────────────────────────────────────────┘
@@ -94,13 +104,17 @@ Each step has a designated agent and a specific deliverable. No step is skipped.
94104│ ↓ │
95105│ next test │
96106│ │
97- │ RED: confirm test fails │
107+ │ RED: confirm test fails │
98108│ GREEN: minimum code to pass (YAGNI + KISS only) │
99109│ REFACTOR: DRY → SOLID → Object Calisthenics (9 rules) │
100110│ → type hints → docstrings │
101111│ SELF-DECLARE: write ## Self-Declaration block in TODO.md │
102- │ 21-item checklist with file:line evidence │
112+ │ 21-item checklist (YAGNI×2, KISS×2, DRY×2, │
113+ │ SOLID×5, OC×9, Semantic×1) with file:line evidence │
114+ │ each item: checked box + evidence, or N/A + reason │
103115│ REVIEWER: code-design check only (no lint/pyright/coverage) │
116+ │ reviewer independently verifies YES claims │
117+ │ reviewer does NOT re-audit self-declared failures │
104118│ COMMIT: feat(<name>): implement <what> │
105119│ │
106120│ After all tests green: │
@@ -142,7 +156,7 @@ Each step has a designated agent and a specific deliverable. No step is skipped.
142156│ │
143157│ ACCEPTED: │
144158│ mv in-progress/<name>.feature → completed/<name>.feature │
145- │ developer creates PR + tags release │
159+ │ developer creates PR (squash merge) + tags release │
146160│ │
147161│ REJECTED: │
148162│ feedback in TODO.md → back to relevant step │
@@ -152,13 +166,64 @@ Each step has a designated agent and a specific deliverable. No step is skipped.
152166
153167---
154168
169+ ## Feature File Structure
170+
171+ Each feature is a single ` .feature ` file. The free-form description before the first ` Rule: ` contains all discovery content added progressively through the workflow:
172+
173+ ```
174+ Feature: <title>
175+
176+ Discovery:
177+
178+ Status: BASELINED (YYYY-MM-DD)
179+
180+ Entities:
181+ | Type | Name | Candidate Class/Method | In Scope |
182+
183+ Rules (Business):
184+ - <business rule>
185+
186+ Constraints:
187+ - <non-functional requirement>
188+
189+ Questions:
190+ | ID | Question | Answer | Status |
191+
192+ Architecture: ← added at Step 2 by developer
193+
194+ ### Module Structure
195+ - <package>/domain/entity.py — ...
196+
197+ ### Key Decisions
198+ ADR-001: <title>
199+ Decision: <what>
200+ Reason: <why>
201+
202+ Rule: <story title>
203+ As a <role>
204+ I want <goal>
205+ So that <benefit>
206+
207+ @id:a3f2b1c4
208+ Example: <scenario>
209+ Given <context>
210+ When <action>
211+ Then <observable outcome>
212+ ```
213+
214+ Two discovery sources:
215+ - ` docs/features/discovery.md ` — project-level (Who/What/Why/When, once per project)
216+ - Feature file description — per-feature discovery, entities, questions, architecture
217+
218+ ---
219+
155220## Supporting Tools
156221
157222| Command | When | Purpose |
158223| ---| ---| ---|
159224| ` uv run task gen-tests ` | Step 3, Step 4 | Reads ` .feature ` files → creates/syncs test stubs in ` tests/features/ ` |
160225| ` uv run task gen-tests -- --check ` | Before gen-tests | Dry run — preview what would change |
161- | ` uv run task gen-tests -- --orphans ` | Step 5 | List tests with no matching ` @id ` |
226+ | ` uv run task gen-tests -- --orphans ` | Step 5 | List tests with no matching ` @id ` — already validated by gen-tests |
162227| ` uv run task gen-todo ` | Every session | Reads in-progress ` .feature ` → syncs ` TODO.md ` |
163228| ` uv run task gen-id ` | Step 1 Phase 4 | Generate 8-char hex ` @id ` for a new Example |
164229| ` uv run task test-fast ` | Step 4 cycle | Fast test run (no coverage) — used during Red-Green-Refactor |
@@ -183,21 +248,41 @@ tests/
183248
184249---
185250
186- ## TODO.md Structure (Step 4)
251+ ## TODO.md Structure
187252
188253``` markdown
189254# Current Work
190255
191256Feature: <name >
192- Step: 4 (implement )
257+ Step: <1-6> (< step name > )
193258Source: docs/features/in-progress/<name >.feature
194259
195260## Cycle State
196261Test: @id :<hex > — <description >
197262Phase: RED | GREEN | REFACTOR | SELF-DECLARE | REVIEWER(code-design) | COMMITTED
198263
199264## Self-Declaration (@id :<hex >)
200- - [x] YAGNI-1 … SOLID-D … OC-1…OC-9 … Semantic (21 items, file: line each)
265+ - [x] YAGNI-1: No abstractions beyond current AC — ` file:line `
266+ - [x] YAGNI-2: No speculative parameters or flags — ` file:line `
267+ - [x] KISS-1: Every function has one job — ` file:line `
268+ - [x] KISS-2: No unnecessary indirection — ` file:line `
269+ - [x] DRY-1: No duplicated logic — ` file:line `
270+ - [x] DRY-2: Every shared concept in one place — ` file:line `
271+ - [x] SOLID-S: One reason to change — ` file:line `
272+ - [x] SOLID-O: Extension, not modification — ` file:line ` or N/A
273+ - [x] SOLID-L: Subtypes fully substitutable — ` file:line ` or N/A
274+ - [x] SOLID-I: No forced stub methods — ` file:line ` or N/A
275+ - [x] SOLID-D: Domain depends on Protocols — ` file:line `
276+ - [x] OC-1: One indent level per method — ` file:line `
277+ - [x] OC-2: No else after return — ` file:line ` or N/A
278+ - [x] OC-3: No bare primitives as domain concepts — ` file:line ` or N/A
279+ - [x] OC-4: No bare collections as domain values — ` file:line ` or N/A
280+ - [x] OC-5: No chained dot navigation — ` file:line ` or N/A
281+ - [x] OC-6: No abbreviations — ` file:line ` or N/A
282+ - [x] OC-7: Functions ≤ 20 lines, classes ≤ 50 lines — ` file:line `
283+ - [x] OC-8: ≤ 2 instance variables per class — ` file:line `
284+ - [x] OC-9: No getters/setters — ` file:line ` or N/A
285+ - [x] Semantic: test abstraction matches AC level — ` file:line `
201286
202287## Progress
203288- [x] @id :<hex >: <done > — reviewer(code-design) APPROVED
@@ -208,6 +293,8 @@ Phase: RED | GREEN | REFACTOR | SELF-DECLARE | REVIEWER(code-design) | COMMITTED
208293<one actionable sentence >
209294```
210295
296+ ` ## Cycle State ` is updated at every phase transition. ` ## Self-Declaration ` is replaced per-test cycle. Both sections are present only during Step 4; omit when in other steps.
297+
211298---
212299
213300## Roles
@@ -232,7 +319,6 @@ Phase: RED | GREEN | REFACTOR | SELF-DECLARE | REVIEWER(code-design) | COMMITTED
232319| Class length | ≤ 50 lines |
233320| Max nesting | 2 levels |
234321| Instance variables per class | ≤ 2 |
235- | Uncovered ` @id ` tags | 0 |
236322| ` noqa ` comments | 0 |
237323| ` type: ignore ` comments | 0 |
238324| Orphaned tests | 0 |
0 commit comments