From contree
Close gaps between intent and implementation — one failing test at a time, outside-in, until the contract is fulfilled. TRIGGER when: implementing behaviour, writing code, or writing tests.
How this skill is triggered — by the user, by Claude, or both
Slash command
/contree:tddThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
1. **Outside-in, always** — start with a failing System test, then TDD inward: driving adapter → use-case → domain → port contract → driven adapter. The System test pulls inner layers into being; each inner layer then owns its own complete coverage with its own failing tests at its own seam. "The System test already covers this unit" is never a reason to skip the unit's own test.
## Test Trees before writing anything. Every test you write reifies exactly one tree. If no tree covers what you're about to build, stop and suggest change.src, unit, integration, functional) before moving to the next test. If that category was previously none, replace it with the new path — closing a declared gap. When you move or rename a file the tree names, update the paths in the same step as the move. TDD is where coverage actually lands on disk, so it is where paths must stay honest.The layer taxonomy, in-memory adapter pattern, shared port contract suite, and tree-naming heuristic all live in skills/change/SKILL.md — that's where decomposition decisions are made. This skill is the tactical cycle that implements those decisions.
Read ## Test Trees in the project's CLAUDE.md. The trees there are the contract. You are implementing against them.
If no tree covers the behaviour you're about to implement, stop and suggest running change first to write the tree before writing any code or tests.
Identify which tree in ## Test Trees covers this behaviour. State it explicitly:
Implementing against tree:
save-score
If the tree seems incomplete, note it but proceed with what's there. Don't modify existing trees — you can add newly discovered cases as you go.
Write one failing System test for the slice. It should map directly to a single when/then path in the tree.
Before writing the next test, decompose the failing path into the hex seams it touches. Pick the outermost untested layer and write one failing test there.
Questions in order:
ScoreRepository tree) first. Both the in-memory adapter and, later, the real adapter must satisfy it.Do not write tests for multiple layers in one step.
Write only enough code to make the failing test pass. YAGNI.
Confirm the inner test passes.
Continue inward — one failing test at a time. Write one, run it, see it fail, implement, see it pass. Then the next. Never batch.
The System test should now pass. If it doesn't, a layer is missing coverage — write another inner test to close the gap, implement, re-run System.
With all tests green, refactor the code you just changed — no broader. Resist the pull to keep tidying; it delays facing the next test. Duplication is a hint, not a command — don't extract abstractions until patterns have proven themselves.
Go to step 1 for the next behaviour (next when/then path in the test tree).
When all behaviours for current work are complete, run mutation testing as final validation. Do NOT run mutation testing during the TDD cycle.
After implementation is complete, suggest the user runs sync to verify test trees and implementation are aligned.
Test trees describe operating principles, not case enumerations. Use EARS patterns (see EARS Patterns below) to choose the right keyword for each requirement.
GOOD — uses EARS patterns to match each requirement's nature:
UserRegistration
then passwords are stored hashed, never in plain text
when a new user registers with valid details
then the user account is created
and a welcome email is sent
if the email is already registered
then registration is rejected
and the existing account is not modified
BAD — enumerates cases:
UserRegistration
when name is "Alice"
then account for Alice is created
when name is "Bob"
then account for Bob is created
skills/change/SKILL.md.skills/change/SKILL.md. At Domain, Use-case, and Port-contract, top-level describes are the unit's functions/methods and every path is an observable branch. At Adapter and System, the tree describes behaviour at the seam.when, while, if, where, or bare then) to match the requirement's nature.then describes outcomes.if/then for error cases and unwanted behaviour.## Test Trees. One tree, one test file.Tactical cheatsheet for the RED/GREEN cycle. See skills/change/SKILL.md for the full layer taxonomy, seam diagram, in-memory adapter pattern, shared port contract suite, and naming heuristic — that's where the strategic decisions live.
*.domain.test.*, colocated)*.use-case.test.*, colocated)execute or the function); inner describes are branches.*.adapter.test.*, colocated)*.adapter.test.*, colocated)*.contract.ts), plus any real-infra test helpers (Testcontainers, local service, etc.).*.system.test.* in test/system/)*.contract.ts). Both in-memory and real adapters must pass it. (Only when a port exists.)Every failing test sits at a named layer. If you can't name the layer, you're not decomposed enough. Equally: if you can't name the implementation pressure from the failing functional test that forces this inner test to exist, don't write it yet.
When System pulls a new unit into being, that unit gets its own tree and its own failing tests at its native layer — before the implementation lands. Do not lean on the System test as the unit's coverage; it isn't. If you find yourself thinking "the System test already exercises this so I'll skip the unit test," that is the signal to write the unit's tree and failing test, not to skip it. Overlap between layers is the intended shape — unit tests prove the unit is complete on its own terms; higher tests prove the wiring and the user-visible arc.
Test trees use EARS (Easy Approach to Requirements Syntax) to choose the right keyword for each requirement. Match the pattern to the requirement's nature — don't force everything into when/then.
Ubiquitous — always true, no condition:
then <outcome>
State-driven — active while a condition holds:
while <precondition>
then <outcome>
Event-driven — response to a trigger:
when <trigger>
then <outcome>
Optional feature — applies only when a feature is present:
where <feature>
then <outcome>
Unwanted behaviour — response to error or undesired situation:
if <condition>
then <outcome>
Complex — state + event combined:
while <precondition>
when <trigger>
then <outcome>
Causal nesting — when a trigger can only occur as a consequence of a prior outcome, nest it under that outcome:
when <trigger>
then <outcome>
when <consequence of outcome>
then <next outcome>
A when that depends on a preceding then is not a sibling — it is a child. If "refresh fails" can only happen because "refresh was attempted", nest it under the then that attempts the refresh.
Choose the pattern that fits: a system constraint is ubiquitous; a precondition that must hold is state-driven; a discrete trigger is event-driven; an error case is unwanted behaviour; a feature flag is optional. Combine when needed. Nest when one behaviour depends on another's outcome.
npx claudepluginhub elimydlarz/claude-code-plugins --plugin contreeProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.