feat(embeddings): every vector records the model whose space it lives in (#4132)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 14s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 1m1s
CI & Build / Python tests (push) Successful in 1m40s
CI & Build / Build & push image (push) Canceled after 27s

The four embedding tables stamped chunker_version but not the model, and
vector(384) is a width, not an identity: a same-width model swap would
write a second geometry beside the first with no error.

- embedding_model on note/rule/milestone/system embeddings (0109; existing
  rows stamped with the only model any install has ever run).
- Every write stamps EMBEDDING_MODEL; every backfill's "current" test is
  is_current_stamp(), both halves of calibration_stamp().
- migrate_floor refuses while any row its surface searches is off the live
  model, before sampling: re-embed, then migrate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-23 19:02:30 -04:00
co-authored by Claude Opus 5.5
parent 11b286d786
commit f4e9cd429b
10 changed files with 178 additions and 10 deletions
+34
View File
@@ -15,6 +15,9 @@ WHAT THIS PINS
mid-backfill would end up with every bar at zero.
4. **Every registry surface can be migrated.** A seventh arm that nobody adds
a re-scorer for is one whose floor silently cannot survive a model change.
5. **A half-migrated corpus is a refusal (#4132).** While any row the surface
searches is stamped with another model, a re-score measures a blend of two
geometries — so nothing is sampled until the backfill has finished.
"""
from unittest.mock import AsyncMock, MagicMock, patch
@@ -43,11 +46,42 @@ def _session_with(rows):
return session
@pytest.fixture(autouse=True)
def _corpus_on_the_live_model():
"""Every test below starts from a wholly re-embedded corpus; the one that
is about a half-migrated corpus patches this again."""
with patch.object(rm, "rows_off_the_live_model", AsyncMock(return_value=0)):
yield
def test_every_surface_has_a_rescorer():
"""Otherwise a surface's floor cannot cross a model change at all."""
assert set(rm._RESCORERS) == set(SURFACES)
def test_every_surface_names_the_corpus_it_searches():
"""Otherwise the half-migrated check has no table to count for it."""
assert set(rm._CORPUS) == set(SURFACES)
@pytest.mark.asyncio
async def test_a_corpus_part_way_through_a_model_change_refuses_before_sampling():
rows = _logs([("q1", None, 0.9), ("q2", None, 0.1)])
rescore = AsyncMock(return_value=0.4)
with patch.object(rm, "rows_off_the_live_model", AsyncMock(return_value=17)) as off, \
patch.object(rm, "async_session", MagicMock(return_value=_session_with(rows))), \
patch.object(rm, "floor_for", AsyncMock(return_value=0.5)), \
patch.object(rm, "set_dial", AsyncMock()) as set_dial, \
patch.dict(rm._RESCORERS, {"prompt_rule": rescore}):
out = await rm.migrate_floor(1, "prompt_rule", apply=True)
assert out["migrated"] is False
assert out["rows_off_model"] == 17
assert off.await_args.args[0] is rm.RuleEmbedding
rescore.assert_not_called()
set_dial.assert_not_called()
def test_the_floor_that_admits_a_fraction_is_an_observed_score():
scores = [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.05]
# 30% of ten is three; the third-best score is the bar that admits exactly