feat(ledger): CSS derive families are names, never bodies — name floor 2 for css, dup: grouping sym-only; derive line says "repeated name" and dismisses scoped-css; plugin 0.1.41 (note #2917)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / integration (push) Successful in 25s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Python tests (push) Successful in 1m0s
CI & Build / Build & push image (push) Successful in 25s

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 00:21:17 -04:00
co-authored by Claude Fable 5
parent a2b377b74d
commit 85111442a6
9 changed files with 104 additions and 43 deletions
+19 -9
View File
@@ -923,6 +923,13 @@ async def stamp_write_path_instances(
# recur by convention, not by duplication).
_DERIVE_MIN_DUP = 2
_DERIVE_MIN_NAME = 3
# CSS is never grouped by body (note 2917): classes for different purposes
# share declarations because the style system makes them alike — `.text-muted`
# and `.pin-badge-auto` carrying the same `color: var(--fs-text-tertiary)` are
# two meanings, not two copies. A CSS family is a NAME defined in more than
# one file: that is a recipe living in several places, and two is already
# the signal (a class name is deliberate in a way `setup`/`load` are not).
_DERIVE_MIN_NAME_CSS = 2
# Semantic checks per repo per refresh — an embedding each (local fastembed),
# bounded so a 4,000-row ledger is worked through over refreshes, not in one.
_SEMANTIC_CAP = 150
@@ -1298,15 +1305,16 @@ def derive_groups(
rows: Iterable[tuple[str, str, str, str]]
) -> dict[tuple[str, str, str], str]:
"""The derive-first grouping over (path, kind, symbol, body_sha) rows
that matched no canon: {(path, kind, symbol): group_key}. Identical
bodies in ≥2 places group as `dup:<sha>`; the same name defined in ≥3
files groups as `name:<kind>:<symbol>`; a row joins at most one group,
the copy before the name."""
that matched no canon: {(path, kind, symbol): group_key}. For code
(kind `sym`) identical bodies in ≥2 places group as `dup:<sha>` and the
same name defined in ≥3 files groups as `name:sym:<symbol>`, the copy
before the name. CSS groups by name only — the same class defined in
≥2 files is `name:css:<symbol>`; its body never groups it (note 2917)."""
by_sha: dict[str, list[tuple[str, str, str]]] = {}
by_name: dict[tuple[str, str], list[tuple[str, str, str]]] = {}
for path, kind, symbol, sha in rows:
key = (path, kind, symbol)
if sha:
if sha and kind != "css":
by_sha.setdefault(sha, []).append(key)
by_name.setdefault((kind, _norm_symbol(symbol)), []).append(key)
out: dict[tuple[str, str, str], str] = {}
@@ -1315,7 +1323,8 @@ def derive_groups(
for key in keys:
out.setdefault(key, f"dup:{sha}")
for (kind, symbol), keys in by_name.items():
if len({k[0] for k in keys}) >= _DERIVE_MIN_NAME:
floor = _DERIVE_MIN_NAME_CSS if kind == "css" else _DERIVE_MIN_NAME
if len({k[0] for k in keys}) >= floor:
for key in keys:
out.setdefault(key, f"name:{kind}:{symbol}")
return out
@@ -1606,9 +1615,10 @@ async def write_time_derive(
named at ``path``, what the ledger already knows about that name
elsewhere in the project —
family the name sits in a derive-first group (identical body in N
files, or the same name in ≥3): "this is a known duplicate
family with no canon — derive it now, don't add a copy";
family the name sits in a derive-first group (code: identical body
in N files or the same name in ≥3; CSS: the same class in
≥2 files, note 2917): "this is a known family with no canon
— derive it now, don't add a copy";
canon a `canonical` row of that name at another path: "this is
canon #N at <path> — reuse, don't redefine".