Skip to content

Fix exited Cloud terminals and shell runtime lifetime - #12492

Closed
lawrencecchen wants to merge 6 commits into
mainfrom
feat-cloud-terminal-lifecycle
Closed

lawrencecchen wants to merge 6 commits into
mainfrom
feat-cloud-terminal-lifecycle

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

Current development build

Open clife5ea from PR commit 5eaec1175d11a9a5f2bdcc65a09579e3e9c0bff5.

  • Fleet job: 45fa9beaa138571b8ae7f59b on cmux10s-Mac-mini.local, completed in 694 seconds.
  • Cloud enabled; the app uses its dedicated GCP backend with direct Tailscale transport. Sign-in returns HTTP 200.
  • Artifact SHA-256: e3a01321a362ce43457a8f83d1e7bf1d8f3e6b60b024fc26f3a0c4dcb1ac250b.
  • Cleanup receipt: job workspace reset, shared cache retained, 240.26 GiB free after cleanup.
  • Submission and terminal receipts: artifacts/fleet/12492-5eaec1175d11/submit.json and terminal.json in the hq workspace.

Summary

  • Exited cmux-tui terminal records are no longer published as openable Cloud terminal surfaces, even when a stale daemon tab remains. Attached native panes close after the accepted graph removes the terminal. Running detached terminals and stale link states remain safe.
  • Cloud work-user setup now enables systemd lingering, starts the uid-1000 runtime directory, and recreates ble.sh's private runtime directory. Attach also repairs existing machines.
  • The Cloud navigation callback type is marked escaping, and Cloud layout comparison uses Bonsplit's public tab UUID accessor. These prerequisite fixes keep the touched app code buildable on the current base.

Evidence

  • Reported machine lawrence-blog was repaired in place. The original Bash process stayed alive after a separate login closed. /run/user/1000/blesh was restored as cmux:cmux mode 0700, and systemd lingering is enabled.
  • The exact attach bundle returned successfully with a trusted listener after the repair.
  • An isolated real ble.sh PTY accepted input after an unrelated login closed, printed no missing-file errors, and exited cleanly. Evidence: cmux-assets/feat-cloud-terminal-lifecycle/runtime-proof.json and runtime-proof.txt.
  • The reported exited tab was removed. Two running terminals were preserved.
  • The exact production parser and pane-closure tests fail with the old parser and pass with the fix. The fixed run used the actual production sources and CmuxCore/CmuxFoundation dependencies on a leased Mac: 2 tests, including 2 lifecycle parameter cases, passed.
  • Web validation passes: 60 tests, bun run typecheck, and bun run lint:complexity.

Testing limits

  • Full cmux-unit CI is blocked by unrelated current-base compile errors in CloudWorkspaceRenameService+Reconciliation.swift, CloudTreeTerminalNavigationCoordinator.swift, DockSplitStore+PaneFocus.swift, and CloudWorkspaceLayout/file-delivery files across earlier base runs. The current PR check is semantic-delivery-integration / tests, which fails in CloudWorkspaceRenameService+Reconciliation.swift before the selected tests run.
  • The tagged macOS app bundle exists at the local tag path and the remote app launched with signed-in personal auth. The isolated development backend had no VM records, so the Cloud row screenshot path could not be exercised without creating a billed VM. The app could list the empty Cloud catalog. The test app, reverse tunnels, credentials, VM backend stack, and fleet lease were cleaned up.

Commits

  1. Public Bonsplit UUID prerequisite.
  2. Behavioral regression tests only.
  3. Lifecycle and runtime-directory fixes.

Summary by CodeRabbit

  • Bug Fixes

    • Exited terminals are no longer shown as openable resources, even when stale tabs remain.
    • Terminal panes now close correctly when a terminal exits while preserving relevant exit history.
    • Existing terminal sessions are more reliably restored after reconnecting or restarting.
  • Reliability

    • Improved virtual machine session setup and recovery by ensuring required user runtime services and directories are active.

@lawrencecchen
lawrencecchen deployed to cloud-vm-image-checks September 13, 2026 05:48 — with GitHub Actions Active
@vercel

vercel Bot commented Sep 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cmux166 Canceled Canceled Sep 13, 2026 7:44am UTC
cmux41 Canceled Canceled Sep 13, 2026 7:44am UTC

@coderabbitai

coderabbitai Bot commented Sep 13, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 5c2900ed-e250-483e-b335-f53291ce33d7

📥 Commits

Reviewing files that changed from the base of the PR and between 9c2ba78 and efca6db.

📒 Files selected for processing (5)
  • Sources/Surfaces/CmuxTuiSnapshotParser.swift
  • cmuxTests/CmuxTuiSurfaceProviderTests.swift
  • web/scripts/verify-devbox-image.ts
  • web/services/vms/drivers/cmuxTuiDaemon.ts
  • web/services/vms/images/workUser.ts

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


📝 Walkthrough

Walkthrough

The parser now excludes all exited terminals from openable resources while retaining exit records and stale tabs. Tests cover pane closure behavior. VM setup and attach commands now establish persistent work-user runtime state, and image verification checks that state.

Changes

Terminal lifecycle handling

Layer / File(s) Summary
Exited terminal resource filtering
Sources/Surfaces/CmuxTuiSnapshotParser.swift
Targeted and compatibility snapshot paths now exclude terminals with an exited lifecycle from openable resources.
Terminal lifecycle and pane closure tests
cmuxTests/CmuxTuiSurfaceProviderTests.swift
Tests verify that exited terminals with retained tabs are excluded, exit records and stale tabs remain indexed, and pane closure depends on snapshot freshness.

Work-user runtime setup

