Skip to content

fix(identity): fold the 5 netid twins the name-indexed dedupe cannot see #3166

Closed

Description

@quntao-z

#3164 landed the ingest half of #3152: resolveOrCreateResearcherId now adopts the live identifiers.netid holder instead of minting a twin, so the split stops growing. This issue carries the stored half, re-sized against a named control after the first draft got it wrong in two ways.

Control

yarn --cwd server researchers:dedupe-accountless-shells (dry run, Development, 2026-09-23) is the committed instrument for this population. Output:

accountLinkedResearchers: 4005
accountlessResearchers:   2393
netidBackedAccountlessResearchers: 385
byReason: { MERGEABLE: 0, NO_NAME: 0, NO_CANONICAL: 2390,
            AMBIGUOUS_MULTIPLE_CANONICAL: 1, ORCID_CONFLICT: 0, NETID_CONFLICT: 2 }

It confirms the 385 independently. Two corrections to my first draft follow from it.

Correction 1: a researcher-merge operation already exists. I wrote that none did. dedupeAccountlessResearcherShells folds a shell onto a stronger-identity canonical, repoints role assignments, archives redundant edges, unions attributes, and re-gates the affected entities. What it cannot do is see this population: it indexes candidates by normalized displayName, and it reports MERGEABLE: 0 today. Its NETID_CONFLICT: 2 is a different thing again, a shell whose netid disagrees with its target's, not a shared netid.

Correction 2: the 5 twins and the 2 bypassed edges are not the same rows. The first draft treated them as one cohort. Measured separately:

population count how it was selected
netid twins: one netid held by two live researcher rows 5 pairs identifiers.netid on an accountless row, matching accounts.netid, with a live researcher keyed to that account
of those 5, pairs sharing a normalized display name 0
of those 5, twins carrying identifiers.netid themselves 0 confirms the mechanism: the twin is keyed on accountId and never writes the netid identifier
of those 5, holders carrying a detached edge 0 so no netid twin bypasses a detachment today
live role edges held by the 5 twin rows 11 1, 1, 6, 1, 2
detached edges bypassed by a same-name twin holding a live edge on the same entity and role 2 selected by displayName, not by netid

So the netid split is real at 5 pairs and 11 live edges, and it is a split-identity defect with no detachment involved. The 2 bypassed edges are a same-name cohort, and this measurement does not establish that either of them arose from the netid path.

What each needs

The 5 netid twins. One human served as two people, 11 live edges on the twin side. The existing dedupe cannot reach them because the two rows carry different display names, which is exactly the case a netid key should decide and a name index cannot. The work is to let that operation key on netid as well as name, and to pick the direction deliberately: it currently folds the accountless shell into the account-linked row, which is the opposite of what a row carrying the netid and the evidence would want.

The 2 bypassed edges. Read through the real detail route: both are a live student_ready LAB serving exactly 1 lead, which is the twin's edge, with 0 live lead edges remaining if that edge were archived. Each would need a visibility re-gate and would likely leave the served surface, which is the #2385 hazard. Their reasons differ and so do their answers: one was detached as a same-surname lead on an entity whose own identity names a different person (#2768), where a wrong lead against no lab is a product call; the other was retired as a lead claim on someone whose title cannot host a student (#2880), a landed decision that already accepts rows leaving the served surface.

Definition of done

researchers:dedupe-accountless-shells can key on netid, the 5 pairs are folded with a deliberate direction, the 11 edges land on one row, and the control reports 0 netid twins. The 2 bypassed edges are re-read on the detail route afterwards and tracked separately, since their provenance is not established here and the #2768 one needs a product answer before anything is archived. Development only.

Activity

  1. changed the title [-]fix(identity): merge the 5 netid twins onto their holder and carry the detachment across[/-] [+]fix(identity): fold the 5 netid twins the name-indexed dedupe cannot see[/+] on Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions