fix: content-stable review ids so resolved state survives ingest regeneration#495
Merged
Merged
Conversation
Review ids were a module-level incrementing counter (review-N). Any queue rebuild re-ran review generation, which re-numbered every review and — because addItems only deduped against *pending* items — discarded resolved state: a resolved review came back as a brand-new pending one. This also makes id-based targeting (e.g. resolving a review by id from the API) unreliable, since the same number stops meaning the same thing. Make the id content-derived and stable: - reviewIdFor(item) = FNV-1a(type + normalizeReviewTitle(title)). Same logical review → same id across regeneration, file moves, and reloads. Deliberately excludes the mutable sourcePath. - addItems dedups on the stable id against ALL items including resolved (resolved wins, array fields merged) — the actual fix for resolved state being dropped on re-surface. - setItems migrates on load: remaps old counter ids to stable ids and collapses duplicates (resolved wins, union arrays, earliest createdAt). Idempotent (id from content, no version flag), so existing on-disk review.json heals on first load and re-save. - addItem dedups by identity (no revival of a resolved item). normalizeReviewTitle (already the dedup key) is now also load-bearing for id identity. Tests rewritten for stable-id behaviour incl. property tests; acceptance cases: resolve-then-reingest keeps id+resolved, and two counter-id rows with identical content collapse to one resolved item.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Review ids are a module-level incrementing counter (
review-N). Any time review generation re-runs — e.g. the ingest queue rebuilds — every review is re-numbered, and becauseaddItemsonly deduped against pending items, a previously resolved review comes back as a brand-new pending one. Its resolution is silently lost.It also makes id-based targeting unreliable: a caller (the Review API, or anything holding an id) points at a number that no longer means the same review after a rebuild.
Fix
Make the id content-derived and stable.
reviewIdFor(item)= FNV-1a(type+normalizeReviewTitle(title)) — the same logical review gets the same id across regeneration, file moves, and reloads.sourcePathis deliberately excluded (it's mutable; including it would re-id a review on a file rename — the same instability being removed).addItemsdedups on the stable id against all items including resolved ones (resolved wins, array fields merged). This is the actual fix for resolved state being dropped when a review re-surfaces.setItemsmigrates on load: remaps oldreview-Nids to stable ids and collapses duplicates (resolved wins, unionaffectedPages/searchQueries, earliestcreatedAt). Idempotent — the id is computed from content, no migration-version flag — so an existingreview.jsonheals on first load + auto-save.addItemdedups by identity (no revival of a resolved item).normalizeReviewTitlewas already the dedup key; it's now also load-bearing for id identity (noted atreviewIdFor).Tests
Unit + property tests rewritten for stable-id behaviour, including acceptance cases:
Context
This is the store-layer counterpart that makes id-based review resolution (e.g. a resolve endpoint) actually reliable — without stable ids, resolving "review-12" is meaningless after the next rebuild.