Skip to content

# [Feature Request] Complete Review Flow with Multi-Level Commenting #5

Description

@rbcb-dev

TL;DR

Agent Hive's current flow is Plan → Approve → Execute → Merge. This proposal adds optional review checkpoints and commenting capabilities throughout that flow:

  • Comment on anything: plans, tasks, diffs, individual lines of code
  • Blocker comments: flag issues that halt execution until resolved
  • Diff review before merge: see what changed per-task before merging
  • Works in VSCode and OpenCode: the two IDEs we actively support

The core Hive workflow stays the same. All new features are additive. You can use as much or as little as you want.


Background

This extends Issue #4 (Built-in Editor for Plan Review), which covers rich plan editing and inline comments. Here we expand commenting to cover the entire development flow and add structured diff review.

The gap: Hive gives you approval at the plan stage, but no visibility into what changed until after merge. Some teams want checkpoints without reintroducing the slow PR review cycle that Hive deliberately avoids.


What This Adds

Multi-level commenting with support for:

  • Prompt refinement ("clarify this requirement")
  • Plan sections ("reconsider this approach")
  • Tasks ("split this into two tasks")
  • Diffs ("this line has a bug")
  • Individual lines of code

Blocker priority that halts execution:

  • Normal comments: informational, no blocking
  • Important comments: warning, continues execution
  • Blocker comments: halts until resolved

Per-task diff review:

  • View what changed in each task's worktree
  • Comment on specific hunks or lines
  • Approve or request changes before merge

Audit trail persistence:

  • Comments stored in .hive/features/<name>/comments/
  • Survives across sessions
  • Machine-readable JSON with human-readable views

How It Works

┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│  PROMPT  │───►│   PLAN   │───►│ EXECUTE  │───►│  REVIEW  │───►│  MERGE   │
└──────────┘    └──────────┘    └──────────┘    └──────────┘    └──────────┘
     │               │               │               │               │
     ▼               ▼               ▼               ▼               ▼
  [OPTIONAL]     [REQUIRED]      [PER-TASK]     [OPTIONAL]      [PER-TASK]
  Refinement     Approval Gate    Blocker        Diff Review     Cleanup
  Comments       (existing)       Injection      Comments

Plan approval remains mandatory (that's Hive's core safety). Everything else is opt-in. If you don't add comments, nothing changes. If you don't review diffs, tasks merge as before.


Technical Approach

Comment Schema

Comments are stored as JSON files in the .hive/ directory:

interface HiveComment {
  id: string;
  parentId?: string;                  // for threading
  target: {
    type: 'prompt' | 'plan' | 'task' | 'diff' | 'file' | 'line';
    featureName: string;
    taskFolder?: string;              // "01-implement-feature"
    file?: string;                    // source file path
    line?: number;                    // single line
    lineRange?: { start: number; end: number };
    hunkIndex?: number;
  };
  body: string;                       // markdown
  author: 'user' | 'agent';
  priority: 'normal' | 'important' | 'blocker';
  status: 'open' | 'resolved' | 'wontfix';
  createdAt: string;
  updatedAt: string;
}

Comments live at .hive/features/<name>/comments/<id>.json. This keeps them version-controlled and inspectable outside the IDE.

How Tools Detect Changes

When an agent calls a Hive tool (like hiveExecStart or hiveExecComplete), the tool checks for relevant changes since the last call:

// Inside tool execution
const changes = detectChanges(feature, lastCheckpoint);

if (changes.blockers.length > 0) {
  return {
    result: "⚠️ BLOCKED",
    blockers: changes.blockers,
    suggestedAction: "review"
  };
}

// Normal execution continues...
return {
  result: "Task started successfully",
  newComments: changes.newComments  // agent sees these
};

The agent decides what to do with this information. We don't inject context or manipulate the conversation—we return change data in the normal tool response.

Diff Review

For viewing diffs, we use what already exists:

VSCode approach:

  • vscode.diff(leftUri, rightUri, title) for side-by-side comparison
  • Comment Controller API for inline threaded comments
  • No custom WebviewPanel needed for basic diff viewing

Additional UI (tree view for navigation):

Feature: user-auth (3 tasks)
├── 01-setup-database         [MERGED]
├── 02-implement-auth-service [READY FOR REVIEW]
│   ├── src/auth.service.ts   +89 -5
│   ├── src/jwt.ts            +45 -0
│   └── tests/auth.spec.ts    +35 -0
└── 03-add-api-routes         [IN PROGRESS]

Clicking a file opens VSCode's native diff view. Comments use VSCode's Comment Controller.

VSCode + OpenCode Focus

We build for:

  • VSCode (via vscode-hive extension): full diff view, Comment Controller, tree views
  • OpenCode (via opencode-hive plugin): MCP tools, limited UI

Other IDEs (JetBrains, Cursor, CLI) could be supported later. We're not designing around them now.


Technical Implementation Details

This section covers the VSCode APIs and patterns we'll use. All approaches rely on native VSCode capabilities—no custom WebviewPanel editors required for core functionality.

Diff Viewer Implementation

VSCode provides the vscode.diff command for opening side-by-side comparisons. We use this with virtual URIs pointing to base and modified file contents.

Opening a single diff:

import * as vscode from 'vscode';

// Create URIs for base (left) and modified (right) versions
const baseUri = vscode.Uri.file('/path/to/base/file.ts');
const modifiedUri = vscode.Uri.file('/path/to/worktree/file.ts');

await vscode.commands.executeCommand(
  'vscode.diff',
  baseUri,
  modifiedUri,
  'auth.service.ts (base ↔ worktree)',
  { viewColumn: vscode.ViewColumn.One }
);

For reviewing multiple files at once, VSCode 1.86+ supports the multi-diff editor:

Multi-diff editor example
// Review all changed files in a task at once
const changes = [
  { uri: modifiedFile1, original: baseFile1, modified: modifiedFile1 },
  { uri: modifiedFile2, original: baseFile2, modified: modifiedFile2 },
  { uri: modifiedFile3, original: baseFile3, modified: modifiedFile3 }
];

await vscode.commands.executeCommand(
  'vscode.changes',
  'Review: 02-implement-auth',
  changes
);

In practice, we get the base and worktree paths from simple-git. The worktree lives at .hive/.worktrees/<feature>/<task>/, and the base branch is known from the plan metadata.

Comment Controller Integration

VSCode's Comment Controller API provides native threaded comments that work in both regular editors and diff views.

Creating the controller:

const controller = vscode.comments.createCommentController(
  'hive.review',      // unique ID
  'Hive Code Review'  // label in UI
);

// Register for disposal
context.subscriptions.push(controller);

Enabling "Add Comment" in gutters:

controller.commentingRangeProvider = {
  provideCommentingRanges(document: vscode.TextDocument) {
    // Allow comments on any line in supported files
    return {
      ranges: [new vscode.Range(0, 0, document.lineCount - 1, 0)],
      enableFileComments: true  // file-level comments too
    };
  }
};

Creating comment threads:

Full thread creation example
interface HiveVSCodeComment extends vscode.Comment {
  id: string;
  body: string | vscode.MarkdownString;
  author: { name: string; iconPath?: vscode.Uri };
  mode: vscode.CommentMode;
  contextValue?: string;  // 'blocker' | 'suggestion' | 'question'
  reactions?: vscode.CommentReaction[];
}

// Create thread at specific line
const thread = controller.createCommentThread(
  documentUri,
  new vscode.Range(42, 0, 42, 100),  // line 42
  [
    {
      id: 'comment-abc123',
      body: new vscode.MarkdownString('**Blocker**: This breaks backward compatibility'),
      author: { name: 'User' },
      mode: vscode.CommentMode.Preview
    }
  ]
);

// Configure thread behavior
thread.state = vscode.CommentThreadState.Unresolved;
thread.collapsibleState = vscode.CommentThreadCollapsibleState.Expanded;
thread.canReply = true;
thread.label = 'Blocking';  // shown in thread header

Comment actions via menus:

{
  "contributes": {
    "commands": [
      { "command": "hive.resolveComment", "title": "Resolve" },
      { "command": "hive.markBlocker", "title": "Mark as Blocker" }
    ],
    "menus": {
      "comments/commentThread/context": [
        { "command": "hive.resolveComment", "when": "commentController == hive.review" }
      ],
      "comments/comment/context": [
        { "command": "hive.markBlocker", "when": "commentController == hive.review" }
      ]
    }
  }
}

