PR3-C: v2-only oclmap (drop allCandidates + legacy load/save)#35
PR3-C: v2-only oclmap (drop allCandidates + legacy load/save)#35paynejd wants to merge 3 commits into
Conversation
…allCandidates + legacy load/save After the v1->v2 candidates migration (ocl_issues#2540) runs in the maintenance window, oclmap reads/writes only the v2 wire format (mapper_schema_version: 2 + concept_definitions + rows). Changes: - onSave: serialize rowMatchState + conceptCache directly to v2. No more legacy candidates array. - fetchAndSetProject: deserialize v2 directly into rowMatchState + conceptCache. No more normalizeLegacyAllCandidates round-trip. - Deleted: post-load re-normalize-on-canonical-resolve effect, allCandidates state, allCandidatesRef, setAllCandidates writes across the bulk-match/bulk-bridge/bulk-scispacy/per-row/onResponse paths. - Deleted: normalizeLegacyAllCandidates from normalizers.js + its test file. - Deleted: UNIFIED_MODEL_ENABLED flag (always true after PR2b). - Translated 49 allCandidates callsites to read from rowMatchState + conceptCache. A small derivedAllCandidates() helper preserves the v1-shape projection for CSV-export readers that haven't yet been refactored to consume rowMatchState directly. Net -267 LOC. DO NOT MERGE until the migration script (oclmap#34) has been run against prod. Until then, this code reads empty for every project. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
paynejd
left a comment
There was a problem hiding this comment.
Review of the two follow-up commits (21f42b7, 7e857a5). Both are correct and fix real bugs — setConfigure(false) removes a dangling loadProjectContext ReferenceError on project load, and the conceptBelongsToTargetRepo relative-URL fallback recovers candidates whose migrated/derived canonical no longer equals the live target_repo.canonical_url. Tests 136/136, eslint clean.
Four polish suggestions below (none blocking). A and D are quick wins; B+C align an inconsistent guard and fix a now-false comment.
| return url.endsWith('/') ? url : `${url}/` | ||
| } | ||
| const normalizeCanonicalUrl = (url) => { | ||
| if(typeof url !== 'string') return '' |
There was a problem hiding this comment.
A — empty-string canonicals compare equal (latent). normalizeCanonicalUrl('') returns '/', not '', which defeats the !== '' guard in canonicalUrlsEqual — so canonicalUrlsEqual('', '') is true, and two concepts with empty canonical URLs are wrongly treated as target-repo members. Verified by exercising the helper directly. Mirror normalizeRelativeUrl's empty-string guard; after this the two helpers are identical and could be merged into one.
| if(typeof url !== 'string') return '' | |
| if(typeof url !== 'string' || url === '') return '' |
| if(canonicalUrlsEqual(conceptDefinition?.reference?.url, targetCanonical)) return true | ||
| const relativeUrl = normalizeRelativeUrl(targetRelativeUrl) | ||
| const oclUrl = conceptDefinition?.ocl_url || '' | ||
| return relativeUrl !== '' && typeof oclUrl === 'string' && oclUrl.startsWith(relativeUrl) |
There was a problem hiding this comment.
D — dead check. oclUrl is already coalesced to a string by || '' on the line above, so typeof oclUrl === 'string' is always true. Drop it.
| return relativeUrl !== '' && typeof oclUrl === 'string' && oclUrl.startsWith(relativeUrl) | |
| return relativeUrl !== '' && oclUrl.startsWith(relativeUrl) |
| // ConceptDefinition.reference.url, so the comparison is exact. | ||
| const isTargetRepoView = (view) => { | ||
| if(!targetCanonical) return true |
There was a problem hiding this comment.
B — stale comment + C — guard inconsistency. This comment now contradicts the code: the comparison is no longer exact — that's the whole point of conceptBelongsToTargetRepo's relative-URL fallback. And this guard checks only !targetCanonical, whereas the sibling guards in qualityRowViews, Concept.isMappable, and pickTopRowView use !targetCanonical && !targetRelativeUrl. So if canonical is ever absent but relative_url is present, the table Action column would render MapButtons on every row (including bridge intermediaries). Align both:
| // ConceptDefinition.reference.url, so the comparison is exact. | |
| const isTargetRepoView = (view) => { | |
| if(!targetCanonical) return true | |
| // ConceptDefinition.reference.url in the common case; the comparison also | |
| // tolerates canonical drift via the OCL relative-URL fallback below. | |
| const isTargetRepoView = (view) => { | |
| if(!targetCanonical && !targetRelativeUrl) return true |
Summary
Closes OpenConceptLab/ocl_issues#2541. Companion to the v1->v2 migration script in oclmap#34.
Draft until the v1->v2 migration runs against prod in the maintenance window. Until then, this code reads empty for every project (no `mapper_schema_version: 2` marker on existing blobs).
After the migration + this PR ship together, oclmap reads/writes only the v2 wire format. ~−267 LOC across `MapProject.jsx` + `normalizers.js` + one deleted test file.
What changes
Test plan
Notes for review
🤖 Generated with Claude Code