Claude Code skills that gate a code change before it is written: reuse what the repository already has, trace invalid state back to the contract that produced it, and fix it there — not where the symptom shows up.
A bug surfaces in a consumer. The smallest patch that turns the test green is a clamp, a
default, an early return, or one more if — right where the failure is visible. It works, it's
one line, it ships.
But the producer still emits the invalid value. The next consumer hits the same thing. The clamp becomes a special case every future reader has to remember, and a visible failure quietly becomes silent corruption.
The point is not "write less defensive code." Validation, assertions, and boundary defenses are good. The point is the layer a fix lands at: repair the contract that made the state wrong, instead of compensating for it downstream.
A gate on how a change gets built. Six steps, each producing something you can actually judge:
| Step | Output |
|---|---|
| 0. Proportional gate | Which tier — trivial / local / structural. Don't gate a typo. |
| 1. Search before you create | A reuse candidate at file:line, or a stated reason none fits |
| 2. State the invariant | One sentence: what should always have been true |
| 3. Trace to first violation | The earliest file:line where that invariant goes false |
| 4. Fix at the contract owner | Which level of the fix hierarchy, and why not a lower one |
| 5. Adjacent consumers + cleanup | Scaffolding removed; boundary defenses kept, with reasons |
| 6. Pass check | Smallest change in semantic scope, not smallest diff |
It explicitly does not fire on typos, formatting, or config values, and it never argues against genuine boundary defenses — external input, auth, memory safety, API compatibility, transaction rollback, concurrency, fault containment.
Self-review of your own contribution PRs, with severity-based routing: P2-or-higher gets posted inline on the PR; everything below is banked into scoped cleanup draft PRs instead of cluttering a feature PR that is about to close. Every P2+ candidate must survive an adversarial refutation pass against actual source before it is posted.
- contribution-review-gate — what to raise publicly (trace → verify → route).
- clean-code-gate — whether the fix for it is sound (reuse → contract owner).
Loaded on demand, so the always-on cost stays small:
contract-traps.md— where invalid state actually enters. Re-routed mutations that drop the old call's side effects; routing into a snapshot mechanism that doesn't capture that state; an index recorded in a different coordinate space than its inverse consumes. Used by both skills — it lives in one place, and neither restates it.dynamic-tracing.md(Korean) — when reading can't find the origin: stack-trace instrumentation before the dangerous operation, bisection for test-pollution.external-skills.md— vetted public skills, recording what was adopted and what was deliberately dropped.
Symlink each skill into ~/.claude/skills/ so the repo stays the single source of truth — edits
here take effect immediately, with no copy to keep in sync:
git clone https://github.com/lpaiu-cs/root-cause-gates.git
cd root-cause-gates
ln -s "$PWD/clean-code-gate" ~/.claude/skills/clean-code-gate
ln -s "$PWD/contribution-review-gate" ~/.claude/skills/contribution-review-gateSkills are loaded from ~/.claude/skills/; Claude Code follows directory symlinks.
Built after comparing against the closest public skills — none combined repo-first reuse with
static contract/coordinate-space tracing. What was borrowed, and what was left behind and why, is
recorded in external-skills.md. Most notably:
the dynamic tracing method comes from
obra/superpowers, but its closing
"add validation at every layer" step is deliberately not adopted — for internal contracts that
is the downstream duplication these skills exist to prevent.