feat(web): session detach/undock + beta instance isolation (port 5000)#103
Open
Ark0N wants to merge 3 commits into
Open
feat(web): session detach/undock + beta instance isolation (port 5000)#103Ark0N wants to merge 3 commits into
Ark0N wants to merge 3 commits into
Conversation
Detach a session tab into its own browser window and back. Detach/undock: - GET /session/:id serves the SPA in "solo mode", reusing the existing client (terminal, local-echo overlay, reconnect) so no terminal code is duplicated. One PTY already fans out to N SSE/WS clients, so a detached window is just another live client — no server fan-out work was needed. - A pop-out icon per tab; detached tabs show a badge and focus the popup on click; closing the popup re-docks. Cross-window state via BroadcastChannel plus a WindowProxy poll, and survives a dashboard reload (roll-call). app.detachSession(id) is a single idempotent entry point (future gesture hook). <base href="/"> so relative assets resolve under /session/:id. Beta-branch isolation (so it can run alongside a prod Codeman): - Default port 3000 -> 5000. - New src/config/instance.ts derives the data dir and tmux socket from CODEMAN_INSTANCE (default "beta"): ~/.codeman-beta + tmux -L codeman-beta. Every ~/.codeman path now goes through dataPath()/getDataDir() (state, mux-sessions, settings, push keys, lifecycle log, screenshots, certs, linked-cases, subagent window state). Overridable via CODEMAN_INSTANCE / CODEMAN_DATA_DIR / CODEMAN_TMUX_SOCKET. Prevents a second instance from discovering and attaching PTYs to the first instance's live tmux sessions. Verified: tsc / eslint / prettier / lockfile clean; Playwright E2E (27 checks) for detach/solo/redock; default isolation confirmed to see zero real sessions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…instance The instance-isolation sweep routed every ~/.codeman write through dataPath() except the legacy ~/.claudeman → ~/.codeman migration in the StateStore constructor, which stayed hardcoded. Gate the whole legacy block on the default (prod) instance so a named instance (e.g. CODEMAN_INSTANCE=beta) never reads or renames into the shared ~/.codeman / ~/codeman-cases layout. Prod behavior is unchanged (CODEMAN_INSTANCE empty → migration still runs). Note: swapping newDir to getDataDir() was rejected — its mkdirSync side-effect would make !existsSync(newDir) false and silently disable the migration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Finding 2: unify the pop-out icon and tab-click paths via _raiseDetached(). After a dashboard reload (no owned WindowProxy ref), clicking the pop-out icon no longer re-runs window.open() — which reloaded the live popup's terminal — and instead raises it via the channel, matching the tab-click behavior. - Finding 3: debounce channel-driven redock. A popup *reload* emits redocked->detached in quick succession; a 1.5s grace lets the re-announce cancel the redock so the dashboard badge no longer blips on popup refresh. - Finding 4: periodic liveness reconcile. A popup hard-killed without a 'pagehide' (crash / OS kill) while the dashboard holds no ref would leave its tab stuck "detached". The dashboard now re-roll-calls every 5s and re-docks any channel-only tab that stays silent. Frontend-only; validated with node --check (app.js is outside the ts/lint/prettier gates). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Beta branch — opened to run CI; not necessarily for immediate merge.
Session detach / undock
GET /session/:idserves the SPA in "solo mode", reusing the existing client (terminal, local-echo overlay, reconnect) — no duplicated terminal code. One PTY already fans out to N SSE/WS clients, so a detached window is just another live client; no server fan-out work was needed (the brief's "critical question" was already solved).BroadcastChannel+ aWindowProxypoll, surviving dashboard reload (roll-call).app.detachSession(id)is a single idempotent entry point (future gesture hook).<base href="/">so relative assets resolve under/session/:id.Beta instance isolation (run alongside prod)
src/config/instance.ts:CODEMAN_INSTANCE(defaultbeta) derives both the data dir (~/.codeman-beta) and tmux socket (tmux -L codeman-beta). Every~/.codemanpath now routes throughdataPath()/getDataDir(). Overridable viaCODEMAN_INSTANCE/CODEMAN_DATA_DIR/CODEMAN_TMUX_SOCKET. Prevents a second instance from discovering and attaching PTYs to the first instance's live tmux sessions.Verification
tsc/eslint/prettier/ lockfile clean.🤖 Generated with Claude Code