@in-the-loop-labs/pair-review 3.2.1 → 3.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@in-the-loop-labs/pair-review",
3
- "version": "3.2.1",
3
+ "version": "3.2.3",
4
4
  "description": "Your AI-powered code review partner - Close the feedback loop with AI coding agents",
5
5
  "main": "src/server.js",
6
6
  "bin": {
@@ -81,5 +81,10 @@
81
81
  "jsdom": "^29.0.1",
82
82
  "supertest": "^7.1.4",
83
83
  "vitest": "^4.0.16"
84
+ },
85
+ "pnpm": {
86
+ "onlyBuiltDependencies": [
87
+ "better-sqlite3"
88
+ ]
84
89
  }
85
90
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pair-review",
3
- "version": "3.2.1",
3
+ "version": "3.2.3",
4
4
  "description": "pair-review app integration — Open PRs and local changes in the pair-review web UI, run server-side AI analysis, and address review feedback. Requires the pair-review MCP server.",
5
5
  "author": {
6
6
  "name": "in-the-loop-labs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-critic",
3
- "version": "3.2.1",
3
+ "version": "3.2.3",
4
4
  "description": "AI-powered code review analysis — Run three-level AI analysis and implement-review-fix loops directly in your coding agent. Works standalone, no server required.",
5
5
  "author": {
6
6
  "name": "in-the-loop-labs",
@@ -97,6 +97,14 @@ Prioritize suggestions in this order:
97
97
  - **Preserve reviewer autonomy** - you're a pair programming partner, not an enforcer
98
98
  - **Provide context** for why each suggestion matters to the reviewer
99
99
 
100
+ ## Summary Structure
101
+ The summary field should synthesize the findings, but it should not be one big paragraph.
102
+ - Start with 1-2 sentences describing the overall assessment
103
+ - Then include a markdown bullet list using "- " bullets for the key specific points
104
+ - After the bullets, add extra sentences or short paragraphs only when needed for requested context or follow-up detail
105
+ - Focus on WHAT was found, not HOW it was found
106
+ - Write as if a single reviewer produced this analysis
107
+
100
108
  ## Output Format
101
109
 
102
110
  **>>> CRITICAL: Output ONLY valid JSON. No markdown, no ```json blocks. Start with { end with }. <<<**
@@ -126,7 +134,7 @@ Output JSON with this structure:
126
134
  "confidence": 0.0-1.0,
127
135
  "reasoning": ["Step-by-step reasoning explaining why this issue was flagged (optional)"]
128
136
  }],
129
- "summary": "Brief summary of the key findings and their significance to the reviewer. Focus on WHAT was found, not HOW it was found. Do NOT mention 'orchestration', 'levels', 'merged from Level 1/2/3' etc. Write as if a single reviewer produced this analysis."
137
+ "summary": "Formatted markdown summary following the Summary Structure guidance above."
130
138
  }
131
139
 
132
140
  ### GitHub Suggestion Syntax
@@ -76,6 +76,13 @@ Max 2-3 praise items. Prefer line-level over file-level. Include actionable sugg
76
76
  ### Framing
77
77
  Use "Consider...", "Worth noting..." - guidance not mandates.
78
78
 
79
+ ### Summary
80
+ The summary field should be markdown, not one big paragraph.
81
+ - Start with 1-2 sentences describing the overall assessment
82
+ - Then include a markdown bullet list using "- " bullets for the key specific points
83
+ - After the bullets, add extra sentences or short paragraphs only when needed for requested context or follow-up detail
84
+ - Write as a single reviewer; do not mention levels or orchestration
85
+
79
86
  ## JSON Schema
80
87
  {
81
88
  "level": "orchestrated",
@@ -99,7 +106,7 @@ Use "Consider...", "Worth noting..." - guidance not mandates.
99
106
  "suggestion": "How to fix (omit for praise)",
100
107
  "confidence": 0.0-1.0
101
108
  }],
102
- "summary": "Key findings as if from single reviewer (no mention of levels/orchestration)"
109
+ "summary": "Formatted markdown summary following the Summary guidance above."
103
110
  }
104
111
 
105
112
  ### GitHub Suggestion Syntax
@@ -212,20 +212,21 @@ Frame all suggestions as guidance for a human reviewer, not automated mandates:
212
212
  Note: Confidence is about certainty of value, not severity. A minor improvement suggestion can have high confidence if you're sure it's helpful.
213
213
 
214
214
  ## Summary Synthesis Guidance
215
- The summary field is not a list of findings - it's a synthesis that helps the reviewer see the forest, not just the trees.
215
+ The summary field should help the reviewer see the forest, not just the trees, but it should not be one big paragraph.
216
216
 
217
217
  **Effective Summary Approach:**
218
- - **Synthesize, don't summarize**: Identify the overarching narrative of this PR's quality and concerns
219
- - **Lead with the most important insight**: What single thing should the reviewer understand first?
220
- - **Connect the dots**: How do individual findings relate to each other or to a common theme?
221
- - **Calibrate severity**: Is this PR fundamentally sound with minor issues, or does it have structural problems?
218
+ - **Start with 1-2 sentences of overall assessment**: Identify the overarching narrative of this PR's quality and concerns
219
+ - **Then use a markdown bullet list with "- " bullets**: Capture the key specific points the reviewer should track
220
+ - **Connect the dots**: Make the overview and bullets feel like one coherent review
221
+ - **Calibrate severity**: Make clear whether this PR is fundamentally sound with minor issues or has structural problems
222
+ - **After the bullets, add extra sentences or short paragraphs only when needed**: Use them for requested context, caveats, or follow-up detail
222
223
  - **Respect reviewer time**: A good summary lets the reviewer decide where to focus attention
223
224
 
224
225
  **Summary Anti-patterns to Avoid:**
225
226
  - Listing findings ("Found 3 bugs, 2 improvements, 1 praise...")
226
227
  - Implementation details ("Merged Level 1 and Level 2 suggestions...")
227
228
  - Vague platitudes ("This PR has some issues to consider...")
228
- - Excessive length (2-3 sentences is ideal)
229
+ - A single unbroken paragraph with no bullets
229
230
 
230
231
  ## Output Format
231
232
 
@@ -256,7 +257,7 @@ Output JSON with this structure:
256
257
  "confidence": 0.0-1.0,
257
258
  "reasoning": ["Step-by-step reasoning explaining why this issue was flagged"]
258
259
  }],
259
- "summary": "Brief summary of the key findings and their significance to the reviewer. Focus on WHAT was found, not HOW it was found. Do NOT mention 'orchestration', 'levels', 'merged from Level 1/2/3' etc. Write as if a single reviewer produced this analysis."
260
+ "summary": "Formatted markdown summary following the Summary Synthesis Guidance above."
260
261
  }
261
262
 
262
263
  ### GitHub Suggestion Syntax
@@ -205,9 +205,11 @@ class AnalysisHistoryManager {
205
205
  /**
206
206
  * Load analysis runs from the API (initial load only)
207
207
  *
208
- * This method is intended for initial page load and always selects the latest run.
209
- * For refreshing after a new analysis completes, use refresh() instead, which has
210
- * logic to optionally preserve the user's current selection.
208
+ * This method is intended for initial page load. On first load it selects the
209
+ * latest run; on subsequent calls it preserves the current selection when that
210
+ * run still exists. For refreshing after a new analysis completes, use
211
+ * refresh(), which has logic to optionally preserve the user's current
212
+ * selection while surfacing a new run indicator.
211
213
  *
212
214
  * @returns {Promise<Array>} The loaded runs
213
215
  */
@@ -227,11 +229,13 @@ class AnalysisHistoryManager {
227
229
  return [];
228
230
  }
229
231
 
230
- // Always select the latest run (first in the list since they're ordered by date DESC)
231
- // This ensures that after a new analysis completes, its results are displayed
232
232
  const latestRun = this.runs[0];
233
- const shouldTriggerCallback = !this.selectedRunId || String(this.selectedRunId) !== String(latestRun.id);
234
- await this.selectRun(latestRun.id, shouldTriggerCallback);
233
+ const currentRun = this.selectedRunId
234
+ ? this.runs.find(run => String(run.id) === String(this.selectedRunId))
235
+ : null;
236
+ const runToSelect = currentRun || latestRun;
237
+ const shouldTriggerCallback = String(this.selectedRunId) !== String(runToSelect.id);
238
+ await this.selectRun(runToSelect.id, shouldTriggerCallback);
235
239
 
236
240
  // Render the dropdown (after selecting so the selected state is correct)
237
241
  this.renderDropdown(this.runs);
@@ -96,7 +96,7 @@ function buildVoiceContext(voice, idx, instructions, progressCallback, db) {
96
96
  const voiceProvider = isExecutable ? createProvider(voice.provider, voice.model) : null;
97
97
 
98
98
  const voiceTier = voice.tier || 'balanced';
99
- const voiceTimeout = voice.timeout || 600000;
99
+ const voiceTimeout = voice.timeout || ProviderClass?.defaultTimeout || 600000;
100
100
 
101
101
  // Wrap progress callback with voice-centric metadata
102
102
  const voiceProgressCallback = progressCallback ? (update) => {
@@ -319,7 +319,10 @@ class Analyzer {
319
319
  const runId = options.runId || uuidv4();
320
320
  const { analysisId, skipRunCreation, skipLevel3, reviewerNum, excludePrevious, serverPort } = options;
321
321
  const logPrefix = options.logPrefix || '';
322
- const executionTimeout = options.timeout || 600000; // Default 10 minutes
322
+ // Respect provider-configured timeout (e.g. Pi's 15 min, executable providers)
323
+ const ProviderClass = getProviderClass(this.provider);
324
+ const providerTimeout = ProviderClass?.defaultTimeout;
325
+ const executionTimeout = options.timeout || providerTimeout || 600000; // Default 10 minutes
323
326
 
324
327
  // Resolve enabledLevels: prefer explicit option, fall back to skipLevel3 compat
325
328
  const enabledLevels = options.enabledLevels
@@ -3396,6 +3399,7 @@ File-level suggestions should NOT have a line number. They apply to the entire f
3396
3399
  : voice.customInstructions;
3397
3400
  }
3398
3401
 
3402
+ const VoiceProviderClass = getProviderClass(voice.provider);
3399
3403
  voiceTasks.push({
3400
3404
  voiceId,
3401
3405
  reviewerLabel,
@@ -3404,7 +3408,7 @@ File-level suggestions should NOT have a line number. They apply to the entire f
3404
3408
  provider: voice.provider,
3405
3409
  model: voice.model,
3406
3410
  tier,
3407
- timeout: voice.timeout || 600000,
3411
+ timeout: voice.timeout || VoiceProviderClass?.defaultTimeout || 600000,
3408
3412
  customInstructions: voiceInstructions,
3409
3413
  voiceCustomInstructions: voice.customInstructions || null
3410
3414
  });
@@ -522,6 +522,11 @@ function createExecutableProviderClass(id, config) {
522
522
  ExecProvider.getDefaultModel = () => resolveDefaultModel(models) || models[0]?.id;
523
523
  ExecProvider.getInstallInstructions = () => config.installInstructions || `Install ${id}`;
524
524
 
525
+ // Surface configured timeout so the UI can pre-populate TimeoutSelect
526
+ if (config.timeout != null) {
527
+ ExecProvider.defaultTimeout = config.timeout;
528
+ }
529
+
525
530
  // Flags for the system
526
531
  ExecProvider.isExecutable = true;
527
532
  const caps = config.capabilities || {};
@@ -123,9 +123,11 @@ Assess severity based on the evidence and reasoning across all reviewers. When r
123
123
 
124
124
  <section name="summary-synthesis" required="true">
125
125
  ## Summary Synthesis
126
- The summary field should synthesize the findings, not list them.
127
- - Synthesize the key findings into a single cohesive paragraph
128
- - **Draw on reviewer summaries**: Use these as evidence for your own synthesis integrate their insights into a cohesive conclusion rather than listing them individually
126
+ The summary field should synthesize the findings, but it should not be one big paragraph.
127
+ - Start with 1-2 sentences describing the overall assessment
128
+ - Then include a markdown bullet list using "- " bullets for the key specific points
129
+ - **Draw on reviewer summaries**: Use these as evidence for your own synthesis — integrate their insights into the overview and bullets rather than listing reviewer-by-reviewer conclusions
130
+ - After the bullets, add extra sentences or short paragraphs only when needed for requested context or follow-up detail
129
131
  - Write as if a single reviewer produced this analysis — do not mention consolidation, merging, or multiple reviewers
130
132
  </section>
131
133
 
@@ -160,7 +162,7 @@ Output JSON with this structure:
160
162
  "confidence": 0.0-1.0,
161
163
  "reasoning": ["Step-by-step reasoning explaining why this issue was flagged (optional)"]
162
164
  }],
163
- "summary": "Single cohesive paragraph summarizing key findings. Write as a single reviewer."
165
+ "summary": "Formatted markdown summary following the Summary Synthesis guidance above."
164
166
  }
165
167
 
166
168
  ### GitHub Suggestion Syntax
@@ -83,7 +83,11 @@ Deduplicate, don't concatenate: merge duplicate findings, preserve distinct ones
83
83
  </section>
84
84
 
85
85
  <section name="summary-synthesis" required="true" tier="fast">
86
- Draw on reviewer summaries as evidence for your own synthesis. Write one cohesive paragraph no mention of consolidation/merging.
86
+ Draw on reviewer summaries as evidence for your own synthesis. The summary field should be markdown, not one big paragraph.
87
+ - Start with 1-2 sentences describing the overall assessment
88
+ - Then include a markdown bullet list using "- " bullets for the key specific points
89
+ - After the bullets, add extra sentences or short paragraphs only when needed for requested context or follow-up detail
90
+ - Write as a single reviewer with no mention of consolidation or merging
87
91
  </section>
88
92
 
89
93
  <section name="output-schema" locked="true">
@@ -109,7 +113,7 @@ Draw on reviewer summaries as evidence for your own synthesis. Write one cohesiv
109
113
  "suggestion": "How to address the file-level concern (omit for praise items)",
110
114
  "confidence": 0.0-1.0
111
115
  }],
112
- "summary": "Single cohesive paragraph of key findings. Write as single reviewer."
116
+ "summary": "Formatted markdown summary following the summary guidance above."
113
117
  }
114
118
 
115
119
  ### GitHub Suggestion Syntax
@@ -167,13 +167,14 @@ Note: Confidence is about certainty of value, not severity.
167
167
 
168
168
  <section name="summary-synthesis" required="true" tier="thorough">
169
169
  ## Summary Synthesis Guidance
170
- The summary field should synthesize the findings, not list them.
170
+ The summary field should synthesize the findings, but it should not be one big paragraph.
171
171
 
172
172
  **Effective Summary Approach:**
173
- - **Lead with the most important insight**: What should the reviewer focus on first?
174
- - **Connect the dots**: How do individual findings relate to each other?
175
- - **Calibrate severity**: Is this code fundamentally sound with minor issues, or are there structural problems?
176
- - **Draw on reviewer summaries**: Use these as evidence for your own synthesis — integrate their insights into a cohesive conclusion rather than listing them individually.
173
+ - **Start with 1-2 sentences of overall assessment**: Lead with the most important insight and calibrate the overall severity
174
+ - **Then use a markdown bullet list with "- " bullets**: Capture the key specific points the reviewer should keep in view
175
+ - **Connect the dots**: Make the overview and bullets feel like one coherent review, not disconnected fragments
176
+ - **Draw on reviewer summaries**: Use these as evidence for your own synthesis — integrate their insights into the overview and bullets rather than listing reviewer-by-reviewer conclusions.
177
+ - **After the bullets, add extra sentences or short paragraphs only when needed**: Use them for requested context, caveats, or follow-up detail
177
178
  - **Write as a single reviewer**: Do not mention consolidation, merging, or multiple reviewers -- unless specifically requested
178
179
  </section>
179
180
 
@@ -208,7 +209,7 @@ Output JSON with this structure:
208
209
  "confidence": 0.0-1.0,
209
210
  "reasoning": ["Step-by-step reasoning explaining why this issue was flagged"]
210
211
  }],
211
- "summary": "Single cohesive paragraph synthesizing key findings and their significance. Write as a single reviewer — do not mention consolidation, merging, or multiple reviewers."
212
+ "summary": "Formatted markdown summary following the Summary Synthesis Guidance above."
212
213
  }
213
214
 
214
215
  ### GitHub Suggestion Syntax
@@ -121,6 +121,16 @@ Prioritize suggestions in this order:
121
121
  - **Provide context** for why each suggestion matters to the reviewer
122
122
  </section>
123
123
 
124
+ <section name="summary-synthesis" required="true">
125
+ ## Summary Structure
126
+ The summary field should synthesize the findings, but it should not be one big paragraph.
127
+ - Start with 1-2 sentences describing the overall assessment
128
+ - Then include a markdown bullet list using "- " bullets for the key specific points
129
+ - After the bullets, add extra sentences or short paragraphs only when needed for requested context or follow-up detail
130
+ - Focus on WHAT was found, not HOW it was found
131
+ - Write as if a single reviewer produced this analysis
132
+ </section>
133
+
124
134
  <section name="output-schema" locked="true">
125
135
  ## Output Format
126
136
 
@@ -151,7 +161,7 @@ Output JSON with this structure:
151
161
  "confidence": 0.0-1.0,
152
162
  "reasoning": ["Step-by-step reasoning explaining why this issue was flagged (optional)"]
153
163
  }],
154
- "summary": "Brief summary of the key findings and their significance to the reviewer. Focus on WHAT was found, not HOW it was found. Do NOT mention 'orchestration', 'levels', 'merged from Level 1/2/3' etc. Write as if a single reviewer produced this analysis."
164
+ "summary": "Formatted markdown summary following the Summary Structure guidance above."
155
165
  }
156
166
 
157
167
  ### GitHub Suggestion Syntax
@@ -218,6 +228,7 @@ const sections = [
218
228
  { name: 'priority-curation', required: true },
219
229
  { name: 'balanced-output', required: true },
220
230
  { name: 'human-centric-framing', required: true },
231
+ { name: 'summary-synthesis', required: true },
221
232
  { name: 'output-schema', locked: true },
222
233
  { name: 'diff-instructions', required: true },
223
234
  { name: 'file-level-guidance', optional: true, tier: ['balanced', 'thorough'] },
@@ -240,6 +251,7 @@ const defaultOrder = [
240
251
  'priority-curation',
241
252
  'balanced-output',
242
253
  'human-centric-framing',
254
+ 'summary-synthesis',
243
255
  'output-schema',
244
256
  'diff-instructions',
245
257
  'file-level-guidance',
@@ -103,6 +103,15 @@ Max 2-3 praise items. Prefer line-level over file-level. Include actionable sugg
103
103
  Use "Consider...", "Worth noting..." - guidance not mandates.
104
104
  </section>
105
105
 
106
+ <section name="summary-synthesis" required="true" tier="fast">
107
+ ### Summary
108
+ The summary field should be markdown, not one big paragraph.
109
+ - Start with 1-2 sentences describing the overall assessment
110
+ - Then include a markdown bullet list using "- " bullets for the key specific points
111
+ - After the bullets, add extra sentences or short paragraphs only when needed for requested context or follow-up detail
112
+ - Write as a single reviewer; do not mention levels or orchestration
113
+ </section>
114
+
106
115
  <section name="output-schema" locked="true">
107
116
  ## JSON Schema
108
117
  {
@@ -127,7 +136,7 @@ Use "Consider...", "Worth noting..." - guidance not mandates.
127
136
  "suggestion": "How to fix (omit for praise)",
128
137
  "confidence": 0.0-1.0
129
138
  }],
130
- "summary": "Key findings as if from single reviewer (no mention of levels/orchestration)"
139
+ "summary": "Formatted markdown summary following the Summary guidance above."
131
140
  }
132
141
 
133
142
  ### GitHub Suggestion Syntax
@@ -167,6 +176,7 @@ const sections = [
167
176
  { name: 'priority-curation', required: true, tier: ['fast'] },
168
177
  { name: 'balanced-output', required: true, tier: ['fast'] },
169
178
  { name: 'human-centric-framing', required: true, tier: ['fast'] },
179
+ { name: 'summary-synthesis', required: true, tier: ['fast'] },
170
180
  { name: 'output-schema', locked: true },
171
181
  { name: 'diff-instructions', required: true, tier: ['fast'] },
172
182
  { name: 'guidelines', required: true, tier: ['fast'] }
@@ -189,6 +199,7 @@ const defaultOrder = [
189
199
  'priority-curation',
190
200
  'balanced-output',
191
201
  'human-centric-framing',
202
+ 'summary-synthesis',
192
203
  'output-schema',
193
204
  'diff-instructions',
194
205
  'guidelines'
@@ -248,20 +248,21 @@ Note: Confidence is about certainty of value, not severity. A minor improvement
248
248
 
249
249
  <section name="summary-synthesis" required="true" tier="thorough">
250
250
  ## Summary Synthesis Guidance
251
- The summary field is not a list of findings - it's a synthesis that helps the reviewer see the forest, not just the trees.
251
+ The summary field should help the reviewer see the forest, not just the trees, but it should not be one big paragraph.
252
252
 
253
253
  **Effective Summary Approach:**
254
- - **Synthesize, don't summarize**: Identify the overarching narrative of this PR's quality and concerns
255
- - **Lead with the most important insight**: What single thing should the reviewer understand first?
256
- - **Connect the dots**: How do individual findings relate to each other or to a common theme?
257
- - **Calibrate severity**: Is this PR fundamentally sound with minor issues, or does it have structural problems?
254
+ - **Start with 1-2 sentences of overall assessment**: Identify the overarching narrative of this PR's quality and concerns
255
+ - **Then use a markdown bullet list with "- " bullets**: Capture the key specific points the reviewer should track
256
+ - **Connect the dots**: Make the overview and bullets feel like one coherent review
257
+ - **Calibrate severity**: Make clear whether this PR is fundamentally sound with minor issues or has structural problems
258
+ - **After the bullets, add extra sentences or short paragraphs only when needed**: Use them for requested context, caveats, or follow-up detail
258
259
  - **Respect reviewer time**: A good summary lets the reviewer decide where to focus attention
259
260
 
260
261
  **Summary Anti-patterns to Avoid:**
261
262
  - Listing findings ("Found 3 bugs, 2 improvements, 1 praise...")
262
263
  - Implementation details ("Merged Level 1 and Level 2 suggestions...")
263
264
  - Vague platitudes ("This PR has some issues to consider...")
264
- - Excessive length (2-3 sentences is ideal)
265
+ - A single unbroken paragraph with no bullets
265
266
  </section>
266
267
 
267
268
  <section name="output-schema" locked="true">
@@ -294,7 +295,7 @@ Output JSON with this structure:
294
295
  "confidence": 0.0-1.0,
295
296
  "reasoning": ["Step-by-step reasoning explaining why this issue was flagged"]
296
297
  }],
297
- "summary": "Brief summary of the key findings and their significance to the reviewer. Focus on WHAT was found, not HOW it was found. Do NOT mention 'orchestration', 'levels', 'merged from Level 1/2/3' etc. Write as if a single reviewer produced this analysis."
298
+ "summary": "Formatted markdown summary following the Summary Synthesis Guidance above."
298
299
  }
299
300
 
300
301
  ### GitHub Suggestion Syntax