Skip to content

Workspaces: span terminals + browser panes (surface persistence)#189

Merged
nedtwigg merged 12 commits into
mainfrom
workspaces
Jun 30, 2026
Merged

Workspaces: span terminals + browser panes (surface persistence)#189
nedtwigg merged 12 commits into
mainfrom
workspaces

Conversation

@nedtwigg

Copy link
Copy Markdown
Member

Summary

Establishes the Workspace/Surface model where a Workspace can span both terminal panes and browser (iframe / agent-browser) panes, and makes session persistence first-class for non-PTY surfaces. A browser Surface has no PTY, scrollback, or registry entry, so save / restore / resume / VS Code PTY-refresh all had to learn to route it differently from a terminal.

Spec/docs pass defines the model (docs/specs/glossary.md, layout.md, transport.md, alert.md, vscode.md, shortcuts.md, …); the code changes implement it.

Key changes

  • surfaceType: 'terminal' | 'browser' persisted per pane. Browser panes are skipped on terminal restore/resume/claim and reconstructed from the dockview layout blob; their PTY-only fields are always blank.
  • Browser-surface TODO is first-class. It lives in a dedicated localSurfaceActivity store rather than the transient primedActivityStates staging map — cleared on kill/replace, never consumed by terminal creation, and a live PTY outranks a stale entry if an id is reused.
  • Shared restoreBrowserSurfaceTodo helper for the cold-restore and live-resume paths (was copy-pasted).
  • Centralized browserPersistedPane() in lib, used by both the renderer save path and the VS Code host refresh, so the persisted browser-pane shape has one source of truth.

Testing

  • npx tsc --noEmit (standalone) — clean
  • Full lib vitest suite — 684 passed, including new coverage for browser-surface persistence, TODO restore/clear, and reused-id precedence.

🤖 Generated with Claude Code

nedtwigg and others added 12 commits June 29, 2026 14:45
Introduce Workspace (one Wall = one Workspace) and Window as containers
in the glossary, with a display-only union projection (ringing/todo/count)
distributed across the area specs:

- glossary: Containers section (Window/Workspace), union status, verbs
  (switch/create/close/rename), invariants I7-I9, naming conventions
- alert: Workspace union projection (derived, includes Doored + inactive)
- layout: standalone workspace strip, switching, lifecycle, persistence
- transport: PersistedWorkspace/PersistedWindow container + v3 migration
- vscode: webview-to-Workspace mapping, union reflection onto tab
  icon/title and view badge; "not yet implemented" bullet
- dor-cli: workspace:<n|name> / window:<n> handle refs
- shortcuts: rename "Workspace mode" -> "Command mode" (frees the word)
- DESIGN / AGENTS / mobile-ui: index + navigation updates

Spec-only; UI visuals and keybindings deferred to the Storybook pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ser panes

Reconcile the glossary's terminal-centric "Session" model with the newer
browser-surface model (iframe + agent-browser). Promote **Surface** to the
canonical durable unit; a terminal Surface is a **Session** (keeps all six
axes), a browser Surface is the other kind (View + Snapshot + TODO-only
Activity). Adopt the hierarchy the dor CLI already commits to:
Window ⊃ Workspace ⊃ Pane ⊃ Surface.

- glossary: new "Panes and Surfaces" section (Pane/Surface nouns, surface
  kinds, per-kind axis table, containment hierarchy, surface-identity I10);
  Containers/union/View/Activity/verbs/invariants/retired-terms/naming all
  reworded over Surfaces; union carries terminal ring + (terminal|browser) TODO
- alert: union projects over Surfaces; browser surfaces carry TODO, never ring
- layout: conceptual model leads with Pane→Surface; switching/lifecycle and
  "pane IDs are session IDs" qualified to terminal Surfaces
- transport: PersistedPane carries surfaceType + render params, closing the
  cold-restore stray-PTY bug and the resume drops-browser-panes bug
- vscode: a Workspace's Surface set = owned PTYs + browser surfaces; union
  scoped to Surfaces (browser = TODO only)
- dor-cli / dor-browser: Surface is the user-facing handle; defer to glossary
- shortcuts: `t` works on any Surface; `a` is terminal-only
- AGENTS: glossary index bullet documents the Surface model

Spec-only; persistence/union wiring lands in the code pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-on to aa72731 (Clarify browser TODO alert ownership): the VS Code
"where the union surfaces" bullet still claimed the host reflects the full
union onto native chrome. Scope it to the terminal portion — browser-surface
TODO stays webview-local until a future webview→host Surface-state channel,
matching the now-corrected vscode.md and transport.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make persistence/restore/resume Surface-aware so today's single-workspace app
handles browser surfaces (iframe + agent-browser) correctly, ahead of the
Workspace container (stage 2b). No feature flag — this is pure correctness for
the current app.

- session-types: PersistedPane.surfaceType ('terminal' | 'browser'); absent
  reads as 'terminal' (migration-safe) and is validated in readPersistedSession
- session-save / use-session-persistence: record surfaceType (browser only, to
  keep terminal snapshots byte-identical), from panel params for visible panes
  and door.component for minimized surfaces
- session-restore: skip restoreTerminal for browser panes — fixes the
  stray-PTY-per-browser-pane bug; they rebuild from the dockview layout blob
- reconnect: keep browser surfaces (visible + doored) in the resume plan so the
  saved layout still matches and isn't discarded — fixes the
  resume-drops-browser-panes bug

Browser-surface TODO already round-trips live via the AlertManager (the `t`
shortcut creates an entry for any id, which primes into the activity store);
added a test locking that behavior. Its cross-restart persistence and union
counting are stage 2b.

Spec: mark the Workspace/Window container, union projection, and strip as not
yet implemented (stages 2b/3/4) across glossary/transport/layout/alert/vscode;
glossary gains an Implementation-status section. The surfaceType + restore/
resume fixes are documented as implemented (stage 2a).

Tests: +6. Full lib suite green (678), tsc -b clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… pane record

- Move browser-surface TODO out of the transient primedActivityStates map into a
  dedicated localSurfaceActivity store (cleared on kill/replace, never consumed
  by terminal creation, live PTY outranks a stale reused-id entry)
- Extract shared restoreBrowserSurfaceTodo helper for the restore/resume paths
- Centralize the persisted browser-pane shape into browserPersistedPane() in lib,
  shared by session-save and the VS Code host refresh

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying mouseterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: 69ab955
Status: ✅  Deploy successful!
Preview URL: https://6b02e614.mouseterm.pages.dev
Branch Preview URL: https://workspaces.mouseterm.pages.dev

View logs

@nedtwigg nedtwigg merged commit 372eba1 into main Jun 30, 2026
9 checks passed
@nedtwigg nedtwigg deleted the workspaces branch June 30, 2026 04:06
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