Skip to content

feat(diagnostics): Help → Report Issue with snapshot-based body - #163

Open
YakiHugo wants to merge 2 commits into
mainfrom
feat/render-recovery-pr2-report-issue
Open

feat(diagnostics): Help → Report Issue with snapshot-based body#163
YakiHugo wants to merge 2 commits into
mainfrom
feat/render-recovery-pr2-report-issue

Conversation

@YakiHugo

Copy link
Copy Markdown
Collaborator

Summary

  • Adds Help → Report Issue... that captures a fixed-shape diagnostics snapshot and pre-fills a GitHub issues/new URL in the user's browser.
  • Snapshot covers app/Electron/Chromium versions, GPU feature status, displays, window visibility, and per-terminal render state. No titles, paths, labels, or PTY content.
  • Falls back to copying the body to the clipboard when the URL would exceed 6000 chars (mirrors VS Code's MAX_URL_LENGTH cutoff).

This is slice 2 of the render-recovery v2 plan. Slice 1 was #162.

Snapshot field allowlist

Reviewable in one place — shared/diagnostics-snapshot.ts:

Section Fields
app appVersion, electronVersion, chromiumVersion, nodeVersion, platform, arch, locale
gpuFeatureStatus feature → status map from app.getGPUInfo('basic')
displays[] id, scaleFactor, rotation, isPrimary, size
window isVisible, isFocused, isMinimized, isFullScreen
renderer visibilityState, documentFocused, devicePixelRatio, innerWidth, innerHeight
terminals[] id (UUID), rendererMode, status, mode, hasXterm, isAttached, isFocused, cols, rows
webglPool poolSize, maxContexts, focusedTerminalId, trackedTerminalIds, contextLossCount, lastContextLossAt

Forbidden by design: window titles, terminal labels, cwd / worktree paths, file names, ANSI / PTY content, command lines, URLs the user is visiting. The collectors (getTerminalDiagnosticSnapshots, getWebGLPoolDiagnosticSnapshot, collectMainSnapshot) only return the shapes above — adding a field requires touching the schema, which is the single audit point.

Why snapshot, not breadcrumb / ring buffer

Documented in the header of `shared/diagnostics-snapshot.ts`. Short version: an open event log requires per-event privacy review forever, while a fixed snapshot schema makes "no labels / no paths / no PTY content" a property of the schema, not contributor discipline. Mirrors VS Code's `baseIssueReporterService.ts` (which submits snapshots, not its rotating logs).

Submission tiers

Same shape as VS Code's reporter, minus the GitHub OAuth tier:

  1. URL prefill (default) — `https://github.com/blueberrycongee/termcanvas/issues/new?title=...&body=...\` opened via `shell.openExternal`.
  2. Clipboard fallback — when the URL > 6000 chars: body written to clipboard, empty new-issue page opened, in-app toast prompts user to paste.

Logs are NOT auto-attached

The rolling JSONL log written by PR 1's `render-diagnostics.ts` is referenced by path in the issue body (so reviewers know where to look), but its content is not bundled. Users who want to share it paste it manually. This matches VS Code's separation of Issue Reporter (snapshot) from `Developer: Show Logs...` (raw logs).

Test plan

  • `pnpm typecheck` passes
  • `pnpm exec tsx --test` for diagnostics-snapshot, visibility-observer, render-throttling-coordinator, terminal-runtime-store, terminal-runtime-policy, terminal-focus-scheduler — 47/47
  • Privacy-leak test (`buildIssueBody does not leak privacy-sensitive content`) passes
  • macOS QA: click `Help → Report Issue...` with several terminals open; default browser opens with body filled
  • macOS QA: simulate long body (e.g. spawn 50 terminals); verify clipboard fallback fires and toast appears
  • macOS QA: verify the rendered body contains no terminal titles, no cwd paths, no PTY output

Out of scope (intentional)

  • OpenTelemetry / external telemetry — diagnostics stay local + manual export.
  • Sentry-style breadcrumb event log — see schema header for rationale.
  • VS Code's GitHub-OAuth POST tier — extra surface for a small return; URL prefill + clipboard already covers >99% of report bodies.

🤖 Generated with Claude Code

Adds a `Help → Report Issue...` menu item that captures a fixed-shape
snapshot of app/Electron/Chromium versions, GPU feature status, displays,
window visibility, and per-terminal render state, formats it into a
markdown body, and opens a pre-filled GitHub `issues/new` URL in the
default browser. Falls back to copying the body to the clipboard if the
URL exceeds 6000 chars (mirrors VS Code's `MAX_URL_LENGTH` cutoff).

The schema is a closed allowlist — enums, booleans, numbers, internal
UUIDs, version strings, GPU feature names. Window titles, terminal
labels, cwd / worktree paths, and PTY content are excluded by design,
not by discipline. The "why snapshot, not ring buffer" decision is
documented in the schema file's header for future readers.

Logs continue to write to the existing rolling JSONL file; they are not
auto-attached. Users who want to share log content paste it manually,
matching VS Code's separation of Issue Reporter (snapshot) from
`Developer: Show Logs...` (raw logs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Apr 28, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
website Ready Ready Preview, Comment May 10, 2026 6:25am

Two follow-ups for PR #163 review feedback:

- Add a frozen field allowlist test plus a privacy-pattern guard. Adding
  any field to the snapshot tree now requires deliberately updating the
  list, and forbidden-shape names (title/label/cwd/path/...) trigger an
  explicit review of PRIVACY_EXCEPTIONS.
- Surface `renderDiagnosticsEnabled` in `RendererSnapshot`. When the
  rolling event log is disabled, the issue body now says so and points
  the user at the localStorage / env flag to flip and reproduce — instead
  of silently linking to an empty file.

Default stays opt-in: focus/navigation hot paths can emit several events
per shortcut, and we don't have evidence yet that the IPC + disk cost is
free under load. Surfacing the state lets bug reporters self-serve.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant