remove task list from review bodies; keep in progress comments only (#542)

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
This commit is contained in:
Colin McDonnell
2026-04-15 20:31:15 +00:00
committed by pullfrog[bot]
parent 7d85e653ca
commit 18c8d34da6
3 changed files with 11 additions and 16 deletions
+3 -2
View File
@@ -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}`;
}
-11
View File
@@ -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;
+8 -3
View File
@@ -58,7 +58,7 @@ export type TodoTracker = {
settled: () => Promise<void>;
/** 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<void>): 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 `<details>\n<summary>Task list (${completed}/${todos.length} completed)</summary>\n\n${markdown}\n\n</details>`;