feat(ledger): the scoped bucket — by-construction one-offs are stamped by the sync, not judged by a person (#2869, milestone 294)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / TypeScript typecheck (push) Successful in 23s
CI & Build / integration (push) Failing after 25s
CI & Build / Python tests (push) Canceled after 51s
CI & Build / Build & push image (push) Canceled after 0s

The 2026-08 audit left 77% of Scribe's ledger `exempt`, most of it a Vue
component's scoped <style> rules and <script setup> functions — one-offs by
construction (unreachable from any other file) that add nothing when judged
one by one and bury the rows a person should look at.

- coverage: Definition carries its line; scoped_definitions() names, per
  .vue file, every sym and every css rule inside <style scoped>; ArchiveShape
  carries the flag.
- sync: such rows are stamped status=scoped / classified_by=mechanical with
  the by-construction reason (history event recorded); un-stamped back to
  unclassified if a later tree makes them ordinary; a judgment overrides.
- The machine still sees them: proposer, derive grouping, divergence, hook
  evidence, canonical stamping and classify_shapes_by_rule's default all
  treat unclassified + scoped as the unjudged set (_MECHANICAL_TODO). Only
  the human todo (status=unclassified) and largest_gaps exclude them.
- accounting counts `scoped`; coverage line and the project card legend show
  it; SHAPE_STATUSES gains it (no DB CHECK on status — no migration).
- shape-accounting skill documents the bucket; plugin 0.1.37.

Operator decision on #2869 (2026-08-21): keep extracting everything, stamp
mechanically, keep `exempt` a human judgment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-21 15:06:52 -04:00
co-authored by Claude Fable 5
parent 9abc4443fb
commit 1ab614bfbe
10 changed files with 172 additions and 26 deletions
+8 -2
View File
@@ -72,7 +72,12 @@ async def list_shapes(
(fed by the coverage refresh). Filters compose:
Args:
status: canonical | instance | variant | exempt | unclassified.
status: canonical | instance | variant | exempt | scoped | unclassified.
`scoped` (#2869) is the sync's mechanical stamp on one-offs by
construction (a Vue component's scoped <style> rules and its
<script setup> functions): accounted for, not judged, still
proposed against / grouped / flagged, and overridable by any
classify_shapes judgment. The human todo is `unclassified`.
path: exact file, or a directory — matches everything beneath it
(the coverage line's "largest" dirs go straight in here).
snippet_id: rows classified against this snippet — a consumer map.
@@ -162,7 +167,8 @@ async def classify_shapes_by_rule(
snippet_id: Required for instance/variant — the canon judged against.
reason: Required for variant/exempt — the why, recorded on every row.
via: "agent" (default) | "audit" | "import".
include_judged: By default only `unclassified` rows are touched — a
include_judged: By default only unjudged rows are touched —
`unclassified` and the sync's mechanical `scoped` stamp — a
sweep never silently overwrites a judgment. True re-judges every
matching live row (use to re-confirm after a recheck, or to
revise a family you judged earlier).