Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 100 additions & 14 deletions docs/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,25 @@ Each step has a designated agent and a specific deliverable. No step is skipped.
│ │
│ Phase 1 — Project Discovery (once per project) │
│ PO asks stakeholder 7 questions → silent pre-mortem │
│ → baseline → create backlog/<name>.feature stubs │
│ → paraphrase + clarify + summarize → stakeholder confirms │
│ → baseline docs/features/discovery.md │
│ → create backlog/<name>.feature stubs (discovery section only) │
│ │
│ Phase 2 — Feature Discovery (per feature) │
│ PO populates Entities table → generates questions from gaps │
│ → interview rounds → stakeholder says "baseline" │
│ PO populates Entities table in .feature file description │
│ → generates questions from gaps, ambiguities, boundaries │
│ → interview rounds → after each round: │
│ paraphrase + clarify + summarize → stakeholder confirms │
│ → stakeholder says "baseline" to freeze discovery │
│ → decomposition check (>2 concerns or >8 examples → split) │
│ → Status: BASELINED written into .feature file description │
│ │
│ Phase 3 — Stories (PO alone) │
│ Write Rule: blocks with user story headers (no Examples yet) │
│ commit: feat(stories): write user stories for <name> │
│ │
│ Phase 4 — Criteria (PO alone) │
│ Silent pre-mortem per Rule │
│ Write @id-tagged Example: blocks under each Rule: │
│ commit: feat(criteria): write acceptance criteria for <name> │
│ ★ FROZEN — changes require @deprecated + new Example │
Expand All @@ -58,11 +65,14 @@ Each step has a designated agent and a specific deliverable. No step is skipped.
├─────────────────────────────────────────────────────────────────────┤
│ │
│ mv backlog/<name>.feature → in-progress/<name>.feature │
│ Read discovery + feature file │
│ Read docs/features/discovery.md (project-level) │
│ Read ALL backlog .feature files (discovery + entities sections) │
│ Read in-progress .feature file (full) │
│ Identify cross-feature entities, shared interfaces, extension pts │
│ Silent pre-mortem (YAGNI/KISS/DRY/SOLID/OC/patterns) │
│ Append Architecture section to feature file description
│ Append Architecture section to in-progress .feature description │
│ (Module Structure + ADRs + Build Changes) │
│ Architecture contradiction check → PO acknowledges
│ Architecture contradiction check — resolve with PO if needed
│ commit: feat(<name>): add architecture │
│ │
└─────────────────────────────────────────────────────────────────────┘
Expand Down Expand Up @@ -94,13 +104,17 @@ Each step has a designated agent and a specific deliverable. No step is skipped.
│ ↓ │
│ next test │
│ │
│ RED: confirm test fails
│ RED: confirm test fails │
│ GREEN: minimum code to pass (YAGNI + KISS only) │
│ REFACTOR: DRY → SOLID → Object Calisthenics (9 rules) │
│ → type hints → docstrings │
│ SELF-DECLARE: write ## Self-Declaration block in TODO.md │
│ 21-item checklist with file:line evidence │
│ 21-item checklist (YAGNI×2, KISS×2, DRY×2, │
│ SOLID×5, OC×9, Semantic×1) with file:line evidence │
│ each item: checked box + evidence, or N/A + reason │
│ REVIEWER: code-design check only (no lint/pyright/coverage) │
│ reviewer independently verifies YES claims │
│ reviewer does NOT re-audit self-declared failures │
│ COMMIT: feat(<name>): implement <what> │
│ │
│ After all tests green: │
Expand Down Expand Up @@ -142,7 +156,7 @@ Each step has a designated agent and a specific deliverable. No step is skipped.
│ │
│ ACCEPTED: │
│ mv in-progress/<name>.feature → completed/<name>.feature │
│ developer creates PR + tags release
│ developer creates PR (squash merge) + tags release │
│ │
│ REJECTED: │
│ feedback in TODO.md → back to relevant step │
Expand All @@ -152,13 +166,64 @@ Each step has a designated agent and a specific deliverable. No step is skipped.

---

## Feature File Structure

Each feature is a single `.feature` file. The free-form description before the first `Rule:` contains all discovery content added progressively through the workflow:

