Skip to content

feat(desktop): make diagnostics context-aware and available on demand - #3427

Merged
M4n5ter merged 17 commits into
mainfrom
feat/on-demand-diagnostics
Aug 22, 2026
Merged

feat(desktop): make diagnostics context-aware and available on demand#3427
M4n5ter merged 17 commits into
mainfrom
feat/on-demand-diagnostics

Conversation

@M4n5ter

@M4n5ter M4n5ter commented Aug 21, 2026

Copy link
Copy Markdown
Member

Fixes #3425

English

Summary

  • Upgrade About and the command palette from environment-only copy to complete diagnostics on demand, with a global Cmd/Ctrl+Shift+D shortcut surfaced quietly beside the About action and in shortcut help.
  • Make manual and error-triggered reports context-aware: Host-scoped operations preserve their profile, Session, or Turn authority through renderer → preload → main, while renderer-local failures remain Desktop-only.
  • Keep diagnostics reachable before the renderer exists: fatal startup failures and startup-blocking native dialogs expose a bilingual copy action, then return to the original recovery decision.
  • Never substitute an unrelated/default Host when a target disappears; keep Desktop evidence available, bound Host reads so copying settles, and retain failed error actions for retry.
  • Retain longer redacted log tails within explicit budgets: 256 KiB for Desktop main-process logs and 64 KiB for Runtime Host logs, while preserving the Host wire ceiling and per-entry limits. Each process collapses its own home path before evidence crosses the process boundary.
  • Reuse the existing clipboard-only report pipeline without adding storage, telemetry, or automatic upload.

Review focus

The operation source owns diagnostic context, preload resolves profile/Session identities, and main validates the resulting Host scope before collecting evidence. Missing authority, the default Host, and a targeted Host are intentionally distinct states. Default-Host operations resolve one identity for both execution and diagnostics, while stale operations cannot overwrite presentation state after the default changes. Startup dialogs remain Desktop-only because no renderer-established Host authority exists yet.

Verification

  • npm run lint
  • npm run format:check
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/core test — 589 passed\n- npm --workspace @maka/ui test — 189 passed\n- npm --workspace @maka/desktop test — 1059 passed\n- npm --workspace @maka/desktop run build\n- npm --workspace @maka/desktop run build-storybook\n- npm --workspace @maka/desktop run smoke:storybook — 160 stories passed\n- node --test packages/runtime-host/dist/__tests__/protocol.test.js — 36 passed

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with implementation, tests, review, scope analysis, and pull request drafting; the human contributor remains responsible for the change.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No
中文

概要

  • 将“关于”页和命令面板从复制环境摘要升级为可随时复制完整诊断信息,增加全局 Cmd/Ctrl+Shift+D 快捷键,并在“关于”页操作旁及快捷键帮助中弱提示。
  • 让主动报告和错误报告具备上下文感知能力:Host 操作的 profile、Session 或 Turn authority 从 renderer 经 preload 传递到 main,纯 Renderer 故障则保持 Desktop-only。
  • 在 renderer 尚未存在时仍可获取诊断:致命启动失败和阻塞启动的原生弹窗提供中英文复制入口,复制后继续原有的恢复决策。
  • 目标消失时不替换为无关或默认 Host;仍保留 Desktop 证据,为 Host 读取设置边界以保证复制能够结束,并在错误操作复制失败后保留重试能力。
  • 在明确预算内保留更长的脱敏日志尾部:Desktop 主进程 256 KiB,Runtime Host 64 KiB,同时保持 Host 线协议上限和单条日志上限不变;每个进程都会在证据跨越进程边界前折叠自身的主目录路径。
  • 复用现有仅写入剪贴板的报告链路,不增加存储、遥测或自动上传。

审查重点

操作发生点拥有诊断上下文,preload 负责解析 profile/Session identity,main 在采集证据前验证最终 Host scope。无 Host authority、默认 Host 和明确目标 Host 是有意区分的三种状态。默认 Host 操作会为执行和诊断解析同一个 identity;默认 Host 变化后,旧操作也不能覆盖当前 presentation state。启动弹窗尚无 renderer 建立的 Host authority,因此始终保持 Desktop-only。

验证

  • npm run lint
  • npm run format:check
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/core test — 589 项通过\n- npm --workspace @maka/ui test — 189 项通过\n- npm --workspace @maka/desktop test — 1059 项通过\n- npm --workspace @maka/desktop run build\n- npm --workspace @maka/desktop run build-storybook\n- npm --workspace @maka/desktop run smoke:storybook — 160 个 story 通过\n- node --test packages/runtime-host/dist/__tests__/protocol.test.js — 36 项通过

AI 使用

Codex 协助了实现、测试、审查、范围分析和 PR 文案;贡献者本人仍对该变更负责。AI 使用选项已在英文部分勾选。

检查清单

  • 测试覆盖该变更,并会在缺少实现时失败。
  • lint、format、typecheck 和受影响测试均已在本地通过。
  • 本 PR 包含用户可见的行为变更,已在概要中说明。

@M4n5ter
M4n5ter force-pushed the feat/on-demand-diagnostics branch 2 times, most recently from 16bd855 to 8a291c5 Compare August 21, 2026 15:53
@M4n5ter M4n5ter changed the title feat(desktop): copy diagnostics on demand feat(desktop): make diagnostics context-aware and available on demand Aug 22, 2026
Promote the environment-summary action into a manual diagnostic capture that reuses the bounded, redacted Desktop and Runtime Host report pipeline. Manual capture remains available when no Runtime Host or About metadata is available and writes only to the system clipboard.

Generated-by: Codex
About metadata reads can remain pending while the Runtime Host reconnects. Render the Host-independent diagnostic action alongside the loading skeleton and cover that state with a server-rendered behavior test.

Generated-by: Codex
Command-palette captures now use the Runtime Host that owns the visible task, without falling back to the default Host when that target is unavailable. The About page also keeps its diagnostic action outside metadata-state branching so every state exposes the same recovery path.

Generated-by: Codex
Resolve manual diagnostic targets at the preload authority boundary so existing tasks and new-task profiles cannot silently fall back to an unrelated Runtime Host. Let IPC rejection remain the single clipboard failure channel and keep renderer environment metadata owned by preload.

Generated-by: Codex
Route default and task diagnostic intent independently from concrete Host scope so Host outages still yield Desktop evidence without falling back to another Host. Keep async toast actions visible when copying fails, and make scope the only concrete Host authority.

Generated-by: Codex
Attach stable session or profile context when task-scoped errors are surfaced, so copying diagnostics still selects the owning Host before an execution event exists. Keep turn metadata as optional evidence instead of using it as Host authority.

Generated-by: Codex
Propagate the session or Runtime Host profile that actually owned each failed operation into manual diagnostics. Keep client-only validation, clipboard failures, and aggregate errors free of misleading Host authority, and preserve the first failing session when reporting multi-session purges.\n\nGenerated-by: Codex
Distinguish renderer-only failures from default-Host captures, carry the selected Settings Host into diagnostic actions, and bound execution evidence reads so copying always settles. Keep purge failure details and their owning Session in one value to prevent mismatched reports.

Generated-by: Codex
Make context-aware diagnostics available through Cmd/Ctrl+Shift+D by invoking the existing command-palette action. Surface the shortcut beside the About action and in localized discovery UI.

Generated-by: Codex <codex@openai.com>
@M4n5ter
M4n5ter force-pushed the feat/on-demand-diagnostics branch from 8a291c5 to b6bcf44 Compare August 22, 2026 01:34
Make RuntimeHostSettingsTarget the single source of Host authority for Settings error diagnostics. Host-only surfaces use a context-bound reporter, while mixed surfaces keep explicit targets so client-local failures remain Desktop-only.

Generated-by: Codex <codex@openai.com>
@M4n5ter
M4n5ter marked this pull request as ready for review August 22, 2026 01:48
Keep diagnostic capture reachable before renderer creation by adding a nonterminal copy action to fatal and startup-blocking native dialogs. Startup reports reuse the bounded, redacted main-process formatter and remain Desktop-only because no Host authority exists yet.

Generated-by: Codex <codex@openai.com>
Increase Desktop main-process retention to 256 KiB and use the existing Runtime Host diagnostics contract more fully with a 64 KiB log budget. Keep redaction, per-entry limits, oldest-first eviction, and the Host wire ceiling unchanged.

Generated-by: Codex <codex@openai.com>
@M4n5ter
M4n5ter force-pushed the feat/on-demand-diagnostics branch from f62707d to f796974 Compare August 22, 2026 02:12
@M4n5ter
M4n5ter marked this pull request as draft August 22, 2026 02:20
Keep client-owned General settings usable while the selected Runtime Host is unavailable, and make diagnostic targets structurally exclusive across renderer call sites. Fatal startup diagnostics now share the same async native-dialog lifecycle as other pre-renderer failures, removing the duplicate synchronous path.

Generated-by: Codex <codex@openai.com>
Bind default-Host surface errors to the profile in use when each operation begins, so delayed diagnostic copies retain the relevant Runtime Host evidence. Close the diagnostic wire contract so renderer crashes and Desktop-only toasts cannot carry impossible Host execution state.

Generated-by: Codex <codex@openai.com>
Resolve the default Runtime Host once per operation and reuse that exact identity for dispatch and diagnostic attribution, so Host switches cannot redirect copied evidence. Collapse Runtime Host home paths at the source and surface failed toast copy actions without creating a recursive diagnostic action.
Keep project presentation updates owned by the current default Host while operations remain bound to the Host on which they began. Bind remaining default-Host error paths, cover common Windows home-path representations, and keep Storybook fixtures aligned with the Host authority contract.
@M4n5ter
M4n5ter marked this pull request as ready for review August 22, 2026 04:06
Record bounded, redacted Runtime Host handler failures at the operation boundary so generic protocol errors retain a local root cause. Render the existing Turn trace across model, tool, permission, compaction, and error steps without exporting prompts or tool inputs.
@M4n5ter

M4n5ter commented Aug 22, 2026

Copy link
Copy Markdown
Member Author

Follow-up: hard Renderer/process crashes, inline-only Renderer failures, and Runtime Host crashes that discard the in-memory log tail still need separate treatment beyond this clipboard-only, no-storage scope.

const next = await window.maka.skills.list();
setSkills(next);
const next = await runOnDefaultRuntimeHost((host) => window.maka.skills.list(host));
setSkills(next.value);

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.

[P2] Discard refresh results from a Host that is no longer the default

Thanks for binding each request and its diagnostic target to the same captured Host. One presentation race remains: if a refresh for default Host A is still pending when the user switches to B, B can return first and display its data, after which A returns and unconditionally overwrites the current Skills state here. The sibling managed-source, bundled-catalog, and scheduled-task refreshes have the same completion behavior.

The existing project refresh already demonstrates the clean fix: capture { profileId, hostId }, then compare it with the current default immediately before committing the result. A shared generation or identity guard for these default-bound projections would avoid duplicating that check. Cancellation alone would not be sufficient because an already-dispatched IPC request may still settle.

});
if (!result.ok) throw new Error('Desktop diagnostic clipboard write failed');
} else {
await navigator.clipboard.writeText(formatRendererErrorReport(error, errorInfo));

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.

[P2] Bound the browser-only fallback report before writing it

Thanks for keeping diagnostics available when the renderer is running without the Electron bridge. The Electron path bounds renderer details in main, but this fallback directly concatenates the error, stack, component stack, user agent, and full location before writing to the clipboard. A very large error or data: URL can therefore create an unbounded write while the renderer is already on its recovery screen.

Could the browser path reuse a bounded renderer-report formatter, with explicit UTF-8 budgets for the details, location, and final report? One focused test with an oversized error and URL should cover the contract without adding another diagnostics authority.

@Astro-Han Astro-Han 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.

Thanks for strengthening diagnostics around the places where evidence is actually needed: normal on-demand collection, operation-scoped failures, renderer-only recovery, and pre-renderer native dialogs.

The final architecture is coherent. Main remains the single collection and formatting authority; preload resolves profile and Session identity without trusting renderer-supplied Host scope; missing, default, and explicitly targeted Hosts remain distinct; Host and Turn reads are bounded; and a vanished target is not silently replaced with the current default.

Keeping bounded, redacted unexpected-failure context in the user-controlled clipboard report is also appropriate here. The report is neither uploaded automatically nor persisted, and retaining the original failure context is part of its diagnostic purpose.

I'm approving this exact head with two non-blocking P2 follow-ups below. Neither requires another diagnostics path or a broader redesign: one should reuse the existing Host-identity completion guard, and the other should make the browser fallback reuse the existing bounded-report principle.

AI-assisted review disclosure: OpenAI Codex coordinated five independent exact-head review passes covering authority, lifecycle and concurrency, privacy and security, cross-platform UI, and final-state simplification. I independently verified the disputed paths against the source, removed an unsupported example during adjudication, refreshed the exact head and CI state, and made the final approval and severity decisions.

@M4n5ter

M4n5ter commented Aug 22, 2026

Copy link
Copy Markdown
Member Author

Tracked both non-blocking P2 review findings, together with the remaining deliberately out-of-scope diagnostics blind spots, in #3463. They do not change #3427's merge bar, so no further changes are needed in this PR.

@M4n5ter
M4n5ter merged commit 26ac078 into main Aug 22, 2026
2 checks passed
@M4n5ter
M4n5ter deleted the feat/on-demand-diagnostics branch August 22, 2026 05:32
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.

feat(desktop): make diagnostics context-aware and available on demand

2 participants