Skip to content

feat: icloud device removal - #3350

Open
kwnms04 wants to merge 6 commits into
steipete:mainfrom
kwnms04:fix/3234-icloud-device-removal
Open

feat: icloud device removal#3350
kwnms04 wants to merge 6 commits into
steipete:mainfrom
kwnms04:fix/3234-icloud-device-removal

Conversation

@kwnms04

@kwnms04 kwnms04 commented Sep 1, 2026

Copy link
Copy Markdown

Closes #3234.
This is not completely verified. see below: Verification
Generated by Claude, Reviewed by kwnms04 and Claude.

What this does

Settings → iCloud Sync → Macs now lists every synced Mac and lets you remove one, with confirmation. Removing a Mac deletes its Device Record and every Usage Snapshot it published, on every Mac on the account.

The list renders from local persistence, so it is visible even with syncing off — otherwise there is nothing to remove a stale device from, which is the state the issue reports.

Why the row does not disappear immediately

An earlier revision removed the row optimistically and put it back on failure. That machinery was the source of most review findings, so it is gone. The row now goes on one signal: CloudKit confirmed the delete, or reported the record was already gone. That is the same path a delete made on another Mac already took, so both cases share one code path.

A Device Record delete is attempted once. Retrying would race the Mac that owns it re-registering itself and delete the record it just published. Failures that get no retry are surfaced in the pane instead of being dropped, and clear when a push completes with nothing failing in it.

Scope

Two deliberate departures, both recorded as ADRs:

  • ADR 0002 — removal is offered for the current Mac too, though triage scoped this to "a selected non-current device". The current Mac re-registers on the next sync start, and queueDeviceRecord cancels its own pending delete, so the removal is self-healing rather than destructive.
  • ADR 0001 — the Device Identifier is derived from the Mac's hardware UUID rather than minted per install, so a reinstall stops stranding a duplicate. This is beyond what the issue asked for. It has a cost the ADR states plainly: every Mac syncing today creates one more Stale Device at its next reinstall. Existing duplicates are not merged — the issue lists auto-merge as out of scope, and triage confirmed "without automatic hostname merging".

Also out of scope, as the issue notes: "reset icloud data".

Duplicates are the point

The confirmation dialog shows the device's absolute last-seen time, because the case this issue is about is two rows with the same host name. On the machine this was developed on, kwnmbp.local currently has four Device Records (0.49.4 → 0.55.1 → 0.55.1 → 0.56.1). Host name alone cannot tell them apart.

Verification

  • make check — swiftformat clean, swiftlint --strict 0 violations across 2075 files, locales 22 catalogs / 1494 keys, packaging and signing checks pass.
  • make test — all 82 groups run green except ClaudeOAuthCredentialsStoreNeverPromptCacheTests, which shells out to /usr/bin/defaults; that tool cannot write any domain on this machine, so those two tests fail for reasons unrelated to this change. The other 11 suites in that group were run separately and pass.
  • New tests cover the confirmed-delete rule, the no-retry policy for Device Records, the reporting rule, and that queueing a delete leaves the fleet row in place.

Not verified locally: the removal itself, the confirmation dialog, and the failure banner. iCloud entitlements are only embedded in identity-signed release builds of com.steipete.codexbar, and this machine has no signing identity. What was verified against a running build is that the Macs list renders with syncing off and the remove controls are correctly disabled without the entitlement.

Follow-ups, not addressed here

  1. CloudSyncState.removeDevice is a closure on an @Observable state object — behaviour where state belongs.
  2. CloudSyncSnapshotMigration now owns Device Record delete policy as well as snapshot migration; it has two reasons to change.
  3. Record kind is carried as a "device-" name prefix rather than a type.
  4. Snapshots the local cache never saw are not deleted, since removal reads the local envelope rather than querying CloudKit.
  5. Removal stays unavailable while syncing is off; the footer says so, but the issue's original complaint is only partly answered.
  6. A delete queued but not sent before the app quits is only requeued through the snapshot push, which is gated on snapshot syncing being on.
  7. macsFootnote concatenates two localized sentences, which is not translatable as a unit.

kwnms04 and others added 4 commits August 31, 2026 22:30
Adds CONTEXT.md with the iCloud Sync vocabulary (Device, Device Record,
Fleet, Usage Snapshot, Stale Device) and an ADR recording why device
identity moves to the machine while existing installs keep the identifier
they already have.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reinstalling minted a fresh device identifier, stranding the previous
device record and its usage snapshots in CloudKit with nothing alive to
refresh them, and the menu kept projecting those snapshots as a second
usage card. Fixes steipete#3234.

- Each row in Settings -> iCloud Sync -> Macs gets a trash button that,
  after confirmation, deletes the device record and every usage snapshot
  that device published. Removal reuses the existing persistent delete
  retry path, and a terminal CloudKit failure puts the row back.
- Device identity now derives from a hashed kern.uuid, which survives a
  reinstall. Installs that already have an identifier keep it.
- Re-registering a device cancels its own pending delete, so the current
  Mac cannot retire the record it just saved.
- The trash button is disabled while sync cannot reach CloudKit, so it
  never looks like it worked when nothing was sent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Queueing a delete no longer hides the row. The fleet entry goes when the
delete is confirmed, or when CloudKit reports the record was already gone,
which is the same path a delete made on another Mac already took.

A Device Record delete is attempted once: retrying would race the Mac that
owns it re-registering, and delete the record it just published. Failures
that get no retry are surfaced instead of being dropped, and the pane shows
them until a push completes with nothing failing in it.

The pending-delete set now holds Device Records as well as Usage Snapshots,
so it is named for what it holds; the persisted key is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UxuRSmcgehfT9gxRzczXGQ
The removal strings sat in the general block; move them beside the other
iCloud Sync strings, and add the message shown when removal is attempted
before the engine is running.

ADR 0002 records why removal is offered for the current Mac even though
triage scoped this to non-current devices, and the glossary gains Device
Identifier, the term the identity decision rests on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UxuRSmcgehfT9gxRzczXGQ
@clawsweeper

clawsweeper Bot commented Sep 1, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 1, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2331691d13

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1357 to +1358
await self.forgetFleetRecords(
CloudSyncSnapshotMigration.confirmedDeletedNames(deletedIDs: deletedIDs, failures: failures))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retain a recovery path until all snapshot deletes finish

When CloudKit confirms the Device Record deletion but returns a terminal error for one of its Usage Snapshot deletions, this immediately removes the device row while finishedFailedDeleteNames also abandons the failed snapshot. The snapshot remains in fleetSnapshots and continues to be rendered by StatusItemController+FleetAccounts.swift, but the missing device row leaves the user no way to retry its removal. Keep the row or another retryable removal record until every associated snapshot is confirmed absent.

Useful? React with 👍 / 👎.

