Elevate

Human judgment doesn't leave the software factory. It relocates.

8.5内容质量
Human judgment doesn't leave the software factory. It relocates.

TL;DR · AI 摘要

软件工厂需保留人类判断核心,通过自动化工具与人工审查结合确保代码质量,AI代理编写代码仍需人工最终决策。

核心要点

  • SonarQube可作为自动化质量门禁工具,强制执行统一代码标准。
  • 软件工厂需在产品设计、系统架构等环节保留人类决策权。
  • AI代理生成代码后,必须经过自动化测试与人工审查双重验证才能部署。

结构提纲

按章节快速跳转。

  1. 软件工厂是可重复的软件开发循环流程,需保留人类判断核心。

  2. 人类需在产品意图、系统设计、质量标准等环节进行关键决策。

  3. 通过类型系统、自动化测试、SonarQube等工具实现持续质量验证。

  4. 当系统需要事件驱动和可重复流程时,软件工厂的构建变得必要。

  5. 使用SonarQube进行跨文件分析,强制执行质量门禁并拦截不合格代码。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 软件工厂与人类判断
    • 核心机制
      • 人类决策环节
      • 自动化质量检查
    • 实施工具
      • SonarQube
      • GitHub Actions
    • 关键挑战
      • AI代理可靠性
      • 质量门禁设置

金句 / Highlights

值得收藏与分享的关键句。

#软件工厂#代码质量#AI代理#自动化测试
打开原文

人类判断不会离开软件工厂,只是转移了位置

构建一个仍有所有者的软件工厂的实践指南

Addy Osmani

2026年8月21日

软件工厂是围绕软件工作构建的可重复循环。如果您正在构建软件工厂,即使代码已经足够发布,仍然需要人类的审美和所有权。我们将讨论这一点,包括您是否现在就需要一个工厂。

如果需要:

  • 在决定产品意图、系统设计(如果您关心的话)和质量标准时,您可能需要在早期阶段让人类参与其中。
  • 进行代码审查(开灯工厂),但要有意识地确定最需要审查的环节。我发现您需要关注自动化反压机制失效的地方,或者需要做出可维护性权衡的地方。
  • 尽可能早且持续地进行质量检查。并非所有检查都必须如此,但这包括类型系统、自动化测试、变异测试、安全扫描器和架构规则的代码规范检查。
  • 检查数量≠质量。您可能需要通过实验确定哪些检查能提供最佳的信号与噪声比。准备好有意识地收紧或放松约束条件。

您希望构建的工厂能让某些人类判断的要素被编码到环境中,代理会提供其工作正确性的证据,同时人类仍然“拥有”什么被部署到生产环境。

