diff --git a/AGENTS.md b/AGENTS.md index 0f978b6c77..8a4ec563c7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,6 +33,10 @@ prose in this repo, including this file. succeed on a candidate the shared rules would refuse. - Do not measure before confirming the code path can fire. An A/B whose B-arm cannot execute returns two green runs masquerading as evidence. +- A green check is evidence only once you have seen it red. Prove a new regression test against the + pre-fix code (revert, run, quote the failing number), a moved test against its gates (planted type + error, discovered-count delta), a structural gate against a planted violation. Three vacuous + regression tests shipped in one day before this rule; review caught all three. - Typed signals over message sniffing: key on structured details (`details.timeoutMs`, reason codes), never on error text. Remaining sniffs are owned debt with in-code rationale — do not copy them. - Snapshot output is the token budget. Never add per-node bytes to the tree; response-level metadata diff --git a/docs/agents/testing.md b/docs/agents/testing.md index 9c4e24b5ec..a5406b7d7d 100644 --- a/docs/agents/testing.md +++ b/docs/agents/testing.md @@ -55,6 +55,17 @@ it through the barrel. Keep tests behavioral. Do not assert shapes or cases TypeScript already proves. +A test added as a regression pin must be shown to fail without the change it pins — vacuity is the +default failure mode, not the exception, because the adversarial input you imagine is rarely the one +the old code was slow or wrong on (edge runs that the old regex handled in one pass; invariants the +old implementation already satisfied; entry points whose trimming defuses the exploit before it +reaches the flagged pattern). The proof is mechanical: revert the production change locally, watch +the test fail, note the failing number, restore. Same rule at other layers: after relocating tests, +prove the runner discovers them (file/test counts must move) and the typechecker reaches them (plant +a type error, watch it surface, remove it); after adding an ownership/structural gate, plant a +violation and watch it name the invariant. Quote the red run in the PR — a reviewer who cannot see +the red has to re-derive it. + Test through public interfaces where practical, and do not add unrelated production exports solely to make a test easier — widening the public surface for a test is a product change, and the exports outlive the test that motivated them. If a seam is genuinely missing, add it as a real one rather