refactor(FN-5633): AI merge reviewer uses the project reviewer/validator model
Drop the bespoke `merger.reviewerModel` setting. The AI merge reviewer now resolves its model via `resolveValidatorSettingsModel` — the same reviewer/validator lane used elsewhere (project validator → global validator → project default) — falling back to the merger model only if that lane is empty. Removes the setting from the type, schema default, and the Settings UI. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -262,7 +262,7 @@ export const DEFAULT_PROJECT_SETTINGS = {
|
||||
],
|
||||
prerebaseDivergenceThreshold: 50,
|
||||
mergeConflictStrategy: "smart-prefer-main",
|
||||
merger: { mode: "ai", reviewerModel: undefined, maxReviewPasses: 3 },
|
||||
merger: { mode: "ai", maxReviewPasses: 3 },
|
||||
mergeDiffVolumeMinLines: undefined,
|
||||
mergeDiffVolumeThreshold: undefined,
|
||||
mergeDiffVolumeAllowlist: undefined,
|
||||
|
||||
@@ -336,10 +336,9 @@ export function normalizeMergerMode(value: unknown): MergerMode {
|
||||
export interface MergerSettings {
|
||||
/** Which merge path to use. Default: "ai". */
|
||||
mode?: MergerMode;
|
||||
/** Optional `provider/modelId` override for the read-only reviewer agent. */
|
||||
reviewerModel?: string;
|
||||
/** How many AI corrective rounds before landing the best result (advisory) or
|
||||
* hard-failing (blocking). Default: 3. */
|
||||
* hard-failing (blocking). Default: 3. The reviewer uses the project's
|
||||
* validator/reviewer model lane — there is no merge-specific model setting. */
|
||||
maxReviewPasses?: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -4626,20 +4626,7 @@ export function SettingsModal({
|
||||
setForm((f) => ({ ...f, merger: { ...(f.merger ?? {}), maxReviewPasses: e.target.value === "" ? undefined : Number(e.target.value) } }))
|
||||
}
|
||||
/>
|
||||
<small>AI corrective rounds before landing the best result (advisory concern) or hard-failing (unfixable correctness concern). Default 3.</small>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="mergerReviewerModel">Reviewer model (optional)</label>
|
||||
<input
|
||||
id="mergerReviewerModel"
|
||||
type="text"
|
||||
placeholder="provider/modelId — defaults to the merger model"
|
||||
value={form.merger?.reviewerModel ?? ""}
|
||||
onChange={(e) =>
|
||||
setForm((f) => ({ ...f, merger: { ...(f.merger ?? {}), reviewerModel: e.target.value || undefined } }))
|
||||
}
|
||||
/>
|
||||
<small>Model for the read-only reviewer agent (a cheaper/faster model is fine). Leave blank to reuse the merger model.</small>
|
||||
<small>AI corrective rounds before landing the best result (advisory concern) or hard-failing (unfixable correctness concern). Default 3. The reviewer uses your project's reviewer/validator model.</small>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -36,6 +36,7 @@ import { join } from "node:path";
|
||||
import {
|
||||
getTaskMergeBlocker,
|
||||
resolveTaskMergeTarget,
|
||||
resolveValidatorSettingsModel,
|
||||
type MergeResult,
|
||||
type Settings,
|
||||
type Task,
|
||||
@@ -346,10 +347,11 @@ function makeMutatingAgent(store: TaskStore, settings: Settings, taskId: string,
|
||||
|
||||
function makeReviewAgent(store: TaskStore, settings: Settings, taskId: string, options: MergerOptions, audit: RunAuditor) {
|
||||
return async (cwd: string, prompt: string): Promise<string> => {
|
||||
const override = settings.merger?.reviewerModel?.trim();
|
||||
const model = override
|
||||
? parseModelOverride(override, settings)
|
||||
: resolveMergerSessionModel(settings);
|
||||
// The reviewer uses the project's validator/reviewer model lane (the same
|
||||
// one used elsewhere for review), falling back to the merger model only if
|
||||
// that lane resolves to nothing.
|
||||
const validator = resolveValidatorSettingsModel(settings);
|
||||
const model = validator.provider && validator.modelId ? validator : resolveMergerSessionModel(settings);
|
||||
let captured = "";
|
||||
const { session } = await createResolvedAgentSession({
|
||||
sessionPurpose: "merger",
|
||||
@@ -384,14 +386,6 @@ function makeReviewAgent(store: TaskStore, settings: Settings, taskId: string, o
|
||||
};
|
||||
}
|
||||
|
||||
function parseModelOverride(value: string, settings: Settings): { provider: string | undefined; modelId: string | undefined } {
|
||||
const slash = value.indexOf("/");
|
||||
if (slash > 0 && slash < value.length - 1) {
|
||||
return { provider: value.slice(0, slash), modelId: value.slice(slash + 1) };
|
||||
}
|
||||
return { provider: resolveMergerSessionModel(settings).provider, modelId: value };
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Local checkout sync
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user