← Context/ issues
Team-crawl accept drops the crawled links and leaves the staged row — double-save risk
`person.apply` writes `linkedin_profile_url` as a scalar only, so accept discards the crawl's links — and the staged row lingers.
The two symptoms (operator-confirmed, 2026-07-24 evening)
Crawled links don't save. The team crawl usually finds a LinkedIn URL (and often a bio page) per person. Accept runs
person.apply+person.affiliate— andperson.apply's create branch writeslinkedin_profile_urlonly as a scalar matching field (person-resolver.tsCREATE), never as apersonal_links[]entry. The new person's card shows zero links; the crawl's best evidence is silently discarded.The accepted row stays staged. After accept the row flips to "added ✓" but remains in the staged list. The person now exists in the People list AND in the staged results — redundant state that invites a second save (via re-accept paths or operator confusion). An accepted row should be CONSUMED: it leaves the staged list; the person appearing in the People list above is the confirmation.
The fix (this doc precedes the implementation by minutes)
On accept, after apply + affiliate: add the crawled
linkedin_urlandbio_urlto the person via the existingperson.links.add— on created persons only (matched persons may already carry them; additive-not-duplicative, per additive discipline). Link failures degrade soft — the personaffiliation are the core writes.
On success, remove the row from the staged list entirely (skip semantics). The "N staged" count and Done-clear affordance follow.