fix(retrieval): the place arm marks its repeats too, and three tests meet the new contract (#4101)
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 41s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / Python tests (push) Failing after 1m2s
CI & Build / Build & push image (push) Skipped

CI on 5c64ea0 surfaced a half-measure I had shipped and three tests pinning the
semantics it replaces.

**The half-measure.** Only the semantic arm was marking repeats; the write
path's PLACE arm still dropped a nearby snippet that was on the ledger. One
menu, two rules, decided by which arm happened to find a record — and the
marker would then read as a complete account of what the session has met while
covering half the lines. `seen` now means this call's own menu and nothing
else, so both reuse arms mark and neither withholds.

**test_session_dedup_excludes_ids_from_the_reuse_arms** asserted the drop and
the ledger going into the query. Both are the defect; it is renamed and asserts
the marker instead.

**test_a_pulled_snippet_already_seen_is_evidence_not_menu** asserted #7 was
evidence and NOT menu, with the limit widened by one to pay for the drop. The
premise was the hard exclusion; #7 is now both, and the widening is no longer
needed for it.

**test_a_record_this_arm_withheld_itself_is_not_a_near_miss** is the
interesting one. Its property still holds and its setup no longer reaches it:
a ledger repeat comes back from the search and is rendered, so nothing is
withheld and `best_available` describes the bar. The one post-search filter
left is a PULLED record this same call already listed by place — kept in the
query because `resembles` needs its score, dropped from the menu because it is
already on it — so the test is rebuilt on that, and a sibling test pins the
direction that changed, so nulling the score whenever the ledger matches
cannot pass both.

Also stubs `superseded_ids` and `owner_names_for` in the new test file, which
were reaching for Postgres in a unit job.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy
This commit is contained in:
2026-09-16 21:16:10 -04:00
co-authored by Claude Opus 5
parent f1e63d207f
commit 825491d859
3 changed files with 123 additions and 35 deletions
+19 -17
View File
@@ -1611,7 +1611,13 @@ async def build_write_path_hint(
# stay eligible here, which is the whole point of the split. Either way
# they join `seen`, so the reuse arms (where the directory query would
# surface them again) never re-list a record the sync block owns.
seen: set[int] = set(excluded)
#
# `seen` IS THIS CALL'S OWN MENU, and nothing else (#4101). It used to start
# from `excluded` — the session ledger — which folded two different claims
# into one variable: "already listed a few lines above" and "shown at some
# earlier point in the session". Only the first is a reason to stay quiet.
# The ledger is now a marker instead, on both reuse arms.
seen: set[int] = set()
synced: list[dict] = []
for item in here:
nid = int(item["id"])
@@ -1625,7 +1631,12 @@ async def build_write_path_hint(
if nid in seen:
continue
seen.add(nid)
placed.append(("nearby", item))
# MARKED HERE TOO, not just on the semantic arm, because these are one
# menu. A hint where some repeats carry `seen` and others are silently
# dropped — decided by which arm happened to find them — is worse than
# either rule applied consistently: the marker would read as a complete
# account of what the session has met before, and it would not be one.
placed.append(("nearby · seen" if nid in excluded else "nearby", item))
# The stamping feed's "actually pulled it" half (#2791). Read once, before
# the semantic arm, because the arm's query doubles as the resemblance
@@ -1657,20 +1668,11 @@ async def build_write_path_hint(
query = concept_query(query) or query
if remaining > 0 and query:
t0 = time.perf_counter()
# `seen` CARRIES TWO DIFFERENT CLAIMS, and only one of them is a reason
# to withhold (#4101). It was built as the ledger plus everything this
# call has already rendered, and the arm treated both the same way:
#
# - already in THIS menu (the sync block, the place arm) — listing it
# twice in one hint is noise with no reader it could help;
# - on the LEDGER from an earlier call — a different claim entirely,
# and the one #3750 says must be rendered rather than dropped.
#
# Splitting them is the whole change here. `in_menu` keeps its
# exclusion; the ledger becomes a marker on the line.
in_menu = seen - excluded
# Pulled-and-already-listed ids stay in the query (as evidence for
# `resembles`) but never in the menu, so the limit has to cover them.
# `seen` is this call's own menu now, which is the only thing left that
# is a reason to withhold (#4101).
in_menu = seen
pulled_in_menu = in_menu & set(pulled)
_rep_wp: dict = {}
hits = await semantic_search_notes(
@@ -1948,11 +1950,11 @@ async def build_write_path_hint(
for marker, item in menu:
# A rendered repeat is not a new surfacing (#4101) — same cut the log
# row takes, so this table and `retrieval_logs` keep agreeing about the
# same call (#3668). The place arm never reaches here with one: a nearby
# snippet on the ledger is skipped before it is ever placed.
# same call (#3668).
if int(item["id"]) in excluded:
continue
arm = "write_path_place" if marker == "nearby" else "write_path_semantic"
arm = ("write_path_place" if marker.startswith("nearby")
else "write_path_semantic")
by_arm.setdefault(arm, []).append(int(item["id"]))
for arm, ids in by_arm.items():
record_surfaced(user_id=user_id, note_ids=ids, source=arm)