fix(retain): derive document_id from content+context (idempotent re-ingest) - #10
Merged
Merged
Conversation
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Looks good. I did not find any high-confidence Critical or Important issues in this diff.
Suggestions (0)
None.
Strengths
- The fallback document id is deterministic while preserving the existing UUID-shaped id contract.
- The id derivation is scoped by sanitized context, which avoids collapsing same-content documents from intentionally different contexts.
- The regression coverage includes both pure helper properties and an end-to-end re-ingest case for the existing document upsert path.
- The namespace constant is guarded by a test, reducing the risk of accidentally orphaning future deterministic ids.
Recommended Action
- Merge once CI passes, especially the package-level retain/document-tracking tests that exercise the async storage path.
…ngest) When a caller supplies no explicit document_id, retain_batch minted a random uuid4. Because the id was random, re-ingesting byte-identical content created a duplicate document instead of upserting — the source of the exact-duplicate documents found in the BLO-9319 bank dedup. Derive the fallback id deterministically from sanitized content namespaced by context (uuid5, preserving the 36-char id shape), so re-ingesting the same content+context upserts the same documents (id, bank_id) row via the existing ON CONFLICT path. Namespacing by context keeps two intentionally-distinct documents that share identical content separate. Forward-only: existing rows keep their random ids, no migration. Tests: pure-function unit coverage of the derivation helper (determinism, context namespacing, content sensitivity, uuid5 shape) + an end-to-end idempotent-reingest regression in test_document_tracking.py. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kkroo
force-pushed
the
blo9319-hindsight-content-derived-docid
branch
from
June 7, 2026 21:05
4b39114 to
6576dce
Compare
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.
What
When a caller supplies no explicit
document_id,retain_batchminted a randomuuid4. Because the id was random, re-ingesting byte-identical content created a duplicate document instead of upserting — the source of the exact-duplicate documents found in the BLO-9319 bank dedup (~14 exact dups).This derives the fallback id deterministically from sanitized content namespaced by context (
uuid5, preserving the 36-char id shape), so re-ingesting the same content+context upserts the samedocuments (id, bank_id)row via the existingON CONFLICTpath.Why namespaced by context
Namespacing keeps two intentionally-distinct documents that happen to share identical content separate; only same-content and same-context re-ingests collapse. Content is sanitized with the same helper used for
content_hash, so whitespace/encoding noise doesn't perturb the id.Notes
document_id(e.g. the MCPagent_knowledge_ingesttitle-derived path) are unaffected.document_idis never parsed as a UUID downstream (verified), but is concatenated into chunk ids / rendered in the UI — hence keeping the uuid shape viauuid5.Changes
engine/retain/orchestrator.py:_derive_document_id()helper + fixed namespace constant; wired into both no-id fallback sites (main path + the multi-id batch-grouping path).tests/test_document_id_derivation.py: pure-function unit coverage (determinism, context namespacing, content sensitivity, uuid5 shape).tests/test_document_tracking.py: end-to-end idempotent-reingest regression (same content+context ⇒ 1 doc; different context ⇒ 2).Verification
py_compileon all changed files.uvML sync).🤖 Generated with Claude Code