feat(ledger): the consumer map surfaces — every css row carries used_by on list_shapes, flag="unused-css" (the map's negative space, surfaced never deleted), derive groups and the write-path family carry consumers, the derive line says "used by N template(s)", coverage payload unused_css + the standing block; docs, SKILL, plugin 0.1.44; the two step-2 tests expected 5 edges where fan-out makes 6 (milestone 302 step 3, #2936)
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / Python lint (push) Successful in 4s
CI & Build / TypeScript typecheck (push) Successful in 38s
CI & Build / integration (push) Failing after 44s
CI & Build / Python tests (push) Successful in 1m26s
CI & Build / Build & push image (push) Successful in 31s

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 14:03:35 -04:00
co-authored by Claude Fable 5
parent ffbdf19116
commit 8664d8ad14
11 changed files with 181 additions and 28 deletions
+19 -7
View File
@@ -116,10 +116,17 @@ async def list_shapes(
classify it: instance if it should use the canon, variant with
the why if deliberate); "recheck": judged instances/variants
whose body changed since judged (the judgment stands; confirm
it again with classify_shapes, or re-judge).
it again with classify_shapes, or re-judge); "unused-css"
(milestone 302): live css rules no file's markup names — a
deletion candidate to look at, never auto-deleted (the map reads
templates only; a class built at runtime is invisible to it).
Returns {"shapes": [...], "total": N} — total counts every match, not
just this page. Each row's `classified_by` says who judged: agent /
just this page. Every css row carries `used_by` {count, paths} — the
files whose markup names its class (milestone 302, the CSS consumer
map: a scoped rule is used by its own template; a shared recipe by
many; a count of 0 is "no template names it"). Each row's
`classified_by` says who judged: agent /
audit / import are judgments; `mechanical` is the canonical stamp the
sync applies; `hook` is write-path EVIDENCE (#2791) — the session pulled
a snippet and then wrote code referencing/resembling it, so the shape
@@ -145,10 +152,12 @@ async def list_shapes(
include_vanished=include_vanished, limit=limit, offset=offset,
proposal=proposal, flag=flag, uses=uses,
)
return {
"shapes": [r.to_compact() if compact else r.to_dict() for r in rows],
"total": total,
}
shapes = [r.to_compact() if compact else r.to_dict() for r in rows]
used_by = await shape_ledger_svc.used_by_map(rows)
for row, out in zip(rows, shapes):
if row.id in used_by:
out["used_by"] = used_by[row.id]
return {"shapes": shapes, "total": total}
async def classify_shapes_by_rule(
@@ -295,7 +304,10 @@ async def refresh_pattern_coverage(project_id: int) -> dict:
Returns the accounting payload — total, accounted, counts by status,
unclassified, repos, largest_gaps, `proposed` (canon proposals awaiting
confirmation), `derive_groups` (the biggest repeats-with-no-canon
families), `derive_new` (copies that joined a family since the previous
families, each css one with `consumers` — the files whose markup
render it, milestone 302), `unused_css` (css rules no template names;
None where the map has no evidence of templates), `derive_new` (copies
that joined a family since the previous
refresh — the drift to act on now: derive the canon, don't queue an
audit), `proposer` (what this refresh examined) — plus
`pattern_coverage`, the same one-line summary enter_project carries.