From c4f9bea789f27b040675a0ec9bc110ba7661861e Mon Sep 17 00:00:00 2001 From: zs <2862877643@qq.com> Date: Tue, 28 Jul 2026 15:21:45 +0800 Subject: [PATCH] fix: avoid reextracting superseded raw items --- src/contextseek/evolution/engine.py | 1 + tests/unit_tests/test_evolution.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/contextseek/evolution/engine.py b/src/contextseek/evolution/engine.py index 31adc33..94402ff 100644 --- a/src/contextseek/evolution/engine.py +++ b/src/contextseek/evolution/engine.py @@ -238,6 +238,7 @@ def record_hop( if it.stage == Stage.raw and not it.is_deleted and it.is_valid_at() + and not it.superseded_by and self._eligible_for_extraction(it) ] extract_succeeded = 0 diff --git a/tests/unit_tests/test_evolution.py b/tests/unit_tests/test_evolution.py index 9e89521..87e2443 100644 --- a/tests/unit_tests/test_evolution.py +++ b/tests/unit_tests/test_evolution.py @@ -426,6 +426,26 @@ def test_repeated_evolve_does_not_re_merge(self): report2.conversion.get("extracted->knowledge", {}).get("attempted", 0) == 0 ) + def test_repeated_evolve_does_not_reextract_superseded_raw(self): + engine = EvolutionEngine() + raw = _make_item( + content="a write-once operational note worth extracting into a summary", + stage=Stage.raw, + access_count=5, + ) + + new1, _, _ = engine.evolve([raw]) + extracted1 = [it for it in new1 if it.stage == Stage.extracted] + assert len(extracted1) == 1 + assert raw.superseded_by == extracted1[0].id + + # Simulate the next compact over the persisted source and its child. + new2, _, report2 = engine.evolve([raw, *new1]) + extracted2 = [it for it in new2 if it.stage == Stage.extracted] + + assert extracted2 == [] + assert report2.conversion.get("raw->extracted", {}).get("attempted", 0) == 0 + def test_distill_inherits_lineage_signals(self): distiller = SkillDistiller(min_use_count=5, min_relevance_boost=1.0) item = _make_item(