Check
Use when proving a repo's tests actually catch their code with Gutcheck's mutation probe (`prove`) and deterministic checker, acting on a hollow oracle, an uncited expected value, or a derivation/assertion mismatch it flags, and before any "it passes" claim.From its SKILL.md
npx -y skills add beepometer/gutcheck --skill checkAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
9.3 KB, as published. Nobody here has run it
Gutcheck—prove the tests, then repair what's hollow
Gutcheck ships inside this plugin—no clone, no install (Node 20+). Two layers run over the
repo: the mutation probe (prove) breaks each tested function and reports which tests don't
notice—execution-proven, not guessed; and a deterministic checker (check) that statically lints test soundness.
Report exactly what each printed, then route every finding to its repair. They locate a defect; they do not
fix it.
Core principle: report the tool's own exit code and lines verbatim—never paraphrase a clean result over a real finding—then repair each at its source, never by making the number look right.
1—Run the mutation probe (execution-proven, not guessed)
prove guts each tested function with a guaranteed-wrong return and runs only that test. A test that still
passes is re-gutted with an opposite-signed wrong return before any accusation: green under both is
hollow—it cannot detect the function breaking; red under exactly one is one-sided (binds one
direction of error; reported, never a blocker). This fires where a static read is silent (an expected
value that re-runs the code under test, an assertion dialect a parser can't see), and the verdict is
execution-proven, not a guess.
- PROVE—the bundled front door. On Claude Code:
"${CLAUDE_PLUGIN_ROOT}/mutation/gutcheck.mjs"; else this bundle's ownmutation/gutcheck.mjs(its absolute path in the installed dir). It runs the startup self-check before probing; same arguments as below. - REPO—the project under test. On Claude Code:
"${CLAUDE_PROJECT_DIR}"; else the repo root you were invoked in.
node "<PROVE>" "<REPO>" # caught/scored counts + the hollow tests, across the repo
node "<PROVE>" "<REPO>" --since=<ref> # scope to tests touched by changes since <ref> — fast; the after-a-change case
A full-repo run prints caught/scored (pct%) and lists each hollow test as ✗ file:line 'name' — survives gutting fn() (fn() is bound by N other proven tests) (single-quoted name and a ✗ marker, exactly as
gutcheck prints it; the trailing parenthetical is the run's own sibling-binding fact—no other probed test binds fn() marks the fn's only probed coverage, the real gap). A --since run instead prints a diff
verdict—N functions in this diff — M proven, K HOLLOW, J with no binding test · L unverifiable · P not probed (cap).—then the same 'name' — survives gutting fn() receipt under a hollow heading, with
separate no binding test and unverifiable sections for the other buckets. On either report every hollow line
is execution-proven: rebuild its oracle (§4), then re-run prove to confirm it now bites. A function whose
result feeds no value-pinning assertion is left unprobed and reported unverifiable, never hollow; the
checker's weakOracleGuard kind can flag that statically, but it ships in no default floor (JS/TS, Python, or
any other build system) and runs only if the project's own gutcheck.config.json opts it in. To drill into one
assertion, gut a single function directly:
node "${CLAUDE_PLUGIN_ROOT}/mutation/probe.mjs" <testFile> <srcFile> <functionName> (HOLLOW vs SOUND).
2—Run the static checker (the source-discipline floor)
- CHECKER—the bundled CLI. On Claude Code:
"${CLAUDE_PLUGIN_ROOT}/checker/cli.mjs". On other bundles: this bundle's ownchecker/cli.mjs(its absolute path in the installed dir). - CONFIG—the project's own
gutcheck.config.jsonat the REPO root if present; else the bundled floor ("${CLAUDE_PLUGIN_ROOT}/gutcheck.config.json"). - TESTDIR—the first of
test/,tests/,__tests__/,spec/that exists under REPO. If none, drop--src-test.
node "<CHECKER>" --config "<CONFIG>" --repo-root "<REPO>" --src-test "<TESTDIR>"
The floor is language-gated. JS/TS (node) gets seven deterministic source-discipline checks: hollow/leaky
test shapes, uncited expected floats, inline-derivation coherence, same-call assertion
consistency, empty-fallback collapse (a || []/?? {} upstream of a compare-to-empty assertion),
external value-citations missing a URL, and an advisory shadow-oracle guard (reported, never failing
the run). Python carries six, swapping a failing shadow-oracle check in for empty-fallback collapse.
Every other detected build system (Gradle/Kotlin, Maven/Java, C++, C#, Rust, Go, Swift, PHP, Julia, Ruby,
Haskell, Fortran) gets only the one language-agnostic value-citation check until its own check set is
calibrated in—expect one finding class there, not seven. Drop any flag whose
input did not resolve, then read the exit code AND the output:
META-GUARD FAILED→ surface it loudly and stop. The checker refused to run because one of its own guards failed its self-test. Do NOT present any result as clean—report the failing guard verbatim.- Exit 0 /
OK→ reportOK — N checks passed(N from the output). - Exit 1 with offenders → report each as printed:
✗ file:line (check) token, grouped by check (offenders print in check-registration order). Don't soften or summarize away a real offender.
3—Repair each finding at its source
| Flag | What it means | Repair |
|---|---|---|
hollow test (from prove) | the test still passes with its function gutted—it asserts nothing real | rebuild a real oracle (§4), then re-prove |
| shadow oracle | the expected value re-derives the code under test, so drift can't fail it | rebuild a real oracle (§4); prove (§1) confirms the rebuild bites |
weak / assertion-free (prove: unverifiable) | a SUT call with no value-pinning assertion, so prove reports it unverifiable rather than probing it | add an assertion that pins the contract |
| uncited magic literal | an expected number with no source | source it (§5), label it engineering-judgment, or drop it |
| derivation / consistency | an inline derivation or a sibling assertion disagrees with the asserted value | one of them is wrong—fix the wrong value, never widen a tolerance to hide it |
| external citation (no URL) | a standard/spec citation backing a value carries no source URL | add the URL inline, or verify the citation (§5) |
| fallback collapse | the actual expression launders an absent field into []/{} before a compare-to-empty assertion, so a broken producer still passes | assert the real populated shape, or remove the fallback from the assertion path |
4—Build a real oracle (never from the code's own output)
THE IRON LAW: NO ORACLE FROM THE CODE'S OWN OUTPUT
An expected value copied from what the code currently returns is a photograph of today's behaviour, bug and
all. Derive it independently: from a spec / standard / closed-form identity, or a different reimplementation,
or a trusted reference tool (assert within a real non-zero residual—an exact 0.0 means one value was stored
twice). When no closed form exists, assert a property (sign / bounds / monotonicity) plus a non-vacuity floor
so an all-null green can't pass; pin a recorded golden only as a documented refactor-guard,
never as a correctness claim.
5—Source a constant / verify a citation
A computed value or cited number must trace to a source, not a tweak that makes it look right.
- Concrete source (a local
file:line, a commitsha, a datasheet on disk)—grep/git show/ read it, then quote the line inline. - Abstract source (a standards section, a patent, a paper)—this is where agents fabricate. Hand it to the opt-in
citation-verifieragent: it fetches the source and confirms four things—it exists, it says what the citation claims, it applies to the context where the value is used, and its attribution is correct—then returns a verified-quote-inline form. A paywalled source it can't reach is labelledunverified-from-public-source, not asserted. - A bare magic number with neither a source nor a labelled rationale is a confabulation risk—refuse it.
A provided "validated against X" / "cross-checked" attestation is a claim about a check, not the check. Re-run it yourself, at the precision the claim asserts, before relying on what it defends.
6—Verify before claiming
NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE
Before claiming work passes: run the verification command (npm test) in THIS message, read the full
output—exit code, failure count, the actual numbers—and only then make the claim, with the evidence. A
regression test is proven red-green: write → run (pass) → revert the fix → run (MUST fail) → restore → run
(pass). "Should pass", a previous run, or an agent's "DONE" is not evidence—read the diff and re-run.
Never
Claim a clean run from a META-GUARD FAILED output · present a prove HOLLOW line as a clean test · invent a
config or path not on disk · pin an expected value from the code's own output · widen a tolerance to make a test
pass · assert an abstract citation without a fetched quote · claim "it passes" without a fresh run in hand.