From 18c8d34da692dd3fa7f76d800988d975d90869ba Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Wed, 15 Apr 2026 20:31:15 +0000 Subject: [PATCH] remove task list from review bodies; keep in progress comments only (#542) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit review bodies were embedding a task-list snapshot that could capture stale in-progress state due to timing between the agent's final TodoWrite and the review submission API call. progress comments are the authoritative checklist surface — remove the review-body embedding entirely so there is a single source of truth. also adds a `completeInProgress` option to `renderCollapsible` so the progress-comment path can finalize any in-progress items at render time without mutating tracker state. Made-with: Cursor --- mcp/comment.ts | 5 +++-- mcp/review.ts | 11 ----------- utils/todoTracking.ts | 11 ++++++++--- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/mcp/comment.ts b/mcp/comment.ts index a0a8574..3522221 100644 --- a/mcp/comment.ts +++ b/mcp/comment.ts @@ -349,8 +349,9 @@ export function ReportProgressTool(ctx: ToolContext) { if (!params.target_plan_comment && ctx.toolState.todoTracker) { ctx.toolState.todoTracker.cancel(); await ctx.toolState.todoTracker.settled(); - ctx.toolState.todoTracker.completeInProgress(); - const collapsible = ctx.toolState.todoTracker.renderCollapsible(); + const collapsible = ctx.toolState.todoTracker.renderCollapsible({ + completeInProgress: true, + }); if (collapsible) { body = `${body}\n\n${collapsible}`; } diff --git a/mcp/review.ts b/mcp/review.ts index 5c9b161..babbd8f 100644 --- a/mcp/review.ts +++ b/mcp/review.ts @@ -83,17 +83,6 @@ export function CreatePullRequestReviewTool(ctx: ToolContext) { execute: execute(async ({ pull_number, body, approved, commit_id, comments = [] }) => { if (body) body = fixDoubleEscapedString(body); - // in Review mode (not IncrementalReview), append the completed task list - if (body && ctx.toolState.selectedMode === "Review" && ctx.toolState.todoTracker) { - ctx.toolState.todoTracker.cancel(); - await ctx.toolState.todoTracker.settled(); - ctx.toolState.todoTracker.completeInProgress(); - const collapsible = ctx.toolState.todoTracker.renderCollapsible(); - if (collapsible) { - body = `${body}\n\n${collapsible}`; - } - } - // set issue context (PRs are issues) ctx.toolState.issueNumber = pull_number; diff --git a/utils/todoTracking.ts b/utils/todoTracking.ts index bf930fd..9e25be0 100644 --- a/utils/todoTracking.ts +++ b/utils/todoTracking.ts @@ -58,7 +58,7 @@ export type TodoTracker = { settled: () => Promise; /** mark in-progress items as completed (for final snapshot before review/progress post) */ completeInProgress: () => void; - renderCollapsible: () => string; + renderCollapsible: (options?: { completeInProgress?: boolean }) => string; readonly enabled: boolean; /** true after the tracker has successfully called onUpdate at least once */ readonly hasPublished: boolean; @@ -143,9 +143,14 @@ export function createTodoTracker(onUpdate: (body: string) => Promise): To } }, - renderCollapsible(): string { + renderCollapsible(options?: { completeInProgress?: boolean }): string { if (state.size === 0) return ""; - const todos = Array.from(state.values()); + const shouldCompleteInProgress = options?.completeInProgress === true; + const todos = Array.from(state.values()).map((item) => + shouldCompleteInProgress && item.status === "in_progress" + ? { ...item, status: "completed" as const } + : item + ); const completed = todos.filter((t) => t.status === "completed").length; const markdown = renderTodoMarkdown(todos); return `
\nTask list (${completed}/${todos.length} completed)\n\n${markdown}\n\n
`;