Problem
Phone numbers flow through two systems with different normalization behaviors:
- context-helpers emits phones as whatever Apple Contacts returns:
(555) 123-4567, 555-123-4567, +1 555 123 4567
- context-library (
PeopleMetadata) normalizes to digits + leading '+' — a different operation
The entity linker compares these two representations when building cross-links. A contact stored as (555) 123-4567 in Apple Contacts and a message sender arriving as 5551234567 from chat.db produces no link — silently. There is no test that catches this.
Proposed fix
1. Define E164 as the canonical format (+{country_code}{number}, e.g. +15551234567)
2. Implement normalization once — a shared utility usable by both systems:
- In context-helpers: normalize at collection time before emitting the payload
- In context-library: normalize at ingest time in
PeopleMetadata and when querying domain_metadata in the entity linker
3. Write a round-trip integration test that:
- Creates a contact with phone
(555) 123-4567
- Creates a message with sender
5551234567
- Asserts that
entity_links contains a row linking them after linker runs
Files to change
src/context_helpers/collectors/contacts/collector.py — normalize phones before emitting
src/context_helpers/collectors/imessage/collector.py — normalize sender/recipients before emitting
src/context_library/storage/models.py — PeopleMetadata phone normalization
src/context_library/core/entity_linker.py — normalize before JSON path comparison
- New shared utility:
src/context_library/core/normalize.py (or equivalent in helpers)
Notes
- International numbers:
phonenumbers library handles E164 conversion robustly including country code inference
- This is a correctness bug, not just a quality issue — some portion of the existing 6,638 entity_links are missing because of this mismatch
Problem
Phone numbers flow through two systems with different normalization behaviors:
(555) 123-4567,555-123-4567,+1 555 123 4567PeopleMetadata) normalizes todigits + leading '+'— a different operationThe entity linker compares these two representations when building cross-links. A contact stored as
(555) 123-4567in Apple Contacts and a message sender arriving as5551234567fromchat.dbproduces no link — silently. There is no test that catches this.Proposed fix
1. Define E164 as the canonical format (
+{country_code}{number}, e.g.+15551234567)2. Implement normalization once — a shared utility usable by both systems:
PeopleMetadataand when queryingdomain_metadatain the entity linker3. Write a round-trip integration test that:
(555) 123-45675551234567entity_linkscontains a row linking them after linker runsFiles to change
src/context_helpers/collectors/contacts/collector.py— normalize phones before emittingsrc/context_helpers/collectors/imessage/collector.py— normalize sender/recipients before emittingsrc/context_library/storage/models.py—PeopleMetadataphone normalizationsrc/context_library/core/entity_linker.py— normalize before JSON path comparisonsrc/context_library/core/normalize.py(or equivalent in helpers)Notes
phonenumberslibrary handles E164 conversion robustly including country code inference