fix(sync): surface built-in profile drift so identity keys reach existing users (v1.54.0) - #181
Merged
paulkr merged 3 commits intoAug 11, 2026
Conversation
…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>
…-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
approved these changes
Aug 11, 2026
paulkr
deleted the
feature/int-4395-sync-identity-keys-never-reach-existing-users-sync-run
branch
August 11, 2026 14:49
This was referenced Aug 11, 2026
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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. Butsync runresolves profiles withreadProfile()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 initbefore #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.isBuiltinNewerThanInstalledexists in the codebase but is wired only intomem 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 runwarns per model and points atone sync init <platform> <model>(which patches, preserving edits).--agentoutput carries aprofileDriftarray withmodel,missingFields, and thefixcommand, since an agent cannot see a console warning.2.
hasIdentityKeyread only the singular key.sync/index.ts:144was!!(p as any).identityKey, sosync profiles --agentreportedhasIdentityKey: falsefor gmail / google-calendar / fathom — precisely the three profiles the plural form was added for. Now checks both, plus a distincthasIdentityKeysso 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
Bccfor recipients, so these resolve only on threads the authenticated user sent — documented rather than silently partial.Deliberately not in this PR
from_emailextraction into the built-in profile) — that changes the record shape for existing users, so it wants its own change with a migration note rather than riding along here.sync testpreviewing resolved identity keys for enrich-deferred profiles) —sync testnever enriches its samples, so the preview correctly reports 0 with an explanatory note. Making it meaningful means havingsync testperform a detail call, which is a real design decision, not a fix.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.tscovering 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-existingidentity-keys.test.tssuites still pass unchanged — 43/43 together.Verification notes
npx tsc --noEmitpasses.npm testsuite: on Windows it reads and writes the developer's real~/.one(tests sandboxprocess.env.HOME, whichos.homedir()ignores on win32).package-lock.jsonversion fields hand-edited rather than regenerated, sincenpm installon Node 24 drops thepgoptional dependency from the lockfile.mainand touchsync/index.tsin different places. Whichever merges later will need its version bump rebased.🤖 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 inf4f8ea4alongside an unrelated README change. Adds.gitignorerules 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).