fix(family): the repeat trigger compares a record only with its own kind - a snippet with snippets, a note with notes (#5130)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 19s
CI & Build / TypeScript typecheck (push) Successful in 56s
CI & Build / integration (push) Successful in 1m38s
CI & Build / Python tests (push) Successful in 2m16s
CI & Build / Build & push image (push) Successful in 32s

A dated release log (a note) matched a signed-APK CI snippet at 0.83 on
shared release vocabulary and was opened as a family candidate, then came
back as a precedent. One chunk of a long narrative scores like the shape
it mentions, so a cross-kind score does not mean "the same thing made
twice". The search is filtered to the new record's kind and the loop
checks it too. Code built from an idea written elsewhere still reaches the
engine through the citation trigger and the shape ledger.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 18:32:55 -04:00
co-authored by Claude Opus 5.5
parent f006f15058
commit 5323a1fbc2
2 changed files with 39 additions and 7 deletions
@@ -278,6 +278,26 @@ async def test_a_repeat_with_no_shared_platform_is_silent(family):
assert await _idea(family["note"]) is None
async def test_a_repeat_across_kinds_is_silent(family):
"""A snippet whose only match is a NOTE is not a repeat (#5130): a dated
release log scored 0.83 against a signed-APK CI snippet on shared
vocabulary and was opened as a candidate. The stub hands back the
cross-kind hit directly, so this pins the trigger's own check, not the
search filter in front of it."""
async with async_session() as s:
snippet = Note(user_id=family["owner"], project_id=family["b"], note_type="snippet",
title="android-release lane", body="sign with the one release key")
s.add(snippet)
await s.commit()
await s.refresh(snippet)
original = await s.get(Note, family["note"])
assert original.note_type == "note"
with patch("scribe.services.embeddings.semantic_search_notes",
AsyncMock(return_value=[(0.86, original)])):
assert await family_svc.repeat_trigger(family["owner"], snippet) is None
assert await _idea(family["note"]) is None
async def test_a_milestone_closing_on_a_platform_asks_and_one_off_platform_does_not(family):
async with async_session() as s:
on_platform = Milestone(user_id=family["owner"], project_id=family["a"], title="m1")