Skip to content

Instantly share code, notes, and snippets.

@eonist
Created February 22, 2026 21:31
Show Gist options
  • Select an option

  • Save eonist/65988b33206fa28feecd38544fe11554 to your computer and use it in GitHub Desktop.

Select an option

Save eonist/65988b33206fa28feecd38544fe11554 to your computer and use it in GitHub Desktop.
review-feature.md

Here's a comprehensive implementation plan for issue #240, based on the existing codebase .

What Exists Today

The PR view already has solid foundations to build on :

Component Status Location
File diff viewer ✅ Working FileDetailView.tsxDiffViewer
PR details view ✅ Working PrDetailsView.tsx
PR store (files, branches) ✅ Working src/views/pr/stores/
GitHub write ops ✅ Partial githubWrite.ts — has PR creation but no review endpoints
GitHub API (Rust) ✅ Partial github_api.rs (34KB) + pr_context.rs + pr_files.rs — no review API yet
Review/comment endpoints ❌ Missing Nothing in Rust or TS for posting PR review comments

Phase 1: GitHub Review API (Rust Backend)

The GitHub Pull Request Review API has three operations you need. Add these to github_api.rs or a new github_review.rs :

// src-tauri/src/github_review.rs (new file)

/// Create a review with inline comments
/// POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews
#[tauri::command]
pub async fn github_create_pr_review(
    owner: String,
    repo: String,
    pull_number: u64,
    body: String,                     // Top-level review summary
    event: String,                    // "APPROVE" | "REQUEST_CHANGES" | "COMMENT"
    comments: Vec<ReviewComment>,     // Inline comments
    github_token: tauri::State<'_, GithubToken>,
) -> Result<ReviewResponse, String> {
    // POST to /repos/{owner}/{repo}/pulls/{pull_number}/reviews
    // Body: { body, event, comments: [{ path, position, body }] }
}

#[derive(Serialize, Deserialize, Clone)]
pub struct ReviewComment {
    pub path: String,       // file path relative to repo root
    pub line: u32,          // line number in the diff
    pub side: String,       // "LEFT" (old) or "RIGHT" (new)
    pub body: String,       // the review comment text
}

/// Also useful: fetch existing review comments for display
/// GET /repos/{owner}/{repo}/pulls/{pull_number}/comments
#[tauri::command]
pub async fn github_list_pr_review_comments(
    owner: String,
    repo: String,
    pull_number: u64,
    github_token: tauri::State<'_, GithubToken>,
) -> Result<Vec<ExistingReviewComment>, String> { ... }

The GitHub Review API requires position (line offset within the diff hunk), not absolute line numbers. You can compute this from the diff hunks you already have in pr_files.rs .

Register in main.rs alongside the existing GitHub commands .

Phase 2: TypeScript Service Layer

Extend githubWrite.ts with review operations :

// Add to src/services/githubWrite.ts

export interface ReviewComment {
  path: string;
  line: number;
  side: 'LEFT' | 'RIGHT';
  body: string;
}

export interface CreateReviewOptions {
  owner: string;
  repo: string;
  pull_number: number;
  body: string;
  event: 'APPROVE' | 'REQUEST_CHANGES' | 'COMMENT';
  comments: ReviewComment[];
}

export interface ReviewInfo {
  id: number;
  body: string;
  state: string;
  html_url: string;
  user: string;
  submitted_at: string;
}

export async function createPRReview(
  options: CreateReviewOptions
): Promise<ReviewInfo> {
  return invoke<ReviewInfo>('github_create_pr_review', {
    owner: options.owner,
    repo: options.repo,
    pullNumber: options.pull_number,
    body: options.body,
    event: options.event,
    comments: options.comments,
  });
}

Phase 3: AI Review Generation

This is where Omni's 6-source enrichment pipeline gives you the edge over every other review tool . Create a new service:

// src/services/reviewGenerator.ts (new file)

interface ReviewRequest {
  owner: string;
  repo: string;
  pullNumber: number;
  repoPath: string;        // local repo path
  baseBranch: string;
  headBranch: string;
  userPrompt?: string;     // optional guidance from prompt overlay
}

interface GeneratedReview {
  summary: string;                    // top-level review body
  comments: ReviewComment[];          // inline per-file comments
  event: 'APPROVE' | 'REQUEST_CHANGES' | 'COMMENT';
}

export async function generateAIReview(
  request: ReviewRequest
): Promise<GeneratedReview> {
  // Step 1: Gather context from all 6 sources
  //   - diff:        reuse getPrFileDiff() from fileViewerService
  //   - files:       read related project files via Tauri
  //   - web:         crawl referenced docs/APIs (existing web crawler)
  //   - connectors:  PR → issue chain via pr_context.rs
  //   - agent input: check for recent agent transcript
  //   - human input: userPrompt from prompt overlay

  // Step 2: Build per-file dossiers (same pattern as AI Rebase)
  //   For each changed file:
  //     - diff hunks
  //     - related project files (imports, tests)
  //     - issue/PR context

  // Step 3: AI generates review per file (recursive, AFM-compatible)
  //   For each file dossier, ask the LLM:
  //     - Any bugs or issues?
  //     - Does the change align with the linked issue?
  //     - Style/architecture concerns?
  //     - What line(s) to comment on?

  // Step 4: AI generates overall summary
  //   Roll up individual file reviews into a cohesive summary

  return { summary, comments, event };
}

