How fingerprints expire reviews
A review records a hash, not a name. Therefore, when the code changes, the hash changes, and the review no longer describes anything that exists.
What counts as a change
Not every edit counts. If reformatting expired existing reviews, nobody would trust it.
As such, the source is normalized first, and only what survives normalization is
hashed. (crates/vidi-lang/src/normalize.rs).
| Edit | Restales? | Why |
|---|---|---|
| Reflow or re-indent | no | Whitespace between tokens is dropped; no token is. |
| Rename the unit or a parameter | no | A name bound by the unit becomes its position, so a consistent rename collapses. |
| Rewrite a comment | no | Comments are excluded from the hash entirely. |
| Rename something it calls | yes | A name the unit does not bind keeps its exact text. |
a + b → a - b | yes | For an operator or keyword, the token itself is the identity. |
| Change a literal | yes | Literals keep their exact text. |
The dividing line is the behaviour: an edit that cannot change what the code does leaves the hash alone, and an edit that could, changes it.
Block structure counts
Moving a statement into or out of a loop body is a real change, and vidi has to see it even where nothing visible marks the block.
In a brace language this is free since { and } are tokens, so the nesting is
already part of the identity. Python has no such token, and flattening the tree
would erase the nesting, making the move hash-invariant. That would be a way to
change behaviour without expiring the review, so those blocks get synthetic
enter and exit markers instead. A whole-unit re-indent still hashes the same.
Nested code restales its parent
A unit’s hash folds in the hashes of its children, so editing a nested function changes both its own hash and its parent’s, so the parent’s identity includes what it contains.
Where child order carries no meaning, children fold order-independently: reordering independent methods is not a change.
Why the rules are part of the hash
The hash covers profileVersion and scopeModelVersion which are the identities of the
normalization rules themselves. A fingerprint means these bytes, under these
rules, and comparing hashes computed under different rules would be
meaningless.
It is also why a review whose hash matches but whose profile does not never reads as fresh. Vidi will not re-hash under new rules and call the result covered. See Fail-closed by default.
What this does not cover
Comments are stripped before hashing, so a comment can be made wrong without anything going stale. A function whose doc comment describes behaviour it no longer has stays fresh, and vidi will not tell you.
This is the right default, since expiring every review in a file because someone fixed a typo would make coverage too noisy to read. But it narrows the guarantee, and the narrowed version is worth stating plainly: vidi certifies that behaviour was reviewed, not that every byte was.