DR-147: A mention row is identified by its resolved canonical, and a re-run may grow a group but never rename it
DR-147 — A mention row is identified by its resolved canonical, and a re-run may grow a group but never rename it
Section titled “DR-147 — A mention row is identified by its resolved canonical, and a re-run may grow a group but never rename it”Context
Section titled “Context”DR-140 clause 1 makes the resolved canonical the value mentions are declared under, which
makes it the row’s identity. Under cocoindex’s contract a changed declared key is a clean
delete-and-recreate — so if the resolver returned a different canonical on a later run
(a new document adds a longer spelling and KhPairResolver prefers longer; the greedy
resolution order shifts; a model version moves on a cache miss), the corpus’s mention rows
would churn wholesale: correct by the engine’s contract, wrong as product behaviour. The
Fable-only entity-architecture review (S554, owner-confirmed board:
reports/s554-entity-architecture-review.html) ruled on identity and stability together.
Decision
Section titled “Decision”- The surrogate id keys on the resolved canonical —
uuid5(ns, "em:{sd_id}:{resolved}:{type}")— so the primary key and the natural key agree by construction. No backfill (DR-093): pre-launch mention rows are mock-tier and are dropped and re-walked. - The stability rule: the resolved canonical is a function of the accumulated
decision record —
entity_pair_resolutions, curation pins, and previously established canonicals seeded intois_existing_canonicalunderExistingCanonicalPolicy.PINNED. A re-run over a grown corpus may add members to a group but never rename one; renames are curation acts only. Probe: add a document introducing a longer spelling of an existing entity, re-run, the group’s canonical is unchanged. - The pin carry-forward relocates with the declare site into phase 2, and pins
additionally seed
is_existing_canonical— id-434 guardrail 2 is ratified as “the pattern survives, probe-verified”, not “the lines are immovable”. - The pair cache is the authoritative durable record: the phase-2 resolve component
is not memoised, so every fresh pair decision is written to
entity_pair_resolutions(which survives an LMDB reset; the memo does not).
Alternatives considered
Section titled “Alternatives considered”- Key the id on the stable per-document surface form. Ids would survive resolution changes, but the primary key and natural key would disagree again — recreating the engine-record/database divergence DR-140 was written to end.
- Allow renames and absorb the churn. Rejected: whole-corpus row churn on an incidental input change is indistinguishable from data loss to every provenance consumer, even when the engine executes it cleanly.
- Memoise the resolve component (upstream’s literal shape). A whole-name-set memo misses on any corpus change, and a hit silently skips pair-cache writes — eroding the only archaeology of the real extractor that DR-140 and id-433 both relied on.
Consequences
Section titled “Consequences”_select_existing_canonical_rosterand the ID-81.9 self-subtraction retire: their real requirement (cross-run stability) is served by clause 2’s seeding; the mechanism is not. The curation-pin write-back exclusion retires with the mutation pass it defended against.- Existing
entity_pair_resolutionsrows keyed on formerly alias-applied names go unreachable post-id-433; the one-off re-ask cost is accepted and the key-space is not repaired — those rows are archaeology. - A resolution-behaviour change that would rename a group must surface as a curation proposal, not as pipeline output.
- Full ruling record and remaining execution detail: id-434 (S554 Progress entry).