Skip to content

pm workspace snapshot restore silently discards divergent items and truncates history JSONL, with exit 0 and no removal report #812

Closed

Description

@unbraind

pm workspace snapshot restore (new in 2026.7.29) silently discards items created after the snapshot and truncates their history JSONL, exits 0, and reports only the files it wrote — never what it removed.

Reproduction (pm 2026.7.29)

git init -q probe && cd probe && pm init
pm create Task --title "First probe task"          # -> pm-6hkz
pm workspace snapshot create baseline

# diverge: append history to the existing item, and add a second item
pm notes pm-6hkz --add "note added AFTER the baseline snapshot"
pm create Task --title "Task created AFTER baseline"

ls .agents/pm/tasks/ | wc -l                       # 2
wc -l < .agents/pm/history/pm-6hkz.jsonl           # 2

pm workspace snapshot restore baseline --json; echo "exit=$?"

Observed

ls .agents/pm/tasks/                     # pm-6hkz.toon        <- second item DELETED
wc -l < .agents/pm/history/pm-6hkz.jsonl # 1                   <- history event DESTROYED
exit=0

The --json payload lists only the 7 files restored:

{
  "schema": "https://schema.unbrained.dev/pm/workspace-snapshot/v1",
  "fingerprint": "c8c67d14afb648c895177dc556409614aa357684ff307d80b437e5a17702b34c",
  "files": ["history/pm-6hkz.jsonl", "schema/...", "settings.json", "tasks/pm-6hkz.toon"],
  "bytes": 7682
}

Nothing in the response distinguishes "restored, nothing lost" from "restored, discarded 1 item and 1 history event". pm workspace snapshot --help shows Options: -h, --help only — there is no --dry-run, no --force, no confirmation, and no summary of removals.

Why this matters for agents

Two properties of this command are load-bearing for the multi-agent workflows pm is designed around, and both are currently unmet:

  1. The history JSONL is the audit trail. Snapshot create correctly captures history/*.jsonl, so restore correctly rewinds it — but rewinding history is not the same as discarding it silently. After a restore, the record that a note was ever added is gone, with no marker and no report. For a workflow where several agents append to the same item across branches, an accidental restore is an undetectable audit-trail rollback.

  2. Exit 0 plus a write-only file list is unauditable. An agent that runs restore cannot programmatically answer "did I just destroy work?" — the only way to know is to have snapshotted the pre-restore state first, which is exactly the thing the agent was using restore to avoid needing. Every other destructive pm operation is gated (pm close on a closed item needs --force; the merge surface reports conflicts); restore is not.

Suggested fix

Any one of these would close the gap; the first two are the valuable ones:

  • Report removals in the payload — e.g. "removed": ["tasks/pm-xxxx.toon"], "history_rewound": [{ "id": "pm-6hkz", "events_discarded": 1 }], and a "destructive": true flag. This alone makes the operation auditable without changing behavior.
  • Require --force (or an explicit --discard-divergent) when the working tracker has diverged from the snapshot, refusing with a non-zero exit and the divergence summary otherwise. That matches the existing pm close --force precedent.
  • Add --dry-run so an agent can preview the removal set.
  • Optionally auto-create a pre-restore safety snapshot and name it in the output, so the rollback is recoverable.

Filed from a hands-on probe while adopting 2026.7.29 across an 18-package fleet; happy to test a patch.

Activity

  1. coderabbitai commented on Jul 29, 2026

    @coderabbitai
    🔗 Related PRs

    #44 - feat(history): audited history-repair re-anchor command; clear legacy drift so pm health is ok [closed]
    #549 - feat(sdk): ship history time travel, rich reads, and runtime integrity [merged]
    #593 - SDK-first agent UX graph, ownership, and recovery contracts [merged]
    #712 - SDK context integrity: atomic Plans, batch similarity, sparse settings, and tombstones [merged]
    #783 - Harden SDK context integrity, merge safety, and agent-efficient output [merged]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. unbraind commented on Jul 29, 2026

    @unbraind
    OwnerAuthor

    Tracked and already delivered by pm-6l2mza. The guarded, audited, reversible restore shipped in PR #813 with dry-run preview, explicit force confirmation, exact impact reporting, recovery snapshots, and durable restore provenance. Closing as completed.

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