我想建的软件工厂:从需求到可验证交付
软件工厂不只是让智能体更快地写代码,而是把请求转化为可验证、可交接、可恢复的变更:本文梳理工单与执行的区别、持久证据、风险分级、独立审查和人工授权,讨论重复事件、执行中断与定向返工,并提出一个先测试失败时能否停止、再衡量真实交付成本的小规模试点方案,明确区分尚待检验的设计与已经验证的能力。
语音摘要:使用本地语音合成生成的中文简要讲解。
在之前的一人公司设计里,我把问题归结为协调:客户反馈、产品决策、代码、运行故障和下一步工作,最终都要回到同一个人的注意力里。
软件工厂是其中更具体的一段:一个已经值得做的问题,怎样变成可以检查、可以接手、必要时可以撤回的软件变更?
我的起点很实际。让一个 coding agent 改代码并不难。难的是让下一次执行知道上一次做到哪里,让审查者看到原始需求而不只是实现者的总结,让失败停在正确的位置,而不是靠更多提示词把流程往前推。
这篇文章整理的是我正在推敲的设计。它还不是一个经过端到端验证、可以无人值守运行的交付平台;文中的风险分级、返工上限和验收规则,都需要通过小规模试点检验。
软件工厂可以从一个很小的循环开始
Matt Pocock 的 Dictionary of AI Coding 用一个朴素的定义描述 software factory:通过触发事件自动启动 agent 会话。
按我的理解,一个定时任务,每次处理一种小型维护工作,留下一个等待人工审查的 PR,就已经符合这个定义。工厂不要求人退出所有决策。
这与 dark factory 有区别。按照同一份词典,后者指的是某个代码范围内,人不再阅读工厂生成的变更。依此理解,晚上无人看守地执行、早上由人审 PR,仍然是有人审查的软件工厂。
我目前想验证的是前一种模式。自动化负责准备和执行一部分工作,人保留产品选择、关键授权和发布责任。
先把一次请求和一次执行分开
设计里最容易混淆的是“任务”。它可能指一张工单,也可能指实现、审查这样的工作类型,还可能指某个 agent 正在进行的一次尝试。
下面是我对 Matt Pocock 软件工厂术语草案的改编,用于表达自己的交付约束,不是对原词表的逐项引用。
- 工单(work item / ticket):一次具体请求,保留问题来源、目标和验收条件。
- Task:可重复使用的工作类型,例如调查、实现、审查和返工。
- Run:执行某个 Task 的一次尝试,有明确的开始和结束。
- Trigger:启动 Run 的事件,例如工单被确认 ready、审查失败或人工补全信息。
- Runner:承载执行的环境,可以是本地进程、工作节点或可丢弃的云机器。
因此,一张工单可以经历调查、实现、审查和返工等多个 Run。它的持久状态不应该只存在于其中某次聊天里。
需要人回答问题时,也不必让一个 Run 一直等待。它应该记录问题和已有证据,结束执行,把工单停在“待澄清”或“待决策”。人工更新后,新的事件再启动下一次 Run。
这使恢复不必依赖某个会话仍然活着。
控制平面协调工作,事实留在原来的系统
我不打算先建一个包办所有事情的新平台。
Git 已经能保存代码历史,CI 能记录检查结果,工单系统能承载需求和责任归属,可观测性系统能报告运行问题。重新复制这些数据,很容易得到几份互相矛盾的“最新状态”。
在这个设计里,Hermes 是协调和审批入口,连接已有系统:
1
2
3
4
5
6
7
8
9
10
11
12
13
问题来源 / 客户反馈 / 运行信号
↓
工单:请求、范围、验收条件
↓
控制平面:路由、权限、预算
↓
隔离执行 → 候选代码
↓
自动检查 → 独立审查
↓
人的决策与发布授权
↓
正常发布流程 → 结果验证
工单负责说明要解决什么;Git 负责说明代码是什么;CI 负责说明某个版本跑过哪些检查。Company OS 保存经过审阅的设计和决策,个人知识系统则保持自己的隐私边界。
控制平面记录这些对象的关联与执行历史,但不替它们宣布事实。一个 agent 说“测试通过了”,仍然需要对应的命令、退出状态和结果;说“已经发布”,也需要发布系统和运行环境的证据。
只有当现有系统之间确实缺少某项能力时,才值得增加新的组件。
交接的是证据,不只是一段总结
我希望一张工单能串起下面这些问题:
1
2
3
4
5
6
7
request:为什么做?要达到什么结果?
scope:允许改什么?明确不做什么?
plan:怎样实现、检查和恢复?
decision:有哪些重要取舍,由谁决定?
change:实际改了什么,执行结果是什么?
audit:这个候选版本是否满足原请求?
debt:哪些剩余风险被明确接受?
这不意味着每次修改都要创建七个文件。小型文档变更可以把请求留在工单里,把变更和检查留在 PR 里。涉及接口、数据语义或重要业务规则时,才需要更完整的记录。
这些记录应该通过稳定工单 ID 和候选 commit SHA 关联,而不是把同一段描述复制到多个地方。
尤其是审查意见,必须说明它针对哪个版本。审查通过后又改了代码,旧意见就不能直接当作新候选的通行证。试点阶段,我倾向于每个新 SHA 都重新审查;将来是否允许对内容完全相同的 rebase 沿用结论,也应由明确的验证规则决定。
失败结果同样需要保留。最后一版测试通过,不应抹掉此前的失败、原因和修正过程。
风险决定审查强度,而不是决定用哪个“更聪明”的模型
我把三个决定分开处理:风险有多高、谁来执行、谁有权验收。
模型名称只能影响执行者选择。它不能扩大权限,也不能替代验收。
当前设计用四档风险组织检查:
- L0:纯文档或格式变更,确认范围、链接和格式,不涉及敏感政策或可执行行为。
- L1:局部、可逆的代码变更,需要验收条件对应的测试,以及未参与实现的独立审查 Run。
- L2:跨组件、接口、数据语义或有实质影响的依赖与配置变更,需要影响分析、更广的回归证据和恢复方案;产品或数据契约取舍交给人决定。
- L3:安全、权限、隐私、生产或客户数据,以及破坏性或难以逆转的操作,需要明确的人类授权、相应责任人审查和操作后的读回验证。
工作类型提供默认清单,风险标记只能提高要求。“chore”不是低风险证明,“bug fix”也不能掩盖认证逻辑的变化。一般风险不明时至少按 L2 处理,数据分类不明或触及生产则按 L3 处理。
分级也不只发生在入口。实现中发现要扩大范围、增加依赖、修改测试预期、跳过测试、更新快照或放宽超时,都应该提出范围问题并重新评估,而不是由实现者为了完成任务自行决定。
工厂本身的控制规则也属于被保护的代码。修改触发器、审查规则或权限边界,至少按 L2 对待;削弱关键制动措施时按 L3 处理。
独立审查需要一个明确的候选对象
独立审查不能只是让模型再读一遍自己的总结。
我希望审查者拿到原始请求、验收条件、base SHA、candidate SHA、完整 diff 和实际检查结果。审查 Run 不参与实现,也不能一边修代码一边批准自己。
更换一个模型不自动产生独立性。审查者如果只看到实现者筛选过的描述,仍可能继承同一套错误假设。
同样,流程界面里存在 review 状态,并不证明审查是硬门槛。需要验证状态转换和权限控制,确认执行者不能绕过必需审查直接宣布完成。Hermes 的 Kanban 文档和 worker lanes 文档描述了卡片、运行记录、交接和完成契约等机制,但具体配置与执行语义仍需在试点版本上检查。
代码工作区的隔离也要说清楚。Git worktree 可以避免两个执行者把文件修改混在一起,却不限制进程读取宿主机文件、凭据或访问网络。需要安全沙箱时,必须另外设置操作系统层面的文件、网络、凭据和资源约束。
人的批准也必须是一个可以核验的事件,来自自动化不能冒充的身份。由 agent 自己填一个 approved: true 字段,不能算人工授权。试点中,L2/L3 变更全部由人审阅,较低风险变更仍做抽查;其中 L3 的恢复或回滚路径也需要实际测试。
返工应该回到能解决问题的那一步
一个流程失败后,最省事的实现往往是重新启动整个 agent。这样做容易反复调查已经知道的事实,也可能把权限故障误当成代码问题。
我希望每条反馈至少包含:问题类型、期望与实际、证据、严重程度、负责人和下一步。
例如,缺少验收条件应交回需求负责人;产品语义有冲突应交回决策人;测试失败应把最小复现、失败命令和结果交给实现者。外部服务不可用则暂停并记录恢复条件,不应靠继续改代码来消耗重试。
对于代码审查发现的问题,最短路径通常是:
1
2
3
4
5
实现 → 检查 → 审查
↓ 发现缺口
定向返工
↓
新候选 → 重新检查与审查
试点暂定每条触发链最多连续进行两次自动返工,然后交给人重新判断范围或方案。两次只是一个待测的运行约束,不是普遍最优值。基础设施重试计数,也不能默认等同于审查返工计数。
未满足的验收条件不能被改名为“技术债”后关闭。技术债只容纳经过明确接受、有负责人和复查条件的剩余风险。
触发与恢复要按会重复、会中断来设计
每增加一个触发源,都要回答几个具体问题:
谁启动执行?它可以读写哪些系统?结束后触发什么?人在哪一步重新进入?重复事件如何避免创建重复工作?
例如,外部事件 ID 可以用于创建工单或卡片时的幂等键,但这不等于所有后续操作都已经幂等。创建分支、提交 PR、写入外部记录,都需要自己的去重和读回规则。
Runner 中断时,接手者至少要能从持久记录找到原始请求、当前候选版本、已经完成的外部操作、已有证据和阻塞原因。无法确认某次写入是否成功,就先查询目标状态,而不是直接再写一次。
这也是我把 Runner 看作可替换执行容量的原因。即使机器长期存在,恢复也不应依赖它的聊天上下文或唯一一份本地文件。
第一轮试点先检查“会不会停”
我不准备一开始就接入所有告警、所有仓库,再安排多个 agent 并行工作。对小团队而言,生成变更的速度很容易超过审查能力。
第一步应是手动选择一项非敏感、低风险、范围清楚的工作。在执行前固定验收条件,确认实现者和审查者的实际身份、权限与工作区,然后完整走一遍实现、检查、审查和人工决策。合并与部署仍是独立授权。
随后,在可丢弃环境中主动制造失败:加入一个已知缺陷,检查审查能否拦住;让必需检查失败,检查流程能否拒绝完成;在审查后修改候选,检查旧结论是否失效;重复发送事件,检查是否产生重复工作;让任务缺少必要信息,检查执行能否停止并准确提问。
这些测试通过,只能说明相应控制路径在测试条件下有效。它们不证明整个工厂可靠,更不证明它已经节省成本。
下一步才是少量真实任务,逐个执行,记录成功、失败、阻塞和放弃的案例。观察人工提示、审查、修复和维护的总投入,以及工具费用、漏检缺陷和最终结果。没有可比较的人工基线,就不声称节省了多少时间。
我希望这套设计最终减少的是上下文丢失、重复调查和无效返工。它是否值得继续建设,要看一个被接受的结果总共花了多少成本,以及它是否真的解决了值得解决的问题。
在得到这些证据以前,我宁愿先建设一个速度有限、停止行为经过测试的交付循环,也不急着把更多工作自动送进队列。
参考资料
- Matt Pocock: Dictionary of AI Coding:Software factory 与 Dark factory
- Matt Pocock: software-factory 术语设计草案,PR #1316。撰稿时该 PR 仍为 Open,并标记为 Draft;它提供设计语言,并非可直接运行的流水线。
- Hermes Agent: Kanban
- Hermes Agent: Kanban worker lanes
- Git 官方文档: git-worktree:说明多个工作树的机制;工作树隔离不等于安全沙箱。
本文进一步展开了此前 Company OS 设计中的交付部分。风险层级、证据结构和试点约束是作者提出的工作方案,不代表上述项目自带的完整保证,也不是已验证的行业标准。