verify-ddd-tdd
Skill7 starsChanged 22 days agoMITView on GitHub
Use after /implement-tdd, before the next batch: audits a .NET batch (correctness, reuse, simplification, cost, plan conformance, test policy, TDD evidence). Fast by default, full on request.
In this repository10 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- askSkill
- business-specSkill
- implement-tddSkill
- kit-initSkill
- knowledge-mergeSkill
- knowledge-syncSkill
- learnSkill
- plan-implementationSkill
- quality-reportSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 56
Don't propose adding a comment, XML doc, anticipatory abstraction or isolated aggregate test: they are deviations, not fixes.
- Very specific: line 75
No green without exit code 0.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
DDD + TDD verification
Audit, never modify. Covers a batch implemented by /implement-tdd, never a feature without plan. Validations run the repo's configured commands (commands.build, commands.test), resolved as in skills/implement-tdd/references/test-scope.md § Runner.
$ARGUMENTS
Modes
- Fast, default: global plan + batch sheet, DDD/APP/PERF coverage, applied ids, diff, modified files, targeted tests.
- Full, with
fullin argument: widens to touched boundaries, adds whole fast suites (§3.4). Never the wholeIntegrationTestssuite. - Resume, with
resume: re-audit after correction. Scope = previous verdict's deviation table + the correction's change set, both supplied by the caller — the change set read off the tree (cctoolkit audit-round), never the files the correction declared. Read only those files and their diff; re-judge only the axes and suites the deviations reach; nothing already verdicted is re-established. A changed file that is neither cited as a deviation's evidence nor the test of one is a Scope Major, unless the correction declared it as an extension whose reason a deviation's closure required. A gap the correction contested gets its answer (§ Contested findings).
Coverage: read the compact indexes ddd-rules.md + architecture-rules.md (under 6 kB), then the lines of the ids the sheet applies. ddd-examples.md only if an id stays ambiguous.
Workflow
1. Establish the scope
- Require
batch FX. The caller supplies the sheet's FX section and the capture ofcctoolkit audit-capture: status,diff --check, modified files, diff,cctoolkit rules-coverage --untestedand--ids <sheet>,cctoolkit access-cost --diff, build /ArchitectureTestsexit codes. Use it as is; read the plan or sheet yourself only if missing or contradicting the repo. No capture → produce status, check and diff yourself, one command. Read the capture's## Mechanical audit — FXsection first (Axis | Check | Result | Evidence): anokrow is never re-established — no rerun, no re-derivation from the diff; agaprow is a finding of the verdict, severity of its axis (§ Severities), itsEvidencecell the evidence; anot checkedrow is yours to judge, the layer-rule axes of §2 always are. No section (older capture): everything above is yours. - No full coverage, or no Design section: still audit the code (§2), report the plan gap as Major, fix = update sheet. Every id is
appliedon a sheetkit:applied-rulesrow, orN/A — reasononce on the global plan'skit:na-rulesline. The capture'snot citedline settles the mechanical half — an id listed there = Blocking unclassified id. Yours: whether a statedN/Areason holds. Never infer design from the implementation. - Walk the diff hunk by hunk, tie each to an RM/CU or sheet step; untied = Scope deviation. Read beyond a hunk only when the axis being judged needs it. Expected diff already committed → require an explicit base in argument.
2. Audit the delivered code
One table, one pass, over the batch diff. A green test proves nothing here. Ids cited = those of ddd-rules.md + architecture-rules.md: read the id line before invoking it.
| Axis | What counts as a deviation | Evidence required to report it |
| Correctness | Untreated error path; absence or null unhandled; wrong comparison boundary; operation order leaving invalid intermediate state; swallowed exception; silent default masking failure; concurrent write on same aggregate, no concurrency handling. Command modifying or saving >1 aggregate outside DDD-08 exception stated with its consistency. Persistence-constraint violation not translated into domain exception (APP-03), or translated by generic filter (Contains("duplicate")) instead of one naming index — upstream uniqueness check = early failure, not deviation; missing translation = deviation. | Concrete breaking scenario, inputs X → wrong behaviour Y. No scenario → no report. |
| Reuse | Type, service, VO or method created while existing element covers need, or 80 % of it. Second type of existing shape: rename or extend existing, never duplicate. | Existing element as path:line. No named element → no report. |
| Simplification | Defensive branch on case an invariant of batch makes impossible — symmetrically, invariant announced in sheet removing no branch, loop, grouping or read is itself deviation. Indirection, wrapper or intermediate mapping with single caller. Dead code introduced or orphaned by batch; parameter never read; optional parameter or default no caller supplies; abstraction with no second implementer. Nullable collection in Domain/Application, or optional concept tested is null at every use instead of modelled (DDD-11). Pre-existing dead code = Minor: removing it lies outside batch scope, unless batch worsens it (§2 Worsened). | Line + concrete effect. No stylistic preference, no alternative-architecture suggestion, no proposed rewrite. |
| Cost | Capture's access-cost section lists the calls: judge from it, open a hunk only for an unclassified receiver or an Include. Flag on a line the batch added = deviation; on a pre-existing line = Minor, outside batch, unless batch worsens it (§2 Worsened). Repository call inside input-driven loop; unbounded read; Include of collection growing without limit; materialisation before filtering; one query per element (PERF-01). Bounded cost differing from sheet = Plan deviation, not code one. | idem |
| Placement | Business rule or validation carried by handler, repository, Infrastructure or WebAPI instead of aggregate concerned (DDD-02, APP-04) — handler orchestrates load, business call, save; never decides. Business operation in helper or static service receiving business object state; Domain Service neither stateless nor justified (DDD-09). Rule owned by external system (identity provider, external catalogue, organisation directory) replayed here, or share/transfer target validated by mere existence instead of the relationship authorising it. Create() and Restore() conflated, or repository not aggregate-centred (DDD-06, APP-03). Resource limit hand-rewritten in handler or carried by Domain instead of its owner (APP-05): WebAPI RequestLimits/rate limiting for transport, PaginationBounds at query creation, ReadLimits for read cap; unpaginated read with no cap. Exception: pre-check duplicating authority named elsewhere (persistence constraint, external system) is deviation only if sole owner of rule. | idem |
| Comments | Comment the code makes useless: paraphrase of the code, change narrative, ticket number, stale statement; XML /// doc in a file that carries none. A comment giving a constraint, decision or workaround the code cannot carry is not a deviation. pre-audit lists added comments without failing: judge each from the capture's diff. | The line + what in the code already says it. |
| Test | A rule of the handler test policy broken (test-scope.md §5: aggregate tested directly, query or command asserted on anything else, interaction assertion); Verify snapshot of a contract test is not an interaction. Wrong or missing level (§1 of same file): diff hunk touching src/{{PRODUCT}}.Infrastructure/ with no integration test and no waiver in sheet; contract test with no route changed. | Test as path:line, or uncovered Infrastructure hunk. |
| Plan | RM/CU with no code owner. Unit test without its [Trait("RM", "{HandlerFolder}/{RM|RL-xx}")], integration test proving a documented rule without it, trait citing rule absent from handler table, or a contract or E2E test carrying one. Id missing from coverage; N/A without reason; id applied with no owner. TDD evidence: a cycle of the capture's TDD cycles section without an observed RED (exit ≠ 0) before its GREEN, or a sheet without ## Cycles whose TDD: ticks claim what nothing observed — except declarative artifacts listed in common-rules.md §4.5, written by orchestrator with no red before them (assumed, not deviation, as long as they carry no branch, validation or mapping decision), and methods a RED listed as unreachable. A stubs with logic line of the capture is a stub the RED check saw carrying a branch: code written before its test unless the line is pure declaration — judge it, Blocking when it is. A decision the run took without the user is listed by the caller for the user to validate (TO-VALIDATE.md): never a deviation for being absent from the sheet. | RM/CU or id, and where evidence is missing. |
| Scope | Diff hunk with no RM/CU nor sheet step carrying it. Refactor, renaming, reformatting, reorganisation of working code batch had no reason to touch. Adjacent bug fixed outside batch RM/CU. Unrequested removal of pre-existing dead code or comment outside touched lines. Flexibility, configurability or abstraction with no expressed need. | Hunk as path:line + missing RM/CU or sheet step. Line required by delivered behaviour — propagated signature, DI registration, newly necessary using — is traced: not deviation. |
Locating the existing element behind a Reuse or Placement deviation: graphify explain|affected "X" first, grep -rn scoped to the layer folder otherwise.
Bug class — a Correctness, Cost or Placement deviation is a pattern, not a line. Before reporting it, git grep -n that pattern over the files the batch changed: every instance goes in the same gap, Evidence listing each path:line, Closure covering them all. Fixed one instance at a time, the class comes back each round.
Worsened — pre-existing defect the batch makes measurably worse, judged as if batch introduced it: severity of its axis, Gap cell prefixed (worsened). Worse means one more of the same thing: one more repository call in an already looping path, one more branch in an already defensive chain, one more copy of an already duplicated block, one more caller of a pre-existing unbounded read. Evidence: pre-existing state (context line of hunk, or path:line at base) and batch line adding to it. Untouched pre-existing defect, or one batch merely sits next to, stays Minor. Fix expected: only what batch added, never pre-existing part — outside scope.
Missing evidence never a favourable assumption: cite file and line where deviation observed, or say point could not be verified.
Don't propose adding a comment, XML doc, anticipatory abstraction or isolated aggregate test: they are deviations, not fixes.
Classify every code/plan divergence before reporting it, one explicit line:
- Faulty code — plan still right, implementation departs. Fix: code.
- Stale plan — implementation better, or decision settled mid-batch. Fix: sheet, plus source spec if RM/CU moves. Severity Minor — the code is the reference, the sheet a plan; Major only when an RM/CU moves and the spec must follow.
- Unsettleable divergence — both readings hold. Report both, arbitration to user. Never decide in plan's place.
RM/CU with no code owner stays blocking in all three cases: hole, not divergence.
3. Run the minimal validations
Runner, filters, suite scope, integration filter → skills/implement-tdd/references/test-scope.md. Test volume is an audit decision: never re-run what /implement-tdd or the capture already ran — read its exit code, run only what is missing or was scoped too narrowly.
- Build +
ArchitectureTests: exit codes from the capture. WhatArchitectureTestslocks is not re-argued; what it breaks is blocking. - Tests named in the sheet: targeted filter first.
- Suites the diff makes mandatory, whole or filtered per §2 of that file.
full: addsUnitTests+ContractTestsin full.
No green without exit code 0. Distinguish not run, skipped, failed. The Validations line carries each command's scope: a filter without scope reads as a full suite.
Severities
- Blocking — any of the four rules of
test-scope.md§5, RM/CU with no code owner, unclassified id, rule applied with no owner, redArchitectureTests, diff touchingsrc/{{PRODUCT}}.Infrastructure/with no integration test and no written waiver, cycle without observed RED (or TDD evidence ticked without observation on a sheet without## Cycles), any Correctness deviation carrying breaking scenario. - Major — missed reuse of named existing element, unbounded cost, business rule outside its aggregate, resource limit outside its owner (APP-05: WebAPI
RequestLimits,PaginationBounds,ReadLimits), comment in production, stale plan moving an RM/CU, hunk outside batch scope. - Minor — simplification with no functional consequence, pre-existing dead code or cost reported (observation, not request to fix), stale plan with no RM/CU moving. Pre-existing defect worsened by batch is never Minor by origin: severity of its axis.
Verdict GAPS as soon as Blocking or Major exists. Minors listed under VALID verdict without calling it into question.
Verdict
Verdict block alone, no preamble, no recap of plan, files or logs; on failure ≤6 useful lines of the command output. Ceiling 1.5 kB for VALID, 3 kB for GAPS — the calling session carries it every later turn. Headings, severities and axis labels are frozen literals (learn-candidates.py parses them). End with one of these two formats, verbatim:
## Verdict — VALID
| RM/CU or rule | Code evidence | Test evidence |
|---------------|---------------|---------------|
| RM-01 / DDD-02 / APP-01 | `path:line` | `Should...` |
Code — minors (do not block the next batch):
| Axis | Finding | Evidence |
|------|---------|----------|
| Simplification | Defensive branch on a case excluded by the invariant | `path:line` |
Scope: `[n]` hunks, all traced to an RM/CU or step — otherwise list the untraced hunks
Assumptions: `Hn` — `[assumption]`, to be validated by `[who]` — or "none"
Reported without fixing: `[pre-existing dead code or adjacent bug]` — `path:line`
Validations: `[command]` — exit 0, scope `[filter or "whole suite"]`, `[n]` tests
Not run: `[suite]` — `[reason]`## Verdict — GAPS
| Severity | Axis | Gap | Evidence | Closure | Expected fix |
|----------|------|-----|----------|---------|--------------|
| Blocking | Correctness | Unhandled absence: `inputs X → wrong behaviour Y` | `path:line` | `inputs X` → `outcome Z`, a test proving it | Handle the missing case in the aggregate |
| Blocking | Test | Spy in a handler test | `path:line` | No interaction assertion left in the test | Assert the result or SavedEvents depending on the handler type |
| Major | Reuse | Second type of the same shape as the existing one | `path:line` | One type of that shape | Rename and extend `path:line` |
| Major | Cost | (worsened) Second repository call in a pre-existing loop | `path:line` | The batch adds no call inside the loop | Remove the call the batch added |
| Major | Plan | Stale plan: an RM moves, the sheet and the spec still state the old one | `path:line` | Sheet and spec state the delivered RM | Update the sheet, and the spec if an RM moves |
| Major | Scope | Hunk with no RM/CU nor owning step | `path:line` | Every hunk traced | Revert the hunk, or tie it to a step of the sheet |
Validations: `[command]` — exit N, scope `[filter or "whole suite"]` / not runClosure = the observable state that closes the gap, checkable by reading the code or running a test; Expected fix is one way to reach it, never an order.
Contested findings
The correction may contest a gap instead of applying it, only by naming a concrete harm its closure would do: a behaviour it breaks, an invariant it violates, a cost it adds. "Complex", "out of scope", "not needed" open no contest: the gap is applied and the objection recorded. The resume audit answers each contest once, never by repeating the gap:
- Accept — the harm holds and outweighs the gap: the finding closes, the trade-off goes to the user's review.
- Counter — another closure reaches the gap without the harm: state it; the next round applies it.
- Refute — the harm does not hold: why, with evidence
path:line; the next round applies the gap. - Escalate — both readings hold and the choice is the user's: it goes to the user's review, nothing waits on it.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

