How To Write Fail-Close Acceptance Invariants
You want your packet's acceptance_invariants to actually fail closed instead of being soft "shoulds." The methodology refuses soft invariants; this recipe shows how to write hard ones.
Recipe
- State the invariant as a verifiable predicate. Not "this should be readable"; "every retained docs/**/*.md path is reachable from sidebar (or nav) in at least one locale."
- Name the verification mechanism. Grep, dev server inspection, build pass, etc.
- Make the failure mode explicit. What does failing this invariant look like? Be concrete.
- Pair with a
negative_testsentry. Negative tests catch violations grep-style; invariants are positive predicates. - Cross-check with
forbidden_shortcuts. If the invariant's negation is one of the catalog patterns, declare both.
Soft Vs Hard
| Soft (refuse) | Hard (admit) |
|---|---|
| "Pages should be readable" | "Each retained sub-page contains at least one concrete reader scenario" |
| "Avoid forbidden claims" | "Forbidden-marker grep returns zero hits across README.md and docs/**" |
| "Build should work" | "pnpm docs:build PASS" |
| "No spec drift" | ".nimi/spec/** remains unchanged (verified by git status -- .nimi/spec)" |
The soft form cannot be mechanically checked. The hard form can.
Reader Scenario: Converting Soft To Hard
A first-draft packet has:
acceptance_invariants:
- Documentation should be readable
- Sidebar should expose all sub-pages
- Build should pass
- No spec driftThese are all soft. Convert:
acceptance_invariants:
- Each retained docs/**/*.md path is reachable from sidebar
(or nav) in at least one locale
- Each retained sub-page carries at least one concrete
scenario or worked example tied to a kernel rule family
- Sidebar /<section>/ group exposes all sub-pages plus
explicit Related cross-links
- pnpm docs:build PASS
- .nimi/spec/** remains unchanged (verified by git status)Each is now a verifiable predicate.
Reader Scenario: Pairing With Negative Tests
The invariant "no concrete provider name introduced" pairs with:
negative_tests:
- grep -rEni '\b(OpenAI|Anthropic|Claude|Gemini|GPT-[0-9]|...)\b'
returns zero hits across README.md and docs/**
(excluding the meta-doc forbidden-claims.md)The negative test is a concrete grep; the invariant is the positive shape.
Reader Scenario: Cross-Check With Forbidden Shortcuts
The invariant "no parallel truth introduced" pairs with declared:
forbidden_shortcuts:
- dual_read
- dual_write
- app_local_shadow_truth
- silent_owner_cut_reopenThe catalog keys are what the audit checks against; the invariant is what the work positively achieves.
What To Watch For
| Symptom | Meaning |
|---|---|
| Invariant phrased as "should" | Soft; refuse, rewrite as predicate |
| No verification mechanism named | Cannot fail-close |
| Failure mode unclear | Reviewer cannot verify |
| Missing negative test pair | Catch only positive case; missing the symmetric |