From cbcc4d1b1a40b1741a0e9418a154b43b71cbce6e Mon Sep 17 00:00:00 2001 From: nullhack Date: Sun, 19 Apr 2026 10:20:33 -0400 Subject: [PATCH 1/3] fix(verify): correct stale Self-Declaration location references SE Self-Declaration is communicated verbally in the handoff message, not written to TODO.md. Three references in verify/SKILL.md still pointed to TODO.md from the v4.1 era when it was a written block. --- .opencode/skills/verify/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.opencode/skills/verify/SKILL.md b/.opencode/skills/verify/SKILL.md index e3e35c0..f748de3 100644 --- a/.opencode/skills/verify/SKILL.md +++ b/.opencode/skills/verify/SKILL.md @@ -19,7 +19,7 @@ This skill guides the reviewer through Step 4: independent verification that the ## When to Use (Step 4) -After the software-engineer signals Step 3 is complete and all self-verification checks pass. Do not start verification until the software-engineer has committed all work and written the Self-Declaration. +After the software-engineer signals Step 3 is complete and all self-verification checks pass. Do not start verification until the software-engineer has committed all work and communicated the Self-Declaration verbally in the handoff message. The reviewer produces one written report (see template below) that includes: all gate results, the SE Self-Declaration Audit, the **Reviewer Stance Declaration**, and the final APPROVED/REJECTED verdict. @@ -31,7 +31,7 @@ Read `docs/features/in-progress/.feature`. Extract: - All `@id` tags and their Example titles from `Rule:` blocks - The interaction model (if the feature involves user interaction) - The architectural decisions in `docs/architecture.md` relevant to this feature -- The software-engineer's Self-Declaration from `TODO.md` +- The software-engineer's Self-Declaration (communicated verbally in the handoff message) ### 2. pyproject.toml Gate @@ -160,7 +160,7 @@ Record what input was given and what output was observed. ### 8. Self-Declaration Audit -Read the software-engineer's Self-Declaration from `TODO.md`. +Read the software-engineer's Self-Declaration from the handoff message. For every **AGREE** claim: - Find the `file:line` — does it hold? From 2c576119b481ef6f3c01116542dced85afe776b7 Mon Sep 17 00:00:00 2001 From: nullhack Date: Sun, 19 Apr 2026 10:45:22 -0400 Subject: [PATCH 2/3] refactor(reviewer): slim reviewer.md and verify skill to reduce token load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - reviewer.md: remove default hypothesis, After APPROVED block, and Available Skills list — all duplicated from verify/SKILL.md which is always loaded in the same session (ai-agents.md #24, #26) - verify/SKILL.md v4.0: - drop Standards Summary table (pure restatement of inline content) - drop 'When to Use' section (no information beyond skill name) - OC size/nesting rules (5d rules 1 and 7) cross-reference 6b thresholds instead of repeating values - replace 5d OC table with design-patterns skill reference (on-demand loading per ai-agents.md #23); commitment-device structure preserved inside that skill - move Self-Declaration Audit to Step 5 (before code review) — if SE flagged a DISAGREE, reviewer saves all of code review before rejecting - DISAGREE handling: triage gate instead of hard reject — accepts genuine out-of-SE-control constraints with a note and suggested alternative; rejects weak/unjustified deviations with specific fix - renumber code review sub-sections 5a-5g → 6a-6g --- .opencode/agents/reviewer.md | 14 ----- .opencode/skills/verify/SKILL.md | 92 +++++++++++--------------------- 2 files changed, 30 insertions(+), 76 deletions(-) diff --git a/.opencode/agents/reviewer.md b/.opencode/agents/reviewer.md index 4bdab37..0f0b350 100644 --- a/.opencode/agents/reviewer.md +++ b/.opencode/agents/reviewer.md @@ -29,8 +29,6 @@ permissions: You verify that work is done correctly by running commands and reading code. You do not write or edit files. -**Your default hypothesis is that the code is broken despite passing automated checks. Your job is to find the failure mode. If you cannot find one after thorough investigation, APPROVE. If you find one, REJECTED.** - ## Session Start Load `skill session-workflow` first. Then load `skill verify` for Step 4 verification. @@ -44,13 +42,6 @@ Load `skill session-workflow` first. Then load `skill verify` for Step 4 verific - **Every PASS/FAIL cell must have evidence.** Empty evidence = UNCHECKED = REJECTED. - **Never move `.feature` files.** The PO is the sole owner of all feature file moves. After producing an APPROVED report, update TODO.md and stop — the PO accepts and moves the file. -## After APPROVED - -When your report verdict is APPROVED: -1. Write the report as described in `skill verify`. -2. Update TODO.md `## Next` line: `Run @product-owner — accept feature at Step 5.` -3. Stop. Do not touch `.feature` files. The PO reviews the feature themselves and moves it to `completed/`. - ## Gap Reporting If you discover an observable behavior with no acceptance criterion: @@ -63,9 +54,4 @@ If you discover an observable behavior with no acceptance criterion: You never edit `.feature` files or add Examples yourself. -## Available Skills -- `session-workflow` — session start/end protocol -- `refactor` — Code refactoring heuristics -- `design-patterns` — Reference for code smell and design patterns -- `verify` — Step 4: full verification protocol with all tables, gates, and report template diff --git a/.opencode/skills/verify/SKILL.md b/.opencode/skills/verify/SKILL.md index f748de3..5e2ee07 100644 --- a/.opencode/skills/verify/SKILL.md +++ b/.opencode/skills/verify/SKILL.md @@ -1,7 +1,7 @@ --- name: verify description: Step 4 — run all verification commands, review code quality, and produce a written report -version: "3.0" +version: "4.0" author: reviewer audience: reviewer workflow: feature-lifecycle @@ -17,11 +17,7 @@ This skill guides the reviewer through Step 4: independent verification that the **You never move `.feature` files.** After producing an APPROVED report: update TODO.md `Next:` to `Run @product-owner — accept feature at Step 5.` then stop. The PO accepts the feature and moves the file. -## When to Use (Step 4) - -After the software-engineer signals Step 3 is complete and all self-verification checks pass. Do not start verification until the software-engineer has committed all work and communicated the Self-Declaration verbally in the handoff message. - -The reviewer produces one written report (see template below) that includes: all gate results, the SE Self-Declaration Audit, the **Reviewer Stance Declaration**, and the final APPROVED/REJECTED verdict. +The reviewer produces one written report (see template below) that includes: all gate results, the SE Self-Declaration Audit, the **Reviewer Stance Declaration**, and the final APPROVED/REJECTED verdict. Do not start until the software-engineer has committed all work and communicated the Self-Declaration verbally in the handoff message. ## Step-by-Step @@ -62,13 +58,28 @@ Run before code review. If any row is FAIL, stop immediately with REJECTED. | App exits cleanly | `timeout 10s uv run task run` | Exit 0 or non-124 | Exit 124 (timeout/hang) | Fix the hang | | Output changes when input changes | Run app, change an input or condition, observe output | Output changes accordingly | Output is static | Implement real logic | -### 5. Code Review +### 5. Self-Declaration Audit + +Read the software-engineer's Self-Declaration from the handoff message. + +For every **AGREE** claim: +- Find the `file:line` — does it hold? + +For every **DISAGREE** claim: +- Read the justification carefully. +- If the constraint genuinely falls outside the SE's control (e.g. external library forces method chaining, dataclass/Pydantic/TypedDict exemption for ≤2 ivars): accept with a note in the report and suggest the closest compliant alternative if one exists. +- If the justification is weak, incomplete, or a best-practice alternative exists that the SE did not consider: REJECT with the specific alternative stated. +- If there is no justification: REJECT. + +Undeclared violations found during code review → REJECT. + +### 6. Code Review Read the source files changed in this feature. **Do this before running lint/static-check/test** — if code review finds a design problem, commands will need to re-run after the fix anyway. **Stop on first failure category — do not accumulate issues.** -#### 5a. Correctness — any FAIL → REJECTED +#### 6a. Correctness — any FAIL → REJECTED | Check | How to check | PASS | FAIL | Fix | |---|---|---|---|---| @@ -76,7 +87,7 @@ Read the source files changed in this feature. **Do this before running lint/sta | No duplicate logic (DRY) | Search for repeated blocks doing the same thing | None found | Duplication found | Extract to shared function | | No over-engineering (YAGNI) | Check for abstractions with no current use | None found | Unused abstraction | Remove unused code | -#### 5b. Simplicity (KISS) — any FAIL → REJECTED +#### 6b. Simplicity (KISS) — any FAIL → REJECTED | Check | How to check | PASS | FAIL | Fix | |---|---|---|---|---| @@ -85,7 +96,7 @@ Read the source files changed in this feature. **Do this before running lint/sta | Functions ≤ 20 lines | Count lines | ≤ 20 | > 20 | Extract helper | | Classes ≤ 50 lines | Count lines | ≤ 50 | > 50 | Split class | -#### 5c. SOLID — any FAIL → REJECTED +#### 6c. SOLID — any FAIL → REJECTED | Principle | Why it matters | What to check | How to check | |---|---|---|---| @@ -95,21 +106,11 @@ Read the source files changed in this feature. **Do this before running lint/sta | ISP | Fat interfaces force unused methods | No Protocol forces stub implementations | Check for NotImplementedError | | DIP | Concrete I/O makes unit testing impossible | High-level depends on abstractions | Check domain imports no I/O/DB | -#### 5d. Object Calisthenics — any FAIL → REJECTED +#### 6d. Object Calisthenics — any FAIL → REJECTED -| # | Rule | How to check | -|---|---|---| -| 1 | One indent level per method | Count max nesting | -| 2 | No `else` after `return` | Search for `else` after early returns | -| 3 | Primitives wrapped | Bare `int`/`str` in domain signatures = FAIL | -| 4 | Collections wrapped | `list[X]` as domain value = FAIL | -| 5 | One dot per line | `a.b.c()` chains = FAIL | -| 6 | No abbreviations | `mgr`, `tmp`, `calc` = FAIL | -| 7 | Small entities | Functions > 20 lines or classes > 50 lines = FAIL | -| 8 | ≤ 2 instance variables | Count `self.x` in `__init__` — >2 = FAIL | -| 9 | No getters/setters | `get_x()`/`set_x()` = FAIL | - -#### 5e. Design Patterns — any FAIL → REJECTED +Load `skill design-patterns` and apply the full OC checklist (9 rules). Record a PASS/FAIL with `file:line` evidence for each rule. Rules 1 and 7 (nesting and entity size) share thresholds with 6b above. + +#### 6e. Design Patterns — any FAIL → REJECTED | Code smell | Pattern missed | How to check | |---|---|---| @@ -119,7 +120,7 @@ Read the source files changed in this feature. **Do this before running lint/sta | External dep without Protocol | Repository/Adapter | Check dep injection | | 0 domain classes, many functions | Missing domain model | Count classes vs functions | -#### 5f. Tests — any FAIL → REJECTED +#### 6f. Tests — any FAIL → REJECTED | Check | How to check | PASS | FAIL | |---|---|---|---| @@ -131,7 +132,7 @@ Read the source files changed in this feature. **Do this before running lint/sta | Function naming | Matches `test__<8char_hex>` | All match | Mismatch | | Hypothesis tests have `@slow` | Read every `@given` for `@slow` marker | All present | Any missing | -#### 5g. Code Quality — any FAIL → REJECTED +#### 6g. Code Quality — any FAIL → REJECTED | Check | How to check | PASS | FAIL | |---|---|---|---| @@ -140,7 +141,7 @@ Read the source files changed in this feature. **Do this before running lint/sta | Public functions have type hints | Read signatures | All annotated | Missing | | Public functions have docstrings | Read source | Google-style | Missing | -### 6. Run Verification Commands +### 7. Run Verification Commands ```bash uv run task lint @@ -152,24 +153,12 @@ Expected for each: exit 0, no errors. Record exact output on failure. If a command fails, stop and REJECT immediately. Do not run subsequent commands. -### 7. Interactive Verification +### 8. Interactive Verification If the feature involves user interaction: run the app, provide real input, verify output changes. Record what input was given and what output was observed. -### 8. Self-Declaration Audit - -Read the software-engineer's Self-Declaration from the handoff message. - -For every **AGREE** claim: -- Find the `file:line` — does it hold? - -For every **DISAGREE** claim: -- REJECT — the software-engineer must fix before requesting review again. - -Undeclared violations → REJECT. - ### 9. Write the Report ```markdown @@ -243,25 +232,4 @@ OR **If REJECTED**: Run `@software-engineer` — apply the fixes listed above, re-run quality gate, update Self-Declaration, then signal Step 4 again. ``` -## Standards Summary - -| Check | Standard | -|---|---| -| Test coverage | 100% | -| Type errors | 0 | -| Lint errors | 0 | -| Function length | ≤ 20 lines | -| Class length | ≤ 50 lines | -| Max nesting | 2 levels | -| Instance variables | ≤ 2 per class | -| Uncovered `@id` tags | 0 | -| `noqa` comments | 0 | -| `type: ignore` | 0 | -| Semantic alignment mismatches | 0 | -| SOLID FAIL rows | 0 | -| ObjCal FAIL rows | 0 | -| Design pattern FAIL rows | 0 | -| Duplicate `@id` in tests | 0 | -| Empty evidence cells | 0 | -| Orphaned tests | 0 | -| Hypothesis tests missing `@pytest.mark.slow` | 0 | + From edd2587cf038ba800eadda11db0adfa1822664f3 Mon Sep 17 00:00:00 2001 From: nullhack Date: Sun, 19 Apr 2026 13:42:21 -0400 Subject: [PATCH 3/3] chore(release): bump version to v6.1.20260419 - Contextual Ambystoma --- .opencode/skills/create-skill/SKILL.md | 1 + .opencode/skills/implementation/SKILL.md | 7 +- .opencode/skills/living-docs/SKILL.md | 210 +++++++++ .opencode/skills/scope/SKILL.md | 4 +- AGENTS.md | 7 +- CHANGELOG.md | 23 + Dockerfile | 51 --- docker-compose.yml | 86 ---- docs/architecture/adr-template.md | 10 - docs/c4/.gitkeep | 0 docs/discovery.md | 2 +- docs/scientific-research/README.md | 5 +- docs/scientific-research/architecture.md | 66 ++- docs/scientific-research/documentation.md | 69 +++ docs/scientific-research/domain-modeling.md | 91 ++++ docs/workflow.md | 449 -------------------- pyproject.toml | 2 +- uv.lock | 2 +- 18 files changed, 476 insertions(+), 609 deletions(-) create mode 100644 .opencode/skills/living-docs/SKILL.md delete mode 100644 Dockerfile delete mode 100644 docker-compose.yml delete mode 100644 docs/architecture/adr-template.md create mode 100644 docs/c4/.gitkeep create mode 100644 docs/scientific-research/documentation.md delete mode 100644 docs/workflow.md diff --git a/.opencode/skills/create-skill/SKILL.md b/.opencode/skills/create-skill/SKILL.md index db8a679..39504b7 100644 --- a/.opencode/skills/create-skill/SKILL.md +++ b/.opencode/skills/create-skill/SKILL.md @@ -141,5 +141,6 @@ Add the skill name to the agent's "Available Skills" section so the agent knows | `code-quality` | software-engineer | Quick reference — redirects to verify | | `pr-management` | software-engineer | Step 5: create PR with squash merge | | `git-release` | software-engineer | Step 5: calver versioning and release | +| `living-docs` | product-owner | Step 5 (after acceptance) + on stakeholder demand: C4 diagrams + glossary | | `create-skill` | software-engineer | Create new skills | | `create-agent` | human-user | Create new agents with research-backed design | \ No newline at end of file diff --git a/.opencode/skills/implementation/SKILL.md b/.opencode/skills/implementation/SKILL.md index 0aa3d0e..8fbf5fd 100644 --- a/.opencode/skills/implementation/SKILL.md +++ b/.opencode/skills/implementation/SKILL.md @@ -44,9 +44,10 @@ Design correctness is far more important than lint/pyright/coverage compliance. ### Read Phase (all before writing anything) 1. Read `docs/discovery.md` (project-level synthesis changelog) and optionally `docs/discovery_journal.md` (Q&A history for context) -2. Read **ALL** `.feature` files in `docs/features/backlog/` (discovery + entities sections) -3. Read in-progress `.feature` file (full: Rules + Examples + @id) -4. Read **ALL** existing `.py` files in `/` — understand what already exists before adding anything +2. Read `docs/glossary.md` if it exists — use existing domain terms when naming classes, methods, and modules; do not invent synonyms for terms already defined +3. Read **ALL** `.feature` files in `docs/features/backlog/` (discovery + entities sections) +4. Read in-progress `.feature` file (full: Rules + Examples + @id) +5. Read **ALL** existing `.py` files in `/` — understand what already exists before adding anything ### Domain Analysis diff --git a/.opencode/skills/living-docs/SKILL.md b/.opencode/skills/living-docs/SKILL.md new file mode 100644 index 0000000..29e0b80 --- /dev/null +++ b/.opencode/skills/living-docs/SKILL.md @@ -0,0 +1,210 @@ +--- +name: living-docs +description: Generate and update C4 architecture diagrams and the living glossary from existing project docs +version: "1.0" +author: product-owner +audience: product-owner +workflow: feature-lifecycle +--- + +# Living Docs + +This skill generates and updates two living documents after a feature is accepted (Step 5) or on stakeholder request: the **C4 architecture diagrams** and the **living glossary**. Both are derived from existing project documentation — no new decisions are made. + +The glossary is a secondary artifact derived from the code, the domain model, and domain-expert conversations. The canonical sources are the completed feature files, the discovery synthesis, and the architectural decisions. The glossary is a human-readable projection of those sources — not an independent authority. + +## When to Use + +- **PO at Step 5** — after the feature is accepted and moved to `completed/`, run this skill to reflect the new feature in C4 diagrams and glossary. +- **Stakeholder on demand** — when the stakeholder asks "what does the system look like?" or "what does term X mean in this context?". + +## Ownership Rules + +| Document | Created/Updated by | Inputs read | +|---|---|---| +| `docs/c4/context.md` | `living-docs` skill (PO) | `docs/discovery.md`, `docs/features/completed/` | +| `docs/c4/container.md` | `living-docs` skill (PO) | `docs/architecture.md`, `docs/features/completed/` | +| `docs/glossary.md` | `living-docs` skill (PO) | `docs/discovery.md`, `docs/glossary.md` (existing), `docs/architecture.md`, `docs/features/completed/` | +| `docs/architecture.md` | SE only (Step 2) | — | +| `docs/discovery.md` | PO only (Step 1) | — | + +**Never edit `docs/architecture.md` or `docs/discovery.md` in this skill.** Those files are append-only by their respective owners. This skill reads them; it never writes to them. + +--- + +## Step 1 — Read Phase (all before writing anything) + +Read in this order: + +1. `docs/discovery.md` — project scope, domain model (nouns/verbs), feature list per session +2. `docs/features/completed/` — all completed `.feature` files (full text: Rules, Examples, Constraints) +3. `docs/architecture.md` — all architectural decisions (containers, modules, protocols, external deps) +4. `docs/c4/` — existing C4 diagrams if they exist (update, do not replace from scratch) +5. `docs/glossary.md` — existing glossary if it exists (extend, never remove existing entries) + +Identify from the read phase: + +- **Actors** — named human roles from feature `As a ` clauses and discovery Scope section +- **External systems** — any system outside the package boundary named in features or architecture decisions +- **Containers** — deployable/runnable units identified in `docs/architecture.md` (Hexagonal adapters, CLIs, services) +- **Key domain terms** — all nouns from `docs/discovery.md` Domain Model tables, plus any terms defined in `docs/architecture.md` decisions + +--- + +## Step 2 — Update C4 Context Diagram (Level 1) + +File: `docs/c4/context.md` + +The Context diagram answers: **who uses the system and what external systems does it interact with?** + +Use Mermaid `C4Context` syntax. Template: + +```markdown +# C4 — System Context + +> Last updated: YYYY-MM-DD +> Source: docs/discovery.md, docs/features/completed/ + +```mermaid +C4Context + title System Context — + + Person(actor1, "", "") + + System(system, "", "<3–5 word system description from discovery.md Scope>") + + System_Ext(ext1, "", "") + + Rel(actor1, system, "") + Rel(system, ext1, "") +``` +``` + +Rules: +- One `Person(...)` per distinct actor found in completed feature files +- One `System_Ext(...)` per external dependency identified in `docs/architecture.md` decisions +- Relationships (`Rel`) use verb phrases from feature `When` clauses or architecture decision labels +- If no external systems are identified in `docs/architecture.md`, omit `System_Ext` entries +- If the file already exists: update only — add new actors/systems, update relationship labels. Never remove an existing entry unless the feature it came from has been explicitly superseded + +--- + +## Step 3 — Update C4 Container Diagram (Level 2) + +File: `docs/c4/container.md` + +The Container diagram answers: **what are the major runnable/deployable units and how do they communicate?** + +Only generate this diagram if `docs/architecture.md` contains at least one decision identifying a distinct container boundary (e.g., a CLI entry point separate from a library, a web server, a background worker, an external service adapter). If the project is a single-container system, note this in the file and skip the diagram body. + +Use Mermaid `C4Container` syntax. Template: + +```markdown +# C4 — Container Diagram + +> Last updated: YYYY-MM-DD +> Source: docs/architecture.md + +```mermaid +C4Container + title Container Diagram — + + Person(actor1, "", "") + + System_Boundary(sys, "") { + Container(container1, "", "", "") + Container(container2, "", "", "") + } + + System_Ext(ext1, "", "") + + Rel(actor1, container1, "") + Rel(container1, container2, "") + Rel(container1, ext1, "") +``` +``` + +Rules: +- Container names and responsibilities come directly from `docs/architecture.md` decisions — do not invent them +- Technology labels come from `pyproject.toml` dependencies when identifiable (e.g., "Python / fire CLI", "Python / FastAPI") +- If the file already exists: update incrementally — do not regenerate from scratch + +--- + +## Step 4 — Update Living Glossary + +File: `docs/glossary.md` + +The glossary answers: **what does each domain term mean in this project's context?** + +### Format + +```markdown +# Glossary — + +> Living document. Updated after each completed feature by the `living-docs` skill. +> Source: docs/discovery.md (Domain Model), docs/features/completed/, docs/architecture.md + +--- + +## + +**Type:** Noun | Verb | Domain Event | Concept | Role | External System + +**Definition:** + +**Bounded context:** + +**First appeared:** + +--- +``` + +### Rules + +- Extract all nouns and verbs from every `### Domain Model` table in `docs/discovery.md` +- Extract all roles from `As a ` clauses in completed `.feature` files +- Extract all external system names from `docs/architecture.md` decisions +- Extract any term defined or clarified in architectural decision `Reason:` fields +- **Do not remove existing glossary entries** — if a term's meaning has changed, add a `**Superseded by:**` line pointing to the new entry and write a new entry +- **Every term must have a traceable source** — completed feature files or `docs/architecture.md` decisions. If a term appears in sources but is never defined, write `Definition: Term appears in [source] but has not been explicitly defined.` Do not invent a definition. +- Terms are sorted alphabetically within the file + +### Merge with existing glossary + +If `docs/glossary.md` already exists: +1. Read all existing entries +2. For each new term found in sources: check if it already exists in the glossary + - Exists, definition unchanged → skip + - Exists, definition changed → append `**Superseded by:** ` to old entry; write new entry + - Does not exist → append new entry in alphabetical order + +--- + +## Step 5 — Commit + +After both C4 diagrams and glossary are updated: + +``` +docs(living-docs): update C4 and glossary after +``` + +If this is a stakeholder-requested update without a specific feature trigger: + +``` +docs(living-docs): refresh C4 diagrams and glossary +``` + +--- + +## Checklist + +- [ ] Read all five source files before writing anything +- [ ] Context diagram reflects all actors from completed feature files +- [ ] Context diagram reflects all external systems from `docs/architecture.md` +- [ ] Container diagram present only if multi-container architecture confirmed in `docs/architecture.md` +- [ ] Glossary contains all nouns and verbs from `docs/discovery.md` Domain Model tables +- [ ] No existing glossary entry removed +- [ ] Every new term has a traceable source in completed feature files or `docs/architecture.md`; no term is invented +- [ ] No edits made to `docs/architecture.md` or `docs/discovery.md` +- [ ] Committed with `docs(living-docs): ...` message diff --git a/.opencode/skills/scope/SKILL.md b/.opencode/skills/scope/SKILL.md index 1ff6099..af0de0f 100644 --- a/.opencode/skills/scope/SKILL.md +++ b/.opencode/skills/scope/SKILL.md @@ -143,7 +143,7 @@ If a feature is new (just created as a stub): write its initial description now. After all `.feature` files are updated, append one `## Session: YYYY-MM-DD` block to `docs/discovery.md`. The block contains: - `### Feature List` — which features were added or changed (0–N entries); if nothing changed, write "No changes" - `### Domain Model` — new or updated domain entities and verbs; if nothing changed, write "No changes" -- `### Scope` (first session only) — 3–5 sentence synthesis of who the users are, what the product does, why it exists, success/failure conditions, and explicit out-of-scope +- `### Context` (first session only) — 3–5 sentence synthesis of who the users are, what the product does, why it exists, success/failure conditions, and explicit out-of-scope **Step D — Mark session complete** @@ -429,7 +429,7 @@ Rules: ## Session: YYYY-MM-DD -### Scope +### Context <3–5 sentence synthesis of who the users are, what the product does, why it exists, success/failure conditions, and out-of-scope boundaries.> (First session only. Omit this subsection in subsequent sessions.) diff --git a/AGENTS.md b/AGENTS.md index cc22f6a..30c737b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -60,6 +60,7 @@ STEP 5: ACCEPT (product-owner) → demo, validate, move .feature to com | `code-quality` | software-engineer | pre-handoff (redirects to `verify`) | | `pr-management` | software-engineer | 5 | | `git-release` | software-engineer | 5 | +| `living-docs` | product-owner | 5 (after acceptance) + on stakeholder demand | | `create-skill` | software-engineer | meta | | `create-agent` | human-user | meta | @@ -117,6 +118,10 @@ docs/ discovery_journal.md ← raw Q&A, PO appends after every session discovery.md ← synthesis changelog, PO appends after every session architecture.md ← all architectural decisions, SE appends after Step 2 + glossary.md ← living glossary, PO updates via living-docs skill + c4/ + context.md ← C4 Level 1 diagram, PO updates via living-docs skill + container.md ← C4 Level 2 diagram, PO updates via living-docs skill features/ backlog/.feature ← narrative + Rules + Examples in-progress/.feature @@ -230,7 +235,7 @@ Use `@software-engineer /skill git-release` for the full release process. When r Every session: load `skill session-workflow`. Read `TODO.md` first, update it at the end. -`TODO.md` is a session bookmark — not a project journal. See `docs/workflow.md` for the full structure including the Cycle State block used during Step 3. +`TODO.md` is a session bookmark — not a project journal. See `.opencode/skills/session-workflow/SKILL.md` for the full structure including the Cycle State block used during Step 3. ## Setup diff --git a/CHANGELOG.md b/CHANGELOG.md index 469a509..01bd738 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,29 @@ All notable changes to this template will be documented in this file. +## [v6.1.20260419] - Contextual Ambystoma - 2026-04-19 (hotfix) + +### Added +- **living-docs skill**: new PO skill for generating C4 architecture diagrams (`docs/c4/context.md`, `docs/c4/container.md`) and maintaining the living glossary (`docs/glossary.md`) after each feature acceptance (Step 5) or on stakeholder demand +- **docs/c4/**: new directory for C4 Level 1 (Context) and Level 2 (Container) Mermaid diagrams; placeholder `.gitkeep` added +- **docs/glossary.md**: new living glossary file owned by `living-docs` skill (PO); terms sourced from completed feature files, `docs/discovery.md` Domain Model, and `docs/architecture.md` decisions +- **Scientific research — documentation.md**: new file with 4 entries (#59–62): Ko et al. 2007 (information needs), Winters et al. 2020 (docs-as-code), Procida 2021 (Diátaxis framework), Allspaw 2012 (blameless post-mortems) +- **Scientific research — domain-modeling.md**: 6 new DDD entries (#63–68): Evans DDD Reference CC-BY, Fowler UbiquitousLanguage bliki, Fowler BoundedContext bliki, Vernon IDDD, Verraes "UL is not a glossary", Evans Whirlpool process +- **Scientific research — architecture.md**: 4 new entries (#55–58): Nygard ADRs, Kruchten 4+1 View Model, Brown C4 Model, Parnas information hiding + +### Changed +- **discovery.md template**: `### Scope` section renamed to `### Context` — the section is a session-level general-context synthesis, not a complete project scope definition +- **scope/SKILL.md**: updated `### Scope` references to `### Context` in Step C instructions and template block +- **living-docs/SKILL.md**: glossary entry format updated — `**Context:**` renamed to `**Bounded context:**` (mandatory for multi-context projects); `Domain Event` added as a distinct Type value; secondary-artifact note added to preamble; source-traceability rule replaces "do not invent" rule; checklist updated accordingly +- **implementation/SKILL.md**: Step 2 Read Phase now includes `docs/glossary.md` as item 2 — SE reads existing domain terms before naming classes, methods, and modules to avoid inventing synonyms +- **create-skill/SKILL.md**: `living-docs` added to available skills table +- **AGENTS.md**: skills table updated with `living-docs`; filesystem structure section updated (`docs/c4/`, `docs/glossary.md` added; `docs/architecture/` subtree removed; TODO.md reference updated) + +### Removed +- **docs/architecture/**: folder deleted; the ADR log lives at `docs/architecture.md` (SE-owned); the old `adr-template.md` inside the folder was redundant +- **docs/workflow.md**: deleted; canonical workflow reference is `AGENTS.md` and the skills under `.opencode/skills/` +- **Dockerfile / docker-compose.yml**: removed as unused template artifacts + ## [v6.0.20260419] - Declarative Nautilus - 2026-04-19 ### Added diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index e6645ec..0000000 --- a/Dockerfile +++ /dev/null @@ -1,51 +0,0 @@ -# syntax=docker/dockerfile:1.7 -# Simplified Dockerfile for python-project-template -# Single-stage development-focused build - -ARG PYTHON_VERSION=3.13.1 - -FROM python:${PYTHON_VERSION}-slim AS base - -# Install uv for fast Python package management -RUN pip install --upgrade pip uv - -# Create non-root user -RUN groupadd --gid 1001 appuser && \ - useradd --uid 1001 --gid appuser --shell /bin/bash --create-home appuser - -WORKDIR /app - -# Copy dependency files first (better layer caching) -COPY pyproject.toml uv.lock* ./ - -# Install dependencies -RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --locked --dev - -# Copy source code -COPY . . - -# Change ownership to appuser -RUN chown -R appuser:appuser /app -USER appuser - -# Configure Python -ENV PYTHONPATH=/app -ENV PYTHONUNBUFFERED=1 -ENV PYTHONDONTWRITEBYTECODE=1 - -# Expose common ports -EXPOSE 8000 8080 5678 - -# Health check -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD python -m app || exit 1 - -# Default command -CMD ["python", "-m", "app"] - -# Labels -LABEL maintainer="eol" -LABEL version="3.0.20260414" -LABEL description="Python template with some awesome tools to quickstart any Python project" -LABEL org.opencontainers.image.source="https://github.com/nullhack/python-project-template" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index f8708f8..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,86 +0,0 @@ -# Docker Compose for python-project-template -# Simplified development setup - -services: - # ============================================================================= - # Main application - # ============================================================================= - app: - build: - context: . - dockerfile: Dockerfile - container_name: python-template-app - volumes: - # Hot reload: mount source code - - ./app:/app/app - - ./tests:/app/tests - - ./pyproject.toml:/app/pyproject.toml:ro - ports: - - "8000:8000" # Main application - - "8080:8080" # Documentation server - - "5678:5678" # Debug port - environment: - - PYTHONPATH=/app - - PYTHONUNBUFFERED=1 - - DEVELOPMENT=true - command: python -m app - restart: unless-stopped - - # ============================================================================= - # Test runner - # ============================================================================= - test: - build: - context: . - dockerfile: Dockerfile - container_name: python-template-test - volumes: - - ./:/app:ro - environment: - - PYTHONPATH=/app - - PYTHONUNBUFFERED=1 - command: task test - profiles: - - test - - # ============================================================================= - # Documentation server - # ============================================================================= - docs: - build: - context: . - dockerfile: Dockerfile - container_name: python-template-docs - volumes: - - ./app:/app/app:ro - - ./pyproject.toml:/app/pyproject.toml:ro - ports: - - "8080:8080" - environment: - - PYTHONPATH=/app - command: task doc-serve - profiles: - - docs - - # ============================================================================= - # Code quality checks - # ============================================================================= - quality: - build: - context: . - dockerfile: Dockerfile - container_name: python-template-quality - volumes: - - ./:/app:ro - environment: - - PYTHONPATH=/app - command: bash -c "task lint && task static-check" - profiles: - - quality - -# ============================================================================= -# Networks -# ============================================================================= -networks: - default: - name: python-template-network \ No newline at end of file diff --git a/docs/architecture/adr-template.md b/docs/architecture/adr-template.md deleted file mode 100644 index d86faf9..0000000 --- a/docs/architecture/adr-template.md +++ /dev/null @@ -1,10 +0,0 @@ -# ADR-NNN: - -**Status:** PROPOSED | ACCEPTED | SUPERSEDED by ADR-NNN - -**Decision:** <what was decided — one sentence> - -**Reason:** <why — one sentence> - -**Alternatives considered:** -- <option>: <why rejected> diff --git a/docs/c4/.gitkeep b/docs/c4/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/discovery.md b/docs/discovery.md index 1f56443..1c91da9 100644 --- a/docs/discovery.md +++ b/docs/discovery.md @@ -4,7 +4,7 @@ ## Session: YYYY-MM-DD -### Scope +### Context <3–5 sentence synthesis: who the users are, what the product does, why it exists, success/failure conditions, and explicit out-of-scope boundaries.> (First session only. Omit this subsection in subsequent sessions.) diff --git a/docs/scientific-research/README.md b/docs/scientific-research/README.md index cb9fd99..3338996 100644 --- a/docs/scientific-research/README.md +++ b/docs/scientific-research/README.md @@ -8,8 +8,9 @@ Theoretical and empirical foundations for the decisions made in this template, o | `testing.md` | 11–15, 51–54 | Observable behavior testing, test-behavior alignment, first-class tests, property-based testing, mutation testing, Canon TDD, GOOS outer/inner loop, Is TDD Dead, BDD origin | | `software-economics.md` | 16 | Cost of change curve (shift left) | | `requirements-elicitation.md` | 17–20, 28–30, 43–50 | INVEST, Example Mapping, declarative Gherkin, MoSCoW, active listening, Kipling 5Ws, BA framework, FDD, affinity mapping, Event Storming, CIT, cognitive interview, laddering, funnel technique, RE issues | -| `domain-modeling.md` | 31 | DDD bounded contexts, ubiquitous language, feature identification | +| `domain-modeling.md` | 31, 63–68 | DDD bounded contexts, ubiquitous language, feature identification, DDD Reference, Fowler UL/BC bliki, Vernon IDDD, Verraes UL-not-glossary, Whirlpool | | `oop-design.md` | 32–35 | Object Calisthenics, Refactoring (Fowler), GoF Design Patterns, SOLID | | `refactoring-empirical.md` | 36–41 | QDIR smell prioritization, smells + architectural refactoring, SPIRIT tool, bad OOP engineering properties, CWC complexity metric, metric threshold unreliability | -| `architecture.md` | 42 | Hexagonal Architecture — ports and adapters | +| `architecture.md` | 42, 55–58 | Hexagonal Architecture, ADRs, 4+1 View Model, C4 model, information hiding | | `ai-agents.md` | 21–27 | Minimal-scope agent design, context isolation, on-demand skills, instruction conflict resolution failure, positional attention degradation, modular prompt de-duplication, three-file separation | +| `documentation.md` | 59–62 | Developer information needs, docs-as-code, Diátaxis documentation framework, blameless post-mortems | diff --git a/docs/scientific-research/architecture.md b/docs/scientific-research/architecture.md index 5b5bb5f..8cf3a9d 100644 --- a/docs/scientific-research/architecture.md +++ b/docs/scientific-research/architecture.md @@ -18,7 +18,69 @@ Foundations for the architectural decisions and patterns used in this template. --- +### 55. Architecture Decision Records (ADRs) + +| | | +|---|---| +| **Source** | Nygard, M. T. (2011). "Documenting Architecture Decisions." *cognitect.com*. https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions | +| **Date** | 2011 | +| **Alternative** | Keeling, M. (2017). *Design It!: From Programmer to Software Architect*. Pragmatic Bookshelf. (Chapter 6: "Architectural Decisions") | +| **Status** | Confirmed — widely adopted industry standard; tooled by adr-tools, ADR Manager, Log4Brains | +| **Core finding** | Architectural decisions should be recorded as short, immutable documents capturing: what was decided, why, and what alternatives were rejected. Without this record, decisions get re-litigated by every new developer (or AI agent) who encounters the codebase, producing rework and re-divergence. | +| **Mechanism** | An ADR is written at decision time, never edited afterward. If the decision changes, a new ADR is written that supersedes the old one. The append-only record becomes a reliable audit trail. The constraint "one sentence per field" forces clarity — if you can't state the reason in one sentence, the decision is not yet understood. | +| **Where used** | `docs/architecture/architecture.md` (ADR template). SE appends one block per non-obvious decision after Step 2. The `living-docs` skill reads ADRs as input for C4 diagram annotations. | + +--- + +### 56. The 4+1 View Model of Architecture + +| | | +|---|---| +| **Source** | Kruchten, P. B. (1995). "The 4+1 View Model of Architecture." *IEEE Software*, 12(6), 42–50. https://doi.org/10.1109/52.469759 | +| **Date** | 1995 | +| **Alternative** | Bass, L., Clements, P., & Kazman, R. (2021). *Software Architecture in Practice* (4th ed.). Addison-Wesley. | +| **Status** | Confirmed — 3,000+ citations; foundational IEEE reference for architectural documentation | +| **Core finding** | A single architectural diagram cannot communicate all relevant aspects of a system. Four distinct views are required: **Logical** (domain objects and relationships), **Process** (runtime behavior and concurrency), **Development** (module organisation and dependencies), **Physical** (deployment topology). A fifth **Scenarios** view (use cases) ties the four together by showing how each scenario exercises each view. | +| **Mechanism** | Different stakeholders need different views: a developer needs the Development view; an operator needs the Physical view; a domain expert needs the Logical view. Conflating views into one diagram produces a cluttered diagram that satisfies nobody. The 4+1 model assigns each concern to its appropriate view and cross-validates them through scenarios. | +| **Where used** | Theoretical foundation for the C4 model (entry 57). The `living-docs` skill generates C4 diagrams that map to: Context diagram (Scenarios view), Container diagram (Physical + Development views), Component diagram (Logical + Development views). | + +--- + +### 57. The C4 Model for Software Architecture + +| | | +|---|---| +| **Source** | Brown, S. (2018). *The C4 Model for Software Architecture*. Leanpub. https://c4model.com | +| **Date** | 2018 (ongoing) | +| **Alternative** | Brown, S. (2023). "The C4 model for visualising software architecture." *InfoQ*. | +| **Status** | Confirmed — widely adopted; tooled by Structurizr, PlantUML C4, Mermaid C4 | +| **Core finding** | Software architecture can be communicated at four zoom levels: **Level 1 — System Context** (who uses the system and what external systems it talks to), **Level 2 — Container** (major runnable/deployable units), **Level 3 — Component** (major structural building blocks within a container), **Level 4 — Code** (classes, interfaces; usually auto-generated). Each level answers a specific question; mixing levels in one diagram creates confusion. | +| **Mechanism** | C4 operationalises the 4+1 View Model (entry 56) into a lightweight notation that can be expressed in text (PlantUML, Mermaid) and version-controlled alongside code. The notation is deliberately constrained: boxes (people, systems, containers, components) and unidirectional arrows with labels. No UML formalism required. Context + Container diagrams cover >90% of communication needs for most teams. | +| **Where used** | The `living-docs` skill generates and updates C4 diagrams in `docs/c4/`. Context diagram (L1) always generated; Container (L2) generated when multiple containers are identified; Component (L3) generated on demand. Source files are Mermaid so they render in GitHub and are version-controlled. | + +--- + +### 58. Information Hiding — Module Decomposition Criterion + +| | | +|---|---| +| **Source** | Parnas, D. L. (1972). "On the criteria to be used in decomposing systems into modules." *Communications of the ACM*, 15(12), 1053–1058. https://doi.org/10.1145/361598.361623 | +| **Date** | 1972 | +| **Alternative** | Parnas, D. L. (1974). "On a 'buzzword': Hierarchical structure." *Proc. IFIP Congress 74*, 336–339. | +| **Status** | Confirmed — 4,000+ citations; foundational criterion for all modular decomposition in software engineering | +| **Core finding** | The correct criterion for decomposing a system into modules is **information hiding**: each module hides a design decision that is likely to change. A module's interface reveals only what callers need; its implementation hides how. Decomposing by execution steps (procedure-based) creates tight coupling to implementation order; decomposing by change-prone decisions (information-hiding) allows each decision to be changed independently. | +| **Mechanism** | Identify which decisions are most likely to change (data structures, algorithms, I/O formats, external service protocols). Each such decision becomes a module boundary. The module's public interface is defined to be change-stable; the implementation is change-free from the caller's perspective. This is the theoretical basis for SOLID-D (depend on abstractions), Hexagonal Architecture (hide external decisions behind ports), and DDD bounded contexts (hide language decisions behind context boundaries). | +| **Where used** | Step 2 Architecture: bounded context check ("same word, different meaning across features? → module boundary") and external dep Protocol assignment both apply the information-hiding criterion. The `living-docs` skill uses module boundaries as container/component boundaries in `docs/c4/` diagrams. | + +--- + ## Bibliography -1. Cockburn, A. (2005). Hexagonal Architecture. *alistair.cockburn.us*. https://alistair.cockburn.us/hexagonal-architecture/ -2. Freeman, S., & Pryce, N. (2009). *Growing Object-Oriented Software, Guided by Tests*. Addison-Wesley. +1. Bass, L., Clements, P., & Kazman, R. (2021). *Software Architecture in Practice* (4th ed.). Addison-Wesley. +2. Brown, S. (2018). *The C4 Model for Software Architecture*. Leanpub. https://c4model.com +3. Cockburn, A. (2005). Hexagonal Architecture. *alistair.cockburn.us*. https://alistair.cockburn.us/hexagonal-architecture/ +4. Freeman, S., & Pryce, N. (2009). *Growing Object-Oriented Software, Guided by Tests*. Addison-Wesley. +5. Keeling, M. (2017). *Design It!: From Programmer to Software Architect*. Pragmatic Bookshelf. +6. Kruchten, P. B. (1995). The 4+1 View Model of Architecture. *IEEE Software*, 12(6), 42–50. https://doi.org/10.1109/52.469759 +7. Nygard, M. T. (2011). Documenting Architecture Decisions. *cognitect.com*. https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions +8. Parnas, D. L. (1972). On the criteria to be used in decomposing systems into modules. *CACM*, 15(12), 1053–1058. https://doi.org/10.1145/361598.361623 diff --git a/docs/scientific-research/documentation.md b/docs/scientific-research/documentation.md new file mode 100644 index 0000000..9c77a00 --- /dev/null +++ b/docs/scientific-research/documentation.md @@ -0,0 +1,69 @@ +# Scientific Research — Documentation + +Foundations for living documentation, docs-as-code, information architecture, and post-mortem practices used in this template. + +--- + +### 59. Information Needs in Collocated Software Development Teams + +| | | +|---|---| +| **Source** | Ko, A. J., DeLine, R., & Venolia, G. (2007). "Information Needs in Collocated Software Development Teams." *Proc. 29th International Conference on Software Engineering (ICSE 2007)*, pp. 344–353. IEEE. https://doi.org/10.1109/ICSE.2007.45 | +| **Date** | 2007 | +| **Alternative** | Dagenais, B., & Robillard, M. P. (2010). "Creating and evolving developer documentation." *Proc. FSE 2010*, pp. 127–136. ACM. | +| **Status** | Confirmed — empirical study; 600+ citations | +| **Core finding** | Developers spend 35–50% of their working time not writing code but searching for information — navigating code, reading past decisions, and understanding relationships between components. The most frequently sought information is: who wrote this, why was it written this way, and what does this module depend on. Direct questioning of teammates is the most common fallback when documentation is absent, creating serial bottlenecks. | +| **Mechanism** | Information seeking is triggered by a task, not by curiosity. A developer encountering an unfamiliar component has a specific decision to make. When documentation is absent, the seek-ask-wait loop (find the right person, ask, wait for a response) dominates time. Persistent documentation (ADRs, architecture diagrams, glossary) short-circuits this loop by making the answer findable without a human intermediary. | +| **Where used** | Justifies the full `living-docs` skill: C4 diagrams answer "what does this module depend on?"; the ADR record answers "why was it written this way?"; the living glossary answers "what does this term mean in this context?". Collectively these eliminate the three most frequent information needs identified by Ko et al. | + +--- + +### 60. Software Engineering at Google — Documentation Chapter + +| | | +|---|---| +| **Source** | Winters, T., Manshreck, T., & Wright, H. (2020). *Software Engineering at Google: Lessons Learned from Programming Over Time*. O'Reilly. Chapter 10: "Documentation." https://abseil.io/resources/swe-book/html/ch10.html | +| **Date** | 2020 | +| **Alternative** | Fitzpatrick, B., & Collins-Sussman, B. (2012). *Team Geek*. O'Reilly. | +| **Status** | Confirmed — large-scale industry evidence from a codebase with ~2 billion lines of code | +| **Core finding** | Documentation that lives outside the code repository decays at a rate proportional to how often the code changes — because there is no mechanism that forces the doc to be updated when the code changes. Docs-as-code (documentation in the same repo, reviewed in the same PRs, tested in the same CI pipeline) dramatically reduces divergence because the cost of updating the doc is incurred at the same moment as the cost of the code change. | +| **Mechanism** | Google's g3doc system co-locates docs with the code they describe. When a PR changes `payments/service.py`, the reviewer also sees `payments/README.md` in the diff and can flag staleness immediately. At scale, Google found that docs with no co-located tests or CI checks become stale within 3–6 months regardless of team discipline. | +| **Where used** | Justifies co-locating `docs/` within the project repository. Living docs (`docs/architecture/c4/`, `docs/glossary.md`) are updated in the same commits as the code they describe. The `living-docs` skill is the mechanism that enforces this — it runs after Step 5 to regenerate diagrams from the current state of the codebase and discovery docs. | + +--- + +### 61. Diátaxis — A Systematic Framework for Technical Documentation + +| | | +|---|---| +| **Source** | Procida, D. (2021). "Diátaxis — A systematic approach to technical documentation." *diataxis.fr*. https://diataxis.fr | +| **Date** | 2021 | +| **Status** | Confirmed — adopted by Django, NumPy, Gatsby, Cloudflare, and the Python Software Foundation | +| **Core finding** | Technical documentation fails because it conflates four fundamentally different needs into a single undifferentiated text. The four types are: **Tutorials** (learning-oriented; guides a beginner through a complete task), **How-to guides** (task-oriented; solves a specific problem for a practitioner), **Reference** (information-oriented; describes the system accurately and completely), **Explanation** (understanding-oriented; discusses concepts and decisions). Each type has a different audience mental state and requires a different writing mode. Mixing them degrades all four. | +| **Mechanism** | The two axes of Diátaxis are: **practical ↔ theoretical** (tutorials and how-to guides are practical; reference and explanation are theoretical) and **acquiring ↔ applying** (tutorials and explanation are for acquiring knowledge; how-to guides and reference are for applying it). A document that tries to be both a tutorial and a reference simultaneously will be a poor tutorial (too much information) and a poor reference (not structured for lookup). | +| **Where used** | Documentation structure in this template maps to Diátaxis: `README.md` = tutorial (getting started), `AGENTS.md` = reference (complete description of roles, skills, commands) and explanation (why the workflow exists), `docs/c4/` = reference (system structure), post-mortems = explanation (why decisions were made). The `living-docs` skill produces reference-type documentation (C4 diagrams, glossary) — not tutorials. | + +--- + +### 62. Blameless Post-Mortems and a Just Culture + +| | | +|---|---| +| **Source** | Allspaw, J. (2012). "Blameless PostMortems and a Just Culture." *code.etsy.com* (archived). https://www.etsy.com/codeascraft/blameless-postmortems/ | +| **Date** | 2012 | +| **Alternative** | Dekker, S. (2006). *The Field Guide to Understanding Human Error*. Ashgate. | +| **Status** | Confirmed — foundational DevOps/SRE practice; referenced in Google SRE Book (2016) | +| **Core finding** | Post-mortems that assign blame produce less information and lower long-term system reliability than blameless post-mortems. When individuals believe they will be blamed, they withhold information about contributing factors, preventing the systemic causes from being identified and fixed. A blameless post-mortem treats the incident as a system failure, not an individual failure — asking "what conditions allowed this to happen?" not "who caused this?" | +| **Mechanism** | Allspaw's model separates two questions: (1) what happened? (factual, blameless) and (2) what changes would prevent recurrence? (systemic). The post-mortem document records both. The output is not an individual's performance review but a list of system changes — process improvements, documentation gaps, tooling additions. Etsy's incident rate fell after adopting blameless post-mortems because engineers began reporting near-misses that they previously concealed. | +| **Where used** | `docs/post-mortem/` directory. Post-mortems in this template follow the blameless model: they report workflow gaps found, not who made the mistake. The output of each post-mortem is a list of improvements to skills, agents, or workflow documentation. The `living-docs` skill is one such improvement — it emerged from the discovery that architecture and glossary documentation were falling behind the codebase. | + +--- + +## Bibliography + +1. Allspaw, J. (2012). Blameless PostMortems and a Just Culture. *code.etsy.com*. https://www.etsy.com/codeascraft/blameless-postmortems/ +2. Dagenais, B., & Robillard, M. P. (2010). Creating and evolving developer documentation. *Proc. FSE 2010*, pp. 127–136. ACM. +3. Dekker, S. (2006). *The Field Guide to Understanding Human Error*. Ashgate. +4. Ko, A. J., DeLine, R., & Venolia, G. (2007). Information Needs in Collocated Software Development Teams. *Proc. ICSE 2007*, pp. 344–353. https://doi.org/10.1109/ICSE.2007.45 +5. Procida, D. (2021). Diátaxis — A systematic approach to technical documentation. *diataxis.fr*. https://diataxis.fr +6. Winters, T., Manshreck, T., & Wright, H. (2020). *Software Engineering at Google*. O'Reilly. Chapter 10. https://abseil.io/resources/swe-book/html/ch10.html diff --git a/docs/scientific-research/domain-modeling.md b/docs/scientific-research/domain-modeling.md index e80626d..eb9143e 100644 --- a/docs/scientific-research/domain-modeling.md +++ b/docs/scientific-research/domain-modeling.md @@ -18,7 +18,98 @@ Foundations for bounded context identification, ubiquitous language, and feature --- +### 63. DDD Reference — Pattern Summaries (CC-BY) + +| | | +|---|---| +| **Source** | Evans, E. (2015). *DDD Reference: Definitions and Pattern Summaries*. domainlanguage.com. https://www.domainlanguage.com/ddd/reference/ | +| **Date** | 2015 | +| **Alternative** | Evans, E. (2003). *Domain-Driven Design*. Addison-Wesley. (full book; entry #31) | +| **Status** | Confirmed — freely available CC-BY canonical summary; maintained by Evans personally | +| **Core finding** | The open-access pattern summary of all DDD patterns from the 2003 book. More precisely citable than the book for specific pattern definitions. Key patterns: Ubiquitous Language ("Use the model as the backbone of a language. Commit the team to exercising that language relentlessly in all communication within the team and in the code."), Bounded Context, Context Map, Domain Events, Aggregates, Repositories. | +| **Mechanism** | Each pattern is described with: intent, prescription, and "therefore" consequences. The Ubiquitous Language pattern prescribes: use the same terms in diagrams, writing, and especially speech. Refactor the code when the language changes. Resolve confusion over terms in conversation, the way confusion over ordinary words is resolved — by agreement and precision. | +| **Where used** | Primary reference for `docs/discovery.md` Domain Model structure and the ubiquitous language practice. `living-docs` skill glossary entries derive from this: terms must match code identifiers (Evans' "use the same language in code" prescription). `docs/scientific-research/domain-modeling.md`. | +| **Note** | Supersedes entry #31 as the citable source for specific pattern quotes. Entry #31 remains as the book reference. Use this entry when citing a specific Evans pattern definition. | + +--- + +### 64. UbiquitousLanguage — Fowler Bliki + +| | | +|---|---| +| **Source** | Fowler, M. (2006). "UbiquitousLanguage." *martinfowler.com*. https://martinfowler.com/bliki/UbiquitousLanguage.html | +| **Date** | 2006 | +| **Alternative** | Evans (2015) DDD Reference (entry #63) — the primary source Fowler summarises | +| **Status** | Confirmed — widely cited secondary source; Fowler wrote the DDD foreword and is considered the authoritative secondary interpreter of Evans | +| **Core finding** | The ubiquitous language is a practice, not a document. The glossary is a secondary artifact — a snapshot of the current state of the language. The language itself lives in conversation, in the code, and in all written communication. "By using the model-based language pervasively and not being satisfied until it flows, we approach a model that is complete and comprehensible." Domain experts must object to inadequate terms; developers must flag ambiguity. | +| **Mechanism** | The key test of a ubiquitous language: can a domain expert read the domain layer code and recognize their domain? If the code uses different names than the glossary, the code must be refactored — not the glossary relaxed. The language evolves through experimentation with alternative expressions, followed by code refactoring to match the new model. | +| **Where used** | `living-docs` skill — grounds the rule "verify each term matches the identifier used in the code's domain layer." `docs/glossary.md` — the glossary is explicitly secondary to the code. `docs/scientific-research/domain-modeling.md`. | + +--- + +### 65. BoundedContext — Fowler Bliki + +| | | +|---|---| +| **Source** | Fowler, M. (2014). "BoundedContext." *martinfowler.com*. https://martinfowler.com/bliki/BoundedContext.html | +| **Date** | 2014 | +| **Alternative** | Evans (2015) DDD Reference (entry #63) — Fowler cites Evans directly | +| **Status** | Confirmed — includes a direct Evans quote; the canonical accessible reference for Bounded Context as a design pattern | +| **Core finding** | "Total unification of the domain model for a large system will not be feasible or cost-effective" (Evans, quoted directly). The same word can mean different things in different Bounded Contexts — this is not a defect but a reflection of domain reality. "You need a different model when the language changes." A Bounded Context is the boundary within which a particular ubiquitous language is internally consistent. Terms must be qualified by their context when a project has more than one bounded context. | +| **Mechanism** | Fowler's electricity utility example: the word "meter" meant different things in billing, grid management, and customer service. Attempting to unify these into one definition created confusion. Each bounded context maintains its own model and its own language. Context Maps document the relationships and translation rules between bounded contexts. | +| **Where used** | `living-docs` skill — `**Bounded context:**` field in `docs/glossary.md` entries is mandatory when the project has more than one bounded context (this is the Evans/Fowler requirement). `docs/scientific-research/domain-modeling.md`. | + +--- + +### 66. Implementing Domain-Driven Design + +| | | +|---|---| +| **Source** | Vernon, V. (2013). *Implementing Domain-Driven Design*. Addison-Wesley. | +| **Date** | 2013 | +| **Alternative** | Evans (2003) DDD (entry #31) — Vernon explicitly builds on Evans | +| **Status** | Confirmed — second most cited DDD book; ~5,000 citations | +| **Core finding** | Three additions to Evans: (1) **Domain Events as first-class vocabulary** — past-tense verb phrases ("OrderPlaced," "VersionDisplayed") are part of the ubiquitous language and belong in the glossary as a distinct type. (2) **Context Maps as the organizing principle** for multi-context glossaries — each bounded context has its own language documentation; the Context Map shows translation rules between contexts. (3) **Documentation co-located with the code** — docs in the same repository decay at the same rate as the code, dramatically reducing divergence. | +| **Mechanism** | Vernon's IDDD samples (github.com/VaughnVernon/IDDD_Samples) demonstrate all three in practice. The Product Owner / Business Analyst plays the domain-expert-representative role in glossary maintenance — validating semantic correctness — while developers own structural precision. Neither writes the glossary unilaterally. | +| **Where used** | `living-docs` skill — `Domain Event` added as a distinct Type value in `docs/glossary.md` entries. Grounds the PO-owned glossary with SE input via `docs/architecture.md` Reason: fields. `docs/scientific-research/domain-modeling.md`. | + +--- + +### 67. Ubiquitous Language Is Not a Glossary — Verraes + +| | | +|---|---| +| **Source** | Verraes, M. (2013). "Ubiquitous Language Is Not a Glossary." *verraes.net*. https://web.archive.org/web/20131004/https://verraes.net/2013/04/ubiquitous-language-is-not-a-glossary/ | +| **Date** | 2013 | +| **Alternative** | Fowler (2006) UbiquitousLanguage (entry #64) — the same secondary-artifact point, less pointed | +| **Status** | Confirmed — original URL is 404; widely documented through community discussion and practitioner secondary accounts; thesis is uncontested in the DDD community | +| **Core finding** | A glossary is not a ubiquitous language. Teams that maintain a glossary but do not reflect its terms in the code have the *appearance* of a ubiquitous language without the substance. The glossary is a secondary artifact derived from the code and domain-expert conversations — not the reverse. The canonical source of truth is the domain layer code, not the glossary document. A glossary that diverges from the code is lying. | +| **Mechanism** | The test: can a domain expert read the domain layer code and recognize their domain without a translator? If yes, the ubiquitous language exists. If the only evidence of the language is the glossary document, it does not exist. Consequence: every term added to the glossary must be verified against the corresponding code identifier. | +| **Where used** | `living-docs` skill — grounds the checklist item "Verify each term matches the identifier used in the code's domain layer." Prevents the common failure mode of glossary-as-theatre. `docs/scientific-research/domain-modeling.md`. | + +--- + +### 68. Whirlpool Process of Model Exploration — Evans + +| | | +|---|---| +| **Source** | Evans, E. (2011). *Whirlpool Process of Model Exploration*. domainlanguage.com. https://www.domainlanguage.com/ddd/whirlpool/ | +| **Date** | 2011 | +| **Alternative** | Brandolini, A. (2013). *Introducing EventStorming*. Leanpub. — a later, more structured alternative to Whirlpool | +| **Status** | Confirmed — freely available; Evans' own post-2003 process guidance | +| **Core finding** | Model exploration is a cycle: Scenario Exploring → Harvesting Abstractions → Probing the Model → Challenging the Model → back to Scenario Exploring. New vocabulary crystallizes at the Harvesting Abstractions step — concrete scenarios surface candidate terms, which are then named, defined, and reflected in the code. The glossary grows at each Harvesting Abstractions step. | +| **Mechanism** | The Whirlpool is not a development process — it fits within most iterative processes. It is a model-exploration subprocess triggered whenever the team encounters a poorly understood domain concept. The output of each cycle is a refined model expressed in clearer language, with updated code identifiers and glossary entries. | +| **Where used** | `living-docs` skill — grounds the timing of glossary updates: after each completed feature (Step 5) corresponds to the Harvesting Abstractions step in the Whirlpool. Discovery sessions (Stage 1) correspond to Scenario Exploring. `docs/scientific-research/domain-modeling.md`. | + +--- + ## Bibliography 1. Context Mapper. (2025). Rapid Object-Oriented Analysis and Design. https://contextmapper.org/docs/rapid-ooad 2. Evans, E. (2003). *Domain-Driven Design: Tackling Complexity in the Heart of Software*. Addison-Wesley. +3. Evans, E. (2011). *Whirlpool Process of Model Exploration*. domainlanguage.com. https://www.domainlanguage.com/ddd/whirlpool/ +4. Evans, E. (2015). *DDD Reference: Definitions and Pattern Summaries* (CC-BY). domainlanguage.com. https://www.domainlanguage.com/ddd/reference/ +5. Fowler, M. (2006). UbiquitousLanguage. martinfowler.com. https://martinfowler.com/bliki/UbiquitousLanguage.html +6. Fowler, M. (2014). BoundedContext. martinfowler.com. https://martinfowler.com/bliki/BoundedContext.html +7. Vernon, V. (2013). *Implementing Domain-Driven Design*. Addison-Wesley. +8. Verraes, M. (2013). Ubiquitous Language Is Not a Glossary. verraes.net (archived). https://web.archive.org/web/20131004/https://verraes.net/2013/04/ubiquitous-language-is-not-a-glossary/ diff --git a/docs/workflow.md b/docs/workflow.md deleted file mode 100644 index 918ddfc..0000000 --- a/docs/workflow.md +++ /dev/null @@ -1,449 +0,0 @@ -# Development Workflow - -This document describes the complete feature lifecycle used to develop software with this framework. - ---- - -## Overview - -Features flow through 5 steps with a WIP limit of 1 feature at a time. The filesystem enforces the limit: - -``` -docs/features/backlog/<name>.feature ← waiting -docs/features/in-progress/<name>.feature ← exactly one being built -docs/features/completed/<name>.feature ← accepted and shipped -``` - -Each step has a designated agent and a specific deliverable. No step is skipped. - ---- - -## Full Workflow Diagram - -``` -╔══════════════════════════════════════════════════════════════════════╗ -║ FEATURE LIFECYCLE (WIP = 1) ║ -╚══════════════════════════════════════════════════════════════════════╝ - - FILESYSTEM ENFORCES WIP: - backlog/<name>.feature → in-progress/<name>.feature → completed/<name>.feature - - -┌─────────────────────────────────────────────────────────────────────┐ -│ STEP 1 — SCOPE agent: product-owner │ -├─────────────────────────────────────────────────────────────────────┤ -│ │ -│ Stage 1 — Discovery (PO + stakeholder, iterative) │ -│ Sessions happen any time scope needs establishing or refining. │ -│ Every session follows the same structure. │ -│ │ -│ SESSION START │ -│ Check docs/discovery_journal.md last block for Status: │ -│ IN-PROGRESS → resume interrupted session first │ -│ (missing file) → create journal + discovery.md from templates│ -│ Append new session header to journal: │ -│ ## YYYY-MM-DD — Session N │ -│ Status: IN-PROGRESS ← written BEFORE any questions │ -│ │ -│ QUESTION ORDER │ -│ 1. General (5Ws + Success + Failure + Out-of-scope) │ -│ [first session only, if journal did not exist yet] │ -│ Gap-finding per answer: CIT · Laddering · CI Perspective │ -│ Level 1: paraphrase each answer on the spot │ -│ 2. Cross-cutting (behavior groups, bounded contexts, │ -│ integration points, lifecycle events) │ -│ Level 2: synthesis when transitioning between groups │ -│ 3. Per-feature (one feature at a time) │ -│ Extract entities from docs/discovery.md Domain Model │ -│ Gap-finding: CIT · Laddering · CI Perspective │ -│ Silent pre-mortem per feature │ -│ REAL-TIME SPLIT: if >2 concerns OR >8 candidate Examples │ -│ → split immediately, record in journal, create stubs, │ -│ continue questions for both features in this session │ -│ │ -│ AFTER QUESTIONS (PO alone, in this order) │ -│ 1. Append answered Q&A to journal (in groups; answered only) │ -│ 2. Rewrite .feature description for each touched feature │ -│ [untouched features stay exactly as-is] │ -│ 3. Append session synthesis block to discovery.md (LAST) │ -│ [only after all .feature files are updated] │ -│ 4. Mark journal session: Status: COMPLETE │ -│ commit: feat(discovery): <session summary> │ -│ │ -│ BASELINING A FEATURE │ -│ When stakeholder approves feature discovery + decomp passes: │ -│ PO writes Status: BASELINED (YYYY-MM-DD) in the .feature file │ -│ Gate: feature may only enter Stage 2 when BASELINED │ -│ │ -│ Stage 2 — Specification (PO alone, per feature) │ -│ Only runs on features with Status: BASELINED. │ -│ If a gap needs stakeholder input → open a new Stage 1 session. │ -│ │ -│ Step A — Stories │ -│ Derive one Rule: block per user story from feature description │ -│ INVEST gate: all 6 letters must pass before committing │ -│ commit: feat(stories): write user stories for <name> │ -│ │ -│ Step B — Criteria │ -│ Pre-mortem per Rule (all Rules checked before Examples) │ -│ Write @id-tagged Examples (Given/When/Then, declarative) │ -│ MoSCoW triage: Must / Should / Could per Example │ -│ Review checklist │ -│ commit: feat(criteria): write acceptance criteria for <name> │ -│ ★ FROZEN — changes require @deprecated + new Example │ -│ │ -│ Bug Handling │ -│ PO adds @bug @id:<hex> Example to relevant Rule: in .feature │ -│ SE implements @id test in tests/features/<name>/ │ -│ SE also writes @given Hypothesis test in tests/unit/ (whole class)│ -│ Both tests required · SE follows normal TDD loop (Step 3) │ -│ │ -└─────────────────────────────────────────────────────────────────────┘ - ↓ PO picks feature from backlog — only if Status: BASELINED -┌─────────────────────────────────────────────────────────────────────┐ -│ STEP 2 — ARCHITECTURE agent: software-engineer │ -├─────────────────────────────────────────────────────────────────────┤ -│ │ -│ PREREQUISITES (stop if any fail — escalate to PO) │ -│ [ ] in-progress/ has no .feature file (WIP = 1) │ -│ [ ] feature Status: BASELINED │ -│ [ ] feature has Rule: + Example: + @id tags │ -│ [ ] package name confirmed (pyproject.toml → directory exists) │ -│ │ -│ READ (all before writing anything) │ -│ docs/discovery.md (project-level synthesis changelog) │ -│ ALL backlog .feature files (narrative + Rules + Examples) │ -│ in-progress .feature file (full: Rules + Examples + @id) │ -│ ALL existing .py files in <package>/ ← know what exists first │ -│ │ -│ DOMAIN ANALYSIS │ -│ From Domain Model in docs/discovery.md + Rules (Business): │ -│ Nouns → named classes, value objects, aggregates │ -│ Verbs → method names with typed signatures │ -│ Datasets → named types (not bare dict/list) │ -│ Bounded Context check: same word, different meaning across │ -│ features? → module boundary goes there │ -│ Cross-feature entities → candidate shared domain layer │ -│ │ -│ SILENT PRE-MORTEM (before writing anything) │ -│ "In 6 months this design is a mess. What mistakes did we make?" │ -│ For each candidate class: >2 ivars? >1 reason to change? │ -│ For each external dep: is it behind a Protocol? │ -│ Any noun serving double duty across modules? │ -│ Any structure missing a named design pattern? │ -│ → If pattern smell detected: load skill design-patterns │ -│ │ -│ WRITE STUBS INTO PACKAGE (signatures only — bodies must be `...`) │ -│ If file exists → add class/method; do not remove existing code │ -│ If file does not exist → create with signatures only │ -│ File placement (common patterns, not required names): │ -│ <package>/domain/<noun>.py ← entities, value objects │ -│ <package>/domain/service.py ← cross-entity operations │ -│ Do not pre-create ports/ or adapters/ without a concrete dep │ -│ Stub rules: │ -│ Bodies: `...` only — no logic, no conditionals │ -│ No docstrings — add after GREEN when signatures are stable │ -│ No inline comments, no TODO, no speculative code │ -│ │ -│ RECORD ARCHITECTURAL DECISIONS (significant only) │ -│ Append to docs/architecture.md │ -│ ## YYYY-MM-DD — <feature>: <title> │ -│ Decision: <what> Reason: <why> │ -│ Alternatives considered: <what was rejected and why> │ -│ │ -│ ARCHITECTURE SMELL CHECK — hard gate (fix before commit) │ -│ [ ] No class with >2 responsibilities (SOLID-S) │ -│ [ ] No behavioural class with >2 instance variables (OC-8; │ -│ dataclasses, Pydantic models, value objects, TypedDicts │ -│ are exempt) │ -│ [ ] All external deps assigned a Protocol (SOLID-D + Hexagonal) │ -│ N/A if no external dependencies identified in scope │ -│ [ ] No noun with different meaning across planned modules │ -│ (DDD Bounded Context) │ -│ [ ] No missing Creational pattern: repeated construction │ -│ without Factory/Builder │ -│ [ ] No missing Structural pattern: type-switching logic │ -│ without Strategy/Visitor │ -│ [ ] No missing Behavioral pattern: state machine or scattered │ -│ notification without State/Observer │ -│ [ ] Each ADR consistent with each @id AC — no contradictions │ -│ [ ] Technically infeasible story → escalate to PO │ -│ │ -│ commit: feat(<name>): add architecture stubs │ -│ │ -└─────────────────────────────────────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────────────────────────────────────┐ -│ STEP 3 — TDD LOOP agent: software-engineer │ -├─────────────────────────────────────────────────────────────────────┤ -│ │ -│ PREREQUISITES (stop if any fail — escalate to PO) │ -│ [ ] Architecture stubs present in <package>/ (Step 2 committed) │ -│ [ ] Read docs/architecture.md — all architectural decisions │ -│ [ ] All tests written in tests/features/<feature>/ │ -│ │ -│ Build TODO.md test list │ -│ List all @id tags from in-progress .feature file │ -│ Order: fewest dependencies first; most impactful within that │ -│ Each @id = one TODO item, status: pending │ -│ │ -│ OUTER LOOP — one @id at a time │ -│ ┌─────────────────────────────────────────────────────────────┐ │ -│ │ Pick next pending @id → mark in_progress in TODO.md │ │ -│ │ (WIP limit: exactly one in_progress at all times) │ │ -│ │ │ │ -│ │ INNER LOOP │ │ -│ │ ┌───────────────────────────────────────────────────────┐ │ │ -│ │ │ RED │ │ │ -│ │ │ Read stubs in <package>/ — base test on them │ │ │ -│ │ │ Write test body (Given/When/Then → Arrange/Act/Assert) │ │ -│ │ │ Update stub signatures as needed — edit .py directly │ │ │ -│ │ │ uv run task test-fast │ │ │ -│ │ │ EXIT: this @id FAILS │ │ │ -│ │ │ (if it passes: test is wrong — fix it first) │ │ │ -│ │ ├───────────────────────────────────────────────────────┤ │ │ -│ │ │ GREEN │ │ │ -│ │ │ Write minimum code — YAGNI + KISS only │ │ │ -│ │ │ (no DRY, SOLID, OC here — those belong in REFACTOR)│ │ │ -│ │ │ uv run task test-fast │ │ │ -│ │ │ EXIT: this @id passes AND all prior tests pass │ │ │ -│ │ │ (fix implementation only; do not advance @id) │ │ │ -│ │ ├───────────────────────────────────────────────────────┤ │ │ -│ │ │ REFACTOR │ │ │ -│ │ │ Load skill refactor — follow its protocol │ │ │ -│ │ │ uv run task test-fast after each individual change │ │ │ -│ │ │ EXIT: test-fast passes; no smells remain │ │ │ -│ │ └───────────────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ │ Mark @id completed in TODO.md │ │ -│ │ Commit when a meaningful increment is green │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -│ Repeat until all @id items completed │ -│ │ -│ QUALITY GATE (all @id green) │ -│ uv run task lint │ -│ uv run task static-check │ -│ uv run task test (coverage must be 100%) │ -│ timeout 10s uv run task run │ -│ coverage < 100%: add test in tests/unit/ for uncovered branch │ -│ (do NOT add @id tests for coverage — @id tests are AC only) │ -│ All must pass before handing off │ -│ │ -│ SELF-DECLARATION (once, after all quality gates pass) │ -│ Communicate verbally to reviewer: │ -│ * YAGNI, KISS, DRY, SOLID, OC checklist — AGREE/DISAGREE │ -│ with file:line evidence for each claim │ -│ * DISAGREE requires inline justification │ -│ │ -│ → Hand off to Step 4 (Verify) │ -└─────────────────────────────────────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────────────────────────────────────┐ -│ STEP 4 — VERIFY agent: reviewer │ -├─────────────────────────────────────────────────────────────────────┤ -│ │ -│ Default hypothesis: BROKEN. Prove otherwise or REJECT. │ -│ │ -│ 4a. READ │ -│ in-progress .feature file (Rules + Examples + @id) │ -│ Self-Declaration communicated verbally by software-engineer │ -│ │ -│ 4b. pyproject.toml GATE │ -│ git diff main -- pyproject.toml │ -│ Any change → REJECT immediately │ -│ software-engineer must revert + get stakeholder approval │ -│ │ -│ 4c. COMMIT HISTORY │ -│ git log --oneline main..HEAD │ -│ All commits follow conventional commit format? │ -│ No "fix tests", "wip", "temp" commits? │ -│ │ -│ 4d. COMMANDS │ -│ uv run task lint (must exit 0) │ -│ uv run task static-check (must exit 0) │ -│ uv run task test (must exit 0, coverage 100%) │ -│ timeout 10s uv run task run (exit 124 = hung = REJECT) │ -│ │ -│ 4e. PRODUCTION GATE │ -│ Does the application behave as described in the feature file? │ -│ Run manually or via integration test — not just green CI │ -│ Input → output check for each Rule: block │ -│ │ -│ 4f. CODE REVIEW (semantic — not covered by tooling) │ -│ [ ] Tests operate at same abstraction level as AC │ -│ [ ] No test asserts implementation details │ -│ [ ] Each @id test covers exactly one Example │ -│ [ ] No logic in tests (no if/for/while) │ -│ [ ] Module structure matches Architecture section │ -│ [ ] No external dependency outside adapters/ │ -│ [ ] Docstrings explain why, not what │ -│ │ -│ 4g. SELF-DECLARATION AUDIT │ -│ For every AGREE claim: find the file:line — does it hold? │ -│ For every DISAGREE claim: is the deviation justified? │ -│ Undeclared violations → REJECT │ -│ │ -│ 4h. INTERACTIVE (if any doubt remains) │ -│ Ask software-engineer one targeted question per ambiguity │ -│ Do not proceed to report if question is unanswered │ -│ │ -│ 4i. REPORT │ -│ APPROVED — all gates passed, no undeclared violations │ -│ REJECTED — list each failure with file:line and required fix │ -│ │ -│ On APPROVED → notify PO │ -│ On REJECTED → return to software-engineer (Step 3 quality gate) │ -└─────────────────────────────────────────────────────────────────────┘ - ↓ APPROVED -┌─────────────────────────────────────────────────────────────────────┐ -│ STEP 5 — ACCEPT agent: product-owner │ -├─────────────────────────────────────────────────────────────────────┤ -│ │ -│ PO runs/observes the feature (real user interaction) │ -│ Checks against original Rule: user stories │ -│ │ -│ ACCEPTED: │ -│ mv in-progress/<name>.feature → completed/<name>.feature │ -│ software-engineer creates PR (squash merge) + tags release │ -│ │ -│ REJECTED: │ -│ feedback in TODO.md → back to relevant step │ -│ │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## Feature File Structure - -Each feature is a single `.feature` file. The description contains the feature description and Status line. All Q&A lives in `docs/discovery_journal.md`; architectural decisions live in `docs/architecture.md`. - -``` -Feature: <title> - - <2–4 sentence description of what this feature does and why it exists.> - - Status: ELICITING | BASELINED (YYYY-MM-DD) - - Rules (Business): - - <business rule> - - Constraints: - - <non-functional requirement> - - Rule: <story title> - As a <role> - I want <goal> - So that <benefit> - - @id:a3f2b1c4 - Example: <scenario> - Given <context> - When <action> - Then <observable outcome> -``` - -Three discovery sources: -- `docs/discovery_journal.md` — raw Q&A from all scope sessions (PO, append-only) -- `docs/discovery.md` — synthesis changelog, domain model, feature list (PO, append-only) -- `docs/architecture.md` — all architectural decisions (software-engineer, append-only) - ---- - -## Architecture Artifacts - -Architectural decisions made during Step 2 are appended to `docs/architecture.md`: - -```markdown -## YYYY-MM-DD — <feature-name>: <short title> - -Decision: <what was decided — one sentence> -Reason: <why — one sentence> -Alternatives considered: <what was rejected and why> -Feature: <feature-name> -``` - -Write a block only for non-obvious decisions with real trade-offs — module boundaries, external dependency strategy, Protocol vs. concrete class, data model choices. Routine YAGNI choices do not need a record. The file is append-only; when a decision changes, append a new block that supersedes the old one. - -Domain entity and service stubs (signatures, no bodies) live directly in the package under `<package>/domain/`, `<package>/ports/`, and `<package>/adapters/` — written at Step 2, filled in during Step 3. - ---- - -## Supporting Tools - -| Command | When | Purpose | -|---|---|---| -| `uv run task test-fast` | Step 3 cycle | Fast test run (no coverage) — used during Red-Green-Refactor | -| `uv run task test` | Handoff, Step 4 | Full suite with coverage — must reach 100% | -| `uv run task lint` | Handoff, Step 4 | ruff — must exit 0 | -| `uv run task static-check` | Handoff, Step 4 | pyright — must exit 0, 0 errors | -| `timeout 10s uv run task run` | Handoff, Step 4 | App must exit cleanly (exit 124 = hang = fix it) | - ---- - -## Test Layout - -``` -tests/ - features/<feature-name>/ - <rule_slug>_test.py ← software-engineer-written, one per Rule: block - function: test_<feature_slug>_<8char_hex>() - unit/ - <anything>_test.py ← software-engineer-authored extras, no @id traceability - plain pytest or Hypothesis @given (software-engineer choice) -``` - ---- - -## TODO.md Structure - -```markdown -# Current Work - -Feature: <name> -Step: <1-5> (<step name>) -Source: docs/features/in-progress/<name>.feature - -## Cycle State -Test: @id:<hex> — <description> -Phase: RED | GREEN | REFACTOR - -## Progress -- [x] @id:<hex>: <done> -- [~] @id:<hex>: <in progress> -- [ ] @id:<hex>: <next> - -## Next -<one actionable sentence> -``` - -`## Cycle State` is updated at every phase transition. This section is present only during Step 3; omit when in other steps. - ---- - -## Roles - -| Role | Type | Responsibilities | -|---|---|---| -| **Stakeholder** | Human | Answers questions, provides domain knowledge, approves syntheses | -| **Product Owner** | AI agent | Interviews stakeholder, writes `.feature` files, picks features, accepts deliveries | -| **Software Engineer** | AI agent | Architecture, tests, code, git, releases | -| **Reviewer** | AI agent | Adversarial verification — defaults to REJECTED until proven correct | - ---- - -## Quality Gates (non-negotiable) - -| Gate | Standard | -|---|---| -| Test coverage | 100% | -| Type errors (pyright) | 0 | -| Lint errors (ruff) | 0 | -| Function length | ≤ 20 lines | -| Class length | ≤ 50 lines | -| Max nesting | 2 levels | -| Instance variables per class | ≤ 2 (behavioural classes only; dataclasses, Pydantic models, value objects, TypedDicts are exempt) | -| `noqa` comments | 0 | -| `type: ignore` comments | 0 | -| Orphaned tests | 0 | -| Hypothesis tests missing `@pytest.mark.slow` | 0 | diff --git a/pyproject.toml b/pyproject.toml index 11a609a..2c1bab2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "python-project-template" -version = "6.0.20260419" +version = "6.1.20260419" description = "Python template with some awesome tools to quickstart any Python project" readme = "README.md" requires-python = ">=3.13" diff --git a/uv.lock b/uv.lock index c3fb979..0914f45 100644 --- a/uv.lock +++ b/uv.lock @@ -735,7 +735,7 @@ wheels = [ [[package]] name = "python-project-template" -version = "6.0.20260419" +version = "6.1.20260419" source = { virtual = "." } dependencies = [ { name = "fire" },