Turn your product spec into executable rules that enforce themselves.
You don't need to learn anything first. Paste this to your LLM:
Set up Specflow for this project. Read LLM-MASTER-PROMPT.md, then:
1. Ask me what should NEVER be broken (plain English is fine)
2. Generate REQ IDs from my description (AUTH-001, STORAGE-001, etc.)
3. Create contracts in docs/contracts/
4. Create tests in src/__tests__/contracts/
5. Add to CI so violations block the build
6. Update CLAUDE.md with the rules
Goal: Anyone who violates a contract = build fails. Start by asking me questions.
The LLM will interview you, then generate everything.
This system uses contracts to make specs testable.
You describe what matters. We convert it into:
- YAML feature contracts (pattern-based rules)
- YAML journey contracts (Definition of Done)
- Automated tests
- A master LLM prompt that keeps the app aligned with those contracts.
If a contract is violated:
- Tests fail
- CI blocks the merge
- LLMs get a clear violation message
This system has exactly two types of contracts:
What they enforce: Architectural rules at the code level
Location: docs/contracts/feature_*.yml
rules:
non_negotiable:
- id: AUTH-001
forbidden_patterns:
- pattern: /localStorage/
message: "Not available in service workers"Feature contracts scan source files for patterns that must exist or must never appear. They catch bad code before it ships.
What they enforce: Complete user experiences work end-to-end
Location: docs/contracts/journey_*.yml
dod:
criticality: critical # critical | important | future
status: passing # passing | failing | not_tested
blocks_release: true
journey_definition:
name: "Complete Purchase"
steps:
- step_name: "Add to Cart"
required_elements:
- selector: "[data-testid='add-to-cart']"Journey contracts ARE your Definition of Done. A feature isn't complete when code compiles—it's complete when users can accomplish their goals. Critical journeys block release if failing.
See USER-JOURNEY-CONTRACTS.md for the complete template and examples.
-
Write or update spec
- Edit
docs/specs/<feature>.mdin a simple, constrained format (seeSPEC-FORMAT.md). - Define ARCHITECTURE constraints first (ARCH-xxx) - structural invariants.
- Define REQS (feature requirements) and JOURNEYS (user flows).
- Mark journeys as Critical, Important, or Future in your Definition of Done.
- Edit
-
Generate / update contracts (Architecture First!)
- First: Create
feature_architecture.ymlwith ARCH-xxx rules (if it doesn't exist). - Then: Create feature contracts with FEAT-xxx rules.
- Then: Create journey contracts with DOD criticality.
- Use the LLM with
LLM-MASTER-PROMPT.mdor runnpm run contracts:generate <feature>.
- First: Create
-
Run tests
npm test -- contracts(pattern tests - includes architecture checks)npm test -- journeys(E2E journey tests)- Fix any violations.
-
Feature Impact Analysis (for changes)
- Which existing journeys does this feature touch?
- Re-run ALL affected journey tests.
- Architecture violations in new code break ALL journeys.
-
Verify Definition of Done
- All Critical journeys must be
passing. - Important journeys should be
passing. - Future journeys can remain
not_tested.
- All Critical journeys must be
-
Implement or refactor
- LLMs AND humans read contracts before touching protected files.
- Architecture contracts are NEVER bypassed without explicit override.
SPEC-FORMAT.md→ How to write specs with REQS, JOURNEYS, and DEFINITION OF DONE
docs/contracts/feature_*.yml→ Feature contracts (code patterns)docs/contracts/journey_*.yml→ Journey contracts (user flows = DOD)CONTRACT-SCHEMA.md→ YAML schema for both contract typesUSER-JOURNEY-CONTRACTS.md→ Complete guide to journey contracts
src/__tests__/contracts/*.test.ts→ Pattern tests for feature contractstests/e2e/journey_*.spec.ts→ E2E tests for journey contracts (release gates)
LLM-MASTER-PROMPT.md→ Prompt that enforces contracts during development
Before modifying ANY protected file:
- Ask: "Is this file protected by a contract?"
- If yes:
- Read the relevant
.ymlcontract. - Check the
compliance_checklist. - Run
npm test -- contractsornode scripts/check-contracts.js <file>. - Only then propose code changes.
- Read the relevant
If user says:
override_contract: <contract_id>
then LLM may suggest changes but must:
- Explain what rule is being broken.
- Suggest how to update the contract and tests if the change is permanent.
# Run all contract tests
npm test -- contracts
# Quick check a single file
node scripts/check-contracts.js src/path/to/file.ts
# Generate or update contracts for a feature (LLM-assisted)
npm run contracts:generate spec/user-authentication.mdSee SPEC-FORMAT.md and CONTRACT-SCHEMA.md to define new features and contracts.
project/
├── docs/
│ ├── specs/ ← Your feature specs (SPEC-FORMAT.md)
│ │ ├── authentication.md
│ │ └── email-service.md
│ └── contracts/ ← Generated contracts (CONTRACT-SCHEMA.md)
│ ├── feature_authentication.yml
│ └── journey_auth_register.yml
├── src/
│ └── __tests__/
│ └── contracts/ ← Contract verification tests
│ ├── auth_contract.test.ts
│ └── email_contract.test.ts
└── scripts/
└── check-contracts.js ← Quick contract checker
- Write spec in
docs/specs/<feature>.mdusingSPEC-FORMAT.md - Give LLM:
LLM-MASTER-PROMPT.md+ your spec - LLM generates contracts + tests + implementation
- Run
npm test -- contractsto verify
- Document what works today: "Auth uses sessions in Redis, 7-day expiry"
- Create contract: "Freeze this behavior—don't break it"
- Generate tests that verify current state
- Now you can refactor safely—tests catch regressions
- Add new section to existing spec:
AUTH-004 (MUST): 2FA required for admin - Update contract: Add rule for AUTH-004
- Update tests: Check for 2FA enforcement
- Implement feature
-
Create
docs/specs/authentication.md:## REQS ### AUTH-001 (MUST) All API endpoints must require authentication.
-
Run LLM with
LLM-MASTER-PROMPT.md:"Generate contracts for docs/specs/authentication.md" -
LLM creates:
docs/contracts/feature_authentication.ymlsrc/__tests__/contracts/auth_contract.test.ts
-
Run tests:
npm test -- auth_contract -
Implement: Add
authMiddlewareto routes -
Tests pass → merge
-
Identify what broke: "LLM used
localStoragein service worker" -
Document as contract:
# docs/contracts/feature_storage.yml rules: non_negotiable: - id: STORAGE-001 forbidden_patterns: - pattern: /localStorage/ message: "localStorage not available in service workers"
-
Create test that scans for
/localStorage/in service worker files -
Next time LLM tries this → test fails → build blocked
Humans read. LLMs attend.
A butterfly sees a flower—but not as petals, stems, or beauty. It sees UV patterns, contrast gradients, motion cues. Same photons. Radically different experience.
When you say "No shortcuts. Do it properly," you're hoping the LLM perceives salience the way you do. It doesn't. It optimizes what it was trained to attend to—and your carefully-worded instructions are just one voice in the crowd, competing with learned priors, token optimization, and style matching.
Three hours into a session, it starts to drift while simultaneously presenting itself as knowing exactly what you're working on. This appearance of continuity is entirely aesthetic—an optimization artifact. It's not real. And it causes cognitive dissonance because we mistake fluency for understanding.
Stop arguing with the butterfly. Paint UV markers on the flower.
- Prompting = hoping the right things feel salient
- Contracts = making salience executable
- Tests = deciding what the model must see
We don't need LLMs to behave. We need them to be checkable.
Prompting expresses intent. Contracts enforce behaviour. If you don't turn continuity into code, you'll mistake fluency for truth.
The compiler analogy:
Most LLM workflows look like this:
Human intent → Prompt → Hope → Review → Fix
Specflow inverts it:
Human intent → Contract → Generate → Test → Stop or Ship
You don't trust the middle. You verify the boundary.
Traditional tests: Check implementation details (units, functions) Contracts: Check architectural invariants (business rules, journeys)
Example:
-
❌ Test: "login function returns token" → Breaks if you refactor login internals
-
✅ Contract: "Users must be authenticated before accessing data" → Enforces requirement, survives refactors
Contracts test what must stay true, not how it's built.
The difference matters most with LLMs. A unit test checks code correctness. A contract catches the moment an LLM "optimizes" your auth flow into something that passes all tests but violates your security requirements.
LLMs aren't bad junior developers. They're untyped, side-effect-prone generators. So instead of instruction, we need compilation.
Generate freely. Fail loudly. Nothing ships unless it type-checks.
The core insight: Unit tests passing ≠ feature complete. Users don't care about your unit tests—they care about completing their goals.
| Traditional | Definition of Done |
|---|---|
| "Tests pass" = done | "User journeys pass" = done |
| Check functions work | Check flows work |
| Developer-centric | User-centric |
| Build breaks on unit failure | Build breaks on journey failure |
Critical (MUST PASS) → Blocks release if failing
Important (SHOULD PASS) → Should fix before release
Future (NOT BLOCKING) → Can release without
## DEFINITION OF DONE
### Critical (MUST PASS)
- J-AUTH-REGISTER → User can create account
- J-AUTH-LOGIN → User can sign in
### Important (SHOULD PASS)
- J-AUTH-LOGOUT → User can sign out
### Future (NOT BLOCKING)
- J-AUTH-2FA → Two-factor authenticationRelease gate logic:
- All Critical journeys
status: passing? ✅ Can release - Any Critical journey
status: failing? ❌ Cannot release - Any Critical journey
status: not_tested? ❌ Cannot release
Contracts and journeys run automatically in CI:
# .github/workflows/ci.yml
- name: Run Unit Tests
run: npm test
- name: Verify Feature Contracts
run: npm test -- contracts
- name: Verify Journey DOD (Critical)
run: npm test -- journeys --grep "critical"
- name: Check DOD Status
run: node scripts/check-dod-status.jsRelease gates:
- Feature contracts fail → PR blocked
- Critical journey fails → Release blocked
- DOD check shows
not_testedcritical journey → Release blocked
Core Docs:
SPEC-FORMAT.md- How to write specsCONTRACT-SCHEMA.md- YAML contract formatUSER-JOURNEY-CONTRACTS.md- Journey contracts and Definition of DoneLLM-MASTER-PROMPT.md- LLM workflow
Legacy Guides (for reference):
MASTER-ORCHESTRATOR.md- Complete automation workflow (comprehensive but heavy)SPEC-TO-CONTRACT.md- Detailed conversion examplesMETA-INSTRUCTION.md- Infrastructure setup guide
Templates:
contract-example.yml- Real contract exampletest-example.test.ts- Test template
You're doing it right when:
- ✅ Feature contract exists - YAML file with pattern rules
- ✅ Journey contract exists - YAML file with DOD criticality
- ✅ Pattern tests enforce feature contracts
- ✅ E2E tests enforce journey contracts
- ✅ Intentional violation fails - Tests catch it
- ✅ Critical journeys pass - DOD verified
- ✅ CI gates releases - No shipping with broken journeys
Made with ❤️ for vibe coders who want specs that actually matter