The per-file approach keeps token budgets small (same principle as the recursive grouping in AI Rebase) — you can review a 200-file PR without blowing up AFM context windows .

Phase 4: UI Integration

4a. Review Button in PR View

Add a "Review PR" action to the existing PR view layout :

// src/views/pr/components/ui/ReviewButton.tsx (new file)

export const ReviewButton: FC = () => {
  const { isGenerating, generateReview, generatedReview } = useReview();

  return (
    <button onClick={generateReview} disabled={isGenerating}>
      {isGenerating ? 'Reviewing...' : '✦ AI Review'}
    </button>
  );
};

4b. Inline Comments on DiffViewer

The biggest UI change: extend FileDetailView.tsx and the DiffViewer component to show and add inline comments :

// Extend the DiffViewer component to accept review comments
<DiffViewer
  fileName={diffData.file_name}
  fileLang={diffData.file_lang}
  oldContent={diffData.old_content}
  newContent={diffData.new_content}
  diffHunks={diffData.diff_hunks}
  theme="light"
  // NEW PROPS:
  reviewComments={commentsForFile}       // show AI-generated comments inline
  onAddComment={(line, side, body) => {  // allow manual additions
    addComment({ path: file.path, line, side, body });
  }}
/>

Each comment renders as a collapsible annotation below the relevant diff line — similar to GitHub's own review UI but within Omni.

4c. Review Preview & Submit

Before posting to GitHub, show a preview:

// src/views/pr/components/overlays/ReviewPreview.tsx (new file)

export const ReviewPreview: FC = () => {
  const { generatedReview, submitReview, editComment, removeComment } = useReview();

  // Shows:
  // 1. Summary text (editable)
  // 2. List of inline comments with file path + line (editable, removable)
  // 3. Event selector: Approve / Request Changes / Comment
  // 4. Submit button → calls createPRReview()
};

4d. Store

// src/views/pr/stores/reviewStore.ts (new file)

interface ReviewStore {
  isGenerating: boolean;
  generatedReview: GeneratedReview | null;
  existingComments: ExistingReviewComment[];  // fetched from GitHub

  // Actions
  generateReview: () => Promise<void>;
  editSummary: (text: string) => void;
  editComment: (index: number, body: string) => void;
  removeComment: (index: number) => void;
  addComment: (comment: ReviewComment) => void;
  submitReview: () => Promise<void>;  // posts to GitHub
  reset: () => void;
}

Phase 5: CLI Support

As described in the blog post, the CLI path omni --pr --review would reuse the same generateAIReview() logic. Add a handler in cli_settings.rs :

// In cli_settings.rs, add:
"--pr" => {
    if args.contains("--review") {
        // 1. Detect current branch → find open PR
        // 2. Gather 6-source context
        // 3. Generate review via AI
        // 4. POST review to GitHub
        // 5. Print: "Review posted. [done]"
    }
}

Pipeline Summary

User clicks "AI Review" (or runs omni --pr --review)
         |
         v
[ Gather 6-source context per file ]
  - diff, project files, web, connectors, agent transcript, human input
         |
         v
[ AI generates per-file comments ]  (recursive, AFM-compatible)
         |
         v
[ AI generates overall summary ]
         |
         v
[ Preview in UI — user edits/approves ]
         |
         v
[ POST to GitHub Reviews API ]
         |
         v
Review appears on PR under @user's name

Suggested File Additions

src-tauri/src/github_review.rs              # Rust: GitHub Review API endpoints
src/services/reviewGenerator.ts             # TS: 6-source AI review generation
src/views/pr/stores/reviewStore.ts          # TS: review state management
src/views/pr/components/ui/ReviewButton.tsx  # UI: trigger button
src/views/pr/components/overlays/ReviewPreview.tsx  # UI: preview & edit before submit
src/views/pr/hooks/useReview.ts             # Hook: wires store → services → Tauri

Key Design Decisions

  • Review posts under the authenticated user's name — not a bot account. This is critical for trust, as your blog post emphasizes .
  • Per-file AI calls, not whole-PR — keeps AFM token budgets manageable and mirrors the recursive approach from AI Rebase.
  • Human-in-the-loop — AI generates, user previews and edits, then submits. No auto-posting without review.
  • Reuse the 6-source pipeline — the context-gathering infrastructure from commit enrichment (pr_context.rs, web crawler, etc.) feeds directly into review generation .
  • The DiffViewer component is the integration surface — it already renders per-file diffs with old/new content and hunks. Adding inline comment annotations is the natural extension .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment