feat(ledger): derive readout ranks body-identical groups first; CSS fingerprints are declarations, not selectors (#2872, milestone 294)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Failing after 25s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 57s
CI & Build / Build & push image (push) Successful in 32s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Failing after 25s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 57s
CI & Build / Build & push image (push) Successful in 32s
The 2026-08 audit consolidated identical bodies under different names and files (five auth views' CSS, two Workspace formatDate()s, four modal blocks) while the derive readout led with name groups (to_dict ×25, main ×5, load ×6) that were convention or coincidence. - proposal_summary ranks dup:<sha> groups above name groups, wider file spread first, and carries `files`; scoped rows (#2869) are in the readout, since that is where view-level copies live. - extract_definitions fingerprints a CSS rule by its declarations — the row identity already carries the selector — so .closed-msg / .error-block / .success-msg with one body are one dup group. One-time effect: judged css rows whose stored fingerprint predates this may show a recheck on the next refresh (the judgment stands; re-confirm). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -468,6 +468,11 @@ def test_extract_definitions_fingerprints_each_block():
|
||||
# And the identity view is unchanged for the hook mirror.
|
||||
from scribe.services.coverage import extract_shapes
|
||||
assert extract_shapes(text) == [(d.kind, d.name) for d in extract_definitions(text)]
|
||||
# A CSS rule's fingerprint is its declarations (#2872): the same body
|
||||
# under another selector is the same shape to the derive grouping.
|
||||
css = ".closed-msg {\n text-align: center;\n padding: 0.5rem 0;\n}\n.error-block {\n text-align: center;\n padding: 0.5rem 0;\n}\n.other {\n text-align: left;\n}\n"
|
||||
d = {x.name: x for x in extract_definitions(css)}
|
||||
assert d["closed-msg"].body_sha == d["error-block"].body_sha != d["other"].body_sha
|
||||
|
||||
|
||||
def test_coverage_line_names_the_proposers_standing():
|
||||
|
||||
@@ -317,6 +317,32 @@ def test_derive_groups_copy_before_name_with_floors():
|
||||
assert ("i.py", "sym", "one") not in g
|
||||
|
||||
|
||||
def test_proposal_summary_ranks_body_identical_groups_first_and_sees_scoped_rows():
|
||||
"""#2872: dup groups (the real copies) outrank name groups (usually
|
||||
convention), wider spread first; #2869: scoped rows are in the readout."""
|
||||
from scribe.models.code_shape import CodeShape
|
||||
from scribe.services.shape_ledger import proposal_summary
|
||||
|
||||
def row(path, symbol, group, kind="css", status="scoped"):
|
||||
return CodeShape(project_id=2, repo_key="r", path=path, symbol=symbol, kind=kind,
|
||||
status=status, proposal_basis="derive", proposal_group=group)
|
||||
rows = [
|
||||
# a name group of 6 across 6 files
|
||||
*[row(f"v/{i}.vue", "status-badge", "name:css:status-badge") for i in range(6)],
|
||||
# a dup group of 3 across 3 files (different selector names, one body)
|
||||
row("v/Login.vue", "closed-msg", "dup:abc"), row("v/Reset.vue", "error-block", "dup:abc"),
|
||||
row("v/Forgot.vue", "success-msg", "dup:abc"),
|
||||
# a dup group of 2 in ONE file — a copy, but not across files
|
||||
row("v/A.vue", "x", "dup:def"), row("v/A.vue", "y", "dup:def"),
|
||||
# judged rows never count
|
||||
row("v/J.vue", "closed-msg", "dup:abc", status="exempt"),
|
||||
]
|
||||
out = proposal_summary(rows)
|
||||
assert [g["group"] for g in out["derive_groups"]] == ["dup:abc", "dup:def", "name:css:status-badge"]
|
||||
assert out["derive_groups"][0]["files"] == 3 and out["derive_groups"][0]["size"] == 3
|
||||
assert out["derive_groups"][0]["label"] == "closed-msg (identical body)"
|
||||
|
||||
|
||||
def test_confirm_requires_a_named_scope():
|
||||
import asyncio
|
||||
|
||||
|
||||
Reference in New Issue
Block a user