dsh-session-guard
Per-session advisory locks that stop two dsh processes from corrupting one session log. Companion to dsh-session-rescue.
- Stars
- 0
- Language
- TypeScript
- Created
- Sep 5, 2026
- Updated
- Sep 5, 2026
Introduction
dsh-session-guard
Stops two DeepSeek Harness processes from corrupting one session log.
中文文档 · Companion: dsh-session-rescue (repairs the damage this plugin prevents)
The most common dsh corruption family is concurrent writing: a dsh web plus a CLI, two instances on different ports, or a desktop shell sharing one $DSH_HOME. Each process keeps its own in-memory seq cursor, the second writer lands events with already-committed seqs, and the session becomes permanently unloadable:
history unavailable for session "…": corrupt session log: seq gap in committed region …
dsh has no cross-process lock today. This plugin adds one — advisory, per-session, with automatic takeover of dead owners — so the conflicting step fails loudly with an actionable message instead of silently destroying your history.
Install
dsh plugin --profile web add dsh-session-guard
Using an AI agent? Tell it: "Install the dsh-session-guard plugin into my dsh."
What you see when it saves you
Error: session-guard: session session-37374e34… is already being written by another
dsh process (pid 84231 on mbp.local, held 42s, last heartbeat 3s ago). Two writers
on one session corrupt its log ("seq gap in committed region"). Close that process
or use a different session; a dead owner’s lock is taken over automatically …
The step fails; the log stays intact; nothing is lost. Crashed processes never wedge a session: a lock whose owner pid is gone is taken over instantly, and unverifiable owners (other hosts on a shared home) expire after 90s without a heartbeat.
Configuration
All optional, set on the plugin row in your profile patch:
- id: session-guard
name: dsh-session-guard
config:
mode: enforce # 'enforce' (default) fails conflicting steps; 'warn' only logs
heartbeatMs: 15000 # heartbeat refresh for held locks
staleAfterMs: 90000 # unverifiable owners expire after this silence
# lockDir: /custom # default: $DSH_HOME/session-locks
Honest boundary
- The lock is advisory: it protects dsh processes that load this plugin. A process without it is not restrained (install the plugin in every profile you run).
- It guards the active turn-write path (
agent/session-start,agent/pre-step). The cold-load repair path that commits synthetic interrupt-closers before any step runs is inside dsh itself and cannot be intercepted from a plugin — that fix needs to land upstream. - Locks live under
$DSH_HOME/session-locks; deployments overriding the session root elsewhere in config still key locks by home + session id. - If corruption already happened, this plugin can't undo it — dsh-session-rescue can.
Zero runtime dependencies. MIT.