Skip to content

Commit 372eba1

Browse files
authored
Workspaces step 1 - update spec to have a workspace model (#189)
2 parents 9ef3aae + 69ab955 commit 372eba1

25 files changed

Lines changed: 676 additions & 69 deletions

AGENTS.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ pnpm build # build lib, vscode extension, and website
3030

3131
The primary job of a spec is to be an accurate reference for the current state of the code. Read the relevant spec before modifying a feature it covers — the spec describes invariants, edge cases, and design decisions that are not obvious from the code alone.
3232

33-
- **`docs/specs/glossary.md`** — Canonical vocabulary for Session states, layers (Process / Registry / View / Link / Activity / Snapshot), transition verbs, and the Liskov contract on Registry APIs. Read this first. Other specs defer to it when naming a state or a verb.
34-
- **`docs/specs/layout.md`** — Tiling layout, pane/door containers, dockview configuration, modes (passthrough/command), keyboard shortcuts, selection overlay, spatial navigation, minimize/reattach, inline rename, session lifecycle, session persistence, and theming. Read this when touching: `Wall.tsx`, `Baseboard.tsx`, `Door.tsx`, `TerminalPane.tsx`, `spatial-nav.ts`, `layout-snapshot.ts`, `terminal-registry.ts`, `session-save.ts`, `session-restore.ts`, `reconnect.ts`, `index.css`, `theme.css`, or any keyboard/navigation/mode behavior.
33+
- **`docs/specs/glossary.md`** — Canonical vocabulary: the **Surface** model (a Pane's durable occupant — a terminal **Session** or a **browser** surface, with a per-kind axis table), Session states and layers (Process / Registry / View / Link / Activity / Snapshot), the `Window ⊃ Workspace ⊃ Pane ⊃ Surface` containment hierarchy and the Workspace union status, transition verbs, and the Liskov contract on Registry APIs. Read this first. Other specs defer to it when naming a state, a surface kind, or a verb.
34+
- **`docs/specs/layout.md`** — Tiling layout, pane/door containers, dockview configuration, modes (passthrough/command), keyboard shortcuts, selection overlay, spatial navigation, minimize/reattach, inline rename, the standalone workspace strip (tabs, switching, lifecycle), session lifecycle, session persistence, and theming. Read this when touching: `Wall.tsx`, `Baseboard.tsx`, `Door.tsx`, `TerminalPane.tsx`, `standalone/src/AppBar.tsx`, `spatial-nav.ts`, `layout-snapshot.ts`, `terminal-registry.ts`, `session-save.ts`, `session-restore.ts`, `reconnect.ts`, `index.css`, `theme.css`, or any keyboard/navigation/mode/workspace behavior.
3535
- **`docs/specs/dor-cli.md`** - the `dor` CLI which is prepended onto the path of every terminal that dormouse launches.
3636
- **`docs/specs/dor-browser.md`** — The unified `dor` browser surface: a single `BrowserPanel` (`surfaceType: 'browser'`) with a swappable `renderMode` (`ab-screencast` / `ab-popout` / `iframe`). Covers the `dor ab` / `dor agent-browser` screencast viewer that delegates to the user's own agent-browser install (canvas screencast, input forwarding, tabs, pop-out modal) and the `dor iframe` renderer (an `<iframe>` fronted by a host-owned transparent proxy that injects a keyboard side-channel, models focus, and renders real error pages). Builds on the surface handle model in `dor-cli.md`. Read this when touching: `lib/src/components/wall/BrowserPanel.tsx`, `browser-surface.ts`, `browser-url.ts`, `AgentBrowserPanel.tsx`, `IframePanel.tsx`, `SurfacePaneHeader.tsx`, `AgentBrowserScreenModal.tsx`, `lib/src/components/wall/agent-browser-{connection,ports,screen,screenshot-loop,sessions,input}.ts`, `lib/src/lib/agent-browser-tab.ts`, `lib/src/host/agent-browser-host.ts`, `lib/src/host/iframe-proxy.ts`, `iframe-proxy-rewrite.ts`, `lib/src/lib/iframe-proxy-registry.ts`, `lib/src/lib/platform/iframe-proxy-types.ts`, `dor/src/commands/agent-browser.ts`, `dor/src/commands/iframe.ts`, `vscode-ext/src/agent-browser-host.ts`, `vscode-ext/src/iframe-proxy-host.ts`, or the browser surface wiring in `Wall.tsx`.
37-
- **`docs/specs/alert.md`** — Activity monitoring state machine, alert trigger/clearing rules, attention model, TODO lifecycle, bell button visual states and interaction, door alert indicators, hardening (a11y, motion, i18n, overflow), notification protocols (`OSC 9` / `OSC 9;4` / `OSC 99` / `OSC 777` / `BEL`), the `ActivityNotification` model, notification text handling and security, and the notification preview/detail UI. Read this when touching: `activity-monitor.ts`, `alert-manager.ts`, `AlertManager` notification/progress paths, the alert bell or TODO pill in `Wall.tsx` (TerminalPaneHeader), alert indicators in `Door.tsx`, the `a`/`t` keyboard shortcuts, or TODO notification preview UI. Layout.md defers to this spec for all alert/TODO behavior.
37+
- **`docs/specs/alert.md`** — Activity monitoring state machine, alert trigger/clearing rules, attention model, TODO lifecycle, bell button visual states and interaction, door alert indicators, hardening (a11y, motion, i18n, overflow), notification protocols (`OSC 9` / `OSC 9;4` / `OSC 99` / `OSC 777` / `BEL`), the `ActivityNotification` model, notification text handling and security, the notification preview/detail UI, and the Workspace union projection (ringing/todo/count). Read this when touching: `activity-monitor.ts`, `alert-manager.ts`, `AlertManager` notification/progress paths, the alert bell or TODO pill in `Wall.tsx` (TerminalPaneHeader), alert indicators in `Door.tsx`, the `a`/`t` keyboard shortcuts, or TODO notification preview UI. Layout.md defers to this spec for all alert/TODO behavior.
3838
- **`docs/specs/terminal-state.md`** — Terminal semantic state for CWD, shell prompt/editing/running/finished lifecycle, command runs, terminal title fallback, normalized semantic OSC events (`OSC 7`, `OSC 9;9`, `OSC 133`, `OSC 633`, `OSC 1337`, `OSC 0/2`), title-candidate diagnostics, header derivation, and grouping keys. Read this when touching `terminal-state.ts`, `terminal-state-store.ts`, semantic event parsing in `terminal-protocol.ts`, adapter semantic event forwarding, or derived pane/door labels.
3939
- **`docs/specs/terminal-escapes.md`** — Registry of every terminal escape sequence Dormouse parses or responds to: supported OSCs with pointers to the spec defining their behavior (alert.md or terminal-state.md), the canonical parsing-location and `pty:data` strip semantics, supported CSI sequences (`CSI > q`, DECSET/DECRST observation, kitty keyboard protocol) and replay-time CSI filtering, iTerm2 self-identification (env vars, fail-inertly rule), and known-unimplemented iTerm2 and clipboard-capable sequences. Read this when touching: OSC parsing at the PTY data boundary, CSI handlers in `terminal-protocol.ts` / `mouse-mode-observer.ts` / `terminal-report-filter.ts`, the iTerm2 identity env vars (`TERM_PROGRAM`, `LC_TERMINAL`), or adding support for a new escape sequence.
40-
- **`docs/specs/transport.md`** — Adapter-agnostic protocol shared across VS Code, standalone, and fake adapters: PTY lifecycle (decoupled from webview), `replayChunks`/`scrollbackChunks` buffering, reconnection sequence (`dormouse:init``pty:list` + `pty:replay`), the full webview ↔ host message protocol, persisted-session types, and universal invariants (shell login args, scrollback trailing newline, replay drop-replies-only). Read this when touching: `pty-manager.ts`, `pty-host.js`, `pty-core.js`, `message-router.ts`, `message-types.ts`, `vscode-adapter.ts`, `fake-adapter.ts`, `reconnect.ts`, `session-save.ts`, `session-restore.ts`, `session-types.ts`, or any code crossing the webview/host boundary.
41-
- **`docs/specs/vscode.md`** — VS Code-specific layer: hosting modes (WebviewView + WebviewPanel), extension manifest, VS Code persistence flow (`workspaceState`, `vscode.setState`, `WebviewPanelSerializer`, deactivate ordering, `mergeAlertStates` rule, `retainContextWhenHidden`), theme integration (`--vscode-*``--color-*` with the runtime resolver), CSP, build pipeline, and dream-architecture commands. The transport protocol it speaks (PTY lifecycle, message protocol, persisted-session types) lives in `transport.md`. Read this when touching: `extension.ts`, `webview-view-provider.ts`, `session-state.ts`, `webview-html.ts`, the theme resolver/observer in `terminal-theme.ts`, or VS Code commands and context keys.
40+
- **`docs/specs/transport.md`** — Adapter-agnostic protocol shared across VS Code, standalone, and fake adapters: PTY lifecycle (decoupled from webview), `replayChunks`/`scrollbackChunks` buffering, reconnection sequence (`dormouse:init``pty:list` + `pty:replay`), the full webview ↔ host message protocol, persisted-session types (including the `PersistedWorkspace` / `PersistedWindow` container and its migration), and universal invariants (shell login args, scrollback trailing newline, replay drop-replies-only). Read this when touching: `pty-manager.ts`, `pty-host.js`, `pty-core.js`, `message-router.ts`, `message-types.ts`, `vscode-adapter.ts`, `fake-adapter.ts`, `reconnect.ts`, `session-save.ts`, `session-restore.ts`, `session-types.ts`, or any code crossing the webview/host boundary.
41+
- **`docs/specs/vscode.md`** — VS Code-specific layer: hosting modes (WebviewView + WebviewPanel), the webview ↔ Workspace mapping and union-status reflection onto native tab icon/title and view badge, extension manifest, VS Code persistence flow (`workspaceState`, `vscode.setState`, `WebviewPanelSerializer`, deactivate ordering, `mergeAlertStates` rule, `retainContextWhenHidden`), theme integration (`--vscode-*``--color-*` with the runtime resolver), CSP, build pipeline, and dream-architecture commands. The transport protocol it speaks (PTY lifecycle, message protocol, persisted-session types) lives in `transport.md`. Read this when touching: `extension.ts`, `webview-view-provider.ts`, `session-state.ts`, `webview-html.ts`, the theme resolver/observer in `terminal-theme.ts`, or VS Code commands and context keys.
4242
- **`docs/specs/tutorial.md`** — Playground tutorial on the website: 3-pane layout, interactive `tut` TUI runner with three sections (keyboard navigation, alerts/TODOs, copy/paste), per-item detection wired to `WallEvent` / activity store / mouse-selection store, single-key `dormouse-tut-v3` localStorage scheme, theme picker, and FakePtyAdapter extensions (`sendOutput`, `pumpActivity`, `setInputHandler`). Read this when touching: `website/src/pages/PlaygroundDesktop.tsx`, `website/src/pages/PocketPlayground.tsx`, `website/src/components/PocketTerminalExperience.tsx`, `website/src/lib/playground-routing.ts`, the `website/src/pages/Playground.tsx` and `website/src/pages/Pocket.tsx` redirect dispatchers, `website/src/lib/tut-runner.ts`, `website/src/lib/tut-detector.ts`, `website/src/lib/tutorial-state.ts`, `website/src/lib/tut-items.ts`, `website/src/lib/tutorial-shell.ts`, `lib/src/components/ThemePicker.tsx`, `lib/src/lib/themes/`, `lib/src/lib/platform/fake-scenarios.ts` (tutorial scenarios), the `WallEvent` union, or the `onApiReady`/`onEvent`/`initialPaneIds` props on Wall.
4343
- **`docs/specs/theme.md`** — Theme system: two-layer CSS variable strategy, theme data model, conversion pipeline, bundled themes, localStorage store, shared ThemePicker component, standalone AppBar picker, runtime OpenVSX installer. Read this when touching: `lib/src/lib/themes/`, `lib/src/components/ThemePicker.tsx`, `lib/src/theme.css`, `lib/scripts/bundle-themes.mjs`, `standalone/src/AppBar.tsx` (theme picker), `standalone/src/main.tsx` (theme restore), or `website/src/components/SiteHeader.tsx` (themeAware mode).
4444
- **`docs/specs/mouse-and-clipboard.md`** — Terminal-owned text selection, copy (Raw / Rewrapped), bracketed paste, smart URL/path extension, mouse-reporting override UI (icon + banner), and the state matrix for which layer owns mouse events. Read this when touching: `lib/src/lib/mouse-selection.ts`, `lib/src/lib/mouse-mode-observer.ts`, `lib/src/lib/clipboard.ts`, `lib/src/lib/rewrap.ts`, `lib/src/lib/selection-text.ts`, `lib/src/lib/smart-token.ts`, `lib/src/components/SelectionOverlay.tsx`, `lib/src/components/SelectionPopup.tsx`, the mouse icon / override banner / Cmd+C-V handling in `lib/src/components/Wall.tsx`, or the parser hooks + mouse listeners in `lib/src/lib/terminal-registry.ts`.

DESIGN.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ The system uses **raised surfaces**, not "cards." There are no nested cards. The
221221

222222
### Navigation
223223

224-
The system has no traditional top-nav. Two surfaces play navigational roles:
224+
The system has no traditional product top-nav. Three surfaces play navigational roles:
225+
- **Workspace strip** (standalone app bar, top): horizontal tabs, one per Workspace, for switching between Workspaces within one window. Inactive tabs carry the union alert/TODO indicators (bell + TODO pill) borrowed from the Door vocabulary; the active tab carries none. This is standalone app-bar chrome around the Wall — see `docs/specs/layout.md` and `docs/specs/alert.md` — and its exact visual treatment is being designed in Storybook. VS Code surfaces the same status on its own native tab/badge chrome instead (`docs/specs/vscode.md`).
225226
- **Baseboard** (bottom of the app): horizontal strip of doors representing minimized panes plus chrome action buttons. Doors are the primary navigation affordance to a minimized terminal. Button style: `h-5 rounded px-1.5 text-sm font-medium font-mono text-muted` with `hover:bg-surface-raised hover:text-foreground transition-colors`.
226227
- **Pane Header (TerminalPaneHeader)**: the tab-replacing strip at the top of each pane. Tab-bar styling is stripped from dockview entirely (`--dv-tabs-and-actions-container-*` overrides); the React header IS the tab.
227228

docs/specs/alert.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> See `docs/specs/glossary.md` for Session / Pane / Door vocabulary. This spec uses it throughout.
44
5-
Alert state belongs to the **Session** Activity layer. It survives Pane <-> Door movement and is destroyed with the Session.
5+
Terminal alert state belongs to the **Session** Activity layer. It survives Pane <-> Door movement and is destroyed with the Session. This spec also defines how the Workspace union counts browser-surface TODO flags: a browser Surface has no Session Activity machine, can never ring, and carries only a user-set TODO flag as Surface state that is destroyed with that browser Surface.
66

77
Dormouse can owe the user attention in three ways:
88

@@ -22,7 +22,7 @@ Terminal-report and command-exit alerts do not require WATCHING to be enabled. A
2222

2323
## Public State
2424

25-
Source of truth: `AlertState` / `ActivityNotification` in `lib/src/lib/alert-manager.ts` and `SessionStatus` in `lib/src/lib/activity-monitor.ts` define the public Activity state. Internal state is deliberately split into independent tracks (`watchingStatus`, `protocolStatus`, `commandExitStatus`, plus `progress` and `commandExitWatch` companion state) so each axis evolves without entangling the others.
25+
Source of truth: `AlertState` / `ActivityNotification` in `lib/src/lib/alert-manager.ts` and `SessionStatus` in `lib/src/lib/activity-monitor.ts` define the public Activity state for terminal Sessions. Internal state is deliberately split into independent tracks (`watchingStatus`, `protocolStatus`, `commandExitStatus`, plus `progress` and `commandExitWatch` companion state) so each axis evolves without entangling the others.
2626

2727
Public `status` is a projection — first match wins:
2828

@@ -173,6 +173,31 @@ Clearing behavior:
173173

174174
`attentionDismissedRing` exists so the next bell click after an attention-based dismissal opens the dialog instead of silently disabling WATCHING.
175175

176+
## Workspace union
177+
178+
> See `docs/specs/glossary.md` for the Workspace / Window containers.
179+
>
180+
> **Not yet implemented (stage 2b).** The union projection and its surfacing are specified ahead of the code. The implemented piece (stage 2a) is that a browser Surface's user-set `todo` round-trips to the activity store live, so its door shows the TODO pill — the same input the union will read once it exists.
181+
182+
A Workspace projects a **union status** over the attention state of the Surfaces it contains (terminal Sessions and browser Surfaces alike — see `docs/specs/glossary.md`):
183+
184+
- `ringing` — any member terminal Session's public `status` is `ALERT_RINGING`. Only terminal Sessions ring; a browser Surface has no BEL/OSC source and never reaches `ALERT_RINGING`.
185+
- `todo` — any member Surface has `todo === true`. A terminal Session or a browser Surface may be flagged.
186+
- `count` — number of member Surfaces owing attention (ringing or `todo`), for the numeric badge a host may show.
187+
188+
Rules:
189+
190+
- The union is **display-only** and derived. It never enters the terminal Activity state machine, never fires a fresh ring, and produces no sound or notification of its own; it only mirrors member state. Every terminal ringing/TODO transition above remains per-Session, and every browser TODO transition remains per-browser Surface.
191+
- Membership includes minimized (`Doored`) Surfaces and, in standalone, the Surfaces of inactive (unmounted) Workspaces. A terminal Session's Activity survives minimize and unmount (glossary I2/I3) and a browser Surface's `todo` survives in its persisted params, so a backgrounded Surface can light up its Workspace's indicator.
192+
- Attention suppression needs no special-casing: a per-Session ring is already suppressed while that Session is attended, so the union simply reflects whatever rings survive.
193+
194+
Where the union surfaces is host-specific:
195+
196+
- **Standalone:** each inactive Workspace's tab in the strip shows the union `ringing` bell and `todo` pill, reusing the Door indicator vocabulary (`bellIconClass`, the TODO pill). The **active** Workspace's tab shows no union indicator — its rings and TODOs are already visible on its own panes and doors. See `docs/specs/layout.md`.
197+
- **VS Code:** the host reflects the **terminal** portion of each Workspace's union onto the webview's native chrome — an editor tab's icon (and optionally title) and the sidebar view's numeric badge. Browser-surface TODO stays webview-local and is not shown on native chrome until a future webview→host Surface-state channel exists. See `docs/specs/vscode.md`.
198+
199+
This spec fixes the projection and the surfacing rules; the exact visual treatment of the standalone strip is settled in the Storybook UI pass.
200+
176201
## UI Contract
177202

178203
### Pane Header

docs/specs/dor-browser.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Dor Browser Surface
22

3-
> See `docs/specs/glossary.md` for canonical Session and Pane vocabulary, and
4-
> `docs/specs/dor-cli.md` for the shared `dor` CLI, surface handle model, and
5-
> host control plumbing this surface builds on.
3+
> See `docs/specs/glossary.md` for canonical Surface / Session / Pane vocabulary
4+
> (a browser pane is a **browser Surface**), and `docs/specs/dor-cli.md` for the
5+
> shared `dor` CLI, surface handle model, and host control plumbing this surface
6+
> builds on.
67
78
Dormouse has one dockview component for web content: `BrowserPanel`, persisted as
89
`surfaceType: 'browser'` with a swappable `renderMode`.

0 commit comments

Comments
 (0)