Comment on lines +849 to +852
if changes.failedRecordSaves.isEmpty, changes.failedRecordDeletes.isEmpty,
!changes.savedRecords.isEmpty || !changes.deletedRecordIDs.isEmpty
{
await MainActor.run { self.state.status.lastError = nil }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear the error after an already-absent delete

When a removal retry reports unknownItem—for example, after the first response was lost or another Mac completed the deletion—confirmedDeletedNames correctly treats the record as deleted and removes the row, while reportableFailedDeletes suppresses the error. This condition nevertheless refuses to clear the previous lastError because failedRecordDeletes is nonempty, so the pane can retain a red failure banner even though the requested removal succeeded and no later push is guaranteed. Treat an all-unknownItem delete result as successful for banner clearing.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Sep 1, 2026
@clawsweeper

clawsweeper Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed September 1, 2026, 8:30 AM ET / 12:30 UTC.

ClawSweeper review

What this changes

The PR adds iCloud Sync controls to remove a selected device record and its usage snapshots, and derives device IDs for new installations from a hashed hardware UUID.

Merge readiness

Blocked until real behavior proof from a real setup is added - 7 items remain

Keep this PR open: it resolves the earlier cache-refresh finding, but current-device removal can leave newly published snapshots without a removable device row, and the central CloudKit workflow still lacks real after-fix proof.

Priority: P2
Reviewed head: bb885b559b994fafcde1b5da2f9ea037f4cadeab
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🧂 unranked krab (1/6) The PR has useful targeted tests and resolves the prior cache-refresh concern, but a P1 lifecycle defect and missing real behavior proof prevent merge readiness.
Proof confidence 🧂 unranked krab (1/6) Needs real behavior proof before merge: The changed production owners are the settings action and CloudSyncEngine deletion path, but the PR body confirms that deletion, confirmation, and error presentation were not exercised on an entitled signed build; tests and a disabled-control observation do not prove the after-fix CloudKit flow. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Verification

Check Result Evidence
Real behavior Needs proof Needs real behavior proof before merge: The changed production owners are the settings action and CloudSyncEngine deletion path, but the PR body confirms that deletion, confirmation, and error presentation were not exercised on an entitled signed build; tests and a disabled-control observation do not prove the after-fix CloudKit flow. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 5 items Current-device deletion trigger: The introduced row action enables the same removal control for the current device as for stale devices; it passes that device ID into the deletion path.
Orphaned-snapshot path: Removal deletes the current device’s fleet records, while the existing snapshot queue independently accepts and sends snapshots from that Mac; no ordering or re-registration guard connects the two paths.
Prior P1 addressed: The head commit adds a successful CloudKit refresh before constructing the deletion set, addressing the prior cache-incomplete snapshot finding.
Findings 1 actionable finding [P1] Prevent current-device snapshots from becoming orphaned
Security None None.

How this fits together

CodexBar’s iCloud Sync subsystem stores per-Mac usage snapshots in CloudKit and projects the fleet into Settings and the menu. The new settings action refreshes the fleet, deletes the selected device’s records, and updates the local cached fleet after CloudKit confirms deletion.

flowchart LR
  A[Settings device list] --> B[Removal confirmation]
  B --> C[Sync engine]
  C --> D[Refresh CloudKit fleet]
  D --> E[Delete device and snapshots]
  E --> F[Local fleet cache]
  F --> G[Settings and menu]
Loading

Decision needed

Question Recommendation
Should this work remain a narrow stale non-current-device cleanup, or should CodexBar adopt the proposed current-device reset and hardware-identity lifecycle changes? Narrow to stale-device removal: Restrict the destructive action to non-current devices and defer the hardware-identity migration or current-device reset to a separately approved design.

Why: The PR intentionally goes beyond the reported cleanup, and its current-device behavior needs a defined lifecycle before the implementation can be judged safe.

Before merge

  • Add real behavior proof - Needs real behavior proof before merge: The changed production owners are the settings action and CloudSyncEngine deletion path, but the PR body confirms that deletion, confirmation, and error presentation were not exercised on an entitled signed build; tests and a disabled-control observation do not prove the after-fix CloudKit flow. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Prevent current-device snapshots from becoming orphaned (P1) - This enables deletion for the current Mac as well as stale Macs. After its Device Record is removed, the normal snapshot queue can publish this Mac’s snapshots without re-registering the device first, leaving menu data with no Mac row through which the user can remove it. Restrict removal to non-current devices, or make reset re-register/order writes before snapshots resume.
  • Resolve merge risk (P1) - Removing the current Mac can allow later snapshot publishing without re-registering its Device Record, leaving usage data with no corresponding row through which to remove it.
  • Resolve merge risk (P1) - The branch deliberately expands the requested stale-device cleanup into a current-device reset and hardware-derived identity migration, changing existing fleet lifecycle behavior without maintainer approval.
  • Resolve merge risk (P1) - No entitled signed-build or production-path CloudKit evidence shows complete deletion, already-absent deletion, and surfaced failure behavior.
  • Complete next step (P2) - Maintainer product direction is required for the expanded current-device reset and identity-migration scope; real CloudKit proof is also still required from the contributor.

Findings

  • [P1] Prevent current-device snapshots from becoming orphaned — Sources/CodexBar/PreferencesICloudSyncPane.swift:78-80
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Source and test delta sources +379/-58, tests +211/-4 The implementation grows beyond a UI control into persistence, identity, CloudKit lifecycle, localization, and tests.

Root-cause cluster

Relationship: fixed_by_candidate
Canonical: #3234
Summary: This PR is the open candidate implementation for the stale iCloud device-record cleanup reported in the canonical issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge-risk options

Maintainer options:

  1. Narrow the destructive action (recommended)
    Hide or disable removal for the current device so stale-device cleanup cannot create an orphan snapshot lifecycle.
  2. Approve and complete reset semantics
    If current-device removal is intentional, define and test how device registration and future snapshot writes remain consistent after reset.
  3. Pause the expanded scope
    Defer the identity migration and current-device behavior until maintainers choose the fleet lifecycle contract.

Technical review

Best possible solution:

Limit removal to non-current stale devices unless maintainers explicitly want reset semantics, then make that reset preserve a removable/re-registered device before snapshot writes resume and verify it on an entitled build.

Do we have a high-confidence way to reproduce the issue?

Yes—source establishes the path: remove the current device, then allow that Mac’s normal snapshot queue to send again without a corresponding device re-registration. This review did not run the entitled CloudKit path because the checkout is read-only and the contributor reports no suitable signed build.

Is this the best way to solve the issue?

No. The current implementation makes an unapproved current-device reset available without preserving the device-to-snapshot lifecycle; a non-current-only action or an explicitly ordered reset is safer.

Full review comments:

  • [P1] Prevent current-device snapshots from becoming orphaned — Sources/CodexBar/PreferencesICloudSyncPane.swift:78-80
    This enables deletion for the current Mac as well as stale Macs. After its Device Record is removed, the normal snapshot queue can publish this Mac’s snapshots without re-registering the device first, leaving menu data with no Mac row through which the user can remove it. Restrict removal to non-current devices, or make reset re-register/order writes before snapshots resume.
    Confidence: 0.9

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against c3a25fd85ff0.

Labels

Label justifications:

  • P2: This is a bounded but user-visible iCloud Sync lifecycle change with limited affected scope.
  • merge-risk: 🚨 compatibility: New hardware-derived device identity and current-device removal alter behavior for existing iCloud Sync fleets.
  • merge-risk: 🚨 session-state: The change can leave fleet snapshot state without its owning device record after current-device removal.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The changed production owners are the settings action and CloudSyncEngine deletion path, but the PR body confirms that deletion, confirmation, and error presentation were not exercised on an entitled signed build; tests and a disabled-control observation do not prove the after-fix CloudKit flow. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

  • Current-device deletion trigger: The introduced row action enables the same removal control for the current device as for stale devices; it passes that device ID into the deletion path. (Sources/CodexBar/PreferencesICloudSyncPane.swift:78, bb885b559b99)
  • Orphaned-snapshot path: Removal deletes the current device’s fleet records, while the existing snapshot queue independently accepts and sends snapshots from that Mac; no ordering or re-registration guard connects the two paths. (Sources/CodexBar/Sync/CloudSyncEngine.swift:1312, bb885b559b99)
  • Prior P1 addressed: The head commit adds a successful CloudKit refresh before constructing the deletion set, addressing the prior cache-incomplete snapshot finding. (Sources/CodexBar/Sync/CloudSyncEngine.swift:1322, bb885b559b99)
  • Contributor-provided proof gap: The PR body explicitly says removal, confirmation, and failure-banner behavior were not verified on an entitled signed build; tests and checks are supplemental rather than proof of the CloudKit deletion path. (bb885b559b99)
  • Feature history: Recent iCloud Sync architecture and snapshot-migration work is attributed to Peter Steinberger and sf-jin-ku; the local history walk could not be extended through missing promisor objects because network resolution failed. (Sources/CodexBar/Sync/CloudSyncEngine.swift:442, 84e4adc94048)

Likely related people:

  • steipete: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • sf-jin-ku: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Restrict current-device deletion or implement a defined reset transaction that cannot publish snapshots before device registration is consistent.
  • Add redacted after-fix entitled-build or production-path evidence for successful deletion, already-absent deletion, and a surfaced failure; update the PR body to trigger re-review.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (2 earlier review cycles)
  • reviewed 2026-09-01T06:30:05.819Z sha 2331691 :: needs real behavior proof before merge. :: [P1] Reconcile all remote snapshots before completing removal | [P2] Retain a recovery handle for partial snapshot deletion | [P2] Clear resolved unknown-item deletion errors
  • reviewed 2026-09-01T10:47:07.002Z sha 39bc822 :: needs real behavior proof before merge. :: [P1] Reconcile the remote snapshot set before deleting a device

Addresses two findings from the Codex/ClawSweeper review of 2331691.

[P2] Retain a recovery handle for partial snapshot deletion
(CloudSyncEngine.swift:1353-1358). When CloudKit confirms the Device
Record delete but terminally rejects one of its Usage Snapshot deletes,
the snapshot kept projecting into the fleet menu with no Macs row left to
remove it from. Rather than hold the row open for a delete that will not
be retried, the confirmed device delete now takes its orphaned snapshots
with it, so nothing unreachable is displayed.

[P2] Clear resolved unknown-item deletion errors
(CloudSyncEngine.swift:849-852). An all-unknownItem delete result is a
removal that landed, but a non-empty failedRecordDeletes kept the red
banner up. The banner now clears on reportable failures being absent, and
counts confirmed deletes as push progress.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UxuRSmcgehfT9gxRzczXGQ
@kwnms04

kwnms04 commented Sep 1, 2026

Copy link
Copy Markdown
Author

Pushed 39bc822 addressing two of the review findings.

Clear resolved unknown-item deletion errors (CloudSyncEngine.swift:849-852) — the banner now clears when the remaining delete failures are non-reportable, and confirmed deletes count as push progress. An all-unknownItem result no longer leaves a red banner on a removal that landed.

Retain a recovery handle for partial snapshot deletion (CloudSyncEngine.swift:1353-1358) — resolved by removing the problem rather than keeping the row: a confirmed Device Record delete now drops the Usage Snapshots that device left behind (CloudSyncDeviceRemoval.orphanedSnapshotNames), so no snapshot is projected into the fleet menu without a Macs row to remove it from. Holding the row open would have offered a retry for a delete that is deliberately not retried. Covered by snapshots of a removed device go with it.

Still open:

  • [P1] Reconcile all remote snapshots before completing removal — removal still works off the local fleetSnapshots cache.
  • Real behavior proof on an entitled signed build (confirmed / partial-failure / already-absent).
  • Owner decision on the device-identity migration and current-Mac removal scope.

I'm trying to close those 3 findings.

Addresses [P1] Reconcile all remote snapshots before completing removal
from the review of 2331691.

Removal built its delete set from the fleet cache alone, so a usage
snapshot published since the last fetch outlived the device record it
belonged to, with no Macs row left to remove it from. Removal now fetches
first and builds the set from what comes back.

A fetch that fails leaves no grounds to delete anything, so it stops the
removal; fetchChanges reports its outcome for that, and already surfaces
the error itself. This is the same rule the confirmed-delete path follows:
nothing is retired on a result CloudKit did not give us.

A CKQuery for the device's snapshots was the reviewer's suggestion and
would guarantee no more: both are authoritative only up to the moment they
run. Records published after that are out of reach either way, which is
the intended outcome for a live Mac that re-registers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UxuRSmcgehfT9gxRzczXGQ
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 session-state 🚨 Merging this PR could lose, corrupt, stale, or mis-associate session or agent state. label Sep 1, 2026
@kwnms04

kwnms04 commented Sep 1, 2026

Copy link
Copy Markdown
Author

Pushed 39bc822 and bb885b5, addressing all three findings.

[P1] Reconcile all remote snapshots (CloudSyncEngine.swift:1307) — removal now fetches zone changes first and builds the delete set from what comes back, rather than from the local cache alone. A failed fetch stops the removal instead of deleting against an unverified set. A CKQuery would guarantee no more: both are authoritative only up to the moment they run.

[P2] Retain a recovery handle for partial snapshot deletion (:1353-1358) — resolved by removing the problem rather than keeping the row: a confirmed Device Record delete now drops the Usage Snapshots that device left behind, so none is projected with no Macs row to remove it from. Holding the row open would offer a retry for a delete that is deliberately not retried.

[P2] Clear resolved unknown-item deletion errors (:849-852) — the banner clears when the remaining delete failures are non-reportable, and confirmed deletes count as push progress.

Still open, both outside the diff:

  • Real behavior proof on an entitled signed build (confirmed / partial-failure / already-absent).
  • Owner decision on the device-identity migration and current-Mac removal scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 session-state 🚨 Merging this PR could lose, corrupt, stale, or mis-associate session or agent state. P2 Normal priority bug or improvement with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No way to remove a stale duplicate device record in iCloud Sync

1 participant