Skip to content

vscode: contextual bottom panel that adapts to active editor (mode resolver + Attention fallback) #1049

@amrmelsayed

Description

@amrmelsayed

Problem

Codev has been moving toward putting activity surfaces in the VSCode bottom panel — the Codev scaffold tab and Codev: Dev are already there, and planned features (#1037 review comments, #807 Reader View, future Recently Closed / Team / Status) all need a panel home.

If each feature gets its own sibling tab, the bottom panel grows tabs faster than the user wants to navigate them. A user reviewing a diff doesn't need a tab for spec-document markers visible right now; a user reading a spec doesn't need the code-review queue visible right now. Side-by-side tabs ask the user to navigate; they don't pair the panel content to what the user is doing.

Proposed pattern

A single contextual panel tab — Codev — that morphs its content based on the active editor + workspace state, with a fallback "Attention" mode when no specific context matches. Existing pattern peers: VSCode's Source Control panel morphs with git state; Outline tracks the active editor; Run and Debug shows context-specific controls.

The user gets the panel content that pairs with what they're looking at, automatically. Power users can pin a mode to override the contextual default and lock the panel to a specific view.

Mode mapping (v1)

Active context Mode What the panel shows
Active editor is a file under codev/{specs,plans,reviews}/ Document Review Review markers (<!-- REVIEW: author "body" -->) anchored to this file, with resolve / edit / delete actions. Source: the marker bytes in the file itself (artifact-canvas / #859 / #945 model).
Active editor is the unified diff editor for a builder Code Review This builder's pending-comments queue (#1037) + Files-not-yet-reviewed checklist (separate sibling issue) + Submit Review action. Source: .builders/<id>/.codev/pending-comments.json.
Active editor is a builder terminal Builder Inspector This builder's current phase, gate state, recent activity, send-message input.
No specific context match Attention (fallback) Cross-cutting "what needs my attention": pending gates, blocked builders, queued review comments rolled up across builders, recently closed audit. The Needs Attention sidebar view, but in panel-format with per-item actions.

Modes that don't apply to the current context still render in the switcher (greyed out), so the user knows the panel can do more than what's active now.

Panel header

A header strip in the panel renders: <context label> · <mode pill buttons for the four modes>. The active mode is bold; others are clickable to override the contextual default. A pin icon next to the mode locks it so the panel stops switching with the editor; persisted as codev.contextualPanel.pinnedMode per workspace.

What stays separate

Codev: Dev keeps its own tab. It's a service-surface (status of a running dev server) that the user wants to glance at independent of what they're working on. The contextual panel is "what I need to act on for the thing I'm looking at"; Dev is "is my dev server still up?" — different mental category.

Architecture

Mode resolver as a separate concern from view rendering:

ContextualPanel
├── ModeResolver (active editor + workspace state + user pin → ModeDescriptor)
└── PanelRenderer (ModeDescriptor → React/webview tree)

The resolver runs on vscode.window.onDidChangeActiveTextEditor and on workspace state changes (new pending gates, new pending comments). The resolver returns one of {kind: 'document-review' | 'code-review' | 'builder-inspector' | 'attention', context: {…}}. The panel re-renders accordingly.

Performance budget: mode resolution runs on every active-editor change, so it must be O(1). URI-prefix matching, contextValue checks, no filesystem walks. Heavier data fetches happen inside the mode's render path, after the mode is chosen.

Multi-window VSCode: each window has its own active editor → each window's panel reflects its own context. Already correct, just worth noting.

Participating features

This umbrella owns the panel skeleton + mode resolver. Individual modes are filed as separate issues that compose with the umbrella:

Acceptance criteria (umbrella scope only — individual modes are separate)

  • One contextual Codev tab in the bottom panel (the existing scaffold tab is repurposed). The Codev: Dev tab is left alone.
  • ModeResolver is a pure function: takes (activeEditor, workspaceState, pinnedMode) and returns ModeDescriptor. No filesystem walks, no async. Unit tests cover each branch.
  • Panel header renders four mode pill buttons (Document Review, Code Review, Builder Inspector, Attention). Active mode is visually distinct. Greyed-out modes are visible but indicate they don't apply to the current context.
  • Clicking a mode pill overrides the contextual default for the current session. A small pin icon next to the active pill toggles persistent pinning; persistence key codev.contextualPanel.pinnedMode per workspace.
  • When no context matches and no pin is set, panel falls back to Attention mode.
  • Mode switches on onDidChangeActiveTextEditor within ~50ms (no perceptible lag).
  • The panel exposes a render-target for each mode but does NOT implement the actual rendering of mode content — that's owned by the participating-feature issues. The umbrella ships with placeholder content per mode and the orchestration that switches between them.
  • Unit tests cover: resolver branches per active-editor type, pin-overrides-context, attention fallback, modes-greyed-when-inapplicable.
  • Dev-approval verification: open a spec, see Document Review mode active; switch to a builder's diff editor, see Code Review mode active; pin Attention, switch editors, see panel stays on Attention.

Plan-gate decisions to lock

  1. Per-window vs per-VSCode-instance pin scope. If a user pins Attention in window A, does window B inherit? Lean: per-window (each VSCode window has its own panel state — matches VSCode's own per-window panel behavior).
  2. Pin visual treatment. A pin icon next to the active mode pill, or a separate "pin current mode" toggle elsewhere in the header? Lean: icon next to the active pill (compact, contextually obvious).
  3. Mode-pill discoverability when greyed. Should hovering a greyed pill explain why it's inactive (e.g., "open a spec/plan/review file to activate Document Review")? Probably yes; cheap to add.
  4. Empty-state per mode. When Code Review mode is active but the current builder has zero pending comments, what does the panel show? Lean: a calm "No pending comments for this builder" with a small "View all builders' queues" link to override to Attention mode.
  5. Mode transitions during user interaction. If the user starts typing a comment in Code Review mode and then focuses a spec editor, does the panel immediately switch to Document Review (losing the in-progress input) or hold until commit? Lean: hold until commit — typed input is sticky; mode switches happen only after the input is settled.

Suggested protocol

PIR. The mode resolver's branching logic is the load-bearing surface and benefits from plan-gate review before coding. Dev-approval is load-bearing because the contextual feel of the panel is hard to evaluate from a PR diff — you have to navigate around in a real workspace to know whether the mode switches feel right.

Out of scope

  • The actual rendering of any specific mode's content. Each participating feature (vscode: codelens-driven review comments in the unified diff editor — per-builder queue with batched submit to PTY (follow-up to #789) #1037, Files-not-yet-reviewed, Reader View, etc.) ships its own rendering in its own PR. This umbrella ships only the skeleton + resolver + mode switching.
  • Codev: Dev tab. Stays separate as a service surface; not folded into the contextual panel.
  • Sidebar restructuring. This is a panel-only change. The sidebar's existing Builders / Backlog / PRs / Workspace / Status views stay as they are.
  • Mode for the editor or terminal panel surfaces. Bottom panel only.
  • Cross-window pin sync. Each VSCode window keeps its own pin state.
  • Split-mode (two modes side-by-side in the same panel). Single mode at a time for v1.

Related

Metadata

Metadata

Assignees

Labels

area/vscodeArea: VS Code extension

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions