v1.108.235 - a cache truncated inside its last line is no longer attested as matching
Reported by @rknighton in #412, a follow-up to his own #401 whose patch introduced the prefix match this closes.
_slice_matches sliced to len(cached_slice), which is a prefix match, and rejected only when the newline count differed. Cutting bytes from inside the final line preserves that count, so a cache holding return 4 against a committed return 42 was reported as git_sha_match. Both verdict paths share the helper, so one defect produced a false match on the recorded commit and a false git_sha_uncommitted against the working tree.
The comment above the guard claimed the line-count check ruled truncation out. It did not, and that false reassurance is why this survived a review looking straight at it. It is corrected in the same commit rather than left to reassure the next reader.
Measured at the caller's entry point, and it cuts against the report
content_verified is computed three lines above the git_sha branch, against the per-symbol content_hash recorded at index time, and it returns False on exactly these caches. So the served response was internally contradictory rather than uniformly confidently wrong. That is a real mitigation the report could not see, because it exercised _slice_matches directly. It is stated here because omitting it would let these notes overstate the bug in our own favour.
It does not excuse the defect. git_sha_verification is the externally-attested signal, its verify / verify_against ride an evidence receipt's canonical projection as mode_args, and a direct caller of the helper has no sibling signal to contradict it. Two paths settling one question and disagreeing is its own defect.
The fix keeps the one legitimate shortfall
The cached byte range stops at the symbol's last byte, so trailing text on the final line must stay uncompared. Text that trails a symbol is separated from it; a truncation cuts mid-token, so the next character continues the token the cache ends on. Requiring the remainder to begin on whitespace separates the two without knowing the language.
Deliberately biased toward refusing, and the source comment says so. A symbol followed immediately by text with no separating space (return 42# note) now reports divergence. A false git_sha_mismatch costs a re-read; a false git_sha_match attests bytes nobody checked, inside a provenance claim.
Both guards are load-bearing, verified in both directions. The line-count check alone admitted this defect; the new boundary check alone would admit a cache missing its whole final line, because the remainder then begins with a newline, which is whitespace. Removing either reopens a different hole.
Verified end-to-end through get_symbol_source against a real git repo with byte_length corrupted in SQLite, not only through the helper. His regression test is included verbatim in tests/test_v1_108_224.py.
Suite 6773 passed / 7 skipped (was 6772 / 7; the +1 is his test). No INDEX_VERSION, tool-count or wire-format change.