[MC-458-J] fix(frontend): key grouped-concept cognate/similarity on the concept uid#648
Conversation
…he concept uid
Compare's buildSpeakerForm read grouped-concept cognate and similarity under
the selected member's raw csv row id (e.g. "89"), but MC-458-E's uid migration
re-keyed cognate_sets and similarity by the concept identity uid ("c-89"). So
every multi-member (e.g. cross-survey) concept showed a blank cognate letter
while singletons and per-speaker flags — already keyed on the uid — worked.
Manual cognate edits on these rows also vanished on reload, because the write
used the raw member id and the migration then moved it to the uid.
Fix: in both grouped branches (mergedKeys and source-item variants), key cognate
+ similarity on concept.key (the uid), exactly like flagKey already does. The
selected variant continues to drive realization display only; singleton keying
is unchanged.
Tests: rewrote the two tests that locked the old per-realization keying to
assert uid keying (member-id keys are now decoys the uid must override) and
added a regression test for the production case (two survey rows unified under
one uid). Full vitest suite (1198 passed) + tsc --noEmit clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review — PR #648 (self-review, MC-458-J)Overview. +62/−22, 2 files. Moves grouped-concept cognate+similarity lookup in Correctness — verified, not assumed:
Tests. Full Scoped limitation (documented, not a regression): the fix sets Follow-ups (out of scope, noted in the PR body): single key-mint chokepoint + branded AGENTS.md review rules: (1) language/data-agnostic ✓ — generic placeholders, no speaker/lexeme/corpus; (2) readable ✓; (3) docs — covered by the persistence doc + PR body; the stale §6.1 note is the one doc debt, tracked above. Risk: low; localized to grouped-concept decision keying, fully covered by tests. Verdict: approve. Correct, tested, and the right convergence step. Leaving merge to the maintainer. |
…MC-458-E) Checklist §8 corrective: the §6.1 note described decisions keying on the underlying realization's concept id, which MC-458-E (uid migration) superseded. Add a one-line note that decisions key on the concept identity uid and that Compare reads grouped-concept cognate under the uid (this PR). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mandatory PR Review Checklist — PR #648 (MC-458-J)Per 1. Scope Confirmation & Sufficiency
2. Test Execution
3. Critical Systems Impact & Regression Check
4. Interactive Surface Verification
5. Side-Effect, Dependency & Performance
6. CI Gates & Merge Hygiene
7. Overall Integrity VerdictIntegrity Verdict: SAFE TO MERGE (pending the required human approval — agents do not merge).
8. Communication, Language & Docs Hygiene (corrective — applied)
|
Problem
In Compare,
buildSpeakerFormresolved grouped-concept cognate and similarity under the selected member's raw csv row id (e.g."89"), viacognateKey = concept.variants[selectedIdx].conceptKey(and the analogousmergedKeys[selectedIdx]). But the MC-458-E uid migration (#640) re-keyedcognate_setsandsimilarity(both inROOT_CONCEPT_KEYED_BLOCKS) by the concept identity uid ("c-89"), and the backend auto-promotes legacy keys to uid on read (promote_legacy_uid_keys).Result: every concept with ≥2 members (e.g. a concept elicited in two surveys) showed a blank cognate letter, while:
concept.key(the uid);flagKeyalready usesconcept.key.It also meant a manual cognate edit on a grouped concept didn't survive a reload: the write used the raw member id, then the migration moved it to the uid, and the next read (raw id) couldn't find it.
This is the unfinished frontend half of the uid migration: the cognate/similarity read+write key was never moved off the per-realization id for grouped concepts.
Fix
In both grouped branches of
buildSpeakerForm(mergedKeysand source-itemvariants), key cognate + similarity onconcept.key(the uid) — matchingflagKeyand the uid-keyed store. The selected variant still drives which realization is displayed; it no longer determines the cognate key. Singleton keying is unchanged. One concept identity → one cognate decision per speaker, which is the intended model.Data/language-agnostic: the change and tests use generic
conceptKey/speakerId/uid placeholders; no speaker, lexeme, or corpus is involved.Tests
…from the selected variant,…from the selected member) to assert uid keying, with member-id keys present as decoys the uid must override.npx vitest run— 1198 passed, 9 skipped, 0 failed.tsc --noEmitclean.Scope / follow-ups (not in this PR)
This converges the last stranded reader onto the uid. The broader hardening the design note already deferred — a single key-mint chokepoint + branded
ConceptKeytype, makingapply_sksyncemit uid directly, and a corpus-level "every decision key is a uid" guard test — remains worth doing to prevent any future surface from drifting again.🤖 Generated with Claude Code