Skip to main content

dsh-turn-rewind

93Stars6Forks4Issues1Watchers

Provides per-turn project file rollback for DSH:

Evidence5/5methodologySourceInstallMaintenanceDSH versionSecurity scan
Machine-auditedInstall commandRepo verifieddsh-plugin topicLicenseREADMEAI wiki
Language
JavaScript
License
BSD-3-Clause
Branch
main
agent-rewindcordis-plugindeepseek-harnessdshdsh-pluginmarisa-pluginrestore-pointturn-rewind

Install

cmdweb profile
$ dsh plugin --profile web add @anionex/dsh-turn-rewind

Run the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial

Install via your agent

Install the DeepSeek Harness plugin Anionex/dsh-turn-rewind for me: review the repository at https://github.com/Anionex/dsh-turn-rewind first, then run the install command and verify the plugin loads successfully.

Paste this instruction to the DSH Web GUI assistant — it will install and verify for you.

One-line Summary

Adds a "Restore to state before sending this message" button to each user message in DeepSeek Harness: clicking shows a list of affected files, confirming precisely restores project files, and optionally opens a new conversation continuing from that message.

Core Capabilities

  • In Web Profile, add an icon-style "Rewind" button after the timestamp and native copy button for each direct user message, with tooltip "Restore to state before sending this message"
  • At startup, via agent/pre-step hook, automatically capture a project file snapshot before the Agent starts processing each round of user messages, serving as a hidden restore point for that turn; capture failure only prevents that message from being restored, won't block the current user request
  • Popup supports two restore modes: default "Restore files and continue from here" (auto-create new session and fill original message text into input box) or "Restore files only" (current conversation remains unchanged)
  • Before each execution, first create a rescue snapshot, then do hash verification after execution; failure automatically rolls back via rescue snapshot; when DSH crashes mid-operation, on startup automatically mark unfinished operation logs as "interrupted" and retain corresponding rescue points for manual recovery
  • Through ctx.changeLedger public service, allow other Cordis plugins to inject and reuse the same set of snapshot, planning, restoration, and reconciliation APIs
  • Git operations, HEAD/branch state, and selected files are double-validated between restoration plan generation and execution; any related changes invalidate the plan, no silent overwrites

Technical Implementation

  • Language: TypeScript (ESM, strict mode)
  • Key Dependencies: @deepseek-ai/cordis (host plugin framework), react + @deepseek-ai/dsh-client-ui-primitives (Web UI), node:fs + node:crypto (snapshots and content-addressed storage), git CLI (read repository facts via subprocess)
  • Architecture Pattern: Standalone DSH Profile Bundle — package.json#dsh.bundle.patch points to cordis.patch.yml, mounts turn-rewind profile layer at host startup; server registers Cordis service via ctx.provide('changeLedger', ...), client registers to runtime + conversation UI via dsh.client.inject
  • Entry Files: src/index.ts (server Cordis service registration), src/rewind-host.ts (HTTP interface + turn checkpoint coordinator), src/client/index.tsx (Web popup and button)

Use Cases

  • User has Agent or external tools modify project files, then realizes the direction is wrong and wants to undo, keeping only the workspace state before a certain message
  • Want to revert project state to before a certain conversation turn, while opening another branch to continue discussion, and fully preserve the original conversation
  • Team runs long sessions on DSH, concerned about Agent accidentally modifying files, tool execution crashing, or accidentally modifying code themselves, needing ability to precisely revert workspace at any time without losing conversation

Prerequisites & Compatibility

