Skip to content

Bulk checkpoint rollback overwrites later peer edits, including fields the batch never changed #1563

Closed

Description

@unbraind

Version: 2026.10.23. Scope: core CLI update many --rollback and exported runUpdateMany. Severity: high collaborative recovery risk. Live item evidence is removed; original events remain recoverable in append-only history. No permanent audit-log deletion is claimed.

Run this 17-line TypeScript reproduction in a fresh scratch npm package containing the pinned dependency, using npx -y tsx repro.ts with ESM enabled:

import { PmClient, runUpdateMany } from '@unbrained/pm-cli';
const c = new PmClient({ cwd: process.cwd(), author: 'codex-agent' });
await c.init(undefined, { defaults: true, agentGuidance: 'skip' });
const id = (await c.create({ type: 'Task', title: 'Original', priority: 2 })).item.id;
const g = { path: '.agents/pm', author: 'codex-agent' };
const batch = await runUpdateMany({ list: { ids: id },
  update: { priority: 0 } }, g);
const peer = new PmClient({ cwd: process.cwd(), author: 'peer-agent' });
await peer.comments(id, { add: 'New peer evidence after the batch' });
await peer.update(id, { title: 'Peer continued implementation', priority: 1 });
const before = await c.get(id, { full: true });
if (!batch.checkpoint) throw new Error('Missing checkpoint');
const rollback = await runUpdateMany({ list: {}, update: {},
  rollback: batch.checkpoint.id }, g);
const after = await c.get(id, { full: true });
console.log(before.item.title, before.item.comments, rollback);
console.log(after.item.title, after.item.priority, after.item.comments);

Observed: after rollback the title is Original, priority is 2 and comments are empty. Rollback returns effect/exit 0 with no warnings. Its changed_fields includes comments/title even though the original batch changed only priority. A separate two-item CLI reproduction agrees: priority-only apply → peer comment → peer title update → actual rollback removes the later title/comment. --dry-run --rollback is refused, so there is no successful rollback preview to warn about these losses.

The per-item failure control additionally showed that the checkpoint includes an item whose forward update failed. Rollback restores that item too and removes its subsequent comment, despite the batch never having changed that row successfully.

Expected: undo only the successful batch effects. Preserve unrelated later fields and annotations; use an inverse patch guarded by the batch's postimage/fingerprint. When a changed field itself has drifted, return a conflict with an explicit resolution path. If whole-item restoration is intentional, require explicit acknowledgement and expose the affected later edits before overwriting them. Failed rows should not be restored as if their forward mutation succeeded.

Measured cost: actual CLI rollback receipt 964 bytes / 241 tokens, 30.538 seconds, followed by a 1,260-byte / 315-token projected state read, 24.348 seconds: two calls / 556 tokens to execute and discover the unrelated losses. The response reports restored rows and empty warnings, not the post-checkpoint edits it discards. The independent SDK control observes the same state change. These timings are host observations, not intrinsic operation latency.

Duplicate searches: each used gh issue list -R unbraind/pm-cli --state all --search '<query>' --limit 20:

  • "rollback" "comment"
  • "update-many" "rollback"
  • "rollback" "drift"
  • "rollback" "concurrent"
  • "bulk" "rollback" "drift"
  • "close-many" "rollback"
  • "rollback" "overwrite"

No matching per-item bulk rollback report found. #812 was read: it concerns whole-workspace snapshot restore truncating histories and removing items; this reproduction never invokes workspace restore and retains history. #613 is the general atomic item-mutation helper, #1370/#256 concern preview semantic validation, and #1545 concerns failed package replacement. None describes this rollback overwriting unrelated later item edits. Searches of probes 5/6 and the named excluded issues found no overlapping draft.

Re-verified independently by the orchestrator on 2026.10.23 with the TypeScript reproduction above: after rollback the item reads Original 2 [] (peer title, priority and comment lost).

Activity

  1. unbraind commented on Oct 24, 2026

    @unbraind
    OwnerAuthor

    Canonical PM owner: pm-gh1563. Implementation, regression evidence and structured PM closure are included in #1569; GitHub closure waits for its reviewed merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions