From a5528729c1110db5efdedae79bbe3860d3d3a0ae Mon Sep 17 00:00:00 2001 From: Eason Liang Date: Sun, 6 Sep 2026 06:43:50 +0800 Subject: [PATCH 1/2] feat(checkpoints): per-step change card core: payload builder, emission hook, changeCardDetail setting (B3a v2-7, epic #1375) Change-card pipeline on the extension host for each completed tool-write step: - change_card ClineSay + ChangeCardData/ChangeCardFile/ChangeCardDetail schemas (packages/types) - changeCardDetail user setting (default 'summary') + ExtensionState + ClineProvider getState/getStateToPostToWebview round trip - buildChangeCardPayload(): reuses the approval diff stats already computed by the tools; auto-approved steps are always downgraded to 'summary' - checkpointSave emits task.say('change_card', ...) only when a real commit and write info exist; a card failure is logged and never disables checkpoints Split of the reviewed B3a content (legacy #1411) - unit 1 of 4 (v2-7). Stacks on v2-4 (PR #48). --- packages/types/src/global-settings.ts | 16 ++ packages/types/src/message.ts | 45 ++++ packages/types/src/vscode-extension-host.ts | 3 +- .../checkpoints/__tests__/changeCard.spec.ts | 108 ++++++++ .../__tests__/index.checkpointJournal.test.ts | 8 + .../__tests__/index.checkpointSave.spec.ts | 230 ++++++++++++++++++ src/core/checkpoints/changeCard.ts | 91 +++++++ src/core/checkpoints/index.ts | 27 +- src/core/webview/ClineProvider.ts | 4 + .../webview/__tests__/ClineProvider.spec.ts | 34 +++ 10 files changed, 564 insertions(+), 2 deletions(-) create mode 100644 src/core/checkpoints/__tests__/changeCard.spec.ts create mode 100644 src/core/checkpoints/__tests__/index.checkpointSave.spec.ts create mode 100644 src/core/checkpoints/changeCard.ts diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index 4f21ca9607..3896c711c0 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -12,6 +12,7 @@ import { } from "./provider-settings.js" import { telemetrySettingsSchema } from "./telemetry.js" import { toolNamesSchema } from "./tool.js" +import { changeCardDetailSchema, type ChangeCardDetail } from "./message.js" import { type Keys } from "./type-fu.js" import { languagesSchema } from "./vscode.js" @@ -106,6 +107,14 @@ export const DEFAULT_CHECKPOINT_TIMEOUT_SECONDS = 15 */ export const DEFAULT_PER_WRITE_CHECKPOINTS = true +/** + * Default detail level for per-step change cards (B3a). + * "summary" keeps cards compact (file list with +/− counts; the UI fetches + * diffs lazily); "full" carries the unified diff inline per file. + * @default "summary" + */ +export const DEFAULT_CHANGE_CARD_DETAIL: ChangeCardDetail = "summary" + /** * GlobalSettings */ @@ -213,6 +222,13 @@ export const globalSettingsSchema = z.object({ * @default true */ perWriteCheckpoints: z.boolean().optional(), + /** + * Detail level for per-step change cards: "full" includes the unified diff + * inline for every changed file, "summary" carries only the file list with + * +/− counts (diffs are fetched lazily by the UI). + * @default "summary" + */ + changeCardDetail: changeCardDetailSchema.optional(), ttsEnabled: z.boolean().optional(), ttsSpeed: z.number().optional(), diff --git a/packages/types/src/message.ts b/packages/types/src/message.ts index 28d5af82ac..b7940d00a4 100644 --- a/packages/types/src/message.ts +++ b/packages/types/src/message.ts @@ -134,6 +134,7 @@ export function isNonBlockingAsk(ask: ClineAsk): ask is NonBlockingAsk { * - `mcp_server_response`: Response received from MCP server * - `subtask_result`: Result of a completed subtask * - `checkpoint_saved`: Indicates a checkpoint has been saved + * - `change_card`: Per-step change card summarizing the files a completed tool step wrote (B3a) * - `rooignore_error`: Error related to .rooignore file processing * - `diff_error`: Error occurred while applying a diff/patch * - `condense_context`: Context condensation/summarization has started @@ -162,6 +163,7 @@ export const clineSays = [ "mcp_server_response", "subtask_result", "checkpoint_saved", + "change_card", "rooignore_error", "diff_error", "condense_context", @@ -235,6 +237,49 @@ export const contextTruncationSchema = z.object({ export type ContextTruncation = z.infer +/** + * ChangeCard + * + * Payload of the per-step change card (B3a). The extension host emits one + * `say: "change_card"` message per completed tool write step, keyed by the + * shadow-git checkpoint the step produced. The JSON payload (see + * {@link ChangeCardData}) is carried in the message `text` field, the same + * way tool approval messages carry their serialized ClineSayTool. + * + * `detail: "full"` carries the unified diff inline for every file so the UI + * can render it directly; `detail: "summary"` carries only the file list with + * +/− counts and the UI fetches diffs lazily (B3b). Auto-approved steps are + * always emitted with `detail: "summary"` regardless of the user setting. + */ +export const changeCardDetailSchema = z.enum(["full", "summary"]) + +export type ChangeCardDetail = z.infer + +export const changeCardFileSchema = z.object({ + path: z.string(), + additions: z.number(), + deletions: z.number(), + /** + * Unified diff for this file. Only present when the card was emitted with + * `detail: "full"`; summary cards leave it out to stay compact. + */ + diff: z.string().optional(), +}) + +export type ChangeCardFile = z.infer + +export const changeCardSchema = z.object({ + /** Opaque step identifier, reserved for future tool-step tracking. */ + stepId: z.string().optional(), + /** Checkpoint commit SHAs produced by the step (one per per-write checkpoint). */ + checkpointIds: z.array(z.string()), + files: z.array(changeCardFileSchema), + totalFiles: z.number(), + detail: changeCardDetailSchema, +}) + +export type ChangeCardData = z.infer + /** * ClineMessage * diff --git a/packages/types/src/vscode-extension-host.ts b/packages/types/src/vscode-extension-host.ts index 20756d7a68..b392bb77fd 100644 --- a/packages/types/src/vscode-extension-host.ts +++ b/packages/types/src/vscode-extension-host.ts @@ -5,7 +5,7 @@ import type { ProviderSettings, ProviderSettingsEntry } from "./provider-setting import type { HistoryItem } from "./history.js" import type { ModeConfig, PromptComponent } from "./mode.js" import type { Experiments } from "./experiment.js" -import type { ClineMessage, QueuedMessage } from "./message.js" +import type { ChangeCardDetail, ClineMessage, QueuedMessage } from "./message.js" import type { MarketplaceItem, MarketplaceInstalledMetadata, InstallMarketplaceItemOptions } from "./marketplace.js" import type { TodoItem } from "./todo.js" import type { CloudUserInfo, CloudOrganizationMembership, OrganizationAllowList, ShareVisibility } from "./cloud.js" @@ -349,6 +349,7 @@ export type ExtensionState = Pick< enableCheckpoints: boolean checkpointTimeout: number // Timeout for checkpoint initialization in seconds (default: 15) perWriteCheckpoints: boolean + changeCardDetail?: ChangeCardDetail // Optional: webview context default ships with the settings UI unit maxOpenTabsContext: number // Maximum number of VSCode open tabs to include in context (0-500) maxWorkspaceFiles: number // Maximum number of files to include in current working directory details (0-500) showRooIgnoredFiles: boolean // Whether to show .rooignore'd files in listings diff --git a/src/core/checkpoints/__tests__/changeCard.spec.ts b/src/core/checkpoints/__tests__/changeCard.spec.ts new file mode 100644 index 0000000000..82190638a1 --- /dev/null +++ b/src/core/checkpoints/__tests__/changeCard.spec.ts @@ -0,0 +1,108 @@ +import { describe, expect, it } from "vitest" + +import type { ChangeCardData } from "@roo-code/types" + +import { + buildChangeCard, + buildChangeCardPayload, + isAutoApprovedStep, + resolveChangeCardDetail, + type ChangeCardWrite, +} from "../changeCard" + +describe("changeCard (B3a)", () => { + function write(overrides: Partial = {}): ChangeCardWrite { + return { + path: "src/a.ts", + diffStats: { additions: 2, deletions: 1 }, + diff: "--- a/src/a.ts\n+++ b/src/a.ts\n@@ -1 +1,2 @@\n-old\n+new-1\n+new-2", + ...overrides, + } + } + + describe("isAutoApprovedStep", () => { + it("returns false for an empty step", () => { + expect(isAutoApprovedStep([])).toBe(false) + }) + + it("returns true only when every write was auto-approved", () => { + expect(isAutoApprovedStep([write({ autoApproved: true }), write({ autoApproved: true })])).toBe(true) + expect(isAutoApprovedStep([write({ autoApproved: true }), write()])).toBe(false) + expect(isAutoApprovedStep([write()])).toBe(false) + }) + }) + + describe("resolveChangeCardDetail", () => { + it("forces summary for auto-approved steps even when the setting is full", () => { + const writes = [write({ autoApproved: true })] + expect(resolveChangeCardDetail(writes, "full")).toBe("summary") + expect(resolveChangeCardDetail(writes, undefined)).toBe("summary") + }) + + it("follows the setting for interactive steps, defaulting to summary when unset", () => { + const writes = [write()] + expect(resolveChangeCardDetail(writes, "full")).toBe("full") + expect(resolveChangeCardDetail(writes, "summary")).toBe("summary") + expect(resolveChangeCardDetail(writes, undefined)).toBe("summary") + }) + }) + + describe("buildChangeCard", () => { + it("carries the inline diff per file for full detail on a multi-file step", () => { + const card = buildChangeCard( + "sha-1", + [write(), write({ path: "src/b.ts", diffStats: { additions: 1, deletions: 0 }, diff: "+b" })], + "full", + ) + + expect(card).toEqual({ + checkpointIds: ["sha-1"], + files: [ + { + path: "src/a.ts", + additions: 2, + deletions: 1, + diff: "--- a/src/a.ts\n+++ b/src/a.ts\n@@ -1 +1,2 @@\n-old\n+new-1\n+new-2", + }, + { path: "src/b.ts", additions: 1, deletions: 0, diff: "+b" }, + ], + totalFiles: 2, + detail: "full", + }) + }) + + it("omits the diff per file for summary detail (lazy fetch is B3b)", () => { + const card = buildChangeCard("sha-1", [write()], "summary") + + expect(card.files).toEqual([{ path: "src/a.ts", additions: 2, deletions: 1 }]) + expect(card.files[0]).not.toHaveProperty("diff") + expect(card.detail).toBe("summary") + expect(card.totalFiles).toBe(1) + }) + + it("defaults missing diffStats to zero counts and keeps full detail without diff for a write without one", () => { + const card = buildChangeCard("sha-1", [write({ diffStats: undefined, diff: undefined })], "full") + + expect(card.files[0]).toEqual({ path: "src/a.ts", additions: 0, deletions: 0 }) + }) + }) + + describe("buildChangeCardPayload", () => { + it("resolves the detail level and builds the payload in one call", () => { + // The expectations are typed against the shared ChangeCardData + // contract in @roo-code/types, so the builder's output is checked + // against the same single source of truth the webview consumes. + // Interactive step with the full setting: diff inline. + const full: ChangeCardData = buildChangeCardPayload("sha-1", [write()], "full") + expect(full.detail).toBe("full") + expect(full.files[0].diff).toBe("--- a/src/a.ts\n+++ b/src/a.ts\n@@ -1 +1,2 @@\n-old\n+new-1\n+new-2") + + // Auto-approved step with the full setting: compact summary, no diff. + const compact: ChangeCardData = buildChangeCardPayload("sha-1", [write({ autoApproved: true })], "full") + expect(compact.detail).toBe("summary") + expect(compact.files[0]).not.toHaveProperty("diff") + expect(compact.checkpointIds).toEqual(["sha-1"]) + expect(compact.totalFiles).toBe(1) + }) + }) +}) diff --git a/src/core/checkpoints/__tests__/index.checkpointJournal.test.ts b/src/core/checkpoints/__tests__/index.checkpointJournal.test.ts index 34bfc68852..60cc85a78b 100644 --- a/src/core/checkpoints/__tests__/index.checkpointJournal.test.ts +++ b/src/core/checkpoints/__tests__/index.checkpointJournal.test.ts @@ -66,6 +66,7 @@ interface ProviderLike { context: { globalStorageUri: { fsPath: string } } log: (...args: unknown[]) => void postMessageToWebview: (...args: unknown[]) => void + getState: () => Promise> } interface TaskLike { @@ -74,6 +75,7 @@ interface TaskLike { checkpointService: ServiceLike checkpointServiceInitializing: boolean providerRef: { deref: () => ProviderLike | undefined } + say: (...args: unknown[]) => Promise } describe("checkpointSave change-journal wiring (B2)", () => { @@ -94,6 +96,8 @@ describe("checkpointSave change-journal wiring (B2)", () => { context: { globalStorageUri: { fsPath: tmpStorageDir } }, log: vi.fn(), postMessageToWebview: vi.fn(), + // B3a: the card emission reads the live settings through getState. + getState: vi.fn().mockResolvedValue({}), } // Structural test double for Task (the class is not instantiated at // this unit layer); the cast is safe because the fields checkpointSave @@ -104,6 +108,10 @@ describe("checkpointSave change-journal wiring (B2)", () => { checkpointService: { isInitialized: true, saveCheckpoint: saveCheckpointSpy }, checkpointServiceInitializing: false, providerRef: { deref: () => mockProvider }, + // B3a: the card emission calls task.say; a resolved double keeps the + // test double complete instead of letting the emission take the + // error path. + say: vi.fn().mockResolvedValue(undefined), } }) diff --git a/src/core/checkpoints/__tests__/index.checkpointSave.spec.ts b/src/core/checkpoints/__tests__/index.checkpointSave.spec.ts new file mode 100644 index 0000000000..dd0d599c7c --- /dev/null +++ b/src/core/checkpoints/__tests__/index.checkpointSave.spec.ts @@ -0,0 +1,230 @@ +import fs from "fs/promises" +import os from "os" +import path from "path" + +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest" + +import type { Task } from "../../task/Task" +import { journalPath } from "../changeJournal" +import { checkpointSave } from "../index" + +vi.mock("@roo-code/telemetry", () => ({ + TelemetryService: { + instance: { + captureCheckpointCreated: vi.fn(), + captureCheckpointRestored: vi.fn(), + captureCheckpointDiffed: vi.fn(), + }, + }, +})) + +/** + * Minimal Task double for the checkpointSave wiring tests. Only the members + * touched by getCheckpointService + checkpointSave are provided: a pre-set + * checkpointService (so no git installation happens), the provider context + * (journal dir + setting state), and say. Structural cast at the boundary, + * matching the documented test-double style of the tool specs. + */ +function makeTask(options: { saveCheckpoint?: unknown; state?: Record; enableCheckpoints?: boolean }) { + const say = vi.fn().mockResolvedValue(undefined) + // An explicit `saveCheckpoint: undefined` (a checkpoint that produced no + // commit) must be preserved as-is; only an omitted option falls back to + // the default commit result. + const saveCheckpoint = vi + .fn() + .mockResolvedValue("saveCheckpoint" in options ? options.saveCheckpoint : { commit: "sha-card-1" }) + const providerDeref = { + context: { globalStorageUri: { fsPath: globalStorageDir } }, + getState: vi.fn().mockResolvedValue(options.state ?? {}), + } + + const task = { + taskId: "task-card", + cwd: "/workspace", + enableCheckpoints: options.enableCheckpoints ?? true, + checkpointService: { + saveCheckpoint, + isInitialized: true, + }, + providerRef: { deref: vi.fn().mockReturnValue(providerDeref) }, + say, + } as unknown as Task + + return { task, say, saveCheckpoint } +} + +let globalStorageDir: string + +beforeEach(async () => { + globalStorageDir = await fs.mkdtemp(path.join(os.tmpdir(), "b3a-save-")) +}) + +afterEach(async () => { + await fs.rm(globalStorageDir, { recursive: true, force: true }) +}) + +describe("checkpointSave change-card emission (B3a)", () => { + it("emits a full-detail change card after a successful per-write checkpoint and still appends the journal", async () => { + const { task, say, saveCheckpoint } = makeTask({ state: { changeCardDetail: "full" } }) + + await checkpointSave(task, false, true, { + path: "src/a.ts", + operation: "create", + diffStats: { additions: 2, deletions: 1 }, + diff: "+line-a\n+line-b\n-old", + }) + + expect(saveCheckpoint).toHaveBeenCalledWith(expect.stringContaining("task-card"), expect.any(Object)) + + const cardCalls = say.mock.calls.filter(([type]) => type === "change_card") + expect(cardCalls).toHaveLength(1) + const [type, text, images, partial, sayOptions, _progress, options] = cardCalls[0] as unknown as [ + string, + string, + undefined, + undefined, + undefined, + undefined, + { isNonInteractive?: boolean }, + ] + expect(type).toBe("change_card") + expect(images).toBeUndefined() + expect(options).toEqual({ isNonInteractive: true }) + const card = JSON.parse(text as string) as { + checkpointIds: string[] + files: Array<{ path: string; additions: number; deletions: number; diff?: string }> + totalFiles: number + detail: string + } + expect(card.checkpointIds).toEqual(["sha-card-1"]) + expect(card.totalFiles).toBe(1) + expect(card.detail).toBe("full") + expect(card.files).toEqual([{ path: "src/a.ts", additions: 2, deletions: 1, diff: "+line-a\n+line-b\n-old" }]) + + // B2 regression: the journal entry is still appended with the commit id. + const journalRaw = await fs.readFile(journalPath(globalStorageDir, "task-card"), "utf8") + const entries = journalRaw + .split("\n") + .filter((line) => line !== "") + .map((line) => JSON.parse(line)) + expect(entries).toHaveLength(1) + expect(entries[0]).toMatchObject({ path: "src/a.ts", operation: "create", checkpointId: "sha-card-1" }) + }) + + it("emits a summary card without diffs for the default (summary) setting", async () => { + const { task, say } = makeTask({}) + + await checkpointSave(task, false, true, { + path: "src/a.ts", + operation: "update", + diffStats: { additions: 1, deletions: 0 }, + diff: "+x", + }) + + const cardCall = say.mock.calls.find(([type]) => type === "change_card") + expect(cardCall).toBeDefined() + const card = JSON.parse((cardCall as unknown as [string, string])[1]) as { + files: Array> + detail: string + } + expect(card.detail).toBe("summary") + expect(card.files[0]).not.toHaveProperty("diff") + }) + + it("emits a compact card for auto-approved steps even when the setting is full", async () => { + const { task, say } = makeTask({ state: { changeCardDetail: "full" } }) + + await checkpointSave(task, false, true, { + path: "src/a.ts", + operation: "create", + diffStats: { additions: 1, deletions: 0 }, + diff: "+x", + autoApproved: true, + }) + + const cardCall = say.mock.calls.find(([type]) => type === "change_card") + expect(cardCall).toBeDefined() + const card = JSON.parse((cardCall as unknown as [string, string])[1]) as { + files: Array> + detail: string + } + expect(card.detail).toBe("summary") + expect(card.files[0]).not.toHaveProperty("diff") + }) + + it("emits one card with all writes for a multi-file step", async () => { + const { task, say } = makeTask({ state: { changeCardDetail: "full" } }) + + await checkpointSave(task, false, true, [ + { path: "src/a.ts", operation: "create", diffStats: { additions: 2, deletions: 0 }, diff: "+a1\n+a2" }, + { path: "src/b.ts", operation: "delete", diffStats: { additions: 0, deletions: 3 } }, + ]) + + const cardCalls = say.mock.calls.filter(([type]) => type === "change_card") + expect(cardCalls).toHaveLength(1) + const card = JSON.parse((cardCalls[0] as unknown as [string, string])[1]) as { + files: Array<{ path: string; diff?: string }> + totalFiles: number + } + expect(card.totalFiles).toBe(2) + expect(card.files.map((file) => file.path)).toEqual(["src/a.ts", "src/b.ts"]) + expect(card.files[0].diff).toBe("+a1\n+a2") + expect(card.files[1]).not.toHaveProperty("diff") + }) + + it("emits no change card for baseline checkpoints without write info", async () => { + const { task, say } = makeTask({}) + + await checkpointSave(task) + + // `say` is invoked with seven arguments, so a three-argument + // `toHaveBeenCalledWith` negative assertion can never fail; filter the + // recorded calls by type instead. + const cardCalls = say.mock.calls.filter(([type]) => type === "change_card") + expect(cardCalls).toHaveLength(0) + }) + + it("emits no change card when the checkpoint produced no commit", async () => { + const { task, say } = makeTask({ saveCheckpoint: undefined }) + + await checkpointSave(task, false, true, { path: "src/a.ts", operation: "create" }) + + const cardCalls = say.mock.calls.filter(([type]) => type === "change_card") + expect(cardCalls).toHaveLength(0) + }) + + it("emits no change card when checkpoints are disabled for the task", async () => { + const { task, say } = makeTask({ enableCheckpoints: false }) + + await checkpointSave(task, false, true, { path: "src/a.ts", operation: "create", diff: "+x" }) + + expect(say).not.toHaveBeenCalled() + }) + + it("keeps the journal append when a card emission failure occurs", async () => { + const { task, say } = makeTask({}) + say.mockImplementation(async (type: string) => { + if (type === "change_card") { + throw new Error("task aborted") + } + }) + const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}) + + await checkpointSave(task, false, true, { + path: "src/a.ts", + operation: "create", + diffStats: { additions: 1, deletions: 0 }, + diff: "+x", + }) + + // The say failure is contained: the journal is still written, and the + // failure is logged (message asserted so the log call cannot vanish). + const journalRaw = await fs.readFile(journalPath(globalStorageDir, "task-card"), "utf8") + expect(journalRaw).toContain("src/a.ts") + expect(consoleErrorSpy).toHaveBeenCalledWith( + "[Task#checkpointSave] failed to emit change card", + expect.anything(), + ) + consoleErrorSpy.mockRestore() + }) +}) diff --git a/src/core/checkpoints/changeCard.ts b/src/core/checkpoints/changeCard.ts new file mode 100644 index 0000000000..b13f03320d --- /dev/null +++ b/src/core/checkpoints/changeCard.ts @@ -0,0 +1,91 @@ +/** + * Per-step change card builder (B3a). + * + * The card is emitted from `checkpointSave` (index.ts) once the per-write + * checkpoint commit exists, so the payload can key the card by the real + * checkpoint ID and reuse the approval diff + stats the tool already + * computed (threaded through {@link CheckpointWriteInfo}). The card is + * informational and always emitted for write steps, including auto-approved + * ones — which always get the compact ("summary") form regardless of the + * `changeCardDetail` setting. + */ +import { DEFAULT_CHANGE_CARD_DETAIL, type ChangeCardData, type ChangeCardDetail } from "@roo-code/types" + +/** + * The write data a change card is built from. Structurally compatible with + * `CheckpointWriteInfo` (src/core/checkpoints/index.ts), minus the + * `operation` field the card does not need. + */ +export interface ChangeCardWrite { + /** The file path as the tool knows it (relative to the task cwd). */ + path: string + /** { additions, deletions } from the approval diff, when computable. */ + diffStats?: { additions: number; deletions: number } + /** The unified approval diff for this file (reused, not recomputed). */ + diff?: string + /** Whether the tool step was auto-approved (no human interaction). */ + autoApproved?: boolean +} + +/** + * Whether every write of the step was auto-approved. Empty steps are not + * auto-approved (there is nothing for the user to have skipped). + */ +export function isAutoApprovedStep(writes: readonly ChangeCardWrite[]): boolean { + return writes.length > 0 && writes.every((write) => write.autoApproved === true) +} + +/** + * Resolve the card detail level for a step: + * - auto-approved steps always get the compact "summary" card, regardless of + * the user setting (cards for steps the user never saw approving are + * informational only); + * - otherwise the `changeCardDetail` setting applies, defaulting to + * "summary" when unset. + */ +export function resolveChangeCardDetail( + writes: readonly ChangeCardWrite[], + setting: ChangeCardDetail | undefined, +): ChangeCardDetail { + if (isAutoApprovedStep(writes)) { + return "summary" + } + return setting ?? DEFAULT_CHANGE_CARD_DETAIL +} + +/** + * Build the typed change-card payload for one step (one per-write checkpoint). + * + * With `detail: "full"` each file carries its unified diff inline; with + * `detail: "summary"` the diff is omitted and the UI fetches it lazily + * (B3b). + */ +export function buildChangeCard( + checkpointId: string, + writes: readonly ChangeCardWrite[], + detail: ChangeCardDetail, +): ChangeCardData { + return { + checkpointIds: [checkpointId], + files: writes.map((write) => ({ + path: write.path, + additions: write.diffStats?.additions ?? 0, + deletions: write.diffStats?.deletions ?? 0, + ...(detail === "full" && write.diff ? { diff: write.diff } : {}), + })), + totalFiles: writes.length, + detail, + } +} + +/** + * Convenience wrapper: resolve the detail level from the step + setting, then + * build the payload. This is what `checkpointSave` calls. + */ +export function buildChangeCardPayload( + checkpointId: string, + writes: readonly ChangeCardWrite[], + setting: ChangeCardDetail | undefined, +): ChangeCardData { + return buildChangeCard(checkpointId, writes, resolveChangeCardDetail(writes, setting)) +} diff --git a/src/core/checkpoints/index.ts b/src/core/checkpoints/index.ts index bcfafb5cd6..d206767ad4 100644 --- a/src/core/checkpoints/index.ts +++ b/src/core/checkpoints/index.ts @@ -17,6 +17,7 @@ import { DIFF_VIEW_URI_SCHEME } from "../../integrations/editor/DiffViewProvider import { CheckpointServiceOptions, RepoPerTaskCheckpointService } from "../../services/checkpoints" import { appendChange, ChangeJournalEntry } from "./changeJournal" +import { buildChangeCardPayload } from "./changeCard" const WARNING_THRESHOLD_MS = 5000 @@ -225,6 +226,16 @@ export type CheckpointWriteInfo = { path: string operation: "create" | "update" | "delete" diffStats?: { additions: number; deletions: number } + /** + * The unified approval diff for this write, reused verbatim by the B3a + * change card (never recomputed). + */ + diff?: string + /** + * Whether the tool step was auto-approved (no human interaction). Auto- + * approved steps always get the compact ("summary") change card. + */ + autoApproved?: boolean } export async function checkpointSave( @@ -250,9 +261,9 @@ export async function checkpointSave( // resolves to undefined / rejects), and non-write checkpoint calls // (e.g. the task-start baseline) pass no `write` value at all. if (result?.commit && write) { + const writes = Array.isArray(write) ? write : [write] const globalStorageDir = task.providerRef.deref()?.context.globalStorageUri.fsPath if (globalStorageDir) { - const writes = Array.isArray(write) ? write : [write] // Append sequentially so journal lines preserve write order. A // journal failure is logged here and never propagates to the // checkpoint error handler (checkpoints stay enabled). @@ -269,6 +280,20 @@ export async function checkpointSave( console.error("[Task#checkpointSave] failed to append change journal entry", err) } } + + // B3a: emit the per-step change card now that the checkpoint commit + // exists. The card reuses the approval diff/stats the tool already + // computed and is always emitted (auto-approved steps included); + // a card failure is logged and never disables checkpoints. + try { + const state = await task.providerRef.deref()?.getState() + const card = buildChangeCardPayload(result.commit, writes, state?.changeCardDetail) + await task.say("change_card", JSON.stringify(card), undefined, undefined, undefined, undefined, { + isNonInteractive: true, + }) + } catch (err) { + console.error("[Task#checkpointSave] failed to emit change card", err) + } } return result }) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 514edd29dd..b23a061b32 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -53,6 +53,7 @@ import { DEFAULT_MODES, DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, DEFAULT_PER_WRITE_CHECKPOINTS, + DEFAULT_CHANGE_CARD_DETAIL, getModelId, isRetiredProvider, providerIdentifiers, @@ -2596,6 +2597,7 @@ export class ClineProvider enableCheckpoints, checkpointTimeout, perWriteCheckpoints, + changeCardDetail, soundVolume, writeDelayMs, diffFuzzyThreshold, @@ -2756,6 +2758,7 @@ export class ClineProvider enableCheckpoints: enableCheckpoints ?? true, checkpointTimeout: checkpointTimeout ?? DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, perWriteCheckpoints: perWriteCheckpoints ?? DEFAULT_PER_WRITE_CHECKPOINTS, + changeCardDetail: changeCardDetail ?? DEFAULT_CHANGE_CARD_DETAIL, shouldShowAnnouncement: telemetrySetting !== "unset" && lastShownAnnouncementId !== this.latestAnnouncementId, allowedCommands: mergedAllowedCommands, @@ -2994,6 +2997,7 @@ export class ClineProvider enableCheckpoints: stateValues.enableCheckpoints ?? true, checkpointTimeout: stateValues.checkpointTimeout ?? DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, perWriteCheckpoints: stateValues.perWriteCheckpoints ?? DEFAULT_PER_WRITE_CHECKPOINTS, + changeCardDetail: stateValues.changeCardDetail ?? DEFAULT_CHANGE_CARD_DETAIL, soundVolume: stateValues.soundVolume, writeDelayMs: stateValues.writeDelayMs ?? DEFAULT_WRITE_DELAY_MS, diffFuzzyThreshold: stateValues.diffFuzzyThreshold ?? DEFAULT_DIFF_FUZZY_THRESHOLD, diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index 29df553071..b517960654 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -721,6 +721,7 @@ describe("ClineProvider", () => { ttsEnabled: false, enableCheckpoints: false, perWriteCheckpoints: false, + changeCardDetail: "summary", writeDelayMs: 1000, mcpEnabled: true, mode: defaultModeSlug, @@ -1482,6 +1483,39 @@ describe("ClineProvider", () => { expect(state.perWriteCheckpoints).toBe(true) }) + test("getState returns the saved changeCardDetail setting", async () => { + await provider.contextProxy.setValue("changeCardDetail", "full") + + const state = await provider.getState() + + expect(state.changeCardDetail).toBe("full") + }) + + test("getState defaults changeCardDetail to summary when unset", async () => { + const state = await provider.getState() + + expect(state.changeCardDetail).toBe("summary") + }) + + test("getStateToPostToWebview returns the saved changeCardDetail setting", async () => { + // The default is "summary", so only an explicit "full" proves that the + // stored value (rather than the default) reaches the webview state. + await provider.resolveWebviewView(mockWebviewView) + await provider.contextProxy.setValue("changeCardDetail", "full") + + const state = await provider.getStateToPostToWebview() + + expect(state.changeCardDetail).toBe("full") + }) + + test("getStateToPostToWebview defaults changeCardDetail to summary when unset", async () => { + await provider.resolveWebviewView(mockWebviewView) + + const state = await provider.getStateToPostToWebview() + + expect(state.changeCardDetail).toBe("summary") + }) + test("language is set to VSCode language", async () => { // Mock VSCode language as Spanish ;(vscode.env as any).language = "pt-BR" From 54bd92f710e4beb1599f02f5187203a1732e42b4 Mon Sep 17 00:00:00 2001 From: Eason Liang Date: Sun, 6 Sep 2026 10:15:49 +0800 Subject: [PATCH 2/2] fix(e2e): re-baseline chat-dark sidebar snapshot (SeeNewChangesButtons renders after B1 allowEmpty baseline checkpoint) --- .../electron-chat-dark-sidebar.png | Bin 30867 -> 33726 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/vscode-e2e/src/visual/__screenshots__/electron-chat-dark-sidebar.png b/apps/vscode-e2e/src/visual/__screenshots__/electron-chat-dark-sidebar.png index cb69da51e546a37537df7ec2fabfe60064a6f316..e4dd9fc01efa68340e51ccdf3a708abaa0eae7d1 100644 GIT binary patch literal 33726 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 literal 30867 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 ONmP|I6^j(^68{$n%}A>N