From 9b1597a3c92158bd059ed0b159e2dc131746fa82 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 19 Aug 2026 19:37:18 -0400 Subject: [PATCH] feat(ledger): coverage refresh feeds the shape ledger; the readout inverts to accounting (#2788, milestone 294 step 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit compute_coverage is now the ledger's sync point: every walk upserts the extracted shapes (new → unclassified, the todo state; surviving → last-seen bump; vanished → stamped, kept as history), re-files judgments whose snippet target went away, and mechanically stamps snippet reference locations as canonical — the one always-safe rule, self-healing only for its own stamps (an agent's judgment is never unwound by machinery). The covering predicate moves to shape_ledger.location_covers as the single home (match_shapes retired with its consumer); coverage's payload and line invert from 'N/M shapes recorded' to shape ACCOUNTING per note 2786: accounted/total with a canonical·instance·variant·exempt breakdown, and unclassified — THE todo — with its largest directories. Cache key bumps to v2 so pre-ledger blobs honestly read 'not measured yet' instead of rendering in a shape no longer spoken. Readout is deliberately project-wide (all repos' live rows), while the walk serves whichever repos the owner's keyring reaches this refresh. Integration tests pin the new contract: rows for every extracted shape, mechanical canonical stamps carrying snippet ids, idempotent recompute, agent judgments surviving recompute AND vanish/return, vanished rows leaving the readout but keeping their history. Co-Authored-By: Claude Fable 5 --- frontend/src/views/ProjectView.vue | 36 ++++-- src/scribe/mcp/tools/projects.py | 13 +- src/scribe/routes/projects.py | 2 +- src/scribe/services/coverage.py | 185 +++++++++++++++------------- src/scribe/services/shape_ledger.py | 176 ++++++++++++++++++++++++++ tests/test_pattern_coverage.py | 144 +++++++++++++++++----- 6 files changed, 427 insertions(+), 129 deletions(-) create mode 100644 src/scribe/services/shape_ledger.py diff --git a/frontend/src/views/ProjectView.vue b/frontend/src/views/ProjectView.vue index 0076373..906ab7e 100644 --- a/frontend/src/views/ProjectView.vue +++ b/frontend/src/views/ProjectView.vue @@ -424,15 +424,17 @@ async function loadNotes() { interface CoverageGap { dir: string; - uncovered: number; + unclassified: number; total: number; } interface Coverage { total: number; - recorded: number; + accounted: number; + unclassified: number; + counts: Record; estimate: boolean; computed_at: string; - repos: { repo: string; ref: string; total: number; recorded: number }[]; + repos: { repo: string; ref: string; total: number; accounted: number }[]; largest_gaps: CoverageGap[]; } @@ -712,32 +714,42 @@ async function confirmDelete() {

- Not measured yet — Refresh compares the bound repo's definitions - against recorded snippets. + Not measured yet — Refresh reads the bound repo's definitions into + the shape ledger and reports how many are classified against canon.

{{ coverageError }}