"""A snippet's `data` mirror survives the GENERIC note door. `notes.data` is derived from the body. The snippet service always composed it from the field set it had just merged, so `update_snippet` was never the problem — the problem was every other way a snippet's body could be written. `update_note` is a `hasattr` loop with no snippet awareness, and both doors reach it: PATCH /api/notes/ and the MCP update_note tool. The Knowledge feed handed you that path, because a snippet card there routed to /notes/:id. The failure was silent and the wrong way round: `snippet_fields` PREFERS the mirror, so the row went on reporting its old repo/path/symbol to the location reverse lookup and to prior-art recall while displaying its new body — a record surfaced with full authority and wrong, which the drift-check docstring calls worse than having no record at all (#3128). """ import pytest from tests.helpers import drive_update_note as _update from tests.helpers import fake_note, fake_snippet OLD_MIRROR = { "name": "debounce", "language": "javascript", "locations": [{"repo": "Scribe", "path": "old/place.js", "symbol": "debounce"}], "verification": {"status": "ok", "code_sha": "abc", "checked_at": "2026-01-01"}, "provenance": {"commit_sha": "deadbeef"}, } MOVED_BODY = ( "**Locations:**\n" "- `Scribe` · `new/place.ts` · `debounce`\n\n" "```typescript\nexport const debounce = 1;\n```\n" ) @pytest.mark.asyncio async def test_a_body_write_moves_the_mirror_with_it(): note = fake_snippet(data=dict(OLD_MIRROR), project_id=None) await _update(note, body=MOVED_BODY) assert note.data["locations"] == [ {"repo": "Scribe", "path": "new/place.ts", "symbol": "debounce"} ], "the mirror still describes where the snippet used to live" assert note.data["language"] == "typescript" @pytest.mark.asyncio async def test_the_verdict_and_provenance_are_carried_not_dropped(): """Neither is in the body to parse, so recomposing must carry them. An ordinary edit must not erase the last drift check — and it needs no invalidation branch either: `code_sha` is recomputed from the new code, so a verdict stamped against the old code expires itself on read.""" note = fake_snippet(data=dict(OLD_MIRROR), project_id=None) await _update(note, body=MOVED_BODY) assert note.data["verification"] == OLD_MIRROR["verification"] assert note.data["provenance"] == OLD_MIRROR["provenance"] assert note.data["code_sha"] != OLD_MIRROR["verification"]["code_sha"] @pytest.mark.asyncio async def test_an_explicit_data_wins_over_recomposition(): """`update_snippet` composes the mirror from the merged field set it holds and passes it here. That caller knows things the body cannot be re-read for — which locations were replaced, whether provenance survives the edit — so an explicit mirror must not be recomputed out from under it.""" note = fake_snippet(data=dict(OLD_MIRROR), project_id=None) authoritative = {"name": "from the service", "locations": []} await _update(note, body=MOVED_BODY, data=authoritative) assert note.data == authoritative @pytest.mark.asyncio async def test_a_plain_note_is_left_alone(): """Only snippets carry a mirror; a note's `data` must not be invented.""" note = fake_note(note_type="note", data=None, project_id=None) await _update(note, body="just some prose") assert note.data is None @pytest.mark.asyncio async def test_a_write_that_cannot_change_the_parse_does_not_touch_the_mirror(): """Status, priority, project — none of them is an input to the body parser, so recomposing on them would be work for nothing and would rebuild a mirror from a body nobody claimed to have changed.""" note = fake_snippet(data=dict(OLD_MIRROR), project_id=None) await _update(note, project_id=4) assert note.data == OLD_MIRROR @pytest.mark.asyncio async def test_a_title_change_reaches_the_mirror_too(): """A snippet's NAME lives in its title, not its body — `parse_snippet_fields` reads both, so both are triggers.""" note = fake_snippet(data=dict(OLD_MIRROR), project_id=None) await _update(note, title="throttle — cap a callback's rate") assert note.data["name"] == "throttle" assert note.data["when_to_use"] == "cap a callback's rate"