spec-locked-tdd
Skill2 starsChanged 3 months agoMITView on GitHub
Drive feature additions, behavior changes, and bug fixes through a specification-locked TDD workflow. Use when the user asks for TDD, red-green-refactor, tests before implementation, behavior/invariant-driven development, regression-first bug fixing, or when coding agents must be prevented from weakening tests merely to make a change pass. Shape observable behavior, derive invariants and a risk-based test portfolio, prove RED, lock the test oracle, implement the minimum GREEN change, refactor only while green, and verify at broader boundaries. Pairs well with defensive/assertion-heavy skills such as tiger-style. Do not use for pure research, docs-only edits, or throwaway spikes unless explicitly requested.
In this repository9 other files it gives its agents.
- animejsSkill
- container-security-auditSkill
- tiger-styleSkill
- nextjs-security-reviewSkill
- reactflowSkill
- react-security-reviewSkill
- structural-refactorSkill
- whatsapp-cloud-apiSkill
- whatsapp-flows-jsonSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
56 rules. About 0 are common, 49 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈49
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Use tests as an executable specification and feedback mechanism, not as a post-hoc ceremony or a coverage game.
- Very specific: line 20
Read repository instructions (AGENTS.md, CONTRIBUTING, test docs, package scripts, CI config) and inspect nearby production code and tests.
- Distinctive: line 22
Run the narrowest relevant existing tests, or the project’s normal baseline test command when practical.
- Distinctive: line 44
If a material product or domain choice is unresolved and no repository convention resolves it, do not invent an oracle and then encode it …
- Distinctive: line 46
If the task is sufficiently specified, proceed without unnecessary approval.
- Distinctive: line 52
Do not mechanically write every kind of test.
- Very specific: line 54
Use references/test-strategy.md for selection guidance.
- Distinctive: line 59
Property-based or fuzz tests: when stable invariants span many inputs.
- Distinctive: line 60
Integration tests: when correctness depends on a real database, serialization layer, filesystem, framework configuration, transaction …
- Distinctive: line 63
Smoke tests: only as coarse “is the integrated system alive?” checks.
- Distinctive: line 66
Do not chase a fixed test pyramid ratio.
- Distinctive: line 74
Prefer one coherent behavior per test.
- Distinctive: line 75
Use descriptive names that state the scenario and expected outcome.
- Distinctive: line 76
Keep setup readable. In tests, clarity is usually more valuable than aggressive DRY abstraction.
- Distinctive: line 77
Prefer real collaborators when they are fast, deterministic, and easy to instantiate.
- Distinctive: line 78
Do not assert incidental internal calls, private methods, temporary data structures, or ordering unless they are part of the contract.
- Distinctive: line 79
Test failure behavior and forbidden states, not only the happy path.
- Distinctive: line 81
Do not use snapshots as the only oracle for important behavior.
- Distinctive: line 82
Never write tautological tests that reproduce the production algorithm in the test.
- Distinctive: line 83
Never create an oracle solely from the implementation being written.
- Distinctive: line 89
Write the smallest test or test slice that expresses it.
- Distinctive: line 90
Run that test immediately.
- Distinctive: line 95
If the test unexpectedly passes, stop and investigate.
- Distinctive: line 103
Do not implement until the RED signal is understood.
- Distinctive: line 109
When practical, run this skill’s deterministic guard:
- Very specific: line 117
If the skill lives outside the repository, invoke the script using its actual skill path.
- Distinctive: line 121
delete the failing test;
- Very specific: line 124
add skip, xfail, .only, retries, sleeps, or arbitrary timeout/tolerance increases to obtain green.
- Distinctive: line 127
add production fallbacks/defaults that hide an invalid state solely to satisfy a test.
- Distinctive: line 143
Write the smallest production change that makes the current RED behavior pass while respecting existing contracts.
- Distinctive: line 145
Keep the diff local.
- Distinctive: line 147
Do not preemptively implement later test cases unless the design naturally covers them.
- Distinctive: line 148
Do not perform broad refactors while RED.
- Distinctive: line 149
Do not add speculative abstractions “for future flexibility.”
- Distinctive: line 156
After focused tests are green:
- Distinctive: line 158
Remove duplication and accidental complexity.
- Distinctive: line 161
Keep public behavior unchanged.
- Distinctive: line 162
Run the focused tests after each meaningful refactor step.
- Distinctive: line 165
If refactoring requires changing a behavior test, determine whether the test was coupled to implementation details.
- Distinctive: line 171
If new information invalidates a locked expectation:
- Very specific: line 176
Harness correction: import/setup/framework mistake that does not alter behavioral meaning.
- Distinctive: line 185
Update the affected tests.
- Distinctive: line 193
When the focused slice is green and refactored:
- Distinctive: line 195
Check the spec lock.
- Distinctive: line 196
Run all directly related unit tests.
- Distinctive: line 197
Run relevant integration/contract tests for touched boundaries.
- Distinctive: line 198
Run the smallest acceptance/E2E or smoke path needed for cross-component confidence.
- Distinctive: line 199
Run type checking, static analysis, linting, and build checks used by the repository.
- Distinctive: line 203
Do not claim correctness from line coverage.
- Very specific: line 207
Prefer many short Red/Green/Refactor cycles over a giant batch of tests followed by a giant implementation.
- Distinctive: line 211
keep a test list / behavior checklist.
- Distinctive: line 214
keep every intermediate state buildable and understandable.
- Distinctive: line 215
add newly discovered behaviors to the list rather than implementing them invisibly.
- Distinctive: line 219
When finishing a TDD-driven change, report concise evidence:
- Distinctive: line 246
Never say “fully correct” merely because the suite is green.
- Very specific: line 250
Read references/agent-failure-modes.md when the change is substantial, flaky, highly mocked, or repeatedly resists GREEN.
≈ “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
Spec-Locked TDD
Use tests as an executable specification and feedback mechanism, not as a post-hoc ceremony or a coverage game.
The governing loop is:
Shape -> Select behavior -> RED -> LOCK -> GREEN -> REFACTOR -> VERIFY -> repeat.
A green suite is evidence, not proof. Never treat “all tests pass” as sufficient if the tests can be weak, stale, over-mocked, or edited to match the implementation.
0. Establish the working context
Before changing behavior:
- Read repository instructions (
AGENTS.md,CONTRIBUTING, test docs, package scripts, CI config) and inspect nearby production code and tests. - Identify the existing test framework, naming/layout conventions, fixtures, factories, fakes, and integration-test infrastructure. Reuse them unless there is a concrete reason not to.
- Run the narrowest relevant existing tests, or the project’s normal baseline test command when practical. Record pre-existing failures separately; do not “fix” unrelated failures as part of the feature.
- Determine whether a companion defensive-programming skill is active. If
tiger-styleor equivalent guidance is available, use its preconditions, postconditions, assertions, bounded behavior, strong typing, and negative-space reasoning as inputs to the feature contract and test design. Do not duplicate or weaken that skill.
1. Shape the feature before coding
TDD requires a crisp next observable behavior, not a complete architecture designed upfront.
For any non-trivial behavior change, establish a compact feature contract before implementation. Use assets/feature-contract-template.md when a persistent artifact is useful.
Define:
- Goal: user/system outcome.
- Public surface: API, command, event, UI behavior, domain operation, or other observable interface.
- Acceptance behaviors: concrete Given/When/Then examples.
- Invariants: conditions that must always hold.
- Forbidden states / negative space: states, transitions, outputs, or side effects that must never occur.
- Failure semantics: expected errors, rejection rules, retries, idempotency, rollback/atomicity, and partial-failure behavior where relevant.
- Boundaries: database, filesystem, network, queue, clock, randomness, third-party API, process, or service boundary.
- Risk notes: money, auth, authorization, destructive operations, concurrency, privacy, security, migration compatibility, latency, or other feature-specific risks.
Shaping gate
If a material product or domain choice is unresolved and no repository convention resolves it, do not invent an oracle and then encode it as a test. Surface the smallest decision set needed to continue.
If the task is sufficiently specified, proceed without unnecessary approval. Make assumptions explicit when they matter.
For exploratory or uncertain work, run a spike outside the TDD loop, discard or quarantine spike code, then convert what was learned into a feature contract before production implementation.
2. Build a risk-based test portfolio
Do not mechanically write every kind of test. Choose the cheapest test level that can faithfully observe each behavior.
Use references/test-strategy.md for selection guidance.
Default preferences:
- Behavior-focused unit tests for deterministic domain/application logic.
- Property-based or fuzz tests when stable invariants span many inputs.
- Integration tests when correctness depends on a real database, serialization layer, filesystem, framework configuration, transaction behavior, or infrastructure component.
- Contract tests at service/client/provider boundaries where mocks can drift from reality.
- Acceptance/E2E tests for a small number of critical user-visible journeys or cross-component behaviors.
- Smoke tests only as coarse “is the integrated system alive?” checks; never as a substitute for focused behavior tests.
- Mutation testing selectively for critical pure/domain logic or whenever ordinary coverage looks reassuring but oracle strength is uncertain.
Do not chase a fixed test pyramid ratio. Prefer small, deterministic tests, but add larger tests wherever the failure mode exists only at a real boundary.
3. Write tests as behavioral contracts
Tests should describe what the system guarantees through public/observable interfaces, not how the current implementation happens to work.
Rules:
- Prefer one coherent behavior per test.
- Use descriptive names that state the scenario and expected outcome.
- Keep setup readable. In tests, clarity is usually more valuable than aggressive DRY abstraction.
- Prefer real collaborators when they are fast, deterministic, and easy to instantiate; otherwise prefer faithful fakes. Use mocks/stubs narrowly.
- Do not assert incidental internal calls, private methods, temporary data structures, or ordering unless they are part of the contract.
- Test failure behavior and forbidden states, not only the happy path.
- For a bug fix, first encode the reported bug as a regression test that fails on the current behavior.
- Do not use snapshots as the only oracle for important behavior. Review any snapshot intentionally.
- Never write tautological tests that reproduce the production algorithm in the test.
- Never create an oracle solely from the implementation being written.
4. RED — prove the test can detect missing behavior
For the next smallest behavior:
- Write the smallest test or test slice that expresses it.
- Run that test immediately.
- Confirm it fails for the expected semantic reason.
A compile/import failure can be a legitimate first RED when the new public API does not exist yet, but reach a behavioral failure as soon as possible.
If the test unexpectedly passes, stop and investigate. Possible explanations:
- behavior already exists;
- the test does not exercise the intended path;
- the assertion is too weak;
- setup bypasses the behavior;
- the specification is stale or redundant.
Do not implement until the RED signal is understood.
5. LOCK — protect the oracle before implementation
Once RED is established, the meaning of the specification and failing test is frozen for the current slice.
When practical, run this skill’s deterministic guard:
python scripts/spec_lock.py lock \
--spec path/to/feature-contract.md \
--tests path/to/relevant-test-fileIf the skill lives outside the repository, invoke the script using its actual skill path. The command writes .tdd-spec-lock.json in the current working directory by default.
During GREEN, do not:
- delete the failing test;
- weaken, remove, or invert an assertion;
- broaden accepted outputs merely to include the implementation’s output;
- add
skip,xfail,.only, retries, sleeps, or arbitrary timeout/tolerance increases to obtain green; - blindly update snapshots;
- replace a faithful dependency with a mock that simply returns the desired answer;
- add production fallbacks/defaults that hide an invalid state solely to satisfy a test;
- swallow errors or silently coerce invalid input solely to satisfy a test;
- edit the feature contract so that the current implementation becomes “correct.”
Run:
python scripts/spec_lock.py checkbefore declaring the slice complete.
The script is a guardrail, not a security boundary. A coding agent can still edit or delete it; process discipline and review remain necessary.
6. GREEN — implement the minimum behavior
Write the smallest production change that makes the current RED behavior pass while respecting existing contracts.
- Keep the diff local.
- Re-run the focused test frequently.
- Do not preemptively implement later test cases unless the design naturally covers them.
- Do not perform broad refactors while RED.
- Do not add speculative abstractions “for future flexibility.”
- Preserve strong typing, explicit errors, assertions, bounds, and defensive checks required by the domain or companion defensive-programming skill.
A minimal implementation does not mean a hack. It means no behavior or abstraction beyond what current evidence requires.
7. REFACTOR — improve design only while green
After focused tests are green:
- Remove duplication and accidental complexity.
- Improve names and responsibility boundaries.
- Extract concepts only when the code now demonstrates the abstraction.
- Keep public behavior unchanged.
- Run the focused tests after each meaningful refactor step.
- Re-run
spec_lock.py checkafter refactoring.
If refactoring requires changing a behavior test, determine whether the test was coupled to implementation details. Fix that coupling through the Spec Revision Protocol rather than casually editing the test.
8. Spec Revision Protocol
Sometimes the test or specification is genuinely wrong. Test immutability is not dogma; silent oracle mutation is forbidden.
If new information invalidates a locked expectation:
- Stop implementation work.
- State exactly which assumption/requirement is wrong and why.
- Classify the change:
- Harness correction: import/setup/framework mistake that does not alter behavioral meaning.
- Specification revision: acceptance behavior, invariant, failure semantics, or allowed output changes.
- For a specification revision, update the feature contract first.
- Record the reason when unlocking:
python scripts/spec_lock.py unlock --reason "<why the oracle must change>"- Update the affected tests.
- Re-run them and, where possible, demonstrate a meaningful RED against the current implementation.
- Re-lock and resume GREEN.
A harness correction may be made without product-level approval if behavioral meaning is unchanged, but it must still be called out in the final evidence report.
9. VERIFY — broaden confidence by risk
When the focused slice is green and refactored:
- Check the spec lock.
- Run all directly related unit tests.
- Run relevant integration/contract tests for touched boundaries.
- Run the smallest acceptance/E2E or smoke path needed for cross-component confidence.
- Run type checking, static analysis, linting, and build checks used by the repository.
- For critical logic, consider mutation testing or property/fuzz testing.
- For concurrency, distributed state, retries, idempotency, transactions, or failure recovery, add targeted tests at the level where those properties are observable.
Do not claim correctness from line coverage. Coverage can reveal unexecuted code; it cannot establish that assertions are meaningful.
10. Repeat in small, uniform slices
Prefer many short Red/Green/Refactor cycles over a giant batch of tests followed by a giant implementation.
For a larger feature:
- keep a test list / behavior checklist;
- anchor the feature with one acceptance behavior if useful;
- implement one coherent behavior at a time;
- keep every intermediate state buildable and understandable;
- add newly discovered behaviors to the list rather than implementing them invisibly.
11. Required completion report
When finishing a TDD-driven change, report concise evidence:
Behavior contract:
- ...
Tests added/changed:
- ...
RED evidence:
- command
- expected failure observed
GREEN evidence:
- command(s)
- result
Spec-lock status:
- unchanged | revised (reason: ...)
Broader verification:
- integration/contract/e2e/typecheck/lint/build/mutation as applicable
Residual risk / intentionally omitted tests:
- ...Never say “fully correct” merely because the suite is green.
12. Failure-mode rules for coding agents
Read references/agent-failure-modes.md when the change is substantial, flaky, highly mocked, or repeatedly resists GREEN.
Escalate instead of cheating when:
- the desired behavior conflicts with existing public behavior;
- the only path to green appears to require weakening the oracle;
- an external dependency cannot be represented faithfully;
- the suite is flaky or non-hermetic;
- implementation reveals an architecture/boundary problem bigger than the requested feature;
- the contract is not deterministic enough for conventional assertions.
For nondeterministic systems (for example LLM output), replace exact-output assumptions with stable contracts: schemas, invariants, deterministic preprocessing, bounded properties, golden datasets, or explicit eval criteria. Conventional TDD still applies to deterministic surrounding code.
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.

