plugins/agentic-engineering-principles/skills/mechanical-guardrails/SKILL.md
Converts recurring "please don't" guidance into structural enforcement agents cannot drift past — deleting the foot-gun API, making illegal states unrepresentable in types, shrink-only ratchets, coverage assertions, checked-in budgets, declare-or-fail registries, derived artifacts, and round-trip contract tests. Use when agents keep reintroducing a pattern you documented against, when asking how to make a convention stick, when planning a migration off a legacy API, when a wrapping or registration convention has silently drifted, or when code review is the only thing standing between the codebase and a defect class.
npx skillsauth add amhuppert/my-ai-resources mechanical-guardrailsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Agents follow prose guidelines imperfectly, and they forget them entirely under context pressure — the guideline was read forty thousand tokens ago, and the call site looks reasonable. A red test or a lint error at the moment of authoring beats any amount of documentation, because it arrives exactly when the decision is being made and it cannot be skimmed. This skill is about converting recurring "please don't" guidance into mechanisms that fail loudly.
| Rung | Mechanism | Fails when | |---|---|---| | 1 | Prose guideline in a doc | The agent didn't read it, or read it and forgot | | 2 | Review vigilance | The reviewer is tired, or the violation is invisible at the call site | | 3 | Lint rule with an allowlist | The allowlist becomes the pressure valve and grows | | 4 | Shrink-only ratchet | Someone raises the ceiling to go green | | 5 | Type-level impossibility | An escape hatch re-admits the shape | | 6 | Deleting the operation | Cannot rot — there is nothing left to call |
Climb as far as the situation allows. Rule of thumb: if you have written the same review comment three times, you are at least one rung too low.
A hot-path anti-pattern dies when the operation dies, not when a convention discourages it.
In one real audit, an expensive whole-state read had already been through a long migration — several reader families and a dozen write sites moved onto focused accessors — and the audit still counted thousands of calls averaging hundreds of milliseconds, landing on request paths. The anti-pattern had been addressed by convention: a lint allowlist plus review vigilance, while the expensive operation itself remained callable and public. Every migration removed instances; the surface that made new instances trivially cheap survived every one of them and refilled.
The sequence that actually ends it:
Test-only fixtures may replace the deleted API for test setup, as long as production code cannot import them.
Two things change shape when you do this:
The rewritten rule is "there is no such operation to call" instead of "please don't call it on a hot path". That is the only form of the rule that cannot rot.
Where deletion is too blunt, move the constraint into the type system so the violating call site does not compile.
(state) => Result, never returning a promise — turns "await slow work while holding the lock" into a compile error rather than a review finding. The caller physically cannot await inside the critical section.{ events, pushes } as plain data cannot broadcast from inside a transaction; the seam performs delivery after the commit resolves. Making the wrong thing inexpressible beats documenting when it is allowed.Pin the constraint itself with a type-error fixture test: a deliberately illegal call site annotated as expected-to-fail. Without it, someone widens the signature later and the hole reopens silently — the guardrail is regression-guarded only if a test asserts it still rejects.
Checklist for a type-level guardrail:
unknown cast) re-admit the shape?Encode the current count of a legacy pattern as a checked-in ceiling that only goes down.
Works for: legacy call sites, legacy selectors or stylesheet lines, architecture seam violations, uses of an async form where the sync form is now the default, files still on a superseded module.
Rules that make a ratchet work:
"Every route is instrumented / wrapped / registered / published through the seam" is only true if a test says so.
In one real audit, 22 handlers shipped outside the request-tracing net. The wrapping happened inside library modules and the route shells just re-exported the result, so a module that forgot the wrap — or added a sibling handler without it — was indistinguishable by eyeball from one that did it right. Those requests carried no trace context, and their timings could not be joined back to a request.
The mechanism:
Generalizes directly to: every event publisher goes through the typed publication seam; every persisted repository has a contract test; every command has a help entry; every trusted schema is registered.
The design tell: if a convention's compliance is invisible at the call site, it will drift. Either make it visible or make it asserted.
Encode performance and size ceilings in a data file and check them: route p95, hold time for a serialized section, storage-read latency, row or payload size, bundle size.
The payoff is timing. One real 5× degradation went unnoticed for two weeks and was only found by retrospective percentile archaeology, because no budget existed to turn it into a number. A checked-in budget converts slow-drift regressions into a same-week red number.
For a recurring class of latent defect, build a gate that enumerates every instance of the class and demands an explicit, typed discharge for each.
The worked example: every collection nested inside a value that is serialized whole into a single storage column grows without eviction, so a per-element write rewrites the entire column. The gate registers each such schema, walks its JSON-schema projection for arrays without a maximum and for open-ended maps, and requires every finding to carry one of:
not-persisted — dropped on write (cross-checked against the durability policy).normalized: <table> — not in the blob; lives in its own child table.pruned: <where> — evicted to a bounded working set by named code.bounded: <why> — capped by construction (author-fixed shape, one in-flight set, config-keyed map).tracked: <item> — honestly still unbounded, naming the structural change that will fix it.Design rules that keep such a registry honest:
tracked: discharge is what makes it adoptable. You do not need everything fixed to turn the gate on today; you need every instance decided.Other classes worth a registry: schemas allowed to skip validation in production (each must be provably free of defaults and transforms), modules allowed to import a restricted path, surfaces allowed to break a layout or design rule.
This is the generalizable alternative to "we wrote a guideline about it".
When several surfaces express the same facts, derive them all from one typed source and let a contract test fail on drift.
Typical set: command help text, per-command flag allowlists, the parser's boolean-flag set, top-level usage, group dispatch, and the command reference table inside a skill doc. They are the same facts, so a hand-maintained copy is a guaranteed future divergence.
The contract test is the definition of correctness: every dispatchable path has an entry, every leaf has at least one example, every cross-reference resolves, every referenced file exists on disk, kind collisions fail.
Drift in agent-facing documentation is worse than absence: absence sends the agent to the source, while drift sends it confidently to the wrong place and trains distrust of every other doc you wrote. Hand-syncing is a defect class, not a review duty.
Every persisted shape gets a maximal write → reload → assert backstop against the real storage layer.
not-persisted discharges in your bounds registry.earned-guidance-docs — write agent guidance only when earned by real failures; root contract plus read-on-demand docsprogressive-disclosure-tooling — help as a navigable disclosure graph derived from one typed registrylive-system-verification — verify features against the running system and durable state, not fakes or UIagent-offloading — offload deterministic work from agents onto code; reserve agents for judgmentdevelopment
Debug a running web app via the web-debugger SDK: app logs, application state, runtime snapshots, React state, query cache.
development
Thoroughly understand a software development objective before implementation: research, identify ambiguities, ask clarifying questions. Use before starting implementation of a non-trivial or ambiguously specified feature, or when requirements leave open design decisions.
development
Locate the on-disk Claude Code transcript file (.jsonl under ~/.claude/projects/) for the current or a specified conversation.
development
Reflect on codebase navigation effectiveness at end of conversation. Surfaces dead ends, inefficiencies, missing context. Does not write files — pair with /kiro:steering-custom to persist.