fix(shapes): the semantic arm proposes at the write-path floor, not a private 0.8 (#4208)
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 56s
CI & Build / Python tests (push) Successful in 1m34s
CI & Build / Build & push image (push) Successful in 22s

0.8 was sized for proposals nobody reads; every semantic proposal is read
by a judge before it is confirmed. Measured, it proposed 0 of 150 while
judged instances of a canon score 0.68-0.71 - the write-path hint's own
floor asks the same question of the same documents at 0.68. The arm now
uses that floor, scans 8 hits instead of 3 (a true instance ranked 4th
behind snippets of other language families), and the proposer version
bumps to 5 so rows examined under the old floor are read again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy
This commit is contained in:
2026-09-22 08:33:01 -04:00
co-authored by Claude Opus 5
parent a875a1b2ee
commit 312dc9f6f7
3 changed files with 46 additions and 22 deletions
+28 -18
View File
@@ -1516,24 +1516,32 @@ _DERIVE_MIN_NAME_CSS = 2
# Semantic checks per repo per refresh — an embedding each (local fastembed),
# bounded so a 4,000-row ledger is worked through over refreshes, not in one.
_SEMANTIC_CAP = 150
# The semantic basis's own floor — stricter than the write-path arm's, because
# a code BODY against a prose-forward snippet document scores 0.680.75 for
# "both are about migrations"; first live run paired every alembic
# upgrade()/downgrade() with an unrelated canon at exactly that band.
_SEMANTIC_FLOOR = 0.8
# How many above-floor hits the semantic arm asks for.
_SEMANTIC_LIMIT = 3
# A MISS FROM THIS ARM IS NOT EVIDENCE, and nothing may read it as one (#4208).
# The semantic arm has NO floor of its own: it uses the write-path surface's,
# because it asks the write-path hint's question — "which canon does this body
# resemble?" — of the same snippet documents (#4208).
#
# It had one, 0.8, set after the first live run paired alembic
# upgrade()/downgrade() with unrelated canons at 0.680.75. That floor was
# sized for a proposal nobody reads, and nobody-reads is not how proposals are
# consumed: a judge reviews each semantic one (confirm_proposals refuses an
# unnamed batch, and the tool says "semantic deserves a look"). Measured on
# 2026-09-22 it proposed 0 of 150, while judged instances of the service-unit
# canon score 0.680.71 against it. A wrong proposal costs the judge a look; a
# floor that yields nothing costs the signal. Noise in this band is expected —
# the score rides on the proposal so the judge can weigh it.
#
# How many hits the arm scans for an ALLOWED canon. Wider than the hint's
# budget because disallowed snippets (other language families) share the
# ranking: one measured true instance sat 4th, behind three it could not use.
_SEMANTIC_LIMIT = 8
# A MISS FROM THIS ARM IS NOT EVIDENCE, and nothing may read it as one (#4208).
# #4208 briefly stored "compared, nothing cleared the floor" and let it
# withdraw divergence prompts. Measured live on 2026-09-22, with the arm's own
# query shape: judged instances of the service-unit canon (#2860) score 0.68
# 0.71 against it at best, and most fall below 0.66; helpers beside it score
# 0.660.75 against snippets they have nothing to do with. Nothing reaches
# 0.8, so the arm answers "no canon" for almost every body, true instance or
# not — a real divergence was silenced exactly as a helper was. A code body
# against a prose-forward snippet document measures the wrong field (#2518),
# and no floor separates the two bands. The arm PROPOSES on a hit; its silence
# withdraw divergence prompts. It silenced real divergences exactly as it
# silenced helpers: most judged instances of a canon score below any floor
# that keeps noise out (0.66 and under, in the measurement above), and helpers
# score 0.660.75 against snippets they have nothing to do with. A code body
# against a prose-forward snippet document measures the wrong field (#2518);
# no floor separates the two bands. The arm PROPOSES on a hit; its silence
# says nothing.
@@ -1561,7 +1569,9 @@ def _semantic_priority(row) -> tuple:
# v4: the semantic arm recorded its misses too (#4208). Retired — a miss is
# not evidence (see _SEMANTIC_LIMIT) — but the proposals themselves did not
# change, so no re-examination is owed; a stale miss basis is inert.
_PROPOSER_VERSION = 4
# v5: the semantic arm's floor dropped from 0.8 to the write-path floor (#4208),
# so rows it examined and found nothing for must be read once more.
_PROPOSER_VERSION = 5
# Signature resemblance floor, name blanked (difflib ratio) — and a length
# floor, because `def NAME():` resembles `def NAME(x):` at 0.95 while saying
# nothing; a family shape has parameters to resemble.
@@ -1810,7 +1820,7 @@ async def _semantic_canon(
query = concept_query(body) or body
hits = await semantic_search_notes(
user_id, query, limit=_SEMANTIC_LIMIT,
threshold=max(WRITEPATH_DEFAULT_THRESHOLD, _SEMANTIC_FLOOR),
threshold=WRITEPATH_DEFAULT_THRESHOLD,
note_type="snippet", scope="browse",
)
for score, note in hits: