Skip to content

feat: iOS Companion App & iCloud KVS Sync#1359

Open
tiagodocouto wants to merge 5 commits into
steipete:mainfrom
tiagodocouto:feat/ios-companion-icloud-kvs
Open

feat: iOS Companion App & iCloud KVS Sync#1359
tiagodocouto wants to merge 5 commits into
steipete:mainfrom
tiagodocouto:feat/ios-companion-icloud-kvs

Conversation

@tiagodocouto

Copy link
Copy Markdown

Adds an iOS Companion App and switches the macOS app's device-to-device sync to iCloud Key-Value Store (KVS), removing the previous Tailscale/HTTP tunnel entirely.

iOS Companion App

  • New CodexBarCompanion, a lightweight SwiftUI iOS app.
  • Mirrors the macOS menubar usage stats, charts, and progress bars.
  • Reads its data exclusively from iCloud KVS (no local network dependency).
  • Adjustable refresh interval (1–10 min) via the clock control in the header.

iCloud KVS Sync

  • macOS serializes the CompanionCardModel payload into NSUbiquitousKeyValueStore on every refresh (StatusItemController+Companion).
  • iOS observes didChangeExternallyNotification and reads the same key, so updates propagate automatically across the user's Apple devices.
  • The KVS identifier is $(TeamIdentifierPrefix)com.steipete.codexbar, shared by both the macOS app entitlement and the iOS companion so they address the same container.

UI & Architecture

  • Empty states: StatusItemController/MenuCardView hide providers with no data or that are logged out (e.g. Gemini "not logged in").
  • iCloud-only: removed the local HTTP server, the Tailscale IP entry field, and the cleartext-HTTP fallback (and its ATS exception). The companion entitlement is now KVS-only — no CloudKit/APS containers.

Build script

  • package_app.sh injects com.apple.application-identifier, com.apple.developer.team-identifier, and com.apple.developer.ubiquity-kvstore-identifier from the resolved $APP_TEAM_ID/$BUNDLE_ID.
  • Optionally embeds a local codexbar-macos.provisionprofile (gitignored) for AMFI validation of iCloud entitlements during local debug builds.

Fork owners

To build with iCloud KVS support:

  1. Register your App ID with the iCloud (Key-Value Store) capability.
  2. Generate a macOS App Development provisioning profile for it.
  3. Save it as codexbar-macos.provisionprofile in the repo root (gitignored; auto-embedded by the build script).
  4. Keep only ONE matching development certificate in your Keychain to avoid codesign ambiguity.
  5. Build with APP_TEAM_ID set to your own team so the macOS app and the companion share the same KVS container.

Verification

  • macOS (swift build): ✅ build complete.
  • iOS companion (xcodebuild, iOS 26 simulator): ✅ build succeeded.

Screenshots — iOS Companion

Overview Codex Claude Antigravity

Adds an iOS Companion App and switches the macOS app's device-to-device sync to iCloud Key-Value Store (KVS), removing the previous Tailscale/HTTP tunnel entirely.

### iOS Companion App
- Created `CodexBarCompanion`, a lightweight SwiftUI iOS application.
- Mirrors the macOS menubar usage stats, charts, and progress bars.
- Reads its data exclusively from iCloud KVS (no local network dependency).
- Adjustable refresh interval (1–10 min) via the clock control in the header.

### iCloud KVS Sync
- macOS serializes the `CompanionCardModel` payload into `NSUbiquitousKeyValueStore` on every refresh (`StatusItemController+Companion`).
- iOS observes `didChangeExternallyNotification` and reads the same key, so updates propagate automatically across the user's Apple devices.
- The KVS identifier is `$(TeamIdentifierPrefix)com.steipete.codexbar`, shared by both the macOS app entitlement and the iOS companion so they address the same container.

### UI & Architecture Improvements
- **Empty States**: `StatusItemController` and `MenuCardView` automatically hide providers that have no data or are not logged in (e.g. Gemini "not logged in"), saving screen space.
- **iCloud-only**: removed the local HTTP server, the Tailscale IP entry field, and the cleartext-HTTP fallback (along with its ATS exception). The companion entitlement is now KVS-only — no CloudKit/APS containers.

