fix(shapes): weak stamps elect no canon; the arrival line names the review; Svelte scopes by default (#4608)
CI & Build / Python lint (push) Successful in 8s
CI & Build / Plugin hooks (push) Successful in 16s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 1m3s
CI & Build / Python tests (push) Successful in 1m44s
CI & Build / Build & push image (push) Successful in 1m5s

Librarian and Stash had 132 and 488 write-path stamps written at 0.68-0.72,
before the 0.80 floor (#4204). Nothing re-judged them, and dominant_canon
counted them, so a YAML CI snippet (#3410) "dominated" Librarian's web
directory and every write there was told it diverged from it — 1408 flags
on one project, 902 on the other, all skimmed past.

- is_weak_stamp: one predicate for "hook-stamped below today's floor".
  dominant_canon and canon_form skip such rows; stamps_to_review lists them
  by the same predicate. No stored row changes — they stay for judgment.
- flag_divergence withdraws a standing flag whose canon no longer dominates
  its directory. A flag is a mechanical prompt, not a judgment.
- The coverage line ends "N weak stamps · M incoherent canons to judge —
  stamps_to_review" when either is nonzero, so a project's own session sees
  the queue on arrival. The shape-accounting skill says what to do with it.
- scoped_definitions handles .svelte: every <style> is component-scoped
  unless <style global> or :global(...); instance-script syms are scoped,
  module-script ones stay ordinary.

Plugin version minted for the skill change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-30 23:27:07 -04:00
co-authored by Claude Opus 5.5
parent 3270fe90c1
commit eb5cc6d3a7
7 changed files with 291 additions and 12 deletions
+43
View File
@@ -823,6 +823,49 @@ def test_scoped_definitions_are_vue_script_setup_and_scoped_style_only():
assert scoped_definitions("src/a.py", "def load():\n pass\n", extract_definitions("def load():\n pass\n")) == set()
def test_svelte_scopes_by_default_and_its_module_script_stays_importable():
"""#4608: Svelte scopes the other way round from Vue — every <style> is
the component's own unless it opts out, and only <script module> /
<script context="module"> can be imported elsewhere. Without this a
Svelte project's every `.card` and `.title` sat in the human todo."""
from scribe.services.coverage import extract_definitions, scoped_definitions
svelte = (
"<script module lang=\"ts\">\n"
"export function stageOf(x: number) {\n return x;\n}\n"
"</script>\n\n"
"<script lang=\"ts\">\n"
"function toggle() {\n open = !open;\n}\n"
"</script>\n\n"
"<div class=\"card\"></div>\n\n"
"<style>\n.card {\n padding: 1rem;\n}\n:global(.toast) {\n color: red;\n}\n</style>\n"
)
defs = extract_definitions(svelte)
names = {(d.kind, d.name) for d in defs}
assert {("sym", "stageOf"), ("sym", "toggle"), ("css", "card")} <= names
scoped = scoped_definitions("web/src/lib/A.svelte", svelte, defs)
assert ("sym", "toggle") in scoped and ("css", "card") in scoped
assert ("sym", "stageOf") not in scoped, "a module script's export is importable"
assert not any(n == "toast" for _, n in scoped), ":global(...) opts a selector out"
# The legacy spelling of the module block, and a whole global style block.
legacy = (
"<script context=\"module\">\nexport function shared() {\n return 1;\n}\n</script>\n"
"<style global>\n.page {\n margin: 0;\n}\n</style>\n"
)
assert scoped_definitions("web/src/lib/B.svelte", legacy, extract_definitions(legacy)) == set()
def test_the_line_names_the_review_queue_and_the_tool_that_holds_it():
"""#4608: `stamps_to_review` existed and two projects never called it,
because nothing on arrival said there was anything to review."""
from scribe.services.coverage import coverage_line
base = {"accounted": 10, "total": 10, "counts": {"exempt": 10},
"unclassified": 0, "computed_at": "2026-09-30T00:00:00"}
assert "stamps_to_review" not in coverage_line(base)
line = coverage_line({**base, "weak_stamps": 132, "incoherent_canons": 3})
assert line.endswith("; 132 weak stamps · 3 incoherent canons to judge — stamps_to_review")
assert coverage_line({**base, "weak_stamps": 1}).endswith("; 1 weak stamp to judge — stamps_to_review")
@pytest.mark.integration
async def test_binding_ref_is_the_branch_the_ledger_follows(seeded):
"""#2873: a binding that names a ref is read at that ref (not the forge's