DeepSeek Harness 工作区与任务列表:自动跑仓库 git hook 与 Clear 清不掉任务
DeepSeek Harness(DSH)有两个容易被忽略的行为缺陷,而且都属于「能力其实存在,只是产品路径没接上」:工作区变更跟踪会在回合开始自动执行 git 操作,而它只清理了环境变量注入的配置、没有屏蔽仓库配置文件里的钩子路径设置——于是仓库里配的本地钩子会在你毫不知情的情况下、以你的用户权限被执行(这属于安全面问题,值得优先处理);后台任务列表的 Clear 按钮其实只做本地隐藏**,后端早已具备移除已完成任务的能力却没有任何调用方,于是已完成的任务条目会在整个会话里残留(#9382、#9602)。
DeepSeek Harness 打开项目就自动跑了它的 git hook
一句话结论:工作区变更跟踪在回合开始会自动执行暂存操作,而它清理的只是通过环境变量注入的 git 配置,没有加上「把钩子路径指向空」这类命令行覆盖——于是仓库自身配置文件里的自定义钩子路径依然生效,仓库里的本地钩子被直接执行。 触发时你并没有要求任何 git 操作(#9382)。
DeepSeek Harness 为什么「清理环境变量」不够
这是本条最核心的一点:环境变量清理只影响「通过环境注入的配置」,而仓库的 .git/config 是文件配置,两者是不同的来源。所以要屏蔽钩子,必须在命令行上显式覆盖,例如把钩子路径指向空、并顺带关掉文件监听类配置(#9382)。
DeepSeek Harness 三步确认
- 确认仓库里配了自定义钩子路径:
git -C <你的仓库> config --get core.hooksPath
# 预期:有输出 —— 说明该仓库把钩子目录指向了自定义位置
(#9382)
- 给钩子加一条记录日志(记录时间、参数与父进程),然后开一个 DSH 会话并只发一条普通消息。如果钩子被调用而你没有做任何 git 操作,即为本条(#9382)。
- 注意触发面比想象广:讨论中给了触发矩阵,多个 git 子命令都会触发钩子,所以「我没执行 git」不是反证(#9382)。
DeepSeek Harness 处置与修法
- 临时规避:暂时移除或改名该仓库的钩子路径配置(排查完再恢复);或在这类仓库上先不要接入工作区(#9382)。
- 修法(一行形状):给这条自动化 git 调用加上两个命令行覆盖——把钩子路径指向空、并关掉文件监听类配置。注意仓库里其它自动化路径已经用了这个写法,说明它是既有约定,只是这条产品路径漏加(#9382)。
- 作用域要保清楚:这个覆盖只应作用于自动化触发的那些 git 调用,不能误伤用户主动执行的提交——所以不要把它写成全局配置(#9382)。
- 验证:在同一个仓库里重开会话发一条消息,预期钩子不再被调用;同时手动
git commit一次,预期钩子照常执行(#9382)。 - 可先兜的插件:讨论中提到有社区插件可按「环境变量被清空」这一标记选择是否拦截,属 fail-open 形态的临时防护(#9382)。
DeepSeek Harness Clear 清不掉任务:按钮只做了本地隐藏
一句话结论:Clear 只是客户端的本地隐藏(不发远端请求),而后端虽然早已实现「移除已完成任务」且语义正确(只接受终态),却没有任何生产调用方**;控制器也只暴露列出、跟随与终止,终止对终态直接返回「已经结束」而不做移除。** 症状是已结束的后台任务条目在整个会话里一直留着(#9602)。
DeepSeek Harness 先分清你遇到的是哪一层
这一步很重要,因为两层的问题性质不同(#9602):
DeepSeek Harness 三步确认与处置
- 确认判据:点击
Clear后条目在刷新后又出现(或仍在),说明它只是本地隐藏;另外确认该任务已经处于终态(#9602)。 - 临时应对:重启会话或新开会话,让列表重新初始化(代价是会话上下文也一起变)(#9602)。
- 修法(讨论中给出,量级很小):在任务控制器上加一个移除(dismiss)入口,并把前端的本地隐藏改成真实调用(约十行)(#9602)。
- 语义要保清楚:移除只应作用于终态任务;对仍在运行的任务应当保持「终止」的语义,不要混为一谈(#9602)。
- 验证:修完后跑一个短任务,结束后点清理,预期刷新后条目不再出现(#9602)。
DSH插件 排查注意事项
这两条的共同排查思路是:先判断「能力有没有」,再判断「路径有没有接上」——因为两条的根因都不是能力缺失,而是接线漏了一处。 六条要点:
- 「我没执行 git」不是反证:多个 git 子命令都会触发钩子(#9382)。
- 环境变量清理治不了文件配置:这是钩子那条的核心(#9382)。
- 修钩子那条要注意作用域:只屏蔽自动化调用,别动用户主动提交(#9382)。
- 仓库里已有该写法的先例:找不到落点时先看看同项目其它自动化路径怎么写的(#9382)。
- 任务列表先分清「观感」与「能力」,否则会在展示层反复调(#9602)。
- 修复状态如实:两条在讨论所指版本(
0.2.0-rc.2前后)里都未修;钩子那条有一行级修法与社区兜底插件(均未合入),任务那条的接口补充仍在提案阶段。
工作区类的行为问题排查时,很容易怀疑「是不是某个插件改了 git 行为」。若想把插件这一层先排掉,与其在各处手敲命令,不如用 DSH Plugin Hub 这类可视化插件市场:已安装列表、装卸历史与系统日志集中在一个面板里。

常见问题
DeepSeek Harness 在你没做任何 git 操作时自动执行了仓库里的 git 钩子,是因为工作区变更跟踪会在回合开始时自动执行一次暂存操作,而它清理的只是通过环境变量注入的配置、并没有屏蔽仓库自身配置文件里的钩子路径设置,于是仓库里配的本地钩子会被调用,且以你的用户权限运行。可行的规避是暂时移除或改名那个钩子路径配置;修法是在这条自动化路径上显式禁用钩子,但要保持用户主动执行 git 提交时的行为不变。
判断是不是 DeepSeek Harness 触发的钩子,先看时序:钩子是否在「回合开始、你还没有提出任何 git 要求」时被调用;再看调用者——可以先给钩子加一行记录当前进程与参数的日志,对照 DSH 会话的时间点。讨论中给出的触发矩阵显示多个 git 子命令都会触发,因此「我没执行 git」并不构成反证。
DeepSeek Harness 后台任务列表的 Clear 按钮没坏,它只是做了本地隐藏。后端其实已经有「移除已完成任务」的能力且语义正确,但没有任何调用方,控制器也只暴露了列出、跟随与终止,而终止对已结束任务会直接返回「已经结束」而不做移除,所以条目会一直留着。修法方向是给控制器加一个移除入口并把本地隐藏改成真实调用。
DeepSeek Harness 后台任务列表的清理值得单独关注,因为它有两层问题:一层是观感——清理粒度与折叠方式不理想;另一层是能力缺失——没有单条移除的入口,于是已经完成的任务在会话内无法真正消失。前者影响体验,后者影响可用性,排查时要先区分你遇到的是哪一层。
这两个 DeepSeek Harness 问题的共同点是:都是「能力其实存在,但产品路径没接上」。钩子屏蔽的写法在仓库其它地方已经用过、只是这条自动化路径漏加;移除任务的能力后端已实现、只是没有调用方。所以两条的修法都很小,问题在于先把「哪一处漏了」找出来。
相关术语
- core.hooksPath
- core.hooksPath 是 git 配置项,用于把钩子目录指向自定义位置。它既可通过命令行参数临时覆盖,也可写在仓库配置文件里;只清理环境变量注入的配置并不能屏蔽仓库文件里的这项设置。— https://github.com/deepseek-ai/deepseek-harness/discussions/9382
- workspace-changes
- workspace-changes 是 DeepSeek Harness 里用于跟踪与展示工作区文件变更的能力,它会在回合开始等时机自动执行 git 操作以获取当前变更集。这些自动操作会读取仓库自身配置,因此在带自定义钩子的仓库里需要额外屏蔽。— https://github.com/deepseek-ai/deepseek-harness/discussions/9382
- job-controller
- job-controller 是 DeepSeek Harness 里管理后台任务的控制器,当前对外暴露列出、跟随与终止三类操作。它没有移除已完成任务的入口,因此前端只能做本地隐藏。— https://github.com/deepseek-ai/deepseek-harness/discussions/9602
- dismiss(移除任务)
- dismiss 指把已经处于终态的后台任务从任务列表中真正移除的操作,与「终止运行中的任务」不同。当前实现里后端具备该能力但没有对外暴露,因此界面上的清理按钮只能做本地隐藏。— https://github.com/deepseek-ai/deepseek-harness/discussions/9602
来源
- #9382 — Security: workspace-changes runs repository-local Git hooks· deepseek-ai(GitHub Discussions)
- #9602 — 后台任务列表的 Clear 无法消除已结束的 job,条目整会话残留· deepseek-ai(GitHub Discussions)