An observed agent failure becomes a check so the next occurrence is caught without your attention. Pick the carrier that fits the failure's constraint, prove what you changed, and record where the rule lives.
Reuse first. Before writing anything, search for an existing rule that can carry the constraint: an ESLint restricted-imports or custom rule, a type narrowing, an existing CI step, a test-utility assertion, a skill body, or a line in the project's root instruction file. Extending an existing rule beats adding a second mechanism that can drift from the first. See implementation.md for worked examples and the source evidence.
Choose the mechanism
Pick the carrier by what the failure actually is; each carrier constrains different properties, so the fit decides, not a cost ladder:
- Type — the failure is an invalid shape a compiler can reject. Makes that state unrepresentable; it constrains what the compiler accepts, not runtime behavior.
- Lint rule — the failure is a mechanical pattern across many files (custom rule when no built-in rule fits; see implementation.md for the source's custom-rule economics). Only a real check once you verify the configured invocation actually loads it, at a severity that fails the run.
- Test — the failure is runtime behavior; assert the specific symptom, not "doesn't crash".
- CI step / script — the failure needs repo-wide or cross-service state checked at a fixed gate.
- Root-instruction line or skill — the failure is a judgment call needing context; these steer attention and they do not enforce by themselves.
False positives: prefer a check with legitimate exceptions handled explicitly (allow-lists, targeted suppressions) over no check. A new false positive is a diagnosis task — narrow the pattern or record a justified exception — not a reason to delete the rule. Do not claim a rule that fires on correct code is always worse than no check; that trade-off is judged per case.
Proportionate proof. An instruction-only change needs a wording review (read the new line back against the observed failure and inspect selected loading when affected); an executable change (lint rule, test, script) uses test-first sequencing at the existing behavioral boundary: first show the prohibited case currently slips through, then implement the smallest correction and prove that case is blocked while a known-good case passes. Reuse adequate existing checks. Recurrence is the normal trigger, not a quota: a single defect justifies a guard when the user explicitly asks for one.
Input / output contract
- Input: the observed failure and its evidence, and the repo where the check will live. Recurrence across runs or an explicit user request establishes that a standing check is wanted; infer fitting scope from the failure rather than asking.
- Output: (a) the rule or check added, (b) the proof proportionate to the mechanism per above, and (c) one line in the project's existing convention record saying what the rule enforces and why.
Acceptance
Proportional to the work: a one-line instruction change needs the wording reviewed against the recorded failure; a custom lint rule needs its fixtures (failing + passing) run and a green run of its tests, with the lint invocation confirmed to include the new rule.
Known failure cases
- Encoding a one-off as a permanent rule without a user request (noise forever).
- Assuming a rule is enforced because it is written: verify the selected invocation, severity, and config actually load it. A rule in a config no script runs is documentation, not a check.
- Suppressed or
any-escaped checks that make the rule green without changing behavior.
Do not activate when
- The failure happened once and the fix is the task itself (unless the user explicitly asked for a guard).
- The user wants a bug diagnosed (use a bug-diagnosis skill).
- The request is general refactoring with no observed failure behind it.
Source patterns
For concrete repository examples and the limits of their evidence, read source-patterns.md when they match the task. These are research references, not imported repository instructions.
Reference Feedback engineering: worked implementation
The video argues for replacing repeated manual corrections with reusable checks around 08:02. Theo adds that agents reduce the cost of implementing and testing a project-specific rule around 08:30. This does not establish that a rule prevents every instance permanently.
A forbidden import
Suppose UI files repeatedly import a database module directly, bypassing the supported API. Inspect the project's existing linter before introducing a new plugin. ESLint's no-restricted-imports can express a restricted path and a message naming the approved replacement.
First show the recorded bad case passes without the restriction. Configure the smallest rule covering that case. Then show the bad case fails and a legitimate API import passes through the actual project lint command. If a custom AST rule is necessary, add meaningful fixtures for the intended pattern and legitimate exceptions using the linter's existing test harness. See the custom rule tutorial.
Check both invocation and severity. A warning may be useful feedback without blocking delivery. Static imports are not every possible runtime import; state the rule's coverage honestly.
A runtime outcome
For a chat feature, use independent authenticated browser contexts: one sends a unique message, the other must observe that exact message. This adapts Theo's Twitch story around 03:59; that test's source was not found here.
Preserve failure evidence deliberately. Playwright saves videos on context close; retention options and retry behavior differ. Consult video recording, trace viewing and retry outcomes. A test that passes only on retry is a different observation from a first-attempt pass.
A failed CI run
Let the agent obtain the actual run for its revision and read failed-step logs using gh run view. Preserve the first failure, classify its cause and observe the repaired revision. Keep communication and branch writes within the user's authorization. This useful loop appears in a sponsor segment; the sponsor's performance claims were not reproduced.
Reference Repository examples: checks that protect the intended result
- T3 custom lint: PR #7209 adds a narrow tooltip rule with fixtures and config integration. At the inspected commit, the rule handles direct intrinsic JSX attributes with specific exceptions; it is not a proof against every tooltip route. PR #9300 illustrates maintenance of suppressions and baseline allowances.
- Melee completeness: the initial verifier checked build/diff success and a reference hash. A follow-up also rejects incomplete source reports. We reproduced the initial false acceptance and later rejection using synthetic bytes and mocked commands; no game build was run.
- Boris's compiler: the CI workflow layers platform/runtime checks, seeded fuzzing and generated-output validation. Its aggregate
ci-okexpression omits two dependencies, so inspect required checks instead of trusting the aggregate name. We read this source; we did not run its compiler suite.
Choose the invariant appropriate to the product. Exact bytes suit matching decompilation; they are not a universal acceptance condition for renderers, refactors or generated code.