Skip to content

vscode: Tower sidebar — cross-workspace navigation hub (machine-wide attention, switch, activate on demand) #1566

Description

@amrmelsayed

Requirements drafted by the codev-ide architect (Amr-directed), reviewed and filed by codev:main. Spec and plan are builder-protocol artifacts; this issue is the requirements record.

Naming (re-ruled 2026-08-31 with the owner)

The surface is Tower (container id codev-tower, view id codev.tower). The machine-level supervision surface already has a user-facing name: the web dashboard is "Agent Farm Control Tower" and the daemon is afx tower. Naming the sidebar the same aligns all three surfaces (web, IDE, CLI) under one word for one vantage point. "Fleet" remains the collection noun in copy (the deck's fleet slot, "Fleet RSS", row counts like "3 workspaces need attention"): Tower is the vantage, fleet is what it watches. Guardrail: the Status view already says "Tower: connected", so this view's copy must always read as navigation over workspaces, never as daemon admin. Command ids are functional, not vocabulary-driven: the quick pick is codev.switchWorkspace. (Supersedes the initial "Fleet" ruling; the owner surfaced the dashboard-title consistency argument.)

Placement (owner-ruled at filing, 2026-08-31)

Tower is a separate sidebar: its own activity-bar view container (codev-tower), NOT an eighth section in the existing Codev sidebar (the owner ruled seven sections is already the ceiling there). The split lands on the real semantic boundary: the existing container is workspace-scope, the Tower container is machine-scope. The container's activity-bar icon carries the aggregate needs-attention count as its badge (TreeView.badge), which makes the separate status-bar badge (requirement 7) a should-have rather than a must-have; the spec decides whether both ship. Iconography must make the two Codev icons distinguishable at a glance.

Differentiation from the workspace-scope container (owner discussion, 2026-08-31, Explorer analogy: Explorer is this-project at the top of the built-in stack; Tower is the higher-level view above it):

  • Icons: same family, one vs many. The Tower icon is the workspace container's motif multiplied into a tiled/stacked form, or a control-tower glyph in the same family, the way Explorer's stacked documents read as "this project's files". Monochrome light/dark pair, rendered and verified at actual 16px (the vscode: Agents view with a 3-way group-by axis (stage / area / architect) + conversational Add Architect #1104 lesson), no brand color.
  • Badge semantics: only the Tower icon badges, and it badges the cross-workspace attention count. The workspace container stays unbadged so the badge itself signals machine-scope.
  • Current-workspace marking: the Tower tree explicitly marks this window's workspace row ("current", distinct styling; the spec decides whether it pins first regardless of urgency order).
  • Titles: "Codev Tower" vs "Codev" for hover/tooltips.
  • Default position: a marketplace extension cannot claim the top activity-bar slot (VS Code appends extension containers below built-ins; a user's manual drag persists). The Codev IDE fork owns default layout and may ship Tower-above-Explorer out of the box as an IDE default; the extension behaves identically everywhere and users of vanilla VS Code drag it up once if they want the same arrangement.

Problem

VS Code windows, and the extension's entire view set, are bound to the single folder the window has open, while Tower is user-global (one daemon, all workspaces). The only true multi-workspace client today is the Stream Deck plugin; the only cross-workspace path INTO VS Code is the inbound codev.focusWorkspaceWindow command. A user running several codev workspaces has no in-IDE way to see which workspace needs a human, or to jump there.

Requirements

  1. Tower view: a tree view in the dedicated container listing all active Tower workspaces (TowerClient.listWorkspaces()), each row showing the workspace's attention state via the SDK's deriveAttention(OverviewData) / isIdleWaiting (@cluesmith/codev-sdk/builder-helpers, Contextual panel: wire the Attention fallback body from OverviewCache (participating feature of #1049, skeleton fast-follow) #1553), never re-derived locally. Rows expand to the agents needing attention (blocked gate, held mail, PR-ready), reusing the overview fields (blocked, blockedGate, heldCount, prReady, mailboxEscalated, queuedFeedback).
  2. Urgency ordering: workspaces sorted by their AttentionSummary so "needs a human" floats to the top. One shared definition of urgency with all other clients. The comparator over AttentionSummary must be deterministic and documented in the spec (e.g. pending gates before waiting before held-mail counts), since it becomes the de facto cross-client urgency order.
  3. Row labels disambiguate colliding basenames. Two active workspaces on the same machine can share a basename (live case: two codev checkouts under different org directories; see afx send <workspace>:<agent> has no disambiguator when basenames collide — support path-tail matching #1565 for the same collision in afx addressing). Rows must render a disambiguating path tail (cluesmith/codev vs amrmelsayed/codev) whenever basenames collide, and the quick pick must do the same.
  4. Switch action: activating a row opens/focuses that workspace's window, reusing the codev.focusWorkspaceWindow re-validation plus vscode.openFolder { forceNewWindow: true } machinery. The hub stops at the workspace boundary: within-workspace agent-terminal cycling is Cycle agent terminals from keyboard and Stream Deck — next/previous in the Codev sidebar Agents order #1563's lane, and the hub composes with its sidebar-order rule rather than duplicating it.
  5. Activate on demand: the view also lists known-but-inactive workspaces (/api/workspaces returns the full registry with an active flag) in a secondary group. Selecting one activates it (TowerClient.activateWorkspace(path), already in the SDK), waits for confirmation (status/SSE), then opens its window. Notes the spec must resolve:
    • ConnectionManager.connect() already calls activateWorkspace() idempotently in every window (connection-manager.ts:110-128), so the open-window path converges without explicit pre-activation; keep explicit activation for headless bring-up and for surfacing confirmations BEFORE a window opens.
    • Activation is Tower's launchInstance(): it registers the workspace, allocates ports, and spawns the main architect PTY, so the workspace comes up live. It also AUTO-ADOPTS a non-codev directory (npx codev adopt --yes, which writes files into the repo). The hub must surface that adopt step for confirmation, never run it silently.
    • The endpoint is rate-limited (10 activations/min/client).
    • Deactivation from the row context menu is a should-have (same SDK method family).
    • If Tower itself is down, the existing codev.autoStartTower path covers it; no new lifecycle code.
  6. Quick pick: a keyboard-first codev.switchWorkspace command presenting the same attention-annotated list as a QuickPick.
  7. Status-bar badge (should-have, see Placement): aggregate cross-workspace needs-attention count; click opens the Tower view or quick pick. The container icon's badge may make this redundant; the spec decides.
  8. Live updates: exactly ONE shared SSE subscription to /api/events per extension host (the tower: offline gh failures aren't negative-cached (10s hang per request); with per-tab SSE this exhausts Chrome's connection pool and the dashboard becomes unloadable #1211 lesson: per-view EventSources exhausted the browser connection pool), driving refresh of the workspace list and per-workspace overviews; low-frequency poll fallback when SSE is unavailable.
  9. Data path: /api/workspaces plus per-workspace /api/overview fan-out, consumed strictly through @cluesmith/codev-sdk (TowerClient) and @cluesmith/codev-types; no raw endpoint coupling. If fan-out proves heavy at high workspace counts, a Tower-side aggregate is a codev-types/Tower addition routed to codev:main pre-gate (explicitly out of scope for v1).
  10. Auth/scope: local key via readLocalKey (@cluesmith/codev-sdk/node, the existing AuthWrapper path); loopback-only. No remote/tunnel reach until the codev-cloud#7-Date/Time Awareness - Metadata Generation Problems #9 threat model lands.
  11. Ship shape: lands in apps/vscode upstream; identical behavior in marketplace and Codev-IDE-bundled builds; zero fork-side code.

Non-goals (v1)

Links

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/vscodeArea: VS Code extension

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions