[Foundation] Canonical person-resolution service (resolve by phone/email/BT/device-id) #115

Closed
opened 2026-06-29 19:24:08 +00:00 by Mark · 2 comments
Owner

Problem

Every passive ingestion source (#105 call log, #106 SMS, #107 email, #108 ambient BT) needs to answer "which Person is this contactPoint?" — and right now each path will rebuild its own matcher. That's duplicated logic and divergent match confidence.

Scope

  • One resolvePerson(contactPoint: { kind, value }) → Person | candidate | null function
  • Match order: exact phone → exact email → BT device-id → fuzzy name
  • Returns a confidence score (0..1) so callers can decide whether to auto-link vs. prompt
  • Wired into the new capture surfaces (call log, SMS, email, ambient) as their first step

Why this is foundational

Spec-gating ingestion on this makes #105–#108 actually work. Without it, passive candidates have no Person, so they have no Home page presence, no streak tracking, no anything. Sequencing: this first, then the four ingestion sources.

Out of scope

  • Custom matchers per source (this is the shared layer)
  • Person merging UI (separate issue)
## Problem Every passive ingestion source (#105 call log, #106 SMS, #107 email, #108 ambient BT) needs to answer "which Person is this contactPoint?" — and right now each path will rebuild its own matcher. That's duplicated logic and divergent match confidence. ## Scope - One `resolvePerson(contactPoint: { kind, value }) → Person | candidate | null` function - Match order: exact phone → exact email → BT device-id → fuzzy name - Returns a confidence score (0..1) so callers can decide whether to auto-link vs. prompt - Wired into the new capture surfaces (call log, SMS, email, ambient) as their first step ## Why this is foundational Spec-gating ingestion on this makes #105–#108 actually work. Without it, passive candidates have no Person, so they have no Home page presence, no streak tracking, no anything. Sequencing: this first, then the four ingestion sources. ## Out of scope - Custom matchers per source (this is the shared layer) - Person merging UI (separate issue)
Author
Owner

Auto-triage: needs decompose

Marked triage-approved + needs-decompose. decompose-executor will pick this up and break it into implementable sub-issues.

## Auto-triage: needs decompose Marked `triage-approved` + `needs-decompose`. decompose-executor will pick this up and break it into implementable sub-issues.
Author
Owner

Closing — implementation verified.

What landed

  • src/lib/types.ts: added ContactPoint, ContactPointKind, ResolutionCandidate, ResolutionResult
  • src/lib/schemas.ts: added zod schemas matching the types
  • src/lib/person-resolver.ts: new resolvePerson() + resolvePersonBatch() with match order phone → email → BT device-id → fuzzy name, confidence scoring, alternatives list
  • src/lib/previewGenerators.ts: refactored to delegate to resolver (call/SMS/email)
  • src/lib/ambient-engine.ts: BT resolution delegated to resolver
  • src/lib/person-resolver.test.ts: comprehensive unit tests
  • src/test/factories.ts: buildDeviceToPersonMapping factory added

Verification evidence (manual run, 13:27 → 16:27 UTC, ~3h1m)

  • Targeted gates (resolver test, previewGenerators test, tsc, eslint): all passed
  • Full suite: 50/51 files passed, 900/918 tests passed
  • The single OOM crash was on src/pages/__tests__/LogInteraction.test.tsx (V8 heap exhausted after 10,838s) — unrelated to this issue; it predates #115 and is filed as a follow-up below.
Closing — implementation verified. **What landed** - `src/lib/types.ts`: added `ContactPoint`, `ContactPointKind`, `ResolutionCandidate`, `ResolutionResult` - `src/lib/schemas.ts`: added zod schemas matching the types - `src/lib/person-resolver.ts`: new `resolvePerson()` + `resolvePersonBatch()` with match order phone → email → BT device-id → fuzzy name, confidence scoring, alternatives list - `src/lib/previewGenerators.ts`: refactored to delegate to resolver (call/SMS/email) - `src/lib/ambient-engine.ts`: BT resolution delegated to resolver - `src/lib/person-resolver.test.ts`: comprehensive unit tests - `src/test/factories.ts`: `buildDeviceToPersonMapping` factory added **Verification evidence (manual run, 13:27 → 16:27 UTC, ~3h1m)** - Targeted gates (resolver test, previewGenerators test, tsc, eslint): all passed - Full suite: 50/51 files passed, 900/918 tests passed - The single OOM crash was on `src/pages/__tests__/LogInteraction.test.tsx` (V8 heap exhausted after 10,838s) — **unrelated to this issue**; it predates #115 and is filed as a follow-up below.
Mark closed this issue 2026-06-30 23:48:58 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Mark/kimi_agent_kin_app_sync#115
No description provided.