From 0efc842028a159809e8d4b4979945d3d95b8c400 Mon Sep 17 00:00:00 2001 From: OrcaWin Date: Fri, 23 Oct 2026 02:16:59 -0700 Subject: [PATCH] [comment audit] Shorten preload comments (#32257) * chore: audit preload root comments and track repository coverage * docs: track repository comment audit coverage * chore: keep comment audit tracker local * chore: shorten preload API contract comments --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> --- src/preload/api/agent-account-api.ts | 9 +--- src/preload/api/agent-skill-api.ts | 4 +- src/preload/api/agent-status-api.ts | 11 ++-- src/preload/api/agent-status-bridge.ts | 4 -- src/preload/api/ai-vault-api.ts | 12 ++--- src/preload/api/app-api.ts | 47 +++++----------- src/preload/api/automation-api.ts | 6 +-- src/preload/api/browser-api.ts | 12 ++--- src/preload/api/crash-report-api.ts | 2 - src/preload/api/dashboard-api.ts | 2 +- src/preload/api/dashboard-bridge.ts | 3 -- src/preload/api/doc-preview-api.ts | 3 -- src/preload/api/filesystem-api.ts | 2 +- src/preload/api/github-pull-request-api.ts | 8 +-- src/preload/api/github-work-item-api.ts | 5 +- src/preload/api/gitlab-api.ts | 7 +-- src/preload/api/legacy-relay-bridge-api.ts | 1 - src/preload/api/mobile-api.ts | 2 - src/preload/api/mobile-bridge.ts | 6 +-- src/preload/api/native-chat-api.ts | 14 ++--- src/preload/api/native-chat-bridge.ts | 1 - src/preload/api/notifications-bridge.ts | 6 +-- src/preload/api/onboarding-api.ts | 4 +- src/preload/api/orca-profile-api.ts | 1 - src/preload/api/platform-bridge.ts | 9 +--- src/preload/api/plugin-host-api.ts | 18 ++----- src/preload/api/preflight-api.ts | 8 ++- src/preload/api/pty-api.ts | 53 +++++++------------ src/preload/api/pty-bridge-session-control.ts | 9 ---- .../pty-bridge-stream-and-serialization.ts | 3 -- src/preload/api/pty-management-api.ts | 21 +++----- src/preload/api/repository-api.ts | 3 -- src/preload/api/runtime-api.ts | 9 ++-- src/preload/api/session-bridge.ts | 1 - src/preload/api/settings-api.ts | 3 +- src/preload/api/settings-bridge.ts | 1 - src/preload/api/skills-bridge.ts | 1 - src/preload/api/speech-bridge.ts | 2 +- src/preload/api/ssh-api.ts | 2 +- src/preload/api/telemetry-api.ts | 13 ++--- ...ui-bridge-clipboard-and-window-controls.ts | 4 +- .../ui-bridge-terminal-and-session-tabs.ts | 7 +-- src/preload/api/ui-command-event-api.ts | 11 ++-- src/preload/api/ui-window-api.ts | 7 ++- src/preload/api/updater-api.ts | 2 +- src/preload/api/workspace-cleanup-api.ts | 4 +- src/preload/api/workspace-session-api.ts | 4 +- src/preload/api/worktree-api.ts | 30 ++++------- src/preload/api/wsl-hosts-api.ts | 5 +- .../browser-find-subscriptions.test.ts | 8 +-- src/preload/browser-find-subscriptions.ts | 5 +- src/preload/browser-window-close.ts | 2 +- .../doc-preview-link-interception.test.ts | 26 ++------- src/preload/doc-preview-link-interception.ts | 35 ++++-------- src/preload/doc-preview-link.ts | 5 +- src/preload/e2e-config.ts | 8 +-- src/preload/gitlab.ts | 4 -- src/preload/index.ts | 1 - src/preload/preload-runtime-support.ts | 2 - .../renderer-heap-statistics-reader.test.ts | 4 -- .../renderer-heap-statistics-reader.ts | 11 ++-- .../renderer-process-memory-reader.test.ts | 5 +- src/preload/renderer-process-memory-reader.ts | 7 +-- src/preload/renderer-restart-wiring.test.ts | 2 +- src/preload/renderer-restart-wiring.ts | 2 +- .../runtime-environment-subscriptions.test.ts | 12 ----- .../runtime-environment-subscriptions.ts | 16 ++---- src/preload/updater-package-recovery.test.ts | 1 - 68 files changed, 148 insertions(+), 410 deletions(-) diff --git a/src/preload/api/agent-account-api.ts b/src/preload/api/agent-account-api.ts index 2ba279801c0..ee59efe1be9 100644 --- a/src/preload/api/agent-account-api.ts +++ b/src/preload/api/agent-account-api.ts @@ -14,7 +14,6 @@ export type CodexAccountsApi = { wslDistro?: string | null }) => Promise cancelPendingLogin: () => Promise - /** Sign-in link of the login waiting on a browser, or null when none is. */ getPendingLoginUrl: () => Promise onPendingLoginUrlChanged: (callback: (url: string | null) => void) => () => void reauthenticate: (args: { @@ -74,9 +73,7 @@ export type CursorAccountsApi = { } export type MinimaxCredentialsApi = { - // Why: cookie + API key each live in their own safeStorage file, so the - // status separates them. 'configured' stays as the OR so existing callers - // that only care about "anything saved" keep working unchanged. + // configured remains cookie OR API key for existing callers. getStatus: () => Promise saveCookie: (cookie: string) => Promise clearCookie: () => Promise @@ -85,9 +82,7 @@ export type MinimaxCredentialsApi = { } export type ZcodePlanCredentialsApi = { - // Why: the GLM Coding Plan key lives in its own safeStorage file and the - // ZCode CLI's config is read-only, so the status reports both sources' - // presence; neither credential value ever crosses the IPC boundary. + // Report presence of the saved key and read-only CLI credentials without exposing either value. getStatus: () => Promise saveApiKey: (key: string) => Promise clearApiKey: () => Promise diff --git a/src/preload/api/agent-skill-api.ts b/src/preload/api/agent-skill-api.ts index 0f54e764a52..c6725f7880a 100644 --- a/src/preload/api/agent-skill-api.ts +++ b/src/preload/api/agent-skill-api.ts @@ -70,9 +70,7 @@ export type SkillsApi = { input: SkillBundleInstallPreviewInput ) => Promise removeInstall: (input: SkillRemoveInput) => Promise - /** Whether the host answering `previewDelete`/`delete` supports them. Always - * true on desktop; on web the "local" host is a remote server that updates - * independently and may predate the capability. */ + /** Always true on desktop; web clients may use a server predating skill deletion. */ deleteSupported: () => Promise previewDelete: (request: SkillDeleteRequest) => Promise delete: (request: SkillDeleteRequest) => Promise diff --git a/src/preload/api/agent-status-api.ts b/src/preload/api/agent-status-api.ts index 119a3c55f6c..780f152866a 100644 --- a/src/preload/api/agent-status-api.ts +++ b/src/preload/api/agent-status-api.ts @@ -13,12 +13,12 @@ export type AgentStatusApi = { onSet: (callback: (data: AgentStatusIpcPayload) => void) => () => void /** Listen for main-process cleanup that evicted cached hook status. */ onClear: (callback: (data: AgentStatusClearIpcPayload) => void) => () => void - /** Return the current main-process hook cache after renderer hydration. */ + /** Read after hydration so startup hook replays can attach to restored tabs. */ getSnapshot: () => Promise inferInterrupt: (request: AgentInterruptInferenceRequest) => Promise - /** Guarded clear for an answered AskUserQuestion wait — the CLI emits no hook at answer time, so the renderer reports the submit keystroke. */ + /** The CLI emits no answer hook, so the renderer reports the submit keystroke. */ inferQuestionAnswered: (request: AgentQuestionAnsweredInferenceRequest) => Promise - /** Whether the host can check this pane's agent process; without that, silence keeps today's cleanup. */ + /** Without host process verification, retain the existing silence-based cleanup. */ hasVerifiableAgentProcess?: (paneKey: string) => Promise /** Listen for PTYs on a legacy numeric pane key that have registry-backed UUID pane proof. */ onMigrationUnsupported: (callback: (entry: MigrationUnsupportedPtyEntry) => void) => () => void @@ -35,10 +35,8 @@ export type AgentStatusApi = { drop: (paneKey: string) => void /** Evict a previously-cleared status only when its identity still matches the main-process cache. */ dropPersisted: (identity: AgentStatusCacheIdentity) => void - /** Same as dropPersisted for many identities in one IPC message and one listener notification. */ dropPersistedBatch?: (identities: readonly AgentStatusCacheIdentity[]) => void - /** Retire a pane whose agent process is proven gone — clears the row AND the per-pane caches a - * dismissal deliberately keeps. Not `drop`: that one is a user dismissal of a live pane's row. */ + /** Proven process exit also clears per-pane caches that a user dismissal retains. */ reconcileEndedProcess: (paneKey: string) => void /** Drop every cached hook status under one terminal tab prefix. Fire-and-forget. */ dropByTabPrefix: (tabId: string) => void @@ -46,7 +44,6 @@ export type AgentStatusApi = { retirePaneAuthority: (paneKey: string, retirementId?: string) => void /** Lift one pane's retirement fence when a live PTY re-attaches to it. Closed tabs stay retired. */ restorePaneAuthority: (paneKey: string) => void - /** Move hook authority when a live pane is detached into another tab. */ transferPaneAuthority: (args: { fromPaneKey: string; toPaneKey: string; ptyId?: string }) => void } diff --git a/src/preload/api/agent-status-bridge.ts b/src/preload/api/agent-status-bridge.ts index 1a056252634..7bff62c94bd 100644 --- a/src/preload/api/agent-status-bridge.ts +++ b/src/preload/api/agent-status-bridge.ts @@ -10,7 +10,6 @@ import type { AgentQuestionAnsweredInferenceRequest } from '../../shared/agent-q import type { PreloadApi } from '../api-types' export const agentStatusApi = { - /** Listen for agent status updates forwarded from native hook receivers. */ onSet: (callback: (data: AgentStatusIpcPayload) => void): (() => void) => { const listener = (_event: Electron.IpcRendererEvent, data: AgentStatusIpcPayload) => callback(data) @@ -23,7 +22,6 @@ export const agentStatusApi = { ipcRenderer.on('agentStatus:clear', listener) return () => ipcRenderer.removeListener('agentStatus:clear', listener) }, - /** Pull cached hook statuses after renderer hydration, so startup replays aren't lost before tabs exist. */ getSnapshot: (): Promise => ipcRenderer.invoke('agentStatus:getSnapshot'), inferInterrupt: (request: AgentInterruptInferenceRequest): Promise => @@ -65,7 +63,6 @@ export const agentStatusApi = { }, getMigrationUnsupportedSnapshot: (): Promise => ipcRenderer.invoke('agentStatus:getMigrationUnsupportedSnapshot'), - /** Drop the cached hook status for a paneKey on both sides (memory + on-disk) so a relaunch can't resurrect a dismissed row. */ drop: (paneKey: string): void => { ipcRenderer.send('agentStatus:drop', paneKey) }, @@ -78,7 +75,6 @@ export const agentStatusApi = { reconcileEndedProcess: (paneKey: string): void => { ipcRenderer.send('agentStatus:reconcileEndedProcess', paneKey) }, - /** Drop all cached hook statuses under one terminal tab prefix; fired on explicit tab close even without a local row. */ dropByTabPrefix: (tabId: string): void => { ipcRenderer.send('agentStatus:dropByTabPrefix', tabId) }, diff --git a/src/preload/api/ai-vault-api.ts b/src/preload/api/ai-vault-api.ts index f1933d331db..280cd31602e 100644 --- a/src/preload/api/ai-vault-api.ts +++ b/src/preload/api/ai-vault-api.ts @@ -37,16 +37,12 @@ export type AiVaultApi = { ) => Promise /** Status describes one index, so it never accepts the `all` scope. */ searchStatus: (executionHostScope?: ExecutionHostId) => Promise - /** - * Turns indexing on or off on a paired Orca server and answers its status after the change. - * Runtime hosts only: the local index follows this desktop's own settings write, SSH hosts - * reject with `unsupported`, and a server predating the method rejects with `host-too-old`. - */ + /** Paired servers only; SSH rejects as unsupported, older servers as host-too-old. */ setSearchEnabled: ( executionHostId: ExecutionHostId, enabled: boolean ) => Promise - /** Deletes and rebuilds this desktop's local search index. */ + /** Rebuilds the local index after deletion. */ clearSearchIndex: () => Promise listSessions: (args?: AiVaultListArgs) => Promise resolveSessionTitles: (args: AiVaultSessionTitlesArgs) => Promise @@ -54,13 +50,11 @@ export type AiVaultApi = { prepareSessionResume: ( args: AiVaultPrepareSessionResumeRequest ) => Promise - /** Lists the Task subagent transcripts of one session, on demand. */ listSubagentSessions: (args: AiVaultSubagentListArgs) => Promise - /** Full first user prompt for copy/reuse (re-parses one transcript). */ getFirstUserPrompt: (args: AiVaultFirstUserPromptArgs) => Promise /** Moves a deletable session's transcript to the OS trash; local sessions only. */ deleteSession: (args: AiVaultDeleteSessionArgs) => Promise - /** Fires when any app window regains OS focus; returns an unsubscribe. */ + /** Fires when any app window regains OS focus. */ onWindowFocused: (callback: () => void) => () => void /** The local scan entry for a request key, if it is still retained. */ getScanProgress: (scanKey: string) => Promise diff --git a/src/preload/api/app-api.ts b/src/preload/api/app-api.ts index 51055642eb2..44ea62e936b 100644 --- a/src/preload/api/app-api.ts +++ b/src/preload/api/app-api.ts @@ -18,53 +18,40 @@ export type AppApi = { getSystemLanguageDetection?: ( browserPreferences?: readonly string[] ) => Promise - /** A local profile storage operation is delayed and holds up subsequent saves. */ isProfileStateSaveDelayed: () => Promise onProfileStateSaveDelayChanged: (callback: (delayed: boolean) => void) => () => void - /** Returns the app identity currently exposed to native chrome and the titlebar. */ getIdentity: () => Promise /** Local Windows desktop elevation; null when unavailable. Does not describe remote hosts. */ getWindowsAdministratorStatus: () => Promise /** Restarts the installed Windows desktop with administrator approval and replaces its local terminal host. */ restartAsAdministrator: () => Promise - /** Returns a URL base for feature-wall assets. In dev this is Vite /@fs; - * in packaged builds this is file:// resources. Renderer appends filenames. */ + /** Append filenames to this base: Vite /@fs in dev, file:// resources when packaged. */ getFeatureWallAssetBaseUrl: () => Promise - /** Relaunches the app (app.relaunch() + app.exit(0)) for settings that need a full restart to apply. */ + /** Uses app.exit(0), bypassing normal quit handling. */ relaunch: () => Promise - /** Restarts Orca through the normal quit pipeline so daemon-backed terminal - * sessions survive and can reattach after the new process starts. */ + /** Uses normal quit handling so daemon terminals survive for reattachment. */ restart: () => Promise - /** Reloads the current app renderer through main so expected renderer - * teardown can be classified before Electron emits process-gone events. */ + /** Main classifies teardown before Electron emits process-gone events. */ reload: () => Promise - /** Stages the renderer's final state synchronously before unload. */ stageBeforeUnloadSync: (args: { sessions: { state: WorkspaceSessionState; hostId?: ExecutionHostId }[] ui: Partial }) => void - /** Resolves once the last staged checkpoint is durably written; rejects if that - * write failed, so a reload/restart can abort instead of losing the snapshot. */ + /** Waits for durable persistence; rejection lets reload/restart abort without losing state. */ awaitBeforeUnloadCheckpoint: () => Promise - /** Resolves when the daemon PTY provider and hook receiver have either - * started or failed open for the first BrowserWindow. */ + /** Waits for daemon PTY and hook startup to succeed or fail open. */ awaitFirstWindowStartupServices: () => Promise - /** Resolves when host Git can run: shell-PATH generation is published and the - * managed WSL CLI registration has reconciled. Does not wait on PTY services. */ + /** Waits for shell PATH and managed WSL CLI registration, independently of PTY startup. */ awaitGitEnvironmentStartupBarrier: () => Promise - /** Inventories retained PTYs and restores durable structured ownership before renderer adoption. */ + /** Restore durable PTY ownership before renderer adoption. */ prepareTerminalStartupRestoration: () => Promise /** Whether this machine's runtime holds a structured chat, saved or live. */ holdsStructuredAgentSessions: () => Promise - /** Fires when that answer changes, e.g. when a paired client creates the first chat here. */ onStructuredAgentSessionsHeldChanged: (callback: (held: boolean) => void) => () => void - /** Reconciles legacy worker authority around persisted terminal reconnect. */ recoverLegacyWorkerTerminalsForRendererStartup: () => Promise - /** Emits a startup benchmark marker when ORCA_STARTUP_DIAGNOSTICS is enabled. */ + /** Enabled only by ORCA_STARTUP_DIAGNOSTICS. */ startupDiagnostic: (event: string, details?: Record) => Promise - /** macOS active input mode, or layout ID when no IME is selected (e.g. `com.apple.keylayout.PolishPro`). - * Distinguishes CJK IMEs and Option-layer-composing layouts that look like US QWERTY (issue #1205). - * Returns null on non-Darwin or when the defaults read fails. */ + /** macOS input mode or non-IME layout ID; null off macOS or if the defaults read fails. */ getKeyboardInputSourceId: () => Promise /** Physical Mission Control chords before layout resolution. */ getMacCapturedDigitRowChords: () => Promise @@ -72,18 +59,14 @@ export type AppApi = { getKeyboardLayoutSnapshot: () => Promise /** Subscribes to active macOS input-source changes. No-op in the browser fallback. */ onKeyboardLayoutChanged: (callback: (event: KeyboardLayoutChangeEvent) => void) => () => void - /** Updates the macOS Dock unread badge. No-op on Windows/Linux. */ + /** No-op on Windows/Linux. */ setUnreadDockBadgeCount: (count: number) => Promise - /** Resolves the launch directory for global Floating Terminal tabs. */ getFloatingTerminalCwd: (args?: FloatingTerminalCwdRequest) => Promise - /** Resolves Orca's app-owned directory for auto-created Floating Workspace - * markdown notes. */ + /** App-owned directory for auto-created Floating Workspace notes. */ getFloatingMarkdownDirectory: () => Promise - /** Opens a native picker for markdown documents, rooted in the floating - * workspace, and authorizes the selected file for editor reads/writes. */ + /** Picks a Floating Workspace document and authorizes editor reads/writes. */ pickFloatingMarkdownDocument: () => Promise - /** Opens a native directory picker and authorizes the selected directory - * for Floating Workspace markdown file creation. */ + /** Picks a directory and authorizes Floating Workspace markdown creation. */ pickFloatingWorkspaceDirectory: () => Promise /** Persists flag-gated terminal render evidence under app-owned userData. */ writeTerminalRenderDesyncEvidence: ( @@ -91,8 +74,6 @@ export type AppApi = { ) => Promise } -/** Panel contribution as surfaced by the main-process plugin service. */ - export type PlatformApi = { get: () => { platform: NodeJS.Platform diff --git a/src/preload/api/automation-api.ts b/src/preload/api/automation-api.ts index efcd2c8a72f..6d82279bfe2 100644 --- a/src/preload/api/automation-api.ts +++ b/src/preload/api/automation-api.ts @@ -20,11 +20,7 @@ export type ExternalAutomationManagerResult = { updatedAt: number } -/** - * Orca automation CRUD rides the local runtime RPC surface (`runtime:call`), - * so this IPC api carries only what stays desktop-native: the external-manager - * scope (probes run on this computer) and the dispatch-loop plumbing. - */ +// Automation CRUD uses runtime RPC; this IPC API handles desktop probes and dispatch. export type AutomationsApi = { listExternalManagerForOwner: ( request: ScopedExternalManagerListRequest diff --git a/src/preload/api/browser-api.ts b/src/preload/api/browser-api.ts index 461e5d54458..576da090873 100644 --- a/src/preload/api/browser-api.ts +++ b/src/preload/api/browser-api.ts @@ -65,7 +65,7 @@ import type { } from '../../shared/browser-client-page-renderer-protocol' export type BrowserApi = { - /** Absent wherever this client hosts no guests of its own, which is how the web client reads. */ + /** Absent on clients that host no browser guests, including web clients. */ readClientHostId?: () => string | null onClientPageRendererRequest?: ( callback: ( @@ -111,7 +111,7 @@ export type BrowserApi = { override: BrowserViewportOverride | null }) => Promise getPageSiteDisplay: (args: { browserPageId: string }) => Promise - /** Zooms the page's site in its browser profile, or resets it to Default Zoom. */ + /** Site zoom is scoped to the browser profile. */ zoomPage: (args: { browserPageId: string direction: BrowserPageZoomDirection @@ -126,7 +126,7 @@ export type BrowserApi = { state: BrowserViewportScrollState }) => void setAnnotationViewportBridge: (args: BrowserSetAnnotationViewportBridgeArgs) => Promise - /** Publishes a client-hosted page's url/title to its runtime over that runtime's host lease. */ + /** Uses the owning runtime's host lease. */ publishClientPageMetadata: (args: { environmentId: string params: BrowserClientPageMetadataParams @@ -218,14 +218,14 @@ export type BrowserApi = { browserFamily: string browserProfile?: string }) => Promise - /** Import-source badges for one environment's client-hosted jars, keyed by profile id. */ + /** Import sources keyed by browser profile ID. */ sessionClientRouteImportSources: (args: { environmentId: string }) => Promise> sessionClearDefaultCookies: () => Promise - /** Remembered Allow and Block answers for one browser profile on this computer, by site. */ + /** Site permissions are local to this computer and browser profile. */ sitePermissionsList: (args: { profileId: string }) => Promise - /** Null forgets the answer so the site is asked again; resolves the profile's updated list. */ + /** Null forgets the answer so the site is asked again. */ sitePermissionsSet: (args: { profileId: string origin: string diff --git a/src/preload/api/crash-report-api.ts b/src/preload/api/crash-report-api.ts index 0f1856e4e0a..90e13b0ff83 100644 --- a/src/preload/api/crash-report-api.ts +++ b/src/preload/api/crash-report-api.ts @@ -26,9 +26,7 @@ export type CrashReportsApi = { copyLatestDiagnostics: ( args?: CrashReportCopyDiagnosticsArgs ) => Promise<{ ok: true } | { ok: false; error: string }> - /** Exact V8/Blink heap sizes; null when the runtime withholds them. */ readHeapStatistics: () => RendererHeapStatistics | null - /** This renderer's OS-level footprint, which the heap counters never include. */ readProcessMemory?: () => Promise } diff --git a/src/preload/api/dashboard-api.ts b/src/preload/api/dashboard-api.ts index c91def1c362..2db2598a7ba 100644 --- a/src/preload/api/dashboard-api.ts +++ b/src/preload/api/dashboard-api.ts @@ -34,7 +34,7 @@ export type TerminalPreviewApi = { opts?: { scrollbackRows?: number } ) => Promise input: (ptyId: string, data: string) => Promise - /** Claim the PTY grid for the preview dialog; resolves to the size actually in effect. */ + /** Claims the PTY grid; returns the size actually in effect. */ fit: (ptyId: string, cols: number, rows: number) => Promise<{ cols: number; rows: number } | null> ack: (ptyId: string, bytes: number) => Promise unsubscribe: (ptyId: string) => Promise diff --git a/src/preload/api/dashboard-bridge.ts b/src/preload/api/dashboard-bridge.ts index c1db45b4862..c4f015e8495 100644 --- a/src/preload/api/dashboard-bridge.ts +++ b/src/preload/api/dashboard-bridge.ts @@ -8,10 +8,8 @@ import type { import type { PreloadApi } from '../api-types' export const dashboardApi = { - // Open the pop-out dashboard window, or focus it if already open. openPopout: (): Promise => ipcRenderer.invoke('dashboardPopout:open'), - // ── Producer side (main window) ────────────────────────────────────── publishSnapshot: (snapshot: DashboardSnapshot): Promise => ipcRenderer.invoke('dashboard:publishSnapshot', snapshot), getPopoutOpen: (): Promise => ipcRenderer.invoke('dashboard:getPopoutOpen'), @@ -52,7 +50,6 @@ export const dashboardApi = { return () => ipcRenderer.removeListener('ui:sleepDashboardWorkspace', listener) }, - // ── Consumer side (pop-out window) ─────────────────────────────────── requestSnapshot: (): Promise => ipcRenderer.invoke('dashboard:requestSnapshot'), onSnapshot: (callback: (snapshot: DashboardSnapshot) => void): (() => void) => { const listener = (_event: Electron.IpcRendererEvent, snapshot: DashboardSnapshot): void => diff --git a/src/preload/api/doc-preview-api.ts b/src/preload/api/doc-preview-api.ts index 51e928096b3..b3df7ec9c59 100644 --- a/src/preload/api/doc-preview-api.ts +++ b/src/preload/api/doc-preview-api.ts @@ -16,7 +16,6 @@ export type DocPreviewGrantRequest = { /** Initial filesystem authority; always the opened document's directory. */ root: string entryRelativePath: string - /** Browser page the document is being opened in; main registers its guest under this id. */ browserPageId: string } @@ -25,9 +24,7 @@ export type DocPreviewApi = { mintGrant: (request: DocPreviewGrantRequest) => Promise<{ grantId: string; url: string }> revokeGrant: (grantId: string) => Promise authorizeDirectory: (grantId: string, relativePath: string) => Promise - /** External link the preview guest tried to open; the renderer turns it into a browser tab. */ onExternalLink: (callback: (payload: { url: string }) => void) => () => void - /** Why the guest is showing an error body instead of the document. */ onLoadFailure: (callback: (payload: DocPreviewFailure) => void) => () => void } } diff --git a/src/preload/api/filesystem-api.ts b/src/preload/api/filesystem-api.ts index 9a6d153235e..066a7ff0165 100644 --- a/src/preload/api/filesystem-api.ts +++ b/src/preload/api/filesystem-api.ts @@ -211,7 +211,7 @@ export type FilesystemApi = { connectionId?: string } & SshMutationExpectation ) => Promise - /** Uploads client-local files into a paired server's store for one structured chat. */ + /** Uploads client-local files to the paired server owning the chat. */ uploadPathsToAgentSessionAttachments: ( args: AgentSessionAttachmentUploadTarget & { paths: string[] } ) => Promise diff --git a/src/preload/api/github-pull-request-api.ts b/src/preload/api/github-pull-request-api.ts index 68de9ac2d31..80f66033a25 100644 --- a/src/preload/api/github-pull-request-api.ts +++ b/src/preload/api/github-pull-request-api.ts @@ -197,12 +197,8 @@ export type GithubPullRequestApi = { ) => Promise checkOrcaStarred: () => Promise starOrca: (source: AppStarSource) => Promise - /** - * GitHub API rate-limit snapshot. Does NOT consume quota (the - * `rate_limit` endpoint is exempt). Cached 30s server-side — pass - * `force: true` to bust after a known-expensive op. - */ + /** Quota-exempt; cached for 30s unless force is true. */ rateLimit: (args?: { force?: boolean }) => Promise - /** Explains scope_missing ProjectV2 failures — notably a shell `GITHUB_TOKEN` shadowing the keyring credential, where `gh auth refresh` is a no-op. */ + /** Detects missing scopes and shell tokens shadowing keyring credentials. */ diagnoseAuth: (args?: { host?: string }) => Promise } diff --git a/src/preload/api/github-work-item-api.ts b/src/preload/api/github-work-item-api.ts index 47a098e2cdc..0511bdf8456 100644 --- a/src/preload/api/github-work-item-api.ts +++ b/src/preload/api/github-work-item-api.ts @@ -115,7 +115,7 @@ export type GithubWorkItemApi = { args: GitHubRepoSelectorArgs & { number: number body: string - /** Why: scopes the cross-window cache invalidation so a PR and issue sharing the same number don't evict each other. */ + /** Keep PR and issue cache invalidation separate when their numbers match. */ type?: 'issue' | 'pr' prRepo?: GitHubOwnerRepo | null } @@ -132,7 +132,7 @@ export type GithubWorkItemApi = { sourceContext?: TaskSourceContext | null ownerRepo?: GitHubOwnerRepo }) => Promise - /** Subscribe to local-mutation broadcasts so the work-item-drawer cache can invalidate across windows. Returns an unsubscribe. */ + /** Invalidate work-item caches across windows after local mutations. */ onWorkItemMutated: ( callback: (payload: { repoPath: string @@ -141,7 +141,6 @@ export type GithubWorkItemApi = { number: number }) => void ) => () => void - // ── ProjectV2 (GitHub Projects) ───────────────────────────────── listAccessibleProjects: ( args?: ListAccessibleProjectsArgs ) => Promise diff --git a/src/preload/api/gitlab-api.ts b/src/preload/api/gitlab-api.ts index 0d692771c1d..3431936c99d 100644 --- a/src/preload/api/gitlab-api.ts +++ b/src/preload/api/gitlab-api.ts @@ -31,8 +31,6 @@ export type GitLabRepoSelectorArgs = { repoOwnerExecutionHostId?: string } -// ── GitLab — parallel to gh, MR/issue surface only in v1 ──────── -// Shapes mirror gh.* except where GitLab's API differs (MR states, host-qualified project path, `glab api -i` paging). export type GitLabApi = { viewer: () => Promise diagnoseAuth: () => Promise @@ -53,8 +51,7 @@ export type GitLabApi = { query?: string } ) => Promise - /** Combined MR + issue list filtered by state. Issues are skipped - * when state is 'merged' (issues don't merge). */ + /** The merged filter excludes issues. */ listWorkItems: ( args: GitLabRepoSelectorArgs & { state?: MRListState @@ -99,7 +96,6 @@ export type GitLabApi = { listAssignableUsers: (args: GitLabRepoSelectorArgs) => Promise /** Cross-project user-scoped todos (gitlab.com/dashboard/todos). */ todos: (args: GitLabRepoSelectorArgs) => Promise - /** Aggregated dialog payload — body + discussions + pipeline jobs. */ workItemDetails: ( args: GitLabRepoSelectorArgs & { iid: number @@ -160,7 +156,6 @@ export type GitLabApi = { args: GitLabRepoSelectorArgs & { jobId: number projectRef?: GitLabProjectRef | null - /** Bound the trace in main to a readable excerpt (see gitLabJobTraceToLogExcerpt). */ logExcerpt?: boolean } ) => Promise diff --git a/src/preload/api/legacy-relay-bridge-api.ts b/src/preload/api/legacy-relay-bridge-api.ts index 2511e1b8782..7144cba339d 100644 --- a/src/preload/api/legacy-relay-bridge-api.ts +++ b/src/preload/api/legacy-relay-bridge-api.ts @@ -20,7 +20,6 @@ export type LegacyRelayBridgeApi = { write: (args: { ptyId: string; data: string }) => void resize: (args: { ptyId: string; cols: number; rows: number }) => void detach: (args: { ptyId: string; acquisitionId: number }) => void - /** Stops the shell its closed tab ran. */ close: (args: { ptyId: string }) => Promise setOutputPaused: (args: { ptyId: string; paused: boolean }) => void onPanes: (callback: (panes: LegacyRelayBridgedPane[]) => void) => () => void diff --git a/src/preload/api/mobile-api.ts b/src/preload/api/mobile-api.ts index 23c40f81504..cee1a0f9b4a 100644 --- a/src/preload/api/mobile-api.ts +++ b/src/preload/api/mobile-api.ts @@ -29,7 +29,6 @@ export type MobileApi = { /** Null when no direct address was advertised — the QR pairs over Relay alone. */ endpoint: string | null deviceId: string - /** Mode the QR actually encodes. */ connectionMode: MobilePairingConnectionMode } > @@ -81,7 +80,6 @@ export type MobileApi = { isWebSocketReady: () => Promise<{ ready: boolean; endpoint: string | null }> getRelayStatus: () => Promise onRelayStatusChanged: (callback: (detail: MobileRelayStatusDetail) => void) => () => void - /** Consumes an auth-failure notification that arrived before the renderer listener mounted. */ consumePendingUnpairedDeviceAuthFailure?: () => Promise /** Fires (throttled, once per session) when an unpaired phone repeatedly fails direct-transport auth. */ onUnpairedDeviceAuthFailure?: (callback: () => void) => () => void diff --git a/src/preload/api/mobile-bridge.ts b/src/preload/api/mobile-bridge.ts index d6144409bd2..097d5dbe20f 100644 --- a/src/preload/api/mobile-bridge.ts +++ b/src/preload/api/mobile-bridge.ts @@ -24,11 +24,9 @@ export const mobileApi = { | { available: true qrDataUrl: string | null - /** Natural bitmap width and height in pixels. */ qrSize: number | null qrError?: 'encoding_failed' pairingUrl: string - /** Null when no direct address was advertised — the QR pairs over Relay alone. */ endpoint: string | null deviceId: string connectionMode: MobilePairingConnectionMode @@ -45,8 +43,7 @@ export const mobileApi = { getRuntimePairingUrl: (args?: { address?: string rotate?: boolean - // Why: the widen is one-way and host-wide, so main must gate it on the reach the user picked, not - // on how the typed address happens to look (a Custom loopback may front an SSH tunnel). + // Gate host-wide exposure on the chosen reach: a loopback address may front an SSH tunnel. reach?: RuntimePairingReach }): Promise< | { available: false; reason?: 'network_exposure_failed'; guidance?: string } @@ -87,7 +84,6 @@ export const mobileApi = { consumePendingUnpairedDeviceAuthFailure: (): Promise => ipcRenderer.invoke('mobile:consumePendingUnpairedDeviceAuthFailure'), - /** Fires (throttled, once per session) when an unpaired phone repeatedly fails direct-transport auth. */ onUnpairedDeviceAuthFailure: (callback: () => void): (() => void) => { const listener = () => callback() ipcRenderer.on('mobile:unpairedDeviceAuthFailure', listener) diff --git a/src/preload/api/native-chat-api.ts b/src/preload/api/native-chat-api.ts index ca89367658b..9ccfedbadc0 100644 --- a/src/preload/api/native-chat-api.ts +++ b/src/preload/api/native-chat-api.ts @@ -12,7 +12,6 @@ export type NativeChatReadSessionResult = } | { error: string; notFound?: true } -/** Messages appended to a live-tailed transcript since the previous emit. */ export type NativeChatAppendedMessages = NativeChatMessage[] export type NativeChatSubscriptionFrame = @@ -22,8 +21,7 @@ export type NativeChatSubscriptionFrame = hasMore: boolean error?: string lifecycle?: NativeChatTurnLifecycle - /** No transcript exists behind this window yet — render it, but do not - * treat it as a settled read of the session's history. */ + /** No transcript yet; do not treat this frame as settled session history. */ pending?: boolean } | { @@ -38,15 +36,13 @@ export type NativeChatSubscriptionFrame = lifecycle?: NativeChatTurnLifecycle } -/** Wire payload for the `nativeChat:appended` push channel. */ export type NativeChatAppendedPayload = { subscriptionId: string frame: NativeChatSubscriptionFrame } export type NativeChatSubscribeArgs = { - /** Unique per-caller id, echoed on every append so multiple live panes in - * one renderer don't cross-talk. */ + /** Unique per caller to isolate live panes sharing a renderer. */ subscriptionId: string agent: AgentType sessionId: string @@ -57,16 +53,14 @@ export type NativeChatSubscribeArgs = { } export type NativeChatApi = { - /** Read the on-disk transcript for an agent + session id, windowed to the most recent `limit` - * turns. `transcriptPath` is the hook-reported authoritative path, preferred over the id glob. */ + /** Reads the latest limit turns; the hook-reported transcriptPath takes precedence over ID globbing. */ readSession: ( agent: AgentType, sessionId: string, limit?: number, transcriptPath?: string ) => Promise - /** Live-tail a transcript. The first frame is a bounded race-safe snapshot; - * later frames contain only newly appended messages. */ + /** First frame is a bounded snapshot; later frames contain only appended messages. */ subscribe: ( args: NativeChatSubscribeArgs, onFrame: (frame: NativeChatSubscriptionFrame) => void diff --git a/src/preload/api/native-chat-bridge.ts b/src/preload/api/native-chat-bridge.ts index 91d6f7e918f..e3744f4e495 100644 --- a/src/preload/api/native-chat-bridge.ts +++ b/src/preload/api/native-chat-bridge.ts @@ -15,7 +15,6 @@ export const nativeChatApi = { transcriptPath?: string ): Promise => ipcRenderer.invoke('nativeChat:readSession', { agent, sessionId, limit, transcriptPath }), - /** Start live tailing; onAppended fires with only newly-appended messages. Returns an unsubscribe fn that closes the watcher. */ subscribe: ( args: { subscriptionId: string diff --git a/src/preload/api/notifications-bridge.ts b/src/preload/api/notifications-bridge.ts index d5da649c057..65368394b89 100644 --- a/src/preload/api/notifications-bridge.ts +++ b/src/preload/api/notifications-bridge.ts @@ -12,7 +12,7 @@ import type { import type { AgentSessionExecutionLocation } from '../../shared/agent-session-record' import type { PreloadApi } from '../api-types' -// Why: cache one shared Audio + blob URL per sound path so notifications do not re-read large files. +// Reuse sound data to avoid reading large files for every notification. let cachedNotificationSound: { path: string blobUrl: string @@ -73,7 +73,7 @@ export const notificationsApi = { disposeCachedNotificationSound() return { played: false, reason: sound.reason } } - // Why: a concurrent playSound may have cached the same path while this load was in flight. + // Another playSound may have populated the cache during this load. const latestEntry = cachedNotificationSound if (latestEntry?.path === sound.path) { entry = latestEntry @@ -89,7 +89,7 @@ export const notificationsApi = { } const audio = entry.audio - // Why: restart from zero on each play so bursts replay instead of stacking copies (GNOME canberra / VS Code signal service). + // Replay from the start so bursts do not stack copies. audio.currentTime = 0 if (typeof options?.volume === 'number' && Number.isFinite(options.volume)) { audio.volume = Math.min(1, Math.max(0, options.volume / 100)) diff --git a/src/preload/api/onboarding-api.ts b/src/preload/api/onboarding-api.ts index e27177a3bb7..75b4292a481 100644 --- a/src/preload/api/onboarding-api.ts +++ b/src/preload/api/onboarding-api.ts @@ -3,13 +3,13 @@ import type { OnboardingState } from '../../shared/onboarding-state-types' export type OnboardingApi = { get: () => Promise - // Why: main merges the checklist field-by-field, so a partial checklist is fine. + // Main merges checklist fields individually. update: ( updates: Partial> & { checklist?: Partial } ) => Promise - /** Read-only: main decides the audience once, from the profile as saved before the chat upgrade. */ + /** Audience is fixed from the profile saved before the chat upgrade. */ getNativeChatUpgradeTipVariant: () => Promise } diff --git a/src/preload/api/orca-profile-api.ts b/src/preload/api/orca-profile-api.ts index 33b93f952d4..8fe63dd6375 100644 --- a/src/preload/api/orca-profile-api.ts +++ b/src/preload/api/orca-profile-api.ts @@ -47,7 +47,6 @@ export type OrcaProfileApi = { onSignInProgressChanged: ( callback: (progress: OrcaCloudSignInProgress | null) => void ) => () => void - /** Stops waiting on the browser; the sign-in resolves as cancelled. */ cancelSignIn: () => Promise refreshAuth: () => Promise signOutCurrent: () => Promise diff --git a/src/preload/api/platform-bridge.ts b/src/preload/api/platform-bridge.ts index fb1aad5de4e..e8fdb68bc4c 100644 --- a/src/preload/api/platform-bridge.ts +++ b/src/preload/api/platform-bridge.ts @@ -3,26 +3,21 @@ import type { PreloadApi } from '../api-types' type PlatformInfo = ReturnType -// Why: the renderer reads this on its render cadence, and every field below is fixed -// for the process lifetime, so resolve once and hand back the same frozen payload. +// Process-lifetime values are cached for frequent renderer reads. let platformInfo: PlatformInfo | undefined function resolvePlatformInfo(): PlatformInfo { return Object.freeze({ platform: process.platform, - // Why: sandboxed preload cannot require node:os; Electron exposes the OS - // version on process.getSystemVersion when available. + // The sandbox cannot require node:os; use Electron's process API. osRelease: (process as NodeJS.Process & { getSystemVersion?: () => string }).getSystemVersion?.() ?? '', arch: process.arch, - // Why: these identify the default shell without probing user config files. - // process.env is available in the sandboxed preload; node:os is not. shell: process.env.SHELL?.trim() || process.env.ComSpec?.trim() || '', displayServer: getLinuxDisplayServer() }) } export const platformApi = { - // Why: resolved lazily so preload startup keeps paying nothing for it. get: () => (platformInfo ??= resolvePlatformInfo()) } satisfies PreloadApi['platform'] diff --git a/src/preload/api/plugin-host-api.ts b/src/preload/api/plugin-host-api.ts index 49222ae7a0b..89165079495 100644 --- a/src/preload/api/plugin-host-api.ts +++ b/src/preload/api/plugin-host-api.ts @@ -8,7 +8,6 @@ import type { PluginChangeEvent } from '../../shared/plugins/plugin-change-event import type { PluginManifest } from '../../shared/plugins/plugin-manifest' import type { PluginMarketplaceGitSource } from '../../shared/plugins/plugin-marketplace' -/** Panel contribution as surfaced by the main-process plugin service. */ export type PluginHostPanel = { id: string title: string @@ -17,9 +16,7 @@ export type PluginHostPanel = { tabKey: `plugin:${string}` } -/** `pending` = awaiting (re-)consent; `idle` = enabled, worker not running - * (lazy); `restarting` = waiting for supervised backoff; `errored` = crashed past the restart budget or failed to start; - * `invalid` = unreadable manifest. */ +/** pending awaits consent; idle defers worker startup; errored exhausted retries or failed startup. */ export type PluginHostStatus = | 'running' | 'restarting' @@ -29,8 +26,7 @@ export type PluginHostStatus = | 'errored' | 'invalid' -/** Wire shape of plugins:list — must stay assignable from the main-process - * projection in src/main/plugins/plugin-list-projection.ts. */ +// Keep assignable from main/plugins/plugin-list-projection.ts. export type PluginHostListEntry = { pluginKey: string consentFingerprint: string | null @@ -143,20 +139,17 @@ export type PluginMarketplaceHostInstallPreview = { export type PluginsApi = { list: () => Promise listLanguagePacks: () => Promise - /** Records the consent-dialog answer; approval is keyed to the plugin's - * current capability and trusted-worker fingerprint. */ + /** Approval is bound to the current capability and trusted-worker fingerprint. */ consent: (args: PluginConsentRequest) => Promise setEnabled: (args: { pluginKey: string; enabled: boolean }) => Promise - /** Returns the panel's CSP-wrapped HTML, or null when the plugin or - * panel is missing/disabled. Rendered only inside a sandboxed iframe. */ + /** CSP-wrapped HTML for a sandboxed iframe; null if missing or disabled. */ readPanelEntry: (args: { pluginKey: string; panelId: string }) => Promise invokeCommand: (args: { pluginKey: string commandId: string args?: unknown }) => Promise - /** Relays a sandboxed panel's bridge request to main, which enforces the - * plugin's consented capabilities before executing. */ + /** Main enforces consented capabilities before executing sandboxed panel requests. */ panelAction: (args: { sessionToken: string action: string @@ -186,6 +179,5 @@ export type PluginsApi = { getLogs: (args: { pluginKey: string }) => Promise /** Re-discovers after settings edits (feature flag, dev paths). */ refresh: () => Promise - /** Fires whenever installed plugins, worker states, panels, or content packs change. */ onChanged: (callback: (event: PluginChangeEvent) => void) => () => void } diff --git a/src/preload/api/preflight-api.ts b/src/preload/api/preflight-api.ts index d8582af13a7..2d1dbfc57a1 100644 --- a/src/preload/api/preflight-api.ts +++ b/src/preload/api/preflight-api.ts @@ -8,7 +8,7 @@ import type { export type PreflightStatus = { git: { installed: boolean } gh: { installed: boolean; authenticated: boolean } - /** Optional — older preload payloads predating GitLab support omit it; consumers gate on `glab?.installed`. */ + /** Absent on payloads predating GitLab support. */ glab?: { installed: boolean; authenticated: boolean } bitbucket?: { configured: boolean; authenticated: boolean; account: string | null } azureDevOps?: { @@ -31,10 +31,8 @@ export type RefreshAgentsResult = { agents: string[] addedPathSegments: string[] shellHydrationOk: boolean - /** Drives agent_picks `on_path:false` triage (dashboard 1562016). `'shell_hydrate'` = detection saw the user's - * full shell PATH; `'sync_seed_only'` = hydration failed and detection ran against the `patchPackagedProcessPath` seed list. */ + /** shell_hydrate uses the full shell PATH; sync_seed_only uses the packaged PATH seed. */ pathSource: PathSource - /** Classified hydration outcome: `'none'` on success, else a failure mode when `shellHydrationOk` is false. */ pathFailureReason: ShellHydrationFailureReason } @@ -47,7 +45,7 @@ export type PreflightRuntimeContext = { export type PreflightApi = { check: (args?: PreflightRuntimeContext & { force?: boolean }) => Promise detectAgents: (args?: PreflightRuntimeContext) => Promise - /** Whether the installed `zcode` can open a session; cached in main per run. */ + /** Cached in main for the process lifetime. */ zcodeInteractiveCapability: () => Promise refreshAgents: (args?: PreflightRuntimeContext) => Promise detectRemoteAgents: (args: { connectionId: string }) => Promise diff --git a/src/preload/api/pty-api.ts b/src/preload/api/pty-api.ts index 4dad7641129..7f6777ad8e6 100644 --- a/src/preload/api/pty-api.ts +++ b/src/preload/api/pty-api.ts @@ -55,27 +55,25 @@ export type PtyApi = { connectionId?: string | null worktreeId?: string sessionId?: string - // Why: lets a single tab open in a different shell than the user's default. shellOverride?: string projectRuntime?: ProjectExecutionRuntimeResolution terminalKittyKeyboardProtocol?: boolean terminalColorQueryReplies?: { foreground?: string; background?: string } - // Why: mark the PTY hidden before its first byte so the delivery gate owns spawn-time queries (terminal-query-authority.md §races). + // Set before the first byte so the delivery gate owns spawn-time queries. initiallyHidden?: boolean // Layout-owner build: attach to `sessionId` or start nothing; older mains ignore it. attachOnlyView?: boolean - // Why: main sync-flushes the (worktreeId,tabId,leafId→ptyId) binding before pty:spawn returns to close a SIGKILL race (INVESTIGATION.md). + // Main persists the pane-to-PTY binding before replying so SIGKILL cannot lose ownership. tabId?: string leafId?: string - // Why: a pane with a live owner is otherwise reattached; a restart names the PTY main must stop first. + // Stop this PTY before restarting; otherwise a live pane owner is reattached. replacesPtyId?: string // Which tab and leaf a fresh PTY joins; older mains ignore it. placement?: TerminalPanePlacement // Visible restores are `user-resume`, hidden ones `automatic-restore`; the fork gate validates. spawnIntent?: SpawnIntent - // The agent launch this pane's spawn starts; main admits and plans it. agentLaunch?: AgentPaneLaunchRequest - // Why: main fires `agent_started` only on spawn success, so launch metadata rides this field (telemetry-plan.md §Agent launch semantics). + // Main emits agent_started only after a successful spawn. telemetry?: { agent_kind: AgentKind; launch_source: LaunchSource; request_kind: RequestKind } }) => Promise<{ id: string @@ -119,7 +117,7 @@ export type PtyApi = { resetInputModes: (id: string) => void killFenced: (request: PtyFencedTerminationRequest) => Promise kill: (id: string, opts?: { keepHistory?: boolean }) => Promise - /** The view painted the restore; `pane` names the pane it painted (layout-owner build). */ + /** Acknowledge the pane that actually painted the restored frame. */ ackColdRestore: (id: string, pane?: PaintedRestorePane) => void /** Hidden-output recovery painted main's snapshot; retires the hidden-delivery drop latch. */ ackHiddenOutputRestoreApplied: (id: string, hiddenDropEpisode?: number) => void @@ -129,27 +127,21 @@ export type PtyApi = { requestId: number processedCharsByPty: Record }) => void - /** Renderer-initiated delivery health/heal lane over invoke — reaches main - * even when every main→renderer push channel is dead (field wedge). */ + /** Invoke still reaches main when main-to-renderer push delivery is broken. */ reportRendererDeliveryState: ( report: PtyRendererDeliveryStateReport ) => Promise - /** Live pty:data listener count on the preload emitter (sync) — heal-time - * discriminator between a detached listener and a dead channel. */ + /** Distinguishes a detached pty:data listener from a dead push channel. */ getPtyDataListenerCount: () => number - /** One-shot signal that this page's pty:data dispatcher is registered, so - * main can release sends held during the load/reload boot window. */ + /** Releases sends main held until this page registered its pty:data dispatcher. */ rendererDispatcherReady: () => void setActiveRendererPty: (id: string, active: boolean) => void setRendererPtyVisible: (id: string, visible: boolean) => void - /** Hidden-delivery gate (Phase 4): hidden=true lets main drop renderer - * byte delivery after model ingestion; reveal restores from snapshots. */ + /** Hidden panes may skip renderer bytes after model ingestion; reveal restores a snapshot. */ setHiddenRendererPty: (id: string, hidden: boolean) => void - /** Ref-counted-on-the-renderer delivery-interest signal that suppresses - * the hidden-delivery gate while any raw-byte consumer is registered. */ + /** Ref-counted raw-byte consumers suppress the hidden-delivery gate. */ setPtyDeliveryInterest: (id: string, interested: boolean) => void - /** View-attribute bridge (Phase 5 slice 2): app-global composed terminal - * appearance push backing main's hidden-PTY OSC/DSR color replies. */ + /** Main uses the composed appearance for hidden-PTY OSC/DSR color replies. */ publishTerminalViewAttributes: (attributes: TerminalViewAttributes) => void hasChildProcesses: (id: string) => Promise getForegroundProcess: (id: string) => Promise @@ -167,14 +159,12 @@ export type PtyApi = { /** Runs the fix with the pane's own Codex; true only once verified. Local panes only. */ disableCodexSharedServerAutoStart: (id: string) => Promise stopCodexSharedServer: (id: string) => Promise - /** A local pane whose daemon lacks the claude function and whose claude runs another account - * than the one selected for the pane's runtime; false for any other pane. */ + /** True only for local panes missing the daemon claude function and using a deselected account. */ openedBeforeClaudeAccounts: ( id: string, target: { runtime: 'host' } | { runtime: 'wsl'; wslDistro: string } ) => Promise - /** A local host pane whose Claude may open its diff panel unasked, judged from Claude's saved - * config; false for any other pane. */ + /** Checks saved Claude config for local host panes; false for other panes. */ claudeDiffPanelMayAutoOpen: ( id: string, target: { runtime: 'host' } | { runtime: 'wsl'; wslDistro: string } @@ -204,19 +194,15 @@ export type PtyApi = { rows: number cwd?: string | null seq?: number - /** Start of main's pending renderer-delivery queue at snapshot time - * (equals `seq` when empty) — bounds the renderer's post-restore - * duplicate window. */ + /** Bounds post-restore duplicates; equals seq when the pending delivery queue is empty. */ pendingDeliveryStartSeq?: number source?: 'headless' | 'renderer' alternateScreen?: boolean /** Authoritative normal buffer paired with an alternate-screen frame. */ scrollbackAnsi?: string - /** Trailing incomplete escape the emulator ingested; the restorer must - * write it after its post-replay resets, last before live chunks. */ + /** Write the incomplete escape after post-replay resets, just before live chunks. */ pendingEscapeTailAnsi?: string - /** Effective kitty flags the snapshot owner proved at `seq`. Absent means - * unknown; consumers must not turn that into a known `0`. */ + /** Effective flags at seq; absent means unknown, never zero. */ kittyKeyboardFlags?: number terminalOwner?: 'shell' } | null> @@ -260,12 +246,9 @@ export type PtyApi = { }) => void ) => () => void onReplay: (callback: (data: { id: string; data: string }) => void) => () => void - /** Out-of-band main→renderer signal that renderer-bound bytes were - * dropped (hidden-delivery gate / pending cap); the pane restores from - * the model snapshot. Never delivered in-band on pty:data. */ + /** Out-of-band byte-drop signal; restore the model snapshot instead of waiting on pty:data. */ onModelRestoreNeeded: (callback: (event: PtyModelRestoreNeededEvent) => void) => () => void - /** Batched derived side-effect facts for PTYs whose bytes transit local - * main. */ + /** Covers only PTYs whose bytes transit local main. */ onSideEffect: (callback: (batch: TerminalSideEffectBatch) => void) => () => void /** Title-only replay snapshot for (re)attach; attention facts never replay. */ getSideEffectSnapshot: (id: string) => Promise diff --git a/src/preload/api/pty-bridge-session-control.ts b/src/preload/api/pty-bridge-session-control.ts index b6253bce014..1111d7610bd 100644 --- a/src/preload/api/pty-bridge-session-control.ts +++ b/src/preload/api/pty-bridge-session-control.ts @@ -51,24 +51,16 @@ export const ptySessionControlApi = { projectRuntime?: ProjectExecutionRuntimeResolution terminalKittyKeyboardProtocol?: boolean terminalColorQueryReplies?: { foreground?: string; background?: string } - // Why: marks the PTY hidden before its first byte so the delivery gate + model responder own spawn-time queries (terminal-query-authority.md §races). initiallyHidden?: boolean - // Why: closes the SIGKILL race (INVESTIGATION.md) — main sync-flushes the (worktreeId, tabId, leafId → ptyId) binding before pty:spawn returns. tabId?: string leafId?: string - // Why: a pane with a live owner is otherwise reattached; a restart names the PTY main must stop first. replacesPtyId?: string - // Which tab and leaf a fresh PTY joins; older mains ignore it. placement?: TerminalPanePlacement - // Visible restores are `user-resume`, hidden ones `automatic-restore`; the fork gate validates. spawnIntent?: SpawnIntent - // The agent launch this pane's spawn starts; main admits and plans it. agentLaunch?: AgentPaneLaunchRequest - // Why: loose typing on purpose — renderer owns launch metadata, main owns whether the launch happened and validates (telemetry-plan.md §Agent launch semantics). telemetry?: { agent_kind: AgentKind; launch_source: LaunchSource; request_kind: RequestKind } }): Promise<{ id: string - /** Which lifetime of `id` this reply named; absent when the execution host predates the field. */ incarnationId?: string launchConfig?: SleepingAgentLaunchConfig snapshot?: string @@ -87,7 +79,6 @@ export const ptySessionControlApi = { coldRestore?: { scrollback: string; cwd: string; cols?: number; rows?: number } startupCwdFallback?: { kind: 'worktree'; cwd: string } agentResumeUnavailable?: true - /** Host verdict on the shell-ready marker; absent when the execution host predates the field. */ shellReadyArmed?: boolean }> => ipcRenderer.invoke('pty:spawn', opts), write: (id: string, data: string, inputKind: TerminalInputKind): void => { diff --git a/src/preload/api/pty-bridge-stream-and-serialization.ts b/src/preload/api/pty-bridge-stream-and-serialization.ts index af28a6a13d7..467a7fc8145 100644 --- a/src/preload/api/pty-bridge-stream-and-serialization.ts +++ b/src/preload/api/pty-bridge-stream-and-serialization.ts @@ -91,12 +91,9 @@ export const ptyStreamAndSerializationApi = { id: string code: number preserveRendererBinding?: boolean - /** Which lifetime of `id` died; absent when the execution host predates the field. */ incarnationId?: string hostId?: string - /** Set only when the owning relay disowned this id; never a claim that the process died. */ ptySourceDisowned?: true - /** Main stopped this PTY so a new process could take its pane; the pane is not dying. */ replacedByRestart?: true }) => void ): (() => void) => { diff --git a/src/preload/api/pty-management-api.ts b/src/preload/api/pty-management-api.ts index 8c57f820284..0ad73c57b9a 100644 --- a/src/preload/api/pty-management-api.ts +++ b/src/preload/api/pty-management-api.ts @@ -1,7 +1,7 @@ import type { DaemonPtyCwdClass } from '../../shared/daemon-adoption-telemetry' import type { DaemonAsyncIoStatus } from '../../shared/daemon-async-io-health' -// Mirror of daemon's `DaemonSessionInfo` (src/main/daemon/types.ts); not imported — preload can't depend on main-only protocol types. +// Mirrors DaemonSessionInfo; preload cannot import main-only daemon protocol types. export type PtyManagementSession = { sessionId: string state: 'created' | 'spawning' | 'running' | 'exiting' | 'exited' @@ -15,34 +15,29 @@ export type PtyManagementSession = { protocolVersion: number } -// 'severed': macOS can no longer attribute daemon terminals to Orca, so Accessibility/ -// Automation grants silently stop applying until the daemon is restarted (STA-3491). +// severed: macOS privacy grants stop applying to daemon terminals until daemon restart. export type PtyManagementMacTccAttributionHealth = 'intact' | 'severed' | 'unknown' export type PtyManagementDaemonCwdClass = DaemonPtyCwdClass -// The daemon spawned a terminal into a folder it can't read while Orca can (STA-7948). -// `daemonScope` is an opaque per-daemon digest, never a path — it only latches the notice. -// `freshDaemonAccess` is what a daemon forked now would get: 'allowed' means restarting is the -// whole remedy, 'denied' means Orca must be re-allowed first, 'unknown' means main could not tell. +// Access a fresh daemon would get: allowed needs restart; denied needs renewed Orca permission. export type PtyManagementFreshDaemonAccess = 'allowed' | 'denied' | 'unknown' +// The daemon cannot read a folder Orca can. export type PtyManagementFolderAccessMismatch = { + /** Opaque per-daemon digest used to latch the notice, never a path. */ daemonScope: string cwdClass: PtyManagementDaemonCwdClass freshDaemonAccess: PtyManagementFreshDaemonAccess } -// Mirrors DaemonFolderAccessResetResult in src/main/daemon/daemon-folder-access-reset.ts. -// 'unsupported': nothing to reset, or the platform/app bundle cannot support one. -// 'reset_failed': tccutil refused. 'probed': the reset ran and `mismatch` is the fresh verdict. +// Mirrors DaemonFolderAccessResetResult; probed carries the post-reset mismatch verdict. export type PtyManagementFolderAccessResetResult = | { outcome: 'unsupported' } | { outcome: 'reset_failed' } | { outcome: 'probed'; mismatch: PtyManagementFolderAccessMismatch | null } -// Mirrors SeveredDaemonStatus in src/main/daemon/daemon-host-image-state.ts: a Linux AppImage -// daemon kept for its live terminals although its program files are gone. +// Mirrors SeveredDaemonStatus: a live Linux AppImage daemon whose program files are gone. export type PtyManagementSeveredDaemon = { pid: number linuxStartTicks: string @@ -56,7 +51,7 @@ export type PtyManagementSeveredDaemonRestartResult = export type PtyManagementApi = { asyncIoHealth: () => Promise - // `degraded`: daemon is alive but can't spawn fresh PTYs, so new terminals run locally without daemon persistence. + // degraded: new PTYs fall back to local spawning without daemon persistence. listSessions: () => Promise<{ sessions: PtyManagementSession[]; degraded: boolean }> killAll: () => Promise<{ killedCount: number diff --git a/src/preload/api/repository-api.ts b/src/preload/api/repository-api.ts index 5a4003e12e5..a9a358e360f 100644 --- a/src/preload/api/repository-api.ts +++ b/src/preload/api/repository-api.ts @@ -23,13 +23,11 @@ import type { BaseRefDefaultResult, BaseRefSearchResult, Repo } from '../../shar export type RepositoryApi = { list: () => Promise - // Why: error union matches the IPC handler's return shape; renderer callers branch on `'error' in result`. add: (args: { path: string kind?: 'git' | 'folder' displayName?: string }) => Promise<{ repo: Repo } | { error: string }> - // Forget a project on one execution host only, leaving the same repo id on other hosts intact. removeForHost: (args: { repoId: string; hostId: string }) => Promise reorder: (args: { orderedIds: string[] }) => Promise<{ status: 'applied' | 'rejected' }> reorderForHost: (args: { @@ -74,7 +72,6 @@ export type RepositoryApi = { pickDirectory: () => Promise clone: (args: { url: string; destination: string }) => Promise cloneAbort: () => Promise - // Why: error union matches the IPC handler's return shape; renderer callers branch on `'error' in result`. create: (args: { parentPath: string name: string diff --git a/src/preload/api/runtime-api.ts b/src/preload/api/runtime-api.ts index b15cac1a28d..a2310a73a67 100644 --- a/src/preload/api/runtime-api.ts +++ b/src/preload/api/runtime-api.ts @@ -72,8 +72,7 @@ export type RuntimeApi = { onBrowserDriverChanged: ( callback: (event: { browserPageId: string; driver: RuntimeBrowserDriverState }) => void ) => () => void - // Why optional: matches onNativeChatLaunchDraftResolved — a renderer running against an older - // preload keeps working without the retention signal instead of throwing on every mount. + // Older preloads lack this signal. onBrowserRemoteViewersChanged?: ( callback: (event: { browserPageId: string; hasRemoteViewers: boolean }) => void ) => () => void @@ -129,7 +128,7 @@ export type RuntimeApi = { prepareBrowserClientHostPlacement: ( args: BrowserClientHostPlacementPreparationRequest ) => Promise - // Why: system resume / browser online advance pending shared-control reconnect timers only. + // Resume/online events advance only pending shared-control reconnect timers. retryConnectionsNow?: () => Promise call: (args: { selector: string @@ -157,9 +156,9 @@ export type RuntimeApi = { onClose?: () => void } ) => Promise - // Why optional: only the desktop preload deploys servers over SSH. + // Only desktop clients deploy servers over SSH. managedOrcad?: ManagedOrcadPreloadApi - // Why optional: only a Windows desktop (or the e2e fake) has WSL distros to host. + // Only Windows desktops (or e2e fakes) host WSL distros. wslHosts?: WslHostsPreloadApi } wsl: { diff --git a/src/preload/api/session-bridge.ts b/src/preload/api/session-bridge.ts index 3cecbd9e7c4..2f33fa21263 100644 --- a/src/preload/api/session-bridge.ts +++ b/src/preload/api/session-bridge.ts @@ -2,7 +2,6 @@ import { ipcRenderer } from 'electron' import type { PreloadApi } from '../api-types' export const sessionApi = { - // hostId is optional; main defaults it to 'local' so existing omitting call sites keep the local session partition. get: (hostId) => ipcRenderer.invoke('session:get', hostId), listHostIds: () => ipcRenderer.invoke('session:list-host-ids'), set: (args, hostId) => ipcRenderer.invoke('session:set', args, hostId), diff --git a/src/preload/api/settings-api.ts b/src/preload/api/settings-api.ts index 30f84c59b39..9b57c778556 100644 --- a/src/preload/api/settings-api.ts +++ b/src/preload/api/settings-api.ts @@ -7,7 +7,7 @@ import type { GhosttyImportPreview, GlobalSettings } from '../../shared/global-s export type SettingsApi = { get: () => Promise - /** Synchronous persisted-settings read for startup decisions that can't wait for async hydration. Blocking IPC — call sparingly. */ + /** Blocking IPC for startup decisions that cannot wait for hydration; call sparingly. */ getSync: () => GlobalSettings | null set: (args: Partial) => Promise setActiveRuntimeEnvironmentPreference: (args: { @@ -17,7 +17,6 @@ export type SettingsApi = { listFonts: () => Promise previewGhosttyImport: () => Promise previewWarpThemeImport: (source: WarpThemeImportSource) => Promise - /** Subscribe to out-of-band settings updates (e.g. View > Appearance toggles) to stay in sync with main. */ onChanged: (callback: (updates: Partial) => void) => () => void } diff --git a/src/preload/api/settings-bridge.ts b/src/preload/api/settings-bridge.ts index 4e7105c00cb..b7ac53919fc 100644 --- a/src/preload/api/settings-bridge.ts +++ b/src/preload/api/settings-bridge.ts @@ -9,7 +9,6 @@ import type { PreloadApi } from '../api-types' export const settingsApi = { get: () => ipcRenderer.invoke('settings:get'), - // Why: blocking read for the few startup decisions (terminal side-effect authority) that can't wait for async hydration. Call sparingly. getSync: () => ipcRenderer.sendSync('settings:get-sync'), set: (args: Record) => ipcRenderer.invoke('settings:set', args), diff --git a/src/preload/api/skills-bridge.ts b/src/preload/api/skills-bridge.ts index e84e617edc1..92c51857c9c 100644 --- a/src/preload/api/skills-bridge.ts +++ b/src/preload/api/skills-bridge.ts @@ -85,7 +85,6 @@ export const skillsApi = { ipcRenderer.invoke('skills:previewBundleInstall', input), removeInstall: (input: SkillRemoveInput): Promise => ipcRenderer.invoke('skills:removeInstall', input), - // Desktop always registers the delete IPC handlers in its own main process. deleteSupported: (): Promise => Promise.resolve(true), previewDelete: (request: SkillDeleteRequest): Promise => ipcRenderer.invoke('skills:previewDelete', request), diff --git a/src/preload/api/speech-bridge.ts b/src/preload/api/speech-bridge.ts index 86465ef42c6..a97eff852ab 100644 --- a/src/preload/api/speech-bridge.ts +++ b/src/preload/api/speech-bridge.ts @@ -32,7 +32,7 @@ export const speechApi = { sessionId: string ): Promise => ipcRenderer.invoke('speech:startDictation', modelId, hotwords, sessionId), feedAudio: (samples: Float32Array, sampleRate: number, sessionId = 'desktop'): Promise => - // Why: Float32Array is zeroed crossing the contextBridge/IPC boundary; wrap in a Buffer to preserve bytes. + // Buffer preserves sample bytes across the contextBridge/IPC boundary. ipcRenderer.invoke( 'speech:feedAudio', Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength), diff --git a/src/preload/api/ssh-api.ts b/src/preload/api/ssh-api.ts index b3c76976a9d..7b0081bcbfc 100644 --- a/src/preload/api/ssh-api.ts +++ b/src/preload/api/ssh-api.ts @@ -15,7 +15,7 @@ import type { FilesystemPathFlavor } from '../../shared/filesystem-entry-types' export type SshApi = { listTargets: () => Promise - // Removed-target id → last known label, for a friendly host name on workspaces still pinned to a removed target. + // Last known labels keyed by removed target ID, for workspaces still pinned to them. listRemovedTargetLabels: () => Promise> addTarget: (args: { target: SshTargetCreateInput }) => Promise updateTarget: (args: { id: string; updates: SshTargetUpdateInput }) => Promise diff --git a/src/preload/api/telemetry-api.ts b/src/preload/api/telemetry-api.ts index 16bff62690d..48b9670d45f 100644 --- a/src/preload/api/telemetry-api.ts +++ b/src/preload/api/telemetry-api.ts @@ -47,19 +47,14 @@ export type DiagnosticsApi = { } export type TelemetryApi = { - /** True means captured or already recorded today; older bridges return void. - * Use lib/telemetry.ts wrappers; main validates the deliberately loose IPC payload. */ + /** Use lib/telemetry.ts; true means captured/already recorded today, void is a legacy reply. */ telemetryTrack: (name: string, props: Record) => Promise - /** Flip the persisted opt-in preference. Subject to a per-session - * consent-mutation rate limit on the main side (≤5/session). */ + /** Main permits at most five consent mutations per session. */ telemetrySetOptIn: (optedIn: boolean) => Promise - /** Diagnostic file controls (telemetry-error-tracking.md §User controls). Main does the FS/network - * work and retains upload payloads so the renderer can't read or substitute arbitrary bytes. */ + /** Main retains upload payloads so the renderer cannot read or substitute arbitrary bytes. */ diagnostics: DiagnosticsApi - /** Read-only effective consent state (+ reason if disabled) — env vars are main-side state the renderer can't read directly. */ telemetryGetConsentState: () => Promise - /** Banner ✕ — persist `optedIn = true` silently. Separate channel from `telemetrySetOptIn`, - * whose `via` derivation would wrongly fire `telemetry_opted_in`. Same per-session rate limit. */ + /** Banner dismissal opts in without emitting telemetry_opted_in; shares the consent rate limit. */ telemetryAcknowledgeBanner: () => Promise stats: StatsApi memory: MemoryApi diff --git a/src/preload/api/ui-bridge-clipboard-and-window-controls.ts b/src/preload/api/ui-bridge-clipboard-and-window-controls.ts index a205efcebfd..fc2c91cbedd 100644 --- a/src/preload/api/ui-bridge-clipboard-and-window-controls.ts +++ b/src/preload/api/ui-bridge-clipboard-and-window-controls.ts @@ -79,9 +79,7 @@ export const uiClipboardAndWindowControlsApi = { connectionId?: string | null runtimeEnvironmentId?: string | null agentSessionAttachment?: AgentSessionAttachmentClipboardTarget - /** A native-chat composer paste, kept where its draft can bring it back. */ forNativeChatDraft?: boolean - /** With `forNativeChatDraft`: a structured chat on this machine, whose sends claim its pastes. */ forStructuredChat?: boolean }): Promise => ipcRenderer.invoke('clipboard:saveImageAsTempFile', args), savePastedTextAsFile: (args: { @@ -194,7 +192,7 @@ export const uiClipboardAndWindowControlsApi = { _event: Electron.IpcRendererEvent, data: { isQuitting: boolean; requestId?: number } ): void => { - // Why: main cannot reach will-quit while a frozen renderer owns the window close handshake. + // Acknowledge before callbacks: a frozen renderer can block main from reaching will-quit. ipcRenderer.send('window:close-request-received', data?.requestId) callback({ isQuitting: data?.isQuitting ?? false }) } diff --git a/src/preload/api/ui-bridge-terminal-and-session-tabs.ts b/src/preload/api/ui-bridge-terminal-and-session-tabs.ts index 20f5f7501e6..b24f01518d1 100644 --- a/src/preload/api/ui-bridge-terminal-and-session-tabs.ts +++ b/src/preload/api/ui-bridge-terminal-and-session-tabs.ts @@ -215,12 +215,7 @@ export const uiTerminalAndSessionTabsApi = { return () => ipcRenderer.removeListener('ui:focusTerminal', listener) }, onFocusEditorTab: ( - callback: (data: { - tabId: string - worktreeId: string - /** The user clicked a notification, so revealing the tab is navigation and not a courtesy. */ - userInitiated?: boolean - }) => void + callback: (data: { tabId: string; worktreeId: string; userInitiated?: boolean }) => void ): (() => void) => { const listener = ( _event: Electron.IpcRendererEvent, diff --git a/src/preload/api/ui-command-event-api.ts b/src/preload/api/ui-command-event-api.ts index 00ea21f9c80..1f634f550b5 100644 --- a/src/preload/api/ui-command-event-api.ts +++ b/src/preload/api/ui-command-event-api.ts @@ -66,20 +66,16 @@ export type UiCommandEventApi = { mutateJiraSavedFilters?: (mutation: JiraSavedFilterMutation) => Promise get: () => Promise set: (args: Partial) => Promise - /** Like set, but REJECTS when the update did not reach the host (the web preload's set - * swallows transport failures for offline use). The diff writer needs the distinction: - * folding an unacked patch into its baseline would silently stop retrying it (STA-5781). */ + /** Unlike web set, rejects transport failures so the diff writer retries unacknowledged patches. */ setWithAck?: (args: Partial) => Promise recordFeatureInteraction: (id: FeatureInteractionId) => Promise onStateChanged: (callback: (ui: PersistedUIState) => void) => () => void onOpenSettings: (callback: () => void) => () => void - /** Consumes a one-shot tray/menu-bar "open settings" intent queued before mount. */ consumePendingOpenSettings: () => Promise onOpenSkillShare: (callback: (shareId: string) => void) => () => void consumePendingSkillShare: () => Promise /** OS "Open With" Markdown/CSV/TSV documents; the local IPC name is retained. */ onOpenMarkdownFiles: (callback: (documents: MarkdownDocument[]) => void) => () => void - /** Drains the "Open With" paths queued before this renderer's listener attached. */ consumePendingMarkdownFileOpens: () => Promise onOpenSetupGuide: (callback: () => void) => () => void onOpenFeatureTour: (callback: () => void) => () => void @@ -248,7 +244,7 @@ export type UiCommandEventApi = { callback: (data: { tabId: string worktreeId: string - /** The user clicked a notification, so revealing the tab is navigation and not a courtesy. */ + /** A notification click authorizes revealing the tab. */ userInitiated?: boolean }) => void ) => () => void @@ -268,7 +264,6 @@ export type UiCommandEventApi = { position?: RuntimeFileOpenPosition }) => void ) => () => void - /** Layout-owner builds: shows a tab main wrote for a file it opened. */ onRevealEditorTabFromRuntime: (callback: (data: RuntimeEditorTabReveal) => void) => () => void onOpenDiffFromMobile: ( callback: (data: { @@ -283,7 +278,7 @@ export type UiCommandEventApi = { onCloseTerminal: (callback: (target: TerminalSurfaceCloseTarget) => void) => () => void onTerminalTabCloseRequest: (callback: (request: TerminalTabCloseRequest) => void) => () => void respondTerminalTabClose: (response: TerminalTabCloseResponse) => void - /** A sleep main runs on this window's workspace, whoever asked; the window follows it. */ + /** Follow main's workspace sleep even when another client requested it. */ onWorkspaceSleep: (callback: (notice: WorkspaceSleepNotice) => void) => () => void onResumeSleepingAgents: (callback: (data: { worktreeId: string }) => void) => () => void onTerminalZoom: (callback: (direction: 'in' | 'out' | 'reset') => void) => () => void diff --git a/src/preload/api/ui-window-api.ts b/src/preload/api/ui-window-api.ts index 184a767f1d6..d9c61f73554 100644 --- a/src/preload/api/ui-window-api.ts +++ b/src/preload/api/ui-window-api.ts @@ -18,16 +18,16 @@ export type UiWindowApi = { /** With `forNativeChatDraft`: a structured chat on this machine, whose sends claim its pastes. */ forStructuredChat?: boolean }) => Promise - /** A long text paste saved as a file the chat's agent reads: here, or in its paired server's store. */ + /** Saves paste text on the execution host so the agent can read it. */ savePastedTextAsFile: (args: { text: string runtimeEnvironmentId?: string | null agentSessionAttachment?: AgentSessionAttachmentClipboardTarget }) => Promise clipboardHasImage: () => Promise - /** Paths of files a file manager copied; empty when there are none or the host cannot list them. */ + /** Empty if no files were copied or the host cannot list them. */ readClipboardFilePaths: () => Promise - /** Which restored draft pastes are still kept: files really in Orca's paste folder. */ + /** Only files inside Orca's paste folder count as kept. */ restoreNativeChatPastes: ( paths: string[] ) => Promise<{ path: string; kept: boolean; exists: boolean }[]> @@ -53,7 +53,6 @@ export type UiWindowApi = { syncTrafficLights: (zoomFactor: number) => void setMarkdownEditorFocused: (focused: boolean) => void setRichMarkdownContextMenuTarget: (target: RichMarkdownContextMenuTableTarget | null) => void - /** The next editable context menu opens on plain text, not a rich Markdown editor. */ markPlainTextContextMenuTarget: () => void setTerminalInputFocused: (focused: boolean) => void setFloatingFocus: (state: { panelFocused: boolean; terminalFocused: boolean }) => void diff --git a/src/preload/api/updater-api.ts b/src/preload/api/updater-api.ts index f768509e647..6c2fe707f54 100644 --- a/src/preload/api/updater-api.ts +++ b/src/preload/api/updater-api.ts @@ -18,7 +18,7 @@ export type UpdaterApi = { getLinuxPackageInstallInstructions: () => Promise /** Desktop-only. Reveals the revalidated cached package in the native file manager. */ showLinuxPackage: () => Promise - /** `force` bypasses the main-process list cache — the refresh button, not mount or channel switches. */ + /** Use force to bypass the cache only for an explicit refresh. */ listBuilds: ( channel: ReleaseChannel, options?: { force?: boolean } diff --git a/src/preload/api/workspace-cleanup-api.ts b/src/preload/api/workspace-cleanup-api.ts index 0e45a55aa98..9349496d418 100644 --- a/src/preload/api/workspace-cleanup-api.ts +++ b/src/preload/api/workspace-cleanup-api.ts @@ -20,7 +20,7 @@ export type WorkspaceCleanupApi = { onProgress?: (progress: WorkspaceCleanupScanProgress) => void ) => Promise cancelScan?: (scanId: string) => Promise - /** Last persisted broad-scan snapshot; null until one completes or when the cache is stale/corrupt. */ + /** Null until a scan completes or when its cache is stale/corrupt. */ getCachedScan: () => Promise dismiss: (args: WorkspaceCleanupDismissArgs) => Promise clearDismissals: () => Promise @@ -31,7 +31,7 @@ export type WorkspaceCleanupApi = { export type WorkspaceSpaceApi = { analyze: () => Promise - /** Last persisted analysis (topLevelItems pruned to bound the payload); null until one completes. */ + /** Cached analysis prunes topLevelItems to bound the payload. */ getCachedAnalysis: () => Promise cancel: () => Promise onProgress: (callback: (progress: WorkspaceSpaceScanProgress) => void) => () => void diff --git a/src/preload/api/workspace-session-api.ts b/src/preload/api/workspace-session-api.ts index 1b7e07eb50b..b816c2cde0e 100644 --- a/src/preload/api/workspace-session-api.ts +++ b/src/preload/api/workspace-session-api.ts @@ -8,9 +8,9 @@ import type { TerminalSurfaceCloseTarget } from '../../shared/terminal-surface-c export type WorkspaceSessionApi = { session: { - // hostId defaults to the 'local' partition on main, so omitting it stays backward-compatible. + // Omitted hostId selects the local persistence partition. get: (hostId?: ExecutionHostId) => Promise - /** Partitions persistence holds, so boot reads them all instead of guessing from the catalog. */ + /** Read persisted partitions at boot; the host catalog may omit some. */ listHostIds: () => Promise set: (args: WorkspaceSessionState, hostId?: ExecutionHostId) => Promise patch: (args: WorkspaceSessionPatch, hostId?: ExecutionHostId) => Promise diff --git a/src/preload/api/worktree-api.ts b/src/preload/api/worktree-api.ts index 6ae12242aa5..90bb29086d4 100644 --- a/src/preload/api/worktree-api.ts +++ b/src/preload/api/worktree-api.ts @@ -44,9 +44,7 @@ import type { export type WorktreeApi = { list: (args: { repoId: string }) => Promise - /** Generated names already spent in this repo, including deleted workspaces. Name suggestions - * exclude these so a recreated workspace never lands on a prior occupant's path. Compacted: a - * fully spent tier is reported as the watermark rather than as its 552 names. */ + /** Retired names prevent path reuse; fully spent tiers are compacted into a watermark. */ listRetiredNames: (args: { repoId: string }) => Promise listDetected: { ( @@ -57,7 +55,7 @@ export type WorktreeApi = { listKnownForExecutionHost?: ( args: ListKnownWorktreesForExecutionHostArgs ) => Promise - /** Retires the persisted metadata an authoritative scan proved gone, so it stops feeding the read above. */ + /** Retire metadata only after an authoritative scan proves the workspace is gone. */ forgetRemovedForExecutionHost?: ( args: ForgetRemovedWorktreesForExecutionHostArgs ) => Promise @@ -65,9 +63,7 @@ export type WorktreeApi = { listAll: () => Promise create: (args: CreateWorktreeArgs) => Promise adoptProvisionedRoot: (args: AdoptProvisionedRootArgs) => Promise - /** Two-phase progress for a background `create`, correlated by `creationId`, plus git's - * checkout meter for local creates. The remote/runtime create path emits nothing, so the - * surface falls back to an indeterminate spinner. */ + /** Local creates report progress by creationId; remote/runtime creates emit nothing. */ onCreateProgress: (callback: (data: CreateWorktreeProgressEvent) => void) => () => void prefetchCreateBase: (args: { repoId: string; baseBranch?: string }) => Promise resolvePrBase: (args: { @@ -77,9 +73,7 @@ export type WorktreeApi = { baseRefName?: string isCrossRepository?: boolean }) => Promise - /** GitLab parallel of resolvePrBase. For same-project MRs returns - * `/`; for fork MRs fetches - * refs/merge-requests//head and returns the SHA. */ + /** Same-project MRs return a remote branch; forks fetch the MR head ref and return its SHA. */ resolveMrBase: (args: { repoId: string mrIid: number @@ -93,28 +87,23 @@ export type WorktreeApi = { worktreeId: string hostId?: ExecutionHostId }) => Promise - /** Main sleeps each workspace on its hosts; the window shows the outcome. */ sleep: (request: WorkspaceSleepRequest) => Promise - /** The user opened a workspace whose sleep main is still running. */ sleepReopened: (worktreeId: string) => Promise - /** Main resumes a slept pane; true once it runs, so the pane's own spawn attaches to it. */ + /** True once running, so the renderer's subsequent spawn reattaches. */ resumeSleptPane: (pane: { worktreeId: string; tabId: string; leafId: string }) => Promise remove: (args: { worktreeId: string hostId?: ExecutionHostId force?: boolean approvedNestedWorktrees?: NestedWorktreeRemovalApproval[] - // Why (#11960): distinct from `force`, which the plain Delete confirmation - // already sets to skip the dirty-file prompt. Only an explicit Force Delete - // may waive the proof that every PTY stopped. + // Only explicit Force Delete waives PTY-stop proof; force merely skips dirty-file prompts. allowUnverifiedPtyStop?: boolean skipArchive?: boolean - // Why (#19334): distinct from `skipArchive` (never runs the hook) and never implied by - // `force` — this waives a hook that ran and FAILED. + // Waives a failed hook, unlike skipArchive; force does not imply this approval. allowFailedArchiveHook?: boolean snapshotPruneBatchId?: string }) => Promise - // Forget a workspace from Orca only (no remote Git/FS work) — for workspaces pinned to a removed/disconnected SSH host. + // Forget local metadata without remote Git/FS work, even when the SSH host is unavailable. forgetLocal: (args: { worktreeId: string hostId?: ExecutionHostId @@ -141,8 +130,7 @@ export type WorktreeApi = { noParent?: boolean }) => Promise persistSortOrder: (args: { orderedIds: string[]; hostIds?: string[] }) => Promise - /** Full CLI output of the last branch auto-rename generation failure, held - * in main memory only — null after a restart or once the failure clears. */ + /** Last failure output; memory-only, cleared on restart or when the failure clears. */ getBranchRenameFailureOutput: (args: { worktreeId: string }) => Promise onChanged: (callback: (data: { repoId: string }) => void) => () => void onGitStatusMetadataChanged: ( diff --git a/src/preload/api/wsl-hosts-api.ts b/src/preload/api/wsl-hosts-api.ts index 619a21021e3..fbc02d5f818 100644 --- a/src/preload/api/wsl-hosts-api.ts +++ b/src/preload/api/wsl-hosts-api.ts @@ -1,7 +1,4 @@ -/** - * WSL distros as hosts; desktop-only and Windows-only (or the e2e fake) behind the internal gate, - * else undefined. - */ +// Available only on Windows desktops or e2e fakes with the internal gate enabled. import { ipcRenderer } from 'electron' import { WSL_HOST_STATUS_CHANNEL, diff --git a/src/preload/browser-find-subscriptions.test.ts b/src/preload/browser-find-subscriptions.test.ts index e6c279ed24a..c25b00baa1d 100644 --- a/src/preload/browser-find-subscriptions.test.ts +++ b/src/preload/browser-find-subscriptions.test.ts @@ -31,8 +31,6 @@ describe('browser Find subscriptions', () => { expect(samePageCallback).not.toHaveBeenCalled() }) - // A client-hosted guest is registered by main's host runtime with no workspace, so its forwarded - // chord can only name the page. it('dispatches a page-only target to every workspace holding that page', () => { const subscriptions = createBrowserFindSubscriptions() const firstCallback = vi.fn() @@ -54,8 +52,7 @@ describe('browser Find subscriptions', () => { const callback = vi.fn() subscriptions.subscribe(FIRST_SOURCE, callback) - // Structured-clone IPC preserves an explicitly-undefined property, so main's optional field - // arrives as a present key rather than an absent one. + // Structured-clone IPC preserves explicitly undefined properties. subscriptions.dispatch({ browserPageId: FIRST_SOURCE.browserPageId, browserWorkspaceId: undefined @@ -92,12 +89,9 @@ describe('browser Find subscriptions', () => { subscriptions.dispatch(FIRST_SOURCE) subscriptions.dispatch({ browserPageId: FIRST_SOURCE.browserPageId }) expect(callback).not.toHaveBeenCalled() - // Not just silent — the entry is gone, so a long session cannot accumulate empty maps. expect(subscriptions.subscribedPageCount()).toBe(0) }) - // Why: the page entry is shared, so pruning it on one workspace's cleanup would silently - // unsubscribe its siblings. it('keeps the other workspaces on a page when one of them unsubscribes', () => { const subscriptions = createBrowserFindSubscriptions() const firstCallback = vi.fn() diff --git a/src/preload/browser-find-subscriptions.ts b/src/preload/browser-find-subscriptions.ts index caf00cc2d2c..8bd9e2a76d0 100644 --- a/src/preload/browser-find-subscriptions.ts +++ b/src/preload/browser-find-subscriptions.ts @@ -5,12 +5,9 @@ type BrowserFindCallback = () => void export function createBrowserFindSubscriptions(): { dispatch: (target: unknown) => void subscribe: (source: BrowserFindSource, callback: BrowserFindCallback) => () => void - /** Pages currently holding subscribers. This registry outlives every pane, so a cleanup that - * leaves entries behind grows without bound over a session. */ subscribedPageCount: () => number } { - // Why: page first, workspace second — a target that names only the page must still reach the one - // pane that owns it, while active splits sharing this renderer stay separable by workspace. + // Page-only targets must reach every workspace holding that page. const callbacksByPage = new Map>>() return { diff --git a/src/preload/browser-window-close.ts b/src/preload/browser-window-close.ts index 7fb8201377f..00935d8c1db 100644 --- a/src/preload/browser-window-close.ts +++ b/src/preload/browser-window-close.ts @@ -1,7 +1,7 @@ import { installBrowserWindowCloseGuard } from './browser-window-close-installation' import type { ContextBridge } from 'electron' -// Why: raw require keeps the sandboxed preload standalone in the main-process CJS build. +// Raw require keeps the sandboxed preload standalone in the CJS build. const { contextBridge } = require('electron') as { contextBridge: ContextBridge } contextBridge.executeInMainWorld({ func: installBrowserWindowCloseGuard }) diff --git a/src/preload/doc-preview-link-interception.test.ts b/src/preload/doc-preview-link-interception.test.ts index 489d0d93cd5..3e0e92f5c58 100644 --- a/src/preload/doc-preview-link-interception.test.ts +++ b/src/preload/doc-preview-link-interception.test.ts @@ -12,7 +12,6 @@ const PREVIEW_GRANT_ID = 'a'.repeat(32) let report: ReturnType void>> -/** The URL the guest is actually on, which is what decides whether an href is a pure fragment. */ function documentUrl(): string { return window.location.href } @@ -22,11 +21,7 @@ function loadPreviewDocument(body: string): void { report = vi.fn<(url: string) => void>() } -/** - * An SVG anchor around a hit target, built rather than parsed: the href is an SVGAnimatedString - * carrying the raw attribute, which is what a plain string read misses and the environment does - * not model. - */ +// happy-dom does not model SVGAnimatedString hrefs. function loadSvgAnchorDocument(href: string): void { loadPreviewDocument('
') const svgNamespace = 'http://www.w3.org/2000/svg' @@ -41,10 +36,6 @@ function loadSvgAnchorDocument(href: string): void { document.getElementById('host')!.appendChild(svg) } -/** - * Dispatches through the same capture-phase listener the preload installs, but registered for one - * press only — a document-level listener left behind would answer every later test's clicks too. - */ function dispatch(selector: string, event: MouseEvent): MouseEvent { const onClick = (candidate: Event): void => handleDocPreviewLinkClick(candidate, report) const onAuxClick = (candidate: Event): void => @@ -60,7 +51,6 @@ function dispatch(selector: string, event: MouseEvent): MouseEvent { return event } -/** Chromium's own press. Nothing a document can dispatch carries this. */ function pressTrusted(selector: string, init: MouseEventInit = {}): MouseEvent { const event = new MouseEvent('click', { bubbles: true, cancelable: true, ...init }) Object.defineProperty(event, 'isTrusted', { configurable: true, value: true }) @@ -68,8 +58,6 @@ function pressTrusted(selector: string, init: MouseEventInit = {}): MouseEvent { } beforeEach(() => { - // Why: the module decides "sibling document" and "pure fragment" against the URL the guest is - // really on, which in a preview is always the preview scheme. ;(window as never as { happyDOM: { setURL: (url: string) => void } }).happyDOM.setURL( `orca-preview://${PREVIEW_GRANT_ID}/index.html` ) @@ -82,7 +70,7 @@ describe('doc preview link interception', () => { }) it('listens for both press kinds in the capture phase, so the document cannot consume them first', () => { - // Why not let it register: a document-level listener would survive into every later press here. + // Avoid leaving document listeners attached across tests. const addEventListener = vi.spyOn(document, 'addEventListener').mockImplementation(() => {}) installDocPreviewLinkInterception(vi.fn()) @@ -93,14 +81,11 @@ describe('doc preview link interception', () => { ]) }) - // Why the headline: this is the whole point of the design. A document that can read its grant - // must not be able to hand it to a browser tab by synthesizing the reader's click. it('routes nothing for a click the document dispatched itself', () => { loadPreviewDocument('go') const scripted = new MouseEvent('click', { bubbles: true, cancelable: true }) - // Why set it: this is what Chromium stamps on anything a document dispatches, and the test - // environment leaves the property off entirely. + // happy-dom omits the isTrusted value Chromium sets for synthetic clicks. Object.defineProperty(scripted, 'isTrusted', { configurable: true, value: false }) const event = dispatch('#external', scripted) @@ -127,8 +112,6 @@ describe('doc preview link interception', () => { expect(report).toHaveBeenCalledExactlyOnceWith('https://example.com/docs') }) - // Why: an SVG anchor's href is an SVGAnimatedString, so reading it as a string finds nothing and - // the link would fall through to the guest's navigation guard and die there. it('reports an SVG anchor by its animated href', () => { loadSvgAnchorDocument('https://example.com/chart') @@ -137,9 +120,6 @@ describe('doc preview link interception', () => { expect(report).toHaveBeenCalledExactlyOnceWith('https://example.com/chart') }) - // Why these three: baseVal is the raw attribute, so an unresolved read sends a relative sibling - // out to a browser tab, drops SVG fragment links on the floor, and turns a rooted path into a - // file URL the guest refuses — each one a divergence from the identical HTML anchor. it('leaves a relative SVG link to the guest, the same as the HTML anchor beside it', () => { loadSvgAnchorDocument('guide.html') diff --git a/src/preload/doc-preview-link-interception.ts b/src/preload/doc-preview-link-interception.ts index 564bff1b883..91896a14ae8 100644 --- a/src/preload/doc-preview-link-interception.ts +++ b/src/preload/doc-preview-link-interception.ts @@ -1,21 +1,10 @@ -/** - * Decides what a click inside a preview guest means. This is the only way a URL leaves the - * preview, so it answers for a click the reader really made: navigation the document starts by - * itself never reaches here, and the guest's navigation policy refuses it outright. - * - * Runs in the guest's isolated world and exposes nothing to page script — the document cannot see - * these listeners, remove them, or call what they call. - */ +// Runs in the isolated world so page scripts cannot access the link reporter or its listeners. export type DocPreviewExternalLinkReporter = (url: string) => void -/** - * Why the channel name is written out rather than imported: this module is bundled into a - * sandboxed preload, whose `require` resolves only 'electron', so an import of shared code emits a - * chunk require the guest cannot load. The test pins it to the constant main listens on. - */ +// Keep this literal: shared imports emit chunk requires the sandboxed preload cannot load. export const PRELOAD_DOC_PREVIEW_LINK_CLICK_CHANNEL = 'docPreview:linkClick' -/** Why not `instanceof HTMLAnchorElement`: an SVG `` is an anchor too, and carries an SVGAnimatedString href. */ +// SVG anchors carry an SVGAnimatedString href and are not HTMLAnchorElements. function readAnchorHref(node: EventTarget): string | null { const element = node as { tagName?: unknown; href?: unknown } if (typeof element.tagName !== 'string' || element.tagName.toUpperCase() !== 'A') { @@ -28,8 +17,7 @@ function readAnchorHref(node: EventTarget): string | null { if (typeof baseVal !== 'string' || baseVal.length === 0) { return null } - // Why resolved here: baseVal is the raw attribute, unlike an HTML anchor's absolute href, so - // every branch below would read an SVG link differently from the identical HTML one. + // SVG baseVal is relative; normalize it to match HTML anchors' absolute hrefs. try { return new URL(baseVal, window.location.href).toString() } catch { @@ -37,7 +25,7 @@ function readAnchorHref(node: EventTarget): string | null { } } -/** Why the composed path and not `event.target`: the press lands on whatever the anchor wraps, shadow roots included. */ +// The anchor may wrap the clicked element, including across a shadow root. function findClickedAnchor(event: Event): { element: EventTarget; href: string } | null { for (const node of event.composedPath()) { const href = readAnchorHref(node) @@ -70,13 +58,12 @@ function scrollToFragment(fragment: string): void { target.scrollIntoView() return } - // Why: `#top` names the top of the document even when nothing carries that id. + // #top also works without a matching element. if (fragment === 'top') { scrollToDocumentTop() } } -/** True when the href only moves within the document already on screen, which this handles itself. */ function handleInDocumentFragment(element: EventTarget, href: string): boolean { if (readAttribute(element, 'href') === '#') { scrollToDocumentTop() @@ -108,7 +95,7 @@ export function handleDocPreviewLinkClick( event: Event, report: DocPreviewExternalLinkReporter ): void { - // Why first: a click the page dispatched is the document asking to leave, not the reader. + // Only user clicks may open external links. if (!event.isTrusted) { return } @@ -120,8 +107,7 @@ export function handleDocPreviewLinkClick( event.preventDefault() return } - // Why left alone: a link served the way this document was is a sibling preview document, which - // the guest policy already answers for — it navigates natively and the preview keeps its history. + // Let the guest navigate sibling preview documents to preserve its history. if (isSameSchemeAsDocument(anchor.href)) { return } @@ -136,13 +122,12 @@ export function handleDocPreviewLinkAuxClick(event: MouseEvent): void { if (!findClickedAnchor(event)) { return } - // Why swallowed rather than routed: a middle click asks for a background tab, and honouring it - // would let one press the reader barely registered open a browser tab. + // Suppress middle-click navigation to avoid opening an external background tab. event.preventDefault() } export function installDocPreviewLinkInterception(report: DocPreviewExternalLinkReporter): void { - // Why capture: the document's own handlers must not be able to consume the press first. + // Capture before the document's handlers can consume the click. document.addEventListener('click', (event) => handleDocPreviewLinkClick(event, report), true) document.addEventListener( 'auxclick', diff --git a/src/preload/doc-preview-link.ts b/src/preload/doc-preview-link.ts index e88e4ab7801..e9ad5802318 100644 --- a/src/preload/doc-preview-link.ts +++ b/src/preload/doc-preview-link.ts @@ -3,13 +3,12 @@ import { PRELOAD_DOC_PREVIEW_LINK_CLICK_CHANNEL } from './doc-preview-link-interception' -// Why: raw require keeps the sandboxed preload standalone in the main-process CJS build. +// Raw require keeps the sandboxed preload standalone in the CJS build. const { ipcRenderer } = require('electron') as { ipcRenderer: { send: (channel: string, ...args: unknown[]) => void } } -// Why no contextBridge: the document must not be able to call this. The listeners live in the -// isolated world, and main still refuses any report that does not come from a live, grant-bound preview guest. +// Keep the reporter in the isolated world so the document cannot call it through contextBridge. installDocPreviewLinkInterception((url) => { ipcRenderer.send(PRELOAD_DOC_PREVIEW_LINK_CLICK_CHANNEL, url) }) diff --git a/src/preload/e2e-config.ts b/src/preload/e2e-config.ts index 8414f62d39a..c62c844a7c8 100644 --- a/src/preload/e2e-config.ts +++ b/src/preload/e2e-config.ts @@ -10,19 +10,13 @@ function isEnvFlagEnabled(value: boolean | string | undefined): boolean { return value === true || value === 'true' } -// Why: `--mode e2e` must be enough for manual rebuilds used with SKIP_BUILD=1; -// keeping this out of a root .env file makes the test-only toggle less visible. +// --mode e2e must also expose the store for manual SKIP_BUILD=1 rebuilds. const exposeStore = preloadEnv?.MODE === 'e2e' || isEnvFlagEnabled(preloadEnv?.VITE_EXPOSE_STORE) -// Why: preload is the renderer's audited bridge into Electron startup state. -// Renderer code should consume a typed config object from this bridge instead -// of reading test-only env vars directly. export const preloadE2EConfig = createE2EConfig({ headless: process.env.ORCA_E2E_HEADLESS === '1', exposeStore, userDataDir: process.env.ORCA_E2E_USER_DATA_DIR ?? null, - // Why: Number('') is 0 and Number(undefined) is NaN; both coerce to null so - // only a real positive override reaches the renderer parking policy. terminalParkingDelayMs: Number(process.env.ORCA_E2E_TERMINAL_PARKING_DELAY_MS) || null, terminalRetentionLimit: Number(process.env.ORCA_E2E_TERMINAL_RETENTION_LIMIT) || null }) diff --git a/src/preload/gitlab.ts b/src/preload/gitlab.ts index 1fdb9057702..e40756acb0b 100644 --- a/src/preload/gitlab.ts +++ b/src/preload/gitlab.ts @@ -1,7 +1,3 @@ -/* GitLab preload bindings — split out of `src/preload/index.ts` so - adding or changing a `gl.*` channel doesn't surface as a merge - conflict on every upstream sync of the much larger central preload - file. Composed back into `api.gl` from `index.ts`. */ import { ipcRenderer } from 'electron' import type { TaskSourceContext } from '../shared/task-source-context' diff --git a/src/preload/index.ts b/src/preload/index.ts index 968a299d330..1dbe3bfd962 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -88,7 +88,6 @@ import { speechApi } from './api/speech-bridge' installBrowserFindListener() -// Custom APIs for renderer. Each domain bridge owns its IPC contract. const telemetryTrackApi: PreloadApi['telemetryTrack'] = (name, props) => ipcRenderer.invoke('telemetry:track', name, props) const telemetrySetOptInApi: PreloadApi['telemetrySetOptIn'] = (optedIn) => diff --git a/src/preload/preload-runtime-support.ts b/src/preload/preload-runtime-support.ts index 2d043bb8cd0..f8753d7794e 100644 --- a/src/preload/preload-runtime-support.ts +++ b/src/preload/preload-runtime-support.ts @@ -4,7 +4,6 @@ import { createBrowserFindSubscriptions } from './browser-find-subscriptions' import { registerRendererRestartIpcRelays } from './renderer-restart-wiring' import { createUpdaterQuitAbortRelay } from '../shared/renderer-restart-preparation' import { ORCA_UPDATER_QUIT_AND_INSTALL_ABORTED_EVENT } from '../shared/updater-renderer-events' -/** Joins the synchronous unload checkpoint with its durable renderer write. */ export async function awaitBeforeUnloadCheckpoint(): Promise { const result = (await ipcRenderer.invoke('app:await-before-unload-checkpoint')) as { ok?: unknown @@ -37,7 +36,6 @@ export const browserClientPageRendererRequests = createBrowserClientPageRenderer }) let browserFindListenerInstalled = false -/** Registers browser find forwarding once for this preload context. */ export function installBrowserFindListener(): void { if (browserFindListenerInstalled) { return diff --git a/src/preload/renderer-heap-statistics-reader.test.ts b/src/preload/renderer-heap-statistics-reader.test.ts index 892a9e865b7..aaaebf72cc8 100644 --- a/src/preload/renderer-heap-statistics-reader.test.ts +++ b/src/preload/renderer-heap-statistics-reader.test.ts @@ -35,9 +35,6 @@ describe('readRendererHeapStatistics', () => { }) it('keeps the exact V8 read when only the Blink metric throws', () => { - // Why: Blink's number is supplementary. Discarding the V8 read over its - // absence would send callers back to the quantized `performance.memory` - // this reader exists to replace — silently defeating the whole feature. const result = readRendererHeapStatistics( source({ blink: () => { @@ -68,7 +65,6 @@ describe('readRendererHeapStatistics', () => { }) ) ).toBeNull() - // Why: no reason to pay for the auxiliary call once the result is unusable. expect(blink).not.toHaveBeenCalled() }) }) diff --git a/src/preload/renderer-heap-statistics-reader.ts b/src/preload/renderer-heap-statistics-reader.ts index 4d1abecd848..aa578e8ff46 100644 --- a/src/preload/renderer-heap-statistics-reader.ts +++ b/src/preload/renderer-heap-statistics-reader.ts @@ -2,11 +2,7 @@ import type { RendererHeapStatistics } from '../shared/renderer-heap-statistics' type HeapStatisticsSource = Pick -/** - * Reads exact V8 heap sizes, which `performance.memory` cannot express: Blink - * quantizes that API and caches it ~20 minutes, so heap growth is invisible to - * it. Available in a sandboxed, context-isolated preload. - */ +// performance.memory quantizes and caches values, hiding heap growth. export function readRendererHeapStatistics( source: HeapStatisticsSource = process ): RendererHeapStatistics | null { @@ -14,14 +10,13 @@ export function readRendererHeapStatistics( try { heap = source.getHeapStatistics() } catch { - // Why: diagnostics must never break the renderer if Electron drops an API. + // Diagnostics must tolerate missing Electron APIs. return null } let blinkAllocatedKB: number | undefined try { - // Why a separate try: Blink's number is supplementary. Losing it must not - // discard the exact V8 read and send callers back to the quantized metric. + // A failed supplementary Blink read must not discard the V8 measurements. blinkAllocatedKB = source.getBlinkMemoryInfo().allocated } catch { blinkAllocatedKB = undefined diff --git a/src/preload/renderer-process-memory-reader.test.ts b/src/preload/renderer-process-memory-reader.test.ts index 759ebbfd53b..d7ab0efbd5c 100644 --- a/src/preload/renderer-process-memory-reader.test.ts +++ b/src/preload/renderer-process-memory-reader.test.ts @@ -1,8 +1,7 @@ import { describe, expect, it } from 'vitest' import { readRendererProcessMemory } from './renderer-process-memory-reader' -// Why the partial type: Electron types `residentSet` as required, but Chromium -// omits it on macOS — the reader's optional handling exists for exactly that. +// Electron requires residentSet in its types, but Chromium omits it on macOS. const source = ( getProcessMemoryInfo: () => Promise> ): Parameters[0] => @@ -32,8 +31,6 @@ describe('readRendererProcessMemory', () => { }) it('returns null for a non-finite private size', async () => { - // Why: a NaN would propagate into breadcrumb megabytes and read as a real - // footprint of zero, which is worse than reporting nothing. await expect( readRendererProcessMemory(source(async () => ({ private: Number.NaN, shared: 0 }))) ).resolves.toBeNull() diff --git a/src/preload/renderer-process-memory-reader.ts b/src/preload/renderer-process-memory-reader.ts index fd46b97248e..2e501b3e740 100644 --- a/src/preload/renderer-process-memory-reader.ts +++ b/src/preload/renderer-process-memory-reader.ts @@ -2,11 +2,6 @@ import type { RendererProcessMemory } from '../shared/renderer-process-memory' type ProcessMemorySource = Pick -/** - * Reads this renderer's OS-level footprint. Available in a sandboxed, - * context-isolated preload; resolves null when the runtime withholds it so a - * dropped Electron API can never break renderer diagnostics. - */ export async function readRendererProcessMemory( source: ProcessMemorySource = process ): Promise { @@ -17,7 +12,7 @@ export async function readRendererProcessMemory( } return { privateKB: info.private, - // Why optional: Chromium reports no resident set on macOS. + // Chromium omits the resident set on macOS. ...(isFiniteKilobytes(info.residentSet) ? { residentKB: info.residentSet } : {}) } } catch { diff --git a/src/preload/renderer-restart-wiring.test.ts b/src/preload/renderer-restart-wiring.test.ts index ba97195a5f5..9ea0dde962f 100644 --- a/src/preload/renderer-restart-wiring.test.ts +++ b/src/preload/renderer-restart-wiring.test.ts @@ -130,7 +130,7 @@ describe('renderer restart wiring', () => { eventTarget.addEventListener(ORCA_RENDERER_UNLOAD_PREVENTED_EVENT, unloadPrevented) eventTarget.addEventListener(ORCA_APP_RESTART_ABORTED_EVENT, restartAborted) ipcRenderer.emit('updater:status', {}, { state: 'error', message: 'install failed' }) - // Why: main abandons an install without any status when its verdict outlived the cycle. + // Main can abandon an install without emitting a status. ipcRenderer.emit('updater:quitAndInstallAborted') ipcRenderer.emit('window:unload-prevented') diff --git a/src/preload/renderer-restart-wiring.ts b/src/preload/renderer-restart-wiring.ts index 38ea1882b9f..67b14d33c71 100644 --- a/src/preload/renderer-restart-wiring.ts +++ b/src/preload/renderer-restart-wiring.ts @@ -32,7 +32,7 @@ export function registerRendererRestartIpcRelays( ipcRenderer.on('updater:status', (_event, status: UpdateStatus) => { relay.handleStatus(status) }) - // Why: main abandons some installs without an error status, and only this tells the renderer. + // Main can abandon an install without emitting an error status. ipcRenderer.on('updater:quitAndInstallAborted', () => { relay.abort() }) diff --git a/src/preload/runtime-environment-subscriptions.test.ts b/src/preload/runtime-environment-subscriptions.test.ts index 585b0f75fa9..dfb847aea40 100644 --- a/src/preload/runtime-environment-subscriptions.test.ts +++ b/src/preload/runtime-environment-subscriptions.test.ts @@ -49,8 +49,6 @@ function createIpc() { } function dispatch(ipc: ReturnType, event: SubscriptionEvent): void { - // A single shared channel listener is registered for the ipc instance; route - // through it the same way the real ipcRenderer would deliver the frame. ipc.emitSubscriptionEvent(event) } @@ -125,8 +123,6 @@ describe('subscribeRuntimeEnvironmentFromPreload', () => { ) expect(ipc.listenerCount()).toBe(0) - // After unsubscribe, frames for the released id must no longer reach the - // consumer (the dispatcher dropped its closure). onResponse.mockClear() dispatch(ipc, { subscriptionId: 'sub-1', @@ -160,7 +156,6 @@ describe('subscribeRuntimeEnvironmentFromPreload', () => { ) ) - // O(1) attached listeners regardless of subscription count - the leak guard. expect(ipc.on).toHaveBeenCalledTimes(1) expect(ipc.removeListener).not.toHaveBeenCalled() expect(handles).toHaveLength(25) @@ -205,9 +200,6 @@ describe('subscribeRuntimeEnvironmentFromPreload', () => { () => 'sub-err' ) - // Error frames are non-terminal: shared-control subscriptions survive - // reconnects, so repeated errors must NOT detach the dispatcher and must keep - // delivering to the live consumer rather than leaking a zombie listener. for (let i = 0; i < 50; i++) { dispatch(ipc, { subscriptionId: 'sub-err', @@ -220,8 +212,6 @@ describe('subscribeRuntimeEnvironmentFromPreload', () => { expect(ipc.removeListener).not.toHaveBeenCalled() expect(ipc.listenerCount()).toBe(1) - // The consumer's unsubscribe is the single release path. After it, error - // frames for the same id no longer reach the consumer - no retained closure. cleanup.unsubscribe() expect(ipc.invoke).toHaveBeenCalledWith('runtimeEnvironments:unsubscribe', { subscriptionId: 'sub-err' @@ -261,7 +251,6 @@ describe('subscribeRuntimeEnvironmentFromPreload', () => { expect(ipc.removeListener).toHaveBeenCalledTimes(1) expect(ipc.listenerCount()).toBe(0) - // A rejected subscribe must not leave a routable entry behind. dispatch(ipc, { subscriptionId: 'sub-2', type: 'response', @@ -322,7 +311,6 @@ describe('subscribeRuntimeEnvironmentFromPreload', () => { expect(ipc.removeListener).toHaveBeenCalledTimes(1) expect(ipc.listenerCount()).toBe(0) - // The entry is already gone. A redundant unsubscribe is still safe. onClose.mockClear() cleanup.unsubscribe() dispatch(ipc, { subscriptionId: 'sub-closed', type: 'close' }) diff --git a/src/preload/runtime-environment-subscriptions.ts b/src/preload/runtime-environment-subscriptions.ts index 23cb67c9af5..d0d83110f16 100644 --- a/src/preload/runtime-environment-subscriptions.ts +++ b/src/preload/runtime-environment-subscriptions.ts @@ -43,11 +43,7 @@ type RuntimeEnvironmentSubscriptionIpc = { const SUBSCRIPTION_EVENT_CHANNEL = 'runtimeEnvironments:subscriptionEvent' -// Why: each subscribe() previously attached its own channel listener that the -// 'error' branch never detached, so reconnecting shared-control subscriptions -// leaked listener closures that pinned renderer state. One active dispatcher per -// ipc instance keeps listener retention O(1) while per-subscription state lives -// only in this map. +// Share one IPC listener so reconnects cannot accumulate listeners retaining renderer state. type RuntimeEnvironmentSubscriptionDispatcher = { callbacks: Map listener: (event: unknown, payload: RuntimeEnvironmentSubscriptionEvent) => void @@ -99,13 +95,10 @@ function getOrCreateDispatcher( } else if (event.type === 'binary') { subscriptionCallbacks.onBinary?.(event.bytes) } else if (event.type === 'error') { - // Why: errors are non-terminal for shared-control subscriptions (they - // survive reconnects), so the entry stays mapped until the consumer - // unsubscribes. + // Shared-control subscriptions survive errors and reconnects. subscriptionCallbacks.onError?.({ code: event.code, message: event.message }) } else { - // Why: close is terminal; release before the callback so a throwing or - // re-entrant onClose cannot keep renderer state mapped. + // Release first so a throwing or reentrant callback cannot retain renderer state. callbacks.delete(event.subscriptionId) releaseIdleDispatcher(ipc, callbacks, listener) subscriptionCallbacks.onClose?.() @@ -132,8 +125,7 @@ export async function subscribeRuntimeEnvironmentFromPreload( createSubscriptionId = createRuntimeEnvironmentSubscriptionId ): Promise { const subscriptionId = args.subscriptionId ?? createSubscriptionId() - // Why: streaming RPCs can emit their first frame before ipcMain.handle() - // resolves, so the dispatcher must be routing this id before invoking. + // Route before invoking: streaming RPCs can emit frames before the subscribe reply. const dispatcher = getOrCreateDispatcher(ipc) if (dispatcher.callbacks.has(subscriptionId)) { throw new Error('Runtime environment subscription id already exists') diff --git a/src/preload/updater-package-recovery.test.ts b/src/preload/updater-package-recovery.test.ts index 15f3576de77..fb58791e9cc 100644 --- a/src/preload/updater-package-recovery.test.ts +++ b/src/preload/updater-package-recovery.test.ts @@ -68,7 +68,6 @@ describe('native preload linux package recovery methods', () => { packageFileName: 'orca.deb' }) - // Why: the renderer must never reach a generic shell/path channel for this cache artifact. expect(invoke.mock.calls).toEqual([['updater:getLinuxPackageInstallInstructions']]) })