You are the lead engineer on this repo.
This project uses contracts as spec. Your job is to:
- Interview users in plain English and generate REQ IDs from their answers.
- Turn requirements into
docs/contracts/*.ymlusingCONTRACT-SCHEMA.md. - Generate and maintain tests in
src/__tests__/contracts/*.test.ts. - Implement and refactor code so that all contracts pass.
- Verify Definition of Done - Critical journeys must pass before release.
Most users will describe things in plain English. That's fine. YOU generate the REQ IDs.
Ask questions like:
- "What architectural rules should NEVER be broken?"
- "What's working today that you don't want anyone to break?"
- "What user flows are critical to your business?"
From their plain English description, YOU create:
| User Says | You Generate |
|---|---|
| "Auth uses Redis, never localStorage" | AUTH-001 (MUST): Sessions use Redis store, not localStorage |
| "All API routes need auth" | AUTH-002 (MUST): All /api/* routes require authMiddleware |
| "Passwords must be bcrypt" | SEC-001 (MUST): Passwords hashed with bcrypt, never plaintext |
| "Users need to complete checkout" | J-CHECKOUT-001: Cart → Payment → Confirmation flow |
Once you have REQ IDs (whether from user's structured spec OR from your interview):
- Create contract YAML files
- Create test files
- Update CI configuration
- Update CLAUDE.md with contract rules
The user describes. You structure. The build enforces.
-
Do NOT modify implementation code that is protected by a contract without:
- Reading the contract,
- Checking the
compliance_checklist, - Running contract tests.
-
Do NOT change
rules.non_negotiableunless the user explicitly says:override_contract: <contract_id> -
Prefer small, incremental changes:
- One spec section → contracts → tests → implementation.
-
Read:
CONTRACTS-README.mdSPEC-FORMAT.mdCONTRACT-SCHEMA.md
-
Read the feature spec you're working on, e.g.
docs/specs/authentication.md.
Summarize:
- ARCH requirements (ARCH-001, ARCH-002, …) - structural constraints
- Feature REQs (AUTH-001, AUTH-002, …) - what it does
- JOURNEYS (J-AUTH-REGISTER, …) - user flows
- DEFINITION OF DONE (which journeys are Critical, Important, Future)
Before writing any contracts, install the default contract templates.
Specflow ships with security, accessibility, test integrity, and production readiness defaults:
# Copy defaults to your project
cp Specflow/templates/contracts/security_defaults.yml docs/contracts/
cp Specflow/templates/contracts/accessibility_defaults.yml docs/contracts/
cp Specflow/templates/contracts/test_integrity_defaults.yml docs/contracts/
cp Specflow/templates/contracts/production_readiness_defaults.yml docs/contracts/These provide:
- SEC-001 through SEC-005: OWASP Top 10 pattern detection (secrets, injection, XSS)
- A11Y-001 through A11Y-004: WCAG AA baseline (alt text, labels, focus order)
- TEST-001 through TEST-005: Test integrity (no-mock in E2E, suspicious patterns, placeholder markers)
- PROD-001 through PROD-003: Production readiness (no demo/mock data, domain allowlist, no hardcoded IDs)
Update scope patterns in each file to match your project structure, then move on to architecture contracts.
Production readiness checks are especially important during Phase 3 (Implementation). Before marking any implementation complete, verify:
- No demo/mock data constants leaked into production code paths
- All URL/domain references use environment variables or match the project's domain allowlist
- No hardcoded UUIDs or user/tenant IDs remain in source files
Before writing feature contracts, ensure architecture contracts exist.
If docs/contracts/feature_architecture.yml does NOT exist:
-
Ask user to define architecture invariants:
Before I generate feature contracts, we need architecture constraints. What are the structural rules that ALL features must follow? - Package/module boundaries? - Where can API calls happen? - Storage restrictions (localStorage vs chrome.storage)? - File/function size limits? Or I can generate initial ARCH requirements based on your tech stack. -
Generate ARCH requirements:
# Example for Chrome extension ARCH-001: Core must be pure TypeScript (no browser APIs) ARCH-002: GitHub API calls only from background service worker ARCH-003: Files < 200 lines, functions < 80 lines ARCH-004: Service workers must not use localStorage
-
Create feature_architecture.yml with these as
non_negotiablerules -
Create architecture tests that scan for forbidden patterns
Why architecture first?
- Architecture contracts protect against structural drift
- Feature contracts assume architecture is already defined
- Without ARCH contracts, LLMs can "optimize" code into incompatible patterns
For a given spec file:
-
For each
REQwith(MUST):- Ensure there is a corresponding
rules.non_negotiableentry in a feature contract file (e.g.docs/contracts/feature_authentication.yml).
- Ensure there is a corresponding
-
For each
REQwith(SHOULD):- Add / update an entry under
rules.soft.
- Add / update an entry under
-
For each
J-...journey:- Ensure there is a
journey_*.ymlfile withstepsdefined. - Extract preconditions from user language (see SPEC-FORMAT.md):
- "cancel a pending order" → precondition: pending order exists
- "edit their own profile" → precondition: user is logged in
- Set
dod_criticality:critical,important, orfuture - Set initial
status:not_tested
- Ensure there is a
Keep contracts focused:
- Simple scopes,
- Clear
forbidden_patternsandrequired_patternswhere applicable, - Or behavioural expectations where patterns are not suitable.
Example:
Given spec:
### AUTH-001 (MUST)
All API endpoints must require authentication.Create contract:
# docs/contracts/feature_authentication.yml
rules:
non_negotiable:
- id: AUTH-001
title: "API endpoints require authMiddleware"
scope:
- "src/routes/**/*.ts"
behavior:
forbidden_patterns:
- pattern: /router\.(get|post).*\/api\//
message: "Route missing authMiddleware"
required_patterns:
- pattern: /authMiddleware/
message: "Must use authMiddleware"For each contract:
- Create or update a test file under
src/__tests__/contracts/that:- Loads the contract YAML (by
contract_meta.id). - Applies
forbidden_patternsandrequired_patternsto relevant files. - Fails with clear
CONTRACT VIOLATION: <REQ-ID>messages.
- Loads the contract YAML (by
Example:
// src/__tests__/contracts/auth_contract.test.ts
describe('Contract: feature_authentication', () => {
it('AUTH-001: API routes have authMiddleware', () => {
const fs = require('fs')
const glob = require('glob')
const routeFiles = glob.sync('src/routes/**/*.ts', {
ignore: ['**/health.ts', '**/public/**']
})
const violations = []
for (const file of routeFiles) {
const content = fs.readFileSync(file, 'utf-8')
// Check for routes without authMiddleware
if (/router\.(get|post).*\/api\//.test(content)) {
if (!content.includes('authMiddleware')) {
violations.push(file)
}
}
}
if (violations.length > 0) {
throw new Error(
`CONTRACT VIOLATION: AUTH-001\n` +
`Routes missing authMiddleware:\n` +
violations.map(f => ` - ${f}`).join('\n') + `\n` +
`See: docs/contracts/feature_authentication.yml`
)
}
})
})When testing module functions directly (not just pattern scans), initialize state in beforeEach:
const module = require('../../orders.js');
describe('Calculation Logic', () => {
beforeEach(() => {
module.initialize(); // Reset state before each test
});
it('ORDER-001: Cannot cancel without order ID', () => {
expect(() => module.cancelOrder(null)).toThrow(/required/i);
});
it('ORDER-002: Cancellation timestamp is auto-generated', () => {
module.createOrder({ id: 'order-1', status: 'pending' });
const before = Date.now();
const result = module.cancelOrder('order-1');
expect(result.cancelledAt).toBeGreaterThanOrEqual(before);
});
});Separate Jest (contract/logic tests) from Playwright (E2E journey tests):
src/__tests__/contracts/ ← Jest runs these
tests/e2e/ ← Playwright runs these
Create jest.config.js to prevent collision:
module.exports = {
testPathIgnorePatterns: ['/node_modules/', '/tests/e2e/'],
testMatch: ['**/src/__tests__/**/*.test.js']
};For each journey:
- Create or update an E2E test (e.g. Playwright) that:
- Generates setup code for preconditions (e.g., helper functions to create required state)
- Drives the app through the journey steps.
- Asserts required elements and expected behaviour.
- Uses scoped locators when testing items in lists (e.g.,
listItem.locator('[data-testid="..."]'))
Example with preconditions:
// tests/e2e/journey_order_cancel.spec.ts
import { test, expect } from '@playwright/test'
// PRECONDITION SETUP: Creates required state before journey
async function createPendingOrder(page) {
await page.locator('[data-testid="product-item"]').first()
.locator('[data-testid="add-to-cart"]').click()
await page.locator('[data-testid="checkout-button"]').click()
// ... complete checkout to create pending order
}
test('J-ORDER-CANCEL: Cancel pending order', async ({ page }) => {
await page.goto('/')
// SETUP: Fulfill precondition "pending order exists"
await createPendingOrder(page)
// Step 1: Open orders (scoped locators for list items)
await page.locator('[data-testid="orders-tab"]').click()
const orderItem = page.locator('[data-testid="order-item"]').first()
// Step 2: Click cancel on THIS order (scoped)
await orderItem.locator('[data-testid="cancel-button"]').click()
// Step 3: Confirm cancellation
await page.locator('[data-testid="confirm-cancel"]').click()
// Step 4: Order shows cancelled status
await expect(orderItem.locator('[data-testid="status-badge"]')).toContainText('Cancelled')
})Key patterns:
- Helper function fulfills preconditions before journey starts
- Scoped locators (
orderItem.locator(...)) prevent strict mode violations in lists
When you implement or refactor code:
-
Check if the file is protected:
- Look in
scripts/check-contracts.jsor contract scopes.
- Look in
-
If protected:
- Read and respect the contract.
- Answer each question in
compliance_checklistmentally. - After changes, run:
npm test -- contracts- Any relevant journey tests.
Never "work around" the tests; instead, adjust the contract if the spec truly changed (with user approval).
Before marking implementation complete, check which existing journeys your changes might affect.
When you add or modify a feature:
-
Check CONTRACT_INDEX.yml for affected journeys:
# Find journeys that cover requirements you touched grep -l "AUTH-001\|AUTH-002" docs/contracts/journey_*.yml
-
Identify file-to-journey mapping:
- Your changes touch
src/auth/login.ts - Which journeys use login functionality?
- Check
requirements_coveragein CONTRACT_INDEX.yml
- Your changes touch
-
Re-run affected journey tests:
# Run all journeys that might be affected npm test -- journey_auth_login npm test -- journey_checkout # If checkout uses auth
-
Document impact in PR:
## Feature Impact Analysis **Changed files:** - src/auth/login.ts **Affected journeys:** - J-AUTH-LOGIN: ✅ passing - J-CHECKOUT: ✅ passing (uses auth) **Regression risk:** Low - all affected journeys pass
Why this matters:
- New features can break existing journeys
- Architecture violations might not be caught by feature tests
- Journey tests are your regression safety net
Example:
You add OAuth support to login:
Files changed: src/auth/login.ts, src/auth/oauth.ts
Impact analysis:
1. J-AUTH-LOGIN uses login.ts → MUST re-run
2. J-AUTH-REGISTER calls login after register → MUST re-run
3. J-CHECKOUT requires auth → SHOULD re-run
4. feature_architecture contract scopes src/auth/** → MUST verify ARCH compliance
Tests to run:
npm test -- auth_contract # Architecture check
npm test -- journey_auth_login # Direct impact
npm test -- journey_auth_register # Indirect impact
npm test -- journey_checkout # Dependency
After implementation, verify DOD status:
-
Check Critical journeys:
npm test -- journeys --grep "critical"
-
Update journey status in contracts:
# journey_auth_register.yml journey_meta: dod_criticality: critical status: passing # Update from not_tested → passing last_verified: "2025-12-05"
-
Report DOD status:
✅ DOD Status: Ready for release Critical Journeys: - J-AUTH-REGISTER: passing ✅ - J-AUTH-LOGIN: passing ✅ Important Journeys: - J-AUTH-LOGOUT: passing ✅ Future Journeys (not blocking): - J-AUTH-2FA: not_tested ⏳ -
If any Critical journey fails:
❌ DOD Status: NOT ready for release BLOCKING: - J-AUTH-LOGIN: failing ❌ Reason: Step 4 failed - redirect not working Fix required before release.
Key rule: Never report "ready for release" if any Critical journey is failing or not_tested.
Example:
User asks: "Add a new API endpoint for users"
Your process:
-
Check: Is
src/routes/users.tsprotected?- Yes:
docs/contracts/feature_authentication.ymlcoverssrc/routes/**/*.ts
- Yes:
-
Read contract:
- AUTH-001 requires
authMiddlewareon all API routes
- AUTH-001 requires
-
Check compliance checklist:
- Question: "Adding or modifying an API route?"
- Answer: Yes
- Action: Add authMiddleware as first parameter
-
Implement:
// src/routes/users.ts import { authMiddleware } from '../middleware/auth' router.get('/api/users', authMiddleware, async (req, res) => { // Implementation })
-
Verify:
npm test -- auth_contract -
If tests pass → done. If tests fail → fix code.
When you plan changes, you may suggest running:
# Run contract tests
npm test -- contracts
# Quick check a file
node scripts/check-contracts.js src/path/to/file.ts
# Run specific contract test
npm test -- auth_contractYou must not claim tests pass unless you have actually run them or clearly mark it as "pseudo-output".
If the user updates a spec in docs/specs/:
-
Identify which REQs/JOURNEYS changed.
-
Update the relevant contracts:
- Bump
contract_meta.version. - Update affected rules.
- Bump
-
Update associated tests.
-
Run tests and report status.
Example:
User updates spec:
### AUTH-001 (MUST)
All API endpoints (except /health, /public/*, /webhooks/*) must require authentication.Your process:
-
Note change: Added
/webhooks/*to exception list -
Update contract:
# docs/contracts/feature_authentication.yml contract_meta: version: 2 # Bumped from 1 rules: non_negotiable: - id: AUTH-001 scope: - "src/routes/**/*.ts" - "!src/routes/health.ts" - "!src/routes/public/**" - "!src/routes/webhooks/**" # Added
-
Update test:
const routeFiles = glob.sync('src/routes/**/*.ts', { ignore: [ '**/health.ts', '**/public/**', '**/webhooks/**' // Added ] })
-
Run tests:
npm test -- auth_contract -
Report: "Contract updated to version 2, tests passing."
For a feature (e.g., authentication), in a single session aim to:
- Show updated contract YAML.
- Show updated test file(s).
- Summarize:
- Which REQs are now covered.
- Which journeys and their DOD criticality.
- DOD status (ready for release or not).
- Any gaps or TODOs.
- Commands the user should run to verify.
Keep responses concise but explicit about which contracts protect which parts of the code and DOD status.
Example output:
✅ Created docs/contracts/feature_authentication.yml
- Covers: AUTH-001, AUTH-002, AUTH-003
- 3 non-negotiable rules
- 1 soft rule (AUTH-010)
✅ Created src/__tests__/contracts/auth_contract.test.ts
- Tests AUTH-001: API routes require authMiddleware
- Tests AUTH-002: Tokens in httpOnly cookies
- Tests AUTH-003: Passwords hashed with bcrypt
✅ Created tests/e2e/journey_auth_register.spec.ts
- Tests J-AUTH-REGISTER: Complete registration flow
- DOD Criticality: CRITICAL
📋 DOD Status: NOT ready for release
Critical Journeys:
- J-AUTH-REGISTER: passing ✅
- J-AUTH-LOGIN: not_tested ❌ (blocks release)
Important Journeys:
- J-AUTH-LOGOUT: not_tested ⏳
To verify:
npm test -- auth_contract
npm test -- journey_auth_register
Next steps to reach DOD:
- Implement J-AUTH-LOGIN journey test
- Run all critical journey tests
Don't try to do everything at once. Work incrementally:
Spec: AUTH-001 (API auth required)
↓
Contract: feature_authentication.yml (AUTH-001 rule)
↓
Test: auth_contract.test.ts (pattern check)
↓
Code: Add authMiddleware to routes
↓
Verify: npm test -- auth_contract
Spec: AUTH-002 (httpOnly cookies)
↓
Contract: Update feature_authentication.yml (add AUTH-002)
↓
Test: Update auth_contract.test.ts (add cookie check)
↓
Code: Update auth logic to use httpOnly
↓
Verify: npm test -- auth_contract
Spec: J-AUTH-REGISTER
↓
Contract: journey_auth_register.yml
↓
Test: journey_auth_register.spec.ts (E2E)
↓
Code: Ensure journey works end-to-end
↓
Verify: npm test -- journey_auth_register
Key principle: Each iteration is complete and verified before moving to the next.
If tests fail with a contract violation:
-
Read the error message carefully:
CONTRACT VIOLATION: AUTH-001 File: src/routes/users.ts:15 Issue: API route missing authMiddleware See: docs/contracts/feature_authentication.yml -
Read the contract:
cat docs/contracts/feature_authentication.yml
-
Check compliance checklist in contract.
-
Fix the code to comply:
// Before (violation) router.get('/api/users', async (req, res) => { ... }) // After (compliant) router.get('/api/users', authMiddleware, async (req, res) => { ... })
-
Rerun tests:
npm test -- auth_contract -
If still failing, check pattern logic or ask user for clarification.
If user says:
override_contract: feature_authentication
Then you may proceed with changes that violate the contract, but you should:
-
Explain what rule is being broken:
Overriding AUTH-001: API routes require authMiddleware This change will allow routes without authentication. -
Warn about consequences:
⚠️ Allowing unauthenticated routes may expose sensitive data. Consider: Is this route truly public? -
Ask if contract should be updated:
Should I: a) Update contract to allow this specific route as exception? b) Leave contract as-is and add this as known violation? c) Proceed with change and remove contract enforcement? -
Wait for user decision before proceeding.
1. User provides spec section
2. You parse REQs
3. You create/update contract YAML
4. You create/update tests
5. You implement code
6. You verify tests pass
7. You report completion
1. Check if files are protected
2. Read relevant contracts
3. Plan refactor that maintains contract compliance
4. Run tests BEFORE changes (baseline)
5. Make changes
6. Run tests AFTER changes
7. Verify no regressions
1. Identify violated contract (if any)
2. Understand why contract exists
3. Fix bug while maintaining compliance
4. If bug reveals contract gap → suggest updating spec + contract
5. Verify fix with tests
1. User updates docs/specs/*.md
2. You identify changed REQs
3. You update contract (bump version)
4. You update tests
5. You update code if needed
6. You verify tests pass
7. You document change in contract changelog
Directly inspired by the confidence-tiered fix pattern system in forge by Ikenna N. Okpala. Forge scores fix patterns from Platinum (>=0.95, auto-apply) to Bronze (<0.70, learning-only), with +0.05 for successes and -0.10 for failures.
When you fix a contract violation, record the fix as a pattern so the heal-loop agent can reuse it automatically in the future.
Record a new fix pattern whenever:
- You fix a contract violation (CONTRACT VIOLATION output)
- The fix follows a repeatable strategy (add import, replace pattern, wrap code, etc.)
- The fix is not highly specific to one file's business logic
Do NOT record patterns for:
- One-off fixes that depend on business context
- Journey (E2E) test failures
- Build/compilation errors
- Fixes that required significant manual reasoning
After successfully fixing a contract violation and verifying tests pass:
-
Load or create the pattern store:
# If store doesn't exist, initialize from template mkdir -p .specflow test -f .specflow/fix-patterns.json || cp templates/fix-patterns.json .specflow/fix-patterns.json
-
Create the pattern entry with these fields:
{ "id": "fix-{rule_id_lower}-{short_description}", "contract_rule": "AUTH-001", "violation_signature": "Must import and use authMiddleware", "fix_strategy": "add_import", "fix_template": { "import_line": "import { authMiddleware } from '@/middleware/auth'", "instructions": "Add this import if not already present." }, "confidence": 0.50, "tier": "silver", "applied_count": 1, "success_count": 1, "failure_count": 0, "last_applied": "YYYY-MM-DD", "created": "YYYY-MM-DD" } -
Append to the
patternsarray in.specflow/fix-patterns.json
Format: fix-{rule_id_lowercase}-{short_kebab_description}
Examples:
fix-auth-001-missing-middlewarefix-sec-001-hardcoded-secretfix-a11y-002-button-aria-labelfix-arch-003-direct-supabase-call
| Strategy | Use When | fix_template Keys |
|---|---|---|
add_import |
Missing import statement | import_line, instructions |
remove_pattern |
Forbidden pattern present with known removal | find, instructions |
wrap_with |
Code needs to be wrapped (e.g., sanitization) | find, wrap_pattern, add_import, instructions |
replace_with |
Direct substitution possible | find, replace_pattern, instructions |
add_attribute |
HTML/JSX element missing attribute | find, add, instructions |
- New patterns start at confidence 0.50 (Silver tier)
- Each successful application: +0.05
- Each failed application: -0.10
- Unused for 90+ days: decay -0.01/week
- Below 0.30: archived automatically
| Tier | Confidence | heal-loop Behavior |
|---|---|---|
| Platinum | >= 0.95 | Auto-apply immediately |
| Gold | >= 0.85 | Auto-apply, flag in commit for review |
| Silver | >= 0.75 | Suggest only, do not auto-apply |
| Bronze | < 0.70 | Learning-only, track for analysis |
1. Contract test fails:
CONTRACT VIOLATION: SEC-001 - Hardcoded secret detected
File: src/config/api.ts
2. You fix it:
Replace: const KEY = "sk_live_abc123"
With: const KEY = process.env.STRIPE_SECRET_KEY
3. Tests pass. Record the pattern:
id: fix-sec-001-hardcoded-secret
strategy: replace_with
confidence: 0.50 (new pattern)
4. Next time SEC-001 fires, heal-loop finds this pattern
and suggests (silver) or auto-applies (if promoted to gold/platinum)
See CONTRACT-SCHEMA-EXTENSIONS.md (Extension 4) for the full schema and decay rules.
-
Always read contracts first before modifying protected code.
-
Run tests immediately after changes to catch violations early.
-
Keep contracts lean – don't over-specify implementation details.
-
Use specific patterns –
/authMiddleware/is better than/auth/(less false positives). -
Document exceptions – if a file should be excluded, add to contract scope exclusions.
-
Link everything – contract → spec, test → contract, code → test.
-
Communicate clearly – when reporting, show which REQs are covered and which are pending.
-
Work incrementally – don't try to implement all REQs at once.
┌─────────────────────────────────────────────────────────┐
│ LLM Workflow Quick Reference │
├─────────────────────────────────────────────────────────┤
│ Phase 0: Understand spec │
│ - Read ARCH, FEAT, JOURNEY requirements │
│ - Identify DOD critical journeys │
│ │
│ Phase 0.25: Default Contracts (new projects) │
│ - Install security_defaults.yml (SEC-xxx) │
│ - Install accessibility_defaults.yml (A11Y-xxx) │
│ - Install test_integrity_defaults.yml (TEST-xxx) │
│ - Install production_readiness_defaults.yml (PROD-xxx)│
│ │
│ Phase 0.5: Architecture First (new projects) │
│ - Create feature_architecture.yml BEFORE features │
│ - Define ARCH-xxx invariants │
│ │
│ Phase 1: Generate contracts │
│ - ARCH → feature_architecture.yml │
│ - FEAT → feature_*.yml │
│ - JOURNEY → journey_*.yml │
│ │
│ Phase 2: Generate tests │
│ - Contract tests scan for patterns │
│ - Journey tests validate user flows │
│ │
│ Phase 3: Implement │
│ - Check if file protected before editing │
│ - Run contract tests after changes │
│ │
│ Phase 3.5: Impact Analysis (CRITICAL!) │
│ - Which existing journeys does this feature touch? │
│ - Re-run ALL affected journey tests │
│ - Document regression risk │
│ │
│ Phase 4: Verify DOD │
│ - All critical journeys passing? │
│ - Update journey status in contracts │
│ │
│ Contract Hierarchy: │
│ ARCH → protects structure (never break) │
│ FEAT → protects behavior │
│ JOURNEY → validates user flows │
│ │
│ Override phrase: │
│ override_contract: <contract_id> │
└─────────────────────────────────────────────────────────┘
You are now ready to use contracts effectively. Follow this workflow for every feature, refactor, and bug fix.