Contract Extraction
Turn capsule invariants into executable contracts: domain types that prevent invalid states, validation at boundaries, and tests that prove enforcement. Operationalizes "design by contract" (Meyer) and "parse, don't validate."
Input
Invariants to enforce (or audit to check current coverage): $ARGUMENTS
Preconditions:
- •A concept capsule must exist (it defines the invariants). If none →
/pragma:capsulefirst. - •At least one slice of working code to attach contracts to. If at skeleton stage →
/pragma:card+/pragma:slicefirst.
Also read: the capsule (glossary + invariants), recent cards (boundary crossings), and existing source code.
Procedure
1. Build the contract map
For each capsule invariant, determine current enforcement status:
| Invariant | Enforcement | Location | Evidence |
|---|---|---|---|
| [from capsule] | Type system / Constructor / Test / None | [file:line or "missing"] | [test name or "none"] |
Enforcement levels (best → worst): Type system (invalid states unrepresentable) → Constructor/validator (checked at entry points) → Test (at least a check somewhere) → None (fix this).
2. Identify boundary contracts
For each public entry point in scope:
Module: [name]
Function: [name]
Preconditions: [what must be true on entry]
Postconditions: [what must be true on exit]
Errors: [what can go wrong and how it's signaled]
Use glossary terms. No clear pre/postconditions → design smell, module may need splitting.
3. Enforce incrementally
One invariant at a time. Prioritize "None" first, then upgrade "Test" → "Constructor" → "Type system":
- •Types first: narrower types to make invalid states impossible (branded IDs, discriminated unions, non-empty collections)
- •Then constructors/validators: validation where data enters the domain (factory functions, constructor guards)
- •Then tests: contract tests asserting invariants hold (table tests, property tests, regression tests)
Keep tests green throughout. Do not change behavior — only tighten enforcement.
4. Update the contract map
Write or update docs/contracts.md with:
- •The invariant-to-enforcement table (updated)
- •Boundary contracts for each module
- •A contract budget: what's enforced now vs. what remains "English-only" and why
5. Verify and commit
Run full verification harness. All checks must pass. Contract extraction must not change behavior.
Commit: Contract: enforce [invariant] at [boundary]
Constraints
- •No behavior changes. Contracts tighten enforcement only. Missing behavior →
/pragma:card. - •Incremental. One invariant or boundary per pass. Do not "contract the whole system" at once.
- •Types over runtime checks. Compile-time enforcement preferred. Runtime is fallback.
- •The capsule is the authority. Capsule wrong → update it first.
- •No heavy frameworks. Native type system + standard assertion patterns only.
Output
- •Contracts enforced: which invariants, at what level
- •Contract budget: what remains unenforced and why
- •Boundary contracts: pre/postconditions added or clarified
- •Code changes: types, validators, tests added
- •Recommended next step: more
/pragma:contractpasses, or back to/pragma:card+/pragma:slice - •Lifecycle:
State: governance,Next: /pragma:consult(or the explicitly recommended next step),Loop: /pragma:consult(default unless user explicitly continues directly)