Falsifying
Every gate in this repo reports success. None of them proves it could have reported failure.
A gate that cannot fail is not a gate — it is a decoration that costs trust twice: once when it
passes something broken, and again when people learn to ignore it. This skill assumes the green
light is lying and tries to prove it.
Scope is the apparatus: checkers, gates, coverage numbers, CI jobs, test suites, dashboards.
For latent defects in the product itself, use bug-hunter. For abuse paths against a running stack over HTTP, use attack-test.
Technique 1 — make it go red
Take the claim the signal makes, construct the smallest input that must contradict it, and run
it. If the signal stays green, the signal is broken.
- State the claim in one sentence. "This gate fails when unit coverage is below 80%."
Vague claims cannot be falsified; sharpen until the claim names a threshold, a set, or a rule.
- Design the counter-case. The cheapest thing that must trip it: a threshold set above the
current value, a fixture with the defect deliberately present, an empty input, a duplicate id,
a value one past the boundary.
- Run it and read the exit code, not the console text. A checker that prints
FAIL and exits
0 is worse than one that says nothing.
- Ask what a false green would look like and test that shape specifically. Most broken gates
fail on a category of input, not on a value: matched by a bare name where the name is not
unique, trusting a subprocess exit code that is always 0, scanning a file range that stops
short.
Real findings from this technique:
- a coverage gate reported PASS at any percentage because it read
make's exit code, and that
target only printed the number — caught by re-running with the threshold set above the measured
value
- an AC tripwire matched criterion ids across the whole suite, so a card with no tests at all
reported full coverage off another card's
AC-001 — caught by running it against a card whose
test files did not exist
Technique 2 — diff every source of the same fact
A fact stated in more than one place is a fact that has already drifted somewhere.
- Enumerate every source. For an endpoint path: the router, the router test, the e2e specs,
the API spec YAML, the generated index, the Bruno collection. Six places, one fact.
- Diff them pairwise and write the table. Do not stop at the first disagreement — measured
once: three sources disagreed with each other in three different ways.
- Decide which one is the truth from evidence, not from hierarchy. Running code with a
passing test that exercises it beats a document that describes it.
- Check the citations resolve. A reference to a path, a card, a decision, or an upstream
contract is a claim; open it. A citation pointing at nothing reads as proof and is not.
Artifacts — no artifact means it did not happen
A falsification pass reports one of exactly two things:
- the counter-case, verbatim, with the output showing the signal going red — or staying green,
which is the finding; or
- the source table, listing each place the fact appears and what it says.
"I reviewed it and it looks correct" is not a result. If a signal could not be falsified, say what
you tried and why it held — that is the useful half of a negative result.
When to run it
- Mandatory: whenever a gate, checker, or verification script is written or changed. Every
defect this skill was built from lived in a gate, not in the product.
- Before quoting a number in an MR or a status report.
- When a suite passes on code nobody has run, or a metric improves without work that explains it.
- When a task is handed to a subagent whose success criterion is "make the gate green" — that
brief is satisfiable by an empty test, so audit the result rather than the report.
The advisor gate — mandatory, twice
Calling a gate broken is a claim about someone else's work, and "the counter-case stayed green"
is one reading of an output you produced yourself. When the advisor tool is present in the
session, consult it at two points: once before you commit to the reading — you have the run output
and are about to declare the signal broken, or sound — and once before the result leaves your
hands, with the write-up already drafted so it survives the round trip. Consult again when a
counter-case will not trip either way, or when you drop one technique for the other.
Report what came back alongside the artifact. If advisor is not in the session, substitute
nothing — say in the write-up that no advisor was available and the reading had no outside reader.
Hand-off
A confirmed finding stops here. Fixing it is the BUG flow: diagnosing-bugs for the cause,
tdd for the failing repro, then the fix. This skill produces the symptom that flow needs; it
does not skip ahead to the patch.
Rationalizations
| Thought |
Reality |
| "The gate passed, so we're covered" |
The gate passed. Whether it could fail is a separate, unasked question. |
| "I wrote the checker, I know it works" |
Every gate defect found so far was written by someone who believed that. |
| "The docs and the code disagree, docs are stale" |
Maybe. Decide from what runs, and write down which source you picked and why. |
| "Constructing a fake failing case is a waste of time" |
It is the only evidence that the gate has any power at all. |
| "One source of truth, nothing to diff" |
Count them. Endpoint paths lived in six places. |
| "My counter-case proves it — no need to ask" |
You wrote the counter-case and read its output. That is the pair the advisor gate exists to check. |
1---2name: falsifying3description: Attacks a green signal to find out whether it can go red at all. Audits the measuring apparatus — a gate, checker, coverage number, CI job, or test suite — rather than the product: constructs the case that must fail and checks that it does, and diffs every independent source of the same fact against the others. Use when a gate or checker is written or changed, when a metric looks better than the work feels, before trusting a number in an MR, or when a suite passes on code nobody has exercised. Produces a failing case or a source-disagreement table as evidence; a confirmed finding is handed to the BUG flow, not fixed in place. Not for a reported bug with a symptom (that is `diagnosing-bugs`), not a diff review (`code-review`), not a hunt through product code for latent defects (`bug-hunter`), and not live HTTP abuse probes (`attack-test`).4---56# Falsifying78Every gate in this repo reports success. None of them proves it could have reported failure.910A gate that cannot fail is not a gate — it is a decoration that costs trust twice: once when it11passes something broken, and again when people learn to ignore it. This skill assumes the green12light is lying and tries to prove it.1314Scope is the **apparatus**: checkers, gates, coverage numbers, CI jobs, test suites, dashboards.15For latent defects in the product itself, use `bug-hunter`. For abuse paths against a running stack over HTTP, use `attack-test`.1617## Technique 1 — make it go red1819Take the claim the signal makes, construct the smallest input that **must** contradict it, and run20it. If the signal stays green, the signal is broken.21221. **State the claim in one sentence.** "This gate fails when unit coverage is below 80%."23 Vague claims cannot be falsified; sharpen until the claim names a threshold, a set, or a rule.242. **Design the counter-case.** The cheapest thing that must trip it: a threshold set above the25 current value, a fixture with the defect deliberately present, an empty input, a duplicate id,26 a value one past the boundary.273. **Run it and read the exit code**, not the console text. A checker that prints `FAIL` and exits28 0 is worse than one that says nothing.294. **Ask what a false green would look like** and test that shape specifically. Most broken gates30 fail on a *category* of input, not on a value: matched by a bare name where the name is not31 unique, trusting a subprocess exit code that is always 0, scanning a file range that stops32 short.3334Real findings from this technique:3536- a coverage gate reported PASS at any percentage because it read `make`'s exit code, and that37 target only printed the number — caught by re-running with the threshold set above the measured38 value39- an AC tripwire matched criterion ids across the whole suite, so a card with no tests at all40 reported full coverage off another card's `AC-001` — caught by running it against a card whose41 test files did not exist4243## Technique 2 — diff every source of the same fact4445A fact stated in more than one place is a fact that has already drifted somewhere.46471. **Enumerate every source.** For an endpoint path: the router, the router test, the e2e specs,48 the API spec YAML, the generated index, the Bruno collection. Six places, one fact.492. **Diff them pairwise** and write the table. Do not stop at the first disagreement — measured50 once: three sources disagreed with each other in three different ways.513. **Decide which one is the truth from evidence**, not from hierarchy. Running code with a52 passing test that exercises it beats a document that describes it.534. **Check the citations resolve.** A reference to a path, a card, a decision, or an upstream54 contract is a claim; open it. A citation pointing at nothing reads as proof and is not.5556## Artifacts — no artifact means it did not happen5758A falsification pass reports one of exactly two things:5960- **the counter-case**, verbatim, with the output showing the signal going red — or staying green,61 which is the finding; or62- **the source table**, listing each place the fact appears and what it says.6364"I reviewed it and it looks correct" is not a result. If a signal could not be falsified, say what65you tried and why it held — that is the useful half of a negative result.6667## When to run it6869- **Mandatory**: whenever a gate, checker, or verification script is written or changed. Every70 defect this skill was built from lived in a gate, not in the product.71- Before quoting a number in an MR or a status report.72- When a suite passes on code nobody has run, or a metric improves without work that explains it.73- When a task is handed to a subagent whose success criterion is "make the gate green" — that74 brief is satisfiable by an empty test, so audit the result rather than the report.7576## The advisor gate — mandatory, twice7778Calling a gate broken is a claim about someone else's work, and "the counter-case stayed green"79is one reading of an output you produced yourself. When the `advisor` tool is present in the80session, consult it at two points: once before you commit to the reading — you have the run output81and are about to declare the signal broken, or sound — and once before the result leaves your82hands, with the write-up already drafted so it survives the round trip. Consult again when a83counter-case will not trip either way, or when you drop one technique for the other.8485Report what came back alongside the artifact. If `advisor` is not in the session, substitute86nothing — say in the write-up that no advisor was available and the reading had no outside reader.8788## Hand-off8990A confirmed finding stops here. Fixing it is the **BUG flow**: `diagnosing-bugs` for the cause,91`tdd` for the failing repro, then the fix. This skill produces the symptom that flow needs; it92does not skip ahead to the patch.9394## Rationalizations9596| Thought | Reality |97|---|---|98| "The gate passed, so we're covered" | The gate passed. Whether it *could* fail is a separate, unasked question. |99| "I wrote the checker, I know it works" | Every gate defect found so far was written by someone who believed that. |100| "The docs and the code disagree, docs are stale" | Maybe. Decide from what runs, and write down which source you picked and why. |101| "Constructing a fake failing case is a waste of time" | It is the only evidence that the gate has any power at all. |102| "One source of truth, nothing to diff" | Count them. Endpoint paths lived in six places. |103| "My counter-case proves it — no need to ask" | You wrote the counter-case and read its output. That is the pair the advisor gate exists to check. |