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
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:
@@ -1638,8 +1638,11 @@ async def test_the_write_time_divergence_check_is_named_in_band():
|
||||
1, "frontend/src/components/Danger.vue", code=REAL_CODE, project_id=24,
|
||||
stamp_shapes=[("sym", "confirmDanger")],
|
||||
)
|
||||
# The payload travels with the call now (#4204): the check compares the
|
||||
# shape being written against the canon's form, and a shape written right
|
||||
# now may exist nowhere but in this code.
|
||||
check.assert_awaited_once_with(24, "frontend/src/components/Danger.vue",
|
||||
[("sym", "confirmDanger")], [])
|
||||
[("sym", "confirmDanger")], [], REAL_CODE)
|
||||
assert out["divergence"] == div
|
||||
assert "Divergence check at `frontend/src/components/Danger.vue`" in out["context"]
|
||||
assert "`confirmDanger` → #2761 (20 of 21 judged siblings are its instances)" in out["context"]
|
||||
|
||||
Reference in New Issue
Block a user