```
Feature: <title>

Discovery:

Status: BASELINED (YYYY-MM-DD)

Entities:
| Type | Name | Candidate Class/Method | In Scope |

Rules (Business):
- <business rule>

Constraints:
- <non-functional requirement>

Questions:
| ID | Question | Answer | Status |

Architecture: ← added at Step 2 by developer

### Module Structure
- <package>/domain/entity.py — ...

### Key Decisions
ADR-001: <title>
Decision: <what>
Reason: <why>

Rule: <story title>
As a <role>
I want <goal>
So that <benefit>

@id:a3f2b1c4
Example: <scenario>
Given <context>
When <action>
Then <observable outcome>
```

Two discovery sources:
- `docs/features/discovery.md` — project-level (Who/What/Why/When, once per project)
- Feature file description — per-feature discovery, entities, questions, architecture

---

## Supporting Tools

| Command | When | Purpose |
|---|---|---|
| `uv run task gen-tests` | Step 3, Step 4 | Reads `.feature` files → creates/syncs test stubs in `tests/features/` |
| `uv run task gen-tests -- --check` | Before gen-tests | Dry run — preview what would change |
| `uv run task gen-tests -- --orphans` | Step 5 | List tests with no matching `@id` |
| `uv run task gen-tests -- --orphans` | Step 5 | List tests with no matching `@id` — already validated by gen-tests |
| `uv run task gen-todo` | Every session | Reads in-progress `.feature` → syncs `TODO.md` |
| `uv run task gen-id` | Step 1 Phase 4 | Generate 8-char hex `@id` for a new Example |
| `uv run task test-fast` | Step 4 cycle | Fast test run (no coverage) — used during Red-Green-Refactor |
Expand All @@ -183,21 +248,41 @@ tests/

---

## TODO.md Structure (Step 4)
## TODO.md Structure

```markdown
# Current Work

Feature: <name>
Step: 4 (implement)
Step: <1-6> (<step name>)
Source: docs/features/in-progress/<name>.feature

## Cycle State
Test: @id:<hex> — <description>
Phase: RED | GREEN | REFACTOR | SELF-DECLARE | REVIEWER(code-design) | COMMITTED

## Self-Declaration (@id:<hex>)
- [x] YAGNI-1 … SOLID-D … OC-1…OC-9 … Semantic (21 items, file:line each)
- [x] YAGNI-1: No abstractions beyond current AC — `file:line`
- [x] YAGNI-2: No speculative parameters or flags — `file:line`
- [x] KISS-1: Every function has one job — `file:line`
- [x] KISS-2: No unnecessary indirection — `file:line`
- [x] DRY-1: No duplicated logic — `file:line`
- [x] DRY-2: Every shared concept in one place — `file:line`
- [x] SOLID-S: One reason to change — `file:line`
- [x] SOLID-O: Extension, not modification — `file:line` or N/A
- [x] SOLID-L: Subtypes fully substitutable — `file:line` or N/A
- [x] SOLID-I: No forced stub methods — `file:line` or N/A
- [x] SOLID-D: Domain depends on Protocols — `file:line`
- [x] OC-1: One indent level per method — `file:line`
- [x] OC-2: No else after return — `file:line` or N/A
- [x] OC-3: No bare primitives as domain concepts — `file:line` or N/A
- [x] OC-4: No bare collections as domain values — `file:line` or N/A
- [x] OC-5: No chained dot navigation — `file:line` or N/A
- [x] OC-6: No abbreviations — `file:line` or N/A
- [x] OC-7: Functions ≤ 20 lines, classes ≤ 50 lines — `file:line`
- [x] OC-8: ≤ 2 instance variables per class — `file:line`
- [x] OC-9: No getters/setters — `file:line` or N/A
- [x] Semantic: test abstraction matches AC level — `file:line`

## Progress
- [x] @id:<hex>: <done> — reviewer(code-design) APPROVED
Expand All @@ -208,6 +293,8 @@ Phase: RED | GREEN | REFACTOR | SELF-DECLARE | REVIEWER(code-design) | COMMITTED
<one actionable sentence>
```

`## 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.

---

## Roles
Expand All @@ -232,7 +319,6 @@ Phase: RED | GREEN | REFACTOR | SELF-DECLARE | REVIEWER(code-design) | COMMITTED
| Class length | ≤ 50 lines |
| Max nesting | 2 levels |
| Instance variables per class | ≤ 2 |
| Uncovered `@id` tags | 0 |
| `noqa` comments | 0 |
| `type: ignore` comments | 0 |
| Orphaned tests | 0 |
Expand Down
Loading