Skip to content

Sleep stops a workspace's native chat agents - #28445

Merged
brennanb2025 merged 37 commits into
mainfrom
brennanb2025/sleep-stops-native-chat
Oct 19, 2026
Merged

brennanb2025 merged 37 commits into
mainfrom
brennanb2025/sleep-stops-native-chat

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 22 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​677 $\color{#cf222e}{\Huge{\mathbf{−}}}$​112 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​565
Prod 58 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1206 $\color{#cf222e}{\Huge{\mathbf{−}}}$​313 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​893

ELI5

The problem. Sleeping a workspace stopped its terminals and browsers but left its native chat agents running: the claude or codex process behind each chat tab. A workspace that only had chats couldn't be slept at all, because Sleep was greyed out.

What's different for you. Sleep now also stops the workspace's chat agents. This applies to Sleep from the sidebar menu, bulk and descendant Sleep, the phone and the command line. The chat tabs and their history stay. Your next message in a slept chat starts the agent again in the same conversation. Chat-only workspaces can now be slept.

  • A chat that is replying is stopped right away, without waiting for the turn to finish. In QA, claude exited about half a second after Sleep.
  • After Sleep, the chat's row keeps its last result (for example "Done") with nothing running.
  • If a chat can't be confirmed stopped, for example because its host is unreachable, everything else still stops. You get one toast, and the workspace isn't counted as asleep.
  • When the same workspace is open on two hosts (say this Mac and an SSH machine), Sleep follows main's rule from [hardening 4/5] fix(sidebar): confirm before sleeping a workspace that another host's copy shares #30047: it sleeps every copy, after the existing "also sleeps the copy on " confirmation. It stops the chats on every host that has a copy.

Marking the slept workspace as asleep and hiding it under "Hide sleeping workspaces" is the stacked follow-up, #28457.

What Changed

  • The host stops the chats. Sleep asks each execution host to stop the workspace's chats, through a new agentSession.sleepWorkspace call. The execution host is the machine running the agents: this desktop, a paired server, or an SSH machine reached through a paired server. The host finds every chat it runs in that workspace, including hidden chats and starts still in progress. It closes them through the existing ordered close path, which ends the process's input, then signals it, then forces an exit if needed. It answers with the chats it can prove are stopped, plus a typed failure for each of the rest.

  • What counts as stopped. A chat counts as stopped only with proof:

    • the host stopped the running process itself;
    • it released an acquisition it owned and saw the exit;
    • the chat's claim is already released, with recorded exit evidence;
    • or the chat never started.

    A release without proof stays unverified, and that's what produces the one toast.

  • Only real newer work overrules a stop. A stop result counts as superseded only on facts: the chat's session restarted, or newer work exists (a running child, a delivery, a pending submission, a create or attach in flight, or an open dispatch). The provider's own "I've ended" report doesn't count. A message you send after the stop still runs and resumes the chat.

  • Sleep acts on the workspace, as main does. The sidebar flow is main's id-based flow from [hardening 4/5] fix(sidebar): confirm before sleeping a workspace that another host's copy shares #30047. It adds one step: when terminal teardown is admitted, it asks every host that publishes the workspace to stop its chats, from main's own list of a workspace's copies. If main's terminal-owner check refuses (it can't tell which copy runs the terminals), no chat is stopped. A workspace's VM is suspended only after its chats have stopped.

  • A failed Claude start is retired after a proven exit. If a Claude chat's start failed and Sleep later proves its process gone, the failed attempt is dropped, so your next message starts a fresh agent instead of being refused.

  • Status rows have one writer. Chat status rows stay owned by the host's status feed. Sleep no longer deletes them from the app window, so there's no race between the two writers. A chat makes a workspace sleepable only while the host reports that it holds the chat's process.

  • Project moves. The shared Sleep routine is also used when a project moves into WSL (feat(wsl-mover): pause a moving project's terminals through Sleep and prove they exited (D1b-5d) #28820), so that move now stops the project's chats too.

Why

The host is the only side that knows which agent processes it owns. The visible tab list misses hidden chats and starts still in progress. Reusing the host's ownership and its existing close path avoids a second way of stopping processes. Taking main's whole-workspace Sleep model keeps one meaning of what Sleep acts on. An earlier version of this PR slept one host's copy at a time; that contradicted main's #30047 decision and would have broken its confirmation flow.

Mixed versions. The new call is checked against the host's advertised capabilities. An older host that lacks it returns an ordinary failure, with the one toast, and is fixed by updating the host. The failures field in the answer is optional, so older peers read the answer unchanged. Nothing else on the wire changes.

Differences from the common pattern:

Known limitation: main's terminal-owner check also refuses a workspace open on two hosts that has no terminal bound in this window, so such a workspace (including one with only chats) still can't be slept. Main shows "can't tell which host runs this workspace's terminals". A chat-only workspace on a single host can be slept.

Linked Issue

Reported in the workspace Sleep thread ("Sleeping a workspace with a native chat should really sleep it ... should be properly marked as slept and hidden"). The marking and hiding half is #28457.

Visual Proof

The same input on each build: a workspace with only a Claude chat (ws-chat), and one with a terminal plus a Claude chat (ws-mixed). Both chats were idle after replying.

Before, on main: a chat-only workspace can't be slept (Sleep is greyed out).

main: Sleep greyed out for a chat-only workspace

Before, on main: after Sleep, ws-mixed shows Inactive and drops its chat row, but that chat's claude is still running.

main: mixed workspace after Sleep, chat still running

After: Sleep is offered for the chat-only workspace.

Sleep enabled for a chat-only workspace

After Sleep on ws-chat: its claude exited, there's no toast, and the workspace is still listed.

after Sleep on the chat-only workspace

Reopening keeps the history, and a new message resumes claude and gets a reply.

history kept, new message gets a reply

After Sleep on ws-mixed: the chat's claude and the terminal's processes all stopped, with no toast.

after Sleep on the mixed workspace

Testing

Final head (5b829e9), live QA: a hidden test copy of Orca on the M4Air, with the real signed-in Claude and Codex driving the UI. Main (70d00aa) got the same input as the comparison.

  • Main: Sleep is disabled for the chat-only workspace. Sleeping the mixed workspace stops its terminal, but its claude keeps running until the app quits.
  • Chat-only Sleep: claude exits 0.46 s after Sleep, and the host lists the chat as stopped. No toast, and the workspace stays listed. Reopening shows the history, and a new message resumes claude and gets a reply.
  • Mixed Sleep: the chat and the terminal's processes all stop within 0.54 s. No toast.

Earlier rounds also covered:

  • a control chat in another workspace surviving;
  • a forced stop failure: exactly one toast, the workspace isn't counted as asleep, and retry works;
  • the same over SSH;
  • an already-stopped chat after an app restart, which sleeps without a toast.

Automated:

  • The full PR workflow is green on 5b829e9.

  • Focused tests cover: the host's Sleep answer, Sleep across the chat's lifetime, the RPC surface, the sidebar Sleep flow, main's twin-Sleep tests, and the failed-start retirement.

  • Each regression from review has a test that failed before its fix: a Sleep stopping a newer turn, a second Sleep after a failed start, and the next send after a retired start.

  • Final build manually verified through the changed native-chat flow

  • Existing automated contracts exercised and targeted changes covered

Not verified:

  • native phone apps;
  • a Windows desktop run;
  • Sleep of a workspace open on two hosts in a live rig (covered by unit tests only).

Seen but not caused by this PR:

  • About 1.5 s after Sleep, an SSH workspace reads Active again; main does this too.
  • Three real-Claude CLI tests fail on model names, because the installed CLI now reports newer IDs. Those files are unchanged from main.

Review

This went through eleven review rounds with independent reviewers, plus design panels on the hard calls. Defects found and fixed here:

  • an already-stopped chat failed Sleep;
  • the status row raced between the host feed and the app window;
  • the first Sleep of a running chat answered "stopped nothing";
  • after main's [hardening 4/5] fix(sidebar): confirm before sleeping a workspace that another host's copy shares #30047, per-copy Sleep broke main's confirmation flow, so the PR was rebuilt onto main's whole-workspace model;
  • in the rebuild, a Sleep could stop a turn sent after waking, and a VM could be suspended before its chats stopped;
  • a failed Claude start could lose its exit proof, or be reused by the next send.

The branch was synced with main at the end (main at 70d00aa) and has no conflicts. The pre-commit formatter also reformatted 13 of main's files that arrived unformatted in an earlier merge (formatting only).

Agent skill upstream boundary

  • This change copies no upstream skill-installer source or documentation.

@brennanb2025
brennanb2025 force-pushed the brennanb2025/sleep-stops-native-chat branch from 98b1618 to 224d130 Compare October 13, 2026 23:14
@brennanb2025 brennanb2025 changed the title Sleep stops a workspace's native chats and hides it Sleep stops a workspace's native chat agents Oct 13, 2026
@brennanb2025
brennanb2025 marked this pull request as ready for review October 13, 2026 23:29
@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

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: 5cf0a255-ca6e-42c7-a176-a505585d25a8
📥 Commits

Reviewing files that changed from the base of the PR and between a9aef85 and 797d7a9.

📒 Files selected for processing: 6
  • src/main/runtime/rpc/methods/structured-agent-session-gate-classification.test-fixture.ts
  • src/main/runtime/rpc/methods/structured-agent-session.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session.ts
  • tests/e2e/cross-version-wire/structured-agent-session-host-fixture.ts
  • tests/e2e/cross-version-wire/structured-agent-session-surface-calls.ts
  • tests/e2e/cross-version-wire/structured-agent-session-surface-manifest.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📝 Walkthrough

Workspace sleep now carries execution-host identity through runtime and renderer paths. The structured-session host closes matching sessions and reports stopped IDs after checking stop receipts and remaining work. The renderer coordinates host-scoped session stops and panel teardown, and terminal connections track sleep intents and teardown by host. The change also updates POSIX process-tree cleanup and Codex managed-process closure.

Priority: ➖ Normal

Merge Risk: 🔵 Low · up to 797d7

Sleep can show a plural failure message for one workspace. An adapter that omits the optional ownership check may also miss a release attempt; confirm the affected adapter paths before merging.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 23.73% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 59 functions across 65 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed 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 and concisely describes the primary change: workspace Sleep now stops native chat agents.
Description check Passed The description is detailed and covers the user impact, implementation, rationale, visual proof, testing, limitations, and review history. The Linked Issue section does not provide a direct issue link…
Full details: Description check

Explanation

The description is detailed and covers the user impact, implementation, rationale, visual proof, testing, limitations, and review history. The Linked Issue section does not provide a direct issue link or completed Fixes # reference, and several checklist items remain unchecked, but the description is otherwise substantially complete.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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: 66d46363-cb90-45fc-8db5-71e2733ee1b3
📥 Commits

Reviewing files that changed from the base of the PR and between 099afc8 and 224d130.

⛔ Files ignored due to path filters: 1
  • src/shared/rpc-contract/rpc-params-catalog.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing: 15
  • src/main/runtime/rpc/methods/structured-agent-session-gate-classification.test-fixture.ts
  • src/main/runtime/rpc/methods/structured-agent-session-pi-dialog-capability.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session.ts
  • src/renderer/src/components/sidebar/sleep-workspace-chats.ts
  • src/renderer/src/components/sidebar/sleep-worktree-activation-race.test.ts
  • src/renderer/src/components/sidebar/sleep-worktree-flow.test.ts
  • src/renderer/src/components/sidebar/sleep-worktree-flow.ts
  • src/renderer/src/components/sidebar/use-worktree-context-menu-model.tsx
  • src/renderer/src/components/sidebar/workspace-lineage-menu-actions.test.ts
  • src/renderer/src/components/sidebar/workspace-lineage-menu-actions.ts
  • src/renderer/src/components/sidebar/worktree-context-menu-policy.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/runtime/structured-agent-session-close.ts
  • src/shared/structured-agent-session-surface-capabilities.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

Comment thread src/renderer/src/components/sidebar/sleep-worktree-flow.ts Outdated

@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: 2


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: fff368ec-bc04-4d95-b920-9cc76924c31e
📥 Commits

Reviewing files that changed from the base of the PR and between 224d130 and 4f5bd1f.

⛔ Files ignored due to path filters: 1
  • src/shared/rpc-contract/rpc-params-catalog.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing: 65
  • mobile/src/host-screen/host-screen-overlays.tsx
  • src/main/acp/acp-structured-session-adapter.ts
  • src/main/claude/claude-structured-session-acquisition.ts
  • src/main/claude/claude-structured-session-adapter.ts
  • src/main/codex/codex-app-server-connection.ts
  • src/main/codex/codex-structured-session-adapter.ts
  • src/main/ipc/dashboard-payload-validation.ts
  • src/main/ipc/ephemeral-vm-runtime-handler-cleanup.test.ts
  • src/main/ipc/ephemeral-vm-runtime-handlers.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-adapter.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-attach-orchestration.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-conversation-lifetime.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-create.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-delivery.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-mutation-wiring.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-surface-lifetime.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-task-queue.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-workspace-sleep.ts
  • src/main/pi/rpc-session-adapter.ts
  • src/main/provider-process/provider-process-teardown.test.ts
  • src/main/provider-process/provider-process-teardown.ts
  • src/main/runtime/agent-session-record-founding.ts
  • src/main/runtime/orca-runtime-list-managed-worktrees.ts
  • src/main/runtime/rpc/methods/structured-agent-session-rpc.test-fixture.ts
  • src/main/runtime/rpc/methods/structured-agent-session-schemas.ts
  • src/main/runtime/rpc/methods/structured-agent-session.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session.ts
  • src/main/runtime/rpc/methods/worktree.ts
  • src/main/runtime/runtime-notifier-contract.ts
  • src/main/runtime/structured-worker-authority.ts
  • src/main/window/runtime-window-lifecycle.ts
  • src/preload/api/ephemeral-vm-api.ts
  • src/preload/api/ui-bridge-clipboard-and-window-controls.ts
  • src/preload/api/ui-command-event-api.ts
  • src/renderer/src/components/dashboard/useDashboardPopoutBridge.ts
  • src/renderer/src/components/sidebar/sleep-worktree-activation-race.test.ts
  • src/renderer/src/components/sidebar/sleep-worktree-flow.test.ts
  • src/renderer/src/components/sidebar/sleep-worktree-flow.ts
  • src/renderer/src/components/sidebar/sleep-worktree-sidebar-position.ts
  • src/renderer/src/components/sidebar/use-worktree-context-menu-commands.ts
  • src/renderer/src/components/sidebar/use-worktree-context-menu-model.tsx
  • src/renderer/src/components/sidebar/workspace-lineage-menu-actions.test.ts
  • src/renderer/src/components/sidebar/workspace-lineage-menu-actions.ts
  • src/renderer/src/components/terminal-pane/pty-connection-deliberate-sleep-guard.test.ts
  • src/renderer/src/components/terminal-pane/pty-connection/run-deferred-connect.ts
  • src/renderer/src/hooks/ipc-events/mobile-terminal-close-ipc-bridge.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/lib/ephemeral-vm-runtime-cleanup.ts
  • src/renderer/src/lib/sidebar-worktree-activation.test.ts
  • src/renderer/src/lib/sidebar-worktree-activation.ts
  • src/renderer/src/lib/worktree-sleep-intent.ts
  • src/renderer/src/runtime/structured-agent-session-client.ts
  • src/renderer/src/store/slices/worktrees/session/set-active-worktree.ts
  • src/renderer/src/store/terminals/terminal-pty-bindings.ts
  • src/renderer/src/store/terminals/terminal-pty-release.ts
  • src/renderer/src/store/terminals/terminal-tab-creation.ts
  • src/renderer/src/store/terminals/terminal-worktree-sleep-owner.test.ts
  • src/renderer/src/store/terminals/terminal-worktree-sleep-owner.ts
  • src/shared/dashboard-snapshot.ts
  • src/shared/ephemeral-vm-runtime-host-match.ts
  • src/shared/rpc-contract/structured-agent-session-params.ts
  • src/shared/rpc-contract/worktree-params.ts

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

Comment thread src/renderer/src/components/sidebar/sleep-worktree-flow.ts Outdated
@brennanb2025
brennanb2025 force-pushed the brennanb2025/sleep-stops-native-chat branch 2 times, most recently from 4f5bd1f to 9d4018c Compare October 14, 2026 07:42

@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: 41ddb650-64f5-446d-9f92-0b61548d700b
📥 Commits

Reviewing files that changed from the base of the PR and between 4f5bd1f and 9d4018c.

⛔ Files ignored due to path filters: 1
  • src/shared/rpc-contract/rpc-params-catalog.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing: 10
  • mobile/src/host-screen/host-server-workspaces-wiring.test.ts
  • mobile/src/host-screen/use-host-worktree-actions.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-create.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-delivery.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
  • src/main/runtime/agent-session-record-founding.ts
  • src/main/runtime/rpc/methods/worktree-sleep-method.ts
  • src/main/runtime/rpc/methods/worktree.ts
  • src/renderer/src/i18n/locales/en.json
  • src/shared/rpc-contract/structured-agent-session-params.ts
🚧 Files skipped from review as they are similar to previous changes: 1
  • src/renderer/src/i18n/locales/en.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review.

Comment thread mobile/src/host-screen/use-host-worktree-actions.ts Outdated

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

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟡 Minor · Preserve active teardown counts when forgetting a worktree. · worktree-sleep-intent.ts:87-114

src/renderer/src/lib/worktree-sleep-intent.ts:87-114
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Preserve active teardown counts when forgetting a worktree.

withWorktreeSleepTeardown keeps a finalizer pending during terminal shutdown. If deletion forgets the worktree, then the same repo::path is recreated and starts another teardown, the old finalizer decrements the recreated worktree's count and removes it. A later PTY bind can then clear the new sleep intent while terminal shutdown is still active.

Suggested fix
     intents.delete(key)
-    teardownCounts.delete(key)
     listeners.delete(key)

ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1631169b-b705-4add-866f-dd4885f7d62d
📥 Commits

Reviewing files that changed from the base of the PR and between 9d4018c and a9aef85.

📒 Files selected for processing: 2
  • src/renderer/src/lib/worktree-sleep-intent.ts
  • src/renderer/src/store/slices/workspace-activation-preparation.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

@brennanb2025

brennanb2025 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor Author

Status (head 9439a9e4f6f524ebf98d704693fc7585c922339c): review done, live QA passed, full PR workflow green.

This head is 5b829e9 plus one merge of main. The merge's only conflict was in the session host's setup, where one field main removed was dropped to match. Live QA ran on 5b829e9; the full PR workflow passed on this head, after one rerun of a job that failed uploading its build artifact.

Why the PR changed since round 9: main merged #30047, which makes Sleep act on the whole workspace. When the same workspace is open on two hosts, Sleep on either copy sleeps both, after a confirmation. This PR had made Sleep act on one host's copy, which broke that confirmation flow. It was re-planned and rebuilt onto main's model. Sleep now asks every host that has a copy to stop its chats. Main's terminal-owner check, confirmation and teardown order stay as they are on main. The rebuild removed about 300 production lines of per-host handling.

Rounds 10–11 reviewed the rebuild, and every finding is fixed and re-verified:

  • an old Sleep could stop a reply sent after waking the workspace. Chat stops are now admitted when terminal teardown is admitted, and a later send still resumes the chat;
  • a VM was suspended before its chats stopped. It now suspends after they have;
  • cleanup after a failed Claude start could lose its exit proof, so a second Sleep reported a failure;
  • after a proven exit, a failed Claude start stayed recorded, so the next message was refused. It is now retired, about 4 lines.

Three-model design panels settled the ordering and retirement calls, and independent host and flow reviewers agreed on each fix. The loop's fixer finished with CI green. The wrap-up (a final main sync and QA) was run by the lane coordinator after the loop session went idle.

Live QA on this head: a hidden test copy on the M4Air, real signed-in Claude, Codex driving the UI, with main 70d00aa as the comparison on the same input.

  • Main: Sleep is greyed out for a chat-only workspace, and a mixed Sleep leaves the chat's claude running.
  • This PR:
    • chat-only Sleep: claude exits 0.46 s later and the host lists the chat as stopped. There's no toast, and reopening shows the history and gets a reply;
    • mixed Sleep: the chat and the terminal's processes all stop within 0.54 s.

Screenshots are in the PR description.

The QA rig left out --password-store=basic --use-mock-keychain, so the test copies may have used the M4Air's real keychain. The real settings.json and hooks.json were unchanged.

CI on this head: the full PR workflow passes. An earlier floating-terminal test failure came from main and was fixed there (#30568).

Pre-existing, not from this PR:

  • three real-Claude CLI tests fail on model names, because the installed CLI now reports newer IDs (those files are unchanged from main);
  • an SSH workspace reads Active about 1.5 s after Sleep.

Disclosed limitation: a workspace open on two hosts with no terminal bound in this window keeps main's "can't tell which host" refusal. That includes one with only chats.

@brennanb2025
brennanb2025 force-pushed the brennanb2025/sleep-stops-native-chat branch 4 times, most recently from 06217f7 to 1d79a56 Compare October 15, 2026 03:28
Sleeping a workspace stopped terminals and browsers but never its structured (native)
chats, so their claude/codex process kept running, and Sleep was disabled for a
workspace whose only content was a chat.

Sleep now stops each chat's agent through a new agentSession.sleep (the host's close,
keeping the tab), routed to the host recorded on the chat's tab; an older host without
the capability fails Sleep with a clear message. The Sleep menu counts a chat.
Main split runSleepWorktrees into sleepWorktreesReportingFailures (no toast) and
a toasting wrapper. Move the native chat stop, host routing and typed failures
into the shared core so the WSL move's Sleep request also stops chats, and
report every workspace not verifiably slept (an unconfirmed chat stop included)
in failedWorktreeIds. Fold one ACP adapter field onto a line so main's file plus
this PR's ownership check stays within the file length limit.
@brennanb2025
brennanb2025 force-pushed the brennanb2025/sleep-stops-native-chat branch from 685ac16 to ba9385a Compare October 15, 2026 14:12
Main grouped the PTY connection suites (#29193) and moved this file to a .spec.ts registered from pty-connection-spawn-and-startup.test.ts. Taking main's copy here keeps the following main merge free of a modify/delete conflict; this PR's test changes are reapplied after the merge.
…n under its line limit

The deliberate-sleep spec moved in #29193; this carries the PR's changes into it: a pane mounted after wake waits for issued teardown, an unqualified pane waits for every same-id host's teardown, and a queued startup waits too.

The merge left claude-structured-session-acquisition.ts over 300 lines. resolveClaudeAcquisitionError, which already builds the exit-unproven error, now decides whether to release the acquisition.
…ops-native-chat

# Conflicts:
#	src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
#	src/main/runtime/rpc/methods/structured-agent-session.ts
#	tests/e2e/cross-version-wire/structured-agent-session-surface-manifest.ts
…ops-native-chat

# Conflicts:
#	src/main/runtime/rpc/methods/structured-agent-session.ts
…ops-native-chat

# Conflicts:
#	src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
#	src/main/runtime/revisioned-state.ts
#	src/main/runtime/workspaces/workspace-selectors.ts
#	src/renderer/src/components/native-chat/StructuredAgentSessionStatusBridge.test.tsx
#	src/renderer/src/components/sidebar/sleep-worktree-flow.ts
#	src/renderer/src/components/sidebar/use-worktree-context-menu-commands.ts
…ops-native-chat

# Conflicts:
#	src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
@brennanb2025
brennanb2025 merged commit 7dcb7d4 into main Oct 19, 2026
91 of 93 checks passed
nwparker added a commit that referenced this pull request Oct 19, 2026
…er pages everywhere, headless sleep stops terminals (#30715)

* fix(runtime): one owned-session teardown policy; removal closes host browser pages everywhere, headless sleep stops terminals

A declared table says what each entry point (worktree, folder and project removal,
sleep, disconnect) does to each owned kind (PTY, native chat, host browser page,
launch record), so a new kind is a compile error until decided. Removal over desktop
IPC and repo.rm now close the host's browser pages and launch records like the
runtime removal; worktree.sleep with no renderer sleeps the host's terminals instead
of doing nothing. Sleep->chat is declared pending #28445; disconnect stops nothing.

* fix(runtime): project removal finds headless pages and failed launches without a client page; stub the new runtime method

* fix(runtime): headless sleep rejects an unproven stop; read headless page owners through the bridge, not Electron
brennanb2025 added a commit that referenced this pull request Oct 19, 2026
…ity, held-send revert

Sleep (#28445) closes a workspace's chats through the same abort a close gives a
registered start, re-aborts a start registered while it waited for the lane, and
judges its receipt once the start it aborted has settled, so only a newer start
reads as later work. Each adapter's owned-acquisition check covers the child it
owns between acquire and open. Main's Sleep cases from the deleted surface
lifetime suite move to the workspace Sleep suite, plus one for a starting agent.

Codex (#30406): the split open sends the chat's command env overrides when it
opens the thread; the adapter test keeps that assertion on the open's request.

Revert of #30134 (#30572): the event sink, exit observation, Pi held-send wrapper
and adapter heldSends overrides go with it; Pi dispatch submits through its
turns again and its idle report is wired back.
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