DeepSeek Harness 权限预设 auto 死锁:sessionProjections 怎么修
如果你在 DeepSeek Harness(DSH)里用 /permission auto 换来过「少点确认」的爽感,大概率也见过这条报错:cannot get required service "sessionProjections" in inactive context。 它不是某个工具坏了,而是权限预设与 auto-review 在启动阶段互相等待:预设需要 auto-review 提供的放行入口,auto-review 又要等预设把投影发布出来。重启能好一阵,是因为下一次构造顺序偶尔不同;只要会话里还留着 durable 的 auto,它迟早会再撞上。
DeepSeek Harness 怎么确认这是权限死锁
一句话结论:报错文本里出现 inactive context,同时 permission 卡片显示启动失败或 auto-review 永久 pending,才是本文说的死锁;只报一次、重启后彻底消失的,是普通的构造顺序抖动。 三个判据一起看:
- 查启动日志,搜索
cannot restore preset "auto" without its active integration或pinInitialPermission;预期能看到构造期抛错。 - 打开
/permission并改一次预设;预期页面能打开,但权限盾牌不出现、改动不生效。 - 看插件列表里的
auto-review状态;预期长时间停在pending,而不是failed。
据讨论里的复现记录,这三条同时出现时,基本可以确定是构造期扫描与 autoAdmit 的环形依赖(#10233、#9882)。权限配置的基础操作可以先对照 权限审批配置。
DSH 环形死锁是怎么形成的
一句话结论:permission-presets 在构造器里扫描所有已载会话并尝试恢复预设,而 auto 预设依赖 auto-review 注册的 autoAdmit;auto-review 又要等 permissionPresets 服务可用才注册,双方都在等对方先完成。
代码路径可以对上两处:
permission-presets/src/index.ts:248-250在构造期调用pinInitialPermission,:428-436在拿不到 active integration 时抛错。auto-review的registerAuto依赖permissionPresets服务,服务未发布就不会执行。
抛错本身不是最致命的,致命的是它发生在「投影注册」之前:permissions 投影没有发布,sessionProjections 的读取方全部拿到 inactive context,后续工具调用自然全挂。
为什么重启有时能好、有时不能
- 如果重启时
auto-review先完成注册,构造期能拿到autoAdmit,死锁不触发。 - 如果会话里已经有 durable 的
auto,即使这次没触发,下一次恢复该会话仍可能把顺序打回死锁。 - 插件越多、并发初始化越多,顺序越不稳定,所以表现像「偶发」。
DeepSeek Harness 权限预设死锁的三种修法
一句话结论:只想马上能用就关 auto-review,只有个别会话中招就改会话头,要提交上游就改构造期扫描;三条不冲突,可以按顺序做。
修法一:先关掉 auto-review,让系统能启动
这是代价最小、见效最快的止血法,适合你现在连设置页都进不去的情况。 关闭后权限预设会退回固定模式,历史会话仍可打开。
- 打开
~/.dsh/profiles/<你的 profile>/cordis.patch.yml;预期能看到当前 profile 的 patch 列表。 - 找到
auto-review对应的行,把disabled设为true;没有该行就在 patch 里补一条同名禁用项,预期该行被明确禁用。 - 完全退出 DSH(不是关窗口),重新启动;预期启动日志不再出现
restore preset抛错。 - 进入设置,把仍带
auto的会话逐个改成default或ask;预期权限盾牌重新出现。 - 确认设置改动立即生效后,再决定是否重新启用 auto-review;预期重新启用后不会立刻回到 pending。
修法二:手工摘掉会话头里的 durable auto
如果只有个别会话触发,直接改会话头的预设字段比关插件更精准,但要先备份。 durable 预设写在会话元数据里,不在全局配置里。
- 退出 DSH,备份
~/.dsh/storages/整个目录;预期备份目录可以完整恢复。 - 在
storages下按修改时间找到报错会话的元数据文件,搜索"preset"或"auto";预期能定位到带 durable auto 的 header。 - 把该会话的预设字段改成
default,不要删除整个 header;预期文件仍是合法的会话元数据。 - 重启后打开该会话;预期不再报
cannot restore preset。 - 如果改完仍报错,说明还有第二个会话带同样字段,重复第 2 步;预期直到启动日志不再出现该抛错。
修法三:改代码,让构造期扫描可降级
这是唯一能根治的方向,核心是把「恢复预设失败」从抛错改成记录并降级,或把扫描从构造期挪到会话首次激活时。 讨论里给出的补丁形状是 pinInitialPermission(session, { reject }) 加一次二次 sweep。
- 在
permission-presets/src/index.ts的构造期扫描处,把pinInitialPermission的失败从throw改为logger.warn并标记该会话待修复;预期单个坏会话不再阻塞启动。 - 给
registerAuto增加一次幂等 sweep:注册完成后重新遍历待修复会话,补上autoAdmit;预期待修复会话状态归零。 - 在
:428-436的restore preset分支加一个「integration 未就绪」的专用错误码;预期它不会和真正的配置错误混在一起。 - 用带 durable auto 的会话做回归:启动、恢复、切预设、再重启;预期不再出现 pending。
- 补一条单测,模拟
auto-review晚于permission-presets初始化的顺序;预期测试能稳定复现并验证降级。
DSH 插件恢复后怎么验证与避坑
一句话结论:至少跑一次新建会话、一次历史会话恢复和两次重启,才能确认死锁没有复发。 验证步骤:
- 新建一个会话,执行一次会触发工具调用的请求;预期不再报
inactive context。 - 打开一个历史会话;预期权限盾牌存在,
/permission改动后立刻生效。 - 重启 DSH 两次;预期
auto-review两次都不再停在 pending。 - 重新启用 auto-review 后,先用一个低风险工具试一次;预期审查调用能完成,再扩大范围。
避坑要点:
- 不要用删除整个
~/.dsh的方式解决,那会连同会话历史、插件配置一起丢掉;先按修法二定位具体会话。 inactive context也可能是别的 fiber 卸载导致的;本文只覆盖「权限预设 + auto-review」这一种,关掉 auto-review 后仍复现就走sessionProjections的通用排查路径。- 修法三属于核心侧改动,升级后可能被覆盖;如果你只是 DSH插件 使用者,优先用前两种。
- 讨论里没有给出官方修复版本,0.2.1-rc.2 仍可复现;看到 release notes 提到 permission preset 恢复逻辑时再确认是否已修。
DeepSeek Harness 权限预设常见问题
Q:DeepSeek Harness 切到 /permission auto 报 inactive context,为什么? A:DeepSeek Harness 的 inactive context 是 permission-presets 与 auto-review 在构造期形成的环形等待,不是会话数据损坏。预设扫描遇到 durable auto 就抛错,permissions 投影无法发布,auto-review 又依赖该服务,于是永久 pending;临时规避是关闭 auto-review 或把预设改回固定值。
Q:DeepSeek Harness 启动报 2 entries did not activate,历史会话打不开怎么救? A:DeepSeek Harness 报 2 entries did not activate,说明持久化会话头带着 auto 预设,而当前进程里 autoAdmit 还没注册。先把 profile 里 auto-review 相关行禁用,让 permission-presets 完成构造,再用不依赖 auto 的会话进入设置,把旧会话改回 default 或 ask。
Q:DeepSeek Harness 的 auto-review 一直 pending,权限盾牌却消失,是什么关系? A:DeepSeek Harness 的 auto-review pending 与盾牌消失是同一个故障的两个观察面。盾牌消失说明 permissions 投影没有发布,pending 说明 auto-review 在等这个服务;两者都源于构造期抛错,不是两个独立 bug。
Q:升级 0.2.1-rc.2 后 DeepSeek Harness 新建会话都失败,必须删 ~/.dsh? A:DeepSeek Harness 新建会话失败不需要删整个 ~/.dsh。先确认失败的是会话级 durable auto 还是全局默认值:会话问题备份后改 header 预设字段,全局问题改 profile 的 permission 配置;只有无法定位具体会话时,才重命名 storages 做隔离验证。
常见问题
DeepSeek Harness 的 inactive context 是 permission-presets 与 auto-review 在构造期形成的环形等待,不是会话数据损坏。预设扫描遇到 durable auto 就抛错,permissions 投影无法发布,auto-review 又依赖该服务,于是永久 pending;临时规避是关闭 auto-review 或把预设改回固定值。
DeepSeek Harness 报 2 entries did not activate,说明持久化会话头带着 auto 预设,而当前进程里 autoAdmit 还没注册。先把 profile 里 auto-review 相关行禁用,让 permission-presets 完成构造,再用不依赖 auto 的会话进入设置,把旧会话改回 default 或 ask。
DeepSeek Harness 的 auto-review pending 与盾牌消失是同一个故障的两个观察面。盾牌消失说明 permissions 投影没有发布,pending 说明 auto-review 在等这个服务;两者都源于构造期抛错,不是两个独立 bug。
DeepSeek Harness 新建会话失败不需要删整个 ~/.dsh。先确认失败的是会话级 durable auto 还是全局默认值:会话问题备份后改 header 预设字段,全局问题改 profile 的 permission 配置;只有无法定位具体会话时,才重命名 storages 做隔离验证。
相关术语
- sessionProjections
- sessionProjections 是 DeepSeek Harness 中按会话维护的派生视图服务,permissions、usage 等投影都挂在它下面。它必须由活跃的 Cordis fiber 发布,读取已卸载 fiber 的 context 会抛 inactive context。— https://github.com/deepseek-ai/deepseek-harness/discussions/10233
- pinInitialPermission
- pinInitialPermission 是 permission-presets 在会话初始化时把预设固化到会话头的函数,目的是让恢复后的会话沿用原权限。它在构造期被调用时如果遇到 auto 这类需要外部集成的预设,会直接抛错而不是降级。— https://github.com/deepseek-ai/deepseek-harness/discussions/9882
- autoAdmit
- autoAdmit 是 auto-review 注册到权限系统里的自动放行入口,只有 auto-review 插件完成注册后才存在。permission-presets 在构造期读取它时通常还是 undefined,这正是环形死锁的起点。— https://github.com/deepseek-ai/deepseek-harness/discussions/10233
来源
- #10233 — 0.2.1-rc.2:permission-presets × auto-review 环形死锁导致 permissions 投影永久丢失· deepseek-ai(GitHub Discussions)
- #9882 — 恢复的会话带 durable auto 预设导致 permission-presets 构造期抛错· deepseek-ai(GitHub Discussions)
- DeepSeek Harness 官方仓库· deepseek-ai(GitHub)