DependencyMinimum VersionDescription
DSH Host (Cordis)@deepseek-ai/cordis ^4.0.1package.json only declares Cordis peer dependency, specific DSH version not specified
Node.js`^22.19.0
git commandAny mainstream versionRead repository facts via subprocess like git ls-files / rev-parse / config
PlatformCross-platform (macOS / Windows / Linux)Uses Node node:fs, node:os, git CLI; no platform-specific code
Native ModulesNoneOnly depends on Node built-in modules

Package declares dsh.bundle.patch, automatically loads as profile layer after installation; this plugin has no native module dependencies.

Installation

dsh plugin --profile web add github:Anionex/dsh-turn-rewind

Configuration Options

ConfigTypeDescriptionDefault
storageDirstringDirectory for persistent restore points, logs, blobs; must not overlap with managed worktree$DSH_HOME/change-ledger/v1, falls back to ~/.dsh/change-ledger/v1 if DSH_HOME not set
maxRestorePointspositive integerMaximum number of user + rescue restore points per workspace50
maxTurnCheckpointsPerSessionpositive integerMaximum number of auto turn checkpoints per session; only cleans up its own oldest, user/rescue points are never silently deleted30
maxFilespositive integerMaximum files covered by a single restore point, fails directly if exceeded20000
maxFileBytesbyte countMaximum allowed size for single file, fails directly if exceeded16777216 (16 MiB)
maxSnapshotBytesbyte countTotal cumulative byte limit for all regular files in a restore point536870912 (512 MiB)
planTtlMsmillisecondValidity period after popup generates restore plan; expires and becomes invalid900000 (15 minutes)
staleLockMsmillisecondThreshold for "owner process dead but lock file still exists" determination for locks, exceeded before takeover allowed30000 (30 seconds)

All capacity and user restore point limits use fail loud strategy, exceeding limits throws error instead of auto-cleanup.
Override in profile's patch layer by id: turn-rewind, e.g.: config: { storageDir: "~/.dsh/change-ledger/v1", maxRestorePoints: 50, ... }.

FAQ

Q: Does it need additional configuration after installation?

A: No. Package already declares dsh.bundle.patch, cordis.patch.yml mounts directly, takes effect after installation; storage directory has default value, after installation restart profile to see rewind icon under each user message.

Q: Will restore affect Git's branches, HEAD, index, stash, commit?

A: No. Security contract explicitly states only restore workspace files, do not modify Git index, branches, HEAD, stash, and commit. Reviewed HEAD/branch changes won't block restore either, restored content will appear as uncommitted modifications of current HEAD.

Q: Can it restore when other Agents are running in the same project directory?

A: No, it will be blocked. Restore scans other Agents' workspaces, if any running Session shares the same worktree, this restore fails with WORKSPACE_IN_USE; idle Sessions don't block restore.

Q: Does restore automatically rollback on failure?

A: Yes. Before each execution, a rescue snapshot is created; execution failure immediately rolls back via rescue snapshot; if rollback also fails, operation status is marked as recovery-required, rescue point can be found via listRecovery for manual processing.

Q: Which Git repositories are supported? Which are not?

A: Only regular Git worktrees supported. Sparse checkout, submodule gitlinks, ignored files, socket/device/FIFO and other special files, extended attributes/ACL/ownership/timestamp/hard-link topology, Git index and repository metadata are not in snapshot scope, creating restore points fails directly when encountering these.

Q: Can other Cordis plugins call this capability?

A: Yes. Plugins get ctx.changeLedger via inject: ['changeLedger'], then can call the complete lifecycle API: create / list / inspect / planRestore / applyRestore / delete / listRecovery; full types exported from @anionex/dsh-turn-rewind/format, engine itself can be used separately from @anionex/dsh-turn-rewind/core.

Q: DSH crashes mid-operation, what happens to unfinished restore operations?

A: Automatic reconciliation at startup: mark those non-final operation logs with unheld workspace locks as interrupted; if another surviving DSH process holds the workspace lock, won't be misidentified. Rescue points are always retained as regular inspectable restore points until explicitly deleted.

Q: Does restore rewrite Git history?

A: No. Repository metadata (index, branches, HEAD, stash, commit) remains unchanged throughout, plugin only reads factual information from commands like git ls-files / rev-parse for validation, never initiates any write operations like commit / stash / reset / checkout / branch.

Learning Curve

Beginner — from user perspective, just install and restart profile, no configuration or commands needed; Agent developers need to read Service API only to call ctx.changeLedger.

Known Issues & Limitations

  • Does not support sparse checkout worktrees, creating restore points fails directly (sparse paths cannot be defined in snapshots)
  • Does not support submodule: when any gitlink is encountered, entire worktree is rejected, requires entering each submodule to create restore points separately
  • Does not track ignored files, special file types (socket/device/FIFO), extended attributes/ACL/ownership/timestamp/hard-link topology, restoration of these objects fails rather than silently discarded
  • If target path has ignored or unmanaged files occupying space during restore, will directly refuse to overwrite (avoid recursively deleting worktree content)
  • Refuses to cross symlink parent directories, also refuses to overwrite non-empty directories
  • When any running state Agent exists in same worktree, this restore is blocked by WORKSPACE_IN_USE; idle Sessions don't block
  • During ongoing Git operations like merge / rebase / cherry-pick / revert / bisect, this restore is blocked
  • Default capacity limits (maxFiles=20000, maxFileBytes=16 MiB, maxSnapshotBytes=512 MiB) are conservative, need to actively increase if workspace exceeds limits
  • If new conversation creation fails during same turn "Restore files and continue from here", plugin automatically rolls back files from rescue point; but if rollback also fails, need manual processing via listRecovery

Read the usage guide →

Install steps, key points, FAQ and compatibility for this plugin — auto-derived from indexed fields.

Listing badge

Listed on deepseek-plugin.org
[![Listed on deepseek-plugin.org](https://img.shields.io/badge/listed_on-deepseek--plugin.org-007EC6)](https://deepseek-plugin.org/plugins/Anionex/dsh-turn-rewind)

Paste this markdown into your GitHub README to link back to this listing. The badge only states the listing — not a security endorsement.

← Back to plugin directory