second-opinion-mcp 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,14 +21,59 @@ Then in Claude Code:
21
21
 
22
22
  That's it. The review appears in `second-opinions/`.
23
23
 
24
+ ## How It Works
25
+
26
+ ```
27
+ ┌─────────────────────────────────────────────────────────────────┐
28
+ │ Claude Code │
29
+ │ │
30
+ │ You: "Add user authentication" │
31
+ │ Claude: [reads files, writes code, runs tests] │
32
+ │ You: "/second-opinion" │
33
+ │ │
34
+ └─────────────────────┬───────────────────────────────────────────┘
35
+
36
+
37
+ ┌─────────────────────────────────────────────────────────────────┐
38
+ │ Second Opinion MCP │
39
+ │ │
40
+ │ 1. Parse Claude Code session logs │
41
+ │ 2. Collect files read/written + their content │
42
+ │ 3. Resolve dependencies and dependents │
43
+ │ 4. Find related tests and types │
44
+ │ 5. Collect branch diff (feature branch vs base) │
45
+ │ 6. Bundle within token budget │
46
+ │ 7. Send to Gemini + GPT (consensus mode) │
47
+ │ 8. Write response to second-opinions/ │
48
+ │ │
49
+ └─────────────────────┬───────────────────────────────────────────┘
50
+
51
+
52
+ ┌─────────────────────────────────────────────────────────────────┐
53
+ │ second-opinions/add-auth.consensus.review.md │
54
+ │ │
55
+ │ # Consensus Code Review │
56
+ │ │
57
+ │ ## Synthesis │
58
+ │ [Claude merges both perspectives with full context] │
59
+ │ │
60
+ │ ## Gemini's Review │
61
+ │ [BLOCKING] Missing rate limiting on login endpoint │
62
+ │ │
63
+ │ ## OpenAI's Review │
64
+ │ [SUGGESTION] Consider adding refresh token rotation │
65
+ │ │
66
+ └─────────────────────────────────────────────────────────────────┘
67
+ ```
68
+
24
69
  ## Features
25
70
 
26
71
  ### Automatic Context Collection
27
72
 
28
- Second Opinion reads your Claude Code session to understand what you're working on:
73
+ Your session is the context. Second Opinion reads it automatically:
29
74
 
30
75
  - **Session files** — Files you read, edited, or created
31
- - **Conversation** — What you asked Claude to do (code blocks stripped to avoid stale references)
76
+ - **Conversation** — What you asked Claude to do
32
77
  - **Dependencies** — Files imported by your modified code
33
78
  - **Dependents** — Files that import your modified code
34
79
  - **Tests** — Test files related to your changes
@@ -47,44 +92,31 @@ Don't just get code reviews—ask for anything:
47
92
  /second-opinion openai Identify potential performance bottlenecks
48
93
  ```
49
94
 
50
- ### Multiple Providers
95
+ ### Consensus & Providers
51
96
 
52
- Switch between Gemini and GPT, or use both:
97
+ By default, Second Opinion calls both Gemini and OpenAI in parallel. Claude then synthesizes the findings using its full session context—merging agreements, surfacing unique insights, and resolving disagreements.
53
98
 
54
99
  ```
55
- /second-opinion consensus Review this code # Uses BOTH in parallel (default)
56
- /second-opinion gemini Review this code # Uses Gemini only
57
- /second-opinion openai Review this code # Uses GPT only
100
+ /second-opinion # Consensus (default) both providers
101
+ /second-opinion gemini Review this # Gemini only
102
+ /second-opinion openai Review this # GPT only
58
103
  ```
59
104
 
60
- ### Consensus Mode
105
+ Consensus mode:
106
+ - Calls both providers simultaneously
107
+ - Claude synthesizes findings using the unified review framework
108
+ - **Smart fallback**: if only one API key is configured, uses that single provider
61
109
 
62
- Get perspectives from both Gemini and OpenAI in a single request:
110
+ ### Diff-Scoped Reviews
63
111
 
64
- ```
65
- /second-opinion consensus
66
- ```
112
+ On feature branches, Second Opinion automatically includes the git diff (branch vs base). Reviewers distinguish issues introduced by your changes from pre-existing issues in the codebase:
67
113
 
68
- Consensus mode:
69
- - Calls both providers simultaneously (faster than sequential calls)
70
- - Returns combined output with each model's perspective
71
- - Highlights areas of agreement and differences
72
- - **Smart fallback**: if only one API key is configured, automatically uses that single provider instead of failing
73
- - Requires both `GEMINI_API_KEY` and `OPENAI_API_KEY` for true consensus; works with just one key via fallback
114
+ - **Findings** — Issues in the diff (your changes)
115
+ - **Pre-existing Issues** Legitimate issues NOT introduced by this change (lower priority)
74
116
 
75
117
  ### Smart Token Budgeting
76
118
 
77
- Context is prioritized to fit within token limits:
78
-
79
- 1. Explicitly included files (highest priority)
80
- 2. Session files (what you worked on)
81
- 3. Git changes
82
- 4. Dependencies
83
- 5. Dependents
84
- 6. Tests
85
- 7. Type definitions
86
-
87
- Files that don't fit are listed in the output so you know what was omitted.
119
+ Context is prioritized by category: explicitly included files first, then session files, git changes, dependencies, dependents, tests, and type definitions. Unused budget spills over to later categories. Files that don't fit are listed so you know what was omitted.
88
120
 
89
121
  ### Include Additional Files
90
122
 
@@ -130,21 +162,9 @@ Analysis complete! Written to second-opinions/add-auth-flow.openai.security-audi
130
162
  Include request/response examples.
131
163
  ```
132
164
 
133
- ### Compare Perspectives
165
+ ### Single Provider
134
166
 
135
- Get reviews from both providers at once:
136
-
137
- ```
138
- > /second-opinion consensus Review this implementation
139
-
140
- Consensus review complete! Written to second-opinions/auth-flow.consensus.review.md
141
- - Both models analyzed 14 files
142
- - Agreement: Both flagged the missing null check on line 42
143
- - Gemini highlighted: Performance concern with nested loops
144
- - OpenAI highlighted: Inconsistent error message formats
145
- ```
146
-
147
- Or separately:
167
+ When you want one model's perspective:
148
168
 
149
169
  ```
150
170
  > /second-opinion gemini Review this implementation
@@ -327,57 +347,11 @@ When calling the MCP tool directly:
327
347
  | `includeDependents` | No | `true` | Include importing files |
328
348
  | `includeTests` | No | `true` | Include test files |
329
349
  | `includeTypes` | No | `true` | Include type definitions |
330
- | `maxInputTokens` | No | `100000` | Context token budget |
350
+ | `maxInputTokens` | No | `200000` | Context token budget |
331
351
  | `maxOutputTokens` | No | `32768` | Max tokens for reviewer's response |
332
352
  | `temperature` | No | `0.3` | LLM temperature (0-1) |
333
353
  | `focusAreas` | No | — | Specific areas to focus on |
334
354
 
335
- ## How It Works
336
-
337
- ```
338
- ┌─────────────────────────────────────────────────────────────────┐
339
- │ Claude Code │
340
- │ │
341
- │ You: "Add user authentication" │
342
- │ Claude: [reads files, writes code, runs tests] │
343
- │ You: "/second-opinion" │
344
- │ │
345
- └─────────────────────┬───────────────────────────────────────────┘
346
-
347
-
348
- ┌─────────────────────────────────────────────────────────────────┐
349
- │ Second Opinion MCP │
350
- │ │
351
- │ 1. Parse Claude Code session logs │
352
- │ 2. Collect files read/written + their content │
353
- │ 3. Resolve dependencies and dependents │
354
- │ 4. Find related tests and types │
355
- │ 5. Bundle within token budget │
356
- │ 6. Send to Gemini/GPT │
357
- │ 7. Write response to second-opinions/ │
358
- │ │
359
- └─────────────────────┬───────────────────────────────────────────┘
360
-
361
-
362
- ┌─────────────────────────────────────────────────────────────────┐
363
- │ second-opinions/add-auth.gemini.review.md │
364
- │ │
365
- │ # Code Review - add-auth │
366
- │ **Provider:** gemini │
367
- │ │
368
- │ ## Summary │
369
- │ The authentication implementation is solid... │
370
- │ │
371
- │ ## Findings │
372
- │ [BLOCKING] Missing rate limiting on login endpoint │
373
- │ [SUGGESTION] Consider adding refresh token rotation │
374
- │ │
375
- │ ## What's Done Well │
376
- │ [PRAISE] Clean separation of auth concerns │
377
- │ │
378
- └─────────────────────────────────────────────────────────────────┘
379
- ```
380
-
381
355
  ## Requirements
382
356
 
383
357
  - Node.js 18+
package/dist/config.js CHANGED
@@ -34,7 +34,7 @@ export function loadConfig() {
34
34
  fileConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
35
35
  }
36
36
  catch (error) {
37
- console.error(`Warning: Invalid JSON in config file ${configPath}. Using defaults.`);
37
+ console.error(`Warning: Invalid JSON in config file ${configPath}. Using defaults.`, error instanceof Error ? error.message : String(error));
38
38
  }
39
39
  }
40
40
  const config = ConfigSchema.parse({
@@ -95,6 +95,12 @@ Work through these phases in order:
95
95
  ### Phase 3: Detailed Analysis
96
96
  - Correctness, security, performance, error handling, edge cases
97
97
 
98
+ When a branch diff is provided:
99
+ - Primary focus: code that appears in the diff (new/changed lines)
100
+ - Use the diff to determine if an issue is newly introduced or pre-existing
101
+ - Findings section = only issues in the diff
102
+ - Pre-existing Issues section = legitimate issues NOT in the diff
103
+
98
104
  ### Phase 4: Self-Interrogation
99
105
  For each finding: form it as a question, search the code for evidence, then:
100
106
  - Confirmed → include as a finding with evidence
@@ -119,11 +125,18 @@ Brief overall assessment.
119
125
 
120
126
  ### Findings
121
127
  Ordered by severity, every finding grounded in specific code.
128
+ When a branch diff is provided, only include issues introduced by the diff.
129
+
130
+ ### Pre-existing Issues
131
+ (Include only when a branch diff is provided and pre-existing issues are found.)
132
+ Issues found in reviewed files that were NOT introduced by this change.
133
+ Same severity labels and evidence requirements as Findings.
122
134
 
123
135
  ### Questions
124
136
  Findings that couldn't be fully grounded.
125
137
 
126
138
  ### Upstream/Downstream Opportunities
139
+ Architectural suggestions beyond the current change.
127
140
  - **What/Where** · **Why** · **Risk Level**: Safe / Worth Investigating / Bold
128
141
 
129
142
  ### What's Done Well
@@ -1,3 +1,4 @@
1
+ import { BudgetCategory } from "../utils/tokens.js";
1
2
  export interface BlockedFile {
2
3
  path: string;
3
4
  reason: "sensitive_path" | "outside_project_requires_allowExternalFiles";
@@ -48,6 +49,8 @@ export interface ContextBundle {
48
49
  commentsCount: number;
49
50
  reviewsCount: number;
50
51
  };
52
+ /** Unified diff of branch changes (from base branch), kept separate from file markdown */
53
+ branchDiff?: string;
51
54
  files: FileEntry[];
52
55
  omittedFiles: OmittedFile[];
53
56
  totalTokens: number;
@@ -74,8 +77,43 @@ export interface ContextBundle {
74
77
  message: string;
75
78
  };
76
79
  }
80
+ export interface CandidateFile {
81
+ path: string;
82
+ content: string;
83
+ category: FileEntry["category"];
84
+ tokenEstimate: number;
85
+ annotation?: string;
86
+ redactionCount: number;
87
+ redactedTypes: string[];
88
+ }
89
+ export interface CategoryCandidates {
90
+ category: BudgetCategory;
91
+ files: CandidateFile[];
92
+ totalDemand: number;
93
+ }
94
+ export interface AllocationResult {
95
+ included: FileEntry[];
96
+ omitted: OmittedFile[];
97
+ categoryTokens: Record<BudgetCategory, number>;
98
+ }
99
+ /**
100
+ * Two-pass budget allocator.
101
+ *
102
+ * If total demand <= filePool, include everything (common case, fixes the original bug).
103
+ * If total demand > filePool, redistribute surplus from low-demand categories to high-demand ones.
104
+ *
105
+ * Within each category:
106
+ * - explicit/session: preserve insertion order (user intent)
107
+ * - all others: sort smallest first (maximize file count)
108
+ */
109
+ export declare function allocateBudget(candidates: CategoryCandidates[], filePool: number, budgetWeights: Record<BudgetCategory, number>, priorityOrder: BudgetCategory[]): AllocationResult;
77
110
  /**
78
- * Collect and bundle all context for review
111
+ * Collect and bundle all context for review.
112
+ *
113
+ * Two-pass architecture:
114
+ * Pass 1 (Collection): Gather all candidate files per category without committing budget.
115
+ * Deduplication: Assign each file to its highest-priority category.
116
+ * Pass 2 (Allocation): Distribute the file pool across categories via allocateBudget().
79
117
  */
80
118
  export declare function bundleContext(options: BundleOptions): Promise<ContextBundle>;
81
119
  /**