Skip to content

fix(workspaces): seed shells only for blank selection - #19940

Merged
brennanb2025 merged 3 commits into
mainfrom
brennanb2025/agent-launch-seeding-rule
Sep 11, 2026
Merged

brennanb2025 merged 3 commits into
mainfrom
brennanb2025/agent-launch-seeding-rule

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 10 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​489 $\color{#cf222e}{\Huge{\mathbf{−}}}$​3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​486
Prod 14 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​212 $\color{#cf222e}{\Huge{\mathbf{−}}}$​92 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​120

ELI5

When the user picks Blank Terminal, Orca opens a shell. When the user picks an agent, that agent owns the initial surface, so Orca does not open a competing idle shell first.

What Changed

  • Thread the picker selection through git-worktree and folder-workspace activation, including structured fallback activation.
  • Treat a non-null agent as the initial surface in active, background, gated-reseed, and paired web-runtime paths while preserving providesInitialSurface for navigation callers.
  • Skip host-owned idle-shell fallback creation for agent-created local, SSH, and folder workspaces.
  • Add focused renderer, folder, paired-runtime, background-create, and host-side coverage.

Workspace Creation Entry Paths

Entry path What this PR changes
New workspace composer — Quick Create The picker selection now travels through the pending/background git-worktree creation flow. An agent selection reserves the first surface for that agent; Blank Terminal still seeds one shell. This also covers completion after the user navigates away while creation continues.
Retained internal full-creation execution path (not currently exposed by the composer UI) The selected agent is passed into initial activation and structured-launch settlement, so this path does not open an idle shell before the chosen agent. It is covered by characterization/unit tests; there is no rendered Electron entry point at this head.
New workspace composer — folder/project-group target Folder-workspace creation passes the same selection through local, WSL, SSH, and paired-runtime activation. Agent and structured-fallback launches own the first surface; Blank Terminal owns the shell path.
Host/runtime worktree.create Inactive/headless creates—used by runtime clients such as CLI, mobile, and paired clients—apply the rule on the execution host for local git worktrees, SSH worktrees, and folder workspaces. A create receipt/startup proves the agent surface; picker intent alone does not.

The PR also updates the shared completion paths used by those entry points:

  • structured native-chat success suppresses fallback shell seeding;
  • structured refusal opens exactly one legacy agent terminal;
  • background completion creates the selected agent surface without activating the workspace;
  • paired web-runtime creation is deduplicated while in flight and reports definite create failures;
  • empty/sleep-resume activation and reseed paths treat a selected agent as the pending initial surface, while ordinary navigation callers can still use providesInitialSurface for editor/diff surfaces.

Reopening or navigating to an existing workspace is not a new creation entry point; it is touched only because the same activation/reseed code finishes newly created and restored workspaces.

Why

Renderer activation and host-side background creation could each seed a default shell before the selected agent opened. Enforcing the same ownership rule at both points prevents duplicate tabs and visible surface swaps while keeping Blank Terminal behavior unchanged.

Linked Issue

N/A — standalone Task 1 from the reviewed agent-launch surface-ownership plan.

Visual Proof

N/A — no visual styling or layout changed; the interaction routing is covered by focused automated tests and ablation.

Testing

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

  • Focused suite: 8 files, 92/92 tests passed.

  • Supporting launch-plan/census suite: 3 files, 29/29 tests passed.

  • Full-creation execution characterization: 1/1 test passed.

  • Sequential typechecks passed: web, Node, and CLI.

  • Direct oxlint on all 17 changed files: 0 errors and 0 warnings.

  • oxfmt --check, git diff --check, and changed-file NUL scan passed.

  • Ablation: reverted the nine production files to origin/main while retaining the tests; 11/92 tests failed and 81/92 passed. Restoring the implementation returned the same suite to 92/92 passing.

Review

The change removes the duplicate-seeding mechanism at both owners instead of adding a renderer-only guard. Existing navigation semantics remain owned by providesInitialSurface; no remote wire contract changes.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

No inaccuracies were found in Task 1 of the plan. The repository does not contain config/tsconfig.tc.node.json, so Node validation used the existing config/tsconfig.node.json as required by the project scripts.

Checklist

  • This PR is small and focused
  • I explained what changed and why (including ELI5)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (focused tests, direct lint/format, and sequential project typechecks passed; CI will cover the full suite and build)

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • worktree-activation-surface-selection.ts — new WorktreeActivationSurfaceSelection with agent?: TuiAgent | null, and activationProvidesInitialSurface() collapsing "navigation caller" and "agent selection" into one surface-ownership signal.
  • worktree-activation.ts — folds all opts?.providesInitialSurface reads into a single computed boolean; the notifyHostRuntime wake-respawn gate now additionally requires opts?.agent == null.
  • worktree-creation-flow-execute.ts — threads preparedRequest.agent into activation and widens the non-activating seed skip from structuredLaunch to agent !== null.
  • Create-flow callers — folder-workspace-composer-submit.ts, full-creation-execution.ts, and full-creation-structured-launch.ts pass the picker selection through activation (including the structured fallback).
  • Host-side guards — runtime-local-worktree-terminal-startup.ts, runtime-folder-worktree-create.ts, and runtime-remote-managed-worktree-create.ts skip the idle-shell fallback when createdWithAgent is set.

The change is coherent and well-motivated: it removes the duplicate-seed at both owners (renderer and host) rather than adding a renderer-only band-aid, and keeps Blank Terminal behavior and navigation-caller providesInitialSurface semantics intact.

I traced the load-bearing seams and found no correctness issues: the widened renderer skip (agent !== null instead of structuredLaunch) is safe because an agent selection always materializes its terminal via one of structured session, backend spawn, or a renderer startupPlan (which keeps hasExplicitTerminalWork true, so the actual seed still happens); agent is non-null in the composer model (tuiAgent: TuiAgent), so the new non-null settleFullCreationStructuredLaunch.agent parameter is well-typed; and the new surface-selection seam is correctly registered in the providesInitialSurface caller census. The tests pin real behavior (exact call/tabCount assertions plus a pre-existing ablation), and the widened assertion in the cancellation test reflects the new behavior rather than masking it.

The one gap worth noting for context only: the two host-side one-line guards (runtime-folder-worktree-create.ts and runtime-remote-managed-worktree-create.ts) have no direct unit test (the sibling startRuntimeLocalWorktreeTerminals does). They mirror tested logic and are exercised by the orca-runtime integration specs, so this is not a blocker.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@coderabbitai

coderabbitai Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: c7ebe314-f830-4a43-93b3-72dbcd856371

📥 Commits

Reviewing files that changed from the base of the PR and between 331df88 and ef8e165.

📒 Files selected for processing (2)
  • src/renderer/src/lib/web-runtime-worktree-terminal-after-wake.ts
  • src/renderer/src/lib/worktree-activation-empty-remote.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 4 remain after this review.


📝 Walkthrough

Walkthrough

Agent selections propagate through folder and worktree creation into activation. Activation derives initial-surface availability from the selected agent or an explicit caller flag. Agent-created worktrees skip fallback terminal creation across local, folder, and remote runtime paths. Web-runtime recovery carries startup and agent data and suppresses duplicate terminal bootstrap. Tests cover these paths and cancelled creation handling.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to ef8e1

The workspace startup changes have no identified merge-blocking risk.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 20 functions across 24 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the main change: shells are seeded only for Blank Terminal selections.
Description check ✅ Passed The description is detailed, focused, and covers the required change, rationale, testing, visual proof, review notes, and checklist. The Linked Issue section is present but lists N/A despite the templ…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 66c3c9e7-39cf-446a-8ddd-b4716fc67031

📥 Commits

Reviewing files that changed from the base of the PR and between fb85f88 and 4f01f05.

📒 Files selected for processing (17)
  • src/main/runtime/runtime-folder-worktree-create.ts
  • src/main/runtime/runtime-local-worktree-terminal-startup.test.ts
  • src/main/runtime/runtime-local-worktree-terminal-startup.ts
  • src/main/runtime/runtime-remote-managed-worktree-create.ts
  • src/renderer/src/components/sidebar/folder-workspace-composer-submit.test.ts
  • src/renderer/src/components/sidebar/folder-workspace-composer-submit.ts
  • src/renderer/src/hooks/composer-state/full-creation-execution.ts
  • src/renderer/src/hooks/composer-state/full-creation-structured-launch.test.ts
  • src/renderer/src/hooks/composer-state/full-creation-structured-launch.ts
  • src/renderer/src/lib/worktree-activation-emptied-workspace-reseed.test.ts
  • src/renderer/src/lib/worktree-activation-surface-caller-wiring.test.ts
  • src/renderer/src/lib/worktree-activation-surface-selection.ts
  • src/renderer/src/lib/worktree-activation-web-runtime.test.ts
  • src/renderer/src/lib/worktree-activation.ts
  • src/renderer/src/lib/worktree-creation-agent-seeding.test.ts
  • src/renderer/src/lib/worktree-creation-flow-execute.ts
  • src/renderer/src/lib/worktree-creation-flow.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.

args.startup && !didSpawnStartup ? args.startup : undefined
)
} else if (deps.ptySpawnAvailable && !didSpawnStartup) {
} else if (deps.ptySpawnAvailable && !didSpawnStartup && !args.createdWithAgent) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n -C 8 '\b(createdWithAgent|draftPaste|startupDraftPaste)\b' src

Repository: stablyai/orca

Length of output: 50370


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in \
  src/main/runtime/runtime-folder-worktree-create.ts \
  src/main/runtime/runtime-local-worktree-terminal-startup.ts \
  src/main/runtime/runtime-remote-managed-worktree-create.ts \
  src/main/runtime/runtime-worktree-agent-startup.ts \
  src/main/runtime/runtime-managed-worktree-create-types.ts
do
  echo "===== $f ====="
  ast-grep outline "$f" 2>/dev/null | head -n 120 || true
done

echo "===== targeted references ====="
rg -n -C 18 'draftPaste|startupDraftPaste|createdWithAgent|didSpawnStartup|shouldActivate|canSpawn|ptySpawnAvailable' \
  src/main/runtime/runtime-folder-worktree-create.ts \
  src/main/runtime/runtime-local-worktree-terminal-startup.ts \
  src/main/runtime/runtime-remote-managed-worktree-create.ts \
  src/main/runtime/runtime-worktree-agent-startup.ts \
  src/main/runtime/runtime-managed-worktree-create-types.ts

Repository: stablyai/orca

Length of output: 50369


🤖 get_repo_knowledge executed:

get_repo_knowledge stablyai/orca /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4/architecture /tmp/coderabbit-repo-knowledge/stablyai-orca-89dc44e4/learnings

Length of output: 47161


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in \
  src/main/runtime/runtime-folder-worktree-create.ts \
  src/main/runtime/runtime-local-worktree-terminal-startup.ts \
  src/main/runtime/runtime-remote-managed-worktree-create.ts
do
  echo "===== $f relevant lines ====="
  rg -n -C 30 'draftPaste|startupDraftPaste|createdWithAgent|didSpawnStartup|shouldActivate|canSpawn|ptySpawnAvailable' "$f"
done

Repository: stablyai/orca

Length of output: 29260


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '110,205p' src/main/runtime/runtime-folder-worktree-create.ts
sed -n '105,190p' src/main/runtime/runtime-local-worktree-terminal-startup.ts
sed -n '165,255p' src/main/runtime/runtime-remote-managed-worktree-create.ts
sed -n '1,145p' src/main/runtime/runtime-worktree-agent-startup.ts

Repository: stablyai/orca

Length of output: 15378


🏁 Script executed:

#!/bin/bash
set -euo pipefail
for f in src/main/runtime/runtime-folder-worktree-create.ts src/main/runtime/runtime-local-worktree-terminal-startup.ts src/main/runtime/runtime-remote-managed-worktree-create.ts; do
  echo "===== $f ====="
  awk 'BEGIN{p=0} /draftPaste|startupDraftPaste|createdWithAgent|didSpawnStartup|shouldActivate|canSpawn|ptySpawnAvailable/{p=1; start=NR-12} p && NR>=start {print NR ":" $0} p && NR>start+24 {p=0}' "$f"
done

Repository: stablyai/orca

Length of output: 19242


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 20 \
  'createRuntimeFolderWorktree|startRuntimeLocalWorktreeTerminals|createRuntimeRemoteManagedWorktree|startupDraftPaste|draftPaste:' \
  src/main/runtime src/main/ipc \
  -g '*.ts' \
  | head -n 1200

Repository: stablyai/orca

Length of output: 50369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 24 'createRuntimeFolderWorktree\(|startRuntimeLocalWorktreeTerminals\(|createRuntimeRemoteManagedWorktree\(' src/main -g '*.ts'
rg -n -C 16 'startupDraftPaste|draftPaste' src/main/runtime/orca-runtime.ts src/main/runtime -g '*.ts' | head -n 1000

Repository: stablyai/orca

Length of output: 50369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 12 'startupDraftPaste|effectiveCreatedWithAgent|effectiveDraftPaste' \
  src/main src/shared src/preload src/cli \
  -g '*.ts' | head -n 1000

Repository: stablyai/orca

Length of output: 32624


Include explicit draft-paste agents in fallback suppression.

The orchestrator derives effectiveCreatedWithAgent from draftStartup.agent only when startup is absent. With explicit startup, it forwards startupDraftPaste separately and leaves the marker equal to createdWithAgent. If startup creation fails, all three fallback branches can therefore create a plain terminal. Guard with the effective draft-paste agent.

📍 Affects 3 files
  • src/main/runtime/runtime-folder-worktree-create.ts#L175-L175 (this comment)
  • src/main/runtime/runtime-local-worktree-terminal-startup.ts#L166-L166
  • src/main/runtime/runtime-remote-managed-worktree-create.ts#L225-L225

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • web-runtime-worktree-terminal-after-wake.ts — ensureWebRuntimeWorktreeTerminalAfterWake now accepts startup/agent/activate and materializes the prepared agent terminal (or blank shell) on the paired host, guarded by a launchAgent dedup against existing mirrored/live tabs.
  • worktree-activation.ts — the notifyHostRuntime gate moved from opts?.agent == null to opts?.providesInitialSurface !== true, now threading startup/agent into the wake-respawn for both worktree and folder activation.
  • worktree-creation-flow-execute.ts / worktree-creation-structured-session.ts — background and structured-fallback creation route agent selections through ensureWebRuntimeWorktreeTerminalAfterWake (activate: false) instead of leaving them surface-less.
  • web-runtime-terminal-create-operation.ts / web-runtime-session-types.ts — new client-only preparedAgentCommand flag forces the legacy session.tabs.createTerminal path, skipping host authority so a command that already encodes the agent startup is not rebuilt.
  • active-session-subscription.ts — the wake-respawn skip flag now also gates the initial-terminal bootstrap, preventing a competing seed while the host-aware surface is in flight.

This commit closes the gap the prior commit left on paired web-runtime workspaces: an agent selection with no structured session, backend spawn, or startup plan previously produced no surface at all, since the renderer never asked the host to create the agent terminal. All affected flows (active reveal, background create, structured fallback, folder activation) now converge on one host-aware creation point, and Blank Terminal keeps its original shell-seeding path unchanged.

The load-bearing seams check out. launchAgent/launchToken/command are pre-existing params on session.tabs.createTerminal (the legacy path already forwarded them); the only wire-adjacent addition is preparedAgentCommand, a client-side flag that is never serialized. The opts?.providesInitialSurface !== true gate intentionally uses the raw navigation flag so agent selections still route through the wake-respawn while navigation (and structured-launch) callers stay excluded. The removed getKnownWorktreeById null-check in ensureWebRuntimeWorktreeTerminalAfterWake is safe because getRuntimeEnvironmentIdForWorktree returns null for unknown ids, and every call site passes a freshly-created worktree/folder key. New tests pin the exact host request (command/env/launchAgent/launchToken), the backend-spawned no-op, and the blank-vs-agent surface count.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • web-runtime-worktree-terminal-after-wake.ts — a failed host terminal-creation request now surfaces a toast.error with a stable per-workspace id, chained between the createWebRuntimeSessionTerminal call and the existing finally respawn teardown.
  • worktree-activation-empty-remote.test.ts — mocks sonner and pins the failure surfacing (toast fires with the host message and stable id, exactly one host call, and the success path does not toast).

This commit closes the silent-failure gap the previous commit left open: when the paired host refused an agent-terminal request, a selected agent ended up with no surface and no explanation. The toast turns that into a concrete signal.

The seam checks out. createWebRuntimeSessionTerminal resolves a WebRuntimeTerminalCreateOutcome ({ status: 'created' } | { status: 'failed'; message: string }), so outcome.status === 'failed' narrows correctly before reading .message; createWebRuntimeSessionTerminalResult catches and converts every internal error into a resolved failed outcome, so the promise never rejects and the finally teardown always runs. The toast id is stable per runtime/worktree, so repeated failures update one toast rather than stacking. The new test is meaningful — it fails if the toast, the message, or the single-call guarantee regresses.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Final review status: clean / merge-ready

Reviewed and fixed through a same-model review loop at head ef8e165b5e21e92faf514f32c5e791ed0f9fc1eb. No P0/P1 findings or release blockers remain.

Functional correctness

The root failure was treating picker selection intent as proof that an initial agent surface existed. That could suppress fallback terminal creation even when the execution host had not created an agent surface, leaving active or background workspaces empty. The final implementation makes backend create receipts authoritative, keeps surface creation on the execution host, and covers active/background creation, git worktrees and folder workspaces, paired runtimes, structured refusal, and in-flight create fencing.

The final follow-up also handles a definite pre-create failure: it shows one environment/worktree-keyed error toast, performs no automatic retry, and still treats post-create reconciliation failures as created so an ambiguous retry cannot duplicate a terminal.

Architecture and precedent

The implementation reuses Orca's existing createWebRuntimeSessionTerminal -> host RPC -> snapshot reconciliation path rather than adding a parallel creator. The execution host owns process/surface creation; the paired client owns selection, focus intent, and presentation reconciliation. No remote wire schema or opcode changed.

Material deviation/risk: mixed-version new-client/old-host sessions can still retain an idle host shell next to the selected agent. That is a pre-existing compatibility limitation and should be capability-gated separately rather than broadening this PR.

Validation

  • Same-model review/fix/re-review: CLEAN.
  • Focused local coverage: 12 files / 139 tests passed for the main fix; the final failure-surfacing follow-up passed 4 lifecycle/sync files / 32 tests and its final 2-test target.
  • pnpm tc:web: passed.
  • Changed-code quality: 0 findings across 24 files; oxlint, React Doctor lint, formatting, NUL scan, and diff checks passed.
  • Performance audit: clean; no polling, fanout, listener, timer, subprocess, or unbounded-growth regression.
  • Final readiness: PASS WITH RISK; no P0/P1 or release blocker.
  • Fresh CI on this exact head: all successful, including static analysis, typecheck, all 8 Node test shards, Linux package, Windows package, changed E2E build/specs, verify, and Pullfrog.

Remaining validation gaps

  • The required Grok Electron validation was attempted but could not start because the provider had reached its weekly usage limit. No Electron app was launched and no screenshot/video evidence was produced or attached.
  • No live Windows, WSL, or SSH flow was run; automated coverage and Windows packaging are green.
  • Mobile QA is not applicable because this PR changes no mobile source, UI, or protocol.
  • A pre-existing startup draft/follow-up timing window can outlast the client-side delivery wait on slow paired-runtime creation; the new host-owned creation behavior improves the prior empty-surface outcome, but timing policy belongs in a follow-up.

Recommendation: merge-ready based on functional review, architectural fit, focused validation, and green CI, with the live-platform and visual-proof gaps above recorded explicitly.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Live platform validation follow-up: Windows, WSL, and SSH pass

Validated exact head ef8e165b5e21e92faf514f32c5e791ed0f9fc1eb through isolated, background Electron instances using rendered UI/CDP. All three lanes recommend land.

Windows native — PASS

Windows High Spec, exact-head disposable child checkout and isolated profile:

  • 29 focused activation/adoption tests passed.
  • Agent selection produced one rendered tab and one PTY with no competing idle shell.
  • Leave/re-enter preserved the same tab/PTY identity.
  • Blank Terminal produced exactly one shell PTY and visible command output.
  • Plain-folder agent creation produced one initial surface; an authenticated Claude run returned QA_CLAUDE_WIN_2288_OK.
  • Codex provider completion was not tested because the isolated profile lacked CODEX_LB_API_KEY; no credentials were copied or exposed.
Windows screenshots

Agent singleton:

Windows agent singleton

Same agent after re-entry:

Windows agent after re-entry

Blank Terminal output:

Windows blank terminal output

Folder agent initial surface:

Windows folder agent

Authenticated folder-agent response:

Windows folder Claude response

WSL — PASS

Windows High Spec with real Ubuntu 24.04 / Git 2.43:

  • 10 focused files / 113 tests passed.
  • Git-worktree and folder-workspace agent selection each produced exactly one tab, one PTY, and one Codex process, with no fallback shell.
  • Blank Terminal in both workspace types produced exactly one shell tab/PTY, no agent process, and successful rendered command I/O.
  • Reactivation reused the original tab/PTY; pending-startup and setup-split state remained empty.
  • Four agent workspaces mapped to four Codex processes; two blank workspaces contained shells only. No retry, polling, or process churn was observed.
  • The rendered errors were entirely bounded hosted-review lookup failures caused by the fixture's intentionally unreachable restored origin; excluding those entries left zero renderer errors.
  • Codex launch/trust/process ownership was proved, but a completed provider response was not because provider auth was unavailable.
WSL screenshots

WSL Codex initial

WSL Codex after trust

WSL Blank Terminal I/O

WSL Codex reactivated

WSL folder agent

WSL folder Blank Terminal I/O

Real SSH — PASS

Disposable Ubuntu 22.04 arm64 SSH container, Node 20.20.2, real demo-project, relay built before connection:

  • Exact Electron worktree identity was verified.
  • Rendered Codex selection created one remote PTY and the real shell -> Codex Node -> native Codex process tree with no competing idle-shell surface; the CLI reached its genuine sign-in UI.
  • Rendered Blank Terminal created one remote PTY running bash, no child agent process, and command output proved cwd, branch, git status, and all backing worktrees.
  • Disconnect removed local PTY sessions but left remote processes alive, correctly preserving the execution-host boundary. Cleanup then terminated only the owned remote PIDs.
  • A completed Codex provider response was not tested because the disposable target had no auth.
SSH screenshots

SSH Codex sign-in

SSH Blank Terminal backing state

Cleanup and final status

  • Windows Low Spec was unavailable, so native Windows and WSL used separate isolated resources on Windows High Spec.
  • All owned Electron/test processes, CDP ports, disposable worktrees/branches/repos/folder contexts, profiles, WSL fixtures, SSH keys, bundle, Docker container, logs, and evidence directories were cleaned and verified absent after upload.
  • The PR worktree remains clean at the exact pushed head.
  • GitHub merge state is CLEAN; all checks remain settled with zero failures and zero pending.

Recommendation: land.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Electron validation status

Validated at exact PR head ef8e165b5e21e92faf514f32c5e791ed0f9fc1eb; PR merge state is CLEAN and required CI is green. The same-model review loop is clean, readiness review is PASS WITH RISK, and the performance audit found no polling, listener, subprocess, render-churn, or unbounded-growth regression.

macOS Electron (fresh pass)

Using ORCA_BACKGROUND_LAUNCH=1, an isolated profile, hidden Electron, and Playwright/CDP only:

  • Quick Create → Blank Terminal: one rendered tab and one shell PTY.
  • Quick Create → Codex: one rendered agent tab/PTy, real Codex TUI/foreground process, and no competing shell.
  • Folder workspace → Blank Terminal and Codex: one tab/PTY each; no duplicate shell.
  • Re-entry twice preserved the same tab/PTY identities with no duplicate surfaces.
  • pnpm run build:electron-vite passed; no renderer errors or performance/polling regressions were observed.

Screenshots:

  • macOS Quick Blank
  • macOS Quick Codex
  • macOS Folder Blank
  • macOS Folder Codex

Other Electron/remote coverage

  • Windows High Spec: rendered Codex/Blank and folder paths, singleton re-entry, real Claude response; 29 focused tests passed.
  • WSL on Windows High Spec: real Ubuntu fixture, git-worktree and folder paths, rendered I/O, re-entry, and process cardinality; 113 focused tests passed.
  • SSH Linux: remote Codex and Blank Terminal PTYs/process ownership, rendered I/O, and disconnect without falsely claiming remote process death.

Remaining validation limits

  • The current composer exposes Quick Create only; “Full Create” is an internal retained execution path covered by characterization/unit tests, not a rendered Electron entry point at this head.
  • A live background/navigation-away race and sleep-resume reseed were not proven in this pass; automated tests cover those contracts.
  • Authenticated Codex turn completion was not available in every environment; macOS proved the real TUI/foreground process, while Windows could not complete Codex auth.
  • Windows Low Spec was unavailable.

No concrete release-blocking regression was found. Status: LAND for the reviewed and tested scope, with the limits above explicitly documented.

@brennanb2025
brennanb2025 merged commit 2ffac47 into main Sep 11, 2026
34 checks passed
brennanb2025 added a commit that referenced this pull request Sep 14, 2026
…nt selection (#20182)

* fix(workspaces): re-seed a gate-reported empty workspace after an agent selection

#19940 routed two different questions through one predicate. An agent selection
justifies skipping the *pre-emptive* shell at create time, but it was also
suppressing the async activation gate's fail-closed re-seed. The gate returns
`empty` only after adoption, structured inventory and resume all produced
nothing, so it is positive evidence the agent surface never arrived (dead PTY,
unreadable census, null startup plan) — exactly when the re-seed is needed.

Suppressing it there left the workspace with zero tabs and no recovery:
ensureWebRuntimeWorktreeTerminalAfterWake returns early for a plain local
workspace, so nothing else seeds one.

`gatedEmptyOutcomeReseedSuppressed` now answers the re-seed question on its own,
honouring only an explicit `providesInitialSurface` caller promise — restoring
v1.4.200's behaviour for that path. The create-time skip keeps using the
agent-inclusive `activationProvidesInitialSurface` unchanged.

* refactor(workspaces): make gated reseed policy explicit

* fix(workspaces): harden gated empty reseeding

* chore(workspaces): split duplicate-folder routing fix

* refactor(workspaces): keep reseed helper outside caller census

---------

Co-authored-by: Merge Sim <sim@local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant