fix(6477): a body uses a canon by name only when the name can resolve to it
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / TypeScript typecheck (push) Successful in 43s
CI & Build / integration (push) Successful in 1m36s
CI & Build / Python tests (push) Successful in 2m7s
CI & Build / Build & push image (push) Successful in 42s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / TypeScript typecheck (push) Successful in 43s
CI & Build / integration (push) Successful in 1m36s
CI & Build / Python tests (push) Successful in 2m7s
CI & Build / Build & push image (push) Successful in 42s
The proposer's reference basis, and every uses edge it writes, counted any word-bounded mention of a canon's symbol. Three holes made that wrong at scale (snippet #5448, symbol `file`, held 2,161 uses edges): - Go, Rust, Kotlin, Swift, Dart, C, C#, Ruby and PHP were outside the language-family maps, so their canons read as "unknown, no gate" and were matched in every Python, TS and CSS body. - Canons in other projects were matched by name, though one repo never calls a function defined in another's. - A plain word (`file`, `seen`) or a module's own helper (`_run`) matched wherever it appeared. names_canon is now the one by-name test, used by match_canon, reference_canons and the write-path hint: same project, not a name the file defines itself (unless the canon is recorded there), no generic verb with or without a leading underscore, and a bare lowercase word only where it is called. The write path keeps the payload's own names in play, since a redefinition of a pulled canon is the copy it exists to flag. Repair: record_uses only adds, so replace_reference_uses now makes a row's machine-written reference edges exactly what the current rule finds, leaving judged and hook edges alone. _PROPOSER_VERSION 7 re-reads every row on its project's next refresh. Migration 0125 deletes the cross-project reference edges already stored. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -294,6 +294,43 @@ async def test_get_snippet_carries_the_structured_consumer_map(seeded):
|
||||
assert consumers == {"instances": [], "variants": [], "uses": []}
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_a_reread_takes_back_the_reference_edges_a_looser_rule_wrote(seeded):
|
||||
"""record_uses only adds; a tightened by-name rule must also remove what
|
||||
the old rule wrote. A judged edge on the same row survives."""
|
||||
from grimoire.services import snippets as snippets_svc
|
||||
from grimoire.services.shape_ledger import record_uses, replace_reference_uses
|
||||
|
||||
owner, pid, sid = seeded["owner"], seeded["pid"], seeded["snippet"]
|
||||
helper = await snippets_svc.create_snippet(
|
||||
owner, name="cls_reread_helper", code="def hash_token(raw):\n return raw\n",
|
||||
language="python", repo="Widget", path="src/hash.py", symbol="hash_token",
|
||||
project_id=pid,
|
||||
)
|
||||
hid = int(helper.id)
|
||||
|
||||
async def make_app_row(s):
|
||||
return (await s.execute(select(CodeShape).where(
|
||||
CodeShape.project_id == pid, CodeShape.symbol == "make_app",
|
||||
))).scalar_one()
|
||||
|
||||
async with async_session() as s:
|
||||
await record_uses(s, await make_app_row(s), [sid, hid], basis="reference")
|
||||
await s.commit()
|
||||
await classify_shapes(owner, pid, [
|
||||
{"path": "src/app.py", "symbol": "make_app", "status": "exempt",
|
||||
"reason": "its own thing", "uses": [hid]},
|
||||
], via="audit")
|
||||
|
||||
async with async_session() as s:
|
||||
await replace_reference_uses(s, await make_app_row(s), [])
|
||||
await s.commit()
|
||||
_, n_sid = await list_project_shapes(owner, pid, uses=sid)
|
||||
rows_hid, n_hid = await list_project_shapes(owner, pid, uses=hid)
|
||||
assert n_sid == 0
|
||||
assert n_hid == 1 and rows_hid[0].symbol == "make_app"
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_sync_refiles_rows_whose_snippet_was_purged(seeded):
|
||||
"""The SET NULL companion: a judgment whose target is hard-deleted
|
||||
|
||||
Reference in New Issue
Block a user