@dotobokuri/fleet-console 1.21.0 → 1.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/AGENTS.md +14 -12
  2. package/dist/cli.mjs +3355 -1891
  3. package/dist/client/assets/{_baseUniq-DuBqUdt5.js → _baseUniq-cap0P4FK.js} +1 -1
  4. package/dist/client/assets/{arc-Cu0mS4Rh.js → arc-yBqa09aK.js} +1 -1
  5. package/dist/client/assets/{architectureDiagram-Q4EWVU46-CXg6Ah4M.js → architectureDiagram-Q4EWVU46-Bug4qdr-.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-DXYQGD6D-BY8CIrjE.js → blockDiagram-DXYQGD6D-BkiIL2xt.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-AHTNJAMY-D4JbTs-7.js → c4Diagram-AHTNJAMY-DYY200Al.js} +1 -1
  8. package/dist/client/assets/channel-B3EqY8ya.js +1 -0
  9. package/dist/client/assets/{chunk-4BX2VUAB-BTO6mLsp.js → chunk-4BX2VUAB-DQKmhVxn.js} +1 -1
  10. package/dist/client/assets/{chunk-4TB4RGXK-C6Fnl7zd.js → chunk-4TB4RGXK-DHpmA3Zl.js} +1 -1
  11. package/dist/client/assets/{chunk-55IACEB6-B13wgLIz.js → chunk-55IACEB6-DeRDuQXE.js} +1 -1
  12. package/dist/client/assets/{chunk-EDXVE4YY-7-iC3e7j.js → chunk-EDXVE4YY-CNpnhSJm.js} +1 -1
  13. package/dist/client/assets/{chunk-FMBD7UC4-Dhpf1rPA.js → chunk-FMBD7UC4-BXGVABL-.js} +1 -1
  14. package/dist/client/assets/{chunk-OYMX7WX6-D2aEd21z.js → chunk-OYMX7WX6-WbJs4VwZ.js} +1 -1
  15. package/dist/client/assets/{chunk-QZHKN3VN-K-8aUXP6.js → chunk-QZHKN3VN-u3BLl6Sl.js} +1 -1
  16. package/dist/client/assets/{chunk-YZCP3GAM-COCKMROt.js → chunk-YZCP3GAM-BFESuhuJ.js} +1 -1
  17. package/dist/client/assets/classDiagram-6PBFFD2Q-BekEZLVJ.js +1 -0
  18. package/dist/client/assets/classDiagram-v2-HSJHXN6E-BekEZLVJ.js +1 -0
  19. package/dist/client/assets/clone-CsVi9-Ni.js +1 -0
  20. package/dist/client/assets/{cose-bilkent-S5V4N54A-CQfKdtka.js → cose-bilkent-S5V4N54A-rouOsZjT.js} +1 -1
  21. package/dist/client/assets/{dagre-KV5264BT-BIgQcK4J.js → dagre-KV5264BT-QCUeCVpM.js} +1 -1
  22. package/dist/client/assets/{diagram-5BDNPKRD-D-Y1duEc.js → diagram-5BDNPKRD-DqerlFb_.js} +1 -1
  23. package/dist/client/assets/{diagram-G4DWMVQ6-BxBM0Lq2.js → diagram-G4DWMVQ6-BS3a1YGN.js} +1 -1
  24. package/dist/client/assets/{diagram-MMDJMWI5-DFEVkQuS.js → diagram-MMDJMWI5-BeauTcSV.js} +1 -1
  25. package/dist/client/assets/{diagram-TYMM5635-QUGnvkyH.js → diagram-TYMM5635-Ci2wLUUE.js} +1 -1
  26. package/dist/client/assets/{erDiagram-SMLLAGMA-BIdCiDyA.js → erDiagram-SMLLAGMA-9MnmiKch.js} +1 -1
  27. package/dist/client/assets/{flowDiagram-DWJPFMVM-C5-H9nJM.js → flowDiagram-DWJPFMVM-CiV9p5EU.js} +1 -1
  28. package/dist/client/assets/{ganttDiagram-T4ZO3ILL-CtEhaGN5.js → ganttDiagram-T4ZO3ILL-D6oNoENl.js} +1 -1
  29. package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-DME3M-OV.js → gitGraphDiagram-UUTBAWPF-DESO385F.js} +1 -1
  30. package/dist/client/assets/{graph-G8vxctrf.js → graph-BZdl-RHy.js} +1 -1
  31. package/dist/client/assets/index-BKpCMFrm.js +380 -0
  32. package/dist/client/assets/index-cg8Uxys9.css +1 -0
  33. package/dist/client/assets/{infoDiagram-42DDH7IO-BDgcbpcl.js → infoDiagram-42DDH7IO-lc8vZnyi.js} +1 -1
  34. package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-BvyDjOaY.js → ishikawaDiagram-UXIWVN3A-BfzvQXhn.js} +1 -1
  35. package/dist/client/assets/{journeyDiagram-VCZTEJTY-Bl3ma4Jh.js → journeyDiagram-VCZTEJTY-BS_Dr0EV.js} +1 -1
  36. package/dist/client/assets/{kanban-definition-6JOO6SKY-DDfQy5MY.js → kanban-definition-6JOO6SKY-Cw7oTQJN.js} +1 -1
  37. package/dist/client/assets/{layout-CJ_GouLh.js → layout-ChwcDQm8.js} +1 -1
  38. package/dist/client/assets/{linear-BYcESPB3.js → linear-C7GLbmND.js} +1 -1
  39. package/dist/client/assets/{mermaid.core-H_nCcZgd.js → mermaid.core-D9phfpQo.js} +4 -4
  40. package/dist/client/assets/{min-Dqa4snAF.js → min-p7Whc_Wi.js} +1 -1
  41. package/dist/client/assets/{mindmap-definition-QFDTVHPH-BdBfgYSw.js → mindmap-definition-QFDTVHPH-fl_SJKrw.js} +1 -1
  42. package/dist/client/assets/{pieDiagram-DEJITSTG-F6w3ulj-.js → pieDiagram-DEJITSTG-Btw7ckA5.js} +1 -1
  43. package/dist/client/assets/{quadrantDiagram-34T5L4WZ-DjioXrlU.js → quadrantDiagram-34T5L4WZ-DB4iJlTI.js} +1 -1
  44. package/dist/client/assets/{requirementDiagram-MS252O5E-DCVw1H_U.js → requirementDiagram-MS252O5E-hXwV5Nhy.js} +1 -1
  45. package/dist/client/assets/{sankeyDiagram-XADWPNL6-KQYKD6-y.js → sankeyDiagram-XADWPNL6-DC-fizCk.js} +1 -1
  46. package/dist/client/assets/{sequenceDiagram-FGHM5R23-DjzGSEIS.js → sequenceDiagram-FGHM5R23-RrfrroR5.js} +1 -1
  47. package/dist/client/assets/{stateDiagram-FHFEXIEX-CVylZcMS.js → stateDiagram-FHFEXIEX-q8FUPV_e.js} +1 -1
  48. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-BErzXGq7.js +1 -0
  49. package/dist/client/assets/{timeline-definition-GMOUNBTQ-ChqpnE67.js → timeline-definition-GMOUNBTQ-tegMd8Od.js} +1 -1
  50. package/dist/client/assets/{vennDiagram-DHZGUBPP-DLzIQLVa.js → vennDiagram-DHZGUBPP-CXx5oN2X.js} +1 -1
  51. package/dist/client/assets/{wardley-RL74JXVD-1W-QRTwp.js → wardley-RL74JXVD-CxSJ3P_7.js} +1 -1
  52. package/dist/client/assets/{wardleyDiagram-NUSXRM2D-noSoHkHg.js → wardleyDiagram-NUSXRM2D-DN1P180Z.js} +1 -1
  53. package/dist/client/assets/{xychartDiagram-5P7HB3ND-iHEYHXFI.js → xychartDiagram-5P7HB3ND-Dcn9ukv5.js} +1 -1
  54. package/dist/client/index.html +2 -2
  55. package/dist/fleet-plugins/skills/routes.mjs +1642 -1274
  56. package/dist/fleet-plugins/terminal/routes.mjs +3351 -1887
  57. package/package.json +1 -1
  58. package/dist/client/assets/channel-BA4bj6Rn.js +0 -1
  59. package/dist/client/assets/classDiagram-6PBFFD2Q-DQxI6Hb4.js +0 -1
  60. package/dist/client/assets/classDiagram-v2-HSJHXN6E-DQxI6Hb4.js +0 -1
  61. package/dist/client/assets/clone-Bfh7HIaB.js +0 -1
  62. package/dist/client/assets/index-Bjyh5AjN.css +0 -1
  63. package/dist/client/assets/index-UoTD8YUw.js +0 -404
  64. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-CvMRv0mx.js +0 -1
