diff --git a/apps/hook/commands/plannotator-review.md b/apps/hook/commands/plannotator-review.md index a8d8dd692..433fa1328 100644 --- a/apps/hook/commands/plannotator-review.md +++ b/apps/hook/commands/plannotator-review.md @@ -9,4 +9,4 @@ allowed-tools: Bash(plannotator:*) ## Your task -Address the code review feedback above. The user has reviewed your changes in the Plannotator UI and provided specific annotations and comments. +If the review above contains feedback or annotations, address them. If no changes were requested, acknowledge and continue. diff --git a/apps/hook/server/index.ts b/apps/hook/server/index.ts index 98b87db09..0fb5c81a8 100644 --- a/apps/hook/server/index.ts +++ b/apps/hook/server/index.ts @@ -183,7 +183,12 @@ if (args[0] === "sessions") { server.stop(); // Output feedback (captured by slash command) - console.log(result.feedback || "No feedback provided."); + if (result.approved) { + console.log("Code review completed — no changes requested."); + } else { + console.log(result.feedback); + console.log("\nThe reviewer has identified issues above. You must address all of them."); + } process.exit(0); } else if (args[0] === "annotate") { diff --git a/apps/opencode-plugin/index.ts b/apps/opencode-plugin/index.ts index 949caadf1..1a43854b7 100644 --- a/apps/opencode-plugin/index.ts +++ b/apps/opencode-plugin/index.ts @@ -221,7 +221,11 @@ Do NOT proceed with implementation until your plan is approved. const shouldSwitchAgent = result.agentSwitch && result.agentSwitch !== 'disabled'; const targetAgent = result.agentSwitch || 'build'; - // Send feedback to agent - it will automatically respond and address it + const message = result.approved + ? `# Code Review\n\nCode review completed — no changes requested.` + : `# Code Review Feedback\n\n${result.feedback}\n\nPlease address this feedback.`; + + // Send feedback to agent try { await ctx.client.session.prompt({ path: { id: sessionId }, @@ -230,7 +234,7 @@ Do NOT proceed with implementation until your plan is approved. parts: [ { type: "text", - text: `# Code Review Feedback\n\n${result.feedback}\n\nPlease address this feedback.`, + text: message, }, ], }, diff --git a/apps/pi-extension/index.ts b/apps/pi-extension/index.ts index 1c8e724bd..ce46de777 100644 --- a/apps/pi-extension/index.ts +++ b/apps/pi-extension/index.ts @@ -255,7 +255,11 @@ export default function plannotator(pi: ExtensionAPI): void { server.stop(); if (result.feedback) { - pi.sendUserMessage(`# Code Review Feedback\n\n${result.feedback}\n\nPlease address this feedback.`); + if (result.approved) { + pi.sendUserMessage(`# Code Review\n\nCode review completed — no changes requested.`); + } else { + pi.sendUserMessage(`# Code Review Feedback\n\n${result.feedback}\n\nPlease address this feedback.`); + } } else { ctx.ui.notify("Code review closed (no feedback).", "info"); } diff --git a/apps/pi-extension/server.ts b/apps/pi-extension/server.ts index 75795a2b1..bf8ff3d69 100644 --- a/apps/pi-extension/server.ts +++ b/apps/pi-extension/server.ts @@ -349,7 +349,7 @@ export interface GitContext { export interface ReviewServerResult { port: number; url: string; - waitForDecision: () => Promise<{ feedback: string }>; + waitForDecision: () => Promise<{ approved: boolean; feedback: string }>; stop: () => void; } @@ -415,8 +415,8 @@ export function startReviewServer(options: { let currentGitRef = options.gitRef; let currentDiffType: DiffType = options.diffType || "uncommitted"; - let resolveDecision!: (result: { feedback: string }) => void; - const decisionPromise = new Promise<{ feedback: string }>((r) => { + let resolveDecision!: (result: { approved: boolean; feedback: string }) => void; + const decisionPromise = new Promise<{ approved: boolean; feedback: string }>((r) => { resolveDecision = r; }); @@ -446,7 +446,10 @@ export function startReviewServer(options: { json(res, { rawPatch: currentPatch, gitRef: currentGitRef, diffType: currentDiffType }); } else if (url.pathname === "/api/feedback" && req.method === "POST") { const body = await parseBody(req); - resolveDecision({ feedback: (body.feedback as string) || "" }); + resolveDecision({ + approved: (body.approved as boolean) ?? false, + feedback: (body.feedback as string) || "", + }); json(res, { ok: true }); } else { html(res, options.htmlContent); diff --git a/apps/review/server/index.ts b/apps/review/server/index.ts index 2c786bcab..1c27b2b0d 100644 --- a/apps/review/server/index.ts +++ b/apps/review/server/index.ts @@ -88,6 +88,7 @@ server.stop(); console.log( JSON.stringify({ gitRef: displayRef, + approved: result.approved, feedback: result.feedback, annotations: result.annotations, }, null, 2) diff --git a/bun.lock b/bun.lock index 858d55ef8..8cadb9c43 100644 --- a/bun.lock +++ b/bun.lock @@ -50,7 +50,7 @@ }, "apps/opencode-plugin": { "name": "@plannotator/opencode", - "version": "0.11.4", + "version": "0.12.0", "dependencies": { "@opencode-ai/plugin": "^1.1.10", }, @@ -71,7 +71,7 @@ }, "apps/pi-extension": { "name": "@plannotator/pi-extension", - "version": "0.11.4", + "version": "0.12.0", "peerDependencies": { "@mariozechner/pi-coding-agent": ">=0.53.0", }, @@ -151,7 +151,7 @@ }, "packages/server": { "name": "@plannotator/server", - "version": "0.11.4", + "version": "0.12.0", "dependencies": { "@plannotator/shared": "workspace:*", }, diff --git a/packages/review-editor/App.tsx b/packages/review-editor/App.tsx index ab7bad579..929c7e070 100644 --- a/packages/review-editor/App.tsx +++ b/packages/review-editor/App.tsx @@ -504,6 +504,7 @@ const ReviewApp: React.FC = () => { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ + approved: false, feedback: feedbackMarkdown, annotations, ...(effectiveAgent && { agentSwitch: effectiveAgent }), @@ -530,7 +531,8 @@ const ReviewApp: React.FC = () => { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ - feedback: 'LGTM - no changes requested.', + approved: true, + feedback: 'LGTM - no changes requested.', // unused — integrations branch on `approved` flag annotations: [], }), }); diff --git a/packages/server/review.ts b/packages/server/review.ts index bb16c9f91..7ed4e9e8a 100644 --- a/packages/server/review.ts +++ b/packages/server/review.ts @@ -56,8 +56,9 @@ export interface ReviewServerResult { url: string; /** Whether running in remote mode */ isRemote: boolean; - /** Wait for user feedback submission */ + /** Wait for user review decision */ waitForDecision: () => Promise<{ + approved: boolean; feedback: string; annotations: unknown[]; agentSwitch?: string; @@ -101,11 +102,13 @@ export async function startReviewServer( // Decision promise let resolveDecision: (result: { + approved: boolean; feedback: string; annotations: unknown[]; agentSwitch?: string; }) => void; const decisionPromise = new Promise<{ + approved: boolean; feedback: string; annotations: unknown[]; agentSwitch?: string; @@ -259,6 +262,7 @@ export async function startReviewServer( if (url.pathname === "/api/feedback" && req.method === "POST") { try { const body = (await req.json()) as { + approved?: boolean; feedback: string; annotations: unknown[]; agentSwitch?: string; @@ -266,6 +270,7 @@ export async function startReviewServer( deleteDraft(draftKey); resolveDecision({ + approved: body.approved ?? false, feedback: body.feedback || "", annotations: body.annotations || [], agentSwitch: body.agentSwitch,