您的代理编写代码。您的门禁决定是否部署。AI代理正在以比以往更快的速度编写我的代码——但速度快并不等于可部署。因此,我让一个编码代理构建一个应用,然后通过SonarQube进行检查。每次提交都会经过相同的确定性检查:深度跨文件分析,清晰的风险分布图,以及一个对所有人和代理都适用的质量门禁。截图?一个未通过审核的PR。这就是门禁在履行职责。立即体验SonarQube → (https://fandf.co/4g7DP8r)。由Sonar赞助。

您真的需要软件工厂吗?

根据我的经验,您使用现成的编码工具套件就能取得令人惊讶的成果!即 Claude CodeCodex,多个会话,内置验证机制的优质SPEC,以及约束条件。您甚至可以向它们批量提交GitHub问题,并设置实现标准和人类参与标准,但当这个系统需要可重复性和事件驱动时,工厂就会变得有用。

因此,我一开始就说软件工厂是围绕软件工作的可重复循环。实际上,我们可以通过以下提示来看一个非常小的工厂循环示例:

在修改代码前阅读GitHub问题#123和仓库说明。仅实现明确的验收标准。不要修改认证、计费、迁移或现有测试断言。在分支上工作并保持差异可审查。运行npm run lint、npm test和npm run build。如果必需的检查无法运行,请停止并解释原因。创建一个草稿拉取请求,列出您运行的检查、剩余风险以及人类仍需做出的决策。不要合并。

一个目标可以推动这个过程持续进行,直到检查通过,我们每天早上可以轮询GitHub问题中的特定标签或审查开放的拉取请求。分支保护可以强制执行合并边界,而人类可以通过选择什么准备就绪、进行审查和做出最终合并决策等方式保持在循环中。

添加一个软件工厂,当你需要一个事件驱动的工作队列(例如 Slack 触发器、GitHub 问题、Linear、待办事项)在隔离的云环境中运行,以处理分类、实现和测试,并需要一些明确的人工监督。一些流程会在循环结束时通过监控代理观察生产环境并重新提交问题以进行再次分类。

在我的经验中,当困难的部分在于让不同的运行保持行为一致、在代理之间传递工作、避免不同会话声称同一问题、保留证据并在人工审查落后时停止生产时,软件工厂变得有用。

解决这些问题的方法可能听起来有些乏味。例如,Warp 提到将每个新问题分类为四个状态之一:准备实现、准备规格说明、需要更多信息、等待实现,而标签会触发下一个代理。

这个标签一次完成多项任务:它是队列、是锁,由于会话只能拾取标记为“准备”的内容,因此也是人类可以暂时停放任务的地方,而无需永久拒绝。

从工作流程来看,与仅使用 Claude/Codex 有一些相似之处和差异:

  • 引导:当代理需要调整方向时,你可以提供输入并重新引导它
  • 通知:工厂被阻塞时的提示方式。这可能是因为需求不明确、启动了高风险操作或需要人工输入(引导)
  • 交接:在云工厂/另一个代理/人工审核员之间转移任务、状态和上下文。良好的交接会跟踪已完成的内容、剩余待办事项以及交接的必要性

在一个优秀的工厂中,人类的作用不仅限于在最后阶段审核和批准最终的差异。他们可以在早期塑造工作,在实现过程中引导,通过交接或阻止其发布到生产环境。

验证是负责任的工厂投入大量时间的地方。我们将在后面更详细地讨论这一点。

如果你决定确实需要一个软件工厂,构建它并不是唯一的选择。搭建基础设施以扩展工厂可能需要大量工作,你可能需要考虑购买现成方案而非自行构建。Factory、Warp 和 HumanLayer 正在为此类方案进行开发。

我现在的一天

过去一年中,我的软件开发日常发生了很大变化。我一直在谈论越来越多地与代理并行工作,朝着“开灯式”软件工厂的方向发展。很多人问我,这些概念到底意味着什么?你在构建什么?你们使用这些工具的项目类型有哪些?答案大致如下:

在非常普通的日子里,我会使用一个更简单的“开灯式”软件工厂。我可以拥有在云端运行的任务。其中一半任务可能涉及与我合作的中小型公司的生产客户端应用。这些应用会有真实用户,真实的身份验证、支付、订阅功能,以及需要特别注意的真实高风险场景。你不能简单地说“代理,去执行这些操作”,而不先建立测试、约束和质量检查机制。

我可以在自己的开源项目上工作。我可以为自己的书籍构建配套网站,可以开发工具,可以构建自己的应用程序。这些都是我正在处理的非常不同类型的项目。有时它们唯一共同点就是我使用的开发工具,对吧?也许我正在处理一次迁移任务,而其他时候我可能在进行实际的、复杂的功能开发。而这些工作的影响力范围也可能存在显著差异。

当我们开始思考如何实现大量并行工作时,我们需要提高速度、提高生产效率,并增强自主性。这意味着要让系统达到我们更加信任它的状态。这时你必须思考哪些环节绝对需要人工代码审查和人工参与。

其中很多工作需要在前期就完成,对吧?当你定义规范、需求时,产品的设计会是什么样子?产品的意图会是什么?然后你如何验证代理确实正确地完成了工作?如何验证它们没有破坏现有系统?如何确保它们满足你的质量标准?

因此,生成代码本身并不一定是需要最担心的部分。只要提供足够的上下文,代理可以编写实现代码、运行测试、检查失败情况并为我们修改代码。我们需要达到一个状态,即环境中有足够多的人类审美判断,使我们能够信任所构建的内容,从而让人类的注意力集中在最需要的地方。

当然,也有一些人会反对,说:“嘿,我不认为这些都可以通过自动化解决。”我们并不是要完全自动化所有内容,对吧?但考虑到生成的代码数量,我认为让人类阅读所有代码是不现实的,尤其是在我们大多数时候并不是在制造火箭,而是在构建用户界面、构建全栈应用的时候。

我们的判断力和审美判断应该集中在最需要的地方。比如,系统中哪些部分风险最大?我们需要在哪些地方应用人类的审美判断?这可能在前端,也可能在系统运作方式上。这并不需要覆盖100%的内容。

我的认知带宽无法与代理规模匹配

现实情况是,是的,我们现在可以并行启动数十、数百甚至数千个代理,但你自己的认知带宽却无法以相同方式扩展。这可能会导致认知债务或理解债务,我之前也讨论过这个问题。

如果你还记得五年前或十年前,工程界曾广泛讨论过上下文切换的成本。我们会谈到人们讨厌在任务进行中,同事或他人突然走到你桌前打扰你。这会耗费你很长时间才能重新进入专注状态,因为你需要重新理清思路:我之前在哪里?我之前在做什么?即使你之前留有少量记忆残影,也需要花费时间才能恢复状态。

我们现在需要进行的上下文切换比以往任何时候都更加频繁。在任何一天,如果我不在软件工厂内工作,可能同时在处理五到十个不同项目的代理任务,或者在一个项目上同时处理五到十个不同的功能。我可以同时拥有五到十个不同的会话窗口,这几乎是可以实现的。

这意味着我必须能够持续关注其中至少几个任务。如果我对某些任务的定义足够清晰,对预期结果的描述足够明确,并且能够验证任务是否完成得足够好,那么我可能会赋予这些任务更多的自主权。但有些任务可能并不具备这些条件,它们可能涉及更多风险或更复杂的细节,这时我就必须保持高度关注。

考虑从评审者的角度优化软件工厂。由于所有这些方法最终都会将输出结果导向某一个人的注意力,你应该思考一下,这个工厂在你仍需做出决策时,是否显著降低了决策成本。

项目错误的典型案例

我记得曾经与代理同时处理多个并行项目时,就曾发生过类似错误。比如,我正在为某个网页应用添加深色模式功能,当时我脑海中已经构思好了这个功能的实现方式。但我不小心进入了另一个项目的会话窗口,开始在那个项目中输入相同的提示。

于是,我开始为一个根本不需要深色模式的项目实现该功能。我可能会犯这种错误,而我并不希望我的软件工厂也犯这种错误。

你需要从系统层面认真思考这个问题。你实际上是在将软件工程文化、团队文化编码到系统中,使其具备相同的行为特征,让责任归属明确,确保始终有人对结果负责,并且要非常明确地定义你对这些事项的思考方式。

绿色状态可能具有误导性

即使在这些系统中,你也需要格外谨慎,对吧?我们很多人都经历过这样的情况:当要求AI帮助通过测试(比如编程测试或单元测试)时,AI可能会修改单元测试以满足条件,或者改变代码逻辑以通过测试。但这并不意味着它真正遵循了你的意图,使功能行为与测试目的保持一致,对吧?

仅仅因为软件工厂显示所有状态都是绿色,并不意味着实际情况确实如此,特别是在初始设置阶段。你需要投入大量注意力,确保所有检查项和验证机制都设计得当,确保它们按照你的预期执行。你不想让这些机制产生误导。

你不想出现这样的情况:测试显示"实际上,我已更改了支持的身份验证提供方"。比如,你要求我添加GitHub作为身份验证提供方,但我的界面只预留了三个位置,所以我删除了另一个提供方。而恰好被删除的是客户实际需要的选项。因此,你必须非常明确地定义这些系统应该如何运作。

不过,安全同样至关重要。如果工厂需要读取类似GitHub问题或Slack消息等不可信输入,这些输入可能具有对抗性,甚至包含供应链攻击等风险。因此,一些软件工厂(如Vercel)在探索过程中,会将代理运行在仅包含任务所需密钥的隔离沙箱环境中。这样即使运行环境被攻破,也无法访问任务不需要的资源。最终你的防御体系会变得层次分明。

哪些旧项目值得重启?

我认为我们当前工作方式的一个重要部分是决定哪些事物应该存在。回想多年前AI尚未普及的时期,存在大量被遗弃的软件工程项目、周末项目和个人项目,它们从未上线是因为我们没有时间完成。当时我们没有足够的精力去优先处理这些项目,因为它们对我们而言并不重要,或者我们找不到时间。

如今我们完成这些项目已经变得非常简单,但同样的判断问题依然存在:这些项目真的值得存在吗?是否应该重新上线?因为你一旦将它们发布到世界上,即使只有五个用户,可能也需要持续维护。你现在可能对产品质量有了更高的标准。

我深知自己多年来在GitHub上积累的众多项目,现在有了代理之后,我做的第一件事就是让这些项目重新构建。当然,你克隆代码后会发现它们无法构建,因为所有依赖项都已变更。一半的项目已经过时,或者存在各种安全漏洞,所以你必须先更新这些内容。

接下来如果你没有测试,还需要添加测试,以确保在升级项目或迁移到更现代的语言/框架时,至少能保证基本行为的稳定性。然后你会开始思考:比如一个傻瓜式的例子,我过去可能用过Twitter Bootstrap来构建这个项目,但现在所有人都在使用Tailwind和shadcn,所以我必须重新实现UI。你会发现,突然之间这需要你投入更多时间,对吧?虽然代理可以快速完成大部分工作,但你现在必须考虑产品感知、审美等所有因素。

你仍然会质疑:这是为谁而做的?它有市场吗?是为自己?还是为其他人?如果我将它发布到世界上,现在任何人都能快速创建类似项目,它是否还会像以前那样有趣?

我认为这些关于"这些事物是否值得存在"的人类判断问题依然极其重要。这正是人类注意力这种稀缺资源真正发挥作用的地方。过去我们每天只有有限的时间,有会议,需要为设计、编码等安排时间。

现在有了代理的帮助,我认为你必须非常明确地说明自己时间的投入方向和原因。

我构建示例工厂时的经历

我将谈谈这个82分钟的工厂运行过程。人们已经问了我很长时间:"我该如何构建软件工厂?"或者"我习惯使用Claude Code或Codex,如何将我的工作流程升级到软件工厂?"

因此,我一直在强调的第一点是:“你可能已经做得很好了。你的工作实际上可能根本不需要工厂就能完成。”但我想为人们提供一个可以参考的示例设置。我整理了一个名为Factory的仓库,你可以去查看。我还准备了一个演示应用和工作坊。

过去几年里,我用于演示的常用应用是电影应用。我是个电影爱好者,我非常爱看电影,经常观看电影,因此我有一个演示应用,它最初是一个非常简单的电影应用。我希望Factory能够实现一些功能,包括收藏功能、搜索功能,以及可能添加暗色主题等。

于是,我让Factory开始处理这些功能。你可以查看实现过程。其中一个好处是它实际上能发现真实的问题。这些问题可能是我如果只是要求它进行一次性的实现时不会发现的。

大约在60分钟时,我感觉:“哇,这进展异常缓慢。”我询问我的测试框架使用Factory,“为什么进展这么慢?”它回答:“其实一切正常,所有验证器仍在运行。”

你可能预期单个任务需要10分钟、15分钟或20分钟,但一旦开始包含验证、重试、浏览器检查、人工审核等额外延迟,它们可能需要两到四倍的时间。

我认为这些延迟可以提升系统的质量和可信度。从度量角度来看,你可能会关注如每个合并的PR成本和代码生命周期等理解债务指标。

你还需要思考哪些是有效的延迟,哪些是工厂的额外开销。在我的案例中,验证器确实发现了一些真实的问题。一部分时间可能被用于生成我想要的证据,另一部分则是工厂运行的开销。我没有花时间进行优化,但一个只运行大量你认为没有价值的检查的工厂,并不意味着它质量高。

你想要研究的是:对于任何重复的检查,它们是否无关紧要?是否产生噪音?它们是否真的让系统更安全?

验证预算

我对验证预算的理解,基本上就是我们正在讨论的内容。我们正在讨论验证预算。我以与以往对性能预算的思考方式相同的方式来思考它。

在软件开发生命周期的早期阶段,你可以运行某些类型的检查,而有些检查非常耗时,但它们的价值极高,因此你希望在后期运行它们。有些检查速度很快,比如代码格式检查、类型检查。这些相对快速的检查可以在早期阶段运行。

我们的完整测试套件可以在提交草稿PR之前或之后运行。这可能包括突变测试、浏览器测试、安全检查等。

我认为,你并不一定希望仅仅用摘要来替代这些内容。你想要的是真正的测试,但你只需要确保在正确的地方为它们预留预算,因为你不希望减慢开发流程。我当然从不希望减慢自己的开发流程。对我而言,拥有快速的迭代循环非常重要,但我也希望仍然保留这些检查与平衡机制。

当运行未被部署时

我之前写的大部分内容都涉及检查机制。

在Vercel的软件工厂中,每个代理运行都会被标记为“成功”、“有缺陷”、“被阻塞”或“人工处理”,只有“成功”会被部署到生产环境。其余状态会重新进入系统。我一直在以类似的方式思考运行状态。

此处“有缺陷”意味着实现了错误的内容,或者可能缺乏完整上下文,因此需要修复。“被阻塞”意味着环境可能缺少凭证,需要你提供。“人工处理”则是工厂目前可能尚未被允许跨越的边界。

这三个状态中,有两个可能有机械性修复方案,最后一个则涉及信任问题。

虽然这种分类方式很好,但它并未显示成本。

回到我之前使用TMDB应用的工厂实现,快速查找功能没有拒绝项时耗时7分钟。而“收藏”功能有两次拒绝和中间的人工决策,耗时56分钟。同样是这个工厂。因此我需要将分类法与每个阶段的耗时进行配对,否则你将无法知道运行返回“有缺陷”状态时,发现该问题所付出的成本。另一个需要修复的是边界交接:我的示例工厂在遇到第一个问题时停止并将其标记为factory:needs-info,这是正确的做法,但我不知道该把答案放在哪里。人工运行的完成时间不是工厂停止的时间,而是人类知道下一步该做什么的时间。

自主性不是单一设置

几周前我写过一篇关于代理自主性以及如何思考自主性的文章,因为自主性不会是每个项目都适用的单一设置。

验证能为你赢得信任,也能赋予代理更多自主性的能力。例如,如果我在处理一个非平凡的变更,但已经建立了多项检查,所有内容都正确验证过,甚至我自己也进行了人工检查。那么下次在相同项目中执行类似任务时,我可能会感到更放心,给予代理更多自主性。

这就是你在构建这些软件工厂时需要思考的问题。你的验证机制会随着风险变化而调整。你的目标是实现最佳的信噪比。你并不只是想要一个需要运行的大型检查清单。

我不得不重新学习的功能

有一个功能是我一直拖延着没有处理,那是在我使用Claude的多个会话期间,同时在处理多个项目、每个项目同时处理多个功能时。Claude已经实现了我正在处理的功能。看起来测试通过了。我没有花太多时间思考验证,但测试通过了,所以我以为它正常工作了,于是将其合并了。

这是一个收藏功能。我以为这个功能其实相当不错。我尝试在浏览器中查看它,看起来似乎没问题。但几天后,我回到代码中,因为我想对这个功能做一些微调。

我并不想只是让我的代理去做出这些改动,因为这只是一个微妙的实现方式。你点击图标时,它在点击时不会显示出正确的效果,所以我想要进行一些微调。我想理解它是如何运作的,这样才能正确地指导我的代理。

我回到代码中,却无法向你解释这个功能是如何运作的。这个仓库原本就是我的,对吧?我曾批准过这个改动。我理解其中很多部分的运作方式,大部分仓库的代码我也了解,但我的理解并没有跟上代码的累积速度。

我未能吸收的是这个新增功能实际是如何运作的,UI是如何运作的,以及它的效果是如何实现的。我必须重新实现这个功能,并逐步思考:“它是如何运作的?我该如何理解它?”

并行工作对理解的影响

当你进行并行工作时,会加剧这个整体问题,而在软件工厂中进行并行工作时,这种影响会更加显著。当你进行五次或十次会话时,它们产生的问题远不止是审查量的问题。它们会创建多个心智模型,而当你在别处工作时,这些模型可能会变得非常冷僻。

我们历史上曾讨论过上下文切换的挑战,一旦聊天被压缩,你就会拒绝某些方法,尝试不同的事情,与代理配对,你将很难记住会话中发生的一切。

你可以向上滚动,但随着压缩的发生,你不会在那找到所有内容,也无法将所有内容存储在脑海中。代码通常会保留某个决策,但不会保留做出该决策的原因。

我认为这对你来说是一个有用的教训,当它重要时,考虑要求你的代理实际存储有关其轨迹的信息,或关于它如何解决问题的有趣经验,以便你之后可以回顾。

这可能是你决定提交到仓库的内容,如果你想的话,你可以将其保留在本地,也可以与团队共享,但之后可以查阅。而不是依赖它可能存在于会话中,或你之后可能记得它。

P.S. - 如果代理正在向你的主分支推送代码,它们需要达到与你相同的质量标准。SonarQube 确定性地对每次提交进行门禁检查:对人类和代理都采用同一标准,对每个 PR 都如此。尝试 Sonar → ( https://fandf.co/4g7DP8r ) · 由 Sonar 赞助。

所有权不会消失

所有这些背后有一个更广泛的原则。

人类实际输入的代码比例可能会大幅下降。但我不认为人类的所有权需要随之下降。

  • 有人仍然选择问题。
  • 有人仍然选择架构。
  • 有人仍然设定质量标准。
  • 有人决定哪些验证信号值得信任。
  • 有人决定何时证据足够以发布。

当系统最终失败时,“代理写了它”并不能解决问题。这就是为什么我不认为软件工程的未来最好被描述为人类退出循环。相反,人类的判断正在被重新定位。

我们应该将人类从机器能够产生更强、更快、更确定信号的循环部分中移除。同时,我们应该将人类集中在那些上下文、品味、风险和长期所有权最重要的地方。

最佳的软件工厂不会由其消除人类参与的彻底性来定义。

它们将由其对人类参与的智能安排方式来定义。

将人类判断置于意图、系统形态和质量标准的上游。在自动化反馈减弱或后果变得主观时进行代码审查。尽可能早且持续地将每一个确定性信号引入循环。随着系统赢得或失去信任,有意地收紧或放松约束。

人类仍需负责最终发布的代码。足够好到可以发布的代码,其起点仍在于此。