Comments work on both sides of a diff view. The left side (base) and right side (modified) are separate documents, so we track which side a comment targets via the URI.

Plan Editor with Comments

For plan review, two approaches are viable:

Option 1: Native markdown + Comment Controller

Open the plan as a regular markdown file. Comments attach to the source markdown using the Comment Controller. Simple, but comments only appear in the source view, not in the rendered preview.

const planUri = vscode.Uri.file('.hive/features/auth/plan.md');
await vscode.window.showTextDocument(planUri);
// Comment Controller handles the rest

Option 2: WebviewPanel for rich editing

For inline comments visible in rendered markdown, use a WebviewPanel with custom highlighting:

WebviewPanel implementation
const panel = vscode.window.createWebviewPanel(
  'hive.planEditor',
  'Plan Review: user-auth',
  vscode.ViewColumn.One,
  {
    enableScripts: true,
    retainContextWhenHidden: true
  }
);

panel.webview.html = `
<!DOCTYPE html>
<html>
<head>
  <script src="${markedJsUri}"></script>
  <style>
    .has-comment { background: #fff3cd; cursor: pointer; }
    .comment-marker { 
      display: inline-block;
      width: 16px;
      height: 16px;
      background: #ffc107;
      border-radius: 50%;
      margin-left: 4px;
      vertical-align: middle;
    }
  </style>
</head>
<body>
  <div id="rendered-content"></div>
  <script>
    const vscode = acquireVsCodeApi();
    
    window.addEventListener('message', event => {
      if (event.data.type === 'updateContent') {
        document.getElementById('rendered-content').innerHTML = 
          marked.parse(event.data.markdown);
        highlightCommentedSections(event.data.comments);
      }
    });
    
    function highlightCommentedSections(comments) {
      comments.forEach(c => {
        // Add visual markers for sections with comments
      });
    }
    
    document.addEventListener('click', e => {
      if (e.target.classList.contains('comment-marker')) {
        vscode.postMessage({ 
          command: 'showComment', 
          id: e.target.dataset.commentId 
        });
      }
    });
  </script>
</body>
</html>
`;

// Handle messages from webview
panel.webview.onDidReceiveMessage(message => {
  switch (message.command) {
    case 'addComment':
      createComment(message.sectionId, message.text);
      break;
    case 'showComment':
      focusCommentThread(message.id);
      break;
  }
});

We'll likely start with Option 1 (native markdown) for simplicity. Option 2 is available if users need inline comment visualization.

Copilot Chat Integration

VSCode supports custom chat participants that can integrate with Copilot. A @review participant would let users ask Copilot to analyze diffs directly in chat.

Register the participant in package.json:

{
  "contributes": {
    "chatParticipants": [{
      "id": "hive.review",
      "name": "review",
      "description": "Review Hive task changes",
      "commands": [
        { "name": "diff", "description": "Analyze diff for a task" },
        { "name": "comment", "description": "Add a review comment" },
        { "name": "approve", "description": "Approve task changes" }
      ]
    }]
  }
}

Implement the request handler:

Chat participant implementation
const participant = vscode.chat.createChatParticipant(
  'hive.review',
  async (request, context, stream, token) => {
    
    if (request.command === 'diff') {
      const task = parseTaskFromPrompt(request.prompt);
      const diffText = await getDiffForTask(task);
      
      // Stream the diff to Copilot for analysis
      const messages = [
        vscode.LanguageModelChatMessage.User(
          `Review this diff and identify potential issues:\n\n${diffText}`
        )
      ];
      
      const response = await request.model.sendRequest(messages, {}, token);
      
      for await (const fragment of response.text) {
        stream.markdown(fragment);
      }
      
      return { metadata: { command: 'diff', task } };
    }
    
    if (request.command === 'comment') {
      const { file, line, text } = parseCommentRequest(request.prompt);
      await addReviewComment(file, line, text);
      stream.markdown(`✓ Added comment at \`${file}:${line}\``);
      return { metadata: { command: 'comment' } };
    }
    
    if (request.command === 'approve') {
      const task = parseTaskFromPrompt(request.prompt);
      await approveTask(task);
      stream.markdown(`✓ Approved task: ${task}`);
      return { metadata: { command: 'approve', task } };
    }
  }
);

