Require Negative Evidence Before You Trust a Control

evidence governance software-delivery testing verification Aug 13, 2026

A control that has only ever returned green has not yet proven it can catch what it claims to catch. Passing results are necessary. They are not sufficient. The missing half is executable negative evidence: a mechanism that fails against the real unfixed baseline, runs on the content you claim to have shipped, and leaves residual risk stated plainly when the work stops short of production readiness.

The problem

Delivery systems accumulate stages, checklists, and audit labels. That structure feels like safety. The quiet failure mode is different: a gate that can only pass. Fixtures that never load. Focused regressions that never run against the broken revision. Typecheck or build evidence collected from a dirty working tree and then presented as if it came from committed, clean-checkout content.

When those gaps stack, the work can look complete while the proofs do not actually support the claims. The danger is not theatrical process theatre for its own sake. It is mistaking the existence of a control for evidence that the control works.

A second, related trap appears at the authority boundary. A requirement asks a consumer host to prove recovery or resume behaviour that a frozen dependency's public API does not expose. The tempting shortcuts — deep imports, engine edits, a second controller — all invent capability the consumer does not own. Refusing that path is not pedantry. It is the difference between a bounded delivery and a boundary violation dressed up as progress.

What actually happened

On one delivery that introduced a new lifecycle host against a frozen engine and wrote into a repository with many active worktrees, the first real blocker was architectural, not coding difficulty. The original acceptance asked for recovery behaviour the public API did not provide. The correct move was scope revision: prove reopen through the public surface, durable reads, and the next safe action — not invent resume logic outside the supported contract.

The product fixes themselves were small and structural: a date contract mismatch, a duplicate dialog mount, a selector/component mismatch, and a same-tick double-submit exposure. Each needed a real fix, not a cosmetic one. But the proof work carried as much weight as the patches.

A safety adapter defect showed up before it touched the live repository: path canonicalization treated existing and not-yet-existing paths inconsistently on macOS-style path variants. A refusal fixture caught it early. That is the pattern worth keeping — test safety adapters against scratch repositories before they guard real worktrees.

The first build audit still found genuine proof defects. Some focused regressions lacked evidence that they failed against the actual unfixed baseline. Host typecheck and build evidence came from a dirty worktree rather than committed clean-checkout content. Both were corrected. The lesson was not "add more stages." It was "make the existing controls able to fail in the way their claims require."

Worktree safety forced the same discipline. Many pre-existing worktrees already had varying dirty states. Capturing and later comparing HEAD and porcelain output byte-for-byte was the right proof. Demanding cleanliness would have been the wrong invariant. Safety evidence must preserve the baseline it is protecting, including dirtiness.

Closeout stayed honest. The item closed as a terminal local result: residual risks recorded, remote work deferred, no claim of PR, CI, merge, deploy, or browser E2E where those had not been proven. Production-backed environment access during prerender, a sibling-path local package layout, and the absence of safe non-production browser infrastructure remained named constraints — not footnotes buried under a green checklist.

The lesson

Treat a control as real only when three things are true:

  1. It can fail. Negative fixtures are discoverable. Expected failure tags exist. The mechanism has been shown to fail against the actual baseline revision, not only to pass after the fix.
  2. It measures the claimed identity. "Clean checkout" means committed content in a genuinely clean clone — not a tidy-looking active worktree. Build identity should include commit, tree, and dirty fingerprint when governed artifacts live in a local working tree.
  3. Closeout does not overclaim. Terminal local completion is a first-class outcome. Residual risks and deferred work stay visible. Local proof is not production readiness.

Human gates earn their keep when they narrow an impossible or unsafe requirement without weakening unrelated safeguards. The valuable refusal is the one that stops invented authority at the public API boundary.

The broader principle

Process value is not proportional to stage count. The useful insistence is narrower: executable evidence, explicit authority boundaries, clean-checkout proof, and honest residual-risk recording.

Boundary-impact planning belongs in the same family. Identify the broadest system that could be harmed — not only the new component under construction — and verify against that system. A new host that writes into a repository with many active worktrees has a worktree-registry blast radius, not just a host-unit blast radius.

Environment classification belongs there too. Non-production, production-read-only, production-mutating, and unavailable are different claims. Collapsing them into "the build worked on my machine" hides the risk that matters for the next deployment.

How to apply it

  • Before accepting any requirement about recovery, resume, or internal workflow semantics, run a public-API capability check. If the consumer cannot do it through the supported surface, revise scope or open a separate API item.
  • For every focused regression tied to a claim, require both: failure against the real baseline and pass after the fix.
  • Make clean-checkout verification a standard build requirement for new hosts and packages, including dependency-layout validation.
  • Before any cross-repository write, capture and later recapture worktree HEAD and porcelain byte-for-byte, preserving pre-existing dirtiness.
  • Classify the environment explicitly. Do not treat production-backed local symlinks as a silent stand-in for non-production proof.
  • Prefer a distributable package source or declared artifact registry over sibling-path local tarballs when portability matters.
  • Keep terminal local closeout as a valid ending, with a mandatory deferred-work list for PR, CI, merge, deploy, and E2E where those remain unproven.