feat: default reviewer is always claude-code (#2241) - temporary change

This commit is contained in:
neversettle 2026-06-30 21:25:26 +05:30 committed by GitHub
parent 78cbe22928
commit 010c7e4c1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 43 additions and 14 deletions

View File

@ -39,7 +39,7 @@ type ProjectConfig struct {
// Reviewers names the agent(s) that review a worker's PR when a review is // Reviewers names the agent(s) that review a worker's PR when a review is
// triggered. It is configured independently of the Worker override; an empty // triggered. It is configured independently of the Worker override; an empty
// list falls back to the worker's own harness (see ResolveReviewerHarness). // list falls back to claude-code (see ResolveReviewerHarness).
Reviewers []ReviewerConfig `json:"reviewers,omitempty"` Reviewers []ReviewerConfig `json:"reviewers,omitempty"`
} }
@ -55,15 +55,11 @@ type ReviewerConfig struct {
const FallbackReviewerHarness = ReviewerClaudeCode const FallbackReviewerHarness = ReviewerClaudeCode
// ResolveReviewerHarness picks the reviewer harness for a worker. A configured // ResolveReviewerHarness picks the reviewer harness for a worker. A configured
// reviewer wins; otherwise it reuses the worker's own harness when that harness // reviewer wins; otherwise claude-code is used.
// is also a supported reviewer, falling back to claude-code. func (c ProjectConfig) ResolveReviewerHarness(_ AgentHarness) ReviewerHarness {
func (c ProjectConfig) ResolveReviewerHarness(workerHarness AgentHarness) ReviewerHarness {
if len(c.Reviewers) > 0 { if len(c.Reviewers) > 0 {
return c.Reviewers[0].Harness return c.Reviewers[0].Harness
} }
if h := ReviewerHarness(workerHarness); h.IsKnown() {
return h
}
return FallbackReviewerHarness return FallbackReviewerHarness
} }

View File

@ -80,13 +80,12 @@ func TestResolveReviewerHarness(t *testing.T) {
t.Fatalf("configured reviewer = %q, want claude-code", got) t.Fatalf("configured reviewer = %q, want claude-code", got)
} }
// No reviewer configured: reuse the worker harness when it is also a // No reviewer configured: always use claude-code.
// supported reviewer (claude-code is).
if got := (ProjectConfig{}).ResolveReviewerHarness(HarnessClaudeCode); got != ReviewerClaudeCode { if got := (ProjectConfig{}).ResolveReviewerHarness(HarnessClaudeCode); got != ReviewerClaudeCode {
t.Fatalf("default = %q, want reviewer claude-code", got) t.Fatalf("default = %q, want reviewer claude-code", got)
} }
// A worker harness that is not a supported reviewer falls back to claude-code. // A worker harness that is not claude-code also falls back to claude-code.
if got := (ProjectConfig{}).ResolveReviewerHarness(HarnessAider); got != FallbackReviewerHarness { if got := (ProjectConfig{}).ResolveReviewerHarness(HarnessAider); got != FallbackReviewerHarness {
t.Fatalf("fallback = %q, want %q", got, FallbackReviewerHarness) t.Fatalf("fallback = %q, want %q", got, FallbackReviewerHarness)
} }

View File

@ -375,8 +375,7 @@ func (e *Engine) List(ctx stdctx.Context, workerID domain.SessionID) (SessionRev
} }
// reviewerHarness resolves which harness reviews the worker's PR: a configured // reviewerHarness resolves which harness reviews the worker's PR: a configured
// reviewer wins, otherwise the worker's own harness is reused (falling back to // reviewer wins, otherwise claude-code is used, per domain.ResolveReviewerHarness.
// claude-code), per domain.ResolveReviewerHarness.
func (e *Engine) reviewerHarness(ctx stdctx.Context, worker domain.SessionRecord) (domain.ReviewerHarness, error) { func (e *Engine) reviewerHarness(ctx stdctx.Context, worker domain.SessionRecord) (domain.ReviewerHarness, error) {
var cfg domain.ProjectConfig var cfg domain.ProjectConfig
if e.projects != nil { if e.projects != nil {

View File

@ -270,7 +270,7 @@ function ReviewerSelect({ id, value, onChange }: { id: string; value: string; on
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="__default__">Project default</SelectItem> <SelectItem value="__default__">claude-code (default)</SelectItem>
{REVIEWER_OPTIONS.map((reviewer) => ( {REVIEWER_OPTIONS.map((reviewer) => (
<SelectItem key={reviewer} value={reviewer}> <SelectItem key={reviewer} value={reviewer}>
{reviewer} {reviewer}

View File

@ -49,6 +49,11 @@ const session = (prs: PullRequestFacts[]): WorkspaceSession => ({
prs, prs,
}); });
const sessionWithProvider = (prs: PullRequestFacts[], provider: WorkspaceSession["provider"]): WorkspaceSession => ({
...session(prs),
provider,
});
function renderWithQuery(children: ReactNode) { function renderWithQuery(children: ReactNode) {
const client = new QueryClient({ const client = new QueryClient({
defaultOptions: { queries: { retry: false }, mutations: { retry: false } }, defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
@ -199,6 +204,36 @@ describe("SessionInspector reviews tab", () => {
expect(onOpenReviewerTerminal).toHaveBeenCalledWith({ handleId: "reviewer-pane", harness: "codex" }); expect(onOpenReviewerTerminal).toHaveBeenCalledWith({ handleId: "reviewer-pane", harness: "codex" });
}); });
it("shows claude-code as the default reviewer before a run exists", async () => {
getMock.mockImplementation(async (path: string) => {
if (path === "/api/v1/sessions/{sessionId}/reviews") {
return { data: { reviewerHandleId: "", reviews: [] } };
}
if (path === "/api/v1/projects/{id}") {
return {
data: {
status: "ok",
project: {
id: "ws-1",
kind: "git",
name: "my-app",
path: "/repo",
repo: "my-app",
defaultBranch: "main",
config: {},
},
},
};
}
return { data: undefined };
});
renderWithQuery(<SessionInspector session={sessionWithProvider([pr(3, "open")], "codex")} />);
await openReviewsTab();
expect(await screen.findByText("claude-code")).toBeInTheDocument();
});
it("shows eligible and up-to-date PR review rows", async () => { it("shows eligible and up-to-date PR review rows", async () => {
mockCommonGets([approvedReview], "reviewer-pane", [ mockCommonGets([approvedReview], "reviewer-pane", [
reviewState(3, "needs_review", "abc123"), reviewState(3, "needs_review", "abc123"),

View File

@ -483,7 +483,7 @@ function ReviewPanel({
} }
const latest = reviewStates.find((review) => review.latestRun)?.latestRun; const latest = reviewStates.find((review) => review.latestRun)?.latestRun;
const harness = latest?.harness || config?.reviewers?.[0]?.harness || session.provider || "reviewer"; const harness = latest?.harness || config?.reviewers?.[0]?.harness || "claude-code";
const terminalEnabled = Boolean(reviewerHandleId && onOpenTerminal); const terminalEnabled = Boolean(reviewerHandleId && onOpenTerminal);
const aggregateVerdict = sessionReviewVerdict(reviewStates); const aggregateVerdict = sessionReviewVerdict(reviewStates);
const runAction = reviewSessionRunAction(reviewStates, isTriggering); const runAction = reviewSessionRunAction(reviewStates, isTriggering);