← Corpus / augment-it / issue
Merging organizations or people — when two objects turn out to be the same entity, dedupe non-destructively
Two rows are sometimes the same entity and nothing merges them — no edge re-pointing, no list union, no slug absorbed into `aliases[]`.
- Path
- issues/Merge-Organizations-Or-People-Non-Destructive-Dedupe.md
- Authors
- Michael Staton
- Augmented with
- Claude Code on Claude Fable 5
- Tags
- Issue · Augment-It · Organizations · Persons · Dedupe · Merge · Canonical-Layer
Merge organizations or people — a stub
The need
Duplicates are inevitable at capture time — the candidate gates reduce them but can’t eliminate them (operator picks “create” when the match was real, two imports spell one org two ways, a person exists once with an email and once with a LinkedIn URL). Today discovering a duplicate is a dead end: nothing merges. The two rows drift apart, each accumulating links, corpus, streams, affiliations, and observations the other doesn’t have.
Shape of the thing (jotted, not designed)
- Non-destructive. The loser is absorbed, not deleted: slug → the
survivor’s
aliases[](theupdateOrgrename precedent), arrays union’d (URL-dedup’d, the additive discipline’s existing keys), observations preserved with their provenance,client_accessunion’d. A tombstone or redirect pointer so anything stamped with the old slug/uuid still resolves. - Effective. Affiliation edges re-pointed to the survivor (dedup’d
against existing edges), opportunities re-stamped (the
updateOrgfan-out precedent) — after the merge there is ONE row to find. - Human-driven. Per [[human-in-drivers-seat]]: the operator picks the
survivor and resolves field conflicts (which
complete_namewins?); side-by-side compare, not an auto-merge score. - Perhaps its own microfrontend. A compare-and-merge surface (two cards, field-by-field pick, one confirm) doesn’t fit inside the org card; a dedicated remote fits the one-surface-per-job pattern the workbench already follows.
Deliberate contrast to keep
Opportunities are never auto-merged by design (duplicates across record sets are intentional — see the Grilling-on-DB-Resolver decisions). This merge is for the CANONICAL layer only: organizations and persons, where one real-world entity should be one row. The opportunity rule stands.
Open questions
- One merge verb (
entity.merge?) or per-table (organization.merge/person.merge)? - Duplicate DISCOVERY — does the merge surface also hunt candidates (same domain, near-name), or only act on pairs the operator brings?
- What does the tombstone look like — a row with
merged_into, or an alias entry alone? - Observations: re-point subject/object to the survivor, or leave them citing the absorbed row and resolve through the tombstone?