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:
@@ -169,6 +169,38 @@ async def test_rule_form_sweeps_unclassified_rows_only_and_applies_whole(seeded)
|
||||
await classify_shapes_where(other, pid, path="src", status="exempt", reason="x")
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_sync_stamps_scoped_rows_and_unstamps_when_they_become_reachable(seeded):
|
||||
"""#2869: by-construction one-offs arrive `scoped` (mechanical), count as
|
||||
accounted, are reached by the sweep's default, and go back to the todo
|
||||
if a later tree makes them ordinary. A judgment overrides the stamp."""
|
||||
from scribe.services.coverage import ArchiveShape
|
||||
owner, pid, sid = seeded["owner"], seeded["pid"], seeded["snippet"]
|
||||
scoped_shapes = [
|
||||
ArchiveShape("web/Card.vue", "css", "card", ".card {", "s1", ".card { x: 1 }", True),
|
||||
ArchiveShape("web/Card.vue", "sym", "load", "function load() {", "s2", "function load() {}", True),
|
||||
ArchiveShape("src/util.py", "sym", "helper", "def helper():", "s3", "def helper(): pass", False),
|
||||
]
|
||||
await sync_repo_shapes(pid, REPO, scoped_shapes, seen_marker="main")
|
||||
rows, _ = await list_project_shapes(owner, pid, path="web/Card.vue")
|
||||
assert {r.status for r in rows} == {"scoped"}
|
||||
assert all(r.classified_by == "mechanical" and "by construction" in (r.reason or "") for r in rows)
|
||||
# The human todo excludes them; the sweep's default still reaches them.
|
||||
assert (await list_project_shapes(owner, pid, status="unclassified", path="web/Card.vue"))[1] == 0
|
||||
out = await classify_shapes_where(
|
||||
owner, pid, path="web/Card.vue", status="instance", snippet_id=sid, kind="css",
|
||||
)
|
||||
assert out["classified"] == 1
|
||||
# Re-synced as ordinary: the stamped sym returns to the todo; the
|
||||
# judged css keeps its judgment.
|
||||
plain = [ArchiveShape(s.path, s.kind, s.name, s.signature, s.body_sha, s.body, False) for s in scoped_shapes]
|
||||
await sync_repo_shapes(pid, REPO, plain, seen_marker="main")
|
||||
rows, _ = await list_project_shapes(owner, pid, path="web/Card.vue")
|
||||
by_symbol = {r.symbol: r for r in rows}
|
||||
assert by_symbol["load"].status == "unclassified" and by_symbol["load"].classified_by is None
|
||||
assert by_symbol["card"].status == "instance" and by_symbol["card"].snippet_id == sid
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_list_filters_compose(seeded):
|
||||
owner, pid, sid = seeded["owner"], seeded["pid"], seeded["snippet"]
|
||||
|
||||
Reference in New Issue
Block a user