Repository navigation
feat(recall): a recalled document segment names its source file and version (#713, slice 2) - #899
Conversation
…ersion (#713, slice 2) ingest_document tags every summary/section memory with doc-ingest:<kind>:<source>@<version>, but recall returned only the raw tags, so a caller had to parse them to trace a segment back to a file version. parse_document_provenance_dedup_tag inverts the tag (a source path may hold ':' and '@'), and annotate_source_attribution now adds document_sources to every hit written by ingest_document. Non-document hits get no key. Refs #713 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_018kyZYt2w35ZfYtNeiy6Ey9
…nt-source # Conflicts: # CHANGELOG.md
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Claude finished @cdeust's task in 2m 57s —— View job PR #899 review (1 of 3, ADR-1119)
No Blockers. I posted 3 Notes:
Verdict: approve |
Review 1 of 3 (ADR-1119): PR #899 at
|
|
The review approved this PR with no Blocker, so I am not pushing for its three Notes (ADR-1119: only a Blocker justifies a push). Here is what happens to each one:
Generated by Claude Code |
Summary
Refs #713 (slice 2 of 4). A
recallhit written byingest_documentnow names the document it came from:document_sourceslists the source file, the content version and the adapter kind.Root cause.
ingest_documentalready tagged every summary/section memory withdoc-ingest:<kind>:<source>@<version>(document_provenance_dedup_tag). Butrecallreturned only the raw tag list, so a caller had to parse tags to trace a segment back to a file version. No code read that tag back.Change.
core/document_model.parse_document_provenance_dedup_taginverts the tag. The kind never holds:. The version is a hex digest, so the last@starts it. A source path may hold either character (C:\docs\team@corp\guide.docxround-trips). Any other or malformed tag givesNone.core/document_reference.annotate_document_sources(pure) addsdocument_sourcesto each hit that has such a tag. A non-document hit gets no key. The value is always a list, so a hit whose tags name two versions shows both instead of an arbitrary pick.recall_helpers.annotate_source_attribution, the read-side provenance surfacingrecallalready calls, now also calls it. I deliberately put the call outsiderecall._handler_impl: touching that function would have put all of it in scope for the ADR-1122 mutation gate.outputSchemadocuments the field.mem.get("content", "") or ""becomesmem.get("content").recall_confabulation_riskalready normalizescontent or "". The redundant defaults produced 4 equivalent mutants once the function was in scope.Remaining slices (listed on the issue): trace a derived claim or wiki synthesis to its source segments, with missing references made explicit; and when a source is corrected or deleted, report the affected references without inventing new locations.
Type of change
Test plan
tests_py/handlers/test_recall_document_sources.py(new, 5 tests):ingest_documentthenrecall, and the hit carries{source, version, source_kind}. It fails without the change (KeyError: 'document_sources').:and@in the path; 8 malformed or foreign tags giveNone; no key on a non-document hit; two versions both listed.pytest tests_py/handlers tests_py/core tests_py/server: 5549 passed, 242 skipped, 1 failed. The failure istest_wiki_coverage_dashboard.py::test_unreadable_page_is_skipped_not_fatal, and it fails the same way onorigin/mainin this container: the container runs as root, sochmoddoes not make the page unreadable.scripts/ci_mutation_diff.py'splanandrun_job:document_model.pyrc 0,document_reference.pyrc 0,recall_helpers.pyrc 0. Before the extra malformed-tag cases, 3 survivors in the validity check; before thecontentsimplification, 4 equivalent survivors.ruff checkandruff format --check(ruff 0.17.3) pass onmcp_server,tests_py/handlersandtests_py/core.python scripts/check_craftsmanship.py: OK.Audit notes
Coding-standards compliance
check_craftsmanship.pyOK.Breaking changes
None: the field is additive and absent on non-document hits.
Reviewer checklist
Generated by Claude Code