Skip to content

VSCode sidebar: View Diff + Run/Stop Dev Server commands #690

@amrmelsayed

Description

@amrmelsayed

Issue 2 — VSCode sidebar: view diff + run/stop dev server for any builder

Problem

The Codev VSCode extension (packages/vscode/) surfaces builders in the Codev sidebar via the Needs Attention and Builders tree views. Users can approve gates (codev.approveGate, Cmd+K G), send messages (codev.sendMessage, Cmd+K D), attach to builder terminals (codev.openBuilderTerminal), and perform other state-level actions — but they cannot review a builder's code without dropping to a terminal.

Today to review a builder's work, a VSCode user must:

  1. Open a terminal
  2. cd .builders/<name>/
  3. Run git diff main manually
  4. Separately run pnpm dev or similar if they want to test it
  5. Deal with port/env setup themselves

This breaks the sidebar-native flow and is especially painful for the upcoming PIR protocol's code-review gate (tracked in Issue 3), but also degrades day-to-day inspection for every existing protocol. This issue adds three VSCode commands exposed via sidebar context menus that eliminate the manual terminal trip.

Proposed solution

Three new commands in the Codev VSCode extension. Each is exposed in the right-click context menu on builders in the Needs Attention and Builders tree views.

Command 1 — codev.reviewDiff

Opens VSCode's native diff editor showing main...HEAD for the selected builder's worktree.

