Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Fail-closed by default

One comment in crates/vidi-core/src/ledger/staleness.rs states the rule:

over-report, never false-fresh: every ambiguity resolves toward STALE / ORPHAN / uncovered.

Wherever vidi cannot be certain, it resolves toward less coverage, not more.

Why

The two ways to be wrong are not symmetric. A false red costs someone twenty minutes re-reading a unit that was probably fine. A false green merges unreviewed code wearing a check mark that says otherwise, which is worse than no gate at all, because the check mark is what people trust.

There is no threshold where that trade reverses, so ambiguity always resolves the same direction. What follows is the four places it could have gone the other way.

When the code changed

Of the seven unit states, exactly one is coverage: Fresh. Two of the others exist to stop a near-miss reading as a hit.

Migration-needed beats fresh. A review whose hash matches exactly, but whose profileVersion or scopeModelVersion does not, never resolves to Fresh. A matching hash is not enough on its own. Vidi also has to believe both hashes were computed under the same rules, and it will not re-hash under new rules and call the result covered.

Rejected is not coverage. Someone read the current bytes and said no. It never reads Fresh, though it does not gate-fail on its own either.

When the ledger is corrupt

A line in .vidi/reviews.jsonl that will not decode is not skipped. It refuses the whole report:

vidi: refusing to assemble a report over a partially-decoded ledger: 1 rejected line(s)

Skipping the bad line is the reasonable-looking choice, and it is exactly the bug: a truncated ledger would read as fewer reviews recorded, which is indistinguishable from nothing is stale, everything is fine. Corruption would present as a pass.

Because this refusal happens before any verdict exists, vidi verify --json exits 1 with empty stdout and vidi report --sarif emits no file at all. There is nothing to serialize.

When the policy will not parse

A broken .vidi/policy.toml is a load error. It never degrades quietly to advisory and never falls back to a default.

Unknown keys are refused rather than ignored. An ignored key is a rule you believe you wrote and do not have, which is a policy stricter on disk than in effect.

When a signature cannot be checked

With no trust root, or a stale one, every review floors to the weakest assurance rung rather than keeping the standing it claimed. A signature that cannot be verified grades as unverified, never as valid.

Two exit codes that mean opposite things

ExitMeaning
1A verdict was formed and it failed: something is stale, orphaned, or unmet.
2No verdict could be formed. Vidi refused — unloadable policy, unreadable repo, bad arguments.

Exit 1 says your code needs review. Exit 2 says vidi could not run. Both block the merge; that does not make them the same event.

What deliberately does not fail closed

Churn, significance, vidi graph and vidi attribute never gate. Severity bands are advisory by contract, and authorship import fails toward unknown rather than toward a guess.

The line is between what vidi computes exactly and what it only estimates. Hashes, decode success and signature validity are exact, so they fail closed. How risky or significant a change is are estimates, and an estimate that gates is noise with a moral posture. Advisory signals order your queue; they never decide it.

What it costs

  • Prose counts. Markdown becomes units, so writing documentation raises your unreviewed count while you write it.
  • Counts drift. Totals move as files change. A different number than last run is normal, not evidence you broke something.
  • NEUTRAL passes with zero coverage. No policy means nothing to enforce, so a repo with no reviews at all exits 0.
  • Volume. vidi explain over thousands of uncovered units prints thousands of diagnostics. Scope it to a path.

None of these argue against the posture. They are its price, and hiding them would be the same mistake in miniature.