diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc index 2077fe4a6fe..d7e19757b11 100644 --- a/config/reliability-gates.jsonc +++ b/config/reliability-gates.jsonc @@ -6396,7 +6396,7 @@ "invariant": "Reconnect, replay, or lifecycle observations from a viewer that negotiated explicit close intent must never kill a live PTY. A capable reasonless close must keep and republish; a legacy paired viewer must retain current-main behavior because its intentional close and cleanup echo are wire-identical. Lifecycle close requires the exact observed publication, terminal, environment, and authoritative liveness, never signals a process, and leaves renderer-owned or partial-split retirement to its owner. Legacy daemon hello and warm reattachment remain non-destructive.", "oracle": "Audit4362 intentionally deletes the imported stale-waiter retry and manually assembled OSC9999 mobile-republish cases, plus the mocked missing-worktree cleanup suite (4 authored / 5 finite cases in three suites). Lost alarms include repeated unread worker_done pointers, working-to-waiting mobile status publication, missing-worktree filtering, and scoped daemon shutdown with unrelated duplicate identities. No replacement coverage or new platform proof is claimed. Audit3881 intentionally removes the entire legacy E2EE channel and mobile socket-wiring test suites and the v2 additive runtime-capability refusal callback, without equivalent replacement. Those deleted suites leave current selectors and that v2 assertion alias is retired. Retained v2 replay/queue-counter cases do not establish the removed capability refusal. Reduced test bytes/selectors have no fresh execution in this static packet; independent dated daemon E2E receipts retain their complete original scope. Historical prior account (preserved verbatim): Audit3832 deliberately retires76 authored/79 finite cases:75 runtime compatibility cases/78 finite cases across14 fragments, plus one localization extractor default-flag case. Three whole runtime fragments are deleted;27 authored/30 finite cases remain across the reviewed sources. This gate retains only its own selected scope; no equivalent replacement or fresh runtime/native/remote evidence is claimed. Runtime component A: Audit3828 composes3822 with independent3824: deliberately retires49 authored/52 finite cases from seven compatibility fragments, leaving15 authored/18 finite cases and deleting two entire fragments. Accepted losses: positive folder-worker recovery/materialization and reveal deadline; persisted-key normalization and legacy split/group/focus projection; fixed stale CAS refusal; occupied/alias/restored/preallocated terminal-handle variants; fixed OpenCode/Cursor/Claude/Codex/Antigravity classification, readiness, title and management examples; direct private-map browser authority projections; browser-focus and OMP title projection; already-aborted claim cleanup. Additional3824 loss: src/main/runtime/orca-runtime-tests/terminal-handles-and-agent-status-part-02.spec.ts :: does not poll a wrapper foreground for a speculative CLI prompt send :: Speculative retryForegroundWrappers:false check must return false on a wrapper after one foreground read, without polling the supplied later codex response. These real bounded alarms are deliberately retired for low marginal value. Retained callbacks are unchanged and provide only their own bounded scope, not equivalent replacement. Historical receipts do not validate reduced callbacks. No fresh runtime/native/SSH/WSL/phone/browser evidence or full transitive closure is claimed. Runtime component B: Audit3834 deliberately retires26 authored/26 finite cases from seven fresh compatibility fragments, leaving10/10 and deleting the one-case saved-binding reattachment fragment. Original position58 is excluded: its existing substantive3578 KEEP7 review remains historical, with no fresh credit. Accepted losses: fixed hook/provider-session identities and stale metadata refusal; decorative/pre-title foreground ordering variants; saved-binding surface reattachment; saved-row exit ghost removal and silent activation selection; unsupported headless wake; positive pending materialization/group projections; per-caller navigation selection; positive SSH hydration/read partition; laptop mobile publication/buffer and background/pending/status projections; abnormal/unregistered SSH grace, normal-exit refusal, persisted SSH hydration, positive serve reattachment, pending-agent launch arguments and direct seeded running-launch admission guard. These are real bounded alarms deliberately retired for low marginal value. Retained cases preserve their own distinct deferred foreground coalescing, usable handle continuity, stale inventory refresh, concurrent browser snapshot preservation, renderer graph fencing, caller dedup isolation, SSH partition writes, runtime split lifetime, independent relay-ready publication, lease admission/state/expiry. The direct running-launch no-spawn guard alarm is deliberately retired; no remaining owning-launch refusal coverage is claimed. Historical runs do not validate reduced callbacks. No equivalent replacement, runtime/native/SSH/WSL/phone/browser result or full transitive closure is claimed. Additional extractor loss: config/scripts/localization/source-extraction/audit-localization-native-dialogs.test.mjs :: does not change the existing renderer scan by default :: Default options must omit the five native-only fields in this supplied snippet. No equivalent replacement is claimed. Historical prior account (preserved verbatim): Audit3814 deliberately retires60 authored/60 finite cases:53runtime compatibility cases,4native XCTest methods and3Python clipboard methods, including the entire StableElementIndexes suite. Clipboard cuts retire the one-over-cap sample, incoming-offer destruction trace and sequential20-copy replay; actual wire, FD/pipe, startup and Xvfb/GTK boundaries remain without equivalent replacement claims. Accepted losses include narrow terminal-send payload/provider projections, legacy and direct no-op/error permutations, timing/work-count examples, private state/title/activity projections and fixture-driven readiness examples, individually enumerated below. These include real bounded production alarms consciously retired for marginal value; retained failed writes, duplicate submission, stale capture, transcript/ring and allocation fences are not equivalent replacements. No fresh native/remote/browser execution or complete transitive closure is claimed. Earlier dated receipts and raw selectors remain historical accounts of prior callback sets. Audit3806 deliberately retires40 authored/40 finite runtime compatibility cases, including the terminal-side-effect-facts-part03 headless-snapshots-part02 and agent-status-and-waits-part03 fragments, plus20 scalar Swift precondition sites. Lost runtime alarms include status/title/attention projection examples, simple renderer/headless frame restoration and status waiting outcomes detailed in the accepted-loss ledger. Swift cuts retire duplicate generation-map/schema/navigation/bridge and notification-wrapper assertions; no standalone native program is deleted. These include real bounded production alarms consciously retired for marginal value. Retained races, pending writes/reflow, namespace and waiter ownership are not equivalent replacements. No fresh native/remote/browser execution or full transitive closure is claimed. Earlier dated receipts and raw selectors remain historical accounts of prior callback sets. Audit3798 deliberately retires21 authored/24 finite compatibility cases, including the entire SSH-worktree-lifecycle and repository-project-operations fragments. Accepted losses include navigation-only settings acknowledgement, browser session cleanup and host preservation projections, window positive/policy-state examples, terminal recovery/reload and no-incarnation remint examples, terminal listing compatibility/malformed IDs, directory browse/sort/Windows path smoke, SSH create refusal/manual lineage, recursive parent-folder creation and fork/origin/avatar/icon projections. Real bounded production alarms are consciously retired for marginal value; retained authority races, cleanup/clone ownership, pending waiters, nested-folder and scan invalidation cases are not equivalent replacements. No fresh native/remote/browser execution or full transitive closure is claimed. Earlier dated receipts and raw selectors remain historical accounts of prior callback sets. Audit3774 (independent peer expansion of3773): deliberately retire7authored/13potential expanded registrations across4whole suites: standalone truncated8-byte E2EE guard; open/empty readiness null fast-path; capability parser acceptance/atomic malformed-array bounds; phone/delegated-parent/desktop/in-process creator provenance projections. These are real guard/policy alarms accepted as low marginal value, not tautologies. No equivalent replacement, authenticated-refusal, observer delivery, persisted visibility, synchronous scheduling or fresh execution is claimed. Prior dated receipts retain their exact original scopes and do not validate the changed/reduced current selector. Independent daemon E2E receipts remain scoped to their own unchanged commands. Historical prior account (preserved verbatim): Audit3403 composes root-adopted3393/3394,3400/3401 and3398/3399: intentionally retires167 authored registrations/196 potential expanded cases across93 whole suites without equivalent replacement or fresh execution. Retained65 registrations/79 potential cases include one conditional missing-input failure sentinel; potential counts are not executions. Historical notes and complete dated receipts retain their exact original scopes. The retained runtime registration driver loses three complete imported fragments: changed-working-label title facts and suppressed-frame tracked snapshots; refusing SSH GitLab MR-base lookup before local Git/glab calls; and missing folder-workspace path creation/update refusal before spawn/store mutation. These alarms are intentionally lost. Other imported fragments and separately rooted dated receipts are unchanged; they are not equivalent replacement coverage. Audit2133 current-parent preparation: Current reduced sources/selectors intentionally retire the alarms listed in knownGaps; prior dated runs and replacement claims do not validate the changed set. Historical prior account (preserved verbatim): Audit2095 current-parent preparation2126: Current reduced sources/selectors intentionally retire the alarms listed in knownGaps; prior dated runs and replacement claims do not validate the changed set. Historical prior account (preserved verbatim): Audit2090 (sources2088/2089): Current reduced suites intentionally retire the alarms listed in knownGaps; prior dated execution and replacement claims do not validate changed source bytes or selectors. Historical prior account (preserved verbatim): Audit2086 (sources2082/2083): Current reduced suites intentionally retire the alarms listed in knownGaps; prior dated execution and replacement claims do not validate changed source bytes or selectors. Historical prior account (preserved verbatim): Audit2076 (sources2073/2074): Intentionally retire these low-value alarms without replacement: src/main/runtime/orca-runtime-tests/terminal-handles-part-02.spec.ts: recovers a moved SSH pane through the tab it now sits in, not the one its lease froze; reports a plain expired orphan; does not report a pane whose only recent lease was superseded; does not report a pane whose only recent lease had its relay id recycled; picks the eligible orphan over a superseded predecessor that matches first; collects the same tabs the per-tab reader reports, in one sweep of the leases; reports no candidate when no lease names any of the worktree tabs. src/main/runtime/orca-runtime-tests/runtime-availability.spec.ts: starts unavailable with no authoritative window; reports the configured Windows terminal shell on status; reports floating workspace availability from settings on status; polls floating tabs with targeted PTY liveness and no repo/provider inventory; hydrates persisted tabs when the store cannot report repos; advertises browser screencast only when a renderer window is available; routes mobile Codex reset consumption through the account mutation coordinator; maps a definite pre-provider rejection into an authoritative current snapshot. Existing unrelated evidenceRuns retain their original scope; unchanged dated receipt objects do not validate changed source bytes or reduced selectors. No fresh gate execution or historical import-closure equivalence is claimed. Frozen current literal-import graph reaches these changed test bytes; unresolved local and computed edges remain debt, and current reachability is not historical execution or equivalent replacement evidence. Historical prior account (preserved verbatim): Audit1983: Delete the reasonless-close scalar suite and optional-capability socket forwarding alias. Delete the mocked close-attribution topology field-inventory suite and its aliases/selectors; preserve independent dated receipts. Changed-source prior results do not validate reduced-source bytes. No fresh execution, equivalent replacement, red/green, measured budget, soak, provider/PTY, rendered, live remote/mobile or cross-platform result is claimed. Historical prior account (preserved verbatim): Audit1959 (sources 1957:11, 1957:35, 1957:36): The fixture-supplied repository roundtrip, isolated capability metadata readback, parser/default-timer/size-threshold/internal failure-counter examples and standalone handshake-only replay example are removed. Source11 retains real encrypted multi-client event ordering, reconnect snapshot and multiplex delivery under synthetic runtime state, and does not establish the broad handshake-to-reasonless-close refusal alias; retire that whole assertion object. Source36 capability metadata readback alias is retired. Source35 retains the actual v2 runtime-only metadata/downgrade refusal callback and captured mutating-trace fresh-nonce rejection; its mapped mobile-v2 refusal alias remains within modeled credential lookup scope. Both independent daemon E2E dated receipts remain byte-exact with their original commands and results. No historical passed receipt is narrowed or transferred to changed source bytes. No fresh execution, equivalent replacement, physical provider/PTY, live remote/mobile, rendered, cross-platform, soak or measured-budget result is claimed by this metadata packet. Historical prior account (preserved verbatim): Audit1939 (sources1934/1935): Retain actual parked exit/disposal/cancel/leaf progression using injected exit and close adapters. The retained last-watcher case checks exact lifecyclePtyId, but no retained callback establishes the whole existing replacement-or-sibling-incarnation alias. Retire that broad assertion object rather than transfer partial support. Capability admission, static fields and duplicate routing examples are intentionally lost; unchanged daemon E2E receipts remain scoped to their own commands. Preserve meaningful remaining selectors/assertions and unchanged dated receipts within their original scope. Reduced selectors have no fresh gate execution evidence in this metadata packet. No equivalent replacement, physical watcher/PTY/provider, live SSH/remote/mobile, rendered, cross-platform, soak or measured-budget result is claimed. Historical prior account (preserved verbatim): Existing exact unchanged-selector receipts remain the only current execution evidence. Changed source selectors have no fresh execution result. Historical prior-source oracle account: Start isolated v25 and v26 daemon generations with one capable-viewer PTY and one legacy-viewer PTY per generation in four target worktrees plus an unaddressed control PTY in a fifth worktree. Route them through the production desktop scanner, runtime, RPC dispatcher, renderer-close relay, and daemon router. First issue sequential reasonless closes from an authenticated capable connection and require refusal, snapshot republish, zero shutdown calls, exact process survival, and post-close I/O. Then issue the byte-identical requests without the negotiated capability and require current-main behavior: two ordered immediate shutdowns, session-killed events, and exact root/descendant death, while capable and control PTYs survive. An observer lists all targets before, between, and after while issuing zero closes. Unit contracts also require in-process reasonless refusal, legacy runtime/mobile compatibility, explicit user closes, encrypted client-auth advertisement, and old-server lifecycle calls never to fall back.", "commands": [ - "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/construction/orca-runtime.test.ts src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts src/shared/remote-runtime/remote-runtime-client.test.ts src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts src/cli/runtime/websocket-transport.test.ts src/renderer/src/web/web-runtime-client.test.ts src/renderer/src/components/terminal/terminal-tab-actions.test.ts src/renderer/src/components/terminal/terminal-close-incarnation.test.ts src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts", + "pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/construction/orca-runtime.test.ts src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts src/shared/remote-runtime/remote-runtime-client.test.ts src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts src/cli/runtime/websocket-transport.test.ts src/renderer/src/web/web-runtime-client.test.ts src/renderer/src/components/terminal/terminal-close-incarnation.test.ts src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts", "pnpm exec playwright test tests/e2e/daemon-generation-reconnect-safety.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1", "pnpm exec playwright test tests/e2e/daemon-generation-legacy-close-safety.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1" ], @@ -6407,7 +6407,6 @@ "src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts", "src/cli/runtime/websocket-transport.test.ts", "src/renderer/src/web/web-runtime-client.test.ts", - "src/renderer/src/components/terminal/terminal-tab-actions.test.ts", "src/renderer/src/components/terminal/terminal-close-incarnation.test.ts", "src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts", "tests/e2e/daemon-generation-reconnect-safety.spec.ts", @@ -6534,7 +6533,8 @@ "Audit3774 historical original active selector/assertion arrays, preserved verbatim; no replacement coverage claim.\ncommands:\n[\n \"pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/construction/orca-runtime.test.ts src/main/runtime/rpc/mobile/e2ee/e2ee-channel.test.ts src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts src/main/runtime/rpc/mobile/mobile-socket-wiring.test.ts src/main/runtime/rpc/callers/runtime-client-capabilities.test.ts src/shared/remote-runtime/remote-runtime-client.test.ts src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts src/cli/runtime/websocket-transport.test.ts src/renderer/src/web/web-runtime-client.test.ts src/renderer/src/components/terminal/terminal-tab-actions.test.ts src/renderer/src/components/terminal/terminal-close-incarnation.test.ts src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts\",\n \"pnpm exec playwright test tests/e2e/daemon-generation-reconnect-safety.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1\",\n \"pnpm exec playwright test tests/e2e/daemon-generation-legacy-close-safety.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1\"\n ]\ntestFiles:\n[\n \"src/main/runtime/construction/orca-runtime.test.ts\",\n \"src/main/runtime/rpc/mobile/e2ee/e2ee-channel.test.ts\",\n \"src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts\",\n \"src/main/runtime/rpc/mobile/mobile-socket-wiring.test.ts\",\n \"src/main/runtime/rpc/callers/runtime-client-capabilities.test.ts\",\n \"src/shared/remote-runtime/remote-runtime-client.test.ts\",\n \"src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts\",\n \"src/cli/runtime/websocket-transport.test.ts\",\n \"src/renderer/src/web/web-runtime-client.test.ts\",\n \"src/renderer/src/components/terminal/terminal-tab-actions.test.ts\",\n \"src/renderer/src/components/terminal/terminal-close-incarnation.test.ts\",\n \"src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts\",\n \"tests/e2e/daemon-generation-reconnect-safety.spec.ts\",\n \"tests/e2e/daemon-generation-legacy-close-safety.spec.ts\"\n ]\nassertionRefs:\n[\n {\n \"file\": \"tests/e2e/daemon-generation-legacy-close-safety.spec.ts\",\n \"assertions\": [\n \"one identified capable viewer and one legacy viewer issue byte-identical sequential reasonless closes while a third viewer lists every target before, between, and after but issues zero closes\",\n \"capable v25/v26 PTY root/descendant incarnations in separate worktrees survive, answer post-close input, and produce zero shutdown calls and zero daemon session-killed events\",\n \"legacy v25/v26 PTY root/descendant incarnations die through ordered immediate shutdown calls with one daemon session-killed event each, matching current-main behavior\",\n \"an unaddressed fifth-worktree PTY root and descendant survive with zero kill events, excluding global fanout\",\n \"the JSON reconstruction records request order, negotiated capabilities, viewer connection, worktree/tab/PTY ids, daemon PID/protocol, call site, and exact before/after process liveness\"\n ]\n },\n {\n \"file\": \"tests/e2e/daemon-generation-reconnect-safety.spec.ts\",\n \"assertions\": [\n \"the production scanner discovers v21/v22/v23/v24/v25 from v26 and every generation accepts repeated client hellos while every exact daemon, PTY-root, and descendant incarnation remains alive\",\n \"desktop and two remote profiles repeat lifecycle closes before and after client relaunch with zero session-killed events\",\n \"shutdown-dispose-failed drops named-pipe authority within the deadline and exact fixture cleanup leaves no process tree\"\n ]\n },\n {\n \"file\": \"src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts\",\n \"assertions\": [\"mobile E2EE v2 continues to reject additive runtime capability metadata\"]\n },\n {\n \"file\": \"src/main/runtime/rpc/callers/runtime-client-capabilities.test.ts\",\n \"assertions\": [\n \"the authenticated capability parser accepts only bounded string arrays and rejects malformed or oversized input\"\n ]\n },\n {\n \"file\": \"src/shared/remote-runtime/remote-runtime-client.test.ts\",\n \"assertions\": [\n \"one-shot and subscription runtime clients remain compatible while sending encrypted client authentication\"\n ]\n }\n ]", "Audit3832 deliberately retires76 authored/79 finite cases:75 runtime compatibility cases/78 finite cases across14 fragments, plus one localization extractor default-flag case. Three whole runtime fragments are deleted;27 authored/30 finite cases remain across the reviewed sources. This gate retains only its own selected scope; no equivalent replacement or fresh runtime/native/remote evidence is claimed. Runtime component A: Audit3828 composes3822 with independent3824: deliberately retires49 authored/52 finite cases from seven compatibility fragments, leaving15 authored/18 finite cases and deleting two entire fragments. Accepted losses: positive folder-worker recovery/materialization and reveal deadline; persisted-key normalization and legacy split/group/focus projection; fixed stale CAS refusal; occupied/alias/restored/preallocated terminal-handle variants; fixed OpenCode/Cursor/Claude/Codex/Antigravity classification, readiness, title and management examples; direct private-map browser authority projections; browser-focus and OMP title projection; already-aborted claim cleanup. Additional3824 loss: src/main/runtime/orca-runtime-tests/terminal-handles-and-agent-status-part-02.spec.ts :: does not poll a wrapper foreground for a speculative CLI prompt send :: Speculative retryForegroundWrappers:false check must return false on a wrapper after one foreground read, without polling the supplied later codex response. These real bounded alarms are deliberately retired for low marginal value. Retained callbacks are unchanged and provide only their own bounded scope, not equivalent replacement. Historical receipts do not validate reduced callbacks. No fresh runtime/native/SSH/WSL/phone/browser evidence or full transitive closure is claimed. Runtime component B: Audit3834 deliberately retires26 authored/26 finite cases from seven fresh compatibility fragments, leaving10/10 and deleting the one-case saved-binding reattachment fragment. Original position58 is excluded: its existing substantive3578 KEEP7 review remains historical, with no fresh credit. Accepted losses: fixed hook/provider-session identities and stale metadata refusal; decorative/pre-title foreground ordering variants; saved-binding surface reattachment; saved-row exit ghost removal and silent activation selection; unsupported headless wake; positive pending materialization/group projections; per-caller navigation selection; positive SSH hydration/read partition; laptop mobile publication/buffer and background/pending/status projections; abnormal/unregistered SSH grace, normal-exit refusal, persisted SSH hydration, positive serve reattachment, pending-agent launch arguments and direct seeded running-launch admission guard. These are real bounded alarms deliberately retired for low marginal value. Retained cases preserve their own distinct deferred foreground coalescing, usable handle continuity, stale inventory refresh, concurrent browser snapshot preservation, renderer graph fencing, caller dedup isolation, SSH partition writes, runtime split lifetime, independent relay-ready publication, lease admission/state/expiry. The direct running-launch no-spawn guard alarm is deliberately retired; no remaining owning-launch refusal coverage is claimed. Historical runs do not validate reduced callbacks. No equivalent replacement, runtime/native/SSH/WSL/phone/browser result or full transitive closure is claimed. Additional extractor loss: config/scripts/localization/source-extraction/audit-localization-native-dialogs.test.mjs :: does not change the existing renderer scan by default :: Default options must omit the five native-only fields in this supplied snippet. No equivalent replacement is claimed.", "Audit3881 intentionally removes the entire legacy E2EE channel and mobile socket-wiring test suites and the v2 additive runtime-capability refusal callback, without equivalent replacement. Those deleted suites leave current selectors and that v2 assertion alias is retired. Retained v2 replay/queue-counter cases do not establish the removed capability refusal. Reduced test bytes/selectors have no fresh execution in this static packet; independent dated daemon E2E receipts retain their complete original scope.", - "Audit3881 historical original selector/assertion arrays, preserved verbatim; retired entries are not active execution evidence or replacement coverage.\ncommands:\n[\n \"pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/construction/orca-runtime.test.ts src/main/runtime/rpc/mobile/e2ee/e2ee-channel.test.ts src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts src/main/runtime/rpc/mobile/mobile-socket-wiring.test.ts src/shared/remote-runtime/remote-runtime-client.test.ts src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts src/cli/runtime/websocket-transport.test.ts src/renderer/src/web/web-runtime-client.test.ts src/renderer/src/components/terminal/terminal-tab-actions.test.ts src/renderer/src/components/terminal/terminal-close-incarnation.test.ts src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts\",\n \"pnpm exec playwright test tests/e2e/daemon-generation-reconnect-safety.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1\",\n \"pnpm exec playwright test tests/e2e/daemon-generation-legacy-close-safety.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1\"\n ]\ntestFiles:\n[\n \"src/main/runtime/construction/orca-runtime.test.ts\",\n \"src/main/runtime/rpc/mobile/e2ee/e2ee-channel.test.ts\",\n \"src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts\",\n \"src/main/runtime/rpc/mobile/mobile-socket-wiring.test.ts\",\n \"src/shared/remote-runtime/remote-runtime-client.test.ts\",\n \"src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts\",\n \"src/cli/runtime/websocket-transport.test.ts\",\n \"src/renderer/src/web/web-runtime-client.test.ts\",\n \"src/renderer/src/components/terminal/terminal-tab-actions.test.ts\",\n \"src/renderer/src/components/terminal/terminal-close-incarnation.test.ts\",\n \"src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts\",\n \"tests/e2e/daemon-generation-reconnect-safety.spec.ts\",\n \"tests/e2e/daemon-generation-legacy-close-safety.spec.ts\"\n ]\nassertionRefs:\n[\n {\n \"file\": \"tests/e2e/daemon-generation-legacy-close-safety.spec.ts\",\n \"assertions\": [\n \"one identified capable viewer and one legacy viewer issue byte-identical sequential reasonless closes while a third viewer lists every target before, between, and after but issues zero closes\",\n \"capable v25/v26 PTY root/descendant incarnations in separate worktrees survive, answer post-close input, and produce zero shutdown calls and zero daemon session-killed events\",\n \"legacy v25/v26 PTY root/descendant incarnations die through ordered immediate shutdown calls with one daemon session-killed event each, matching current-main behavior\",\n \"an unaddressed fifth-worktree PTY root and descendant survive with zero kill events, excluding global fanout\",\n \"the JSON reconstruction records request order, negotiated capabilities, viewer connection, worktree/tab/PTY ids, daemon PID/protocol, call site, and exact before/after process liveness\"\n ]\n },\n {\n \"file\": \"tests/e2e/daemon-generation-reconnect-safety.spec.ts\",\n \"assertions\": [\n \"the production scanner discovers v21/v22/v23/v24/v25 from v26 and every generation accepts repeated client hellos while every exact daemon, PTY-root, and descendant incarnation remains alive\",\n \"desktop and two remote profiles repeat lifecycle closes before and after client relaunch with zero session-killed events\",\n \"shutdown-dispose-failed drops named-pipe authority within the deadline and exact fixture cleanup leaves no process tree\"\n ]\n },\n {\n \"file\": \"src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts\",\n \"assertions\": [\"mobile E2EE v2 continues to reject additive runtime capability metadata\"]\n },\n {\n \"file\": \"src/shared/remote-runtime/remote-runtime-client.test.ts\",\n \"assertions\": [\n \"one-shot and subscription runtime clients remain compatible while sending encrypted client authentication\"\n ]\n }\n ]" + "Audit3881 historical original selector/assertion arrays, preserved verbatim; retired entries are not active execution evidence or replacement coverage.\ncommands:\n[\n \"pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/construction/orca-runtime.test.ts src/main/runtime/rpc/mobile/e2ee/e2ee-channel.test.ts src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts src/main/runtime/rpc/mobile/mobile-socket-wiring.test.ts src/shared/remote-runtime/remote-runtime-client.test.ts src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts src/cli/runtime/websocket-transport.test.ts src/renderer/src/web/web-runtime-client.test.ts src/renderer/src/components/terminal/terminal-tab-actions.test.ts src/renderer/src/components/terminal/terminal-close-incarnation.test.ts src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts\",\n \"pnpm exec playwright test tests/e2e/daemon-generation-reconnect-safety.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1\",\n \"pnpm exec playwright test tests/e2e/daemon-generation-legacy-close-safety.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1\"\n ]\ntestFiles:\n[\n \"src/main/runtime/construction/orca-runtime.test.ts\",\n \"src/main/runtime/rpc/mobile/e2ee/e2ee-channel.test.ts\",\n \"src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts\",\n \"src/main/runtime/rpc/mobile/mobile-socket-wiring.test.ts\",\n \"src/shared/remote-runtime/remote-runtime-client.test.ts\",\n \"src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts\",\n \"src/cli/runtime/websocket-transport.test.ts\",\n \"src/renderer/src/web/web-runtime-client.test.ts\",\n \"src/renderer/src/components/terminal/terminal-tab-actions.test.ts\",\n \"src/renderer/src/components/terminal/terminal-close-incarnation.test.ts\",\n \"src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts\",\n \"tests/e2e/daemon-generation-reconnect-safety.spec.ts\",\n \"tests/e2e/daemon-generation-legacy-close-safety.spec.ts\"\n ]\nassertionRefs:\n[\n {\n \"file\": \"tests/e2e/daemon-generation-legacy-close-safety.spec.ts\",\n \"assertions\": [\n \"one identified capable viewer and one legacy viewer issue byte-identical sequential reasonless closes while a third viewer lists every target before, between, and after but issues zero closes\",\n \"capable v25/v26 PTY root/descendant incarnations in separate worktrees survive, answer post-close input, and produce zero shutdown calls and zero daemon session-killed events\",\n \"legacy v25/v26 PTY root/descendant incarnations die through ordered immediate shutdown calls with one daemon session-killed event each, matching current-main behavior\",\n \"an unaddressed fifth-worktree PTY root and descendant survive with zero kill events, excluding global fanout\",\n \"the JSON reconstruction records request order, negotiated capabilities, viewer connection, worktree/tab/PTY ids, daemon PID/protocol, call site, and exact before/after process liveness\"\n ]\n },\n {\n \"file\": \"tests/e2e/daemon-generation-reconnect-safety.spec.ts\",\n \"assertions\": [\n \"the production scanner discovers v21/v22/v23/v24/v25 from v26 and every generation accepts repeated client hellos while every exact daemon, PTY-root, and descendant incarnation remains alive\",\n \"desktop and two remote profiles repeat lifecycle closes before and after client relaunch with zero session-killed events\",\n \"shutdown-dispose-failed drops named-pipe authority within the deadline and exact fixture cleanup leaves no process tree\"\n ]\n },\n {\n \"file\": \"src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts\",\n \"assertions\": [\"mobile E2EE v2 continues to reject additive runtime capability metadata\"]\n },\n {\n \"file\": \"src/shared/remote-runtime/remote-runtime-client.test.ts\",\n \"assertions\": [\n \"one-shot and subscription runtime clients remain compatible while sending encrypted client authentication\"\n ]\n }\n ]", + "Audit4389 retires the entire terminal-tab-actions mock-projection suite (8 authored/10 finite cases). Real local/host mutation, confirmation settlement and transport are mocked; routing/reason/pin/sibling spy alarms intentionally lost, with no replacement or equivalence claim. Historical entries remain archival only. Original active command: pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/construction/orca-runtime.test.ts src/main/runtime/rpc/mobile/e2ee/e2ee-channel-v2.test.ts src/shared/remote-runtime/remote-runtime-client.test.ts src/shared/remote-runtime/control/remote-runtime-shared-control-connection.test.ts src/cli/runtime/websocket-transport.test.ts src/renderer/src/web/web-runtime-client.test.ts src/renderer/src/components/terminal/terminal-tab-actions.test.ts src/renderer/src/components/terminal/terminal-close-incarnation.test.ts src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts" ], "demotionRule": "Keep experimental or quarantine if reconnect emits session-killed for a live canary, an exact root/descendant dies, an old server receives fallback destructive close, cleanup leaks a fixture process/pipe, or the gate flakes without a proven harness defect." }, diff --git a/config/scripts/ci/sharding/ci-shard-timings.json b/config/scripts/ci/sharding/ci-shard-timings.json index 79048338914..161d4562ec7 100644 --- a/config/scripts/ci/sharding/ci-shard-timings.json +++ b/config/scripts/ci/sharding/ci-shard-timings.json @@ -4992,7 +4992,6 @@ "src/renderer/src/components/sidebar/workspace-card/identity/WorktreeTitleInlineRename.editor-lifecycle.test.tsx": 407, "src/renderer/src/components/sidebar/workspace-visibility/dialog/WorktreeVisibilityDialog.test.tsx": 2602, "src/renderer/src/components/sidebar/host-admission/ssh/add-remote-host-ssh-actions.test.ts": 232, - "src/renderer/src/components/sidebar/project-admission/completion/add-repo-skip-finalization.test.ts": 59, "src/renderer/src/components/sidebar/chat-markdown-math-typeset.test.ts": 1336, "src/renderer/src/components/sidebar/workspace-actions/deletion/delete-worktree-always-force-preference.test.tsx": 2175, "src/renderer/src/components/sidebar/workspace-actions/deletion/delete-worktree-dirty-change-counts.test.ts": 258, @@ -5374,7 +5373,6 @@ "src/renderer/src/components/terminal/terminal-close-incarnation.test.ts": 42, "src/renderer/src/components/terminal/terminal-tab-actions-unified-close.test.ts": 1831, "src/renderer/src/components/terminal/terminal-tab-actions-unrouted-close.test.ts": 589, - "src/renderer/src/components/terminal/terminal-tab-actions.test.ts": 626, "src/renderer/src/components/terminal/terminal-tab-close-running-confirm.test.ts": 499, "src/renderer/src/components/terminal/use-terminal-provider-snapshot-capability.test.tsx": 573, "src/renderer/src/components/terminal/window-close-running-work.test.ts": 97, diff --git a/src/renderer/src/components/sidebar/project-admission/completion/add-repo-skip-finalization.test.ts b/src/renderer/src/components/sidebar/project-admission/completion/add-repo-skip-finalization.test.ts deleted file mode 100644 index e85a10ded0c..00000000000 --- a/src/renderer/src/components/sidebar/project-admission/completion/add-repo-skip-finalization.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import type { Worktree } from '../../../../../../shared/worktree/types' -import { - finalizeImportedRepoAfterSkip, - type AddRepoSkipFinalizationState -} from './add-repo-skip-finalization' - -function makeWorktree(overrides: Partial & { id: string; repoId: string }): Worktree { - return { - path: `/tmp/${overrides.id}`, - head: 'abc123', - branch: 'refs/heads/feature', - isBare: false, - isMainWorktree: false, - displayName: overrides.id, - comment: '', - linkedIssue: null, - linkedPR: null, - linkedLinearIssue: null, - linkedGitLabMR: null, - linkedGitLabIssue: null, - isArchived: false, - isUnread: false, - isPinned: false, - sortOrder: 0, - lastActivityAt: 0, - ...overrides - } -} - -function makeState(overrides: Partial): AddRepoSkipFinalizationState { - return { - activeRepoId: null, - filterRepoIds: [], - showActiveOnly: false, - hideDefaultBranchWorkspace: false, - showSleepingWorkspaces: true, - alwaysShowDefaultBranchWorkspace: true, - repos: [], - worktreesByRepo: {}, - setActiveRepo: vi.fn(), - setFilterRepoIds: vi.fn(), - setShowActiveOnly: vi.fn(), - setHideDefaultBranchWorkspace: vi.fn(), - setAlwaysShowDefaultBranchWorkspace: vi.fn(), - ...overrides - } -} - -describe('finalizeImportedRepoAfterSkip', () => { - it('preserves default-branch hiding when importing a folder project with only its root', () => { - const state = makeState({ - hideDefaultBranchWorkspace: true, - repos: [{ id: 'folder-new', kind: 'folder' }], - worktreesByRepo: { - 'folder-new': [ - makeWorktree({ - id: 'folder-new::/notes', - repoId: 'folder-new', - isMainWorktree: true, - head: '', - branch: '' - }) - ] - } - }) - - finalizeImportedRepoAfterSkip(state, 'folder-new') - - expect(state.setHideDefaultBranchWorkspace).not.toHaveBeenCalled() - }) - - it.each([false, true])( - 'ignores archived siblings when revealing a folder root after Skip (root archived: %s)', - (rootArchived) => { - const state = makeState({ - hideDefaultBranchWorkspace: true, - showSleepingWorkspaces: false, - alwaysShowDefaultBranchWorkspace: false, - repos: [{ id: 'folder-new', kind: 'folder' }], - worktreesByRepo: { - 'folder-new': [ - makeWorktree({ - id: 'folder-new::/notes', - repoId: 'folder-new', - isMainWorktree: true, - head: '', - branch: '', - isArchived: rootArchived - }), - makeWorktree({ - id: 'folder-new::/notes::workspace:archived', - repoId: 'folder-new', - head: '', - branch: '', - isArchived: true - }) - ] - } - }) - - finalizeImportedRepoAfterSkip(state, 'folder-new') - - if (rootArchived) { - expect(state.setHideDefaultBranchWorkspace).not.toHaveBeenCalled() - expect(state.setAlwaysShowDefaultBranchWorkspace).not.toHaveBeenCalled() - } else { - expect(state.setHideDefaultBranchWorkspace).not.toHaveBeenCalled() - expect(state.setAlwaysShowDefaultBranchWorkspace).toHaveBeenCalledWith(true) - } - } - ) - - it('re-enables the default-branch exemption when the import would land asleep and hidden', () => { - const state = makeState({ - showSleepingWorkspaces: false, - alwaysShowDefaultBranchWorkspace: false, - worktreesByRepo: { - 'repo-new': [ - makeWorktree({ - id: 'repo-new::/repo/main', - repoId: 'repo-new', - isMainWorktree: true, - branch: 'refs/heads/main' - }) - ] - } - }) - - finalizeImportedRepoAfterSkip(state, 'repo-new') - - expect(state.setAlwaysShowDefaultBranchWorkspace).toHaveBeenCalledWith(true) - }) -}) diff --git a/src/renderer/src/components/terminal/terminal-tab-actions.test.ts b/src/renderer/src/components/terminal/terminal-tab-actions.test.ts deleted file mode 100644 index 098c0bf391a..00000000000 --- a/src/renderer/src/components/terminal/terminal-tab-actions.test.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' - -const { - activateWebRuntimeSessionTabMock, - createBrowserUuidMock, - closeWebRuntimeSessionTabMock, - createWebRuntimeSessionTerminalMock, - getLatestWebSessionTabsPublicationEpochMock, - getStateMock, - isWebRuntimeSessionActiveMock, - isWebTerminalSurfaceTabIdMock, - resolveHostSessionTabIdForWebSessionTabMock, - toHostSessionTabIdMock -} = vi.hoisted(() => ({ - activateWebRuntimeSessionTabMock: vi.fn(), - createBrowserUuidMock: vi.fn(() => 'tab-1'), - closeWebRuntimeSessionTabMock: vi.fn(), - createWebRuntimeSessionTerminalMock: vi.fn(), - getLatestWebSessionTabsPublicationEpochMock: vi.fn(() => 'epoch-1'), - getStateMock: vi.fn(), - isWebRuntimeSessionActiveMock: vi.fn(), - isWebTerminalSurfaceTabIdMock: vi.fn(() => false), - resolveHostSessionTabIdForWebSessionTabMock: vi.fn<() => string | null>(() => null), - toHostSessionTabIdMock: vi.fn((tabId: string) => tabId) -})) - -vi.mock('@/store', () => ({ - useAppStore: { - getState: getStateMock - } -})) - -vi.mock('../../../../shared/non-secure-context-uuid', () => ({ - createNonSecureContextUuid: createBrowserUuidMock -})) - -vi.mock('@/runtime/web-session-tabs-sync/actions/web-runtime-session-tab-lifecycle', () => ({ - activateWebRuntimeSessionTab: activateWebRuntimeSessionTabMock, - closeWebRuntimeSessionTab: closeWebRuntimeSessionTabMock -})) -vi.mock('@/runtime/hosted-terminals/creation/web-runtime-terminal-creation', () => ({ - createWebRuntimeSessionTerminal: createWebRuntimeSessionTerminalMock -})) -vi.mock('@/runtime/web-session-tabs-sync/identity/web-runtime-session-environment', () => ({ - isWebRuntimeSessionActive: isWebRuntimeSessionActiveMock -})) -vi.mock('../../../../shared/workspace-layout/terminal-surface-id', () => ({ - isWebTerminalSurfaceTabId: isWebTerminalSurfaceTabIdMock, - toHostSessionTabId: toHostSessionTabIdMock -})) - -vi.mock('@/runtime/web-session-tabs-sync/tracking-lifecycle', () => ({ - getLatestWebSessionTabsPublicationEpoch: getLatestWebSessionTabsPublicationEpochMock -})) -vi.mock('@/runtime/web-session-tabs-sync/tracking-mappings', () => ({ - resolveHostSessionTabIdForWebSessionTab: resolveHostSessionTabIdForWebSessionTabMock -})) - -import { closeOtherTerminalTabs, closeTerminalTab } from './terminal-tab-actions' -import { terminalOwnerRows } from './terminal-tab-owner-rows.test-fixture' - -describe('closeTerminalTab', () => { - beforeEach(() => { - vi.clearAllMocks() - isWebRuntimeSessionActiveMock.mockReturnValue(false) - resolveHostSessionTabIdForWebSessionTabMock.mockReturnValue(null) - isWebTerminalSurfaceTabIdMock.mockReturnValue(false) - }) - - it('lets the HUB snapshot adjudicate a stream exit', () => { - const closeTab = vi.fn() - isWebRuntimeSessionActiveMock.mockReturnValue(true) - resolveHostSessionTabIdForWebSessionTabMock.mockReturnValue('host-tab-1') - getStateMock.mockReturnValue({ - ...terminalOwnerRows('web-runtime'), - tabsByWorktree: { - 'wt-1': [{ id: 'local-tab-1' }, { id: 'local-tab-2' }] - }, - activeWorktreeId: 'wt-1', - activeTabId: 'local-tab-1', - closeTab, - setActiveTab: vi.fn() - }) - - closeTerminalTab('local-tab-1', { - reason: 'pty-exit', - lifecyclePtyId: 'remote:web-runtime@@term-1' - }) - - expect(closeTab).not.toHaveBeenCalled() - expect(closeWebRuntimeSessionTabMock).not.toHaveBeenCalled() - }) - - it('sends hostCloseReason on the wire without tagging the local close reason', () => { - // Lifecycle close reason must reach host adjudication while local guards still use the original reason. - const closeTab = vi.fn() - isWebRuntimeSessionActiveMock.mockReturnValue(true) - resolveHostSessionTabIdForWebSessionTabMock.mockReturnValue('host-tab-1') - getStateMock.mockReturnValue({ - ...terminalOwnerRows('web-runtime'), - tabsByWorktree: { - 'wt-1': [{ id: 'local-tab-1' }, { id: 'local-tab-2' }] - }, - activeWorktreeId: 'wt-1', - activeTabId: 'local-tab-1', - closeTab, - setActiveTab: vi.fn() - }) - - closeTerminalTab('local-tab-1', { - hostCloseReason: 'pty-exit', - lifecyclePtyId: 'remote:web-runtime@@term-1' - }) - - expect(closeTab).toHaveBeenCalledWith('local-tab-1', { - reason: undefined, - remoteCloseOwnedByHost: true - }) - expect(closeWebRuntimeSessionTabMock).toHaveBeenCalledWith({ - worktreeId: 'wt-1', - tabId: 'host-tab-1', - environmentId: 'web-runtime', - reason: 'pty-exit', - publicationEpoch: 'epoch-1', - terminalHandle: 'term-1' - }) - }) - - it.each([ - ['user', 'user'], - ['requested', 'user'], - ['cleanup', 'cleanup'] - ] as const)( - 'sends a %s close to a paired host as %s, so only declared intent is destructive (#37245)', - (reason, wireReason) => { - isWebRuntimeSessionActiveMock.mockReturnValue(true) - resolveHostSessionTabIdForWebSessionTabMock.mockReturnValue('host-tab-1') - getStateMock.mockReturnValue({ - ...terminalOwnerRows('web-runtime'), - tabsByWorktree: { 'wt-1': [{ id: 'local-tab-1' }, { id: 'local-tab-2' }] }, - activeWorktreeId: 'wt-1', - activeTabId: 'local-tab-1', - closeTab: vi.fn(), - setActiveTab: vi.fn() - }) - - closeTerminalTab('local-tab-1', { reason, skipRunningProcessConfirm: true }) - - expect(closeWebRuntimeSessionTabMock).toHaveBeenCalledWith( - expect.objectContaining({ tabId: 'host-tab-1', reason: wireReason }) - ) - } - ) - - it('keeps the pinned confirmation guard for a hostCloseReason pty-exit close', () => { - const requestPinnedTabCloseConfirm = vi.fn() - const closeUnifiedTab = vi.fn() - getStateMock.mockReturnValue( - makePinnedTabState({ - confirmClosePinnedTab: true, - requestPinnedTabCloseConfirm, - closeUnifiedTab - }) - ) - - closeTerminalTab('pinned-entity-1', { hostCloseReason: 'pty-exit' }) - - expect(closeUnifiedTab).not.toHaveBeenCalled() - expect(requestPinnedTabCloseConfirm).toHaveBeenCalledTimes(1) - }) - - it('closes unified-only terminal tabs when tabsByWorktree is missing the row', () => { - const closeTab = vi.fn() - const closeUnifiedTab = vi.fn() - getStateMock.mockReturnValue({ - ...terminalOwnerRows(null), - tabsByWorktree: {}, - unifiedTabsByWorktree: { - 'wt-1': [ - { - id: 'unified-tab-1', - entityId: 'terminal-entity-1', - contentType: 'terminal', - groupId: 'group-1', - worktreeId: 'wt-1', - label: 'Claude', - customLabel: null, - color: null, - sortOrder: 0, - createdAt: 0, - isPreview: false, - isPinned: false - } - ] - }, - activeWorktreeId: 'wt-1', - activeTabId: 'terminal-entity-1', - openFiles: [], - browserTabsByWorktree: {}, - reconcileWorktreeTabModel: vi.fn(() => ({ renderableTabCount: 0 })), - closeTab, - closeUnifiedTab, - setActiveTab: vi.fn(), - setActiveWorktree: vi.fn() - }) - - closeTerminalTab('terminal-entity-1', { reason: 'user' }) - - expect(closeTab).toHaveBeenCalledWith('terminal-entity-1', { reason: 'user' }) - expect(closeUnifiedTab).not.toHaveBeenCalled() - }) - - it('routes closes on a remote worktree to the host even when the local→host map has no entry', () => { - // Decode unmapped plain-UUID host tabs too, or the next authoritative snapshot resurrects a locally closed tab. - const closeTab = vi.fn() - isWebRuntimeSessionActiveMock.mockReturnValue(true) - resolveHostSessionTabIdForWebSessionTabMock.mockReturnValue(null) - getStateMock.mockReturnValue({ - ...terminalOwnerRows('web-runtime'), - tabsByWorktree: { - 'wt-1': [{ id: 'plain-uuid-tab' }, { id: 'local-tab-2' }] - }, - activeWorktreeId: 'wt-1', - activeTabId: 'plain-uuid-tab', - openFiles: [], - closeTab, - setActiveTab: vi.fn() - }) - - closeTerminalTab('plain-uuid-tab', { reason: 'user' }) - - expect(closeTab).toHaveBeenCalledWith('plain-uuid-tab', { - reason: 'user', - remoteCloseOwnedByHost: true - }) - expect(closeWebRuntimeSessionTabMock).toHaveBeenCalledWith({ - worktreeId: 'wt-1', - tabId: 'plain-uuid-tab', - environmentId: 'web-runtime', - reason: 'user' - }) - }) - - function makePinnedTabState( - overrides: { confirmClosePinnedTab: boolean } & Record - ): Record { - const { confirmClosePinnedTab, ...rest } = overrides - return { - settings: { activeRuntimeEnvironmentId: null, confirmClosePinnedTab }, - ...terminalOwnerRows(null), - tabsByWorktree: {}, - unifiedTabsByWorktree: { - 'wt-1': [ - { - id: 'unified-pinned-1', - entityId: 'pinned-entity-1', - contentType: 'terminal', - groupId: 'group-1', - worktreeId: 'wt-1', - label: 'Server', - generatedLabel: null, - customLabel: null, - color: null, - sortOrder: 0, - createdAt: 0, - isPreview: false, - isPinned: true - } - ] - }, - activeWorktreeId: 'wt-1', - activeTabId: 'pinned-entity-1', - openFiles: [], - browserTabsByWorktree: {}, - reconcileWorktreeTabModel: vi.fn(() => ({ renderableTabCount: 0 })), - closeTab: vi.fn(), - closeUnifiedTab: vi.fn(), - setActiveTab: vi.fn(), - setActiveWorktree: vi.fn(), - requestPinnedTabCloseConfirm: vi.fn(), - ...rest - } - } - - it('guards a pinned tab closed by its unified id (workspace overlay path)', () => { - const requestPinnedTabCloseConfirm = vi.fn() - const closeUnifiedTab = vi.fn() - getStateMock.mockReturnValue( - makePinnedTabState({ - confirmClosePinnedTab: true, - requestPinnedTabCloseConfirm, - closeUnifiedTab - }) - ) - - // Overlay close supplies the unified ID, so pin detection must recognize it. - closeTerminalTab('unified-pinned-1', { reason: 'user' }) - - expect(closeUnifiedTab).not.toHaveBeenCalled() - expect(requestPinnedTabCloseConfirm).toHaveBeenCalledTimes(1) - }) -}) - -describe('closeOtherTerminalTabs', () => { - beforeEach(() => { - vi.clearAllMocks() - isWebRuntimeSessionActiveMock.mockReturnValue(false) - }) - - it('delegates other terminal closes to the host runtime in paired web clients', () => { - const setActiveTab = vi.fn() - const closeTab = vi.fn() - isWebRuntimeSessionActiveMock.mockReturnValue(true) - getStateMock.mockReturnValue({ - ...terminalOwnerRows('web-runtime'), - tabsByWorktree: { - 'wt-1': [{ id: 'keep' }, { id: 'close-a' }, { id: 'close-b' }] - }, - setActiveTab, - closeTab - }) - - closeOtherTerminalTabs('keep', 'wt-1') - - expect(setActiveTab).toHaveBeenCalledWith('keep') - expect(closeWebRuntimeSessionTabMock).toHaveBeenCalledTimes(2) - expect(closeWebRuntimeSessionTabMock).toHaveBeenCalledWith({ - worktreeId: 'wt-1', - tabId: 'close-a', - environmentId: 'web-runtime', - reason: 'user' - }) - expect(closeWebRuntimeSessionTabMock).toHaveBeenCalledWith({ - worktreeId: 'wt-1', - tabId: 'close-b', - environmentId: 'web-runtime', - reason: 'user' - }) - expect(closeTab).toHaveBeenCalledTimes(2) - expect(closeTab).toHaveBeenNthCalledWith(1, 'close-a', { remoteCloseOwnedByHost: true }) - expect(closeTab).toHaveBeenNthCalledWith(2, 'close-b', { remoteCloseOwnedByHost: true }) - }) -})