// Suggest follow-up actions based on context
participant.followupProvider = {
  provideFollowups(result, context, token) {
    if (result.metadata?.command === 'diff') {
      return [
        { prompt: 'Approve these changes', command: 'approve' },
        { prompt: 'Add a comment about this', command: 'comment' }
      ];
    }
    return [];
  }
};

context.subscriptions.push(participant);

This gives users a natural language interface for reviews: @review /diff 02-implement-auth analyzes the task's changes, then suggests follow-up actions.

Real Extension Patterns

Several existing extensions solve similar problems and provide proven patterns:

GitHub Pull Requests and Issues extension:

  • Uses Comment Controller for PR review threads
  • Maps local line numbers to GitHub's position format
  • Uses review: URI scheme to distinguish diff sides
  • Stores PR context in comment contextValue

GitLens:

  • Uses TextEditorDecorationType for inline blame annotations
  • Comment Controller for code discussions
  • WebviewPanels for rich history visualization

These patterns inform our approach: use native VSCode APIs where possible, fall back to WebviewPanel only for truly custom UI requirements.


GitHub Copilot Terms of Service

This architecture operates within standard MCP tool behavior. Specifically:

We do NOT:

  • Extend or manipulate Copilot sessions
  • Inject context outside of tool responses
  • Make programmatic API calls to Copilot
  • Stream or push data to the LLM

We DO:

  • Return data in normal tool responses (standard MCP behavior)
  • Let the LLM decide how to interpret and act on that data
  • Use documented VSCode APIs (Comment Controller, diff command, tree views)

GitHub officially supports MCP tools in Copilot. Their own documentation describes returning structured data from tools. We follow that pattern exactly.

Reference: GitHub Copilot MCP Integration


Implementation

Phase 1: Core Comment System

  • Define HiveComment schema in @agent-hive/core
  • Implement CommentService for CRUD operations
  • Add comment storage to .hive/ structure
  • Create hiveCommentAdd, hiveCommentResolve tools

Phase 2: Reactive Tool Checks

  • Add change detection to existing tools
  • Return blockers and newComments in tool responses
  • Implement blocker resolution flow

Phase 3: Diff Review

  • Integrate parse-diff for structured diff access
  • Create VSCode tree view for file navigation
  • Wire up Comment Controller for line-level comments
  • Use native vscode.diff command

Phase 4: UI Polish

  • Diff approval workflow
  • Comment notification badges
  • Resolution confirmation dialogs

Package Structure

We don't need 7 packages. Start with what exists:

@agent-hive/core      # Business logic, types, services (already hive-core)
vscode-hive           # VSCode extension (already exists)
opencode-hive         # OpenCode plugin (already exists)

Additional packages only if truly needed later.


Philosophy Alignment

Pillar How This Extends It
Context Persists Comments persist across sessions in .hive/
Plan → Approve → Execute Additional optional gates, not replacements
Isolated Worktrees Per-task diff review before merge
Sequential Tasks Blockers can pause/resume execution
Tests Define Done Diff review as optional verification layer

Everything is additive. The existing workflow keeps working unchanged.


Open Questions

  1. Comment storage format: JSON files (proposed) vs inline YAML frontmatter in markdown?

  2. Blocker UX: Should blocked tasks show a specific icon in the tree view? How do we surface blockers prominently?

  3. Comment threading depth: Support unlimited nesting or cap at 2-3 levels?

  4. Diff caching: Cache parsed diffs or regenerate on demand? Worktrees can have many files.


What We're Not Building

  • JetBrains adapter (no current users asking for it)
  • Cursor-specific integration (uses VSCode base, may work automatically)
  • CLI diff viewer (terminal-based review is out of scope)
  • Real-time collaboration (comments are async, not live)
  • Integration with GitHub PR reviews (this is about pre-merge review)

Dependencies

Package Purpose
simple-git Git operations (already in use)
parse-diff Structured diff parsing
zod Schema validation

No new heavy dependencies.


Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions