All skills
oaustegard avatar

/declaring-invariants

@abb25f0

Find tests that enumerate a domain by copying it, and declare the invariants a codebase depends on. Reports where a parametrize list, for-loop, or it.each iterates a hand-written subset of a dict/set/tuple/Enum that exists in the source, and names the members nothing covers. Use when reviewing tests, when a module gains a name-to-thing table, registry, enum, or dispatch map, before trusting a green suite as evidence a domain is covered, or when asked "is this test actually total", "does anything cover X", "what does this repo guarantee", "which invariants do we declare". Also for vacuous tests that pass over an empty collection, for a domain that has silently NARROWED (an enumeration cannot see that), and for recording the refutation that proves a claim can fail.

  • 7 files
  • 105.9 KB
  • Updated last month
  • GitHub

Use this Skill: https://skilld.dev/gh/oaustegard/claude-skills/declaring-invariants

This session only. Nothing lands on disk.

README.md

≈717 tokens on demand. Your agent reads this file only when SKILL.md points to it.

declaring-invariants

Find tests that enumerate a domain by copying it, and declare the invariants a codebase depends on. Stdlib ast only — no install, no config file, no network. Python.

python3 scripts/totality_lint.py <repo>   # tests that copy a domain
python3 scripts/claims.py <repo>          # what the repo declares, and what backs it

Features

  • Copied-domain detection — a parametrize or for over a literal whose members are a strict subset of a dict/set/tuple/Enum in the source, with the uncovered members named
  • Ratchets, the second claim form — an enumeration loops whatever the domain now holds, so it cannot see the domain narrowing. # totality: ratchet — <why> marks a hand-list as a deliberate floor, and the linter checks the pin: ratchet-broken names a member that left, statically, before any test runs. unratcheted names a registry with an enumeration and no floor
  • Vacuity detection — a live registry iterated with no len(...) >= n assertion, which passes over an emptied collection
  • Membership join — [1, 2, 3, 4, 8] and SUPPORTED_BITS share no token, so containment is the join key; no naming convention is assumed
  • Reachability filter — a literal matches a registry only when the test imports its module, shares its top-level directory, or is its paired tests/test_<mod>.py
  • First-class acknowledgement — # totality: partial — <why> retires a finding, and an acknowledgement on a test that later covers the whole domain is reported as stale-ack
  • Claim inventory — a claim is a test whose docstring opens invariant:, and refuted: records the observed negative control
  • Report by default — --strict opts into a nonzero exit; --json for machine consumption; --selftest runs fixtures with no repo

Why

On oaustegard/remex, adding a fourth member to ROTATION_CODES with no construction behind it left the entire 267-test suite green. Four tests looked total; each parametrized ["haar", "rht"] against a three-member registry.

The other direction is worse. Substituting "xyz" for "none" in both spellings of that domain — cardinality unchanged, both spellings agreeing — left the domain floor, the enumeration and the parity check green, five passing tests over a registry that had stopped supporting a rotation every index on disk was written with. That is what the ratchet form is for.

Adapted from the meta-oracle in daniloc/coherence, which classifies an oracle's iteration root as LIVE or LITERAL by parsing the oracle's own AST. The check needs none of that harness's spec files, claim grammar, ledger or Node runtime.

See SKILL.md for the full reference, including how to write a refutation you have actually observed.

Source: SKILL.md on GitHub

No third-party reports yet.

Signed by skilld at abb25f0. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated last month
metadata
{
  "version": "0.2.3"
}

README badge

README badge for oaustegard/claude-skills/declaring-invariants