dsh-rewind-plugin 0.2.7 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -178
- package/README.zh.md +77 -165
- package/docs/harness-reference.md +23 -0
- package/docs/release.md +90 -0
- package/docs/troubleshooting.md +39 -0
- package/docs/troubleshooting.zh.md +31 -0
- package/lib/client.js +217 -148
- package/lib/types/client/index.d.ts +14 -18
- package/lib/types/client/portals.d.ts +66 -0
- package/lib/types/client/styles.d.ts +0 -2
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -1,46 +1,26 @@
|
|
|
1
1
|
# dsh-rewind
|
|
2
2
|
|
|
3
|
-
[
|
|
4
|
-
|
|
5
|
-
In-place conversation rewind for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness): the Claude Code `/rewind` semantics inside the **same session window** — cut the model context back to an earlier user message, and optionally restore workspace files from **disk-persisted before-backups**.
|
|
6
|
-
|
|
7
|
-
> **Status:** published to npm (`dsh-rewind-plugin`, v0.2.7) via GitHub Actions Trusted Publishing + Sigstore provenance. Targets the web profile (`dsh --profile web`). Interaction mirrors Claude Code's rewind, adapted to dsh's real web UI.
|
|
8
|
-
>
|
|
9
|
-
> **v0.2.7 highlights:** composer refill is event-driven (reopening a session never resurrects withdrawn text); subagent edits are not tracked (Claude Code alignment); concurrent rewinds are guarded; the code-restore option appears only when tracked changes exist (mixed host/client versions safe).
|
|
3
|
+
In-place conversation rewind for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness): Claude Code's `/rewind` semantics inside the **same session window** — cut the model context back to an earlier user message, and optionally restore workspace files from disk-persisted before-backups.
|
|
10
4
|
|
|
11
5
|
[](https://www.npmjs.com/package/dsh-rewind-plugin)
|
|
12
6
|
[](https://github.com/SiriLee/dsh-rewind/blob/main/LICENSE)
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
| Feature | Description |
|
|
32
|
-
| --- | --- |
|
|
33
|
-
| In-place rewind | Rewind to **any** user message from a per-message ↶ button: the target message and everything after it (agent replies, tool calls) are withdrawn from the model context *and* the rendered transcript — no new session, no window switch |
|
|
34
|
-
| Time-travel semantics | Rewinding to a message withdraws **that message too**; its text is offered back in the composer so you can edit and re-send it |
|
|
35
|
-
| Claude-Code-style file restore | Write-class edits are backed up **before** they happen and persisted on disk; "conversation and code" restores files to their pre-edit content and deletes files created after the target |
|
|
36
|
-
| Impact preview | "Conversation and code" first shows the exact restore / delete list for confirmation (the option is hidden when there are no tracked changes — like Claude Code's code-restore visibility) |
|
|
37
|
-
| Approval-plugin coexistence | Capture runs at the `tools/execute` around-dispatch stage, so another plugin's pre-execute approval short-circuit (e.g. dsh-edit-approval) cannot skip the backup, and a denied call never records |
|
|
38
|
-
| Paths resolved by session cwd | Relative paths are backed up and restored against the **real** file using the fs-tools session-cwd rule; the resolved display path is what gets recorded |
|
|
39
|
-
| Restores write real files | Restore goes through plain `node:fs` directly to the filesystem; symbolic and hard links are skipped with a warning (no clobber through a shared inode) |
|
|
40
|
-
| Survives host restart | Backups live on disk under `~/.dsh/rewind-snapshots/<session>/<anchor seq>/`, newest 100 message groups per session |
|
|
41
|
-
| Localized | `zh` / `en` copy registered into the dsh locale system |
|
|
42
|
-
|
|
43
|
-
## 📸 Screenshots
|
|
8
|
+
> English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
A deliberately focused plugin with one job: rewind to any earlier user message, in place.
|
|
11
|
+
|
|
12
|
+
| Mode | Conversation | Workspace files |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| **Rewind conversation only** | Cut back to the target message | Untouched |
|
|
15
|
+
| **Rewind conversation and code** | Cut back to the target message | Restored to their state before it (modified files written back, later-created files deleted) |
|
|
16
|
+
|
|
17
|
+
Rewinding is time-travel: the target message and everything after it (agent replies, tool calls) are withdrawn from the model context *and* the rendered transcript — no new session, no window switch — and the target's text is offered back in the composer so you can edit and re-send it.
|
|
18
|
+
|
|
19
|
+
The plugin never rewrites the append-only session log and never touches your git repository.
|
|
20
|
+
|
|
21
|
+
## Preview
|
|
22
|
+
|
|
23
|
+
Each user message gains a compact **↶ rewind** action in its action row. Clicking it opens a mode-selection popover; "conversation and code" first shows the exact restore / delete list for confirmation (the option is hidden when there are no tracked changes — like Claude Code's code-restore visibility).
|
|
44
24
|
|
|
45
25
|
<table>
|
|
46
26
|
<tr>
|
|
@@ -53,132 +33,78 @@ In-place conversation rewind for [DeepSeek Harness](https://github.com/deepseek-
|
|
|
53
33
|
</tr>
|
|
54
34
|
</table>
|
|
55
35
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Two halves work together: the **conversation rewind** (in-place, same window) and the **checkpoint file restore** (Claude-Code-style before-backups).
|
|
36
|
+
Manual `/rewind` input in the composer is intercepted — submitting shows a transient hint pointing at the ↶ button.
|
|
59
37
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
The plugin appends an **empty-content marker** `assistant/message` into the session log whose `surfaceOp: { op: 'replace', start, end }` replaces every surface node after the target message with the marker:
|
|
63
|
-
|
|
64
|
-
- The marker carries `sourceEventSeqs` covering every shadowed node, and the `Session.append` surface rules validate the cut (only a contiguous range on the current surface).
|
|
65
|
-
- Because the marker is **empty**, the harness derives it to `null` — it never enters the model context and never renders as conversation content. The agent and the user both see the conversation exactly as it was at the target.
|
|
66
|
-
- The marker's **turn number reuses the LAST STARTED turn** (`markerTurnOf`), never `lastTurn + 1`: the harness's agent loop numbers its next real turn exactly `last turn/start + 1`, so a marker numbered the same way would leave an `assistant/message` BEFORE the `turn/start` of the same turn — the client conversation-context builder rejects that ordering with `conversation Context …:turn-tail… received an update before its start Match`, history load fails, and the whole conversation disappears from the UI (the real defect in ≤ 0.2.4, fixed in 0.2.5). Reusing an already-consumed turn makes the marker a harmless trailing update on the previous completed turn's tail — it can never collide with a future turn.
|
|
67
|
-
- The append-only log is **untouched** — the audit trail keeps every withdrawn event; only the model-visible surface is cut, so the next request derives its context from the target onward.
|
|
68
|
-
|
|
69
|
-
A running turn (LLM thinking / streaming) is force-stopped first (`cancel({ kind: 'user' })`) and the rewind waits for quiescence; if it can't stop, the rewind is aborted with an error.
|
|
70
|
-
|
|
71
|
-
### 2. Checkpoint file restore
|
|
72
|
-
|
|
73
|
-
The plugin tracks the write-class tools — `write`, `edit`, `str_replace_editor` (mutating commands `create` / `str_replace` / `insert`):
|
|
74
|
-
|
|
75
|
-
1. **Before-capture** at `tools/execute` (the around-dispatch stage): the target file is read and the resolved path + content are held in a pending map. This stage only runs after any pre-execute approval gate let the call through — so an `ask` short-circuit (dsh-edit-approval) **cannot skip** the backup, and a denied call never records.
|
|
76
|
-
2. **Disk commit** at `tools/post-execute`: the before-backup is written under the turn's **anchor message seq** (`~/.dsh/rewind-snapshots/<session>/<anchor seq>/<callId>.json`).
|
|
77
|
-
3. **Restore** (`/rewind @<seq> both`): every backup anchored at or after the target applies — modified files are written back to their **earliest** captured before-state, files created after the target are deleted, symbolic / hard links are skipped. Writes go through plain `node:fs`, independent of the fs service.
|
|
78
|
-
4. A failed tool body that **throws** skips `tools/post-execute`; a `tools/result` safety net clears the pending capture so nothing leaks in memory.
|
|
79
|
-
|
|
80
|
-
Backups persist across host restarts, bounded to the newest 100 anchor groups per session.
|
|
81
|
-
|
|
82
|
-
## 🔧 Troubleshooting: history load failure (`…turn-tail… received an update before its start Match`)
|
|
83
|
-
|
|
84
|
-
Versions ≤ 0.2.4 corrupted client replay when a rewind was **followed by further
|
|
85
|
-
conversation**: the marker's turn number collided with the next real turn's
|
|
86
|
-
`turn/start`, so reopening the session showed
|
|
87
|
-
`Failed to load history: conversation Context …:turn-tail… received an update before its start Match (internal)`
|
|
88
|
-
and the history vanished. Rewinds created from 0.2.5 on no longer produce the
|
|
89
|
-
collision, but **already-corrupted sessions need an offline repair** (the log is
|
|
90
|
-
append-only — it cannot be rewritten in memory).
|
|
91
|
-
|
|
92
|
-
The repair tool ships **inside the npm package** (`dsh-rewind-repair`) — no
|
|
93
|
-
source checkout needed:
|
|
38
|
+
## Install
|
|
94
39
|
|
|
95
40
|
```sh
|
|
96
|
-
|
|
97
|
-
# a disk repair is overwritten by the next checkpoint)
|
|
98
|
-
# 2. Run the offline repair (scans every session under ~/.dsh/sessions,
|
|
99
|
-
# rewriting each marker's turn back to the last started turn)
|
|
100
|
-
npm exec --yes --package=dsh-rewind-plugin -- dsh-rewind-repair
|
|
101
|
-
npm exec --yes --package=dsh-rewind-plugin -- dsh-rewind-repair -- --dry-run # preview only
|
|
102
|
-
# 3. Restart dsh web — the repaired sessions load their history again
|
|
41
|
+
dsh plugin --profile web add dsh-rewind-plugin
|
|
103
42
|
```
|
|
104
43
|
|
|
105
|
-
|
|
106
|
-
`dsh-rewind-repair` directly; from a source checkout the same tool is
|
|
107
|
-
`node scripts/repair-markers.mjs` (identical flags).
|
|
44
|
+
Restart `dsh web` (`--profile web`) after installing.
|
|
108
45
|
|
|
109
|
-
|
|
110
|
-
(keeping seqs, order, and the zstd frame structure intact), backs up the original
|
|
111
|
-
file to `session.jsonl.zstd.bak-<timestamp>` before writing, and never touches
|
|
112
|
-
any other event — safe to run repeatedly.
|
|
46
|
+
> ⚠️ The npm name `dsh-rewind` belongs to another author's package — install with `dsh-rewind-plugin`.
|
|
113
47
|
|
|
114
|
-
|
|
48
|
+
From a local checkout or a pinned GitHub commit:
|
|
115
49
|
|
|
116
|
-
|
|
50
|
+
```sh
|
|
51
|
+
dsh plugin --profile web add /path/to/dsh-rewind # local checkout
|
|
52
|
+
dsh plugin --profile web add github:SiriLee/dsh-rewind#<sha> # pinned commit
|
|
53
|
+
```
|
|
117
54
|
|
|
118
|
-
|
|
55
|
+
A git install fails on first run: pnpm blocks git dependencies from running build scripts. Follow the CLI hint to add an `allowBuilds` key to the profile's `pnpm-workspace.yaml`, then retry — pnpm runs the plugin's `prepare` (full build) and installs it.
|
|
119
56
|
|
|
120
|
-
|
|
57
|
+
## Usage
|
|
121
58
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
59
|
+
1. **Hover** any user message you sent — a **↶ rewind** button appears in its action row.
|
|
60
|
+
2. **Click it.** The target is that message; a small popover offers the two modes ("conversation and code" is hidden when no tracked file changes exist after the target).
|
|
61
|
+
3. The rewind executes as an in-session command; a result message confirms, and the withdrawn message's text is filled back into the composer for editing and re-sending.
|
|
125
62
|
|
|
126
|
-
|
|
63
|
+
The ↶ button appears on user messages rendered in the **current session view** — switch to another session before rewinding it. A rewind can itself be rewound (its marker enters the log), but the file-restore action is not re-backed up.
|
|
127
64
|
|
|
128
|
-
|
|
129
|
-
cd dsh-rewind
|
|
130
|
-
npm install # devDeps come from the npm registry; no harness checkout needed
|
|
131
|
-
npm run build # full build: lib/ (host ESM + client bundle + .d.ts)
|
|
132
|
-
dsh plugin --profile web add /path/to/dsh-rewind # link install
|
|
133
|
-
```
|
|
65
|
+
## How it works
|
|
134
66
|
|
|
135
|
-
###
|
|
67
|
+
### 1. Conversation rewind (in-place)
|
|
136
68
|
|
|
137
|
-
|
|
138
|
-
dsh plugin --profile web add github:SiriLee/dsh-rewind#<commit-sha>
|
|
139
|
-
```
|
|
69
|
+
The plugin appends an **empty-content marker** `assistant/message` into the session log whose `surfaceOp: { op: 'replace', start, end }` replaces every surface node after the target message with the marker:
|
|
140
70
|
|
|
141
|
-
|
|
142
|
-
the
|
|
143
|
-
(
|
|
144
|
-
the
|
|
71
|
+
- The marker carries `sourceEventSeqs` covering every shadowed node, and `Session.append`'s surface rules validate the cut (a contiguous range on the current surface).
|
|
72
|
+
- Because the marker is **empty**, the harness derives it to `null` — it never enters the model context and never renders as conversation content. Agent and user both see the conversation exactly as it was at the target.
|
|
73
|
+
- The marker's **turn number reuses the last started turn** (`markerTurnOf`), never `lastTurn + 1`: the harness numbers its next real turn exactly `last turn/start + 1`, so a `maxTurn + 1` marker would sit *before* that `turn/start` — the client conversation builder rejects the ordering (`…turn-tail… received an update before its start Match`), history load fails, and the whole conversation disappears from the UI (the real defect in ≤ 0.2.4, fixed in 0.2.5). Reusing an already-consumed turn makes the marker a harmless trailing update on the previous completed turn's tail — it can never collide with a future turn.
|
|
74
|
+
- The append-only log is **untouched** — every withdrawn event stays in the audit trail; only the model-visible surface is cut, so the next request derives its context from the target onward.
|
|
145
75
|
|
|
146
|
-
|
|
76
|
+
A running turn (LLM thinking / streaming) is force-stopped first (`cancel({ kind: 'user' })`) and the rewind waits for quiescence; if it can't stop, the rewind is aborted with an error.
|
|
147
77
|
|
|
148
|
-
###
|
|
78
|
+
### 2. Checkpoint file restore
|
|
149
79
|
|
|
150
|
-
|
|
151
|
-
2. **Click it.** The target is that message (step one is done). A small popover opens (step two):
|
|
152
|
-
- **Rewind conversation only** — cut the model context back to before the message; workspace files stay untouched.
|
|
153
|
-
- **Rewind conversation and code** — same context cut, plus workspace files restored to their state before the message. An impact list (files to restore / delete) is shown first, then you confirm.
|
|
154
|
-
- The "conversation and code" option is **hidden** when no tracked file changes exist after the target (matching Claude Code's behavior).
|
|
155
|
-
3. The rewind executes as an in-session command; a result message confirms (e.g. "已撤回 seq N 及之后内容;还原 M 个文件"), and the withdrawn message's text is filled back into the composer for editing and re-sending.
|
|
80
|
+
The plugin tracks the write-class tools — `write`, `edit`, `str_replace_editor` (mutating commands `create` / `str_replace` / `insert`):
|
|
156
81
|
|
|
157
|
-
|
|
82
|
+
1. **Before-capture** at `tools/execute` (the around-dispatch stage): the target file is read; the resolved path + content are held in a pending map. This stage runs only after any pre-execute approval gate let the call through — an `ask` short-circuit (dsh-edit-approval) **cannot skip** the backup, and a denied call never records. If the read fails (e.g. a permission error), the change is simply not backed up — the plugin warns in the log but **does not block the write**.
|
|
83
|
+
2. **Disk commit** at `tools/post-execute`: the before-backup is written under the turn's anchor message seq (`~/.dsh/rewind-snapshots/<session>/<anchor seq>/<callId>.json`).
|
|
84
|
+
3. **Restore** (`/rewind @<seq> both`): every backup anchored at or after the target applies — modified files are written back to their **earliest** captured before-state, files created after the target are deleted, symbolic / hard links are skipped (they share an inode with another name; restoring through one would clobber both). Writes go through plain `node:fs`, independent of the fs service — under sandbox / remote backends, path resolution may be restricted.
|
|
85
|
+
4. A tool body that **throws** skips `tools/post-execute`; a `tools/result` safety net clears the pending capture so nothing leaks in memory.
|
|
158
86
|
|
|
159
|
-
|
|
87
|
+
Backups persist across host restarts, bounded to the newest 100 anchor groups per session.
|
|
160
88
|
|
|
161
|
-
|
|
89
|
+
## What it deliberately does NOT do
|
|
162
90
|
|
|
163
|
-
|
|
91
|
+
- **Whole-tree / git-first snapshots** — only write-class tool edits are backed up. `bash`, other tools, and external edits are not tracked and cannot be restored: the same limitation as Claude Code, which defers such rollbacks to the user's git.
|
|
92
|
+
- **Subagent edits** — not tracked (same as Claude Code): a subagent runs its own session, so its backups could never be restored by a rewind of the parent session.
|
|
93
|
+
- **Fork / branch rewind and `/compact`** — the harness already provides these ("branch in new chat", compact).
|
|
94
|
+
- **Keyboard shortcuts** (esc+esc rewind menu) — planned as a follow-up.
|
|
164
95
|
|
|
165
|
-
##
|
|
96
|
+
## Comparison with similar projects
|
|
166
97
|
|
|
167
|
-
|
|
168
|
-
- **Subagent edits are not tracked** — same as Claude Code. A subagent runs its own session, so its backups could never be restored by a rewind of the parent session; the capture is skipped instead of recording to an unreachable store.
|
|
169
|
-
- If a before-capture read fails (e.g. a permission error), that change is simply not backed up and a `both` rewind cannot restore it — the plugin logs a warning but **does not block the write**.
|
|
170
|
-
- File restore/delete writes through the **real local filesystem**; under sandbox / remote backends path resolution may be restricted.
|
|
171
|
-
- Symbolic links and hard links are not written through (they share the inode with another name; a restore would clobber both) — they are skipped and reported.
|
|
172
|
-
- A rewind can itself be rewound (its marker enters the log), but the file-restore action is not re-backed up.
|
|
173
|
-
- The ↶ button is injected on user messages rendered in the **current session view**; switch to another session before rewinding it.
|
|
174
|
-
- When no tracked file changes exist after the target, the mode popover offers only "conversation only" (Claude Code hides code-restore options the same way).
|
|
98
|
+
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) also has [Anionex/dsh-turn-rewind](https://github.com/Anionex/dsh-turn-rewind) — a rewind plugin with the same user-facing idea (a per-message action that rolls the conversation back and restores workspace files), but a different approach:
|
|
175
99
|
|
|
176
|
-
|
|
100
|
+
| Dimension | dsh-rewind (this plugin) | Anionex dsh-turn-rewind |
|
|
101
|
+
| --- | --- | --- |
|
|
102
|
+
| Conversation rollback | **In-place, same session/window** — the model-visible surface is cut back to the target; the append-only log is untouched | **Forks a new Session** at the previous `turn/end`; the original session is always retained |
|
|
103
|
+
| File-restore engine | **Lightweight before-backups** of write-class tools only, restored via plain `node:fs` | **Change Ledger** — a durable restore-point engine with Git fences, an approval gate, rescue points and crash reconciliation |
|
|
104
|
+
| Tracked-change scope | Only write-class tool edits (like Claude Code) | Any Git-managed file (Git worktree required) |
|
|
105
|
+
| Public service API | No — a focused single-purpose plugin | Yes — `ctx.changeLedger` service + `/turn-rewind` HTTP endpoint |
|
|
177
106
|
|
|
178
|
-
-
|
|
179
|
-
- `/compact` — provided by the harness.
|
|
180
|
-
- Fork / branch rewind — the harness's built-in "branch in new chat".
|
|
181
|
-
- Whole-tree / git-first snapshots covering bash and external edits — **deliberately not implemented**, in line with Claude Code's native rewind (which also defers such rollbacks to the user's git).
|
|
107
|
+
The essential difference: dsh-turn-rewind keeps the log immutable and therefore forks a new session; this plugin cuts the model-visible surface in place with an empty marker, so the original conversation continues in the same window — the non-trivial part (see [Known issues](#known-issues)) that dsh-turn-rewind sidesteps.
|
|
182
108
|
|
|
183
109
|
## Compatibility
|
|
184
110
|
|
|
@@ -189,6 +115,16 @@ Rewinding to a message **withdraws** it and everything after it — the transcri
|
|
|
189
115
|
> This project and DeepSeek Harness are both in developer preview. Pin exact
|
|
190
116
|
> versions in reproducible environments and review the behavior notes above.
|
|
191
117
|
|
|
118
|
+
## Known issues
|
|
119
|
+
|
|
120
|
+
Rewinds created with versions `≤ v0.2.4` could corrupt client replay when followed by more conversation (a marker turn collides with the next `turn/start`). The offline repair tool ships **inside the npm package** (`dsh-rewind-repair`). This only affects sessions you already had before upgrading — a fresh install never hits it.
|
|
121
|
+
|
|
122
|
+
Full instructions: [docs/troubleshooting.md](docs/troubleshooting.md)
|
|
123
|
+
|
|
124
|
+
## Security
|
|
125
|
+
|
|
126
|
+
This plugin only appends rewind-marker events to the session log; it never deletes or rewrites logged history. File writes happen only when you choose "conversation and code" — before-backups and restores stay under `~/.dsh/rewind-snapshots/`. It never touches your git repository, makes no network requests, and accesses no credentials.
|
|
127
|
+
|
|
192
128
|
## Development
|
|
193
129
|
|
|
194
130
|
```sh
|
|
@@ -199,55 +135,19 @@ npm run build # esbuild: lib/index.js (host ESM) + lib/client.js (loade
|
|
|
199
135
|
node scripts/verify-host.mjs # boot the BUILT host artifact end-to-end (18 checks)
|
|
200
136
|
```
|
|
201
137
|
|
|
202
|
-
`prepare` runs the full build, so git installs and `npm pack` / `npm publish`
|
|
203
|
-
always produce a complete `lib/` and the `LICENSE`.
|
|
138
|
+
`prepare` runs the full build, so git installs and `npm pack` / `npm publish` always produce a complete `lib/` and the `LICENSE`.
|
|
204
139
|
|
|
205
|
-
Maintainers:
|
|
206
|
-
DeepSeek Harness interface reference (subsystem docs + key source index).
|
|
140
|
+
Maintainers: the module map and harness interface reference live in [docs/harness-reference.md](docs/harness-reference.md); publishing steps in [docs/release.md](docs/release.md).
|
|
207
141
|
|
|
208
|
-
##
|
|
142
|
+
## Release
|
|
209
143
|
|
|
210
|
-
Releases go out through GitHub Actions Trusted Publishing (OIDC, no stored
|
|
211
|
-
`NPM_TOKEN`):
|
|
144
|
+
Releases go out through GitHub Actions Trusted Publishing (OIDC, no stored `NPM_TOKEN`): push a `v<version>` tag and CI publishes with Sigstore provenance.
|
|
212
145
|
|
|
213
146
|
```sh
|
|
214
|
-
npm version patch && git push origin main --tags
|
|
147
|
+
npm version patch && git push origin main --tags
|
|
215
148
|
```
|
|
216
149
|
|
|
217
|
-
-
|
|
218
|
-
a full build + artifact verification, publishes with `--provenance`
|
|
219
|
-
(Sigstore), and creates a GitHub Release. It is **idempotent** — an already
|
|
220
|
-
published version is skipped. CI (`.github/workflows/ci.yml`) runs the same
|
|
221
|
-
checks on every push / PR, plus a `npm pack --dry-run` sanity check that the
|
|
222
|
-
tarball carries `lib/` and `LICENSE`.
|
|
223
|
-
- One-time npm-side configuration (cannot be done from this repo): open
|
|
224
|
-
[dsh-rewind-plugin](https://www.npmjs.com/package/dsh-rewind-plugin) →
|
|
225
|
-
**settings → Trusted Publisher → Add**, with Provider **GitHub Actions** ·
|
|
226
|
-
Organization or user **`SiriLee`** · Repository **`dsh-rewind`** (the GitHub
|
|
227
|
-
repo, not the npm name) · Workflow filename **`publish.yml`** · Environment
|
|
228
|
-
**empty** · Allowed actions **`npm publish`**. Once configured, pushes of
|
|
229
|
-
`v<version>` tags publish automatically.
|
|
230
|
-
|
|
231
|
-
## Directory layout
|
|
232
|
-
|
|
233
|
-
```
|
|
234
|
-
src/index.ts host plugin: /rewind command + checkpoint pipeline (tools/execute|post-execute)
|
|
235
|
-
src/rewind.ts pure planning: target resolution, surface range, candidate listing
|
|
236
|
-
src/snapshot.ts checkpoint store (disk before-backups, restore/preview, bounded prune)
|
|
237
|
-
src/session-cwd.ts session-cwd resolution (fs-tools rule)
|
|
238
|
-
src/client/index.ts client plugin: per-message ↶ button + manual /rewind guard
|
|
239
|
-
src/client/popover.ts mode-selection popover (both-mode impact confirm)
|
|
240
|
-
src/client/hidden.ts withdrawn-span computation (hiddenSeqsOf), pure
|
|
241
|
-
src/client/locales.ts zh / en copy (LocaleNamespaceMap)
|
|
242
|
-
src/client/styles.ts injected styles (dsh design tokens)
|
|
243
|
-
scripts/build.mjs esbuild: lib/index.js (host ESM) + lib/client.js (loader closure) + .d.ts
|
|
244
|
-
scripts/verify-host.mjs end-to-end host verification (18 checks)
|
|
245
|
-
tests/ vitest suites (rewind / snapshot / hidden / session-cwd / integration, 46 cases)
|
|
246
|
-
docs/harness-reference.md maintainer docs: DeepSeek Harness interface reference
|
|
247
|
-
assets/screenshots/ UI screenshots
|
|
248
|
-
cordis.patch.yml bundle patch (mounts the dual-face plugin row)
|
|
249
|
-
package.json dsh.bundle + dsh.client manifests, optional peerDependencies
|
|
250
|
-
```
|
|
150
|
+
One-time npm-side setup and the full workflow details: [docs/release.md](docs/release.md).
|
|
251
151
|
|
|
252
152
|
## License
|
|
253
153
|
|