Skip to content

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”

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.

  1. The surrogate id keys on the resolved canonicaluuid5(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.
  2. The stability rule: the resolved canonical is a function of the accumulated decision recordentity_pair_resolutions, curation pins, and previously established canonicals seeded into is_existing_canonical under ExistingCanonicalPolicy.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.
  3. 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”.
  4. 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).
  • 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.
  • _select_existing_canonical_roster and 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_resolutions rows 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).