skills/verification/abstract-invariant-generator/SKILL.md
Generates abstract invariants using domain abstraction — intervals, octagons, polyhedra, sign domains — to find invariants that concrete reasoning misses. Use when standard invariant inference fails, when the invariant involves relationships between multiple variables, or when verifying numerical code.
npx skillsauth add santosomar/general-secure-coding-agent-skills abstract-invariant-generatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
When → invariant-inference (which works from concrete traces) can't find the invariant, abstract interpretation can. It over-approximates: instead of tracking exact values, track which region of a chosen domain the values are in.
| Domain | Can express | Example invariant | Cost |
| -------------- | -------------------------------------- | ------------------------------ | --------- |
| Sign | x > 0, x = 0, x < 0 | n > 0 | Trivial |
| Interval | lo ≤ x ≤ hi | 0 ≤ i ≤ n | Cheap |
| Octagon | ±x ± y ≤ c (two-var bounds) | i ≤ j, j - i ≤ n | Moderate |
| Polyhedra | Arbitrary linear inequalities | 2i + 3j ≤ n + 5 | Expensive |
| Congruence | x ≡ k (mod m) | i is even | Cheap |
Start cheap. Intervals catch 80% of array-bounds invariants. Octagons catch most two-pointer patterns. Polyhedra are for when you actually need a weird linear relationship.
i = 0 → in intervals: i ∈ [0, 0].i := i + 1 on [a, b] → [a+1, b+1].[0,0] ⊔ [1,1] = [0,1].[0,1] ⊔ [0,2] ⊔ [0,3] ⊔ ... → widen to [0, +∞). Then narrow: apply the loop guard i < n to get [0, n-1].Code:
int i = 0, j = n;
while (i < j) {
i++;
j--;
}
// invariant at loop head? need: 0 ≤ i, j ≤ n, and relationship between i and j
Interval abstraction:
| Iteration | i | j |
| --------- | --------- | ----------- |
| Init | [0, 0] | [n, n] |
| After 1 | [1, 1] | [n-1, n-1] |
| Join | [0, 1] | [n-1, n] |
| After 2 | [1, 2] | [n-2, n-1] |
| Join | [0, 2] | [n-2, n] |
| …widen | [0, +∞) | (-∞, n] |
| Narrow (guard i < j) | [0, n] | [0, n] |
Interval invariant: 0 ≤ i ≤ n ∧ 0 ≤ j ≤ n. True but weak — doesn't capture i + j = n.
Octagon domain (tracks ±x ± y ≤ c):
Initial: i + j = n (since i=0, j=n). Transition: i' = i+1, j' = j-1 → i' + j' = i + j = n. Preserved. Octagon finds i + j = n (as i+j ≤ n ∧ -(i+j) ≤ -n).
Lesson: Intervals are per-variable; they can't see i + j = n. For relational invariants, you need a relational domain.
i ≤ j) → octagons.[-∞, +∞]), the domain can't express the invariant — upgrade.[0, +∞) — useless. The guard narrows it back.i*i ≤ n — none of these domains can express it. You need a polynomial domain or template-based search.## Domain
<interval | octagon | polyhedra | congruence> — <why this domain>
## Fixpoint iteration
<table: iteration → abstract state>
## Invariant
<the stabilized abstract state, written as a logical formula>
## Strength check
Sufficient for the postcondition? <yes | no — need stronger domain: which>
development
Extracts human-readable pseudocode from a verified formal artifact (Dafny, Lean, TLA+) while preserving the verified properties as annotations, so the proof-carrying logic can be reimplemented in a production language. Use when porting verified code to an unverified target, when documenting what a formal spec actually does, or when handing a verified algorithm to an implementer.
development
Translates natural-language or pseudocode descriptions of concurrent and distributed systems into TLA+ specifications ready for the TLC model checker. Identifies state variables, actions, type invariants, safety properties, and liveness properties from the description. Use when formalizing a protocol, when the user describes a distributed algorithm to verify, when designing a consensus or locking scheme, or when starting formal verification of a concurrent system.
testing
Reduces a TLA+ model so TLC can actually check it — shrinks constants, adds state constraints, abstracts data, or applies symmetry — when the state space is too large to enumerate. Use when TLC runs out of memory, when checking takes hours, or when a spec works at N=2 and you need confidence at larger scale.
development
TLA+-specific instance of model-guided repair — reads a TLC error trace, identifies the enabling condition that should have been false, strengthens the corresponding action, and maps the fix to source code. Use when TLC reports an invariant violation or deadlock and you have the code-to-TLA+ mapping from extraction.