package/AGENTS.md CHANGED
@@ -10,9 +10,9 @@
10
10
  - Terminal sessions are spawned server-side by the Terminal plugin and observed in-process; carrier events flow directly into the observer store and browser SSE without a separate fleet-cli registration channel.
11
11
  - Console durable state is persisted in the console data directory's `state.json` (`createDurableJsonStore`, `sensitivity: "sensitive"`). The data directory follows the release channel: published stable builds use `~/.fleet/console/state.json`, while unpublished local runs (`pnpm fleet-console`/`tsx`) use the project workspace `.fleet/console/state.json` co-located with the lock, so a dev console never shares Theaters/Operations with a globally installed one. Setting `FLEET_CONSOLE_DIR` relocates the durable state (and captures) into that directory too — co-located with the lock, matching the runtime-file escape hatch — so a read-only checkout can point its writable runtime slot away from the project tree. The console server is the sole writer; the file stores `{ version: 2, theaters, operations }`. On startup the server restores Theaters and Operations into a dormant state (no PTY), and Operation state survives console restarts.
12
12
  - A capture inbound channel writes `{fleetSessionId}.json` under the same console data directory's `captures/` (`~/.fleet/console/captures/` for stable, the project `.fleet/console/captures/` for local runs). Provider CLI SessionStart hooks record provider session ids via `fleet-console hook capture-session <provider>`; the server reads the capture file, merges the provider session id into durable state, and cleans up the capture file. This is separate from the console lock file in `os.tmpdir()` (stable) / the project `.fleet/console` lock (local).
13
- - The React SPA served from the console backend at `/console/`: layout, components, styles, and visual identity. The global navigation bar owns **Theater** selection — a project root directory that groups console-owned terminal sessions and Codex wiki context. The Operations surface renders a single spatial Map canvas of terminal sessions filtered to the active Theater; operators create sessions directly on the canvas (Shift-drag or right-click), choosing an Agent CLI before a new terminal session starts. Each session panel lists its active carrier jobs in a floating job dock, and selecting a job opens a centered streaming overlay scoped to that session's jobs. The canvas also hosts free shell panels (right-click) that resolve their cwd from the active Theater. A console-wide Operation quick-search (Cmd/Ctrl+K) searches terminal sessions across all Theaters, switches to the selected Operation's Theater, selects that Operation, and navigates to `/operations`; on `/codex` paths the same shortcut yields to Codex's own search.
13
+ - The React SPA served from the console backend at `/console/`: layout, components, styles, and visual identity. The bottom StatusBar provides version/What's New, self-update, and repository affordances, while the Operations SideBar owns **Theater** selection — a project root directory that groups console-owned terminal sessions and Codex wiki context. The Operations surface renders a single spatial Map canvas of terminal sessions filtered to the active Theater; operators create sessions directly on the canvas (Shift-drag or right-click), choosing an Agent CLI before a new terminal session starts. Each session panel lists its active carrier jobs in a floating job dock, and selecting a job opens a centered streaming overlay scoped to that session's jobs. The canvas also hosts free shell panels (right-click) that resolve their cwd from the active Theater. A console-wide Operation quick-search (Cmd/Ctrl+K) searches terminal sessions across all Theaters, switches to the selected Operation's Theater, selects that Operation, and navigates to `/operations`; on `/codex` paths the same shortcut yields to Codex's own search.
14
14
  - The built-in Terminal plugin (`runtime/fleet-plugins/terminal`, package `@fleet-plugins/terminal`): one plugin id, `terminal`, owns the Shell and Agent operation kinds plus plugin-scoped WebSocket, ticket registry, PTY session lifecycle, and launch runtime. It absorbs the server-shared and client-shared helpers, keeps operation type ids `shell` and `agent` (carrier streaming renders inside the Agent panel as a resident collapsible stream dock pinned to the panel bottom — live output always visible without a click, per-browser collapsed state persisted — plus a detail modal for full track history accessed via the dock header, not a separate child operation), serves plugin HTTP routes under `/plugins/terminal/{shell,agent}/*`, and uses the plugin-scoped `ws` route for PTY transport. The Shell launch label is `Shell`.
15
- - The Codex/Fleet Wiki web surface under `/console/codex`: the console-owned Codex server gateway, workspace registry, wiki API routes, and migrated vanilla TypeScript Maritime Codex client. The console-level **TheaterRegistry** is the source of truth for project roots and does not require a Fleet Wiki knowledge root; the Codex `WorkspaceRegistry` is the subset of Theaters whose directories contain a Fleet Wiki knowledge root. Codex is mounted as a Right Rail built-in panel under the Fleet Console GNB without an iframe or proxy daemon.
15
+ - The Codex/Fleet Wiki web surface under `/console/codex`: the console-owned Codex server gateway, workspace registry, wiki API routes, and migrated vanilla TypeScript Maritime Codex client. The console-level **TheaterRegistry** is the source of truth for project roots and does not require a Fleet Wiki knowledge root; the Codex `WorkspaceRegistry` is the subset of Theaters whose directories contain a Fleet Wiki knowledge root. Codex is mounted as a Right Rail built-in panel without an iframe or proxy daemon.
16
16
  - The observer-side client contract: REST snapshot fetches and the SSE consumption loop with reconnect/resync.
17
17
  - The streaming view model: the event reducer that folds `CarrierJobStreamEvent` timelines into per-job, per-track views with incremental text accumulation.
18
18
  - Console self-update (`POST /api/v1/updates/apply`): the console backend owns an independent detached self-update worker that re-installs the globally published `fleet-cli` and `fleet-console` packages, writes a status file and a log file under the console data directory. The route enforces exact loopback Origin, rejects local/unpublished builds, re-checks the latest release before accepting, and returns `202 { status: "accepted" }` only after the worker has been spawned and detached. The worker shuts down the console server and re-opens a browser on the new server at a fresh OS-assigned random loopback port once the install completes; the old tab is intentionally not preserved. Console must never import or depend on `@dotobokuri/fleet-cli` for this flow.
@@ -20,11 +20,11 @@
20
20
  ## Codex / Fleet Wiki Surface
21
21
 
22
22
  - Canonical Codex workspace routes live under `/console/codex/w/:ws/...`; MRU-compatible API routes live under `/console/codex/api/...`. Do not reintroduce global `/api/...` wiki routes because console owns its own local API namespace. The Codex server exposes exactly 4 REST resources: `GET /api/search` (empty `q` = full index via `listWiki`; non-empty `q` = `briefingQuery`), `GET /api/entry/:id` (with optional `?include=raw` to embed raw source content inline — raw is never served as a separate endpoint), `GET|POST /api/drydock[/:id[/decision]]` (replaces the former `/api/queue*` surface; all queue actions now go through `drydock/:id/decision`), and `GET /api/conflicts[/:id]`. All deprecated paths — `/api/health`, `/api/workspaces`, `/api/index`, `/api/index-md`, `/api/log`, `/api/raw`, and `/api/queue*` — return 404 or 405 and must not be reintroduced.
23
- - The console-level **Theater** is the parent concept for project roots. Codex workspaces share the same id space (`workspaceHash(realpath(dir))`) but are a strict subset of the Theater registry (`hasWiki=true`). The Codex left workspace switcher is removed; Theater selection in the global navigation bar is the only workspace switch, and Theaters without a Fleet Wiki knowledge root render a "Codex 없음" state instead of mounting a wiki surface.
23
+ - The console-level **Theater** is the parent concept for project roots. Codex workspaces share the same id space (`workspaceHash(realpath(dir))`) but are a strict subset of the Theater registry (`hasWiki=true`). The Codex left workspace switcher is removed; Theater selection in the Operations SideBar is the only workspace switch, and Theaters without a Fleet Wiki knowledge root render a "Codex 없음" state instead of mounting a wiki surface.
24
24
  - The migrated Codex client stays Vanilla TypeScript under `core/client/src/codex/**`; do not rewrite it into React state or components beyond the React mount host.
25
25
  - Codex is a **Right Rail built-in panel** (after ALERTS; `BUILT_IN_RAIL_PANELS = [alertsPanel, codexPanel]`). The rail renders a single-column **Navigator** (search input + entry list + Drydock pending-count badge + Conflicts entry) — there is no `app-shell` 3-pane grid, container-responsive pane-shedding, or pane-collapse toggle. A single shared mount host (`codex-host.ts`) relocates the Vanilla singleton into the rail container with `appendChild` via `mountNavigatorInto` + a `setOnRequestOpenReader` callback + `setNavigatorTheater`; `destroy()`+remount is never called. Workspace selection is driven by Theater state (`ctx.theaterId` from `RailPanelContext`); the left workspace switcher is removed. Mount paths: Theater auto-registration (`server.ts` `codex.registerWorkspace(cwd)`) and restart restoration (`server.ts` `restoreCodexWorkspaces`). The admin workspace registration endpoint, bearer-token surface, standalone `fleet-wiki` binary, Vanilla `router.ts`, `setCodexPresentationMode`/`setCodexPaneCollapsed`, and the `fleet-console.codex.nav-collapsed`/`rail-collapsed` localStorage keys are all removed.
26
26
  - The Codex reading surface has two tiers. Selecting a Navigator entry opens an **inline 2-pane split** inside the rail panel: the rail slot widens (the user's nav width + a ~360px document pane, driven by `useCodexSplitExtraWidth` reading `codexReader` state) and renders the preserved markdown reader on the **left** (`.codex-doc-pane`, ~46ch measure, with a collapsible inline ToC and a compact `⤢ Expand` button) while the Navigator stays on the **right** (`.codex-nav-pane`, still browsable — selecting another entry swaps the left document). The `⤢ Expand` button opens the **Reading overlay** (`CodexReadingSheet`, `createPortal` to `document.body`) — a centered modal "large view" over the Operations canvas at a fixed comfortable width (`min(960px, calc(100vw - 120px))`, no width toggle), gated on `codexReader != null && codexReaderExpanded`. The overlay is `role="dialog"` + `aria-modal="true"`, focus-trapped, animated with `codex-rise-centered` (which preserves the base `translateX(-50%)` centering — plain `codex-rise` sets only `translateY` and would clobber it), marks the background canvas/SideBar inert via `body[data-codex-reading]`, carries a 200px ToC rail with an `IntersectionObserver` scroll-spy (brass = active section), and closes on Esc/scrim/✕ back to the **2-pane split** (not nav-only) with focus restored to the Expand button. A single Vanilla reader instance (`codex-host` `readerHostNode`/`tocHostNode`) relocates between the split doc-pane and the overlay via `appendChild`, preserving content and scroll. The reading measure is owned by `.markdown-body` and its reading-wrapper siblings (`.document-header`, `.related-list`), never a shell grid. Codex typography is tokenized through `--font-size-*`; brass = active/location and aurora = live/link semantics, glass surfaces, self-hosted Fraunces/Manrope/JetBrains Mono, and `prefers-reduced-motion` short-circuits are unchanged. The deprecated `app-shell`/`app-shell--wide`/`app-shell--raw` grid, container queries, document-level ToC drawer, Manifest panel, `⌘\`/`Ctrl+\` width toggle, `.codex-reading-sheet.is-wide`, and the `Esc · ⌘\` hint are removed.
27
- - Preserve Maritime Codex reading aesthetic: the markdown render pipeline (`renderMarkdown` — marked + DOMPurify + hljs + wiki links; Mermaid hydrator with `securityLevel: "strict"`) and the `.markdown-body`/`.document-header`/`.related-list`/`.code-block` styling are preserved verbatim and reused in both the inline split doc-pane and the Reading overlay. These are now owned by `@fleet-console/markdown` (`runtime/fleet-console/markdown/`) — the shared workspace package that is the new SSoT for `renderMarkdown`, `installDiagramHydrator`, and the shared CSS. Surfaces: Navigator (search + entry list + Drydock + conflicts), the inline 2-pane split (document + browsable navigator), and the Reading overlay (large markdown view + ToC scroll-spy + copy-context actions + diagram lightbox), with brass/aurora roles and self-hosted fonts. The standalone raw viewer route, index/log views, command palette, Manifest panel, and document-level ToC drawer are removed; raw source is embedded inline via `GET /api/entry/:id?include=raw`.
27
+ - Preserve Maritime Codex reading aesthetic: the markdown render pipeline (`renderMarkdown` — marked + DOMPurify + hljs + wiki links; Mermaid hydrator with `securityLevel: "strict"`) and the `.markdown-body`/`.document-header`/`.related-list`/`.code-block` styling are reused in both the inline split doc-pane and the Reading overlay; `.document` is now a plain flow container, so document bodies render flat on the reading surface like the file-explorer md viewer while `.document-header` (breadcrumb/title/chips) and its hairline remain preserved. These are now owned by `@fleet-console/markdown` (`runtime/fleet-console/markdown/`) — the shared workspace package that is the new SSoT for `renderMarkdown`, `installDiagramHydrator`, and the shared CSS. Surfaces: Navigator (search + entry list + Drydock + conflicts), the inline 2-pane split (document + browsable navigator), and the Reading overlay (large markdown view + ToC scroll-spy + diagram lightbox), with brass/aurora roles and self-hosted fonts. The standalone raw viewer route, index/log views, command palette, Manifest panel, document-level ToC drawer, and the entry-footer copy-context actions (Compact context / Provenance / Context pack / Why this matched) are removed; raw source is embedded inline via `GET /api/entry/:id?include=raw`.
28
28
  - Preserve wiki security invariants: Host allowlist, Origin guard, write-surface loopback gate, DOMPurify markdown sanitization, Mermaid `securityLevel: "strict"` with `htmlLabels: false` and no `bindFunctions`, path containment, and lockfile bearer auth for admin workspace registration.
29
29
  - Browser payloads must not expose MCP/session tokens, terminal tickets, or Codex admin tokens.
30
30
 
@@ -133,9 +133,9 @@ These guards are robustness measures on top of the trust model, not a replacemen
133
133
 
134
134
  Operation chrome (maximize, minimize, focus, and the Operations Left SideBar) is host-owned. Plugins render only their panel body through `OperationRenderContext` and do not participate in window-state decisions.
135
135
 
136
- - **Per-panel maximize** (`maximizedOperationId` in `core/client/src/canvas/canvas-store.ts`) is orthogonal to **map fullscreen** (`mapFullscreen`, renamed from the earlier map-level maximize while keeping the same storage key). A maximized panel renders in a temporary full-canvas geometry — the map canvas column (col2), which excludes the SideBar (col1) and the Activity Rail (col3) — over the same instance without remounting. Drag, resize, and geometry persistence are blocked while maximized.
136
+ - **Per-panel maximize** (`maximizedOperationId` in `core/client/src/canvas/canvas-store.ts`) is orthogonal to **map fullscreen** (`mapFullscreen`, renamed from the earlier map-level maximize while keeping the same storage key). A maximized panel renders in a temporary full-canvas geometry — the map canvas column (col2), which excludes the SideBar (col1) and the Activity Rail (col3) — over the same instance without remounting. The body columns carry zero column gaps at all times, so the canvas card (and a maximized panel within it) sits flush against the SideBar and Rail while keeping its rounded corners and border. Drag, resize, and geometry persistence are blocked while maximized.
137
137
  - **Minimize preserves PTY**: minimized panels stay in the DOM with `visibility:hidden` and `inert` instead of unmounting, preserving terminal PTY / WebSocket state. Because the host chrome handles this, all plugins benefit uniformly and plugins need not be PTY-aware.
138
- - **Operations Left SideBar = all-panel chip list**: the left progressive 3-tier SideBar (`rail` 56px / `list` 180px / `detail` 280px) shows every Operation in the current Theater as a vertical chip, sorted by `operationOrder` (drag reorder / Alt+Shift+↑↓). Chips show active highlight (brass), minimized dim, close button (two-step ARM), accent (`--chip-accent` border + 1px ring), and notification count. **Chip leading slot**: a 24×24 non-interactive `<span aria-hidden>` hosts the Operation's kind icon (resolved via `renderKindIcon` — no new SDK surface); if no icon resolves, a neutral fallback glyph is shown. Plugins may declare which launch kind created an Operation through `payload.launchKindId`; when multiple kinds share the same type and no matching launch kind is present, the chip shows the neutral fallback glyph. Underway/status state is reflected through CSS class modifiers on the chip (`side-bar-chip--underway-{live|turn|awaiting}`, `side-bar-chip--underway-ring`). Right-clicking a chip opens the accent popover (`onContextMenu` on `<li>`). Accent tints the chip's focus-border channel only — never the icon fill. In `rail` tier, chips are horizontally centred (justify-content:center, padding 0) and labels are hidden. The SideBar header hosts **+New** (opens a `createPortal` global overlay with `mode="launch"` — Operations catalog only — positioned to the right of the button at `rect.right+8, rect.top`; no transient sidebar width expansion) and a **⚙ Settings** button (active, rail tier hidden) that opens a `createPortal` global overlay with `mode="controls"` — Map fullscreen, Radar sweep, Panel pulse, and Shortcuts (collapsed in `<details>`) — positioned to the right of the button. There is no footer on the SideBar; Map/Radar/PanelPulse controls live exclusively in the ⚙ controls overlay. Width persists per browser at `fleet-console.operations.side-width`; collapsed state at `fleet-console.operations.side-collapsed`. Clicking a chip focuses the Operation (restoring it if minimized); if a panel is currently maximized and the clicked chip is a different Operation, the maximized panel is switched to the clicked Operation (`setMaximizedOperationId`) without triggering a canvas pan. Double-clicking a chip's name opens an inline rename input that reuses the canvas panel rename flow through the shared `useInlineRename` hook (Enter commits, Escape cancels, blur commits); the rename input is hidden in `rail` tier alongside the name, so rename is only reachable from `list`/`detail` tiers.
138
+ - **Operations Left SideBar = Theater tree + active-panel chip list**: the left progressive 3-tier SideBar (`rail` 56px / `list` 180px / `detail` 280px) owns Theater selection and renders registered Theaters as sections. The active Theater uses brass emphasis and shows the full Operation tree; inactive Theaters are dimmed peek sections whose chips switch Theater and focus through the existing pending-focus path. The active Theater's Operations are sorted by `operationOrder` (drag reorder / Alt+Shift+↑↓), and group behavior remains Theater-scoped. Chips show active highlight (brass), minimized dim, close button (two-step ARM), accent (`--chip-accent` border + 1px ring), and notification count. **Chip leading slot**: a 24×24 non-interactive `<span aria-hidden>` hosts the Operation's kind icon (resolved via `renderKindIcon` — no new SDK surface); if no icon resolves, a neutral fallback glyph is shown. Plugins may declare which launch kind created an Operation through `payload.launchKindId`; when multiple kinds share the same type and no matching launch kind is present, the chip shows the neutral fallback glyph. Underway/status state is reflected through CSS class modifiers on the chip (`side-bar-chip--underway-{live|turn|awaiting}`, `side-bar-chip--underway-ring`). Right-clicking a chip opens the accent popover (`onContextMenu` on `<li>`). Accent tints the chip's focus-border channel only — never the icon fill. In `rail` tier, only active-Theater chips are shown, horizontally centred (justify-content:center, padding 0), with labels hidden. The SideBar header hosts **Add Theater** (opens the folder browser and registers through the Theater folder grant path) and a **⚙ Settings** button (active, rail tier hidden) that opens a `createPortal` global overlay with `mode="controls"` — Radar sweep, Panel pulse, and Shortcuts (collapsed in `<details>`) — positioned to the right of the button (the Maximized-map switch was removed; the StatusBar collapse chevron owns that state); the header-level +New Operation button is removed. Operation creation is available through canvas Shift-drag/right-click and each list/detail Theater row's **+** button, which switches to that Theater if needed and opens the `mode="launch"` overlay anchored to the row control. List/detail Theater rows expose quiet controls in order: chevron collapse/expand (persisted per browser at `fleet-console.operations.theater-collapsed` as an array of Theater ids), **⋯ Theater actions** (owns `New group…`, separator, and destructive `Forget Theater`), then **+ theater-scoped launch**; these controls are hidden in `rail` tier. Forget Theater lives in the **⋯ Theater actions** menu. There is no footer on the SideBar; Radar/PanelPulse controls live exclusively in the ⚙ controls overlay. Width persists per browser at `fleet-console.operations.side-width`; collapsed state at `fleet-console.operations.side-collapsed`. Clicking a chip focuses the Operation (restoring it if minimized); if a panel is currently maximized and the clicked chip is a different Operation, the maximized panel is switched to the clicked Operation (`setMaximizedOperationId`) without triggering a canvas pan. Double-clicking a chip's name opens an inline rename input that reuses the canvas panel rename flow through the shared `useInlineRename` hook (Enter commits, Escape cancels, blur commits); the rename input is hidden in `rail` tier alongside the name, so rename is only reachable from `list`/`detail` tiers.
139
139
  - **Active Operation SSoT**: `activeOperationId` (`core/client/src/store.ts`) is the single source of truth for active highlight and for `Alt + Left / Right` cycling. The cycle order is the same as the Left SideBar's visible order — the shared `sortOperationsByOrder` helper (`store.ts`) ranks by the canvas `operationOrder` (drag reorder) and falls back to createdAt for unranked Operations — so `Alt + Left / Right` never diverges from the chip list. If the active Operation is minimized, active is cleared. When a new panel is added while maximized, the maximized state is kept and the new panel becomes the maximized one. The same maximize-preserving rule applies to the one-shot jump path — ALERTS "Open" and the Cmd/Ctrl+K quick-search, both routed through `pendingOperationFocus` consumed in `operations.tsx`: when a panel is maximized as the jump resolves, the maximized target is swapped to the destination Operation (`setMaximizedOperationId`) instead of clearing maximize, matching the chip-click and `Alt + Left / Right` policy. The jump handlers themselves must not call `clearMaximizedOperationId()` directly — the consume effect owns that decision after `loadForTheater` restores the destination Theater's maximize state.
140
140
  - **`operationsHydrated`**: the canvas prunes stale Operation geometries only after the first `operations` fetch has set `operationsHydrated` to `true` (`core/client/src/store.ts`). Until then, pruning is deferred so restored geometry is not discarded during initial load.
141
141
 
@@ -202,14 +202,15 @@ These CSS variables are declared in `rail.css` and must not be inlined elsewhere
202
202
  **Layout contract**:
203
203
 
204
204
  - `.console-body.is-canvas` is `display:grid; grid-template-columns: auto minmax(0,1fr) auto` with `column-gap: var(--space-3)`. Col1 = `<OperationsSideBar>` (width driven by `--side-bar-width` CSS variable); col2 = the Operations map canvas; col3 = `<RightRail>` (floating glass card).
205
- - The SideBar (col1), the Operations map (col2), and the Activity Rail (col3) are **independent**: per-panel maximize (`maximizedOperationId !== null`) is confined to the map canvas (col2) and does **not** collapse the SideBar or Rail columns. The maximized panel fills col2 (which already excludes the SideBar and Rail), so both stay visible and reflow the canvas if opened/closed while a panel is maximized. `.console-body.is-canvas` no longer takes an `is-map-fullscreen` modifier; that modifier remains only on `.console-shell` for map fullscreen (topbar collapse).
205
+ - The SideBar (col1), the Operations map (col2), and the Activity Rail (col3) are **independent**: per-panel maximize (`maximizedOperationId !== null`) is confined to the map canvas (col2) and does **not** collapse the SideBar or Rail columns. The maximized panel fills col2 (which already excludes the SideBar and Rail), so both stay visible and reflow the canvas if opened/closed while a panel is maximized. `.console-body.is-canvas` no longer takes an `is-map-fullscreen` modifier; that modifier remains only on `.console-shell` for map fullscreen (StatusBar collapse).
206
206
  - The `canvas.tsx` `ResizeObserver` naturally reflows the canvas width when the rail opens/closes — no manual layout math is needed.
207
- - `.console-shell` grid (64px header + 1fr body) is immutable; only `.console-body.is-canvas` grid changes.
207
+ - `.console-shell` grid is content plus a 28px bottom StatusBar row (`--console-statusbar-height: 28px` in `layout.css`), with zero shell padding/gap so the chrome sits flush against the browser edges: the StatusBar is a full-bleed bottom strip (border-top only, no card radius/shadow), the SideBar touches the left edge and the Activity Rail touches the right edge (each squares its outer corners and keeps the inner radius). Map fullscreen collapses the StatusBar row; only `.console-body.is-canvas` owns the SideBar/map/Rail columns.
208
208
 
209
209
  **Design rules for RailPanel chrome**:
210
210
 
211
211
  - Active icon = `--brass`; idle = `--ink-fog`; hover = `--ink-spectral`. Do **not** use `--aurora` for rail icon states.
212
212
  - Active icon carries a left-edge 2px `--brass` bar (`.right-rail-ico.is-active::before`).
213
+ - Carriers (`/carrier-settings`) and Settings (`/settings`) live in the bottom-pinned Right Rail route-nav cluster after built-in/plugin panel icons, separated by a spacer/divider. These route buttons are core rail chrome, not `RailPanelDescriptor` entries, and must not toggle or persist rail panels.
213
214
  - Panel open/close transition = `width var(--duration-base) var(--ease-spring)`. `prefers-reduced-motion: reduce` must short-circuit to `0.01ms`.
214
215
  - Panel chrome (header 46px min-height + body 1fr; head and body `min-width: 240px`, aligned with `MIN_PANEL_WIDTH` in `right-rail.tsx`) follows the mock `.panel` pattern. Panel body content is plugin-owned; chrome is host-owned.
215
216
  - Viewer-surface syntax/diff colors go in new surface CSS files (e.g., `rail-viewer.css`); `theme.css` is immutable.
@@ -220,13 +221,14 @@ The console is the operations variant of Fleet Wiki's **Maritime Codex** languag
220
221
 
221
222
  - **Relationship to Maritime Codex**: `core/client/src/codex/**` owns the migrated Maritime Codex reading surface. Console may translate the vocabulary for operations needs, but it must stay visibly related through the shared token system, glass atmosphere, brass/aurora pairing, Fraunces display type, and `codex-rise` motion.
222
223
  - **Color semantics**:
223
- - `brass` means "지금 보고 있는 곳" — selected job brass dot indicator, active navigation, structural decoration, and non-live active/focus-adjacent emphasis.
224
- - `aurora` means "지금 살아있는 것" — streaming status, live dots, tenant beacons, stream caret, follow button, and `connection-chip--live`. Unlike Fleet Wiki, console does not reserve aurora only for document linkage because there is no document-link concept here.
224
+ - `brass` means "지금 보고 있는 곳" — selected job brass dot indicator, active route navigation, structural decoration, and non-live active/focus-adjacent emphasis.
225
+ - `aurora` means "지금 살아있는 것" — StatusBar update-ready/unread indicators, streaming status, live dots, tenant beacons, stream caret, follow button, and `connection-chip--live`. Unlike Fleet Wiki, console does not reserve aurora only for document linkage because there is no document-link concept here.
225
226
  - `coral` means error/bad; `--warn` (amber, near `oklch(80% 0.13 85)`) means warning/connecting; neutral ink means idle.
226
227
  - User accents are a user-chosen hue (any hue across the wheel — red/amber/green included) that **occupies the same outer-edge channel the focus highlight uses** — the border outline plus its 1px ring — on **both the SideBar chip and its canvas Operation panel**, fed by `--chip-accent` / `--op-accent`. When an accent is set it **takes over that focus channel in the accent color and shows permanently, regardless of focus**: an accented panel/chip always wears the accent on its border (and focus ring), so it reads as "focused in the user's hue" whether or not it is the active Operation, and focusing it keeps the accent instead of reverting to brass. Focus brass is used only when no accent is set (active → brass border/ring; idle → neutral rim). Status keeps its own separate channel — the underway/in-progress aurora/warn conic rides the edge `::before` (a minimized chip's `::before` carries the rotating conic; a visible operation's rotation is owned by its canvas panel) and the running glow/wake is unchanged — so an accented Operation shows its accent border together with the running conic. The SideBar chip's active brass *fill* stays as a secondary focus highlight beneath the accent outline. The accent never animates on its own (an infinitely orbiting ring is reserved for the functional in-progress signal) and never tints the panel/chip fill, name, beacon, count, close, or the status conic.
227
- - **Typography**: `Fraunces Variable` is display type for the topbar brand, job titles, idle marks, and large headings. `Manrope Variable` is the default UI family. `JetBrains Mono Variable` is for stream output, job ids, timelines, and eyebrow labels with uppercase tracked styling. **Exception**: the Operations terminal (xterm) uses `Cascadia Code` — a terminal-tuned face for box-drawing/Powerline glyph alignment — rendered via the xterm WebGL addon with DOM fallback. This is the sole surface where the console mono identity deliberately diverges from JetBrains Mono; the terminal font lives in the `terminal.tsx` xterm options (xterm takes a JS font string, not a CSS token), so it is not a `theme.css` variable.
228
+ - **Typography**: `Fraunces Variable` is display type for the StatusBar brand, job titles, idle marks, and large headings. `Manrope Variable` is the default UI family. `JetBrains Mono Variable` is for stream output, job ids, timelines, and eyebrow labels with uppercase tracked styling. **Exception**: the Operations terminal (xterm) uses `Cascadia Code` — a terminal-tuned face for box-drawing/Powerline glyph alignment — rendered via the xterm WebGL addon with DOM fallback. This is the sole surface where the console mono identity deliberately diverges from JetBrains Mono; the terminal font lives in the `terminal.tsx` xterm options (xterm takes a JS font string, not a CSS token), so it is not a `theme.css` variable.
228
229
  - **Surface and atmosphere**: `body::before` owns the multi-radial cold teal + brass afterglow field, and `body::after` owns the `feTurbulence` grain overlay. Sidebar, selected-job stage, timeline dock, and job summary are glass cards using `backdrop-filter: blur(18px) saturate(140%)`, `--surface-glass`, `--surface-rim`, `--shadow-soft`, and `--radius-xl`/large-radius surfaces.
229
- - **Motion**: panes use one first-paint `codex-rise` reveal (720ms, `--ease-spring`, topbar/sidebar/stage staggered 40/120/200ms). Live dots use aurora pulse, the stream caret keeps its blink, and ambient infinite motion is forbidden. `prefers-reduced-motion` must continue to short-circuit animation. Exception: the Operations canvas background may render a user-toggleable ambient radar sweep, paired with a user-toggleable panel-pulse perimeter animation, that persists per browser; both default on in the stable channel but default off in the local (unpublished `pnpm`) channel so dev restarts start quiet, an explicit per-browser toggle preference always wins over the channel default, and both remain short-circuited by `prefers-reduced-motion`. Second exception: a running Operation panel renders a continuous perimeter "wake" ripple as a functional status signal (not ambient decoration) it is driven by the plugin `ClientOperationStatusCapability` value reported through `operationStatus` (`running` = amber `--warn` turn, including carrier streaming; `awaiting` = aurora), appears only while work is in progress (`idle` and `dormant` render no perimeter wake), and stays short-circuited by `prefers-reduced-motion`, degrading to a static tinted rim and glow. Like the live-dot pulse, this is allowed functional status motion, not forbidden ambient motion.
230
+ - **StatusBar**: the 28px bottom bar is a full-bleed app-shell strip on Operations, Settings, and Carrier Settings flush to the browser's bottom/left/right edges with no margins, card radius, or floating shadow. The left cluster owns only a collapse chevron (operations route only) that toggles the `mapFullscreen` state collapsing hides the bar, and a small fixed reveal handle at the bottom-left corner (portal) restores it; the controls overlay no longer carries this switch. The right cluster owns `UpdateApplyControl`, Carriers/Settings route links on non-operations routes only (the Rail is operations-scoped, so the StatusBar inherits route navigation there; active = brass), the Fraunces `Fleet` wordmark link (nav home, immediately left of the GitHub icon), GitHub repository/star affordances, and a quiet neutral version chip (no brass/amber emphasis the only accent is the small aurora unread dot). What's New is opened from the version chip, with aurora unread state tied to release-note visibility; the standalone What's New chrome trigger, a connection beacon, and an active-Theater indicator must not be (re)introduced in the StatusBar.
231
+ - **Motion**: panes use one first-paint `codex-rise` reveal (720ms, `--ease-spring`, StatusBar/sidebar/stage staggered 40/120/200ms). Live dots use aurora pulse, the stream caret keeps its blink, and ambient infinite motion is forbidden. `prefers-reduced-motion` must continue to short-circuit animation. Exception: the Operations canvas background may render a user-toggleable ambient radar sweep, paired with a user-toggleable panel-pulse perimeter animation, that persists per browser; both default on in the stable channel but default off in the local (unpublished `pnpm`) channel so dev restarts start quiet, an explicit per-browser toggle preference always wins over the channel default, and both remain short-circuited by `prefers-reduced-motion`. Second exception: a running Operation panel renders a continuous perimeter "wake" ripple as a functional status signal (not ambient decoration) — it is driven by the plugin `ClientOperationStatusCapability` value reported through `operationStatus` (`running` = amber `--warn` turn, including carrier streaming; `awaiting` = aurora), appears only while work is in progress (`idle` and `dormant` render no perimeter wake), and stays short-circuited by `prefers-reduced-motion`, degrading to a static tinted rim and glow. Like the live-dot pulse, this is allowed functional status motion, not forbidden ambient motion.
230
232
  - **Hard bans**: no font CDN; no `Inter`/`Roboto`/`Arial`/`system-ui` as the first font family; no solid `#fff` or `#000` backgrounds; no card/button/chip radius at or below 4px; no removal of `prefers-reduced-motion`; no mixing brass and aurora roles; no reintroduction of `--carbon-*` or `--signal-*` token families; the user accent lives only in the focus outline channel it shares with brass (border + focus ring) — when set it overrides the focus brass there and shows permanently; no accent leak into the panel/chip fill, name, beacon, count, close, or the status (underway conic / aurora-warn / running glow) channel.
231
233
  - CSS stays in three layers: `theme.css` (tokens/reset/keyframes only), `layout.css` (shell grid/breakpoints only), `components.css` (every concrete surface).
232
234