feat(write-path): the derive arm — the hint names a duplicate family (no canon) or a canon elsewhere for the shapes being written; exclude_derive channel (#2900, milestone 299 step 2)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Failing after 9s
CI & Build / integration (push) Successful in 25s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Python tests (push) Successful in 58s
CI & Build / Build & push image (push) Successful in 23s
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Failing after 9s
CI & Build / integration (push) Successful in 25s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Python tests (push) Successful in 58s
CI & Build / Build & push image (push) Successful in 23s
shape_ledger.write_time_derive asks the ledger what it knows about each named (kind, symbol): a derive-grouped family (identical body / same name in N other files) -> "derive it now, do not add a copy"; a canonical row at another path -> "canon #N at <path>, reuse". Judged rows at the path and the canon own file stay silent. Rendered by _derive_line beside the divergence line; keyed (group id / canon:<id>) on a third per-session dedup channel in the hook (.derive.ids -> exclude_derive=). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -597,6 +597,49 @@ async def test_derive_groups_land_on_rows_and_in_the_summary(seeded):
|
||||
assert {r.symbol for r in rows} == {"slug"} # 2 files < the name floor
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_write_time_derive_names_the_family_or_the_canon_for_a_name(seeded):
|
||||
"""#2900: against real rows — a name in a dup family → the family (other
|
||||
files, count); a name whose canonical row lives elsewhere → that canon;
|
||||
a judged row at the path, the canon's own file, or an unknown name →
|
||||
silence."""
|
||||
from scribe.services.shape_ledger import apply_derive_groups, write_time_derive
|
||||
|
||||
owner, pid, sid = seeded["owner"], seeded["pid"], seeded["snippet"]
|
||||
defs = _defs(
|
||||
("v/A.vue", "css", "log-empty", ".log-empty {", ".log-empty { color: red }"),
|
||||
("v/B.vue", "css", "log-empty", ".log-empty {", ".log-empty { color: red }"),
|
||||
("v/C.vue", "css", "log-empty", ".log-empty {", ".log-empty { color: red }"),
|
||||
("src/factory.py", "sym", "factory", "def factory():", "def factory():\n return 1"),
|
||||
)
|
||||
await sync_repo_shapes(pid, REPO, defs, seen_marker="m1")
|
||||
await classify_shapes(owner, pid, [
|
||||
{"path": "src/factory.py", "symbol": "factory", "status": "canonical", "snippet_id": sid},
|
||||
])
|
||||
assert await apply_derive_groups(pid) >= 3
|
||||
|
||||
# A 4th copy about to be written → the family, naming the other files.
|
||||
out = await write_time_derive(pid, "v/D.vue", [("css", "log-empty"), ("css", "unknown")])
|
||||
assert len(out) == 1 and out[0]["symbol"] == "log-empty" and out[0]["kind"] == "css"
|
||||
fam = out[0]["family"]
|
||||
assert fam["identical"] is True and fam["label"] == ".log-empty"
|
||||
assert fam["files"] == ["v/A.vue", "v/B.vue", "v/C.vue"] and fam["file_count"] == 3
|
||||
assert out[0]["key"] == fam["group"] and fam["group"].startswith("dup:")
|
||||
# Editing one existing member still names the OTHER members.
|
||||
out = await write_time_derive(pid, "v/A.vue", [("css", "log-empty")])
|
||||
assert out[0]["family"]["files"] == ["v/B.vue", "v/C.vue"] and out[0]["family"]["size"] == 3
|
||||
# The canon's name elsewhere → the canon; in the canon's own file → silence.
|
||||
out = await write_time_derive(pid, "src/other.py", [("sym", "factory")])
|
||||
assert out == [{"symbol": "factory", "kind": "sym", "key": f"canon:{sid}",
|
||||
"canon": {"snippet_id": sid, "path": "src/factory.py", "label": "factory"}}]
|
||||
assert await write_time_derive(pid, "src/factory.py", [("sym", "factory")]) == []
|
||||
# A judged row at the path is not re-litigated.
|
||||
await classify_shapes(owner, pid, [
|
||||
{"path": "v/B.vue", "symbol": "log-empty", "status": "exempt", "reason": "print sheet"},
|
||||
])
|
||||
assert await write_time_derive(pid, "v/B.vue", [("css", "log-empty")]) == []
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_derive_new_names_the_copy_that_joined_a_family_since_the_stamp(seeded):
|
||||
"""#2899: the first sync seeds one `slug`; a later sync adds an identical
|
||||
|
||||
Reference in New Issue
Block a user