Conversation
…nt collision resolveEntityForClaim auto-created cultivar entities with a plain INSERT. When a cultivar already existed under a DIFFERENT (typo/synonym duplicate) species parent — e.g. two "Fragaria × ananassa" rows differing only by the × vs x glyph, which COLLATE NOCASE doesn't fold — the parent-scoped lookup missed it and the INSERT collided on UNIQUE(scientific_name, variety_name), rolling back the ENTIRE promote transaction (0 rows promoted). Fix mirrors getOrCreateEntity's collision-safe pattern: INSERT OR IGNORE + a compound-scientific_name fallback lookup, so the claim attaches to the existing cultivar instead of crashing. Duplicate species rows remain a separate dedup concern (both stay needs_dedup=1). TDD: reproduces the exact SQLITE_CONSTRAINT in-memory with the composite unique index; promote-staged-claims.test.js 15/15 green. Surfaced while promoting 7,065 UC IPM Pest Management Guideline claims (33 sources — the known-biocontrol denominator). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
resolveEntityForClaimauto-creates cultivar entities with a plainINSERT. When a cultivar already exists under a different species parent than the claim's species name resolves to, the parent-scoped lookup misses it and theINSERTcollides onUNIQUE(scientific_name, variety_name)— aborting the entire promote transaction (0 rows promoted, everything rolled back).This is triggered by duplicate species rows that
COLLATE NOCASEcannot fold — e.g. twoFragaria × ananassaentities differing only by the×(U+00D7) vs ASCIIxglyph. The cultivars sit under one; the species name resolves to the other.Note the asymmetry this fixes:
getOrCreateEntity(the species path) already uses a collision-safeINSERT OR IGNORE; only the variety path used a bareINSERT.Fix
Mirror the existing collision-safe pattern:
INSERT→INSERT OR IGNOREscientific_namefallback lookup, so the claim attaches to the existing cultivar rather than crashing the batch.Duplicate species rows remain a separate dedup concern (both stay
needs_dedup=1). The promote pipeline should never be hostage to one bad row.Test plan
SQLITE_CONSTRAINT: UNIQUE constraint failed: entities.scientific_name, entities.variety_namein-memory (the test DB now also creates the compositeidx_entities_name_varietyindex, matching production).node --test backend/promote-staged-claims.test.js→ 15/15 pass.Context
Surfaced while promoting 7,065 UC IPM Pest Management Guideline claims across 33 sources, where 3 strawberry cultivars ('Portola', 'San Andreas', 'Albion') aborted the whole run.
🤖 Generated with Claude Code