### Build Script Enhancements
- `package_app.sh` injects `com.apple.application-identifier`, `com.apple.developer.team-identifier`, and `com.apple.developer.ubiquity-kvstore-identifier` from the script's resolved `$APP_TEAM_ID` and `$BUNDLE_ID`.
- Optionally embeds a local `codexbar-macos.provisionprofile` (gitignored) if present at the repo root, to satisfy AMFI validation for iCloud entitlements during local debug builds.

### ⚠️ IMPORTANT: Instructions for Fork Owners
To compile this project locally with iCloud KVS support, you must:
1. Register your App ID with the **iCloud (Key-Value Store)** capability in the Apple Developer Portal.
2. Generate a **macOS App Development** provisioning profile for that App ID.
3. Save it as `codexbar-macos.provisionprofile` in the repo root (gitignored; the build script auto-detects and embeds it).
4. Keep only ONE matching development certificate in your Keychain to avoid `codesign` ambiguity.
5. Build with `APP_TEAM_ID` set to your own team so the macOS app and the iOS companion sign under the same team and share the same KVS container.
@clawsweeper

clawsweeper Bot commented Jun 8, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed June 9, 2026, 7:20 PM ET / 23:20 UTC.

Summary
The PR adds a SwiftUI iOS companion app, opt-in macOS iCloud KVS sync, optional macOS iCloud entitlements in packaging, localized settings copy, screenshots, and companion sync tests.

Reproducibility: not applicable. this is a new iOS companion and iCloud sync feature, not a reported current-main bug. The gating evidence is real signed behavior proof rather than a bug reproduction path.

Review metrics: 2 noteworthy metrics.

  • Diff size: 41 files, +2055/-0. This is a broad feature and platform addition, not a narrow bug fix.
  • Signing surface: 1 package script plus 2 iOS signing config files. iCloud KVS only works when macOS and iOS entitlements resolve to the same team/container.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🦐 gold shrimp
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted live proof showing the macOS writer log and iOS reader/cards from the same signed iCloud KVS container.
  • Align iOS signing/team configuration with the macOS APP_TEAM_ID/KVS container and document the supported release/debug path.
  • Reset the iOS selection when the synced payload no longer contains the selected provider.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: Screenshots and tests are useful, but they do not show a signed macOS KVS write being read by the iOS app; add redacted logs or a recording, update the PR body, and ask for re-review if it does not rerun automatically.

Risk before merge

  • [P1] The iCloud path changes CodexBar's local-data/privacy boundary by storing usage-card payloads in iCloud KVS when the new setting is enabled, so it needs maintainer sign-off and live signed proof.
  • [P1] The macOS packaging flag and iOS target signing settings are not a single source of truth yet, so fork, debug, or release builds can miss the shared KVS container.
  • [P1] The available screenshots and unit proof do not show a real macOS KVS write being read by the iOS app in a signed setup.

Maintainer options:

  1. Align signing before merge (recommended)
    Make the iOS and macOS targets derive the team ID and KVS container from one documented source, then prove fresh and fork-owner builds use the same container.
  2. Approve as opt-in beta
    Maintainers can intentionally accept the Apple Developer setup burden if they want this to land as an opt-in companion feature before the release path is fully smooth.
  3. Split the companion work
    Pause or split the iOS app from macOS sync if the repository is not ready to own a second platform and iCloud signing support yet.

Next step before merge

  • [P1] Needs contributor live proof and maintainer product/signing/privacy approval; the code findings are fixable, but automation cannot prove the signed iCloud setup.

Security
Needs attention: The diff adds an opt-in iCloud KVS data-storage path and entitlement surface, so privacy/signing approval and live proof are still needed.

Review findings

  • [P1] Keep the iOS KVS team aligned with the macOS build — CodexBarCompanion/CodexBarCompanion.xcodeproj/project.pbxproj:273
  • [P2] Reset selection when the synced provider disappears — CodexBarCompanion/CodexBarCompanion/ContentView.swift:194
Review details

Best possible solution:

Land only after iOS and macOS share a configurable signing/KVS contract, the selected-provider update edge case is fixed, and maintainers approve the privacy/release path with redacted live-sync proof.

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

Not applicable; this is a new iOS companion and iCloud sync feature, not a reported current-main bug. The gating evidence is real signed behavior proof rather than a bug reproduction path.

Is this the best way to solve the issue?

Unclear; iCloud KVS is a plausible narrow transport, but the current branch still has signing/config drift and no live signed KVS proof, so maintainers cannot yet treat it as the best release path.

Full review comments:

  • [P1] Keep the iOS KVS team aligned with the macOS build — CodexBarCompanion/CodexBarCompanion.xcodeproj/project.pbxproj:273
    The companion target hardcodes DEVELOPMENT_TEAM = Y5PE65HELJ, but the macOS package path derives its KVS entitlement from APP_TEAM_ID. Fork or debug builds can sign macOS with one team while iOS stays on another team or fails to sign, so both apps will not reliably share the same KVS container. Use one documented team/container source for both targets or leave the iOS team configurable.
    Confidence: 0.86
  • [P2] Reset selection when the synced provider disappears — CodexBarCompanion/CodexBarCompanion/ContentView.swift:194
    After filtering the KVS payload, selectedProviderID is only reset when nil, but it starts as overview and can later point to a provider that the new payload removed. Hiding a provider or receiving a payload without the selected provider can leave the page view bound to a tag that no longer exists; reset to overview when the current selection is absent from models.
    Confidence: 0.78

Overall correctness: patch is incorrect
Overall confidence: 0.84

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against a4f278d91fe4.

Label changes

Label justifications:

  • P2: The PR is a normal-priority feature with meaningful user value but bounded by opt-in behavior and maintainer approval needs.
  • merge-risk: 🚨 compatibility: Hardcoded iOS signing and configurable macOS APP_TEAM_ID can leave users with builds that do not share a KVS container.
  • merge-risk: 🚨 security-boundary: Merging adds an opt-in path that uploads usage-card data to iCloud KVS, changing CodexBar's data-storage/privacy boundary.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: Screenshots and tests are useful, but they do not show a signed macOS KVS write being read by the iOS app; add redacted logs or a recording, update the PR body, and ask for re-review if it does not rerun automatically.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. Screenshots and tests are useful, but they do not show a signed macOS KVS write being read by the iOS app; add redacted logs or a recording, update the PR body, and ask for re-review if it does not rerun automatically.
Evidence reviewed

Security concerns:

  • [medium] New iCloud storage boundary needs approval — Sources/CodexBar/StatusItemController+Companion.swift:22
    Once opt-in is enabled, the macOS app serializes usage cards to iCloud KVS and includes account email unless hidePersonalInfo is on; that is a meaningful data-storage/privacy boundary change that should not merge without maintainer approval and signed live proof.
    Confidence: 0.86

What I checked:

  • Repository policy read: AGENTS.md was read in full; its SwiftPM, signing, focused-test, and no-Keychain-prompt guidance informed the review constraints. (AGENTS.md:1, a4f278d91fe4)
  • Vision sign-off boundary: VISION.md says new features and behavior affecting data storage, releases, or user privacy need sign-off, which applies to opt-in iCloud KVS sync and the new iOS target. (VISION.md:1, a4f278d91fe4)
  • PR sync implementation: The PR head writes encoded companion models into NSUbiquitousKeyValueStore and includes email unless hidePersonalInfo is enabled. (Sources/CodexBar/StatusItemController+Companion.swift:22, 8712afcafcc4)
  • Signing mismatch evidence: The iOS target hardcodes DEVELOPMENT_TEAM while the macOS package path derives its KVS entitlement from APP_TEAM_ID, leaving no single team/container source across both apps. (CodexBarCompanion/CodexBarCompanion.xcodeproj/project.pbxproj:273, 8712afcafcc4)
  • Mac packaging gate: The PR gates macOS iCloud entitlement injection behind CODEXBAR_ICLOUD_COMPANION and builds the KVS identifier from APP_TEAM_ID plus BUNDLE_ID. (Scripts/package_app.sh:155, 8712afcafcc4)
  • Proof still pending: The contributor provided screenshots, unit-test output, and log marker names, but explicitly said a redacted live recording would be attached later once both devices are on the same signed build. (8712afcafcc4)

Likely related people:

  • Peter Steinberger: Current main history shows repeated recent work on StatusItemController, MenuCardView, package_app.sh, releases, and appcast/versioning, all central to this PR's sync and signing surface. (role: recent area and release-signing owner; confidence: high; commits: a4f278d91fe4, 920997c6a365, d8b7619de439; files: Sources/CodexBar/StatusItemController.swift, Sources/CodexBar/MenuCardView.swift, Scripts/package_app.sh)
  • Thiago Costa: Current main includes prior merged work by the same contributor on the local CLI serve surface, localization, provider routing, and settings-like features, which are adjacent to this companion/sync proposal. (role: adjacent current-main contributor and PR proposer; confidence: medium; commits: 74a019c4aa65, 22c44848d5a2, 7e53a12db668; files: Sources/CodexBarCLI/CLIServeCommand.swift, Tests/CodexBarTests/CLIServeRouterTests.swift, Sources/CodexBar/Resources/pt-BR.lproj/Localizable.strings)
  • Zhongyue Lin: Current history shows recent provider-cost menu card work, which is one of the card surfaces serialized and re-rendered by the companion app. (role: adjacent menu-card contributor; confidence: medium; commits: 8fccb454acbb; files: Sources/CodexBar/MenuCardView.swift, Sources/CodexBar/StatusItemController+CostMenuCard.swift, Tests/CodexBarTests/StatusMenuCostMenuCardTests.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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.

How this review workflow works
  • 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.

@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: d363a523a8

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

withObservationTracking {
_ = self.store.menuObservationToken
} onChange: { [weak self] in
Task { @MainActor [weak self] in

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 Sync companion after settings changes

Because the companion payload is refreshed only from the store-observation path and startup, settings-only changes that affect the rendered card never update iCloud KVS. For example, toggling hidePersonalInfo or disabling/reordering providers is handled by handleSettingsChange() and redraws the macOS menu, but the previously synced payload can keep exposing the old email/plan/provider list on the iOS companion until a later usage refresh happens. Please also call syncCompanion() from the settings-change path that rebuilds/invalidate menus.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. 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. labels Jun 8, 2026
…ilter

Responds to the ClawSweeper/Codex review on steipete#1359:

- [P1] iCloud companion sync is now OPT-IN (off by default) via a new
  `companionSyncEnabled` setting (Preferences → Advanced). When disabled,
  syncCompanion() clears any previously-synced KVS payload so upgrades never
  leave usage data in iCloud. Email is omitted from the payload when
  `hidePersonalInfo` is enabled (data minimization).
- [P1] package_app.sh no longer injects iCloud entitlements into every build.
  They are gated behind CODEXBAR_ICLOUD_COMPANION=1; default/local/adhoc/fork/
  release builds are unchanged and need no Apple iCloud App ID or profile.
- [P2] iOS reader keeps content-bearing cards (cost/notes/credits/placeholder)
  instead of dropping everything without quota metrics (hasDisplayableContent).
- [P2] syncCompanion() is now also called from handleSettingsChange(), so
  toggling hidePersonalInfo / hiding / reordering providers refreshes the
  companion payload instead of leaving stale data on iOS.

Proof: adds CompanionSyncProofTests (JSON round-trip + content filter) and
os_log markers on the macOS writer and iOS reader for live KVS verification.
@tiagodocouto

Copy link
Copy Markdown
Author

Thanks for the thorough review — all four findings addressed in 37830505.

Review findings

Finding Status Change
[P1] Gate iCloud sync behind explicit opt-in (StatusItemController.swift:379) ✅ Fixed New companionSyncEnabled setting, OFF by default (Preferences → Advanced). syncCompanion() early-returns when disabled and removes any previously-synced latestUsageSync value from KVS, so upgraded users never get data uploaded without consent. Email is also dropped from the payload when hidePersonalInfo is on (data minimization).
[P1] Keep default packaging independent of iCloud (package_app.sh:161-166) ✅ Fixed The iCloud entitlements (application-identifier, team-identifier, ubiquity-kvstore-identifier) and the provisioning-profile embed are now gated behind CODEXBAR_ICLOUD_COMPANION=1. Default / local / adhoc / fork / release builds are unchanged and need no Apple iCloud App ID or profile.
[P2] Do not drop non-quota companion cards (ContentView.swift:193) ✅ Fixed Filter is now hasDisplayableContent (metrics or providerCost / tokenUsage / credits / usageNotes / placeholder), so cost-only / note-only / error-only providers are kept.
[P2] Sync companion after settings changes (StatusItemController.swift:445) ✅ Fixed syncCompanion() is now also invoked from handleSettingsChange(), so toggling hidePersonalInfo / hiding / reordering providers refreshes the KVS payload instead of leaving stale email/plan on iOS.

Proof

Unit proof — the KVS value is plain JSON, so this verifies the macOS-writer → iOS-reader round-trip and the content filter (Tests/CodexBarTests/CompanionSyncProofTests.swift):

$ swift test --filter CompanionSync
✔ Test "Payload survives the JSON round-trip that crosses iCloud KVS" passed
✔ Test "Content filter keeps content-bearing cards that have no quota metrics" passed
✔ Suite "Companion KVS sync" passed — 2 tests

Live-sync observability — added os_log markers on both ends so the real cross-device path is verifiable in Console.app:

  • macOS writer: Companion sync → iCloud KVS: <N> providers, <M> bytes
  • iOS reader: Companion read ← iCloud KVS: <N> cards

To reproduce end-to-end (opt-in on, same iCloud account on both devices): enable Preferences → Advanced → “Sync to iOS app (iCloud)”, trigger a refresh on macOS, and both log lines fire in order. I'll attach a redacted screen recording of that path once I have both devices on the same signed build.

Builds: macOS swift build ✅ · iOS companion xcodebuild (iOS 26 sim) ✅.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 8, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

…cales)

- Add CompanionSyncProofTests.optInDefaultsOff: a fresh SettingsStore returns
  companionSyncEnabled == false, directly proving the privacy default.
- Add companion_sync_title/subtitle to the remaining 9 locales (es, fr, ca, nl,
  sv, vi, uk, zh-Hans, zh-Hant) so non-English builds don't fall back to English.
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 8, 2026
Resolve conflict in StatusItemController.swift: upstream refactored the
store-change observation callback into handleObservedStoreMenuChange().
Re-applied the companion sync by calling self.syncCompanion() inside that
new method (right after observeStoreChanges()), preserving the PR's intent
of refreshing the iOS companion KVS payload on every usage refresh.
Addresses ClawSweeper [P2] (CompanionCardView.swift:38-46): hasDisplayableContent
keeps cards that only have providerCost / tokenUsage / creditsText (no metrics),
but the view's body branched on metrics.isEmpty and only rendered usageNotes or a
placeholder in that case — so cost-only / credits-only providers showed a blank
header + divider with the actual details missing.

Hoist hasUsage/hasCredits/hasCost out of the metrics-empty branch and render the
full content block whenever any of them is present; fall back to the placeholder
only when there is no content at all. Also include creditsText in hasDetails so
credits-only cards get the header divider/padding for consistency.
@tiagodocouto

Copy link
Copy Markdown
Author

Rebased onto latest main and addressed the open [P2] rendering finding.

Merge conflict resolved

main refactored the store-change observation callback into handleObservedStoreMenuChange() (extracting observeStoreChanges() + invalidateMenus(...)), which collided with the syncCompanion() call this PR had inserted in that block. Resolved by keeping upstream's refactor and re-applying self.syncCompanion() inside handleObservedStoreMenuChange() (right after observeStoreChanges()), so the iOS companion KVS payload still refreshes on every usage refresh. The startup and handleSettingsChange() call sites auto-merged cleanly. PR is now mergeable.

Review finding

Finding Status Change
[P2] Render content-bearing cards without quota metrics (CompanionCardView.swift:38-46) ✅ Fixed The view's body branched on metrics.isEmpty and only rendered usage notes or a placeholder in that case, so cost-only / credits-only / token-usage-only cards (which hasDisplayableContent keeps) showed a blank header + divider. Hoisted hasUsage / hasCredits / hasCost out of the metrics-empty branch and now render the full content block whenever any of them is present; the placeholder is shown only when there is no content at all. Also added creditsText to hasDetails so credits-only cards get the header divider/padding for consistency.

Verification

  • macOS swift build
  • iOS companion xcodebuild (iOS Simulator) ✅ — CompanionCardView.swift compiles
  • swift test --filter CompanionSync ✅ — 3/3 (JSON round-trip, opt-in defaults OFF, content filter keeps content-bearing cards)
  • Note: StatusMenuSwitcherRefreshTests."merged provider switch restores cached tab content" fails locally, but it fails identically on a clean main checkout as well — pre-existing/environment-sensitive, not introduced by this merge.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 9, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

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: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P2 Normal priority bug or improvement with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant