feat(gui): add a Copy Diagnostics button to the About window#206
Conversation
Greptile SummaryThis PR adds a Copy Diagnostics button to the About window that renders a privacy-filtered Markdown report to the clipboard. The data shape and rendering live in a new
Confidence Score: 5/5Safe to merge. All changed paths are additive (new module + button), no existing behaviour is altered, and the change is well-tested. The feature is entirely additive — a new button and new modules with no changes to existing rendering, IPC, or device management logic. The core diagnostics module has eight unit tests, the timer race condition is already guarded with the generation counter, and the OS-version lookup was correctly replaced with the non-blocking NSProcessInfo API. The one correctness wrinkle (redact_home using string strip_prefix instead of Path::strip_prefix) is a low-impact edge case in a user-visible string that has no effect on functionality. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant AboutView
participant Collector as "diagnostics::collect"
participant Resolver as "AssetResolver"
participant State as "AppState"
participant Clipboard
User->>AboutView: click Copy Diagnostics
AboutView->>Collector: collect(cx)
Collector->>Resolver: new() — reads index from disk
Resolver-->>Collector: resolver
Collector->>State: try_global — last_status, last_inventory, device_list
State-->>Collector: state snapshot
Collector-->>AboutView: DiagnosticsReport
AboutView->>AboutView: to_markdown()
AboutView->>Clipboard: write_to_clipboard
AboutView->>AboutView: "copied=true, copied_gen++"
Note over AboutView: label flips to Copied!
AboutView->>AboutView: spawn 2s timer with generation
AboutView->>AboutView: "timer fires — if gen matches, copied=false"
Note over AboutView: label reverts to Copy Diagnostics
Reviews (3): Last reviewed commit: "Merge master into feat/diagnostics-repor..." | Re-trigger Greptile |
Resolve the IPC poll conflict against the startup-states rework and adapt the diagnostics adapter to master: - call store_agent_snapshot before the status snapshot moves into AgentLink::Ready; the inventory merge keeps the InventoryHealth gate (AprilNEA#213/AprilNEA#215/AprilNEA#220) - read accessibility from the retained AgentStatus; the AppState.accessibility_granted field no longer exists - map DeviceRoute::Unifying (AprilNEA#181) to a new ConnectionKind::UnifyingReceiver
Summary
Adds a Copy Diagnostics button to the About window that copies a privacy-filtered, Markdown diagnostics report to the clipboard for pasting into a bug report. It gives enough detail to reproduce environment-specific issues — device connection, capabilities, missing render images, agent/GUI version skew, asset-cache state — without exposing anything that uniquely identifies the user's hardware.
What it collects
Privacy
Model-level only. Serial numbers, unit IDs, and the Bolt receiver UID are excluded by construction — the report structs have no field to hold them, so a future edit can't leak one by forgetting to redact. The home directory is redacted to
~in the cache path.Design
openlogi-core(diagnostics.rs) — platform-free and unit-tested.openlogi-gui/src/diagnostics.rs) maps liveAppState(device list, agent status, asset resolver) onto it, refining connection type from the device's announced transports.AgentStatusand the raw inventory snapshot (previously discarded after each poll) so the report can include agent version, hook state, and transports.cx.write_to_clipboard(ClipboardItem::new_string(...)); the button confirms with a "Copied!" label for ~2s.Testing
openlogi-corecover section rendering, version/protocol mismatch flags, empty/offline devices, the no-serial-or-unit-id guarantee, and direct-connection slot rendering.Screenshots