Skip to content

fix(sync): surface built-in profile drift so identity keys reach existing users (v1.54.0) - #181

Merged
paulkr merged 3 commits into
mainfrom
feature/int-4395-sync-identity-keys-never-reach-existing-users-sync-run
Aug 11, 2026
Merged

fix(sync): surface built-in profile drift so identity keys reach existing users (v1.54.0)#181
paulkr merged 3 commits into
mainfrom
feature/int-4395-sync-identity-keys-never-reach-existing-users-sync-run

Conversation

@siddharth-bhansali

@siddharth-bhansali siddharth-bhansali commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Addresses the remaining gaps on #129 and #130 · INT-4395

Why these two issues are still open

The core ask of both landed in 1acbc48 (#167) and the profiles are correct. But sync run resolves profiles with readProfile() alone (sync/index.ts:706, :795, :919) — it never merges or diffs against the shipped built-in.

So every user who had already run sync init before #167 kept their older profile and writes zero identity keys — silently, forever. Record counts are identical whether the feature is active or not, so there is no signal at all. isBuiltinNewerThanInstalled exists in the codebase but is wired only into mem migrate.

That is why I left #129/#130 open rather than closing them on the #167 merge.

Changes

1. Detect and surface profile drift. findMissingBuiltinCapabilities() compares the installed profile against the shipped built-in across a curated set of additive fields: identityKeys, identityKey, enrich, dateFilter, memory.

A direct field comparison rather than the existing mtime approach — file mtimes are not meaningful for an npm-installed package, where every file is stamped at install time. The list is curated on purpose: a profile is user-editable, and fields someone may have deliberately removed (transform, exclude, onChange, …) must never nag. These five only ever add behaviour.

sync run warns per model and points at one sync init <platform> <model> (which patches, preserving edits). --agent output carries a profileDrift array with model, missingFields, and the fix command, since an agent cannot see a console warning.

2. hasIdentityKey read only the singular key. sync/index.ts:144 was !!(p as any).identityKey, so sync profiles --agent reported hasIdentityKey: false for gmail / google-calendar / fathom — precisely the three profiles the plural form was added for. Now checks both, plus a distinct hasIdentityKeys so the two concepts stay separable. Same fix for the human-mode [identity] tag.

3. Bcc participants (#129). The issue's Problem section names From/To/Bcc; the profile declared only From/To/Cc. Added. Note Gmail strips Bcc for recipients, so these resolve only on threads the authenticated user sent — documented rather than silently partial.

Deliberately not in this PR

Both are worth keeping the issues open for if you want them; happy to split them out.

Tests

8 new tests in profile-drift.test.ts covering the drift detector (reports a genuinely-missing capability against the real gmail built-in, stays quiet when present, never reports user-editable fields, handles missing built-in / missing installed / explicitly-empty-value) and the Bcc addition. The pre-existing identity-keys.test.ts suites still pass unchanged — 43/43 together.

Verification notes

🤖 Generated with Claude Code


Also in this PR (unrelated housekeeping)

Removes test/all-emails.json, a committed API-response capture that nothing in the codebase references — it landed by accident in f4f8ea4 alongside an unrelated README change. Adds .gitignore rules so local captures cannot be committed the same way again. Full suite passes with it gone.

Also merges main (this branch predated CI landing, so it had no checks at all).

…ting users (v1.54.0) (#129/#130)

Identity keys shipped in 1acbc48 (#167), but `sync run` resolves profiles with
readProfile() alone — it never merges or diffs against the shipped built-in.
So every user who had already run `sync init` kept their older profile, wrote
zero identity keys, and got no warning: record counts look identical whether
the feature is active or not. The plumbing landed; the feature reached nobody
who had onboarded.

- findMissingBuiltinCapabilities() compares the installed profile against the
  shipped built-in across a curated set of additive fields (identityKeys,
  identityKey, enrich, dateFilter, memory). A direct field comparison, not an
  mtime check — file mtimes are meaningless for an npm-installed package.
  User-editable fields someone may have removed on purpose (transform,
  exclude, onChange, ...) are deliberately not reported.
- `sync run` warns per model and points at `one sync init <platform> <model>`,
  which patches rather than overwrites. `--agent` output carries the same
  information as a `profileDrift` array.
- `sync profiles` read only the SINGULAR identityKey, so it reported
  hasIdentityKey:false for gmail/gcal/fathom — the three profiles the plural
  form was added for. Now checks both, and adds a distinct hasIdentityKeys.
  Same fix for the human-mode [identity] tag.
- gmail/gmailThreads collects Bcc participants. The issue named to/cc/bcc; the
  profile declared only From/To/Cc. Gmail strips Bcc for recipients, so these
  resolve on threads the authenticated user sent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@linear

linear Bot commented Aug 11, 2026

Copy link
Copy Markdown

INT-4395

siddharth-bhansali and others added 2 commits August 11, 2026 20:02
…-identity-keys-never-reach-existing-users-sync-run

# Conflicts:
#	package-lock.json
#	package.json
test/all-emails.json is referenced nowhere in the codebase — no source, test,
doc, or workflow file loads it. It landed by accident in f4f8ea4 alongside an
unrelated README change and has sat in the tree since.

Also adds .gitignore rules so a local capture can't be committed the same way
again. Unit-test fixtures live inline in the *.test.ts files that use them, so
nothing needs a tracked test/ directory.

Verified with the full suite (443 tests) after removal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@paulkr
paulkr merged commit bca2ed2 into main Aug 11, 2026
7 checks passed
@paulkr
paulkr deleted the feature/int-4395-sync-identity-keys-never-reach-existing-users-sync-run branch August 11, 2026 14:49
paulkr pushed a commit that referenced this pull request Aug 13, 2026
…ting users (v1.54.0) (#181)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants