bib: Store.upsert clobbers curated tags/collections on URL-dedupe update (wipe-and-replace _sync_tags) #624

Closed
opened 2026-08-17 14:57:48 +00:00 by kert · 0 comments
Owner

Root cause of the CY2027-NPRM-missing-from-Zotero incident (see the milestone for the full chain).

Store.upsert (src/bib/store.py:207) dedupes by URL and, on the existing-item path, calls self.update(ekey, tags=item.tags, collections=item.collections) → _sync_tags (src/bib/store.py:423), which does DELETE FROM item_tags WHERE item_id = ? and rewrites only the incoming set. The # Merge tags comment merges the tags= parameter into the incoming item — it never merges with the tags already stored on the existing row. _sync_collections has the identical wipe-and-replace hazard.

Observed damage (2026-08-14): the comment-farm re-ingest (store.upsert(rule) at src/cli/bib.py:241,251) rebuilt rule items from the FR API and wiped curated tags:

  • 5ITGVDJV (CY2027 NPRM) lost sup:2027_PFS_NPRM + file:rvu + year:2027 at 05:58:13Z — added 5h earlier by fetch_nprm_addenda --year 2027 --register
  • 2KVJ2HKX (CY2026 NPRM) lost sup:2026_PFS_NPRM + file:rvu + year:2026 at 00:27:43Z
  • both sup:*_PFS_NPRM tags now have zero item associations in bib; Zotero still shows sup:2026_PFS_NPRM on 2KVJ2HKX only as a stale pre-wipe snapshot
  • this is the same drift that surfaced as the docs test failure in #623 (fixed there by making the export hermetic — symptom, not cause)
  • follow-on breakage: pfs.nprm._addendum_b_path discovers Addendum B by sup:<year>_PFS_NPRM tag (NPRM_SOURCES), so load_rvu_proposed re-runs now raise "No Addendum B attachment found" for both years

Fix: on the upsert dedupe path, union the existing row's tags and collections with the incoming ones before calling update(). Store.update(tags=...) keeps its explicit replace semantics (documented); deliberate removal stays remove_tag. Regression tests: existing curated tag survives a URL-dedupe upsert; same for collection membership.

Data repair is #625; Zotero catch-up sync is #626; nightly prevention is #627.

**Root cause of the CY2027-NPRM-missing-from-Zotero incident** (see the milestone for the full chain). `Store.upsert` (src/bib/store.py:207) dedupes by URL and, on the existing-item path, calls `self.update(ekey, tags=item.tags, collections=item.collections)` → `_sync_tags` (src/bib/store.py:423), which does `DELETE FROM item_tags WHERE item_id = ?` and rewrites only the incoming set. The `# Merge tags` comment merges the `tags=` *parameter* into the incoming item — it never merges with the tags already stored on the existing row. `_sync_collections` has the identical wipe-and-replace hazard. **Observed damage** (2026-08-14): the comment-farm re-ingest (`store.upsert(rule)` at src/cli/bib.py:241,251) rebuilt rule items from the FR API and wiped curated tags: - `5ITGVDJV` (CY2027 NPRM) lost `sup:2027_PFS_NPRM` + `file:rvu` + `year:2027` at 05:58:13Z — added 5h earlier by `fetch_nprm_addenda --year 2027 --register` - `2KVJ2HKX` (CY2026 NPRM) lost `sup:2026_PFS_NPRM` + `file:rvu` + `year:2026` at 00:27:43Z - both `sup:*_PFS_NPRM` tags now have **zero** item associations in bib; Zotero still shows `sup:2026_PFS_NPRM` on 2KVJ2HKX only as a stale pre-wipe snapshot - this is the same drift that surfaced as the docs test failure in #623 (fixed there by making the export hermetic — symptom, not cause) - follow-on breakage: `pfs.nprm._addendum_b_path` discovers Addendum B by `sup:<year>_PFS_NPRM` tag (`NPRM_SOURCES`), so `load_rvu_proposed` re-runs now raise "No Addendum B attachment found" for both years **Fix**: on the upsert dedupe path, union the existing row's tags and collections with the incoming ones before calling `update()`. `Store.update(tags=...)` keeps its explicit replace semantics (documented); deliberate removal stays `remove_tag`. Regression tests: existing curated tag survives a URL-dedupe upsert; same for collection membership. Data repair is #625; Zotero catch-up sync is #626; nightly prevention is #627.
kert added this to the P38: Zotero Rule Sync — upsert tag merge, tag repair, nightly rules scope milestone 2026-08-17 14:57:48 +00:00
kert added the bibquality labels 2026-08-17 14:57:48 +00:00
kert closed this issue 2026-08-17 15:13:22 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: homelab/stack#624