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
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:
@@ -258,7 +258,7 @@ async def test_coverage_measures_the_tree_exactly_and_caches(seeded):
|
||||
assert coverage["accounted"] == 2
|
||||
assert coverage["unclassified"] == 2
|
||||
assert coverage["counts"] == {
|
||||
"canonical": 2, "instance": 0, "variant": 0, "exempt": 0,
|
||||
"canonical": 2, "instance": 0, "variant": 0, "exempt": 0, "scoped": 0,
|
||||
}
|
||||
assert coverage["estimate"] is True
|
||||
assert coverage["repos"] == [{
|
||||
@@ -500,3 +500,31 @@ def test_coverage_line_names_divergence_and_recheck():
|
||||
assert line.endswith("; 1 judged shape changed since judged — recheck")
|
||||
assert "DIVERGENT" not in coverage_line(base)
|
||||
assert "recheck" not in coverage_line(base)
|
||||
|
||||
|
||||
def test_scoped_definitions_are_vue_script_setup_and_scoped_style_only():
|
||||
"""#2869: one-offs by construction — every sym in a .vue and every css
|
||||
rule inside <style scoped>; an unscoped <style> block and non-.vue files
|
||||
stay ordinary."""
|
||||
from scribe.services.coverage import extract_definitions, scoped_definitions
|
||||
vue = (
|
||||
"<script setup lang=\"ts\">\n"
|
||||
"function load() {\n return 1;\n}\n"
|
||||
"const save = async () => {\n return 2;\n};\n"
|
||||
"</script>\n\n"
|
||||
"<template><div class=\"card\"/></template>\n\n"
|
||||
"<style scoped>\n.card {\n padding: 1rem;\n}\n.title {\n margin: 0;\n}\n</style>\n"
|
||||
"<style>\n.global-toast {\n color: red;\n}\n</style>\n"
|
||||
)
|
||||
defs = extract_definitions(vue)
|
||||
names = {(d.kind, d.name) for d in defs}
|
||||
assert {("sym", "load"), ("sym", "save"), ("css", "card"), ("css", "title"), ("css", "global-toast")} <= names
|
||||
scoped = scoped_definitions("frontend/src/views/A.vue", vue, defs)
|
||||
assert scoped == {("sym", "load"), ("sym", "save"), ("css", "card"), ("css", "title")}
|
||||
# Definitions know their line, which is what the scoped-style range uses.
|
||||
assert next(d for d in defs if d.name == "card").line > next(d for d in defs if d.name == "save").line
|
||||
# Not a .vue: nothing is scoped, whatever it contains.
|
||||
assert scoped_definitions("frontend/src/assets/components.css", ".card {\n x: 1;\n}\n",
|
||||
extract_definitions(".card {\n x: 1;\n}\n")) == set()
|
||||
assert scoped_definitions("src/a.py", "def load():\n pass\n", extract_definitions("def load():\n pass\n")) == set()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user