让 AI 真正完成开发任务:Windows 上的 DSH Headless、Git Worktree 与自动编译实践

让 AI 真正完成开发任务:Windows 上的 DSH Headless、Git Worktree 与自动编译实践

AI-CODING 实践系列(二)

关键词:AI 自动编码、DeepSeek Harness、Git Worktree、Python、Scheduler、MSBuild、C++、Windows

前言

在上一篇文章中,我介绍了如何通过 DeepSeek Harness(DSH)和飞书机器人建立一个远程开发入口。

但能通过手机与 AI 讨论代码,并不意味着拥有一套真正的自动开发系统。

要让 AI 从聊天走向实际开发,还需要解决几个工程问题:

  • 如何让 AI 自动进入正确的项目?
  • 如何避免多个任务修改同一个工作目录?
  • 如何自动编译 AI 生成的 C++ 代码?
  • 如何知道任务是成功了,还是只得到一个看起来合理的回答?
  • 如何取消异常任务,避免后台残留进程?
  • 如何在程序重启后恢复任务状态?

这些问题最终通过一套轻量的 Python Runner + Scheduler 得到了解决。

本文记录这部分工程实现和真实验证结果。

一、先明确目标:不是让 AI 写代码,而是让它完成任务

AI 编码工具已经能够根据自然语言生成和修改代码。

但对于无人值守开发,我希望最终得到的不只是代码,还包括:

  1. 实际的文件修改。
  2. 可复现的构建结果。
  3. 可检查的测试结果。
  4. 可追踪的执行记录。
  5. 与原始开发分支隔离的修改。
  6. 明确的成功、失败或取消状态。

因此,我把一次自动开发定义为:

接收开发任务
    ↓
创建独立工作区
    ↓
启动 AI 编码 Agent
    ↓
检查代码修改
    ↓
执行 MSBuild
    ↓
运行验证
    ↓
保存结果与日志

这才是可以交给后台系统调度的完整任务单元。

二、为什么使用 Git Worktree?

如果直接让 AI 修改原始工作目录,风险比较明显。

一旦任务中断、修改失败或者同时存在多个任务,就可能影响开发者正在使用的代码。

为此,我使用 Git Worktree 为每个任务创建独立的工作目录。

例如:

repositories/
└── demo-project/          # 原始 Git 仓库

workspaces/
├── task-001/              # 任务 1
├── task-002/              # 任务 2
└── task-003/              # 任务 3

每个任务拥有自己的分支和工作目录。

一个典型的操作是:

git worktree add -b ai/task-001 ../workspaces/task-001 master

这样 AI 可以在独立目录内修改代码,而不需要切换原始仓库的当前分支。

在实际验证中,Runner 自动创建了独立 Worktree 和任务分支,DSH Headless 只修改了测试任务中的目标源文件,原仓库 HEAD 和工作状态在执行前后保持一致。

这里需要特别说明:

Git Worktree 提供的是版本管理层面的隔离,而不是完整的操作系统安全沙箱。

它能有效隔离不同任务的 Git 工作状态,但不能单独限制进程读取其他目录或访问网络。

三、DSH Headless:将编码 Agent 变成可调度程序

交互式 Agent 适合讨论需求,而自动化系统更需要可独立启动、执行和退出的进程。

DSH Headless 正好可以承担这个角色。

它能够通过命令行接收任务,并将执行过程输出为结构化事件。

在实际工程中,我主要利用以下能力:

  • 为任务指定独立工作目录。
  • 通过 Headless Profile 调用已经授权的模型。
  • 使用 JSON 事件流记录运行过程。
  • 获取模型 Session ID。
  • 通过进程退出码判断执行状态。
  • 在任务完成后结束进程。

Runner 不依赖用户一直打开 DSH Web 页面。

它会根据任务配置启动一个独立 Headless 进程,完成当前任务后退出。

这也意味着,飞书聊天中的 Session 与实际编码 Session 可以完全分离。

前者保存讨论上下文,后者专门负责某一次开发任务。

四、Runner v0.1:最小自动编码执行器

第一阶段实现了一个 Python Runner。

核心模块包括:

模块 主要职责
models.py 解析和校验任务规格
gitops.py 创建、检查和清理 Worktree
dsh.py 启动 DSH Headless,解析事件
build.py 执行受信任的构建与验证命令
process.py 管理子进程、超时和终止
orchestrator.py 串联完整执行流程

Runner 提供统一的 CLI:

python -m runner run --spec task.json --task-id task-001

这里的 task.json 不只是自然语言需求,还包含经过校验的仓库、构建、超时和允许修改路径等配置。

一个重要原则是:

模型负责修改源代码,不负责随意决定系统应该执行什么构建命令。

构建命令来自受信任配置。

这可以减少 AI 因为理解错误而选择错误工具链、构建路径或系统命令的风险。

当然,受信任的构建命令并不意味着构建过程本身完全安全,因为参与编译的源码可能由 Agent 修改。

五、Windows 进程管理比想象中重要

自动化 Agent 可能启动多个子进程。

例如:

Python Runner
    └── Node.js / DSH
          └── PowerShell
                └── 其他开发工具

如果只终止最外层进程,内部启动的子进程可能继续存在。

这对于长期运行的开发机尤其麻烦。

Runner 使用 Windows Job Object 管理任务进程树,并提供 taskkill /T /F 作为经过身份校验后的回退方式。

这里有一个非常重要的约束:

不能通过结束所有 **node.exe** 进程来清理任务。

因为长期运行的 DSH Web Host 本身也依赖 Node.js。

错误的清理操作可能把整个远程开发入口一起关闭。

因此,执行器只针对当前任务所属的进程树进行清理。

测试中验证了任务超时后的进程树终止,真实 Runner 端到端执行结束后也未发现新增的残留 DSH Headless 进程。

六、真实 C++ 编译验证

自动编码的关键验收,不应该是 AI 说“代码已经修改完成”,而应该是编译和测试确实通过。

本次验证使用 Windows 11、Visual Studio 2026、MSVC 和 Windows SDK。

测试任务要求 DSH Headless 创建一个简单的 C++ 加法程序,并通过 MSBuild 编译。

核心逻辑类似:

#include <iostream>

int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(2, 3);

    if (result == 5) {
        std::cout << result << std::endl;
        return 0;
    }

    return 1;
}

执行结果:

  • DSH Headless 成功生成源代码。
  • MSBuild 成功编译。
  • 生成的 EXE 正常运行。
  • 程序输出 5。
  • 任务退出码为 0。
  • 原始仓库没有被修改。
  • 结果与日志成功保存。

最终 Runner v0.1 的真实端到端测试耗时约 17 秒,10 项自动化测试全部通过。

当然,这只是一个简单 C++ 工程的验证,不代表复杂 CAD 插件工程也能在相同时间内完成。

它证明的是底层执行链路可行,而不是 AI 对复杂工程的开发质量已经得到充分验证。

七、为什么还需要 Scheduler?

Runner 解决的是如何执行一个任务。

但真正从飞书远程发起任务,还需要处理多个任务之间的关系。

例如:

  • 用户连续提交两个需求。
  • 第一个任务仍在执行。
  • 用户希望取消第二个任务。
  • 开发机突然重启。
  • 聊天消息重复投递。
  • 某个任务执行失败,需要查看历史记录。

如果把这些逻辑全部交给 Agent 自己处理,很容易产生状态混乱。

因此,我增加了独立的 Python Scheduler。

它只负责几个确定性的功能:

任务提交
    ↓
SQLite 持久化
    ↓
FIFO 队列
    ↓
单 Worker
    ↓
调用 Runner
    ↓
保存结果

为什么只采用单 Worker?

因为当前使用的是一台资源有限的 Windows 开发机,而且 C++ 编译本身会消耗较多 CPU、内存和磁盘资源。

在这种环境下,与其提前开发复杂的并发调度,不如先保证任务依次完成。

八、Scheduler v0.2 的实现

Scheduler 使用 SQLite 保存任务状态、执行记录和任务事件。

任务状态包括:

queued
running
succeeded
failed
cancelled
interrupted

一次正常执行的状态变化为:

queued → running → succeeded
                 → failed
                 → cancelled

它还提供了几个基础能力:

FIFO 排队

按照数据库中的任务序号依次执行,防止任务插队。

幂等提交

相同幂等键重复提交时,返回已有任务,避免重复运行。

单实例运行

通过 Windows 文件锁和 SQLite 原子领取机制,防止多个 Worker 重复执行同一个任务。

任务取消

可以取消尚未执行的任务,也可以向正在运行的 Runner 发送取消请求。

异常恢复

程序重启后,排队中的任务继续保留;原先处于运行状态的任务标记为 interrupted,默认不自动重复执行,避免出现未知状态下的二次修改。

清理预览

