AI 已经会写代码了,但我更关心:它说“完成了”,到底有什么证据? 📅 2026/7/13 22:22:03 最近一段时间我越来越少担心 AI 会不会写代码。真正让我不太放心的是它写完代码之后那段过于熟练的总结已完成重构已运行测试全部通过修改范围符合要求没有影响其他功能如果只是让 AI 写一个一次性脚本我可能看一眼运行结果也就过去了。但当我开始用 Codex、Claude Code 这类 Coding Agent 长期维护项目以后这几句话就没有那么容易让人安心了。它读取的项目说明是不是最新版本它有没有修改我没让它动的目录它说测试通过测试到底在哪个代码状态下运行的测试结束后它是不是又继续改了文件这次交付经过了哪些环节现在还能不能算有效换一个 Agent 接手时它知不知道项目过去为什么作出某项决定这些问题听上去很工程化实际上很好理解。假设你请人装修房子对方告诉你水电已经验收通过。这个结论当然有价值但你还需要知道验收的是不是现在这套水电验收结束后墙里有没有继续改线验收记录对应的是哪个施工方案AI 编程也逐渐出现了类似的问题。代码写得越来越快但“完成”这个结论究竟对应哪份代码、哪些规则和哪次验证反而越来越难说清楚。这也是我开发Agent Engineering Toolkit简称 AET的原因。它不是另一个替你写代码的 AI也不负责告诉 Agent 应该怎么思考。它更像是放在 Coding Agent 旁边的一套工程记录和验证工具检查 AI 读取的规则、约束它的改动边界、记录真实执行过的命令、判断证据有没有过期并把项目中的关键决定与原始资料联系起来。项目目前已经发布到v1.3.0。相比最初的 v1.0它已经不再只是给一次 AI 任务生成“验收收据”而是在逐渐形成一套轻量的 Agent 工程档案。AI 编程真正缺少的可能不是更聪明的模型很多 AI 编程产品都在解决同一个方向的问题让模型写得更准、改得更多、执行得更自动。这些能力当然重要。但当 Coding Agent 真正进入日常开发之后我逐渐发现很多风险并不是模型不会写代码而是整个过程缺少清晰的边界。例如我让 AI 给一个股票分析项目增加基金分析能力。我的真实要求可能是基金模块只改变分析对象模型配置、专家视角、报告结构和风险控制逻辑应该尽量继承股票模块的现有设计。AI 可能很好地理解了需求只增加少量代码也可能为了快速实现功能复制出另一套相似逻辑还可能顺手重构十几个文件把一个局部需求变成全局改造。最后它们都可能交付一段相似的总结基金分析功能已经完成并复用了现有架构这时光看自然语言结论是不够的。真正需要核对的是它到底改了哪些文件改动是否落在批准范围内是否突破了预先约定的变更规模需要提供的验证有没有真正完成。AET 的review就是在做这件事。在 Agent 开始修改代码前可以先用一份简单的意图文件说明本次任务允许修改哪些路径、变更规模大致是多少以及交付前需要提供哪些证明。任务结束后AET 会把真实的 Git 变更与这份约定进行对照。它不会评价代码写得优不优雅也不会凭空理解复杂业务。它只先回答一个更基础的问题这次 AI 的实际行动有没有超出人类批准的范围这种机制在 AET 中叫作 Intent Gate可以理解为“意图门禁”。我认为它的重要性在于它把“我大概让 AI 改这些东西”变成了一份可以复查的合同。尤其是经过多轮对话后人的要求和 Agent 的理解都可能逐渐漂移有一份明确边界比依赖聊天记录靠谱得多。“测试通过”不代表现在这份代码通过了测试AET v1.0 已经可以使用trace记录一条命令是否真实运行并把审计、改动审查和执行记录组合成 Evidence Pack。但项目继续迭代后我发现这里还存在一个很容易被忽略的问题测试确实运行过不代表眼前这份代码就是当时接受测试的代码。例如Agent 先运行测试得到全部通过的结果随后又顺手修改了两个配置文件。此时“测试通过”这件事仍然是真的但它证明的是修改配置之前的代码而不是当前准备交付的版本。如果只看测试日志很难发现这个差别。因此AET v1.1 增加了workspace_snapshot也就是工作区快照。从这一版开始审计、改动审查和命令执行记录都会保存当时的 Git 提交位置以及已跟踪和未跟踪文件状态的确定性摘要。生成证据包时AET 会对比这些快照判断审查、测试和最终打包对应的是不是同一个工作区。用不太技术化的话解释就是每完成一个关键步骤AET 都给当时的项目状态拍一张“指纹照片”。如果测试之后代码没有变化结果可以显示为精确匹配。如果 Git 提交没有变但工作目录里的文件又被修改过它会明确告诉你工作区已经不同。如果连 Git 提交都变了它也不会再把之前的测试结果悄悄挂到新的代码上。这里有一个我很在意的设计代码后来改变不会让过去真实运行过的测试突然变成失败。测试当时通过仍然是PASS但这份证据对当前交付已经过期交付状态会被标记为STALE。这比简单地把所有事情压成“通过”或“不通过”更符合现实。一张昨天的体检报告没有造假但它不能自动证明你今天的身体状态。证据是真的与证据现在是否仍然适用是两个不同的问题。AET v1.2 又进一步细化了这种失效原因。它可以区分是任务意图发生了变化、配置发生了变化、未跟踪文件集合改变了还是整个工作区或 Git 提交已经不同。对于普通用户来说不必记住这些状态名。只需要理解一件事AI 不能再拿旧状态下的测试结果为后来修改过的代码背书。一次 AI 交付不能只留下几份互不相关的报告随着审计、范围检查、执行记录和证据包逐渐增加又会出现下一个问题。这些产物都存在但它们之间是什么关系某份审计报告属于哪一次任务当前任务已经完成范围审查了吗测试已经执行但证据包是否生成证据包生成后项目有没有再次变化这次交付究竟是正在处理中还是已经正式关闭在 v1.0 中这些文件更像几张独立的检查单。它们各自有用却缺少一条完整的交付时间线。AET v1.2 因此增加了可选的Run Manifest。它可以理解成一次任务的本地交付账本。一项任务从绑定意图开始随后可以经历审计、改动审查、执行证明、证据打包最终关闭。如果中途工作区发生变化它会进入过期状态而不是继续沿用原来的完成结论。它大致记录这样一条过程已绑定任务意图 → 已完成规则审计 → 已完成改动审查 → 已执行验证 → 已生成证据包 → 已关闭任何关键文件在中途发生变化都可能让这条证据链变成STALE。Run Manifest 采用追加记录的方式保存状态变化不会静默改写过去发生过的事情。它也不会接管 Agent不会主动选择命令、调用模型、失败后自动重试更不是一个复杂工作流平台。它只是忠实记录一次交付走到了哪里为什么从一个状态进入了另一个状态。这项能力看起来是为团队交付准备的但我认为它对个人开发者同样有价值。个人使用 AI 编程时经常会在多个任务之间来回切换。今天改一半明天继续中间临时修了另一个问题顺便更新了配置。等准备发布时很容易记不清哪些测试是在什么时候运行的哪些报告还对应当前版本。Run Manifest 不会替你管理项目但它至少能避免把不同阶段的证据混成一个模糊的“应该没问题”。AI 说它读过项目说明我们究竟能证明什么AET v1.3 增加的第一项能力叫Context Manifest也就是上下文清单。这是一个我认为很符合真实 Agent 使用场景的功能。现在维护稍微复杂一点的项目往往会给 AI 准备很多说明材料AGENTS.md里写全局规则某个目录里还有局部说明Skill 文件告诉 Agent 如何完成特定任务架构文档解释模块关系项目记忆记录过去的设计选择。理论上Agent 应该先阅读这些内容再开始工作。问题是当 Agent 说“我已经阅读了相关说明”时我们到底能证明到哪一步它可能真的读取了文件也可能只是扫描到了文件名可能文件在任务开始后被修改也可能它读过但并没有正确理解。一个容易制造虚假安全感的工具会直接告诉用户Agent 已理解全部项目上下文。AET 刻意不这样说。aet context discover可以发现当前工作区内可用的项目指令和 Skill并记录它们的 SHA-256 哈希。这能够证明某个文件在当时确实存在内容是什么。aet context record --read则可以记录 Agent 或宿主声明自己读取过某份材料。但在证据等级上这仍然只是一条attestation也就是声明或背书。它不能证明模型真的看见了全部内容更不能证明它理解并正确使用了这些内容。AET v1.3 明确将文件发现与哈希视为本地证据而把“已读”单独保存为 Agent 声明。这听起来似乎有点较真但我觉得恰恰是 Agent 工程里最需要的边界。我们经常把“文件已经提供给模型”“模型说自己读过”和“模型正确理解了文件”当成同一件事。实际上这是三个不同层次。Context Manifest 不会试图证明最后一层。它只把目前真正能验证的事情记录下来哪些上下文文件在任务发生时可以被发现它们当时的内容哈希是什么Agent 声称读取了哪些文件这些文件后来有没有改变几天后再次运行verify如果某份项目说明已经被修改之前的读取声明不会继续被默认为有效。系统会明确告诉你当前上下文与当时记录的上下文已经不同。这对长期运行的 Coding Agent 特别重要。因为很多 Agent 出错并不是代码能力不足而是使用了已经过期的项目说明或者沿用了上一次任务留下的上下文。项目为什么这样设计不能永远只存在于某次聊天里v1.3 增加的第二项核心能力是Decision Ledger决策账本。做项目时间长了以后最难保存的通常不是代码而是代码背后的决定。为什么这个功能没有采用最简单的实现为什么没有引入某个依赖为什么基金模块必须继承股票模块而不是复制一份为什么评分机制被放弃只保留态度和证据为什么某个数据源后来被替换这些决定刚做出时往往非常清楚。它们可能来自一次 Issue 讨论、一份设计文档、一段实验结果或者一次对现有架构的复盘。但几个月后代码还在理由却已经散落了。尤其是使用 AI 开发时很多设计讨论发生在临时对话中。对话结束以后新 Agent 只能看到最终代码不知道哪些方案曾经被认真考虑过、哪些路线已经被否定。结果就是同一个问题可能被反复讨论甚至重新走回过去已经证明不合适的方案。Decision Ledger 的作用是把关键项目决定保存成带来源的本地记录。一条决策不只是写一句“我们决定这样做”还可以记录它的证据状态、来源文件的哈希以及后来是否被另一项决策替代。例如可以记录DEC-0001所有测试执行必须保持显式不允许 Agent 自动把未运行命令声明为验证完成。这条决定可以引用项目设计文档作为来源。以后运行验证时如果来源文件发生变化AET 会提示原来记录的内容哈希已经不一致。如果未来项目改变了方向也不需要删除旧决定。可以新增一条决策并明确说明新记录替代了旧记录。这样得到的不是一份永远正确的“项目真理”而是一条可追溯的决定演化链。AET 也刻意强调Decision Ledger 不是一个通用的 Agent Memory更不是 RAG 知识库。它不会自动吸收所有聊天也不会让模型把一切内容都存进向量数据库。它只保存维护者选择记录、并且能够追到来源的关键决定。这个边界很重要。项目记忆不是越多越好。把所有对话永久保存往往只会得到越来越混乱的上下文。真正有价值的是哪些决定仍然有效它们基于什么来源后来是否已经被替代。即使不会编程也能理解 AET 在做什么看到命令行、Git 和哈希这些词没有编程基础的人可能会觉得AET 显然还是程序员工具。从安装方式来说目前确实如此。它还不是一个打开网页、点击几个按钮就能完成检查的消费级应用。但它解决的问题并不要求用户先懂代码才能理解。假设你完全不会编程只是让 AI 帮你做了一个个人记账网站。第一次你让它增加登录功能。第二次你让它增加 Excel 导出。第三次你让它修改数据库结构。到了第四次Agent 告诉你“为了继续开发我需要对整个项目进行重构。”你未必能看懂它修改的每一行代码但你完全可以提出几个合理要求只能修改与这次功能相关的目录修改前先阅读项目规则修改后必须运行指定测试测试完成后不能继续偷偷改变代码重要架构决定需要记录来源没有验证过的部分必须明确说不知道这些要求本质上并不比验收一次装修更难理解。对于非程序员来说更现实的使用方式也不是自己背下全部 AET 命令而是把 AET 的 Skill 安装到 Codex、Claude Code 等 Agent 环境中然后用自然语言提出要求修改代码前先检查项目说明和 Skill 是否存在失效引用并记录本次可用的上下文或者修改完成后检查改动是否超出我批准的目录运行测试并确认测试之后工作区没有发生变化又或者把这次关于数据库方案的最终决定记录下来引用对应设计文档不要把推测写成已证实结论AET 自带一个可移植的 Agent Skill可以引导支持 Skill 的 Agent在审计、范围审查、执行证据、任务生命周期、上下文记录、决策记录和仓库演进分析之间选择合适的流程。用户与 Agent 仍然可以用自然语言交流但最终交付不再只剩下一句“相信我已经做好了”。AET 和测试工具、安全扫描工具有什么区别AET 并不替代测试也不替代安全扫描、代码审查或 Coding Agent 本身。测试工具关注的是代码在指定条件下能否产生正确结果。安全扫描关注的是代码中是否存在已知漏洞或危险模式。代码审查关注的是实现方式是否合理是否容易维护。AET 关注的则是它们之间经常被忽略的一层Agent 当时依据了哪些规则人类批准了什么范围真实改动是什么验证命令是否执行证据是否仍对应当前代码以及关键决定能否追溯到来源。所以它并不是一个裁判更像是记录员和证据管理员。它不会告诉你某个 Agent 的可信度是 92 分。因为这样的总分虽然看起来直观却很容易掩盖真正重要的问题到底是哪一项通过哪一项失败哪一项根本没有证据。AET 保留PASS、FAIL、UNKNOWN和NOT_APPLICABLE等独立状态。缺少证据就是UNKNOWN不会被折算成一个大体还不错的分数。它唯一使用权重的地方是triage对待修问题进行排序这个排序不会改变原始检查状态。这也是整个项目一直坚持的原则证据优先不是结论优先。从 v1.0 到 v1.3它真正补上的是什么如果只看命令列表可以说 v1.3 比 v1.0 多了工作区快照、Run Manifest、Context Manifest 和 Decision Ledger。但这些变化背后其实对应了四个更具体的问题。v1.0 回答的是AI 做了什么有没有证据v1.1 进一步追问这些证据对应的是不是现在这份代码v1.2 开始回答一次交付已经走到了哪个阶段整条证据链是否仍然有效v1.3 则补上Agent 当时可以看到哪些规则它只是声称读过什么项目关键决定来自哪里后来有没有被替代这让 AET 的定位发生了一点变化。最早它更像一张 AI 编程任务的工程收据。现在它正在变成一份轻量、可验证、能够持续更新的项目工程档案。这份档案不会保存所有内容不会替项目编造一个完整故事也不会声称理解模型内部发生了什么。它只记录那些能够明确描述、验证和追溯的事实。哪些人可能真正需要它第一类是已经让 Codex、Claude Code、Cursor 或类似 Agent 修改真实项目的人。当 AI 只补一个函数时可能不需要额外流程。但当它一次修改几十个文件开始接触数据库、配置、权限和发布流程仅靠聊天窗口里的总结就不太够了。第二类是同时维护多个项目的独立开发者。个人开发最大的优势是快最大的风险也是快。没有完整团队替你做审查、测试、交接和发布管理时许多判断都压在一个人身上。AET 不能替你建立一支工程团队但可以让一些关键过程不再只依赖记忆。第三类是使用 AI 做产品、但编程基础并不深的人。这类用户可能看不懂复杂代码却完全可以理解允许修改的范围、必须运行的验证、过期的证据和有来源的项目决定。事实上边界表达得越明确Agent 越不容易在模糊要求中自由发挥。第四类是需要进行任务交接和版本发布的小团队。一项工作从某个 Agent 交给人再从人交给另一个 Agent或者从开发进入发布阶段时Run Manifest 和 Evidence Pack 可以提供一份轻量的交接记录。第五类是刚刚接手陌生仓库的人。AET 的evolve可以连接 Git、文档、版本发布、Issue 和 Pull Request生成带来源的时间线与决策索引。Decision Ledger 则可以补充维护者明确保存的关键决定。相比让 AI 读完仓库后直接写一篇流畅的“项目历史”这种方式可能没有那么会讲故事但更适合支持真实判断。它目前依然有明显门槛我不想把 AET 包装成所有人安装后都能立刻受益的万能工具。它当前更适合已经使用本地 Coding Agent、并且愿意维护基本工程流程的用户。它仍然需要命令行环境Context Manifest 只能证明文件被发现和被声明为已读不能证明模型真正理解了它Decision Ledger 只能验证来源内容是否改变不能证明某项决定永远正确。它也不会替你判断业务需求本身是否合理。如果你让 Agent 删除用户数据AET 可以检查它有没有超出批准范围、是否运行了指定验证、证据是否过期却不能替你决定“删除用户数据”这个需求是不是正确。它同样无法证明测试覆盖是否充分也无法保证没有安全漏洞。AET 是测试、安全扫描、代码审查和 Agent runtime 之间的一层证据基础设施而不是这些能力的替代品。对于一个写完就丢的一次性脚本完整流程可能显得过重。对于长期维护、涉及真实数据、需要多次交接和发布的项目它的价值才会逐渐显现。所以项目没有要求每次改代码都运行全部能力。简单任务可以只做一次审计需要控制改动范围时增加 review需要证明命令执行时使用 trace正式交付时再建立 Run Manifest只有需要长期保存的上下文和关键决定才写入 Context Manifest 与 Decision Ledger。不是流程越多越专业而是在风险出现的地方留下恰当证据。我为什么觉得这类工具会越来越重要AI 编程正在让“做出一个软件”变得越来越容易。过去一个不会写代码的人想做网站最大的障碍是没有能力实现。现在他可以用自然语言让 Agent 一步一步完成。但软件开发的难点从来不只有代码生成。当产品开始拥有真实用户、保存真实数据、持续更新以后问题会从“能不能做出来”变成这次改动会不会影响旧功能Agent 是否遵守了原来的规则测试结果是否对应现在的代码任务交付以后证据有没有过期更换 Agent 以后新的 Agent 是否知道过去为什么这样设计当结果出现问题时能不能找到当时依据了什么AI 降低了代码生产成本也放大了验证、交接和项目记忆的重要性。代码生成得越快工程证据越不能只留在聊天窗口里。这就是我继续迭代 Agent Engineering Toolkit 的原因。我并不认为所有问题都应该继续交给模型解决。有些事情更适合让确定性的本地程序完成检查路径计算变更范围记录文件哈希绑定工作区快照保存命令退出状态记录交付阶段验证上下文是否改变维护决策的替代关系。Agent 负责理解和行动AET 负责边界、证据和留痕。一个负责把事情做快另一个负责提醒我们做得快不等于已经证明做对了。项目地址Agent-Engineering-Toolkit目前 AET 已发布 v1.3.0。相比 v1.0它新增了工作区快照与证据新鲜度检查、可追加记录的 Run Manifest、Context Manifest以及带来源哈希和替代历史的 Decision Ledger。回归测试也从 v1.0 的 20 项增加到了 v1.3 的 27 项。它距离真正面向普通用户的无门槛产品还有一段距离但它至少试图认真回答一个以后可能越来越常见的问题当 AI 说“我已经完成了”我们除了相信它还能留下哪些可以复查的东西