From 41d94686e80498925d297af98c91af35e6d0197e Mon Sep 17 00:00:00 2001 From: nullhack Date: Sun, 19 Apr 2026 09:03:47 -0400 Subject: [PATCH] fix(workflow): move self-declarations from TODO.md to verbal agent communication --- .opencode/skills/implementation/SKILL.md | 64 +++++++++--------- .opencode/skills/scope/SKILL.md | 30 ++++----- .opencode/skills/session-workflow/SKILL.md | 41 ------------ AGENTS.md | 2 +- docs/workflow.md | 78 +++------------------- 5 files changed, 55 insertions(+), 160 deletions(-) diff --git a/.opencode/skills/implementation/SKILL.md b/.opencode/skills/implementation/SKILL.md index 01d099c..0085129 100644 --- a/.opencode/skills/implementation/SKILL.md +++ b/.opencode/skills/implementation/SKILL.md @@ -222,45 +222,41 @@ All must pass before Self-Declaration. ### Self-Declaration (once, after all quality gates pass) -Answer honestly the `## Self-Declaration` report: - -```markdown -## Self-Declaration -As a software-engineer I declare: -* YAGNI: no code without a failing test — AGREE/DISAGREE | file:line -* YAGNI: no speculative abstractions — AGREE/DISAGREE | file:line -* KISS: simplest solution that passes — AGREE/DISAGREE | file:line -* KISS: no premature optimization — AGREE/DISAGREE | file:line -* DRY: no duplication — AGREE/DISAGREE | file:line -* DRY: no redundant comments — AGREE/DISAGREE | file:line -* SOLID-S: one reason to change per class — AGREE/DISAGREE | file:line -* SOLID-O: open for extension, closed for modification — AGREE/DISAGREE | file:line -* SOLID-L: subtypes substitutable — AGREE/DISAGREE | file:line -* SOLID-I: no forced unused deps — AGREE/DISAGREE | file:line -* SOLID-D: depend on abstractions, not concretions — AGREE/DISAGREE | file:line -* OC-1: one level of indentation per method — AGREE/DISAGREE | deepest: file:line -* OC-2: no else after return — AGREE/DISAGREE | file:line -* OC-3: primitive types wrapped — AGREE/DISAGREE | file:line -* OC-4: first-class collections — AGREE/DISAGREE | file:line -* OC-5: one dot per line — AGREE/DISAGREE | file:line -* OC-6: no abbreviations — AGREE/DISAGREE | file:line -* OC-7: ≤20 lines per function, ≤50 per class — AGREE/DISAGREE | longest: file:line -* OC-8: ≤2 instance variables per class (behavioural classes only; dataclasses, Pydantic models, value objects, and TypedDicts are exempt) — AGREE/DISAGREE | file:line -* OC-9: no getters/setters — AGREE/DISAGREE | file:line -* Patterns: I have no good reason to refactor parts of the code using OOP or Design Patterns — AGREE/DISAGREE | file:line -* Patterns: no creational smell — AGREE/DISAGREE | file:line -* Patterns: no structural smell — AGREE/DISAGREE | file:line -* Patterns: no behavioral smell — AGREE/DISAGREE | file:line -* Semantic: tests operate at same abstraction as AC — AGREE/DISAGREE | file:line -``` - -A `DISAGREE` answer is not automatic rejection — state the reason inline and fix before handing off. +Communicate verbally to the reviewer. Answer honestly for each principle: + +- YAGNI: no code without a failing test — AGREE/DISAGREE | file:line +- YAGNI: no speculative abstractions — AGREE/DISAGREE | file:line +- KISS: simplest solution that passes — AGREE/DISAGREE | file:line +- KISS: no premature optimization — AGREE/DISAGREE | file:line +- DRY: no duplication — AGREE/DISAGREE | file:line +- DRY: no redundant comments — AGREE/DISAGREE | file:line +- SOLID-S: one reason to change per class — AGREE/DISAGREE | file:line +- SOLID-O: open for extension, closed for modification — AGREE/DISAGREE | file:line +- SOLID-L: subtypes substitutable — AGREE/DISAGREE | file:line +- SOLID-I: no forced unused deps — AGREE/DISAGREE | file:line +- SOLID-D: depend on abstractions, not concretions — AGREE/DISAGREE | file:line +- OC-1: one level of indentation per method — AGREE/DISAGREE | deepest: file:line +- OC-2: no else after return — AGREE/DISAGREE | file:line +- OC-3: primitive types wrapped — AGREE/DISAGREE | file:line +- OC-4: first-class collections — AGREE/DISAGREE | file:line +- OC-5: one dot per line — AGREE/DISAGREE | file:line +- OC-6: no abbreviations — AGREE/DISAGREE | file:line +- OC-7: ≤20 lines per function, ≤50 per class — AGREE/DISAGREE | longest: file:line +- OC-8: ≤2 instance variables per class (behavioural classes only; dataclasses, Pydantic models, value objects, and TypedDicts are exempt) — AGREE/DISAGREE | file:line +- OC-9: no getters/setters — AGREE/DISAGREE | file:line +- Patterns: I have no good reason to refactor parts of the code using OOP or Design Patterns — AGREE/DISAGREE | file:line +- Patterns: no creational smell — AGREE/DISAGREE | file:line +- Patterns: no structural smell — AGREE/DISAGREE | file:line +- Patterns: no behavioral smell — AGREE/DISAGREE | file:line +- Semantic: tests operate at same abstraction as AC — AGREE/DISAGREE | file:line + +A `DISAGREE` answer is not automatic rejection — state the reason and fix before handing off. ### Hand off to Step 4 (Verify) Signal completion to the reviewer. Provide: - Feature file path -- Self-Declaration report +- Self-Declaration (communicated verbally, as above) - Summary of what was implemented --- diff --git a/.opencode/skills/scope/SKILL.md b/.opencode/skills/scope/SKILL.md index 3937373..1ff6099 100644 --- a/.opencode/skills/scope/SKILL.md +++ b/.opencode/skills/scope/SKILL.md @@ -281,23 +281,19 @@ All Rules must have their pre-mortems completed before any Examples are written. **Self-Declaration (mandatory before criteria commit)** -Write the following block into `TODO.md` before committing. Every `DISAGREE` is a **hard blocker** — explain inline and fix before the commit. Do not commit until all items are AGREE or have a documented resolution. - -```markdown -## Self-Declaration -As a product-owner I declare: -* INVEST-I: each Rule is Independent (no hidden ordering or dependency between Rules) — AGREE/DISAGREE | conflict: -* INVEST-V: each Rule delivers Value to a named user — AGREE/DISAGREE | Rule: -* INVEST-S: each Rule is Small enough for one development cycle — AGREE/DISAGREE | Rule: -* INVEST-T: each Rule is Testable (I can write a pass/fail Example for it) — AGREE/DISAGREE | Rule: -* Observable: every Then is a single, observable, measurable outcome — AGREE/DISAGREE | file:line -* No impl details: no Example tests internal state or implementation — AGREE/DISAGREE | file:line -* Coverage: every entity in the feature description appears in at least one Rule — AGREE/DISAGREE | missing: -* Distinct: no two Examples test the same observable behavior — AGREE/DISAGREE | file:line -* Unique IDs: all @id values are unique within this feature — AGREE/DISAGREE -* Pre-mortem: I ran a pre-mortem on each Rule and found no hidden failure modes — AGREE/DISAGREE | Rule: -* Scope: no Example introduces behavior outside the feature boundary — AGREE/DISAGREE | file:line -``` +Communicate verbally to the next agent. Every `DISAGREE` is a **hard blocker** — fix before committing. Do not commit until all items are AGREE or have a documented resolution. + +- INVEST-I: each Rule is Independent (no hidden ordering or dependency between Rules) — AGREE/DISAGREE | conflict: +- INVEST-V: each Rule delivers Value to a named user — AGREE/DISAGREE | Rule: +- INVEST-S: each Rule is Small enough for one development cycle — AGREE/DISAGREE | Rule: +- INVEST-T: each Rule is Testable (I can write a pass/fail Example for it) — AGREE/DISAGREE | Rule: +- Observable: every Then is a single, observable, measurable outcome — AGREE/DISAGREE | file:line +- No impl details: no Example tests internal state or implementation — AGREE/DISAGREE | file:line +- Coverage: every entity in the feature description appears in at least one Rule — AGREE/DISAGREE | missing: +- Distinct: no two Examples test the same observable behavior — AGREE/DISAGREE | file:line +- Unique IDs: all @id values are unique within this feature — AGREE/DISAGREE +- Pre-mortem: I ran a pre-mortem on each Rule and found no hidden failure modes — AGREE/DISAGREE | Rule: +- Scope: no Example introduces behavior outside the feature boundary — AGREE/DISAGREE | file:line Commit: `feat(criteria): write acceptance criteria for ` diff --git a/.opencode/skills/session-workflow/SKILL.md b/.opencode/skills/session-workflow/SKILL.md index cd56398..db97507 100644 --- a/.opencode/skills/session-workflow/SKILL.md +++ b/.opencode/skills/session-workflow/SKILL.md @@ -104,46 +104,10 @@ No feature in progress. Next: Run @ — load skill feature-selection and pick the next BASELINED feature from backlog. ``` -## Step 1 (Stage 2 Criteria) Self-Declaration TODO Format - -When Stage 2 Step B (criteria) is complete and before the `feat(criteria):` commit, TODO.md **must** include a `## Self-Declaration` block written by the PO: - -```markdown -# Current Work - -Feature: -Step: 1 (SCOPE — Stage 2 Criteria) -Source: docs/features/backlog/.feature - -## Self-Declaration -As a product-owner I declare: -* INVEST-I: each Rule is Independent — AGREE/DISAGREE | conflict: -* INVEST-V: each Rule delivers Value to a named user — AGREE/DISAGREE | Rule: -* INVEST-S: each Rule is Small enough for one development cycle — AGREE/DISAGREE | Rule: -* INVEST-T: each Rule is Testable — AGREE/DISAGREE | Rule: -* Observable: every Then is a single, observable, measurable outcome — AGREE/DISAGREE | file:line -* No impl details: no Example tests internal state or implementation — AGREE/DISAGREE | file:line -* Coverage: every entity in the feature description appears in at least one Rule — AGREE/DISAGREE | missing: -* Distinct: no two Examples test the same observable behavior — AGREE/DISAGREE | file:line -* Unique IDs: all @id values are unique within this feature — AGREE/DISAGREE -* Pre-mortem: I ran a pre-mortem on each Rule and found no hidden failure modes — AGREE/DISAGREE | Rule: -* Scope: no Example introduces behavior outside the feature boundary — AGREE/DISAGREE | file:line - -## Progress -- [x] `@id:`: - -## Next -Run @ — load skill implementation and begin Step 2 (Architecture) for -``` - -Every `DISAGREE` is a hard blocker — fix before committing. - ## Step 3 (TDD Loop) Cycle-Aware TODO Format During Step 3 (TDD Loop), TODO.md **must** include a `## Cycle State` block to track Red-Green-Refactor progress. -When `Phase: REFACTOR` is complete, a `## Self-Declaration` block is also **mandatory** before handing off to Step 4. - ```markdown # Current Work @@ -155,9 +119,6 @@ Source: docs/features/in-progress/.feature Test: `@id:` — Phase: RED | GREEN | REFACTOR -## Self-Declaration -As a software-engineer I declare this code follows YAGNI-1 ... (full checklist in implementation/SKILL.md) - ## Progress - [x] `@id:`: - [~] `@id:`: ← in progress (see Cycle State) @@ -199,5 +160,3 @@ Run `gen-todo` at session start (after reading TODO.md) and at session end (befo 5. The "Next" line must be actionable enough that a fresh AI can execute it without asking questions 6. During Step 3, always update `## Cycle State` when transitioning between RED/GREEN/REFACTOR phases 7. When a step completes, update TODO.md and commit **before** any further work -8. During Step 3, write the `## Self-Declaration` block into TODO.md after all quality gates pass — every claim must have AGREE/DISAGREE with `file:line` evidence -9. During Step 1 Stage 2 Step B (criteria), write the `## Self-Declaration` block into TODO.md before the criteria commit — every DISAGREE is a hard blocker that must be resolved before committing diff --git a/AGENTS.md b/AGENTS.md index e112246..cc22f6a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -230,7 +230,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 and Self-Declaration blocks used during Step 3. +`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. ## Setup diff --git a/docs/workflow.md b/docs/workflow.md index a09c36b..c2dd544 100644 --- a/docs/workflow.md +++ b/docs/workflow.md @@ -213,11 +213,6 @@ Each step has a designated agent and a specific deliverable. No step is skipped. │ │ │ Load skill refactor — follow its protocol │ │ │ │ │ │ uv run task test-fast after each individual change │ │ │ │ │ │ EXIT: test-fast passes; no smells remain │ │ │ -│ │ ├───────────────────────────────────────────────────────┤ │ │ -│ │ │ SELF-DECLARE │ │ │ -│ │ │ Fill Self-Declaration block in TODO.md │ │ │ -│ │ │ AGREE/DISAGREE per principle with file:line │ │ │ -│ │ │ DISAGREE requires inline justification │ │ │ │ │ └───────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ Mark @id completed in TODO.md │ │ @@ -231,38 +226,14 @@ Each step has a designated agent and a specific deliverable. No step is skipped. │ 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 Self-Declaration │ +│ (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) │ -│ As a software-engineer I declare: │ -│ * YAGNI: no code without a failing test — AGREE/DISAGREE | file:line │ -│ * YAGNI: no speculative abstractions — AGREE/DISAGREE | file:line │ -│ * KISS: simplest solution that passes — AGREE/DISAGREE | file:line │ -│ * KISS: no premature optimization — AGREE/DISAGREE | file:line │ -│ * DRY: no duplication — AGREE/DISAGREE | file:line │ -│ * DRY: no redundant comments — AGREE/DISAGREE | file:line │ -│ * SOLID-S: one reason to change per class — AGREE/DISAGREE | file:line│ -│ * SOLID-O: open for extension, closed for modification │ -│ — AGREE/DISAGREE | file:line │ -│ * SOLID-L: subtypes substitutable — AGREE/DISAGREE | file:line │ -│ * SOLID-I: no forced unused deps — AGREE/DISAGREE | file:line │ -│ * SOLID-D: depend on abstractions, not concretions │ -│ — AGREE/DISAGREE | file:line │ -│ * OC-1: one level of indentation per method — AGREE/DISAGREE | file:line│ -│ * OC-2: no else after return — AGREE/DISAGREE | file:line │ -│ * OC-3: primitive types wrapped — AGREE/DISAGREE | file:line │ -│ * OC-4: first-class collections — AGREE/DISAGREE | file:line │ -│ * OC-5: one dot per line — AGREE/DISAGREE | file:line │ -│ * OC-6: no abbreviations — AGREE/DISAGREE | file:line │ -│ * OC-7: ≤20 lines per function — AGREE/DISAGREE | file:line │ -│ * OC-8: ≤2 instance variables per class (behavioural classes only; dataclasses, Pydantic models, value objects, and TypedDicts are exempt) — AGREE/DISAGREE | file:line │ -│ * OC-9: no getters/setters — AGREE/DISAGREE | file:line │ -│ * Patterns: no creational smell — AGREE/DISAGREE | file:line │ -│ * Patterns: no structural smell — AGREE/DISAGREE | file:line │ -│ * Patterns: no behavioral smell — AGREE/DISAGREE | file:line │ -│ * Semantic: tests operate at same abstraction as AC │ -│ — AGREE/DISAGREE | file:line │ +│ 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) │ └─────────────────────────────────────────────────────────────────────┘ @@ -275,7 +246,7 @@ Each step has a designated agent and a specific deliverable. No step is skipped. │ │ │ 4a. READ │ │ in-progress .feature file (Rules + Examples + @id) │ -│ Self-Declaration from software-engineer │ +│ Self-Declaration communicated verbally by software-engineer │ │ │ │ 4b. pyproject.toml GATE │ │ git diff main -- pyproject.toml │ @@ -308,8 +279,8 @@ Each step has a designated agent and a specific deliverable. No step is skipped. │ [ ] Docstrings explain why, not what │ │ │ │ 4g. SELF-DECLARATION AUDIT │ -│ For every YES claim: find the file:line — does it hold? │ -│ For every NO claim: is the deviation justified? │ +│ 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) │ @@ -436,34 +407,7 @@ Source: docs/features/in-progress/.feature ## Cycle State Test: @id: -Phase: RED | GREEN | REFACTOR | SELF-DECLARE - -## Self-Declaration -As a software-engineer I declare: -* YAGNI: no code without a failing test — AGREE/DISAGREE | file:line -* YAGNI: no speculative abstractions — AGREE/DISAGREE | file:line -* KISS: simplest solution that passes — AGREE/DISAGREE | file:line -* KISS: no premature optimization — AGREE/DISAGREE | file:line -* DRY: no duplication — AGREE/DISAGREE | file:line -* DRY: no redundant comments — AGREE/DISAGREE | file:line -* SOLID-S: one reason to change per class — AGREE/DISAGREE | file:line -* SOLID-O: open for extension, closed for modification — AGREE/DISAGREE | file:line -* SOLID-L: subtypes substitutable — AGREE/DISAGREE | file:line -* SOLID-I: no forced unused deps — AGREE/DISAGREE | file:line -* SOLID-D: depend on abstractions, not concretions — AGREE/DISAGREE | file:line -* OC-1: one level of indentation per method — AGREE/DISAGREE | deepest: file:line -* OC-2: no else after return — AGREE/DISAGREE | file:line -* OC-3: primitive types wrapped — AGREE/DISAGREE | file:line -* OC-4: first-class collections — AGREE/DISAGREE | file:line -* OC-5: one dot per line — AGREE/DISAGREE | file:line -* OC-6: no abbreviations — AGREE/DISAGREE | file:line -* OC-7: ≤20 lines per function, ≤50 per class — AGREE/DISAGREE | longest: file:line -* OC-8: ≤2 instance variables per class (behavioural classes only; dataclasses, Pydantic models, value objects, and TypedDicts are exempt) — AGREE/DISAGREE | file:line -* OC-9: no getters/setters — AGREE/DISAGREE | file:line -* Patterns: no creational smell — AGREE/DISAGREE | file:line -* Patterns: no structural smell — AGREE/DISAGREE | file:line -* Patterns: no behavioral smell — AGREE/DISAGREE | file:line -* Semantic: tests operate at same abstraction as AC — AGREE/DISAGREE | file:line +Phase: RED | GREEN | REFACTOR ## Progress - [x] @id:: @@ -474,7 +418,7 @@ As a software-engineer I declare: ``` -`## Cycle State` is updated at every phase transition. `## Self-Declaration` is written once after all quality gates pass in Step 3. Both sections are present only during Step 3; omit when in other steps. +`## Cycle State` is updated at every phase transition. This section is present only during Step 3; omit when in other steps. ---