Skip to content

feat(checkpoints): per-step change card core: payload builder, emission hook, changeCardDetail setting (B3a v2-7, epic #1375) - #49

Open
easonLiangWorldedtech wants to merge 2 commits into
feat/fws-v2-4-journal-wiringfrom
feat/fws-v2-7-changecard-core
Open

feat(checkpoints): per-step change card core: payload builder, emission hook, changeCardDetail setting (B3a v2-7, epic #1375)#49
easonLiangWorldedtech wants to merge 2 commits into
feat/fws-v2-4-journal-wiringfrom
feat/fws-v2-7-changecard-core

Conversation

@easonLiangWorldedtech

@easonLiangWorldedtech easonLiangWorldedtech commented Sep 5, 2026

Copy link
Copy Markdown
Owner

What

v2-7 of the file-write safety v2 rebuild (epic #1375): change-card core (B3a) ??the per-step change-card pipeline end to end on the extension host: types + user setting, the card payload builder, and the emission hook in checkpointSave. This is unit 1 of 4 in the split of the reviewed B3a content (legacy #1411, 1891 lines standalone ??v2-7 core, v2-8a apply-diff tool wiring, v2-8b apply-patch/edit/search tool wiring, v2-9 settings/i18n UI).

  • packages/types/src/message.ts ??new change_card ClineSay (documented in the clineSays table) plus the payload schemas: ChangeCardDetail (full | summary), ChangeCardFile (path, +/??counts, optional inline unified diff), ChangeCardData (checkpointIds, files, totalFiles, detail).
  • packages/types/src/global-settings.ts ??the changeCardDetail user setting (optional, enum) with shared default DEFAULT_CHANGE_CARD_DETAIL = summary. summary keeps cards compact (file list with +/??counts; the UI fetches diffs lazily ??v2-9+); full carries the unified diff inline per file.
  • packages/types/src/vscode-extension-host.ts ??changeCardDetail on ExtensionState (webview half of the round trip; the UI control lands in v2-9).
  • src/core/checkpoints/changeCard.ts (new) ??buildChangeCardPayload(commit, writes, detail): one card per completed tool write step, keyed by the shadow-git checkpoint. It reuses the approval diff/stats the tool already computed (CheckpointWriteInfo.diff, never recomputed) and always downgrades to summary for auto-approved steps regardless of the user setting.
  • src/core/checkpoints/index.ts ??CheckpointWriteInfo gains diff? and autoApproved?; checkpointSave now emits task.say(change_card, ...) after a real commit exists (same guard as the journal: only result?.commit && write). A card failure is logged and never disables checkpoints ??the emission is strictly additive on top of the v2-3/v2-4 journal hook.
  • src/core/webview/ClineProvider.ts ??changeCardDetail in getState() and getStateToPostToWebview() (with the shared default), completing the storage-to-webview round trip per the settings checklist.
  • Specs ??new changeCard.spec.ts (payload builder: full vs summary detail, inline diff presence, auto-approved downgrade, empty-write edge) and index.checkpointSave.spec.ts (emission: one card per step, checkpointIds, detail from live getState(), failure swallowed without disabling checkpoints, non-write saves emit nothing; the index. prefix follows the v2-4 index.checkpointJournal.test.ts convention so the suite is picked up as a direct test of index.ts by the Stryker diff gate); ClineProvider.spec.ts +4 tests (saved value reaches getState/getStateToPostToWebview, default summary when unset); index.checkpointJournal.test.ts +8 (test doubles keep the emission on the happy path).

Gates (local, pre-push)

  • vitest: message / global-settings (packages/types) ??10 passed; changeCard / index.checkpointSave / index.checkpointJournal / ClineProvider (src) ??186 passed.
  • eslint: --max-warnings=0 on all 10 touched files (full zoo-code lint via pre-commit); eslint-suppressions.json counts unchanged.
  • pnpm check-types: clean.
  • Stryker (scripts/stryker-diff.mjs ci, base 6c2ac075c = v2-4 head, head this commit): 42 changed-code mutants (31 in changeCard.ts, 9 in the index.ts emission block, 2 in ClineProvider.ts), all Killed ??0 Survived / 0 NoCoverage.

Equivalent mutants

None ??the final run is clean (0 Survived / 0 NoCoverage), so no exclusion directives were needed. The emission-failure test pins the exact console.error message, which kills the catch-block mutants (empty block, message string) rather than excluding them.

Line budget

Standalone diff vs the PR base (6c2ac075c): 566 lines (564+/2?? 10 files) ??over the 400-line soft design target.

Stacking / merge order

Base: feat/fws-v2-4-journal-wiring (PR #48). v2-8a (apply-diff tool wiring) and v2-8b (apply-patch/edit/search tool wiring) stack on this PR; v2-9 (settings UI + i18n) stacks on those. After the whole v2-7..v2-9 chain lands on main, each base switches to main with an identical diff.

Visual regression re-baseline (extension-host-visual)

The deterministic electron-chat-dark-sidebar diff is root-caused and fixed in 54bd92f71:

  • Root cause: this stack inherits the B1 per-write baseline checkpoint (checkpointSave(true, true), allowEmpty). In the mock completion scene it commits an empty baseline and posts a checkpoint_saved webview message (suppressed, so its row stays hidden). However, the pre-existing getCompletionCheckpoint() in packages/types scans the full message list, finds that checkpoint, and sets completionCheckpoint on the completion row, so the pre-existing SeeNewChangesButtons component ("See New Changes" / "Restore Changes") now renders. On upstream main the comparable pre-prompt checkpoint is not allowEmpty and is a no-op in the clean mock workspace, so the old baseline had no buttons.
  • Verdict: intentional feature UI. The diff removes zero pixels (632 brighter pixels added: the two button rows); welcome scenes pass.
  • Fix: baseline re-captured from the deterministic actual artifact (3/3 retries byte-identical). Stacked PR feat(settings): change card detail control in CheckpointSettings + webview default (B3a v2-9, epic #1375) #52 inherits the new baseline and its visual job is expected to pass on the stacked rebase.

@easonLiangWorldedtech easonLiangWorldedtech added coderabbit-review-active Required CI passed; CodeRabbit review is active awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit labels Sep 5, 2026
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

Review status

Thanks for contributing. This comment tracks the review sequence and the next action.

Current step: Required CI passed. Waiting for automated review of the latest commit.

If automated review does not start, a maintainer must restart it.

Review-state labels are managed by this workflow; do not edit them manually.

…on hook, changeCardDetail setting (B3a v2-7, epic Zoo-Code-Org#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 Zoo-Code-Org#1411) - unit 1 of 4 (v2-7). Stacks on v2-4 (PR #48).
@easonLiangWorldedtech
easonLiangWorldedtech force-pushed the feat/fws-v2-7-changecard-core branch from 11eeb88 to a552872 Compare September 6, 2026 00:54
@github-actions github-actions Bot added coderabbit-review-active Required CI passed; CodeRabbit review is active and removed coderabbit-review-active Required CI passed; CodeRabbit review is active labels Sep 6, 2026
…s renders after B1 allowEmpty baseline checkpoint)
@easonLiangWorldedtech
easonLiangWorldedtech force-pushed the feat/fws-v2-7-changecard-core branch from e687f18 to 54bd92f Compare September 6, 2026 02:16
@github-actions github-actions Bot added coderabbit-review-active Required CI passed; CodeRabbit review is active and removed coderabbit-review-active Required CI passed; CodeRabbit review is active labels Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit coderabbit-review-active Required CI passed; CodeRabbit review is active

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants