$npx -y skills add UnpaidAttention/fable5-methodology --skill verification-loopThe tight edit-verify cycle DURING implementation — after every meaningful change, run the fastest sufficient check before making the next change; never accumulate a batch of unverified edits. Trigger this continuously while writing or modifying code: after each function implemen
| 1 | # Verification Loop |
| 2 | |
| 3 | One verified change at a time. N unverified edits followed by one test run converts N |
| 4 | independent, trivially-locatable bugs into one entangled failure with N suspects. The loop |
| 5 | exists to keep the suspect list at length one. |
| 6 | |
| 7 | ## The cycle |
| 8 | |
| 9 | ``` |
| 10 | edit → fastest sufficient check → green? → next edit |
| 11 | → red? → fix NOW (suspect list has one entry) |
| 12 | ``` |
| 13 | |
| 14 | **Rule: never leave the tree red while moving on to something else.** A red state you walk |
| 15 | away from becomes someone's (usually your own) archaeology dig an hour later. |
| 16 | |
| 17 | ## Step 1: Choose the fastest SUFFICIENT check per change |
| 18 | |
| 19 | Match the check to what the change could have broken — no stronger, no weaker: |
| 20 | |
| 21 | | Change | Sufficient check | |
| 22 | |---|---| |
| 23 | | Syntax-level edit, rename, import change | Type-check / compile only: `tsc --noEmit`, `cargo check`, `ruff check` + import | |
| 24 | | Logic change inside one function | That module's unit tests: `pytest tests/test_x.py -k name`, `cargo test module::`, `vitest run file` | |
| 25 | | Interface change (signature, schema, contract) | Consumers' tests too — grep for callers, run their suites | |
| 26 | | Config / env / build-system change | A real build or boot: the thing configs actually affect | |
| 27 | | Bug fix | The regression test (must fail pre-fix, pass post-fix) + the module suite | |
| 28 | | Behavior visible to users | One end-to-end probe (curl the endpoint, run the CLI command) in addition to tests | |
| 29 | |
| 30 | Two costly mismatches to avoid: running the full 10-minute suite after a one-line rename |
| 31 | (wasteful — you'll start batching to avoid it), and running only a type-check after a logic |
| 32 | change (theater — types don't verify behavior). |
| 33 | |
| 34 | ## Step 2: Batching rules |
| 35 | |
| 36 | 1. **Logic changes: verify individually.** One behavioral edit per cycle. |
| 37 | 2. **Mechanical changes may batch within one file** (a rename's call sites, formatting, |
| 38 | import sorting) — then one check for the batch. |
| 39 | 3. **Cross-file mechanical sweeps** (rename across 12 files): batch the sweep, but compile/ |
| 40 | type-check immediately after, before any behavioral work resumes. |
| 41 | 4. If you notice three unverified edits stacked up, stop adding and verify now — you're |
| 42 | already one edit past the limit. |
| 43 | |
| 44 | ## Step 3: Keep the feedback fast |
| 45 | |
| 46 | 1. At task start, establish the fast commands for THIS repo (from CI config or the manifest's |
| 47 | scripts) and note them: the type-check command, the single-file test command, the full |
| 48 | suite command. |
| 49 | 2. If the tightest available check takes >~2 minutes, invest five minutes FIRST in finding a |
| 50 | faster subset (single-file runner, `-k` filters, watch mode, `cargo check` vs full build). |
| 51 | The investment pays back on every subsequent cycle — slow feedback is the root cause of |
| 52 | batching, and batching is the root cause of entangled debugging. |
| 53 | 3. Escalate breadth at boundaries: cheap check per edit → module suite per completed function |
| 54 | → full suite at each unit checkpoint (and always before delivery — that final gate belongs |
| 55 | to verification-and-review). |
| 56 | |
| 57 | ## Worked example |
| 58 | |
| 59 | Task: add pagination to a list endpoint (handler + query + serializer + 2 call sites). |
| 60 | |
| 61 | - Weak rhythm: edit all five places, run the suite once → 7 failures across 3 files, mixed |
| 62 | causes, 40 minutes of untangling. |
| 63 | - Loop rhythm: |
| 64 | 1. Edit query function → run its unit test → green. |
| 65 | 2. Edit serializer → its test → red: cursor field name typo → fixed in 30 seconds (one |
| 66 | suspect). |
| 67 | 3. Edit handler → module tests + `curl 'localhost:3000/orders?limit=2'` → green, response |
| 68 | shape confirmed. |
| 69 | 4. Update 2 call sites (mechanical, batched) → `tsc --noEmit` → green. |
| 70 | 5. Checkpoint: full suite → green. Commit (if authorized). |
| 71 | Same edits, zero entanglement; no failure ever had more than one suspect. |
| 72 | |
| 73 | ## Done when |
| 74 | |
| 75 | Ongoing — the loop has no terminal state during implementation. You are following it when: no |
| 76 | behavioral edit was ever stacked on an unverified behavioral edit, the tree was never left red |
| 77 | while you moved on, and at every unit boundary the full relevant suite ran green. Hand off to |
| 78 | verification-and-review for the final pre-delivery gate. |