@in-the-loop-labs/pair-review 2.5.0 → 2.6.0

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.
@@ -205,10 +205,13 @@ async function runTask(
205
205
  onUpdate: OnUpdate | undefined,
206
206
  makeDetails: (results: TaskResult[]) => TaskDetails,
207
207
  ): Promise<TaskResult> {
208
- // Build args: full tool access, JSON output, no session persistence
208
+ // Build args: full tool access, JSON output, no session persistence.
209
+ // Skills and extensions are left enabled so subtasks have access to the
210
+ // user's configured environment. --no-prompt-templates is kept because
211
+ // prompt templates can't be triggered in -p mode.
209
212
  const args: string[] = [
210
213
  "--mode", "json", "-p", "--no-session",
211
- "--no-extensions", "--no-skills", "--no-prompt-templates",
214
+ "--no-prompt-templates",
212
215
  "-e", EXTENSION_DIR,
213
216
  ];
214
217
  if (model) {
@@ -0,0 +1 @@
1
+ {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@in-the-loop-labs/pair-review",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
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": {
@@ -14,6 +14,7 @@
14
14
  "public/",
15
15
  "plugin/",
16
16
  "plugin-code-critic/",
17
+ "config.managed.json",
17
18
  "README.md",
18
19
  "LICENSE"
19
20
  ],
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pair-review",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
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": "2.5.0",
3
+ "version": "2.6.0",
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",
@@ -174,7 +174,14 @@ class ClaudeProvider extends AIProvider {
174
174
  ].join(',');
175
175
  permissionArgs = ['--allowedTools', allowedTools];
176
176
  }
177
- const baseArgs = ['-p', '--verbose', ...cliModelArgs, '--output-format', 'stream-json', ...permissionArgs];
177
+ // Suppress user hooks in analysis subprocesses to avoid side-effects
178
+ // (notifications, confirmations, etc.) firing on every tool call during review.
179
+ // Uses --settings '{"disableAllHooks":true}' since Claude has no --no-hooks flag.
180
+ // Skills and extensions are left enabled so the subprocess has access to the
181
+ // user's configured environment. To disable skills, add --disable-slash-commands
182
+ // to extra_args in provider/model config.
183
+ const hooksArgs = ['--settings', '{"disableAllHooks":true}'];
184
+ const baseArgs = ['-p', '--verbose', ...cliModelArgs, '--output-format', 'stream-json', ...hooksArgs, ...permissionArgs];
178
185
  if (maxBudget) {
179
186
  const budgetNum = parseFloat(maxBudget);
180
187
  if (isNaN(budgetNum) || budgetNum <= 0) {
@@ -23,7 +23,8 @@ const BIN_DIR = path.join(__dirname, '..', '..', 'bin');
23
23
  * Based on OpenAI Codex Models guide (developers.openai.com/codex/models)
24
24
  * - gpt-5.1-codex-mini: Smaller, cost-effective variant for quick scans
25
25
  * - gpt-5.2-codex: Advanced coding model for everyday reviews, good reasoning/cost balance
26
- * - gpt-5.3-codex: Most capable agentic coding model with frontier performance and reasoning
26
+ * - gpt-5.3-codex: Capable agentic coding model with frontier performance and reasoning
27
+ * - gpt-5.4: Latest generation with enhanced reasoning depth
27
28
  */
28
29
  const CODEX_MODELS = [
29
30
  {
@@ -50,7 +51,16 @@ const CODEX_MODELS = [
50
51
  name: 'GPT-5.3 Codex',
51
52
  tier: 'thorough',
52
53
  tagline: 'Deep Review',
53
- description: 'Most capable agentic coding model—combines frontier coding performance with stronger reasoning for deep cross-file analysis.',
54
+ description: 'Capable agentic coding model—combines frontier coding performance with strong reasoning for cross-file analysis.',
55
+ badge: 'Thorough',
56
+ badgeClass: 'badge-power'
57
+ },
58
+ {
59
+ id: 'gpt-5.4',
60
+ name: 'GPT-5.4',
61
+ tier: 'thorough',
62
+ tagline: 'Latest Gen',
63
+ description: 'Latest generation model with enhanced reasoning depth for complex architectural reviews.',
54
64
  badge: 'Most Thorough',
55
65
  badgeClass: 'badge-power'
56
66
  }
@@ -143,6 +143,24 @@ const CURSOR_AGENT_MODELS = [
143
143
  description: 'Deep analysis with extended thinking—Cursor default for maximum review quality',
144
144
  badge: 'Most Thorough',
145
145
  badgeClass: 'badge-power'
146
+ },
147
+ {
148
+ id: 'gpt-5.4-high',
149
+ name: 'GPT-5.4 High',
150
+ tier: 'thorough',
151
+ tagline: 'Latest OpenAI',
152
+ description: 'Latest generation with high reasoning effort—strong for complex architectural reviews',
153
+ badge: 'Latest Gen',
154
+ badgeClass: 'badge-power'
155
+ },
156
+ {
157
+ id: 'gpt-5.4-medium',
158
+ name: 'GPT-5.4',
159
+ tier: 'thorough',
160
+ tagline: 'Latest Gen',
161
+ description: 'Latest generation at medium reasoning depth',
162
+ badge: 'Latest',
163
+ badgeClass: 'badge-power'
146
164
  }
147
165
  ];
148
166
 
@@ -189,24 +189,23 @@ class PiProvider extends AIProvider {
189
189
  // --no-session: Each pi invocation is an ephemeral analysis — there's no need to
190
190
  // persist session state between runs. Set PAIR_REVIEW_PI_SESSION=1
191
191
  // to enable session saving for debugging (sessions saved to ~/.pi/sessions/).
192
- // --no-skills: Skills are disabled by default to keep runs deterministic. A skill can
193
- // still be loaded via `--skill` in model-specific `extra_args` if needed.
194
-
195
192
  // Build args: base args + built-in extra_args + provider extra_args + model extra_args
196
193
  // In yolo mode, omit --tools entirely to allow all tools (including edit, write)
197
194
  // The task extension is loaded to give the model a subagent tool for delegating
198
195
  // work to isolated subprocesses, preserving the main context window.
199
- // --no-extensions prevents auto-discovery of other extensions.
200
- // --no-skills and --no-prompt-templates keep the subprocess focused.
196
+ // --no-prompt-templates: prompt templates can't be triggered in -p mode, so suppress
197
+ // them to avoid wasting context. Skills and extensions are left enabled so the
198
+ // subprocess has access to the user's configured environment. To disable them,
199
+ // add --no-skills or --no-extensions to extra_args in provider/model config.
201
200
  const sessionArgs = process.env.PAIR_REVIEW_PI_SESSION ? [] : ['--no-session'];
202
201
  let baseArgs;
203
202
  if (configOverrides.yolo) {
204
203
  baseArgs = ['-p', '--mode', 'json', ...cliModelArgs, ...sessionArgs,
205
- '--no-extensions', '--no-skills', '--no-prompt-templates',
204
+ '--no-prompt-templates',
206
205
  '-e', TASK_EXTENSION_DIR];
207
206
  } else {
208
207
  baseArgs = ['-p', '--mode', 'json', ...cliModelArgs, '--tools', 'read,bash,grep,find,ls', ...sessionArgs,
209
- '--no-extensions', '--no-skills', '--no-prompt-templates',
208
+ '--no-prompt-templates',
210
209
  '-e', TASK_EXTENSION_DIR];
211
210
  }
212
211
  const builtInArgs = builtIn?.extra_args || [];
@@ -273,12 +273,9 @@ class PiBridge extends EventEmitter {
273
273
  }
274
274
 
275
275
  // Load extensions via -e (e.g., task extension for subagent delegation).
276
- // --no-extensions prevents auto-discovery; only explicitly listed ones load.
277
- if (this.extensions.length > 0) {
278
- args.push('--no-extensions');
279
- for (const ext of this.extensions) {
280
- args.push('-e', ext);
281
- }
276
+ // These are additive — the user's auto-discovered extensions remain available.
277
+ for (const ext of this.extensions) {
278
+ args.push('-e', ext);
282
279
  }
283
280
 
284
281
  return args;
package/src/config.js CHANGED
@@ -13,6 +13,7 @@ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
13
13
  const CONFIG_LOCAL_FILE = path.join(CONFIG_DIR, 'config.local.json');
14
14
  const CONFIG_EXAMPLE_FILE = path.join(CONFIG_DIR, 'config.example.json');
15
15
  const PACKAGE_ROOT = path.join(__dirname, '..');
16
+ const MANAGED_CONFIG_FILE = path.join(PACKAGE_ROOT, 'config.managed.json');
16
17
 
17
18
  const DEFAULT_CONFIG = {
18
19
  github_token: "",
@@ -175,6 +176,7 @@ async function loadConfig() {
175
176
 
176
177
  const localDir = path.join(process.cwd(), '.pair-review');
177
178
  const sources = [
179
+ { path: MANAGED_CONFIG_FILE, label: 'managed config', required: false },
178
180
  { path: CONFIG_FILE, label: 'global config', required: true },
179
181
  { path: CONFIG_LOCAL_FILE, label: 'global local config', required: false },
180
182
  { path: path.join(localDir, 'config.json'), label: 'project config', required: false },