Skip to content

iOS: add in-app share diagnostics - #7006

Closed
austinywang wants to merge 45 commits into
mainfrom
issue-5515-ios-in-app-share-diagnostics-copy-share-logs
Closed

austinywang wants to merge 45 commits into
mainfrom
issue-5515-ios-in-app-share-diagnostics-copy-share-logs

Conversation

@austinywang

@austinywang austinywang commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #5515

Summary

  • Adds a release-safe mobile diagnostics report builder with secret scrubbing, app/device metadata, auth/connection state, event logs, debug log, and recent OSLog lines.
  • Wires Share Diagnostics into the iOS workspace detail menu with Copy and ShareLink actions.
  • Injects diagnostics logs in Release/TestFlight and records redacted auth/connection transitions.

Validation

  • git diff --check
  • python3 -m json.tool ios/cmux/Resources/Localizable.xcstrings >/dev/null
  • python3 scripts/check-workspace-package-groups.py --check
  • Localization audit: added en/ja entries for mobile.diagnostics.close/copy/share/shareAction and checked both locales are present.

Local dev builds and xcodebuild were intentionally not run per issue instructions.


Summary by cubic

Adds in‑app Share Diagnostics on iOS so users can copy or share a redacted report from the Workspace menu. Tightens privacy and improves support/triage for #5515.

  • New Features

    • Introduces CmuxMobileDiagnostics: secret scrubber, report builder, store‑scoped in‑app event log, and a current‑process OSLog reader that omits message bodies and preserves an “OSLog unavailable” status.
    • Adds a “Share Diagnostics” sheet with selectable text, Copy, and Share; shows app/device info, auth (with last display‑safe error), connection (host/last error), in‑app events, debug‑log line count, and OSLog count/status; omits the process‑wide structured log for account‑scoped privacy; adds en/ja strings.
    • Builds a structured DiagnosticLog for all builds to stamp feedback; it remains private in Release and is exportable only on DEBUG.
  • Bug Fixes

    • Records display‑safe auth failures via AuthCoordinator.lastAuthError across send/verify code, OAuth, password sign‑in, token read/refresh, and offline checks; clears on successful sign‑in.
    • Protects shared‑device privacy and stability: blanks host before disconnect, scrubs and retains lastConnectionError, scopes the diagnostics event log to the shell store and swaps in a fresh instance on sign‑out to avoid races and cross‑account leakage, and cancels report work if the sheet is dismissed; gates structured diagnostic‑log export to DEBUG in privileged feedback.
    • Improves Xcode 16 compatibility with nonisolated loggers, a Sendable notification‑status read, and compiler‑guarded iOS 26 glass APIs.

Written for commit 89e665d. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added an in-app iOS “Share Diagnostics” sheet with a selectable, copy/shareable report and automatic secret redaction.
    • The report now includes app metadata, auth/connection status, in-app events, structured diagnostics events, and recent OS log entries.
    • Added diagnostics event logging for sign-in/out and connection error changes.
  • Bug Fixes
    • Improved authentication error tracking so the most recent display-safe auth failure is consistently captured.
    • Hardened chat UI keyboard handling and iOS 26-related scrolling/glass styling across compiler versions.
  • Tests
    • Added/updated unit tests for diagnostics report formatting/redaction and auth offline/unauthorized error assertions.

@vercel

vercel Bot commented Jun 26, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jul 5, 2026 5:04am
cmux-staging Building Building Preview, Comment Jul 5, 2026 5:04am

@coderabbitai

coderabbitai Bot commented Jun 26, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds auth failure tracking, mobile diagnostics data/reporting, in-app diagnostics sharing, and compiler-gated chat UI updates.

Changes

Diagnostics sharing and auth telemetry

