DeepSeek Harness 源码开发与构建:submodule 装不上、worktree 失败与 fork 定时任务
从源码参与 DeepSeek Harness(DSH)开发时,有三个典型的「环境差异」问题会挡在第一步:把仓库作为子模块检出后 pnpm install 必然失败(安装脚本要启用的工作树配置键与子模块的既有配置冲突);create_worktree 在旧版 git** 上百分之百失败(它无条件前置了一个新版本才有的选项);以及fork 仓库继承了定时工作流、每天因缺少上游密钥而报错。** 这三条都不是产品功能缺陷,而是「本地/持续集成环境的差异没被覆盖」——所以排查思路也很一致:先确认你是哪种检出方式、哪个 git 版本、哪个仓库,再对照已知限制(#9856、#9676、#9499)。
DeepSeek Harness 子模块检出后安装必失败
一句话结论:作为子模块检出时,git 会把工作树路径写在共享配置里(这是标准行为),而安装脚本需要启用工作树范围的钩子路径配置,遇到这个已存在的键就直接抛错;脚本里没有子模块分支,报错里给的「把它移走」也不可操作。 报错形态是「无法启用某扩展配置因为它在共享配置里」(#9856)。
DeepSeek Harness 子模块三步处置
- 确认判据:只有作为子模块检出时复现;普通克隆仓库时安装正常(#9856)。
- 规避(已验证):以持续集成模式运行安装,让脚本走短路分支:
CI=true pnpm install
# 预期:安装成功;并且之后运行脚本时不会再重复执行该安装校验
讨论中确认这条路径会短路检查,且安装完成后依赖校验也不会再跑(#9856)。
- 修法方向:脚本里加子模块检测并在该情形下改用局部钩子路径配置;也可以用专门的环境变量覆盖(讨论中确认现有变量不覆盖这一处检查,所以需要新增或调整)(#9856)。
- 验证:在子模块检出里重跑
CI=true pnpm install,预期无报错且后续开发命令可正常执行(#9856)。
DeepSeek Harness create_worktree 在旧版 git 上失败
一句话结论:该能力把 --no-lazy-fetch 无条件前置到每条 git 命令上,而这个选项是较新版本才加入工作树子命令的——所以在旧版 git 上第一步就报「未知选项」。 这条已在 dsh-v0.2.1-alpha.3 修复(社区回复确认)(#9676)。
DeepSeek Harness create_worktree 三步处置
DeepSeek Harness fork 后每天收到定时任务失败
一句话结论:定时触发的判定条件写得过宽(只排除了拉取请求事件),于是定时事件在 fork 仓库里也照常运行;而它需要上游仓库的密钥,fork 里没有,就在预检环节硬失败。 症状是 fork 之后每天收到一次工作流失败通知、并消耗配额(#9499)。
DeepSeek Harness fork 定时任务三步处置
- 确认判据:通知来自 nightly 类定时工作流;错误发生在预检阶段、原因是缺少密钥;只在 fork 仓库出现,上游仓库正常(#9499)。
- 修法(推荐,对上游友好):在既有判定条件之前追加一个仓库守卫(要求仓库等于上游仓库),让定时触发在 fork 里直接跳过。job 级跳过会被记为成功,不会出现红叉——这一点很关键,能避免「修完反而更显眼」(#9499)。
- 只解决自己的做法:在自己的 fork 里禁用或删除该工作流文件(#9499)。
- 注意一个易错点:讨论里提醒仓库名的字面量有不同记录形式,改守卫前建议先用一次性手动触发打印出实际仓库名,确认拼写(#9499)。
- 验证:改完后观察一个夜间周期,预期不再收到失败通知(#9499)。
DSH插件 排查注意事项
这三条全部属于「环境差异」,所以第一步永远是确认环境:检出方式 / git 版本 / 仓库归属。 七条要点:
- 「只有子模块复现」是第一条判据(#9856)。
CI=true那条规避已验证,且不会重复触发校验(#9856)。- 报错里的「把它移走」不可操作:不要照着做,改用环境变量或补丁(#9856)。
- 「未知选项」优先怀疑版本而不是参数(#9676)。
- 该条已修:
dsh-v0.2.1-alpha.3起可用,别继续在手写绕过(#9676)。 - fork 定时任务要「加守卫」而不是「关掉上游」:改的是条件,不是别人的工作流(#9499)。
- 修复状态如实:子模块那条未修(只有已验证规避);
create_worktree那条已在0.2.1-alpha.3修复;fork 定时任务那条是上游工作流需要改条件(属仓库配置而非产品代码)。
源码开发与构建类问题往往要连着「依赖与插件」一起看。如果你在本地搭了多个 profile 做验证,与其在各处手敲命令比对,不如用 DSH Plugin Hub 这类可视化插件市场:已安装列表带来源与版本、装卸历史与系统日志集中在一个面板里。

常见问题
DeepSeek Harness 在子模块检出后 pnpm install 必失败,根因是子模块的 git 工作树路径由父仓库写在共享配置里,而安装脚本需要在工作树范围内设置钩子路径,遇到这个已存在的配置键就直接抛错。已验证的规避是在安装时把持续集成环境变量设为真(例如以 CI=true 前缀运行安装),脚本会因此走短路分支、安装成功后也不会重复执行校验。
DeepSeek Harness 的 create_worktree 报「未知选项 --no-lazy-fetch」不是参数写错,而是本机 git 版本太旧。该选项是在较新的 git 里才加入工作树子命令的,而工具把它无条件前置到每条 git 命令上,所以在旧版 git 上第一步就失败。可行做法是升级 git 到该选项被支持的版本;如果你在维护这个工具,修法是先探测版本、仅在满足条件时才下发该参数。
DeepSeek Harness 的 fork 仓库每天收到一次工作流失败通知,是因为定时触发的判定条件写得不对,定时事件也被当成满足条件,于是夜间任务在 fork 仓库里照常运行。而它需要上游仓库的密钥,fork 里没有,就在预检环节硬失败。修法是在既有条件前再补一个「仓库必须等于上游仓库」的守卫;job 级跳过会被记为成功,不会出现红叉。
这三个 DeepSeek Harness 源码开发问题的共同点是都属于「本地/持续集成环境的差异」:子模块与普通检出的 git 配置不同、旧版 git 不支持新选项、fork 仓库缺少上游密钥。所以排查时的共同思路是先确认「我这里是哪种检出方式、哪个 git 版本、哪个仓库」,再对照已知限制。
在 fork 里避免 DeepSeek Harness 继承来的定时任务消耗配额有两种做法。一是按讨论所述补上仓库守卫,让定时触发在非上游仓库直接跳过;二是在自己的 fork 里禁用该工作流(在界面里关掉或删掉该工作流文件)。注意第一种做法对上游维护者友好、第二种只解决你自己的问题。
相关术语
- git submodule 的 core.worktree
- core.worktree 是 git 用来记录某个工作树路径的配置键。把仓库作为子模块检出时,git 会把该模块的工作树路径写进共享配置,这是版本控制系统的标准行为;安装脚本若需要启用工作树范围内的配置键,就会因为这个已存在的键而失败。— https://github.com/deepseek-ai/deepseek-harness/discussions/9856
- create_worktree
- create_worktree 是 DeepSeek Harness 提供的创建独立工作树检出的能力,用于在不影响当前工作区的前提下得到一个干净的代码副本。它通过调用 git 的工作树子命令实现,因此受本机 git 版本能力限制。— https://github.com/deepseek-ai/deepseek-harness/discussions/9676
- --no-lazy-fetch
- --no-lazy-fetch 是 git 工作树子命令在较新版本里加入的选项,用于禁用惰性拉取。它不在旧版本的参数表里,因此被无条件使用时旧版 git 会直接报未知选项。— https://github.com/deepseek-ai/deepseek-harness/discussions/9676
- 定时触发(schedule)
- 定时触发是持续集成里按计划时间运行工作流的事件类型。判定条件里若把非拉取请求事件都视为允许,则定时事件在 fork 仓库中也会执行,从而暴露「缺少上游密钥」这类只在 fork 存在的问题。— https://github.com/deepseek-ai/deepseek-harness/discussions/9499
来源
- #9856 — pnpm install fails in submodule checkouts: install-lefthook cannot enable extensions.worktreeConfig· deepseek-ai(GitHub Discussions)
- #9676 — [Bug] create_worktree 在 git < 2.42 的机器上完全不可用· deepseek-ai(GitHub Discussions)
- #9499 — [Bug] e2e.yml 定时任务在 Fork 仓库中触发并因缺少 Secret 报错· deepseek-ai(GitHub Discussions)