Skip to content

feat(desktop): user-reviewed diagnostics package export#1472

Merged
Astro-Han merged 9 commits into
devfrom
claude/diag-review-panel
Jun 23, 2026
Merged

feat(desktop): user-reviewed diagnostics package export#1472
Astro-Han merged 9 commits into
devfrom
claude/diag-review-panel

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Summary

Rework the Prepare diagnostics package flow so the user reviews and explicitly shares the package — PR3 of the diagnostics-package rebuild (#1465). Control is inverted away from a single main-process call that silently did everything:

  • prepareReport (main) only generates, redacts, saves the package, prunes older ones, and returns review metadata (status: "ready" | "failed"). No clipboard, reveal, or form side effects.
  • revealReport(reportId) / submitReport(reportId) are the user's explicit follow-up actions, each validated against a single pending slot so a stale report id can't act (submitReport returns { status: "stale" }, which the review surface shows as a clear notice rather than silently closing).
  • A shared presentational DiagnosticsReviewBody lists what the package contains, states the privacy caveat, and offers reveal / submit. Menu / command entry renders it in a Dialog; the crash error page renders it inline (the ErrorBoundary fallback has no DialogProvider in scope).
  • The Help-menu entry routes through a registered diagnostics.prepare command (reusing the existing menu-command channel) instead of a bespoke IPC channel. If the feedback form fails to open, the surface shows a visible, selectable URL plus a copy-summary action.
  • i18n: added diagnostics.review.* keys (en + zh); removed the now-dead native-dialog confirm/status copy, feedbackDialogLabels, and errorReportStatusMessage.

Why

Before, one reportProblem call did everything — generate → copy summary → reveal file → open the feedback form — with no chance for the user to see what was in the package before it left the machine. Inverting control puts an explicit human review step between generation and sharing, which is the backstop the redaction layers (PR1/PR2) are documented to rely on.

Related Issue

Refs #1465 (umbrella). This is PR3; PR1 #1470 is merged, PR2 #1471 is open. Flat PR on dev — the only overlap with PR1/PR2 is a small region of feedback.ts that resolves trivially on rebase.

Human Review Status

Pending

Review Focus

  • The control-flow inversion and the single pending-slot validation: revealReport / submitReport only act on the current report id, and a stale id surfaces a notice instead of silently closing.
  • The two review surfaces sharing one DiagnosticsReviewBody — Dialog vs inline, the latter because the ErrorBoundary fallback has no DialogProvider.
  • The menu entry reusing the menu-command channel via a registered diagnostics.prepare command (no new IPC surface).
  • The form-fallback path (visible selectable URL + copy-summary) when the feedback form cannot open.

Risk Notes

  • Visible UI change (review Dialog + inline panel on the error page). Manual click-through was not done — this headless environment has no GUI — so the UI/copy checklist item below is left unticked; left to the maintainer to verify visually.
  • The review surface uses three actions (cancel / reveal / submit) rather than DESIGN.md's two-button default — a deliberate, approved choice for this flow.
  • Flat on dev; the feedback.ts overlap with PR1/PR2 resolves trivially on rebase. Intended to land after PR1 and PR2.

How To Verify

bun run typecheck — clean
eslint — clean
app tests — 1947 pass · desktop-electron tests — 589 pass
/codex gate (xhigh) — iterated to no P0/P1 (validated submitReport stale handling, the
  no-form path, and the visible form-fallback URL)
bun run dev:desktop manual click-through — NOT done (no GUI in this env), left to maintainer

Screenshots or Recordings

Not captured — the review Dialog / inline panel are visible UI, but this environment is headless. Visual verification is left to the maintainer (see Risk Notes).

Checklist

How to use this checklist:

  • Tick a box by replacing [ ] with [x]. Do not edit, add, or remove items.
  • The bot-applied label items can only be honestly ticked AFTER the PR is opened and the labeler / priority-triage bots have run — return to the PR description and tick them then.
  • Most items are required. The few that are conditional are explicitly marked (conditional); for those, leave unticked if they truly do not apply and explain why in Risk Notes. All other items must be ticked before requesting human review.
  • Type label — this PR carries exactly one of bug, enhancement, task, documentation. Type labels are author-added; the labeler bot does NOT assign them. Add the label in the GitHub UI, then tick this.
  • Routing labels — this PR carries at least one of app, ui, platform, harness, ci. The labeler bot assigns these on PR open based on changed paths. Confirm the bot's choice (or override if wrong), then tick this.
  • Priority label — this PR carries exactly one of P0, P1, P2, P3. The priority-triage bot suggests one on PR open. Confirm or override, then tick this.
  • Human Review Status above is set to Pending, Approved by @<reviewer>, or Not required: <reason> (default is Pending; "not required" is restricted to bot-authored low-risk PRs).
  • I linked the related issue, or stated in Summary why there is no issue.
  • I described the review focus and any meaningful risks.
  • I replaced the example block in How To Verify with the real verification steps and the key result for each.
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope.
  • (conditional) I manually checked visible UI or copy changes when needed, with screenshots or recordings. Leave unticked only if no visible UI or copy changed.
  • (conditional) I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes. Leave unticked only if no platform/packaging surface was touched.
  • (conditional) I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant. Leave unticked only if none of those surfaces was touched.
  • I reviewed the final diff for unrelated changes and suspicious dependency changes.
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a multi-step diagnostics review experience that prepares diagnostics, lets you reveal the report, and submits feedback from a dedicated dialog.
    • Introduced a “Prepare diagnostics” command in the command palette (enabled only when diagnostics are available).
  • Bug Fixes

    • Improved failure handling with clearer error notifications and safer fallbacks (including keeping the review dialog open when actions become stale or incomplete).
  • Documentation

    • Updated diagnostics-related text and labels for the new review workflow (including English and Chinese).

@Astro-Han Astro-Han added enhancement New feature or request P2 Medium priority platform Electron shell, OS integration, packaging, updater, signing, paths, and permissions labels Jun 23, 2026
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Astro-Han, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 41 minutes and 3 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8df2fe6f-bf1c-45f3-ad5c-c5ca8a9c1861

📥 Commits

Reviewing files that changed from the base of the PR and between e7ad2c1 and ff8c24e.

📒 Files selected for processing (1)
  • packages/desktop-electron/scripts/report-problem-smoke.mjs
📝 Walkthrough

Walkthrough

Replaces the monolithic reportProblem IPC call with a three-step prepareReport / revealReport / submitReport diagnostics flow. Adds a new SolidJS DiagnosticsReviewBody in-app review component and openDiagnosticsReview orchestrator, rewrites the main-process FeedbackHandler, updates the error page, registers a diagnostics.prepare layout command, and refreshes i18n strings in English and Chinese.

Changes

Diagnostics review three-step flow

Layer / File(s) Summary
API contract types: PrepareReportResult, SubmitReportResult, DiagnosticsReviewContents
packages/app/src/desktop-api-contract.ts, packages/app/src/desktop-api.ts, packages/desktop-electron/src/preload/types.ts, packages/app/src/context/platform.tsx
Removes ReportProblemResult; adds DiagnosticsReviewContents (per-component counts + rendererError), PrepareReportResult (ready with identifiers/contents or failed), and SubmitReportResult (opened/form-fallback/no-form/stale). Updates Platform context type to expose prepareReport, revealReport, and submitReport optional methods.
Main-process feedback handler: split prepare/reveal/submit
packages/desktop-electron/src/main/feedback.ts, packages/desktop-electron/src/main/feedback.test.ts
Rewrites createFeedbackHandler to return a FeedbackHandler with stateful pending tracking, prepareReport (concurrency deduplication, file save, cleanup, contents computation), revealReport (folder reveal with directory fallback), and submitReport (no-form/form-fallback outcomes). Removes feedbackDialogLabels and the prior all-in-one flow. Tests cover timeouts, fallbacks, stale IDs, and busy-guard behavior.
IPC/preload/renderer wiring for three-step channels
packages/desktop-electron/src/main/ipc.ts, packages/desktop-electron/src/preload/index.ts, packages/desktop-electron/src/renderer/index.tsx, packages/desktop-electron/src/main/index.ts, packages/desktop-electron/src/main/ipc-window-config.test.ts
Replaces the report-problem IPC handler with prepare-report, reveal-report, and submit-report (with windowID forwarding). Exposes the three methods on the preload api bridge and wires them into the renderer Platform context. Removes clipboard/feedbackDialogLabels from the main process, demotes onError to log-only, and redirects the menu "report problem" item to send diagnostics.prepare to the focused window.
DiagnosticsReviewBody component and openDiagnosticsReview entry point
packages/app/src/components/diagnostics-review.tsx, packages/app/src/components/diagnostics-review.test.tsx
Adds presentational sub-components (Row, ContentsList), the stateful DiagnosticsReviewBody (submit/reveal/copy-summary actions, stale/fallback rendering), the DialogDiagnosticsReview wrapper, and the async openDiagnosticsReview orchestrator. Tests verify all four outcomes: unavailable, ready, failed, and thrown.
Error page integration: prepareDiagnostics replaces reportProblem
packages/app/src/pages/error.tsx, packages/app/src/pages/error-report.ts, packages/app/src/pages/error-report.test.ts
Replaces the confirm-modal reportProblem flow with prepareDiagnostics (calls platform.prepareReport, populates store.review on success, clipboard-copy fallback on failure), renders DiagnosticsReviewBody inline when store.review is set. Removes errorReportStatusMessage and its test coverage. Adds diagnosticsFailureState helper.
Layout commands: diagnostics.prepare command wiring
packages/app/src/pages/layout/layout-commands.ts, packages/app/src/pages/layout/layout-commands.test.ts, packages/app/src/pages/layout.tsx
Adds diagnosticsActions.prepare to LayoutCommandRegistration with canPrepare gating, registers diagnostics.prepare in the Help category, and tests verify shape stability and availability gating. Wires layout.tsx to call openDiagnosticsReview from the command handler.
Localization: i18n updates for Help category and diagnostics review
packages/app/src/i18n/en.ts, packages/app/src/i18n/zh.ts
Adds command.category.help and command.diagnostics.prepare labels. Replaces error.page.report.* failure/copy/unavailable messages. Introduces the full diagnostics.review.* key set for the diagnostics package review UI (titles, contents labels, notices, actions, form-fallback text, stale warning, and error messages) in English and Chinese.
Desktop smoke test: prepareReport contract validation
packages/desktop-electron/scripts/report-problem-smoke.mjs
Updates smoke test to call window.api.prepareReport({ rendererError }), removes clipboard assertions, and validates the new return shape (status === "ready", reportId, fileName, contents.rendererError). Adds stale reveal/submit verification and end-to-end dialog menu-command path validation.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant ErrorPage as Error Page / Menu
  participant openDiagnosticsReview
  participant Platform as Platform (renderer)
  participant IPC
  participant FeedbackHandler as FeedbackHandler (main)

  rect rgba(99, 132, 199, 0.5)
    note over User, FeedbackHandler: Step 1 – Prepare
    User->>ErrorPage: clicks "Prepare diagnostics package"
    ErrorPage->>openDiagnosticsReview: openDiagnosticsReview({platform, dialog, language})
    openDiagnosticsReview->>Platform: prepareReport(input)
    Platform->>IPC: prepare-report(input, windowID)
    IPC->>FeedbackHandler: prepareReport(input, {windowID})
    FeedbackHandler-->>IPC: PrepareReportResult {ready | failed}
    IPC-->>Platform: PrepareReportResult
    Platform-->>openDiagnosticsReview: PrepareReportResult
    alt status = "ready"
      openDiagnosticsReview->>ErrorPage: dialog.show(DiagnosticsReviewBody)
    else status = "failed"
      openDiagnosticsReview->>User: showToast(error)
    end
  end

  rect rgba(180, 99, 132, 0.5)
    note over User, FeedbackHandler: Step 2 – Reveal (optional)
    User->>ErrorPage: clicks "Reveal in Finder"
    ErrorPage->>Platform: revealReport(reportId)
    Platform->>IPC: reveal-report(reportId)
    IPC->>FeedbackHandler: revealReport(reportId)
    FeedbackHandler-->>User: opens folder / fallback directory
  end

  rect rgba(99, 180, 132, 0.5)
    note over User, FeedbackHandler: Step 3 – Submit
    User->>ErrorPage: clicks "Submit"
    ErrorPage->>Platform: submitReport(reportId)
    Platform->>IPC: submit-report(reportId)
    IPC->>FeedbackHandler: submitReport(reportId)
    FeedbackHandler-->>User: opens feedback URL
    FeedbackHandler-->>ErrorPage: SubmitReportResult {opened | form-fallback | no-form | stale}
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

  • Astro-Han/pawwork#179: Both PRs modify packages/desktop-electron/src/main/feedback.ts and its tests around createFeedbackHandler behavior, failure handling, and fallback flows.
  • Astro-Han/pawwork#187: Both PRs refactor the renderer-error-report pipeline and the platform.reportProblem/IPC contract, with this PR replacing that contract entirely with the new three-step flow.

Suggested labels

desktop

Poem

🐇 Hippity-hop, the old one-step's gone,
Now prepare, reveal, submit—carry on!
A shield checks the logs, a folder peeks inside,
Three tidy IPC channels open wide.
The rabbit stamps "ready" and toasts on fail,
No more clipboard chaos—just a clean review trail! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.54% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: converting diagnostics package export to include explicit user review.
Description check ✅ Passed The description is comprehensive and complete, covering summary, rationale, related issues, review focus, risks, verification steps, and all required checklist items addressed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/diag-review-panel

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.

@github-actions github-actions Bot added app Application behavior and product flows ui Design system and user interface labels Jun 23, 2026

@github-actions github-actions 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.

Suggested priority: P2 (includes user-path files (packages/app/src/components/diagnostics-review.test.tsx, packages/app/src/components/diagnostics-review.tsx, packages/app/src/context/platform.tsx, packages/app/src/desktop-api-contract.ts, packages/app/src/desktop-api.ts, packages/app/src/i18n/en.ts, packages/app/src/i18n/zh.ts, packages/app/src/pages/error-page-source.test.ts, packages/app/src/pages/error-report.test.ts, packages/app/src/pages/error-report.ts, packages/app/src/pages/error.tsx, packages/app/src/pages/layout.tsx, packages/app/src/pages/layout/layout-commands.test.ts, packages/app/src/pages/layout/layout-commands.ts, packages/desktop-electron/src/main/feedback.test.ts, packages/desktop-electron/src/main/feedback.ts, packages/desktop-electron/src/main/index.ts, packages/desktop-electron/src/main/ipc-window-config.test.ts, packages/desktop-electron/src/main/ipc.ts, packages/desktop-electron/src/preload/index.ts, packages/desktop-electron/src/preload/types.ts, packages/desktop-electron/src/renderer/index.tsx)).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

Replace the auto copy/reveal/open-form problem report flow with an
explicit in-app review surface. prepareReport now only generates,
redacts, and saves the package and returns review metadata; revealReport
and submitReport become the user's explicit follow-up actions.

- contract: prepare/reveal/submit replace the single reportProblem call
- renderer: a shared DiagnosticsReviewBody backs both a Dialog (menu
  entry) and an inline panel on the error page, which has no
  DialogProvider in its ErrorBoundary fallback scope
- menu entry routes through a registered diagnostics.prepare command
  instead of a bespoke IPC channel
- i18n: add diagnostics.review.* keys (en/zh); drop the dead native
  confirm/status copy and feedbackDialogLabels

Claude-Session: https://claude.ai/code/session_011KyY9wTxQu9oZLy4yPEi3W
@Astro-Han Astro-Han force-pushed the claude/diag-review-panel branch from 6a87b78 to 1788832 Compare June 23, 2026 13:30
The diagnostics-package flow was inverted: window.api.reportProblem was
replaced by prepareReport / revealReport / submitReport, and preparation
no longer copies to the clipboard, reveals the file, or opens the form.
The smoke still called the removed reportProblem and asserted clipboard
side effects, so smoke-macos-arm64 failed with
'window.api.reportProblem is not available'.

Drive prepareReport({ rendererError }) instead and assert the new
contract: status 'ready' with reportId / fileName / contents, plus the
saved markdown report still carries the renderer error, JSON payload,
and main/backend log tails. Drop the clipboard assertions (that side
effect was intentionally removed); the smoke stays prepare-only and
side-effect-free, as the old confirm:false path was.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
packages/desktop-electron/src/main/feedback.ts (1)

180-197: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve null counts when diagnostics collection fails.

The contract says counts are null when a component is absent or failed, but Line 260 reports 0 renderer events after the failure/timeout path creates an empty "write_failed" slice. Line 258 also treats a successfully collected empty log the same as a failed/missing log.

Proposed fix
     let diagnostics: ProblemReportDiagnostics
     let logTail = ""
+    let logTailCollected = false
@@
     try {
       logTail = deps.logTail()
+      logTailCollected = true
     } catch (error) {
       fullReportFailure ??= safeFailureReason(error)
     }
@@
     const contents: DiagnosticsReviewContents = {
-      logLines: logTail ? logTail.split(/\r?\n/).filter((line) => line.length > 0).length : null,
+      logLines: logTailCollected ? logTail.split(/\r?\n/).filter((line) => line.length > 0).length : null,
       sessionMessages: sessionExport.status === "ok" ? sessionExport.messages.length : null,
-      rendererEvents: rendererDiagnostics.events.length,
+      rendererEvents: rendererDiagnostics.status === "ok" ? rendererDiagnostics.events.length : null,
       rendererError: Boolean(input.rendererError),
     }

Also applies to: 205-210, 257-260

🤖 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/desktop-electron/src/main/feedback.ts` around lines 180 - 197, The
issue is that when diagnostics collection fails (in the try-catch blocks for
deps.diagnostics(context) and deps.logTail()), the fallback approach using
fallbackDiagnostics() and empty slices returns zero counts instead of preserving
null values as specified in the contract. To fix this, ensure that when a
diagnostics collection operation fails or times out, the resulting data
structure maintains null counts to indicate the component is absent or failed,
rather than using zero or empty values. This distinction is important at lines
around 260 where renderer events are being reported, so the error handling for
rendererDiagnostics initialization and the fallbackDiagnostics() function need
to properly preserve null values for failed/missing components while only using
zero counts for successfully collected but genuinely empty data.
🤖 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/app/src/components/diagnostics-review.tsx`:
- Around line 101-123: The reveal function and submit function both make
optional platform method calls that can be rejected without proper error
handling. In the reveal function, add a catch handler to the revealReport call
to handle any promise rejections and provide feedback to the user. In the submit
function, add a catch block after the try block to handle any rejections from
submitReport (in addition to the existing finally block), ensuring that
submitting is set to false and appropriate error feedback is provided to the
user instead of leaving unhandled rejections.

In `@packages/app/src/pages/error.tsx`:
- Around line 107-113: In the catch block of the prepareDiagnostics call (around
the setStore invocation), add clearing of the review property to prevent stale
review content from remaining visible when the prepare operation fails. Include
review: undefined in the setStore object alongside the existing actionError and
actionMessage properties to ensure the review is cleared whenever an error
occurs in this error handling path.

In `@packages/app/src/pages/layout/layout-commands.ts`:
- Around line 50-53: The diagnosticsActions object in layout-commands.ts
currently exposes the prepare command unconditionally, which results in a no-op
command when diagnostics is not supported. Instead of always exposing the
command, add a gating condition by including a canPrepare function alongside the
prepare handler in the diagnosticsActions object. The canPrepare function should
check if platform.prepareReport exists to determine if the command should be
available. Apply this same gating pattern to both the diagnosticsActions object
and any other similar diagnostic-related command structures referenced in lines
187-193 to ensure consistency across all diagnostic commands.

In `@packages/desktop-electron/src/main/feedback.ts`:
- Around line 274-279: The inFlight guard in the prepareReport function is too
broad and returns the same cached promise for all concurrent callers regardless
of their input parameters and context. Scope the in-flight tracking to be
context-aware by associating the inFlight promise with the specific input and
contextOverride parameters, so that only requests with matching input parameters
return the existing promise. Requests with different input.rendererError or
contextOverride values should proceed independently with their own context,
ensuring each window's crash-page prepare gets its own package and report ID
rather than reusing the first window's IDs.

---

Outside diff comments:
In `@packages/desktop-electron/src/main/feedback.ts`:
- Around line 180-197: The issue is that when diagnostics collection fails (in
the try-catch blocks for deps.diagnostics(context) and deps.logTail()), the
fallback approach using fallbackDiagnostics() and empty slices returns zero
counts instead of preserving null values as specified in the contract. To fix
this, ensure that when a diagnostics collection operation fails or times out,
the resulting data structure maintains null counts to indicate the component is
absent or failed, rather than using zero or empty values. This distinction is
important at lines around 260 where renderer events are being reported, so the
error handling for rendererDiagnostics initialization and the
fallbackDiagnostics() function need to properly preserve null values for
failed/missing components while only using zero counts for successfully
collected but genuinely empty data.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 714d6b9d-8ed1-4d04-8aae-9b3f1552dfe3

📥 Commits

Reviewing files that changed from the base of the PR and between b004523 and 1788832.

📒 Files selected for processing (22)
  • packages/app/src/components/diagnostics-review.test.tsx
  • packages/app/src/components/diagnostics-review.tsx
  • packages/app/src/context/platform.tsx
  • packages/app/src/desktop-api-contract.ts
  • packages/app/src/desktop-api.ts
  • packages/app/src/i18n/en.ts
  • packages/app/src/i18n/zh.ts
  • packages/app/src/pages/error-page-source.test.ts
  • packages/app/src/pages/error-report.test.ts
  • packages/app/src/pages/error-report.ts
  • packages/app/src/pages/error.tsx
  • packages/app/src/pages/layout.tsx
  • packages/app/src/pages/layout/layout-commands.test.ts
  • packages/app/src/pages/layout/layout-commands.ts
  • packages/desktop-electron/src/main/feedback.test.ts
  • packages/desktop-electron/src/main/feedback.ts
  • packages/desktop-electron/src/main/index.ts
  • packages/desktop-electron/src/main/ipc-window-config.test.ts
  • packages/desktop-electron/src/main/ipc.ts
  • packages/desktop-electron/src/preload/index.ts
  • packages/desktop-electron/src/preload/types.ts
  • packages/desktop-electron/src/renderer/index.tsx
💤 Files with no reviewable changes (1)
  • packages/app/src/pages/error-page-source.test.ts

Comment thread packages/app/src/components/diagnostics-review.tsx Outdated
Comment thread packages/app/src/pages/error.tsx
Comment thread packages/app/src/pages/layout/layout-commands.ts
Comment thread packages/desktop-electron/src/main/feedback.ts Outdated
- gate the diagnostics.prepare command when the prepareReport bridge is
  absent (non-desktop hosts) instead of firing a no-op
- clear a prior successful review when a re-prepare fails (error page)
- dedupe an in-flight prepare by window + renderer-error context, not
  globally, so a different context never gets the wrong package's reportId
- surface a recoverable notice when reveal/submit IPC rejects rather than
  failing silently
- tests: review-body click contract, command gate, cross-context dedupe
Replace the two hand-rolled stroked SVGs with @opencode-ai/ui Icon —
folder on Reveal, lock on the privacy caveat (the shared set has no
shield glyph). Aligns the panel with the app-wide Icon convention.
Drop the decorative lock/folder icons, and replace the contents list's
per-row divider hairlines with a soft grouped panel separated by spacing.
Label reads as primary (fg-base), counts as secondary (fg-weak).
Second review round on the review panel:
- revealReport now returns RevealReportResult (revealed | opened-directory
  | stale | failed) end-to-end (contract -> main -> ipc/preload -> platform).
  A stale id or an OS-open failure the main process used to swallow now
  surfaces in the review notice instead of a silent no-op.
- resolve prepare/reveal/submit once at the openDiagnosticsReview and
  error-page boundaries into a non-optional ReviewActions; the body no
  longer optional-chains, closing the `await undefined -> onDone` trap where
  a missing submit silently closed the review as if it had been sent.
- tests: real reveal-contract cases in feedback.test.ts, reveal-result
  branches in the body check, and a side-effect-free stale reveal/submit
  through the real bridge in the desktop smoke.
…e, real menu-path smoke

- error page now copies the redacted summary when prepare returns failed (it was
  dropped for a bare error), matching the menu's copy-fallback toast; extract a pure
  diagnosticsFailureState helper with tests
- collapse the review body's stale/failed booleans into one notice signal: every
  reveal/submit clears it first, so a stale reveal then a failed submit shows only the
  latest reason instead of a mixed pair
- report-problem smoke walks the real menu-command -> command registry -> dialog ->
  review-panel path and tears it down via Cancel, covering wiring the prepare-only
  calls bypassed (reveal/submit OS side effects stay on the stale calls)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (1)
packages/app/src/components/diagnostics-review.tsx (1)

233-235: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Handle clipboard write rejection in the toast action.

Line 234 can produce an unhandled rejected promise if clipboard write fails; swallow the rejection in the click handler.

Suggested patch
-                onClick: () => void navigator.clipboard.writeText(summary),
+                onClick: () => {
+                  void navigator.clipboard.writeText(summary).catch(() => undefined)
+                },
🤖 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/app/src/components/diagnostics-review.tsx` around lines 233 - 235,
The onClick handler that calls navigator.clipboard.writeText(summary) does not
handle promise rejections, which can result in unhandled rejected promises if
the clipboard write fails. Modify the onClick handler to add rejection handling
using either .catch() method chaining or by converting the handler to an async
function with try-catch block to gracefully handle any errors from the clipboard
operation and prevent unhandled promise rejections.
🤖 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/desktop-electron/scripts/report-problem-smoke.mjs`:
- Around line 168-172: The window selection in the app.evaluate callback uses
the first window from BrowserWindow.getAllWindows(), which is nondeterministic
when multiple windows exist. Replace this approach with
BrowserWindow.getFocusedWindow() to get the currently focused window, and add a
fallback to the first window from getAllWindows() if no window is focused. This
ensures the menu-command is sent to the correct target window.

---

Outside diff comments:
In `@packages/app/src/components/diagnostics-review.tsx`:
- Around line 233-235: The onClick handler that calls
navigator.clipboard.writeText(summary) does not handle promise rejections, which
can result in unhandled rejected promises if the clipboard write fails. Modify
the onClick handler to add rejection handling using either .catch() method
chaining or by converting the handler to an async function with try-catch block
to gracefully handle any errors from the clipboard operation and prevent
unhandled promise rejections.
🪄 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: CHILL

Plan: Pro Plus

Run ID: a0d7ba01-2730-497c-b5b7-ecb4635c174f

📥 Commits

Reviewing files that changed from the base of the PR and between d952c10 and e7ad2c1.

📒 Files selected for processing (15)
  • packages/app/src/components/diagnostics-review.test.tsx
  • packages/app/src/components/diagnostics-review.tsx
  • packages/app/src/context/platform.tsx
  • packages/app/src/desktop-api-contract.ts
  • packages/app/src/desktop-api.ts
  • packages/app/src/i18n/en.ts
  • packages/app/src/i18n/zh.ts
  • packages/app/src/pages/error-report.test.ts
  • packages/app/src/pages/error-report.ts
  • packages/app/src/pages/error.tsx
  • packages/desktop-electron/scripts/report-problem-smoke.mjs
  • packages/desktop-electron/src/main/feedback.test.ts
  • packages/desktop-electron/src/main/feedback.ts
  • packages/desktop-electron/src/main/ipc.ts
  • packages/desktop-electron/src/preload/types.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • packages/app/src/desktop-api.ts
  • packages/app/src/i18n/en.ts
  • packages/app/src/components/diagnostics-review.test.tsx
  • packages/app/src/pages/error-report.test.ts
  • packages/app/src/desktop-api-contract.ts
  • packages/app/src/pages/error.tsx
  • packages/app/src/i18n/zh.ts
  • packages/desktop-electron/src/main/feedback.ts
  • packages/desktop-electron/src/main/feedback.test.ts

Comment thread packages/desktop-electron/scripts/report-problem-smoke.mjs Outdated
…gnostics

The menu walk timed out waiting for the review dialog: BrowserWindow.getAllWindows()[0]
is not guaranteed to be the window Playwright observes (a loading splash can coexist with
the main window), so the menu-command fired in a renderer the smoke never sees. Target
app.browserWindow(window) instead, and dump on-screen state on timeout so a future failure
is self-explaining.
…ble in CI smoke)

The menu-command -> command-registry -> dialog walk never rendered the review dialog in
the macOS smoke. The CI app sits on the home screen and firing diagnostics.prepare there
produced neither the dialog nor an error toast (on-screen dump: dialogs=0, toasts=[],
shellMain=true), so the renderer-internal menu->command->DialogProvider chain doesn't
activate without first opening a real project/session -- not the "thin" test the review
asked for, and brittle to drive over a 3-4min CI loop.

Keep the real IPC-contract coverage already in the smoke (prepareReport + stale
reveal/submit through the live bridge); the menu id + disabled gating stays covered by
layout-commands.test.ts and the dialog/button handlers by diagnostics-review.test.tsx.
@Astro-Han Astro-Han merged commit cf26ae9 into dev Jun 23, 2026
42 checks passed
@Astro-Han Astro-Han deleted the claude/diag-review-panel branch June 23, 2026 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows enhancement New feature or request P2 Medium priority platform Electron shell, OS integration, packaging, updater, signing, paths, and permissions ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant