fix(cache): scope semantic cache writes to extracted files (#1757)

This commit is contained in:
tpateeq
2026-07-13 00:35:32 +01:00
committed by safishamsi
parent a46eee49ef
commit 579ba1da3c
41 changed files with 196 additions and 41 deletions
+46
View File
@@ -524,6 +524,52 @@ def test_save_semantic_cache_overwrites_by_default(tmp_path):
assert ids == {"b"}, "default must overwrite, not accumulate"
def test_save_semantic_cache_rejects_out_of_scope_source_file(tmp_path):
"""#1757: an undispatched file must keep its complete cache entry when a
semantic result misattributes a node to it."""
from graphify.cache import save_semantic_cache
intended = tmp_path / "intended.md"
intended.write_text("# Intended\n")
protected = tmp_path / "protected.md"
protected.write_text("# Protected\n")
save_semantic_cache(
[{"id": "original", "source_file": "protected.md"}],
[],
root=tmp_path,
)
nodes = [
{"id": "expected", "source_file": str(intended.resolve())},
{"id": "stray", "source_file": "protected.md"},
]
edges = [
{"source": "stray", "target": "expected", "source_file": "protected.md"},
]
hyperedges = [
{"id": "stray_hyperedge", "nodes": ["stray"], "source_file": "protected.md"},
]
with pytest.warns(RuntimeWarning, match="out-of-scope source_file 'protected.md'"):
saved = save_semantic_cache(
nodes,
edges,
hyperedges,
root=tmp_path,
allowed_source_files=["intended.md"],
)
assert saved == 1
intended_cache = load_cached(intended, root=tmp_path, kind="semantic")
assert {node["id"] for node in intended_cache["nodes"]} == {"expected"}
protected_cache = load_cached(protected, root=tmp_path, kind="semantic")
assert {node["id"] for node in protected_cache["nodes"]} == {"original"}
assert protected_cache["edges"] == []
assert protected_cache["hyperedges"] == []
def test_save_semantic_cache_merge_existing_unions(tmp_path):
"""#1715: merge_existing=True unions with the prior entry so a file split
across chunks (checkpointed per chunk) keeps every slice."""
+12
View File
@@ -102,6 +102,15 @@ def test_extract_succeeds_when_at_least_one_chunk_completes(
monkeypatch.setattr(
"graphify.llm.extract_corpus_parallel", _one_chunk_succeeded
)
cache_call = {}
def _capture_semantic_cache(*args, **kwargs):
cache_call.update(kwargs)
return 0
monkeypatch.setattr(
"graphify.cache.save_semantic_cache", _capture_semantic_cache
)
monkeypatch.setattr(mainmod, "_check_skill_version", lambda _: None)
monkeypatch.setattr(
mainmod.sys,
@@ -121,6 +130,9 @@ def test_extract_succeeds_when_at_least_one_chunk_completes(
assert (out_dir / "graphify-out" / "graph.json").exists(), (
"graph.json must be written on the happy path"
)
assert {
str(path) for path in cache_call["allowed_source_files"]
} == {str(corpus / "README.md")}
def _code_only_corpus(tmp_path):
+12 -1
View File
@@ -487,7 +487,8 @@ def test_monoliths_change_only_sanctioned_lines():
The round-trip (multiset diff vs the pinned v8 blob) must come back clean:
each added/removed line matches one of the documented sanctioned predicates
in gen — the enum unification, the unified description, the chunk-cleanup
rewrite (#1172), and the four #1392 runbook fixes. Anything else is drift.
rewrite (#1172), the four #1392 runbook fixes, and semantic-cache source
scoping (#1757). Anything else is drift.
"""
platforms = gen.load_platforms()
for key in ("aider", "devin"):
@@ -534,6 +535,16 @@ def test_monoliths_carry_the_1392_runbook_fixes():
assert "if not wrote:" in body
def test_monoliths_scope_semantic_cache_writes_to_uncached_files():
"""#1757: generated monoliths pass the dispatched-file allowlist when
replacing semantic cache entries."""
platforms = gen.load_platforms()
for key in ("aider", "devin"):
body = gen.render(platforms[key])[0].content
assert ".graphify_uncached.txt').read_text(" in body
assert "allowed_source_files=uncached" in body
def test_generated_runbooks_pass_root_to_save_manifest():
"""#1417: every save_manifest call in a shipped runbook threads root=.