dsh-turn-review
简体中文 · English
A DeepSeek Harness web plugin: a Turn Review tab in dsh-better-sidebar (omdsh-dev/DSH-better-sidebar) — a human gate on the diff of the just-finished agent turn: Approve / Request changes.
Not a rewind. Others build time machines; we build the review gate.
Five features (v1 ships all of them)
1. Only the last turn. No checkpoint timeline, no forking back; a new turn expires the previous review. 2. Same session. No fork, no conversation trimming; the comment lands via agent.inject (no wake). 3. Attribution. Paths are grouped by main session / subagent / unattributed (shell or out-of-session edits). 4. Per-path Request changes + optional comment. The inject notice carries only paths + attribution + comment — no file content, no tokens. 5. See the diff first. Click a path to read the turn-start snapshot vs now unified diff, inline in the tab (never the built-in Git index/HEAD diff).
Two quality baselines: the workspace is snapshotted at turn start (so shell edits show up too), and git reset --hard / git clean / session fork / /rewind / model tools are forbidden.
Read-only history
The tab footer shows the last 20 turns: each is tagged approved / requested-changes (with paths and comment) / expired, expandable to the path list. History is always read-only — you cannot restore disk from turn N-3. No timeline rewind in this product.
Coexistence
Turn Review = Approve / Request changes on the just-finished turn's diff.
To go back to earlier messages or fork a session, use /rewind-style plugins.
For commits and pushes, use the better-sidebar Git tab and Git remotes.Install
dsh plugin --profile web add dsh-better-sidebar
dsh plugin --profile web add git+https://github.com/yq04/dsh-turn-review.gitWithout better-sidebar the host routes still mount; the client declares inject = ['betterSidebar'] so the tab stays inactive. Remove with:
dsh plugin --profile web remove dsh-turn-review
dsh plugin --profile web --dump-configRequires system git. The plugin never stores tokens and redacts common token shapes in inject text.
Boundaries
| Does | Does not |
|---|---|
| turn-start snapshot + end diff (subagents and shell included) | checkpoint timeline, step-back |
| per-path restore (unlink / checkout start HEAD / write back bytes) + disk re-read | git reset --hard, git clean, force-push |
agent.inject notice (no wake) | sessions.prompt auto re-run |
POST + application/json + Host trust fence | model-facing tools |
| refuse binary / over-cap / symlink paths | silent skip, follow symlinks |
Request changes requires confirm: true — human-clicked, like the Git remotes push.
Model Experience
Only when the human requests changes and the inject succeeds does the model see, in the next request, one user message with source.kind === 'plugin'. Copy is locked Chinese: paths + attribution + optional comment. Approve injects nothing. If the agent is unavailable after disk restore (agent-unavailable), the UI says so explicitly.
Limits
- Not a time machine: no fork, no
/rewind, no checkpoint timeline. - Restore targets the turn-start workspace state (including pre-turn
dirt); files committed mid-turn are only removed from the worktree — the index/HEAD stays for the Git tab.
- Non-git workspaces: attribution only, no restore (UI states this).
- Caps live in
src/config.ts(1 MiB per file, 200 files); not
configurable in v1.
Develop
pnpm install
pnpm typecheck
pnpm test
pnpm build
node scripts/verify-self-contained.mjsdsh.bundle.patch is cordis.patch.yml. Run pnpm build before release (npm prepare runs tsdown).
License
BSD-3-Clause (same as the official plugin-template).