Behavior:

  1. Resolve the selected builder's worktree path from the tree item
  2. List changed files: shell out to git -C <worktree> diff --name-only main...HEAD
  3. For each changed file, use vscode.commands.executeCommand('vscode.diff', leftUri, rightUri) where:
    • leftUri points to the main branch version of the file (via VSCode's built-in git: URI scheme provided by the vscode.git extension)
    • rightUri is the file in the worktree
  4. VSCode opens its native side-by-side diff editor with syntax highlighting and +/- counts

Fallback approach if the vscode.diff API proves awkward: spawn a terminal in the worktree and run git diff main | less -R. Start with the native diff attempt; fall back if the URI resolution is complex.

Command 2 — codev.runWorktreeDev

Spawns the worktree's devCommand as a Tower-managed dev PTY (same mechanism as afx dev from Issue 1). Detects an existing Codev dev PTY and prompts to swap.

Behavior:

  1. Resolve the selected builder's worktree path and look up worktree.devCommand from .codev/config.json via the existing Codev config loader
  2. Error with a VSCode notification if devCommand is unset
  3. Query Tower for existing dev-type PTYs. If one is found:
    • Show a vscode.window.showWarningMessage modal: "Currently running dev for <other-builder>. Stop it and start <this-builder>?" with Yes / No buttons
    • On Yes: kill the existing dev PTY via Tower's REST API, then proceed
    • On No: cancel
  4. Create a new Tower PTY (same mechanism as afx dev) with cwd = worktree path, command = devCommand, type = 'dev'
  5. The spawned PTY auto-opens as a VSCode terminal tab via the existing Tower→VSCode terminal bridge (see packages/vscode/src/terminal-manager.ts), named "Dev: <builder-id>"

Users must stop main's dev themselves before running this (main is outside Tower). The dev PTY inherits main's ports and URLs by design — see Issue 1 for the serial-swap rationale.

Command 3 — codev.stopWorktreeDev

Stops the currently running Codev-managed dev PTY (the one started by codev.runWorktreeDev or afx dev). Counterpart to Command 2.

Behavior:

  1. Query Tower for PTYs with type: 'dev'
  2. If one is found, kill it via Tower's REST API
  3. If none found, show an informational notification: "No Codev-managed dev server is running."

Context menu integration

Add context menu items on the codev.needsAttention and codev.builders tree views, gated by contextValue. Extend the view providers (packages/vscode/src/views/needs-attention.ts and packages/vscode/src/views/builders.ts) to set distinct contextValue strings per builder state so menus can show the right actions:

  • builder-active — for builders not blocked at a gate
  • builder-plan-gate — for builders awaiting plan-approval (used by PIR, tracked in Issue 3)
  • builder-code-review-gate — for builders awaiting code-review (PIR)
  • builder-pr-gate — for builders awaiting PR review

Context menu mapping:

  • Active or plan-gate builder: Approve Gate (existing), Send Message (existing), Open Builder Terminal (existing), View Diff (new)
  • Code-review gate builder: View Diff, Run Dev Server, Stop Dev Server, Approve Gate, Send Message, Open Builder Terminal
  • PR gate builder: Approve Gate, View Diff, Open Builder Terminal

Existing commands codev.approveGate, codev.sendMessage, codev.openBuilderTerminal, codev.cleanupBuilder are reused unchanged.

Note: at the plan-approval gate, the primary review artifact is the GitHub issue comment, not a code diff. So "View Diff" for plan-gate builders is optional (they may not have any diff yet if they haven't written code). Show it only when there are committed changes on the branch — check if the worktree's HEAD differs from main before offering the action.

Files to touch

New

  • packages/vscode/src/commands/review-diff.ts — implements codev.reviewDiff
  • packages/vscode/src/commands/run-worktree-dev.ts — implements codev.runWorktreeDev
  • packages/vscode/src/commands/stop-worktree-dev.ts — implements codev.stopWorktreeDev

Modified

  • packages/vscode/package.json — register the three new commands in contributes.commands; add context menu items in contributes.menus.view/item/context keyed on viewItem
  • packages/vscode/src/extension.ts — register the three new commands on activation (wire them to their implementation modules, following the pattern established by existing codev.approveGate at packages/vscode/src/commands/approve.ts)
  • packages/vscode/src/views/needs-attention.ts — set distinct contextValue per builder state
  • packages/vscode/src/views/builders.ts — same
  • packages/vscode/src/test/extension.test.ts — smoke tests for the three new commands (resolve builder, invoke command, verify expected side effect — Tower PTY spawn for dev, diff editor opens for reviewDiff, etc.)

Acceptance criteria

  1. codev.reviewDiff opens diff editor: right-click a builder with committed changes → "View Diff" → VSCode's native diff editor opens showing the changed files from main...HEAD. Syntax highlighting works. Multiple files open as separate diff tabs (or navigable list, whichever VSCode's diff API produces).
  2. codev.reviewDiff handles empty diff: right-click a builder with no committed changes → show a notification: "No changes to review yet." No error thrown.
  3. codev.runWorktreeDev spawns Tower PTY: right-click a builder → "Run Dev Server" → Tower PTY created in the worktree running worktree.devCommand. PTY appears as a VSCode terminal tab named "Dev: <builder-id>".
  4. codev.runWorktreeDev prompts on swap: with a dev PTY already running for builder A, right-click builder B → "Run Dev Server" → modal appears asking to stop A. Yes → kills A, spawns B. No → cancels.
  5. codev.runWorktreeDev handles missing devCommand: if worktree.devCommand is unset in .codev/config.json, show a notification with a helpful pointer: "Configure worktree.devCommand in .codev/config.json to use this action."
  6. codev.stopWorktreeDev kills the dev PTY: with a Codev dev PTY running, invoking the command terminates it. With none running, shows an informational notification.
  7. Context menu items are gate-aware: builder blocked at code-review shows View Diff + Run Dev Server + Stop Dev Server + Approve + Send Message. Builder blocked at plan-approval shows Approve + Send Message (+ View Diff if there are commits). Builder active without a gate shows only the always-available items.
  8. Existing commands unchanged: codev.approveGate (Cmd+K G) and codev.sendMessage (Cmd+K D) continue to work identically. No regressions in codev.openBuilderTerminal, codev.cleanupBuilder, codev.spawnBuilder, etc.
  9. Tests: smoke tests verify command registration, command invocation, and expected side effects.

Non-goals (explicitly out of scope)

  • A dedicated codev.rejectGate command — rejection in Codev happens via codev.sendMessage (feedback loop), matching SPIR's established pattern at spec-approval / plan-approval gates. No new gate command needed.
  • A codev.openWorktree command (open worktree as separate VSCode window) — users who want this can code .builders/<name>/ from a terminal; not worth a dedicated command.
  • Changes to the dashboard (outside VSCode) — the dashboard already renders Tower terminals including dev PTYs; no UI work needed there.
  • Keybindings for the new commands — no default keybinding; users can customize via keybindings.json if they want.

Benefits to existing protocols (value delivered without any new protocol)

  • Any builder (bugfix, air, spir, aspir) becomes reviewable from the VSCode sidebar with one click — no terminal trip
  • SPIR builders at the plan-approval gate could have their branch inspected via "View Diff" if they've started committing code (though SPIR's primary artifact is the spec/plan file)
  • Any builder's worktree can be spun up as a dev server via "Run Dev Server"

Reference implementations / existing patterns

  • Existing command pattern: packages/vscode/src/commands/approve.ts — shows how to register a VSCode command that shells out to porch via spawn, uses the ConnectionManager to fetch overview data, and shows notifications
  • Tower REST API client in VSCode: packages/vscode/src/connection-manager.ts — provides getClient() and getOverview(workspacePath)
  • Tower terminal bridge (Tower PTY → VSCode terminal): packages/vscode/src/terminal-manager.ts
  • Tree view provider pattern with contextValue: packages/vscode/src/views/builders.ts already uses it; follow the same pattern for new state-specific values
  • vscode.diff command API: https://code.visualstudio.com/api/references/vscode-api#commands (executeCommand with 'vscode.diff')

Dependencies

  • Requires Issue 1 merged first:
    • codev.runWorktreeDev reuses the Tower dev-PTY concept (type: 'dev') and the swap-detection logic introduced by afx dev
    • codev.runWorktreeDev reads worktree.devCommand from the config block added in Issue 1
    • codev.stopWorktreeDev relies on the Tower dev-PTY type being recognizable

Blocks

  • Issue 3 (PIR protocol) consumes all three commands in its code-review gate UX. PIR can technically ship without them (review would be purely terminal-based), but the intended UX is sidebar-driven.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions