# dsh-session-guard **阻止两个 DeepSeek Harness 进程写坏同一个会话日志。** [English](README.md) · 姊妹项目:[dsh-session-rescue](https://github.com/po-et/dsh-session-rescue)(修复本插件所预防的那种损坏) dsh 最高发的损坏家族就是并发写入:`dsh web` + CLI 双开、两个端口两个实例、桌面壳与网页共享一个 `$DSH_HOME`——每个进程各持一份内存 seq 游标,第二个写入方落盘的事件与已提交 seq 撞号,会话从此永远打不开: ``` history unavailable for session "…": corrupt session log: seq gap in committed region … ``` dsh 目前没有跨进程锁。本插件补上一把:按会话的咨询锁 + 死进程自动接管——冲突的那一步会**带着可操作的报错响亮失败,而不是悄悄毁掉你的历史**。 ## 安装 ```sh dsh plugin --profile web add @po-et/dsh-session-guard ``` 在用 AI agent?直接对它说:**"给我的 dsh 装上 dsh-session-guard 插件。"** ## 它救你时长这样 ``` 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). … ``` 该步失败、日志完好、什么都没丢。崩溃的进程永远不会卡死会话:属主 pid 已消失的锁会被立即接管;无法验证的属主(共享目录上的其他主机)90 秒无心跳即过期。 ## 配置 全部可选,写在 profile patch 的插件行上: ```yaml - id: session-guard name: "@po-et/dsh-session-guard" config: mode: enforce # 'enforce'(默认)拦下冲突步;'warn' 只告警不拦 heartbeatMs: 15000 # 持有锁的心跳刷新间隔 staleAfterMs: 90000 # 无法验证的属主静默多久算过期 # lockDir: /custom # 默认 $DSH_HOME/session-locks ``` ## 诚实边界 - 锁是**咨询性**的:只保护装了本插件的 dsh 进程,没装的进程不受约束(请在你运行的每个 profile 里都装上)。 - 只覆盖**活跃写入路径**(`agent/session-start`、`agent/pre-step`)。冷加载修复路径(在任何 step 之前提交合成中断收尾事件)发生在 dsh 内部,插件无法拦截——那一半只能等官方修。 - 锁文件在 `$DSH_HOME/session-locks`;若你在配置里把会话根目录改到了别处,锁仍按 home + 会话 id 定位。 - 已经发生的损坏本插件救不了——[dsh-session-rescue](https://github.com/po-et/dsh-session-rescue) 可以。 零运行时依赖。MIT。