santosomar/general-secure-coding-agent-skills/invariant-inference
- community
Checking that the SKILL.md file is still in the repository.
Infers likely loop invariants and function contracts by observing execution traces, synthesizing candidates, and checking them inductively. Use when a verifier rejects a loop because the invariant is missing or too weak, when a Daikon-style tool is needed, or before translating code to a verification language.
Install
npx vskill@latest install santosomar/general-secure-coding-agent-skills/invariant-inferenceSKILL.md
Invariant Inference
A loop invariant is what stays true every time you hit the loop head. Verifiers need it stated; programmers rarely state it. This skill guesses it from evidence.
Two routes to an invariant
| Route | How it works | Good at | Bad at | |
|---|---|---|---|---|
| Dynamic (Daikon-style) | Run the code, record state at loop head, generalize patterns | Concrete relationships in traces | Generalization — might be coincidence | |
| Static (template-based) | Guess invariants of form ax + by ≤ c, solve for a,b,c | Sound by construction | Limited to the template shapes |
Do both: dynamic finds candidates fast; static checks them.
Dynamic — the observe-and-generalize loop
- Instrument. At every loop head, dump all local variable values.
- Run on a bunch of inputs. The more diverse, the better.
- Mine patterns across the dumps. What's true at every observation?
- Filter for inductiveness. A pattern true by coincidence won't survive the inductive check.
Template library (what to look for in the dumps):
| Template | Example | |
|---|---|---|
| Constant | n == 10 in every observation | |
| Range | 0 <= i <= n | |
| Linear relation | i + j == n, 2*i == k | |
| Ordering | i < j, a[i] <= a[j] | |
| Membership | x in {0, 1, 2} | |
| Collection property | sorted(a[:i]), sum(a[:i]) == s | |
| Implication | flag => (x > 0) |
Step-by-step
- Collect traces. Run with varied inputs; dump
(iter, locals)at loop head. - Enumerate candidates. For each template, instantiate with the observed variables. Keep any that hold on all traces.
- Prune coincidences. If
x == 5in every trace but your test inputs all hadn == 5— it's not invariant, it's your test bias. Varyn. - Check inductiveness. For each survivor
I: doesI ∧ guard ∧ body ⟹ I'? Use an SMT solver or just plug into the verifier. - Check sufficiency. Does
I ∧ ¬guard ⟹ postcondition? If not,Iis true but useless — you need a stronger one.
Worked example
Loop:
Traces (input a = [3, 1, 4, 1, 5]):
| iter | i | m | a[:i] | |
|---|---|---|---|---|
| 0 | 1 | 3 | [3] | |
| 1 | 2 | 3 | [3, 1] | |
| 2 | 3 | 4 | [3, 1, 4] | |
| 3 | 4 | 4 | [3, 1, 4, 1] | |
| 4 | 5 | 5 | [3,1,4,1,5] |
Candidate patterns (mined):
1 <= i <= len(a)✓ all rowsm in a✓ all rowsm == max(a[:i])✓ all rows — this is the onem >= a[0]✓ all rows — true but weaker than the above
Inductive check on `m == max(a[:i])`:
- Init:
i=1, m=a[0]→max(a[:1]) = a[0] = m. ✓ - Preserved: Assume
m == max(a[:i]). Body setsm' = max(m, a[i])andi' = i+1. Thenm' = max(max(a[:i]), a[i]) = max(a[:i+1]) = max(a[:i']). ✓ - Sufficient: Exit when
i == len(a). Thenm == max(a[:len(a)]) == max(a). ✓
Invariant: 1 <= i <= len(a) ∧ m == max(a[:i]).
When dynamic fails
- Not enough trace diversity: All your inputs hit the same branch → you miss the invariant for the other branch. Fix: coverage-guided input generation.
- The invariant isn't in your template library:
a[i] * a[j] < n— nonlinear. →abstract-invariant-generatorwith a polynomial domain, or hand-write. - Ghost state needed: The invariant mentions a quantity the code doesn't compute (e.g., "the number of swaps so far"). Add a ghost variable.
Do not
- Do not trust a candidate that passes on traces but fails the inductive check. Traces are a finite sample. The inductive check is the proof.
- Do not stop at the first invariant that's inductive. Check it's sufficient for the postcondition.
trueis inductive; it proves nothing. - Do not over-fit.
i in {1, 2, 3, 4, 5}holds on your one trace — but the real invariant is1 <= i <= len(a). Prefer the most general candidate that survives.
Output format
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/verification/invariant-inference/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/santosomar/general-secure-coding-agent-skills/invariant-inference)