能够检查哪些历史 Worktree 符合清理条件,但不自动删除正在运行或身份不明确的工作区。

这些能力并不复杂,但对无人值守系统的可靠性非常重要。

九、Scheduler 的真实验证结果

Scheduler v0.2 完成后,使用同一个 C++ 测试仓库提交了两个任务。

每个任务均通过 Scheduler 调用真实的 Runner、DSH Headless 和 MSBuild。

验证结果如下:

验证项目 结果
Scheduler 自动化测试 18/18 通过
Runner 回归测试 11/11 通过
管理模块 Python 回归测试 142 项通过
管理插件 Node 测试 24 项通过
真实编码任务 2 个,全部成功
执行顺序 严格串行
独立 Worktree 通过
独立 DSH Session 通过
MSBuild 编译 两次成功
EXE 运行验证 两次通过

两次真实任务的 Runner 执行时间分别约为 21 秒和 21 秒。

需要注意,本轮真实验证使用了两次独立的单任务 Worker 进程,证明了串行领取和执行链路有效。长期常驻 Worker 的稳定性、真实长任务取消和异常重启恢复,还需要进一步验证。

这也是开发报告中必须坚持的一点:

模拟测试通过、真实任务通过和生产长期运行稳定,是三个不同层级的结论。

十、最不能忽视的问题:安全边界

在自动编码系统中,安全不仅仅是防止 Agent 修改错误文件。

更大的风险来自自动执行 AI 生成的代码。

本次验证发现:

  • DSH 的 workspace-write 模式能够拒绝部分工作区外写入。
  • 工作区外文件读取并未受到同等限制。
  • Git Worktree 本身不提供操作系统隔离。
  • MSBuild 构建和生成的 EXE 运行不在 DSH 沙箱内。
  • 路径白名单检查主要发生在代码修改之后。

尤其需要注意:如果自动编译的源代码包含恶意行为,最终生成的程序可能以 Runner 用户权限运行。

因此,当前版本仍然属于受控环境中的自动化开发原型。

后续接入真实项目时,需要考虑:

  1. 使用独立的低权限执行账号。
  2. 限制构建进程可以访问的目录和凭据。
  3. 明确网络访问策略。
  4. 限制 CPU、内存、磁盘及执行时间。
  5. 在必要时使用独立虚拟机执行不可信构建。
  6. 对自动修改的代码保留人工审核。

这些问题比一味追求更多 Agent 并行更重要。

十一、从自动编码到实际开发助手

随着 Runner 和 Scheduler 完成,系统的三个核心部分逐渐清晰:

Control
    管理项目、话题和权限

Scheduler
    管理任务、队列与执行状态

Runner
    管理 Worktree、Agent、编译和验证

它们分别解决不同的问题。

而飞书和 DSH Host 负责将自然语言需求转化为可以提交的任务。

目前系统已具备通过飞书驱动开发的能力,形成了从远程交互到本地自动执行的初步闭环。

但这只是阶段性成果。

接下来真正重要的,不是继续增加架构层次,而是把它用于实际开发项目。

例如使用现有 C++ 工程完成一次功能修改、缺陷修复或构建问题排查,并观察它在需求理解、代码质量和编译修复方面的表现。

十二、阶段性反思

这次实践最大的收获,并不是写出了一套 Python 任务调度程序。

而是逐渐认识到:AI 自动开发系统的难点,不只是模型能否生成代码,更在于如何将不确定的模型行为纳入可靠的软件工程流程。

在这个过程中,几个设计原则逐渐明确:

  • 对话 Agent 和编码 Agent 可以分离。
  • 每个任务应拥有独立的工作区和执行上下文。
  • 任务状态应该由确定性程序管理。
  • 构建与测试结果比模型的文字总结更可信。
  • 自动化系统必须支持失败、取消和恢复。
  • 安全隔离不能仅依赖 Agent 的提示词或沙箱声明。
  • 不应为了未来可能出现的需求,过早开发复杂架构。

当前系统已经完成了第一阶段的主要目标。

下一阶段,我更希望它真正参与日常开发,而不是继续围绕基础设施进行迭代。

毕竟,衡量 AI 开发助手价值的最终标准,不是它拥有多少 Agent、多少插件或多少架构模块,而是:

它是否能够可靠地完成实际开发任务,并真正减少开发者的工作量。


本文中的性能和测试数据来自特定 Windows 测试环境,不构成其他机器或复杂业务工程的性能保证。阶段性验证结果不代表已经达到生产环境的安全性与可靠性要求。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注