Layer / File(s) Summary
Auth failure recording
Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthError.swift, Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift, Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator+SessionPriming.swift, Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator+Tokens.swift, Packages/Shared/CmuxAuthRuntime/Tests/CmuxAuthRuntimeTests/AuthCoordinatorTests.swift, Packages/Shared/CmuxAuthRuntime/Tests/CmuxAuthRuntimeTests/Fakes.swift
AuthError gains stable diagnostic names, and AuthCoordinator records and clears the latest display-safe auth failure across sign-in, token, refresh, and cached-session paths; the tests cover the new offline flows and lastAuthError.
Diagnostics data and log capture
Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/*, Packages/iOS/CmuxMobileDiagnostics/Tests/CmuxMobileDiagnosticsTests/MobileDiagnosticsEventLogTests.swift, Packages/iOS/CmuxMobileDiagnostics/Tests/CmuxMobileDiagnosticsTests/MobileDiagnosticsSecretScrubberTests.swift
Adds app metadata, redacted auth/connection/event snapshot types, secret scrubbing, and the in-memory event log with eviction and redaction tests.
App, shell, and root-scene wiring
ios/cmux/AppCompositionRoot.swift, ios/cmux/cmuxApp.swift, ios/cmuxPackage/Sources/cmuxFeature/CMUXMobileRootScene.swift, Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite.swift
Removes DEBUG-only diagnostics branching, threads diagnostics logs through the app/root scene/shell store, and records auth and connection state transitions as structured events.
Diagnostics sheet UI
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift, Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDiagnosticsSheet.swift, ios/cmux/Resources/Localizable.xcstrings
Adds the workspace diagnostics sheet, report loading/copy/share actions, and the localized labels used by the new UI.

Chat UI compatibility adjustments

Layer / File(s) Summary
Compiler-gated view updates
Packages/iOS/CmuxAgentChatUI/Sources/CmuxAgentChatUI/Composer/ChatComposerView.swift, Packages/iOS/CmuxAgentChatUI/Sources/CmuxAgentChatUI/Screen/ChatScrollEdgeCoordinator.swift, Packages/iOS/CmuxAgentChatUI/Sources/CmuxAgentChatUI/Transcript/ChatTranscriptTableView.swift, Packages/iOS/CmuxAgentChatUI/Sources/CmuxAgentChatUI/Transcript/ChatTranscriptUITableView.swift, Packages/iOS/CmuxMobileSupport/Sources/CmuxMobileSupport/View+MobileGlass.swift
Adds compiler-version gates and main-actor annotations around existing chat composer, scroll-edge, transcript, and mobile-glass view code.
Tap lifecycle and accessibility label
Packages/iOS/CmuxAgentChatUI/Sources/CmuxAgentChatUI/Screen/KeyboardDismissTap.swift, Packages/iOS/CmuxAgentChatUI/Sources/CmuxAgentChatUI/Transcript/Rows/ChatFileEditCardView.swift
Updates the keyboard-dismiss tap installer to remove its recognizer when windows change, and adjusts diff-line accessibility text to reuse a stripped line prefix.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • manaflow-ai/cmux#6457: Both changes extend AuthError-related auth failure handling in Packages/Shared/CmuxAuthRuntime/....

Poem

A hop of logs, a scrubbed-out gleam,
A diagnostics sheet now joins the stream.
I nibbled secrets, left them bare no more,
Then shared the clues right out the door.
🐇✨

🚥 Pre-merge checks | ✅ 22 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes unrelated Chat*, keyboard-dismiss, and glass/compiler-gating fixes that don't belong to the diagnostics share feature. Split unrelated UI and compiler-compatibility edits into separate PRs so this change only covers in-app diagnostics sharing.
Docstring Coverage ⚠️ Warning Docstring coverage is 26.51% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description covers Summary and validation, but it omits required Demo Video, Review Trigger, and Checklist sections. Add the missing template sections: Demo Video, Review Trigger, and Checklist, and rename Validation to Testing if needed.
✅ Passed checks (22 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes match #5515 by adding a scrubbed diagnostics report, copy/share UI, event and OSLog capture, localization, and release-safe logging.
Cmux Swift Actor Isolation ✅ Passed PASS: The new diagnostics types are pure Sendable values or an actor, and all store/UI call sites I checked are explicitly MainActor-scoped.
Cmux Swift Blocking Runtime ✅ Passed Touched production code uses actors/tasks, not new semaphores/locks/sync waits; sleeps found are existing deadlines or test-only scaffolding.
Cmux Browser Automation Off-Main ✅ Passed The commit changes iOS diagnostics/UI and localization files only; no edits to TerminalController, ControlCommandExecutionPolicy, or browser.* routing/tests appear.
Cmux Expensive Synchronous Load ✅ Passed No new agent-history/file corpus load was added to a main-actor or interactive path; OSLog reading is detached and other snapshots are bounded in-memory.
Cmux Cache Substitution Correctness ✅ Passed The new diagnostics snapshot reads event-driven last-error fields and ring-buffer logs, not a stale cache replacing a fresh authoritative read.
Cmux No Hacky Sleeps ✅ Passed No covered non-Swift runtime/script files were changed; the PR only touches Swift/localization code, so the no-hacky-sleeps rule is not implicated.
Cmux Algorithmic Complexity ✅ Passed PASS: all new scans/sorts are on bounded collections (events cap 200, OSLog limit 120, tiny metadata fields); no hot-path nested rescans added.
Cmux Swift Concurrency ✅ Passed No new DispatchQueue/Combine/completion-handler APIs; the new Tasks are awaited or tied to sync SwiftUI/state callbacks, not long-lived fire-and-forget work.
Cmux Swift @Concurrent ✅ Passed No touched Swift API adds invalid @concurrent or new nonisolated async work; heavy diagnostics reads are explicitly hopped via Task.detached or actor methods.
Cmux Swift File And Package Boundaries ✅ Passed Diagnostics logic lives in a dedicated CmuxMobileDiagnostics SwiftPM target; new source files are compact (210 lines max), and oversized app/shell files were only incidentally touched.
Cmux Swiftpm Lockfiles ✅ Passed No cmux-owned .gitignore ignores Package.resolved; changed remote-dependency manifests have matching Package.resolved files, and the root Xcode lockfile is included.
Cmux Swift Logging ✅ Passed The diff only adds DEBUG-gated NSLog paths and nonisolated Logger constants; runtime auth/connection logging is redacted or privacy=.private, with no ad hoc prod logging leaks.
Cmux User-Facing Error Privacy ✅ Passed PASS: New share/report strings are generic, auth errors are reduced to AuthError., connection errors are scrubbed before storage, and raw debug/OSLog text is omitted.
Cmux Full Internationalization ✅ Passed New diagnostics UI/report strings are localized and every new key has en/ja catalog entries; reused connection strings are localized, and the only hardcoded label is DEBUG-only.
Cmux Swiftui State Layout ✅ Passed Touched SwiftUI changes add @State/task-based diagnostics UI and modern @Observable/actor diagnostics types; no new ObservableObject/@published, GeometryReader, or render-time state mutation.
Cmux Architecture Rethink ✅ Passed PASS: Diagnostics has a single WorkspaceDetailView entrypoint, clear owners (AuthCoordinator/CMUXMobileShellStore), and no added sleeps/locks/observers/duplicate wiring.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed Only adds a UIKit sheet/menu action; no new NSWindow/NSPanel/WindowGroup/NSWindowController or cmuxAuxiliaryWindowIdentifiers changes, so the rule doesn't apply.
Cmux Source Artifacts ✅ Passed All changed paths are hand-written Swift source/tests/resources (.swift, .xcstrings); no artifact dirs, logs, build output, or temp folders appear in the diff.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Touched Sources files add production diagnostics/reporting APIs; no new test-only or debug-seam accessor was added in the modified files.
Cmux No Ambient Global State ✅ Passed Changed Swift files add instance/actor-owned diagnostics types and private file-scope loggers only; no new top-level API, mutable global, or singleton was introduced.
Title check ✅ Passed The title clearly matches the main change: adding in-app diagnostics sharing on iOS.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-5515-ios-in-app-share-diagnostics-copy-share-logs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…-share-diagnostics-copy-share-logs

# Conflicts:
#	.github/swift-file-length-budget.tsv
#	ios/cmuxPackage/Sources/cmuxFeature/CMUXMobileRootScene.swift
@greptile-apps

greptile-apps Bot commented Jun 27, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds an in-app "Share Diagnostics" sheet for iOS that lets users copy or share a redacted diagnostics report from the workspace menu, and wires up the supporting infrastructure across auth, connection, and shell layers.

  • Introduces the CmuxMobileDiagnostics package: a secret-scrubbing report builder, actor-backed in-app event log, and a current-process OSLogStore reader (message bodies omitted, entries counted only in the shared report) with a proper circular-buffer implementation for the last-N semantic.
  • Adds lastAuthError to AuthCoordinator (recorded across send/verify/OAuth/password/token paths, cleared on successful sign-in) and lastConnectionError/diagnosticsEventLog to MobileShellComposite, with account-boundary hygiene: connectedHostName is blanked before the disconnect event fires on sign-out, and the event log is synchronously swapped (not async-cleared) so in-flight recordDiagnosticsEvent tasks always write to the discarded old instance.
  • Promotes DiagnosticLog from DEBUG-only to all builds for the build stamp; its structured export in the privileged dogfood feedback path remains DEBUG-only to prevent cross-account leakage on shared devices.

Confidence Score: 4/5

The diagnostics infrastructure is carefully designed with proper scrubbing, account-boundary hygiene, and privacy guards; one auth-state cleanup gap noted in a prior review cycle remains open.

lastAuthError is cleared by applySignedInUser() on a successful sign-in but is not touched by clearAuthState(), which is called unconditionally from signOut(). Between sign-out and the next successful sign-in, a shared-device user opening the diagnostics sheet would see the previous session's last auth failure in the report. This gap was called out in the previous review cycle and remains unresolved in the current diff.

AuthCoordinator.swift (clearAuthState() does not clear lastAuthError) and WorkspaceDiagnosticsSheet.swift (reads authManager.lastAuthError without a sign-out guard).

Important Files Changed

Filename Overview
Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift Adds lastAuthError (display-safe, cleared on sign-in, not cleared in clearAuthState()), recordAuthError(_:) helper, and requireOnlineForAuth() wrapper. The lastAuthError surviving clearAuthState() across sign-out is a known open issue from the previous review cycle.
Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite.swift Adds diagnosticsEventLog (swapped synchronously on sign-out to avoid race), lastConnectionError (scrubbed at write time via MobileDiagnosticsSecretScrubber), and fire-and-forget recordDiagnosticsEvent capturing old log instance through guard let to prevent cross-account leakage. Host is correctly blanked before the connectionState = .disconnected transition.
Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsOSLogStoreReader.swift Implements a correct in-place circular buffer (O(1) per entry, pre-allocated ring with index tracking) replacing the earlier sliding-window approach; correctly returns entries in chronological order when nextIndex wraps to 0. Message bodies set to empty string for privacy.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDiagnosticsSheet.swift New sheet with proper MainActor reads + utility-priority detached tasks for OSLog and report assembly. Pre-flight and post-OSLog cancellation guards prevent wasted work on dismissal. Structured event log correctly omitted from shared report with clear comment explaining account-boundary rationale.
Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsReportBuilder.swift Builds and scrubs the final report; includes only count summaries for debug log and OSLog entries (never raw content). String(format:) for count lines is on a cold, user-initiated path — not a hot-path concern.
Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsEventLog.swift Actor-backed ring buffer with scrubbing at write time. record() trims with a simple removeFirst(count - capacity) — bounded to capacity+1 entries so the trim cost is O(1) amortized in practice.
Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsSecretScrubber.swift Seven compiled regex patterns covering bearer tokens, key=value credential pairs, URL-encoded pairs, JWT-shaped strings, and email addresses. Static let patterns computed once and reused. Correct.
ios/cmux/AppCompositionRoot.swift Removes DEBUG guards around DiagnosticLog creation; MobileDiagnosticsAppInfoResolver().current().buildStamp now seeds the build stamp in all builds. Structured-log export in the feedback path retains its DEBUG gate.
ios/cmux/Resources/Localizable.xcstrings Adds 27 new localization keys for diagnostics UI and report labels, all with both en and ja translations present. Pre-existing mobile.connection.connected / mobile.connection.unavailable keys reused by the assembler are already translated.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobilePushCoordinator.swift Replaces async notificationSettings() (returns non-Sendable UNNotificationSettings) with a nonisolated continuation wrapper that extracts only the Sendable UNAuthorizationStatus enum, fixing Xcode 16.4 strict concurrency warning.
Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+DogfoodFeedback.swift Correctly gates structured-log export behind #if DEBUG to prevent cross-account leakage on shared-device Release/TestFlight builds. buildStamp fallback uses empty string in Release (caller always supplies it). Well-documented rationale.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDiagnosticsReportAssembler.swift Thin value-type assembler bridging the UI layer to the report builder; uses L10n.string() (main-bundle aware) for connection state labels, and correctly handles OSLog read failures by returning a sentinel "unavailable" entry.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift Adds isDiagnosticsSheetPresented state and wires the Share Diagnostics menu item; injects AuthCoordinator from environment to pass to the sheet. Correct SwiftUI sheet binding pattern.
Packages/iOS/CmuxMobileSupport/Sources/CmuxMobileSupport/View+MobileGlass.swift Guards all #if os(iOS) iOS 26 glass API blocks with && compiler(>=6.2) to prevent compilation failure on older Xcode toolchains that don't expose the glass APIs even under #available.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant WorkspaceDetailView
    participant WorkspaceDiagnosticsSheet
    participant MobileShellComposite
    participant AuthCoordinator
    participant MobileDiagnosticsEventLog
    participant OSLogStoreReader
    participant MobileDiagnosticsReportBuilder

    User->>WorkspaceDetailView: Tap "Share Diagnostics"
    WorkspaceDetailView->>WorkspaceDiagnosticsSheet: present sheet
    WorkspaceDiagnosticsSheet->>WorkspaceDiagnosticsSheet: .task → loadReport()
    WorkspaceDiagnosticsSheet->>MobileShellComposite: diagnosticsEventLog?.snapshot()
    MobileShellComposite->>MobileDiagnosticsEventLog: snapshot() [actor hop]
    MobileDiagnosticsEventLog-->>WorkspaceDiagnosticsSheet: [MobileDiagnosticsEvent]
    WorkspaceDiagnosticsSheet->>AuthCoordinator: isAuthenticated, lastAuthError
    WorkspaceDiagnosticsSheet->>MobileShellComposite: connectionState, connectedHostName, lastConnectionError
    WorkspaceDiagnosticsSheet->>OSLogStoreReader: recentEntries(since:limit:120) [Task.detached]
    OSLogStoreReader-->>WorkspaceDiagnosticsSheet: [MobileDiagnosticsOSLogEntry] (message bodies omitted)
    WorkspaceDiagnosticsSheet->>MobileDiagnosticsReportBuilder: buildReport() [Task.detached]
    MobileDiagnosticsReportBuilder->>MobileDiagnosticsReportBuilder: scrub(rawReport)
    MobileDiagnosticsReportBuilder-->>WorkspaceDiagnosticsSheet: String report
    WorkspaceDiagnosticsSheet-->>User: Show selectable text + Copy/Share buttons
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant WorkspaceDetailView
    participant WorkspaceDiagnosticsSheet
    participant MobileShellComposite
    participant AuthCoordinator
    participant MobileDiagnosticsEventLog
    participant OSLogStoreReader
    participant MobileDiagnosticsReportBuilder

    User->>WorkspaceDetailView: Tap "Share Diagnostics"
    WorkspaceDetailView->>WorkspaceDiagnosticsSheet: present sheet
    WorkspaceDiagnosticsSheet->>WorkspaceDiagnosticsSheet: .task → loadReport()
    WorkspaceDiagnosticsSheet->>MobileShellComposite: diagnosticsEventLog?.snapshot()
    MobileShellComposite->>MobileDiagnosticsEventLog: snapshot() [actor hop]
    MobileDiagnosticsEventLog-->>WorkspaceDiagnosticsSheet: [MobileDiagnosticsEvent]
    WorkspaceDiagnosticsSheet->>AuthCoordinator: isAuthenticated, lastAuthError
    WorkspaceDiagnosticsSheet->>MobileShellComposite: connectionState, connectedHostName, lastConnectionError
    WorkspaceDiagnosticsSheet->>OSLogStoreReader: recentEntries(since:limit:120) [Task.detached]
    OSLogStoreReader-->>WorkspaceDiagnosticsSheet: [MobileDiagnosticsOSLogEntry] (message bodies omitted)
    WorkspaceDiagnosticsSheet->>MobileDiagnosticsReportBuilder: buildReport() [Task.detached]
    MobileDiagnosticsReportBuilder->>MobileDiagnosticsReportBuilder: scrub(rawReport)
    MobileDiagnosticsReportBuilder-->>WorkspaceDiagnosticsSheet: String report
    WorkspaceDiagnosticsSheet-->>User: Show selectable text + Copy/Share buttons
Loading

Reviews (25): Last reviewed commit: "Import mobile support in diagnostics ass..." | Re-trigger Greptile

Comment thread Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite.swift Outdated
@austinywang

Copy link
Copy Markdown
Contributor Author

Addressed Greptile's diagnostics notes in db955e0: retained connection errors are now scrubbed before storage, and the OSLog reader now uses a fixed-size ring buffer instead of repeated removeFirst trimming.

…-share-diagnostics-copy-share-logs

# Conflicts:
#	.github/swift-file-length-budget.tsv
…-share-diagnostics-copy-share-logs

# Conflicts:
#	.github/swift-file-length-budget.tsv

@coderabbitai coderabbitai 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.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift (1)

222-243: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Record offline preflight failures too.

requireOnline() still runs before each new do/catch, so AuthError.offline exits these entrypoints without ever hitting recordAuthError(_). That leaves lastAuthError stale/nil for one of the most common sign-in failures, so the diagnostics report can miss the actual auth failure that just happened.

Also applies to: 248-268, 273-289, 302-323

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift`
around lines 222 - 243, sendCode currently throws from requireOnline() before
the do/catch block, so offline failures bypass recordAuthError and leave
lastAuthError stale. Update sendCode (and the same pattern in the other auth
entrypoints like the ones using runPhase and recordAuthError) to catch the
requireOnline() failure and pass it through recordAuthError(_), ensuring
AuthError.offline is recorded before rethrowing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsAppInfo.swift`:
- Around line 45-46: The report-facing strings in MobileDiagnosticsAppInfo are
currently hardcoded in English, including buildStamp and the "unknown"
fallbacks. Update the MobileDiagnosticsAppInfo properties so they either return
structured values only or use localized strings via the app’s localization flow,
and keep any final user-facing formatting in the report builder. Make sure the
symbols buildStamp, bundleIdentifier, deviceModel, and osVersion no longer
expose plain English fallback text directly.

In
`@Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsReportBuilder.swift`:
- Around line 60-82: The diagnostics report builder is still emitting hardcoded
English section headers and fallback values, so the report body is not
localized. Update MobileDiagnosticsReportBuilder to route all user-facing
strings in the report through String(localized:) keys, including section titles
and sentinel values like “none” and status labels. Add the matching entries to
Resources/Localizable.xcstrings for every supported locale, and apply the same
localization approach to the related report-building content referenced in the
same builder.

In
`@Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsSecretScrubber.swift`:
- Around line 36-61: The secret redaction rules in
MobileDiagnosticsSecretScrubber.secretPatterns only handle key=value and %3D
formats, so JSON-style fields can still leak through. Update the scrubber to
match and redact quoted JSON key/value pairs for the same sensitive keys (for
example access_token, password, token, secret, api_key, client_secret, etc.)
while keeping the existing replacements consistent. Ensure the new pattern is
added alongside the current regex list so
MobileDiagnosticsReportBuilder.buildReport benefits from redaction in shared
report payloads.

In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDiagnosticsSheet.swift`:
- Around line 109-113: The connection diagnostics builder in
WorkspaceDiagnosticsSheet is mixing two error sources by falling back from
lastConnectionError to store.connectionError, which can bypass the retained
scrubbed value. Update the MobileDiagnosticsConnectionState construction to rely
only on the authoritative diagnostics field already stored for this feature, or
ensure the live error is scrubbed and recorded before it reaches this builder.
Keep the fix localized around the connection state report so the diagnostics
path stays single-sourced and consistent.
- Around line 82-89: Move the diagnostics assembly work out of the main actor in
WorkspaceDiagnosticsSheet.buildReport(). Keep only the actor-bound state capture
on `@MainActor`, then hand off the UTF-8 decoding of the exported diagnostics blob
and the MobileDiagnosticsReportBuilder report construction to a nonisolated
helper or Task.detached before setting reportText. Use buildReport() and
MobileDiagnosticsReportBuilder as the key locations to refactor, and avoid doing
String(decoding: ...) plus final report assembly on the main thread.

In
`@Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift`:
- Around line 42-47: The shared diagnostics field lastAuthError is still falling
back to raw Swift type names for non-AuthError failures, which can leak
vendor/internal identifiers. Update AuthCoordinator’s auth-failure mapping logic
so the setter only stores curated, display-safe categories for unknown errors
instead of String(describing: type(of: error)), and apply the same replacement
to the other affected assignment path around the later auth error handling
block.

---

Outside diff comments:
In
`@Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift`:
- Around line 222-243: sendCode currently throws from requireOnline() before the
do/catch block, so offline failures bypass recordAuthError and leave
lastAuthError stale. Update sendCode (and the same pattern in the other auth
entrypoints like the ones using runPhase and recordAuthError) to catch the
requireOnline() failure and pass it through recordAuthError(_), ensuring
AuthError.offline is recorded before rethrowing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0471ee5c-0c06-445b-a943-89d03b06fb69

📥 Commits

Reviewing files that changed from the base of the PR and between 1e4b334 and a3f2407.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (24)
  • Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator+SessionPriming.swift
  • Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator+Tokens.swift
  • Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift
  • Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthError.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsAppInfo.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsAuthState.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsConnectionState.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsEvent.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsEventLog.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsOSLogEntry.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsOSLogReading.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsOSLogStoreReader.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsReportBuilder.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsSecretScrubber.swift
  • Packages/iOS/CmuxMobileDiagnostics/Tests/CmuxMobileDiagnosticsTests/MobileDiagnosticsEventLogTests.swift
  • Packages/iOS/CmuxMobileDiagnostics/Tests/CmuxMobileDiagnosticsTests/MobileDiagnosticsReportBuilderTests.swift
  • Packages/iOS/CmuxMobileDiagnostics/Tests/CmuxMobileDiagnosticsTests/MobileDiagnosticsSecretScrubberTests.swift
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDiagnosticsSheet.swift
  • ios/cmux/AppCompositionRoot.swift
  • ios/cmux/Resources/Localizable.xcstrings
  • ios/cmux/cmuxApp.swift
  • ios/cmuxPackage/Sources/cmuxFeature/CMUXMobileRootScene.swift

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift (2)

42-46: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the lastAuthError doc comment to match the new fallback.

The comment still says unknown failures retain the thrown Swift error type, but diagnosticDescription(for:) now always collapses them to AuthError.authFailure.

Suggested diff
-    /// Raw backend errors can contain opaque identifiers or token-adjacent
-    /// payloads, so diagnostics retain only ``AuthError`` case names or the
-    /// thrown Swift error type when no display-safe mapping exists.
+    /// Raw backend errors can contain opaque identifiers or token-adjacent
+    /// payloads, so diagnostics retain only ``AuthError`` case names or the
+    /// fallback category `AuthError.authFailure` when no display-safe mapping exists.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift`
around lines 42 - 46, Update the `lastAuthError` documentation in
`AuthCoordinator` so it matches `diagnosticDescription(for:)`’s current
behavior: unknown failures should no longer be described as preserving the
thrown Swift error type, but instead as collapsing to `AuthError.authFailure`.
Keep the comment aligned with the actual fallback path used for diagnostics and
reference the `lastAuthError` property and `diagnosticDescription(for:)` helper
when editing.

631-636: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Route external sign-in failures through recordAuthError(_). completeExternalSignIn() is reached from Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/BrowserSignIn/HostBrowserSignInFlow.swift, but its catch bypasses the shared diagnostics path, so seeded sign-in failures never update lastAuthError. Reuse recordAuthError(error) here instead of rethrowing the mapped error directly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift`
around lines 631 - 636, The external sign-in failure path is bypassing the
shared diagnostics update, so seeded failures never set lastAuthError. Update
completeExternalSignIn() in AuthCoordinator to route the caught error through
recordAuthError(_:) before propagating it, instead of rethrowing the mapped
error directly. Use the existing recordAuthError(_:) helper and the
completeExternalSignIn()/HostBrowserSignInFlow flow to keep the diagnostics path
consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDiagnosticsSheet.swift`:
- Around line 107-110: The connection state serialization in
WorkspaceDiagnosticsSheet uses String(describing:) on store.connectionState,
which leaks enum case names into the report. Update the
MobileDiagnosticsConnectionState construction to map each connection state
through the existing localized mobile.connection.* strings before assigning
state, keeping user-facing export text fully localized and stable against enum
renames.

---

Outside diff comments:
In
`@Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift`:
- Around line 42-46: Update the `lastAuthError` documentation in
`AuthCoordinator` so it matches `diagnosticDescription(for:)`’s current
behavior: unknown failures should no longer be described as preserving the
thrown Swift error type, but instead as collapsing to `AuthError.authFailure`.
Keep the comment aligned with the actual fallback path used for diagnostics and
reference the `lastAuthError` property and `diagnosticDescription(for:)` helper
when editing.
- Around line 631-636: The external sign-in failure path is bypassing the shared
diagnostics update, so seeded failures never set lastAuthError. Update
completeExternalSignIn() in AuthCoordinator to route the caught error through
recordAuthError(_:) before propagating it, instead of rethrowing the mapped
error directly. Use the existing recordAuthError(_:) helper and the
completeExternalSignIn()/HostBrowserSignInFlow flow to keep the diagnostics path
consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 03cfbd38-dd63-4e11-9a1d-7e980211dda1

📥 Commits

Reviewing files that changed from the base of the PR and between a3f2407 and b9ae83e.

📒 Files selected for processing (7)
  • Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsAppInfo.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsReportBuilder.swift
  • Packages/iOS/CmuxMobileDiagnostics/Sources/CmuxMobileDiagnostics/MobileDiagnosticsSecretScrubber.swift
  • Packages/iOS/CmuxMobileDiagnostics/Tests/CmuxMobileDiagnosticsTests/MobileDiagnosticsSecretScrubberTests.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDiagnosticsSheet.swift
  • ios/cmux/Resources/Localizable.xcstrings

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift (1)

42-46: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the lastAuthError docs to match the redaction contract.

The comment still says unknown failures are stored as the thrown Swift error type, but diagnosticDescription(for:) now collapses those to AuthError.authFailure. Leaving the old wording here advertises a leakier contract than the code actually guarantees. Based on the PR objective and downstream diagnostics contract, this field should describe only display-safe auth categories.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift`
around lines 42 - 46, The documentation for lastAuthError in AuthCoordinator
should be updated to reflect the current redaction behavior. Adjust the comment
near diagnosticDescription(for:) so it no longer says unknown failures preserve
the thrown Swift error type; instead, state that only display-safe AuthError
categories are retained and uncategorized failures collapse to
AuthError.authFailure. Keep the wording aligned with the existing diagnostic
contract and the display-safe purpose of lastAuthError.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift`:
- Around line 42-46: The documentation for lastAuthError in AuthCoordinator
should be updated to reflect the current redaction behavior. Adjust the comment
near diagnosticDescription(for:) so it no longer says unknown failures preserve
the thrown Swift error type; instead, state that only display-safe AuthError
categories are retained and uncategorized failures collapse to
AuthError.authFailure. Keep the wording aligned with the existing diagnostic
contract and the display-safe purpose of lastAuthError.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 30754d45-7718-4bac-b279-8cbfda2d90c0

📥 Commits

Reviewing files that changed from the base of the PR and between b9ae83e and 5aeff06.

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv
📒 Files selected for processing (3)
  • Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift
  • Packages/Shared/CmuxAuthRuntime/Tests/CmuxAuthRuntimeTests/AuthCoordinatorTests.swift
  • Packages/Shared/CmuxAuthRuntime/Tests/CmuxAuthRuntimeTests/Fakes.swift

…-share-diagnostics-copy-share-logs

# Conflicts:
#	.github/swift-file-length-budget.tsv
austinywang and others added 3 commits July 1, 2026 22:16
…hare-logs

Resolve conflicts:
- MobileShellComposite.swift: keep diagnostics feature (import, secret
  scrubber, diagnosticsEventLog) + adopt main's isolated deinit.
- CmuxAgentChatUI, CmuxMobileTerminal: reset to origin/main (my compat-only
  shims are unneeded on main's toolchain).
- Localizable.xcstrings: union — main's values for all shared keys + 27 new
  mobile.diagnostics.* keys (502 total).
- swift-file-length-budget.tsv: regenerated via swift_file_length_budget.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-share-diagnostics-copy-share-logs

# Conflicts:
#	.github/swift-file-length-budget.tsv
#	Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift
signOut() wiped drafts, paired Macs, registry devices, and visible
connection context, but retained the two new Share Diagnostics inputs:
lastConnectionError (deliberately kept across a visible-error clear) and
the injected diagnosticsEventLog. On a shared device a user could sign
out after a connection failure, another could sign in, and Share
Diagnostics would then surface the previous account's scrubbed
connection error and prior auth/connection events.

Clear both at the account boundary. Also blank connectedHostName before
the .disconnected transition so the conn.state diagnostics event that
connectionState.didSet records cannot carry the previous account's host
across sign-out; this makes the event-log actor clear() order-independent
for privacy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 31 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .github/swift-file-length-budget.tsv Outdated
austinywang and others added 2 commits July 2, 2026 03:15
Tie WorkspaceDiagnosticsSheet report generation to the view lifecycle:
bail out of buildReport() before the off-main OSLog read and report
assembly when the driving `.task` is cancelled (sheet dismissed), so the
detached work is not started for a report nothing will consume.

Regenerate .github/swift-file-length-budget.tsv so MobileShellComposite's
budget matches its actual 7827 lines (the sign-out diagnostics-clear fix
grew it past the stale 7813 entry, failing workflow-guard-tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Share Diagnostics exported the process-wide structured `diagnosticLog`
(a flight recorder created once in AppCompositionRoot) into the report,
but that log is never reset at the account boundary — signOut() only
clears the account-scoped `diagnosticsEventLog` and `lastConnectionError`.
On a shared device the next user could open Share Diagnostics and surface
the previous account's structured activity history (connection/pairing/
input/composer timing).

Stop feeding the process-wide structured log into this account-scoped
report: buildReport() no longer reads store.diagnosticLog, and
assembleReport passes structuredEventLog: nil. The report keeps its
account-scoped In-App Event Log (diagnosticsEventLog, cleared on
sign-out) as the event source; the flight recorder keeps recording for
its non-account-scoped debugging purpose. The report builder and its
tests are unchanged (the "Structured Event Log" section renders "none").

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
austinywang and others added 4 commits July 2, 2026 03:41
The privileged agent-feedback path (submitPrivilegedAgentFeedback) is
intentionally not #if DEBUG-gated so it ships to @manaflow.ai users on
Release/TestFlight. This PR un-gated the process-wide structured
diagnosticLog to all builds, which routed it into that release-capable
export. Because the log is a process-lifetime flight recorder that is
never reset at the account boundary, on a shared device a later signed-in
team user could submit a Release feedback bundle carrying the previous
account's structured activity (connection/pairing/input/composer timing).

Export the structured log into the feedback bundle on DEBUG builds only;
on Release the bundle carries only the freeform note, terminal text, and
the string debug log. This restores the pre-PR Release behavior
(diagnosticLog was nil on Release, so the export was already empty Data()
there) and, with the structured log already omitted from the
account-scoped Share Diagnostics report, leaves no release-reachable
diagnosticLog.export() sink.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-share-diagnostics-copy-share-logs

# Conflicts:
#	.github/swift-file-length-budget.tsv
The prior account-boundary fix cleared diagnosticsEventLog with a
fire-and-forget Task { await log.clear() }, which autoreview flagged as
racy: the clear could run after the next signed-in user's Share
Diagnostics snapshot() (leaking the previous account's events), and a
still-in-flight recordDiagnosticsEvent task could land after the clear and
reinsert a prior-account event.

Make the reset ordered with the (MainActor) sign-out by swapping in a
fresh MobileDiagnosticsEventLog instance instead of clearing in place. The
swap is synchronous, so it precedes anything the next user can do, and
because recordDiagnosticsEvent binds the current instance locally, any
in-flight record writes to the previous, now-discarded instance rather
than the new one. diagnosticsEventLog becomes private(set) var; the only
external holder (AppCompositionRoot) reads it once at init to inject it, so
the internal swap affects no other reader.

Bumps the MobileShellComposite length budget for the added rationale
comment (regenerated via scripts/swift_file_length_budget.py).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-share-diagnostics-copy-share-logs

# Conflicts:
#	.github/swift-file-length-budget.tsv
@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in cmux backlog Sep 23, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — 89e665d8 Deployed Jul 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS: in-app Share Diagnostics (copy/share logs) for beta debugging

3 participants