fix(ledger): a canon is only urged on a shape that could be it (#4204)
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Failing after 51s
CI & Build / TypeScript typecheck (push) Successful in 55s
CI & Build / Python tests (push) Successful in 1m33s
CI & Build / Build & push image (push) Successful in 25s

Two halves of one defect, found while writing #3431 and measured on a second
project.

THE DIVERGENCE CHECK WAS A BASE RATE. `dominant_canon` answers "what is most
common in this directory" and never "is this that" — the candidate's
signature was not examined at all. With `kind` carrying only `css | sym`, a
frozen dataclass, a module constant, a sync predicate, a class and an async
service function are all siblings, so the prior was not merely the best
signal, it was the only one. Writing a registry module of pure helpers
produced five prompts to build them from the `async_session` service canon.

THE AUTO-STAMP HAD NO FLOOR. `elif sid in resembles` took any score at all:
0.69 asserted as confidently as 0.95, and the number went into the reason
line without ever being compared to anything. Worse, the score is computed
against the WHOLE PAYLOAD, so one number spoke for every symbol in the file.
On Portal that recorded `class SessionAbsent`, `def build_channel`,
`async def attach` and a dozen test functions as instances of one snippet —
17 rows under #3283, which then made that directory "canon-dense" and started
instructing every later writer in it.

The two compound: loose stamping manufactures the density the divergence
check reads as authority. Both are fixed by one primitive.

`shape_form` derives a coarse form — css / type / async-fn / fn / binding —
from the signature, on READ. `kind` is part of the row identity, so widening
that column needs a migration and a re-extract (#4204 option 2, still the
principled fix); deriving costs nothing and is reversible. Every caller asks
`shape_form`, so the day the column carries the answer it returns that.

THE BURDEN SCALES WITH THE EVIDENCE, and getting this wrong was the first
version. A by-name reference — the payload names the canon's symbol — is
strong and needs only the absence of contradiction; demanding positive
agreement there silenced it whenever a shape's definition was not in the
payload (an Edit rather than a Write), turning strong evidence into none for
a reason unrelated to the code. A resemblance score is weak and must
positively agree.

`canon_form` reads the form a canon's own judged rows agree on, and returns
unknown when they disagree. That makes the halves cooperate: a canon already
poisoned by loose stamping — Portal's #3283 — falls silent instead of
flagging anyone else.

`forms_agree` requires BOTH sides known, so an unreadable signature makes the
checks quieter rather than more confident. `_RESEMBLE_MIN` is 0.80 rather
than the retrieval floors near 0.70: those decide whether to SHOW a record,
where being wrong costs a glance; this decides whether to RECORD a claim
unattended, where being wrong misinstructs everyone who writes there after.

Caught by the tests, not by review: a first pass required `const`/`let`/`var`
before a binding, so every Python module constant read as unreadable and a
whole form was silently excluded from both checks.

Not addressed: rows already carrying a wrong snippet_id are not undone by a
guard at the point of classification (lesson #4202). Portal's 17 keep
producing dominance until something re-judges them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy
This commit is contained in:
2026-09-20 21:16:51 -04:00
co-authored by Claude Opus 5
parent e2c3a5c2b5
commit 947203fa44
4 changed files with 541 additions and 8 deletions
+265
View File
@@ -0,0 +1,265 @@
"""A canon may only be urged on a shape that could plausibly BE it (#4204).
WHAT WAS WRONG. `dominant_canon` is a base rate: it answers "what is most
common in this directory" and never "is this that". With `kind` carrying only
`css | sym`, a frozen dataclass, a module constant, a sync predicate, a class
and an async service function were all siblings, so the prior was the entire
argument — it told a registry module of pure helpers to build from the
`async_session` service canon. Upstream, the auto-stamp had no resemblance
floor at all (`elif sid in resembles`), so 0.69 asserted as confidently as
0.95, and one payload-level score was applied to every symbol in the file.
The two halves compound: loose stamping manufactures the density that the
divergence check then reads as authority. Both are fixed by the same
primitive, and it is tested here on REAL signatures taken from the ledger —
Python, Go, TypeScript and Vue — rather than invented ones, because a
classifier that only works on the examples its author imagined is the failure
this is meant to end.
The unknown case is tested hardest. `forms_agree` requires BOTH sides to be
known, so an unreadable signature makes the checks quieter rather than more
confident. A guard that treats "I cannot tell" as "match" is the shape of the
bug, not the fix.
"""
from __future__ import annotations
import pytest
from scribe.services.shape_ledger import (
FORM_UNKNOWN, canon_form, forms_agree, shape_form, signature_in,
)
class _Row:
"""A ledger row, as `canon_form` reads one."""
def __init__(self, signature, snippet_id=7, status="instance", kind="sym"):
self.signature, self.snippet_id = signature, snippet_id
self.status, self.kind = status, kind
# ── shape_form, on signatures actually in the ledger ──────────────────────
@pytest.mark.parametrize("signature,want", [
# Python
("class SessionAbsent(RuntimeError):", "type"),
("def build_channel() -> str:", "fn"),
("async def attach(self) -> None:", "async-fn"),
("async def _make_room(self, user_id: int, credential_id: int, opening) -> bool:",
"async-fn"),
("def test_version_regex_rejects_bad_formats():", "fn"),
# Go
("func NewService(pool *pgxpool.Pool, cfg *lidarrconfig.Service) *Service {", "fn"),
("type Store struct {", "type"),
# TypeScript / Vue SFC
("export function useBuild() {", "fn"),
("function offsetWords(minutes: number): string {", "fn"),
("export default class Thing {", "type"),
("interface Lesson {", "type"),
("const handler = async (req) => {", "async-fn"),
("const offset = (n) => n + 1", "fn"),
("const MAX_BUDGET = 10", "binding"),
# Unreadable
("", FORM_UNKNOWN),
(" ", FORM_UNKNOWN),
("# just a comment", FORM_UNKNOWN),
("}", FORM_UNKNOWN),
])
def test_shape_form_reads_real_signatures(signature, want) -> None:
assert shape_form(signature, "sym") == want
def test_css_is_its_own_form_regardless_of_signature() -> None:
assert shape_form(".pin {", "css") == "css"
assert shape_form("", "css") == "css"
def test_the_five_shapes_that_started_this_are_not_service_functions() -> None:
"""The concrete case. #2860 is an `async def` service unit; none of these
is one, and all five were told to build from it."""
canon = shape_form("async def create_note(user_id: int, ...):", "sym")
assert canon == "async-fn"
for sig in (
"class Point:",
"def _p(source, kind, what, **kw) -> tuple[str, Point]:",
"def get_point(source: str) -> Point | None:",
"def is_registered(source: str) -> bool:",
"def sources_expected_to_emit() -> list[str]:",
):
assert not forms_agree(shape_form(sig, "sym"), canon), sig
# ── forms_agree: unknown never matches ────────────────────────────────────
def test_two_known_equal_forms_agree() -> None:
assert forms_agree("fn", "fn")
def test_different_forms_do_not() -> None:
assert not forms_agree("fn", "async-fn")
assert not forms_agree("type", "fn")
@pytest.mark.parametrize("a,b", [
(FORM_UNKNOWN, "fn"), ("fn", FORM_UNKNOWN), (FORM_UNKNOWN, FORM_UNKNOWN),
])
def test_unknown_never_agrees_with_anything(a, b) -> None:
"""Including with itself — "I cannot tell" twice is not a match."""
assert not forms_agree(a, b)
# ── canon_form: a canon whose own rows disagree has no opinion ────────────
def test_a_canon_whose_instances_agree_asserts_that_form() -> None:
rows = [_Row("async def a():"), _Row("async def b():"), _Row("async def c():")]
assert canon_form(rows, 7) == "async-fn"
def test_a_canon_whose_instances_disagree_asserts_nothing() -> None:
"""Portal's #3283 exactly: one snippet recorded as canon for a class, a
plain def, an async def and a dozen tests. That spread is the SYMPTOM of
loose stamping, so reading it as "no opinion" makes the two fixes
cooperate — a poisoned canon falls silent instead of flagging others."""
rows = [_Row("class A:"), _Row("def b():"), _Row("async def c():")]
assert canon_form(rows, 7) == FORM_UNKNOWN
def test_a_clear_majority_still_asserts() -> None:
rows = [_Row("def a():"), _Row("def b():"), _Row("def c():"), _Row("class D:")]
assert canon_form(rows, 7) == "fn"
def test_rows_of_other_canons_and_unjudged_rows_do_not_vote() -> None:
rows = [
_Row("def a():"), _Row("def b():"), _Row("def c():"),
_Row("class X:", snippet_id=9), # another canon
_Row("class Y:", status="unclassified"), # not judged
_Row("class Z:", status="variant"), # a departure, not a vote
]
assert canon_form(rows, 7) == "fn"
def test_a_canon_with_no_readable_signatures_asserts_nothing() -> None:
assert canon_form([_Row(""), _Row(""), _Row("")], 7) == FORM_UNKNOWN
def test_a_canon_with_no_rows_at_all_asserts_nothing() -> None:
assert canon_form([], 7) == FORM_UNKNOWN
# ── signature_in: the payload is where a brand-new shape lives ────────────
CODE = '''
import re
MAX = 10
class Point:
"""A point."""
async def fetch(user_id: int) -> None:
...
def helper(x):
return x
export function useBuild() {
'''
@pytest.mark.parametrize("symbol,want_form", [
("Point", "type"),
("fetch", "async-fn"),
("helper", "fn"),
("useBuild", "fn"),
("MAX", "binding"),
])
def test_a_definition_in_the_payload_is_found(symbol, want_form) -> None:
assert shape_form(signature_in(CODE, symbol, "sym"), "sym") == want_form
def test_a_symbol_that_is_only_CALLED_is_not_a_definition() -> None:
"""The conflation worth keeping out: referencing a name is evidence of
USE, never of being that shape."""
assert signature_in("value = helper(3)\nreturn fetch(x)", "helper", "sym") == ""
def test_a_missing_symbol_yields_nothing_rather_than_a_guess() -> None:
assert signature_in(CODE, "nowhere", "sym") == ""
assert shape_form(signature_in(CODE, "nowhere", "sym"), "sym") == FORM_UNKNOWN
def test_an_empty_payload_yields_nothing() -> None:
assert signature_in("", "Point", "sym") == ""
def test_a_css_class_is_found_by_its_selector() -> None:
assert signature_in(".pin { color: red; }", "pin", "css").startswith(".pin")
assert signature_in(".pin { }", ".pin", "css").startswith(".pin")
def test_a_near_name_is_not_matched() -> None:
"""Word-bounded, so `helper` never claims `helper_two`."""
assert signature_in("def helper_two(x):\n ...", "helper", "sym") == ""
# ── The burden scales with the evidence ───────────────────────────────────
#
# Two kinds of evidence reach the stamp, and treating them alike was the
# first version of this fix and was wrong in both directions. An explicit
# by-name reference — the payload literally names the canon's symbol — is
# strong; demanding positive form agreement there silenced it whenever the
# shape's definition was not in the payload (an Edit rather than a Write),
# turning strong evidence into none for a reason unrelated to the code.
# A whole-file resemblance SCORE is weak: one number speaks for every symbol
# in the file, which is precisely how a class, an async method and a private
# helper were all recorded as instances of one snippet.
from scribe.services.shape_ledger import _stamp_allowed, forms_conflict # noqa: E402
@pytest.mark.parametrize("a,b,want", [
("fn", "type", True),
("async-fn", "fn", True),
("fn", "fn", False),
(FORM_UNKNOWN, "fn", False), # cannot contradict what you cannot read
("fn", FORM_UNKNOWN, False),
(FORM_UNKNOWN, FORM_UNKNOWN, False),
])
def test_forms_conflict_needs_both_sides_readable(a, b, want) -> None:
assert forms_conflict(a, b) is want
def test_a_named_reference_stands_unless_the_forms_contradict() -> None:
assert _stamp_allowed(2, "fn", "fn")
assert _stamp_allowed(2, FORM_UNKNOWN, "fn") # unreadable shape, strong evidence
assert _stamp_allowed(2, "fn", FORM_UNKNOWN)
assert not _stamp_allowed(2, "type", "fn") # a class is not that function
def test_a_resemblance_score_must_positively_agree() -> None:
"""The weak path, and the one that produced the mess being fixed."""
assert _stamp_allowed(1, "fn", "fn")
assert not _stamp_allowed(1, FORM_UNKNOWN, "fn")
assert not _stamp_allowed(1, "fn", FORM_UNKNOWN)
assert not _stamp_allowed(1, "type", "fn")
def test_the_portal_case_no_longer_stamps_one_canon_onto_a_whole_file() -> None:
"""A class, an async method and a sync helper in one file, against one
payload-level score. Previously all three were stamped; now the score
alone cannot carry any of them, and only a matching form could."""
canon = "async-fn"
written = [("class SessionAbsent(RuntimeError):", False),
("async def attach(self) -> None:", True),
("def _run_control_client(self, command: str) -> None:", False)]
for signature, should_stamp in written:
assert _stamp_allowed(1, shape_form(signature, "sym"), canon) is should_stamp
def test_the_resemblance_floor_is_above_the_retrieval_floors() -> None:
"""An unattended WRITE about the codebase should need more evidence than
a suggestion shown to a reader — the retrieval bars sit near 0.70."""
from scribe.services.shape_ledger import _RESEMBLE_MIN
assert _RESEMBLE_MIN >= 0.80