Create and refresh local WSL tmux sessions - #91
Conversation
Sessions created outside Ghosthub should appear promptly without turning host discovery into a polling loop. Matching the Swift application's activation-driven behavior keeps discovery responsive while preserving explicit Retry and Connect authority for failed or disconnected hosts. Reusing the already-admitted host avoids repeating tmux verification each time the window regains focus, and retaining cached rows keeps active navigation usable during the refresh. Validation: the live WSL workspace suite passed all seven lifecycle cases. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
An attach-only client forced users out to another terminal just to bootstrap a local workspace. Let a ready WSL host create or atomically attach to one named tmux session while keeping tmux in charge of process lifetime and preserving the existing terminal presentation during failure. Creation authority is consumed exactly once and is demoted to ordinary attach identity after live discovery. Races attach to the existing exact-name session, while ambiguous failures never rerun creation or gain cleanup authority. Validation: isolated live WSL tests created the first session in an empty namespace and proved an external same-name creation race retained the exact existing identity. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
The creation dialog treated its untouched state as an error, offered no visible focus feedback, and briefly revoked creation whenever an activation refresh marked an admitted host as connecting. That made a routine local action feel broken even while the underlying host remained usable. Keep the selected endpoint pinned while permitting the existing admitted capability through background refresh. Disconnected, unavailable, and changed endpoints remain blocked so better interaction feedback does not weaken host identity boundaries. Validation: isolated live WSL tests created a first session and preserved the exact existing identity across a same-name creation race. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
The sidebar should prioritize workspace navigation, while distro and endpoint configuration belongs in settings and endpoint-specific safety surfaces. Repeating the configured distro under the logical WSL host made the primary navigation taller and visually heavier than the Swift application. Keep endpoint identity in the window title, creation flow, diagnostics, and retained-session qualification, but render the persistent host entry as one compact logical-host row. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
The Rust dialog mixed endpoint configuration, validation, and lifecycle policy into one prominent line, making the WSL substrate look like the product identity and obscuring the actual creation decision. The shipped Swift sheet already defines a clearer hierarchy for this workflow. Use the same generic title, logical-host validation language, terminal-marked input, and subdued ownership footer so the two native applications communicate the same model without exposing implementation detail as chrome. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
Routine creation should ask for the required name and expose the decision, not teach endpoint routing or session ownership. Explanatory policy copy made a small modal taller and noisier while competing with the only feedback users need there: actionable validation errors. Keep lifecycle and host configuration semantics in documentation and settings-oriented surfaces. The creation modal now remains silent for empty and valid input and speaks only when the user must correct something. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
The session-row close affordance must not masquerade as detach when the shipped product treats it as the only destructive session action. Require a fresh live identity before presenting confirmation, then let tmux compare the server PID, session ID, and creation time atomically so a same-named replacement can never be killed from cached inventory. Cancellation and every lookup, runtime, identity, or command failure leave the presentation open. A successful kill removes only the matching presentation and refreshes WSL inventory; ordinary navigation and application shutdown remain detach-only.\n\nValidation: the isolated live WSL lifecycle suite proved cancel preserves the session, a same-named replacement survives stale confirmation, and a second fresh confirmation kills only that replacement.\n\nGenerated with Codex\nCo-authored-by: Codex <noreply@openai.com>
A requested session name is only intent, not proof of what an atomic new-session -A client actually entered. Hooks may rename a new session, and a same-name replacement may appear before discovery, so granting presentation authority from the name could reject the real client or attach state to the wrong server object.\n\nHave the ordinary client report its stable tmux identity, preserve existing session environments on the raced attach path, and publish the resulting inventory against the latest compatible WSL runtime generation. This keeps creation one-shot while making rename, replacement, and concurrent-refresh races explicit.\n\nValidation: isolated WSL tests proved a real after-new-session rename follows the creating client, an existing-session race preserves exact identity, and new-session -A -E retains the session environment.\n\nGenerated with Codex\nCo-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
User-created names cross a tmux format-aware boundary, so separate argv handling alone is not sufficient to rule out format jobs. The session tree also needs to distinguish closing Ghosthub's client from destroying server-owned work, particularly while cached inventory remains visible during host failure. Reject format syntax before creation authority exists, keep retained presentations restorable without enabling stale fresh attaches, and serialize successful kill cleanup with navigation so a concurrent switch cannot close an unrelated client. Validation: an isolated real-WSL tmux test verified a format-job-shaped name cannot create its sentinel file. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
WSL distributions can share kernel identity and can occasionally report colliding init start values. Runtime identity alone therefore cannot prove that cached tmux capability evidence belongs to the distro currently selected by default resolution. Require both the resolved endpoint and runtime to match before reusing admission, so a distro change always re-establishes the tmux capability boundary. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
CreateOnce cannot be retried safely after a terminal startup failure, so assuming xterm-256color could consume creation authority before the client reports its identity. Admission now proves the same atomic client shape and binds the supported TERM to the admitted WSL endpoint and runtime before creation begins.\n\nThis preserves full color on normal distributions while minimal installations use the proven xterm baseline and existing reduced-color notice without rerunning creation.\n\nValidation: an isolated real WSL lifecycle test reached the client identity marker, detached, and preserved the exact session. Generated with Codex\nCo-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
The attaching view previously appeared before tmux creation had any reserved lifecycle state. A session switch could invalidate the background task without finding anything to cancel, leaving navigation stranded in Attaching.\n\nTreat pending creation as an explicit cancellable reservation whose fallback ownership promotes atomically into the ordinary attachment state. Superseding navigation restores inventory immediately, while any late background completion remains generation-stale and cannot publish. Generated with Codex\nCo-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
Kill confirmation is meaningful only while its live-identity request remains the current destructive operation. Checking generation outside the confirmation lock allowed cancellation, navigation, or a newer request to race stale UI authority back into view.\n\nUse the pending-kill lock as the linearization boundary for generation changes and publication, while retaining a defensive generation filter at read time. Detach now also consumes and cancels pending creation so closing an attaching presentation cannot leave WSL work or stale workspace authority behind. Generated with Codex\nCo-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
Discovered tmux names are untrusted display data, and passing one back through a target expression lets tmux interpret format syntax before destructive confirmation. Fresh authority must therefore come from identity-bearing inventory rather than a second name-targeted command.\n\nMatch the length-framed all-session result in Rust and carry only the captured stable identity into the conditional kill. Reserve destructive-request generation before validation as well, so every newer user intent supersedes older identity queries even when the new request is rejected.\n\nValidation: an isolated real WSL lifecycle test confirmed that a replaced session survives stale confirmation and only a newly captured identity is killed. Generated with Codex\nCo-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
WSL attachment, creation, guarded kill, and client-lifetime behavior cross a real Windows/ConPTY/WSL2 boundary that ordinary cargo test intentionally skips. Those contracts need repeatable acceptance evidence without making fast pull-request CI depend on a hosted runner configuration that does not guarantee a usable WSL2 distro. Keep the live suites isolated behind one documented Make target and a dedicated labeled acceptance workflow, with early runtime and tmux checks so an unsuitable runner cannot produce misleading results. Validation: all 16 ignored terminal and workspace tests passed against the local WSL2 Ubuntu/tmux environment. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
A persistent WSL2 runner is a privileged execution boundary, so branch-selectable dispatch and reusable workflow callers must not be able to place arbitrary Rust build logic on it. Limit dispatch to the canonical rust-port branch, pin checkout to that dispatch's immutable SHA, and route the job through a dedicated runner group whose external policy is scoped to this workflow. Feature branches continue proving the live boundary on isolated developer machines before merge. Validation: actionlint 1.7.10 accepted the hardened workflow. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
A stable tmux session ID that disappears before confirmed deletion prevents if-shell from evaluating its identity mismatch branch. Reporting that as an ordinary missing session hides the important fact that the original name now belongs to different processes. Use the existing length-framed all-session query only for classification after a missing stable target. The destructive command remains identity-targeted, while a same-named different identity receives the replacement diagnostic and survives untouched. Validation: the isolated WSL2 guarded-kill test replaced the confirmed session, observed the replacement diagnostic, preserved it, and then killed it only after fresh confirmation. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
- Keeps local WSL tmux sessions current when the Ghosthub window regains focus, so sessions created elsewhere appear without a manual refresh. - Lets users create the first or an additional local tmux session from the compact `+` action beside a ready WSL host. - Uses one atomic `new-session -A` ordinary client, then captures the exact WSL runtime, tmux server, session ID, and creation time before publishing the terminal. - Preserves the current terminal during refresh and creation, restores it when a new client cannot be established, and never reruns or kills a session after an ambiguous launch. - Keeps SSH and remote lifecycle work out of scope. - Exercises empty-namespace creation and same-name creation races against isolated real WSL tmux servers; the full Rust workspace, Clippy, architecture contracts, strict docs, and license closure pass. Co-authored-by: Wes McKinney <wesm@users.noreply.github.com>
- Keeps local WSL tmux sessions current when the Ghosthub window regains focus, so sessions created elsewhere appear without a manual refresh. - Lets users create the first or an additional local tmux session from the compact `+` action beside a ready WSL host. - Uses one atomic `new-session -A` ordinary client, then captures the exact WSL runtime, tmux server, session ID, and creation time before publishing the terminal. - Preserves the current terminal during refresh and creation, restores it when a new client cannot be established, and never reruns or kills a session after an ambiguous launch. - Keeps SSH and remote lifecycle work out of scope. - Exercises empty-namespace creation and same-name creation races against isolated real WSL tmux servers; the full Rust workspace, Clippy, architecture contracts, strict docs, and license closure pass. Co-authored-by: Wes McKinney <wesm@users.noreply.github.com>
- Keeps local WSL tmux sessions current when the Ghosthub window regains focus, so sessions created elsewhere appear without a manual refresh. - Lets users create the first or an additional local tmux session from the compact `+` action beside a ready WSL host. - Uses one atomic `new-session -A` ordinary client, then captures the exact WSL runtime, tmux server, session ID, and creation time before publishing the terminal. - Preserves the current terminal during refresh and creation, restores it when a new client cannot be established, and never reruns or kills a session after an ambiguous launch. - Keeps SSH and remote lifecycle work out of scope. - Exercises empty-namespace creation and same-name creation races against isolated real WSL tmux servers; the full Rust workspace, Clippy, architecture contracts, strict docs, and license closure pass. Co-authored-by: Wes McKinney <wesm@users.noreply.github.com>
- Keeps local WSL tmux sessions current when the Ghosthub window regains focus, so sessions created elsewhere appear without a manual refresh. - Lets users create the first or an additional local tmux session from the compact `+` action beside a ready WSL host. - Uses one atomic `new-session -A` ordinary client, then captures the exact WSL runtime, tmux server, session ID, and creation time before publishing the terminal. - Preserves the current terminal during refresh and creation, restores it when a new client cannot be established, and never reruns or kills a session after an ambiguous launch. - Keeps SSH and remote lifecycle work out of scope. - Exercises empty-namespace creation and same-name creation races against isolated real WSL tmux servers; the full Rust workspace, Clippy, architecture contracts, strict docs, and license closure pass. Co-authored-by: Wes McKinney <wesm@users.noreply.github.com>
+action beside a ready WSL host.new-session -Aordinary client, then captures the exact WSL runtime, tmux server, session ID, and creation time before publishing the terminal.