Skip to content

Sync off keeps every chat, and a copied older chat can no longer be wiped - #2082

Merged
AbirAbbas merged 5 commits into
devfrom
fix/2072-sync-off-keeps-chats
Oct 31, 2026
Merged

AbirAbbas merged 5 commits into
devfrom
fix/2072-sync-off-keeps-chats

Conversation

@AbirAbbas

Copy link
Copy Markdown
Collaborator

Closes the rest of #2072 (item H). Items A, D, F, G, I, L and M landed in #2075, #2070's items in #2078, and B in #2079.

What changes

  • Sync off keeps every chat. With CODEAF_SYNC_URL=off, or sync quiet before pairing, Home lists every chat on this computer once: chats in the copy folder (.moving) and older chats alike. Each one opens and can be written.
    • A completed copy opens even while sync is off. Before, movablePlace returned early, so the untouched original opened instead.
    • Saved hold receipts stay dormant while sync is off, so a local send never waits on them.
    • No sync drive starts.
    • A window that another device displaced still refuses to send (TestDisplacedWindowWithLocalEmptyReadingRefusesSend).
  • A copied older chat can no longer be wiped (data loss, already on dev).
    • The bug: a rewind or a take onto a copy removed .cell/copy-ready. Home then fell back to the original, and opening that original ran CopyLegacy, which removed the copy with every turn written since.
    • Restores now keep this computer's own .cell bookkeeping (copy-ready, copy-offered, published.json, adopted.json).
    • A take onto a copy root re-stamps the copy markers.
    • CopyLegacy refuses to remove a destination that already holds sealed turns. It reopens and re-stamps a valid one, or fails without deleting anything.
  • One walk per bucket. BucketSessionDirs is the single listing of a bucket and its copy folder, used by Home, recent sessions, knowledge history, session workspaces and the v3 layout scan. It reads .moving at most once, and makes no copy lookups at all when a bucket has no copies. Before, it made 400 CopyRoot and 610 Copied calls for 200 chats with no copies.
  • Doctor sends one read to the sync service and nothing else, and skips unfinished copy folders.

Not done, and why

  • Doctor naming a client/service capability gap. The only capability header (codeaf-conditional-takes) comes back on POST /v1/dir/acquire, and doctor must not create anything on the service. GET /v1/dir/list carries no capabilities, so doctor has no read-only way to ask. codeaf-release service keeps the probe.
  • Doctor naming a removed device still referenced locally. Holds, offers and saved rows store a device's display label, which changes on a rename. Matching labels against the paired list would report and clear the wrong things. Never lock a person out of their own chat on an older sync service #2075 already stops offering removed devices.

Validation contract → tests

  1. Sync off keeps every chat: TestSyncOffHomeKeepsEveryChatOpensAndWrites drives the real Home with CODEAF_SYNC_URL=off and with a quiet unpaired home. It opens and writes every chat and checks that zero requests reach the service. Also TestBucketSessionDirsKeepsMovingAndLegacyChatsOnce.
  2. A copy survives rewind and take-back: TestCopiedLegacyChatKeepsCopyReadyAfterRewind and TestCopiedLegacyChatKeepsCopyReadyAfterTakeBack (borrowed project and owned workspace). Each failed before the fix.
  3. Opening a stale original never deletes a populated copy: TestOpeningStaleOriginalNeverDeletesPopulatedCopy and TestCopyLegacyRefusesToWipePopulatedDestination.
  4. A displaced window never sends: TestDisplacedWindowWithLocalEmptyReadingRefusesSend.
  5. Home stays fast: TestBucketWithoutMovingMakesNoCopyLookups counts lookups through seams. It sees 0 with no copies, and 1 Copied for one copy among 200 chats.
  6. Doctor is read-only on the service: TestDoctorDoesNotCreateRecordsOnSyncService checks that it sends only GET /v1/dir/list, adds no namespaces, and sends nothing at all with sync off.
  7. The manual: a "sync off and my chats are gone" probe and exact-quote test.

Proof

Focused runs on the branch: internal/cell, internal/cellstore, internal/handoff (copy, restore, rewind, materialize, take), internal/session (bucket, copy, recent, knowledge), internal/tui3 (displaced, held elsewhere), cmd/codeaf (sync off, doctor, older chats, layout) and internal/manual. gofmt, build and vet are clean. The touched-package suites run in CI.

🤖 Generated with Claude Code

AbirAbbas and others added 5 commits October 30, 2026 21:46
A rewind or a take onto a copied older chat removed .cell/copy-ready, so Home
fell back to the untouched original, and opening that original ran CopyLegacy,
which removed the copy and every turn written since. Restore now keeps this
computer's own .cell bookkeeping, a take re-stamps the copy markers, and
CopyLegacy refuses to remove a destination that already holds sealed turns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BucketSessionDirs is now the one walk over a project bucket and its .moving
copy folder. Home, recent sessions, knowledge history and session workspaces
all go through it. It reads .moving at most once and does no copy lookups at
all when a bucket has no copies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With sync off, or quiet before pairing, a completed copy still opens, saved
hold receipts stay dormant so a local send never waits on them, and no sync
drive starts. A displaced window still refuses to send. Doctor skips
unfinished copy folders and sends nothing but one read to the sync service.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With chats in the copy folder now listed, the row says `here · 2 copies …`,
and the explanation wraps across its column with the projects panel's words
in between, so a screen search missed it although the row said it whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AbirAbbas
AbirAbbas merged commit 70c5c62 into dev Oct 31, 2026
9 checks passed
@AbirAbbas
AbirAbbas deleted the fix/2072-sync-off-keeps-chats branch October 31, 2026 02:06
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.

1 participant