Skip to content
Skillpedia
General coding48k · #3351

invariant-guard

Helps your agent think through all details before writing code. Ensures code is correct and handles edge cases.

What it does

This tool helps you write more reliable code. It makes you describe the rules (invariants), how the code will finish, and special cases before you write the actual code.

When to use it

  • ✓When writing algorithms that might have subtle bugs.
  • ✓When dealing with repetitions (loops) or recursive calls.
  • ✓When reviewing code to ensure it works in all situations.

Example of what to ask your AI

“Write a function to find the largest element in a list, but first define the loop invariant, termination argument, and edge cases.”

Want more? Open the sections below.

How to use

The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.

Skill link

https://github.com/sickn33/agentic-awesome-skills/blob/main/plugins/agentic-awesome-skills-claude/skills/invariant-guard/SKILL.md

Ready-to-paste message

Use this skill to help me: https://github.com/sickn33/agentic-awesome-skills/blob/main/plugins/agentic-awesome-skills-claude/skills/invariant-guard/SKILL.md Read the SKILL.md file at that link and follow its instructions for my task.
How it works

The tool forces you to formally state the conditions that must be true before, during, and after each step of your code (like loops or recursion). This helps prevent common bugs that often go unnoticed.

Installation

Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.

In the terminal (Claude Code, Codex, Cursor), in your project folder:

npx skills add sickn33/agentic-awesome-skills --skill invariant-guard

Or download just the file:

curl -L https://raw.githubusercontent.com/sickn33/agentic-awesome-skills/main/plugins/agentic-awesome-skills-claude/skills/invariant-guard/SKILL.md -o SKILL.md
Technical content (original SKILL.md)

Original text by the author, straight from GitHub.

invariant-guard — Correctness-First Coding

The model knows what a loop invariant is. It knows recursion needs a base case. It knows about empty lists, integer overflow, and the difference between < and ≤. It just does not write these down before producing code, so it ships subtle correctness bugs that tests do not catch.

invariant-guard fixes the behavior. State the invariants. State the base case. State the termination argument. State the edge cases. Then write the code — and verify that the code maintains what you stated.

Violating the letter of these rules is violating the spirit of the skill. "I know this algorithm" is the exact rationalization that ships off-by-one and missing-postcondition bugs.

When to Use This Skill

Use invariant-guard when writing or reviewing algorithms where the obvious implementation is subtly wrong:

  • Postcondition stronger than the loop's natural invariant: Boyer–Moore majority, Floyd's cycle detection, leftmost vs any binary search, QuickSelect partition.
  • In-place mutation with read+write pointers: dedup-in-place, partition, rotate.
  • Recursion with multiple parameters or accumulator state.
  • Off-by-one suspects with duplicates, empty inputs, boundary values.
  • Iterative refinements that must terminate: fixed-point, Newton, EM.
  • Any function where you catch yourself thinking "I know this algorithm" — the trap is usually in the contract, not the loop body.

Pairs with lemmaly (picks the algorithm) and mathguard (picks the math). Load invariant-guard after the algorithm has been chosen and before the loop body is written.

The Iron Law

NO LOOP OR RECURSION WITHOUT A WRITTEN INVARIANT AND TERMINATION ARGUMENT

If you cannot write the invariant in one sentence, you have not designed the loop. Write code anyway and you are coding by guess — and the bug will be in the case you did not enumerate.

Non-negotiable rules

  1. Every loop gets a one-line invariant. Before writing any loop, state in one sentence what is true at the top of every iteration. Examples:

    • "At loop top: result contains the sum of a[0..i)."
    • "At loop top: lo ≤ target_position ≤ hi."
    • "At loop top: seen contains every element processed so far; dups contains every element that appeared at least twice."

    If you cannot write the invariant in one sentence, you have not designed the loop yet.

  2. Every loop gets a one-line termination argument. Name the quantity that strictly decreases (or strictly increases toward a bound) on every iteration. Examples:

    • "hi − lo strictly decreases each iteration."
    • "i increases by 1 and is bounded above by n."
    • "stack.length strictly decreases each pop; nothing pushes inside this branch."

    No termination argument, no loop.

  3. Every recursion gets an explicit base case and a measure. Before writing a recursive function, state:

    • The base case(s) — the smallest inputs that return without recursing.
    • The measure — a non-negative integer that strictly decreases on every recursive call (e.g. len(xs), hi − lo, depth, n).
    • The combination — how the recursive results combine into the answer.

    No base case + measure, no recursion. (Mutual recursion: state the measure across the cycle.)

  4. List edge cases before writing, not after. For every function operating on a collection or number, list which of these apply and how they behave:

    • Empty input ([], "", null, undefined, None).
    • Singleton ([x]).
    • All-equal elements.
    • Already-sorted / reverse-sorted input.
    • Duplicates (when uniqueness is assumed).
    • Negative numbers, zero, exactly the boundary value.
    • Integer overflow / underflow at the type max/min.
    • NaN, ±Infinity, -0, denormals (for floats).
    • Off-by-one boundaries: index 0, index n−1, index n, length 0, length 1.
    • Concurrent modification while iterating.

    The cases that apply must each have a one-phrase expected behavior written down.

  5. Make illegal states unreachable, not just unhandled. Prefer encoding constraints in types and structure so the wrong state cannot be constructed:

    • Sum type over boolean flag soup (Loading | Loaded(data) | Error(msg) not {loading, data, error}).
    • Newtype for IDs that must not be swapped (UserId vs OrderId).
    • Non-empty list type when the function requires at least one element.

…

FAQ

What is a 'loop invariant'?

It's a statement that is always true at the beginning of each repetition of a loop. For example, 'the variable X always holds the sum of elements processed so far'.

What is a 'termination argument'?

It's the explanation of how a loop or a recursive function will end. It usually shows that a specific quantity is always decreasing or increasing towards a bound with each step.

Why list 'edge cases' first?

Because many bugs happen in unusual situations, like empty lists, single-item lists, or duplicate values. Thinking about these beforehand prevents errors.

Details

Original description by the author

Correctness-first: forces writing the function contract, loop invariant, termination argument, and edge cases BEFORE code. Catches Boyer-Moore, leftmost binary search, QuickSelect traps.

repo: sickn33/agentic-awesome-skills

Popularity

GitHub stars
48k
Ranking position
#3351
License
MIT
Updated
10/15/2026

Is this skill useful?

0

Sign in to vote.

Comments

  • …

More skills from this repository

Similar skills