Layer / File(s) Summary
Persistent runtime setup and attach repair
web/services/vms/images/workUser.ts, web/services/vms/drivers/cmuxTuiDaemon.ts
Work-user setup enables lingering, starts the user runtime, creates the blesh runtime directory, and runs the repair from attach bundles.
Runtime state verification
web/scripts/verify-devbox-image.ts
Image verification checks lingering, the per-user runtime service, and /run/user/<uid> ownership and mode.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Suggested reviewers: austinywang


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux User-Facing Error Privacy ❌ Error The attach change can expose raw system-service diagnostics in a user-facing API error. cmuxTuiAttachBundleCommand now runs loginctl, systemctl, and install, then exits on failure. The existin… Keep runtime-repair stderr server-side. Do not include the attach bundle's raw stderr/stdout in ProviderError or in the public reason and details.providerMessage; return stable generic attach failure copy and log bounded diagnostics i…
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 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.
Cmux Cloud Persistent Session And Early Input ✅ Passed The diff does not introduce any listed Cloud persistent-session or early-input violation. It only filters exited terminal records from resource publication and adds idempotent remote work-user runtime…
Cmux Swift Actor Isolation ✅ Passed PASS. The only production Swift file changed is Sources/Surfaces/CmuxTuiSnapshotParser.swift. The diff adds local SurfaceLifecycle value computation and exit filtering in an existing Sendable pa…
Cmux Swift Blocking Runtime ✅ Passed PASS. The authoritative diff changes one production Swift file, Sources/Surfaces/CmuxTuiSnapshotParser.swift. Its changes only filter exited terminals and reuse a computed lifecycle value. They add …
Cmux Browser Automation Off-Main ✅ Passed PASS. The PR changes five files covering cmux-tui parsing/tests and Cloud work-user runtime setup. It does not change Sources/TerminalController.swift or ControlCommandExecutionPolicy.swift. No added …
Cmux Expensive Synchronous Load ✅ Passed PASS. The only production Swift change is in CmuxTuiSnapshotParser.swift. It adds lifecycle guards and removes retained-tab resource construction for exited terminals. The diff adds no `RestorableAg…
Cmux Cache Substitution Correctness ✅ Passed No cache substitution is introduced. The Swift diff only changes lifecycle filtering in existing snapshot projection paths. The targeted path still reads state.lookupIndex, which is a materialized i…
Cmux No Hacky Sleeps ✅ Passed The covered TypeScript changes introduce no fixed sleep, timer, polling loop, delayed dispatch, or wall-clock wait. The new runtime repair uses loginctl enable-linger, `systemctl start user-runtime-…
Cmux Algorithmic Complexity ✅ Passed PASS. The production diff does not introduce a complexity violation. In CmuxTuiSnapshotParser.swift, the new lifecycle guards add constant-time work and move before existing terminal/tab scans; the …
Cmux Swift Concurrency ✅ Passed PASS. The authoritative diff changes only synchronous logic in Sources/Surfaces/CmuxTuiSnapshotParser.swift and adds synchronous lifecycle tests in cmuxTests/CmuxTuiSurfaceProviderTests.swift. The…
Cmux Swift @Concurrent ✅ Passed PASS. The Swift diff changes only synchronous resource filtering in CmuxTuiSnapshotParser.resources(...) and synchronous regression tests. It adds no nonisolated async, @concurrent, actor-isolat…
Cmux Swift Package Boundaries ✅ Passed PASS. The only production Swift change is a small update to the existing Sources/Surfaces/CmuxTuiSnapshotParser.swift: it computes the existing lifecycle value and filters exited terminals in two ex…
Cmux Swiftpm Lockfiles ✅ Passed PASS: The authoritative PR diff changes only two Swift source/test files and three TypeScript files. It does not change any Package.swift, Package.resolved, Xcode project/workspace, .gitignore, workfl…
Cmux Swift Logging ✅ Passed The Swift diff changes terminal lifecycle filtering and tests only. It adds no print, debugPrint, dump, NSLog, Logger, or ad hoc diagnostic output. The existing output and file-writing refer…
Cmux Full Internationalization ✅ Passed PASS — the authoritative PR diff adds no user-facing Swift text, localization key, string-catalog entry, web UI copy, API response copy, metadata, or locale-dependent data. The Swift changes alter ter…
Cmux Swiftui State Layout ✅ Passed PASS. The pull request changes only Sources/Surfaces/CmuxTuiSnapshotParser.swift and cmuxTests/CmuxTuiSurfaceProviderTests.swift on the Swift side. The changed parser code is a pure Sendable dat…
Cmux Architecture Rethink ✅ Passed PASS. The Swift diff is a small projection correctness fix. It excludes exited terminals in the existing full-snapshot and targeted-resource paths, while retaining the terminal and tab records in `Clo…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS: The PR changes only terminal parsing and test fixtures in Swift. It adds no NSWindow, NSPanel, NSWindowController, SwiftUI Window, WindowGroup, close-shortcut routing, or cmux.* identifier assig…
Cmux Source Artifacts ✅ Passed PASS. The authoritative diff changes only five existing hand-written Swift and TypeScript source/test files. The changes implement terminal lifecycle behavior, runtime setup, attach repair, image veri…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS. The review range changes one production Swift file: Sources/Surfaces/CmuxTuiSnapshotParser.swift. Its added code only derives terminal lifecycle values and skips .exited resources. It adds n…
Title check ✅ Passed The title clearly summarizes both primary changes: exited Cloud terminal handling and shell runtime lifetime fixes.
Description check ✅ Passed The description provides a detailed summary, testing evidence, known testing limits, and commit context. It does not use all template sections: it omits the Demo Video, Review Trigger, and Checklist s…
Full details: Cmux User-Facing Error Privacy

Explanation

The attach change can expose raw system-service diagnostics in a user-facing API error. cmuxTuiAttachBundleCommand now runs loginctl, systemctl, and install, then exits on failure. The existing attach failure path includes up to 500 characters of the guest command's stderr in ProviderError. The provider error responder then places that message in the API reason and details.providerMessage; its sanitizer does not remove systemd unit names, runtime paths, or other raw command output. This pull request therefore activates a prohibited command-output and internal-detail leak. The parser and test-only changes do not add such text.

Resolution

Keep runtime-repair stderr server-side. Do not include the attach bundle's raw stderr/stdout in ProviderError or in the public reason and details.providerMessage; return stable generic attach failure copy and log bounded diagnostics internally. Add a regression test with a failing runtime command whose output contains systemctl, user-runtime-dir@1000.service, or /run/user/1000, and assert that the API error body contains none of those values.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@lawrencecchen
lawrencecchen force-pushed the feat-cloud-terminal-lifecycle branch from 907ece0 to 3c9d224 Compare September 17, 2026 23:00
@lawrencecchen
lawrencecchen deployed to cloud-vm-image-checks September 19, 2026 00:05 — with GitHub Actions Active
@blacksmith-sh

This comment has been minimized.

@lawrencecchen
lawrencecchen marked this pull request as ready for review September 19, 2026 01:45
@lawrencecchen
lawrencecchen deployed to cloud-vm-image-checks September 19, 2026 04:04 — with GitHub Actions Active
@cursor

cursor Bot commented Sep 19, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@lawrencecchen
lawrencecchen deployed to cloud-vm-image-checks September 19, 2026 04:28 — with GitHub Actions Active
@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Fleet build instructions for this PR, head c59d03ef9ae7505c22648ee7617da6819ecd42ec:

JOB_JSON=$(~/.local/bin/cmux-ci submit --kind cmux --command 'CMUX_FLEET_BUILD_TAG=pr-12492-c59d03ef /Users/Shared/cmux-build-fleet/recipes/cmux.sh https://github.com/manaflow-ai/cmux.git c59d03ef9ae7505c22648ee7617da6819ecd42ec' --artifact artifacts/cmux.app.zip --workspace https://github.com/manaflow-ai/cmux/pull/12492 --source-digest c59d03ef9ae7505c22648ee7617da6819ecd42ec --cache-key cmux:pr-12492 --min-free-bytes 268435456000 --label cmux --label ram48)
JOB_ID=$(python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' <<<"$JOB_JSON")
~/.local/bin/cmux-ci wait "$JOB_ID" --receipt artifacts/fleet/$JOB_ID.json
~/.local/bin/cmux-ci publish-hq "$JOB_ID"

The job survives disconnects. Do not resubmit after a wait timeout; rerun cmux-ci wait with the same ID. The artifact receipt records worker, queue/build/package/upload times, cache state, and disk before/after cleanup. The build is exact-head and does not include uncommitted edits.

@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Verified macOS fleet artifact for c59d03e: pr-12492-c59d03ef. HQ restores/downloads this exact artifact on click.

Job a0ae78659eba054816e1eb33. Active execution/cleanup: 756.0s; queue/setup: 3.0s. Free disk: 312.3 → 312.3 GiB. Workspace reset: True.

This proves a macOS app build and publication; it does not prove iOS, tests, or UI behavior. Fetch the durable receipt with cmux-ci wait a0ae78659eba054816e1eb33 --receipt artifacts/fleet/a0ae78659eba054816e1eb33.json. Do not resubmit this completed build. If the head changes, rebuild the new exact SHA.

@lawrencecchen
lawrencecchen deployed to cloud-vm-image-checks September 20, 2026 04:52 — with GitHub Actions Active
@greptile-apps

greptile-apps Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no actionable correctness, security, or repository-rule violations were identified.

Summary

This PR fixes Cloud terminal lifecycle publication and repairs persistent work-user runtime state.

  • Excludes exited terminal records from full and targeted Cloud resource publication, including records with retained stale tabs.
  • Adds regression coverage for exited-terminal filtering and attached-pane closure.
  • Enables systemd lingering, starts the uid-1000 runtime directory, and restores ble.sh runtime ownership during image setup and attach.
  • Extends image verification to assert the persistent runtime contract.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Snapshot[cmux-tui snapshot or delta] --> Lifecycle{Terminal lifecycle}
    Lifecycle -->|running| Resource[Publish Cloud terminal resource]
    Lifecycle -->|exited| History[Retain terminal exit record]
    History --> Remove[Omit resource from accepted graph]
    Remove --> Close[Close attached native pane when graph is current]

    Attach[Cloud attach request] --> Runtime[Repair uid-1000 runtime state]
    Runtime --> Linger[Enable systemd lingering]
    Linger --> UserDir[Start user-runtime-dir service]
    UserDir --> Blesh[Restore private ble.sh directory]
    Blesh --> Probe[Probe daemon and trusted listener]
Loading

Reviews (1) · Last reviewed commit: "Merge branch 'main' into feat-cloud-term..."

@teamleaderleo

Copy link
Copy Markdown
Collaborator

Superseded by the Cloud terminal lifecycle and recovery work now in main, including #15116 and the CmuxCloud extraction.

This branch was successfully deployed

3 active (2 outdated) deployments
cloud-vm-image-checks — 5eaec117 Deployed Sep 20, 2026 by lawrencecchen via reachable #371
Preview – cmux41 — 907ece0b Deployed Sep 13, 2026 by vercel[bot]
Preview – cmux166 — 907ece0b Deployed Sep 13, 2026 by vercel[bot]
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.

2 participants