Maintainability sensors for coding agents
标题:编码代理的可维护性传感器
编码代理的可维护性传感器
在最近一篇关于为编码代理用户提供引导工程的文章中,我阐述了一个扩展编码代理引导系统的思维模型:一个由指南和传感器组成的系统,用于提高代理输出优质结果的可能性,并在问题暴露在人类面前之前实现自我纠正。本文是一个更实用的后续,我将分享我在使用传感器帮助保持代码库可维护性方面的经验。
在我们的代码库中,通常有几个维度需要实现和监控:功能正确性(按预期工作)、架构适应性(足够快/安全/易用)以及可维护性。这里我将可维护性定义为让代码库随着时间的推移易于修改且风险较低——也称为"内部质量"。这样,我不仅希望今天能快速修改,也希望未来也能如此。我不希望每次修改——或者由AI进行修改时——都担心引入缺陷或降低适应性。当AI生成的代码库出现可维护性问题的早期迹象时,我通常会注意到:为了一个小小的调整,需要修改的文件数量增多了。或者修改开始破坏之前能正常工作的东西。
内部质量问题对AI代理的影响方式与对人类开发者类似。一个在混乱的代码库中工作的代理可能会在错误的位置查找现有实现,因为未注意到重复而导致不一致,或者被迫加载超出任务所需的更多上下文。
在本文中,我将描述我在各种传感器方面的实验,这些传感器帮助我和AI反思代码库的可维护性,以及我从中获得的心得。
应用
我正为一个社区管理员构建一个内部分析仪表盘,它从多个API读取聊天空间活动、参与度和人口统计数据,并在Web前端展示数据。

图1:示例应用:Web UI、服务层和外部API。
技术栈是TypeScript、NextJS和React。后端读取并从API中连接数据。这个应用已经存在一段时间了,但为了这些实验,我使用AI从头重建了它。
几乎没有为AI提供的关于代码质量和可维护性的指南(如markdown文件),我想看看仅依靠传感器反馈它能做得如何。
所有使用到的传感器概览

图2:传感器可以运行的位置:初始编码会话期间、流水线中、按计划执行、以及生产环境。
这是我在通往生产路径上设置的所有传感器的概览。
编码会话期间
这些传感器与代理同步持续运行,提供快速反馈。
- 类型检查器(计算型)
- ESLint(计算型)
- Semgrep,由我们内部AppSec团队规定的SAST工具(计算型)
- dependency-cruiser,运行结构规则检查内部模块依赖关系(计算型)
- 测试套件结果,包括测试覆盖率(计算型——尽管测试套件由AI生成,因此是以推理方式创建的)
- 增量变异测试(计算型)
- GitLeaks作为预提交钩子的一部分运行,我认为它也是一个传感器,因为它会在代理尝试提交时向代理提供反馈(计算型)
集成后——流水线
相同的计算型传感器在CI中再次运行。会话内的传感器在开发过程中为代理提供早期反馈。CI流水线确认干净基础设施上的结果,并在集成后确认结果。
重复执行
这些传感器以较慢的节奏运行,检测随时间累积的漂移,而不是即时发生的错误。
- 安全审查,根据我们内部应用的安全性 checklist 派生的提示(推理型)
- 数据处理审查,提示描述如"绝不应将任何用户名发送到Web前端"等内容(推理型)
- 依赖新鲜度报告,首先运行脚本获取库依赖的年龄和活跃度,然后由AI生成报告,提出关于潜在升级、弃用等建议(计算型和推理型)
- 模块化与耦合审查(计算型和推理型)
了解了这个背景之后,让我们深入探讨第一类传感器。
基本引导与模型
在构建整个应用过程中,我混合使用了Cursor、Claude Code和OpenCode(按使用频率排序)。我的默认模型通常是Claude Sonnet,对于某些规划和分析任务我使用Claude Opus,而对于实现任务我经常使用Cursor的composer-2模型。
静态代码分析:基础代码检查
我将从在这个应用中使用ESLint的经验开始。像ESLint这样的基础代码检查工具主要针对文件和函数级别的可维护性风险。
针对典型AI缺陷的规则
根据我的经验,静态代码分析最容易捕获的AI故障模式包括:
- 函数参数数量上限
- 文件长度
- 函数长度
- 循环复杂度
然而,这些规则在ESLint的默认预设中甚至没有启用,我必须先为它们配置最大值。希望静态分析工具能够发展出更适用于AI的预设。一些研究表明,人们已经开始发布针对已知代理故障模式的ESLint插件规则集,比如Factory的这个,包含诸如要求测试文件或结构化日志等规则。
自我纠正的指导
传感器的目的是向代理提供反馈,以便其能够自我纠正。理想情况下,我们希望为代理提供额外的上下文以促进自我纠正——这可以看作是一种良好的提示注入。为了做到这一点,我构建了一个自定义的ESLint格式化器来覆盖一些默认消息——当然,在AI的帮助下。
以下是我为 no-explicit-any 警告提供的指导示例。
我们希望对事物进行类型化,以便更容易避免错误,特别是对于关键概念。但我们也希望避免用不必要的类型使代码库变得臃肿。请对此做出判断。如果你选择不引入类型,请用以下方式抑制该警告:// eslint-disable-next-line @typescript-eslint/no-explicit-any -- (给出理由)
管理警告——现在更可行了?
静态代码分析已经存在很长时间了,然而,即使团队已经设置了它,他们也往往没有一致地使用它。原因之一就是随之而来的管理开销。有效使用这种分析需要团队保持"整洁的环境",否则这些指标就只会变成噪音。特别是像上面 no-explicit-any 这样的警告很棘手,因为你无法