[claude/hotfix] fix(store): drop duplicate physical sources for the same logical session#39
[claude/hotfix] fix(store): drop duplicate physical sources for the same logical session#39div0-space wants to merge 1 commit into
Conversation
…gical session — freshest copy wins - aicx all -H 30 na żywym korpusie padoł na końcu biegu: 'duplicate canonical card id: card3:1980d570c88bce990c7e30e8' — ta samo logiczno sesjo odkryto z dwóch ścieżek fizycznych (np. live rollout + zarchiwizowano kopia) - root cause: ingested_session_ids (BTreeSet) dubla nie wstawiał, ale canonical_cards.extend() szedł per-źródło -> dwa komplety kart o identycznych content-derived id w projekcji - fix: order_sources_freshest_first (mtime desc, sort stabilny) + strażnik per-batch: druga kopia już-ingestowanej sesji -> drop liczony w duplicate_sources (NIE skip: nie trzymie watermarku, nie triggeruje retry) - summary raportuje duplicate_sources=N tylko gdy N>0 - test: duplicate_session_sources_are_ordered_freshest_first Authored-By: claude <agents@vetcoders.io> session_id: 49a84e4c-f24d-4167-9f55-ae0f8123a66f timestamp: 2026_0715_1540_CEST runtime: claude-code-interactive
There was a problem hiding this comment.
Code Review
This pull request introduces a mechanism to handle duplicate session sources by sorting them freshest first based on their modification timestamp. This ensures that the most recent copy of a logical session is parsed first, and subsequent older duplicates are dropped and tracked via a new duplicate_sources counter. A unit test was added to verify the sorting order, and the session ingest summary output was updated to display duplicate sources when present. The reviewer suggested using sort_unstable_by instead of sort_by to improve sorting efficiency.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| fn order_sources_freshest_first(sources: &mut [crate::session_catalog::CatalogSource]) { | ||
| sources.sort_by(|left, right| { | ||
| right | ||
| .fingerprint | ||
| .modified_unix_nanos | ||
| .cmp(&left.fingerprint.modified_unix_nanos) | ||
| }); | ||
| } |
There was a problem hiding this comment.
Since stability is not required when sorting sources by modification time, we can use sort_unstable_by instead of sort_by. This is more efficient as it avoids allocating temporary memory and is generally faster.
| fn order_sources_freshest_first(sources: &mut [crate::session_catalog::CatalogSource]) { | |
| sources.sort_by(|left, right| { | |
| right | |
| .fingerprint | |
| .modified_unix_nanos | |
| .cmp(&left.fingerprint.modified_unix_nanos) | |
| }); | |
| } | |
| fn order_sources_freshest_first(sources: &mut [crate::session_catalog::CatalogSource]) { | |
| sources.sort_unstable_by(|left, right| { | |
| right | |
| .fingerprint | |
| .modified_unix_nanos | |
| .cmp(&left.fingerprint.modified_unix_nanos) | |
| }); | |
| } |
There was a problem hiding this comment.
Pull request overview
This PR updates the app-only session extraction pipeline to handle cases where the same logical session is discoverable via multiple physical sources (e.g., live rollout + archived copy) by processing the freshest copy first and dropping older duplicates, while reporting how many were dropped.
Changes:
- Added
duplicate_sourcestoSessionExtractionBatchand incremented it when a second physical source for an already-ingested session is encountered. - Introduced
order_sources_freshest_firstand changedextract_agent_sessionsto sort selected sources by mtime descending before parsing/ingesting. - Updated CLI/session batch summary output and added a unit test to validate the ordering behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/extraction/mod.rs | Adds duplicate source counting, introduces freshest-first ordering, and updates extraction loop to drop duplicates. |
| src/extraction/tests.rs | Adds a test asserting freshest-first ordering for duplicate-session sources. |
| src/main.rs | Extends session ingest summary output to include duplicate_sources when non-zero. |
Comments suppressed due to low confidence (1)
src/extraction/mod.rs:139
- Duplicate sources are only detected after parsing the file. Since
CatalogSourceoften already haslogical_session_id, you can drop already-ingested duplicates before callingparse_file, saving work for archived/older copies while still keeping the post-parse guard as a fallback whenlogical_session_idis missing.
batch.selected_sessions += 1;
let parsed = crate::parser_dispatch::parse_file(
parser_agent,
&source.source_id,
source.logical_session_id.clone(),
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if batch | ||
| .ingested_session_ids | ||
| .contains(&session.model().session_id) | ||
| { | ||
| batch.duplicate_sources += 1; |
This pull request improves how duplicate physical sources for the same logical session are handled during session extraction. It ensures that only the freshest copy is processed, tracks and reports dropped duplicates, and adds tests for the new ordering logic.
Session extraction improvements:
duplicate_sourcesfield toSessionExtractionBatchto count extra physical sources for already-ingested logical sessions within a batch. These are dropped to avoid reprocessing the same session from multiple files.extract_agent_sessions, sources are now sorted so that the freshest (most recently modified) copy is parsed first. Older duplicates are detected and counted using the newduplicate_sourcesfield, and are not ingested. [1] [2] [3]Testing and reporting:
order_sources_freshest_firstfunction and a test (duplicate_session_sources_are_ordered_freshest_first) to verify that sources are correctly ordered by modification time.Authored-By: claude agents@vetcoders.io
session_id: 49a84e4c-f24d-4167-9f55-ae0f8123a66f
timestamp: 2026_0715_1540_CEST
runtime: claude-code-interactive