AI 辅助开发的核心在于规则体系设计
一个 Android 组件化项目的实践复盘
我们团队在一个大型 Android 组件化应用中落地 AI 辅助开发已经不少时间,踩过不少坑,也攒下了一套可复用的规则体系。这篇文章把我们的设计思路和实战经验整理出来,供同样在推 AI Coding 的 Android 团队参考。
1. 为什么需要规则体系
刚把 AI 助手引入项目时,我们遇到三类问题:
上下文遗忘。 项目有 20+ 模块,复杂的依赖方向(libcore → libapi → 业务模块),特定的继承体系(新增 Activity 必须继承 ChannelPlayActivity),这些约束 AI 并不天然知道。每次对话都要重新交代一遍,交代漏了就出问题。
幻觉编造。 AI 会"发明"项目中不存在的类名、方法名、资源名。比如随口编一个 ImageUtils.load(),实际上项目用的是 ImageLoader.with()。等你发现时,已经 review 完好几段代码了。
多规则混乱。 项目同时有通用编码规范、TV 焦点规则、埋点规范、性能规范,每次都全量加载,上下文窗口很快撑爆不说,AI 还容易把不同规则的约束搅在一起。
核心矛盾是:AI 的能力取决于你喂给它的上下文质量,但上下文窗口是一个稀缺资源。 规则体系要解决的就是"在正确的时刻,把正确的约束,以正确的粒度喂给 AI"。
2. 工具链:Qoder IDE Plugin + Qoder CLI
我们的规则体系运行在 Qoder 工具链上:
- Qoder IDE Plugin:在 IDE(Android Studio / IntelliJ)中集成,负责读取规则文件并注入到 AI 对话上下文中,同时提供技能调用、自查清单等交互能力。
- Qoder CLI :命令行工具,主要负责 Git Hook 集成,在
post-commit时自动记录 AI 参与的提交,用于后续的效果度量和知识沉淀。
工具链的定位是"规则的执行引擎"------它不生产规则,只负责按调度策略加载规则、按触发条件激活技能。真正有含金量的工作,是规则本身的设计。
3. 新人入手:AGENTS.md 作为第一入口
一个新成员加入项目,或者 AI 第一次被接入项目时,面对 20+ 模块、十几份 reference 文档、多个规则和技能,最大的困惑是"我应该从哪看起"。
我们的做法是用一个 AGENTS.md 作为统一入口。这份文件放在项目根目录,包含:
- 项目一句话概述(这是什么项目、用什么技术栈)
- 构建命令速查(怎么编译、怎么跑单个模块)
- 构建环境参数(Gradle 版本、Kotlin 版本、targetSdk 等)
- 规则与技能的触发策略------这是核心差异化部分
AGENTS.md 不写具体规则内容,只做两件事:告诉 AI 这个项目长什么样 ,以及告诉 AI 什么情况下应该去读哪份规则。它是整个规则体系的"调度器"。
有了 AGENTS.md,AI 在每次对话开始时就有了关于项目的最基本信息,也知道在遇到具体开发任务时该去哪找详细规则。新成员也可以通过读这一份文件快速建立对项目规范体系的全景认知。
4. 架构设计:三层体系
我们把规则拆成三个层次,每一层解决不同的问题:
bash
调度层(AGENTS.md)
├── 约束层(rules/)
│ ├── car_project_rule.md # 项目开发主规则
│ └── tv_focus_rule.md # TV 焦点专项规则
├── 参考层(references/ + skills/)
│ ├── references/ # 模块文档 · 依赖关系 · 约定 · Crash模式
│ └── skills/ # 埋点技能 · 性能优化技能等技能
4.1 调度层:AGENTS.md
AGENTS.md 扮演的是"路由"角色。它不包含具体的开发约束,而是定义了一组触发条件 和跳过条件。
每一条规则或技能在 AGENTS.md 中都有一个对应的节,写明:
- 触发条件:满足什么条件时加载(如"执行代码生成、修改、审查操作")
- 跳过条件:什么情况下即使匹配关键词也不加载(如"纯闲聊""通用编程知识问答")
- 核心约束摘要:用表格给出最关键的那几条规则,让 AI 在不需要完整加载时也能有一个快速参考
这种设计的好处是:按需加载。AI 不会一次性塞进几万字的规则文档,而是根据当前任务动态决定读什么。既节省了上下文窗口,又保证了相关约束不丢失。
4.2 约束层:rules/
约束层是整个体系的核心,定义了"什么能做、什么不能做"。
car_project_rule.md(项目开发主规则) 覆盖了 13 个维度的约束:
| 维度 | 典型约束 |
|---|---|
| 架构 | 模块依赖方向、业务模块间通信方式、继承体系 |
| 路由 | 新增页面必须四处注册(路径常量 + Handler 映射 + ActionType 常量 + @Route 注解) |
| 网络 | 双链路选择、线程安全、网络检查 |
| 存储 | SPHelper 优先、禁止直接 SharedPreferences、Key 禁止硬编码 |
| 安全 | 加密逻辑封装、密钥管理、登录服务获取方式 |
| 初始化 | ApplicationHelper 职责边界、注册要求 |
| JSON | 必须使用 GsonUtil + try-catch |
| 日志 | 四级优先级(LogUtils > L > Logger > android.util.Log) |
| 性能 | 内存泄漏防护、图片加载规范、线程与并发规范、列表优化 |
| 资源 | dimens/string/color/drawable/layout 的命名与同步规则 |
| 代码质量 | 共性抽取、禁止冗余、风格一致 |
| 自查清单 | 23 项生成后必检项 |
tv_focus_rule.md(TV 焦点专项规则) 则是针对 Android TV 遥控器焦点系统的专项约束,覆盖了焦点三层架构、编译期插件替换机制、DialogFragment 焦点处理、按键事件分发、无障碍适配等复杂场景。这类专项规则的特点是:领域知识非常深,但只有少数场景需要------完美匹配按需加载的策略。
4.3 参考层:references/ + skills/
references/ 是"事实层"------记录项目真实存在的类名、方法名、路径、依赖关系。每个模块一份文档,以模块的实际目录结构为骨架展开。此外还有:
dependencies.md:模块依赖图与第三方库版本conventions.md:代码生成步骤(新增接口/页面/服务/渠道的标准流程)与反模式示例crash_patterns.md:历史 Crash/ANR 模式的特征识别、根因分析、修复方案
skills/ 是"流程层"------为特定领域的复杂任务提供分步骤的操作指导。例如 amber_skill 覆盖了从初始化、页面埋点、播放器控件埋点、广告埋点、搜索埋点、支付埋点到登录全链路的详细约束和调用模板;performance_skill 则提供了内存泄漏、启动速度、ANR、网络、渲染、车机特有性能的关注点和检测流程。
每一份 skill 文档都具备独立交付能力------AI 加载后不需要再追问,直接可以执行。
5. 否定词保护:5 种否定模式的触发过滤
这是我们在实践中踩坑最多、迭代次数也最多的一个设计。
一开始我们只做简单的关键词匹配------用户消息中出现了"焦点"就加载焦点规则,出现了"埋点"就加载埋点技能。很快发现问题:关键词匹配的准确率远低于预期。
比如用户说"这个页面的生命周期类似 page_start,但跟埋点无关",机械匹配会因为"page_start"而触发 amber_skill,但用户显然不想讨论埋点。
我们总结出 5 种需要过滤的否定场景:
| 否定模式 | 典型示例 | 应跳过的原因 |
|---|---|---|
| 已关闭/已完成 | "焦点问题已经修好了,不需要再看焦点规则" | 问题已解决,加载规则纯属浪费 |
| 类比/对比 | "这个页面的生命周期类似 page_start,但跟埋点无关" | 提及关键词仅做类比,非实际需求 |
| 通用概念讨论 | "Gson 和 GsonUtil 在原理上有什么区别?" | 通用知识问答,非项目开发操作 |
| 明确排除 | "检查首页布局问题,不涉及焦点和埋点" | 用户显式排除了这些领域 |
| 间接引用 | "日志里报了 position_click 相关错误" | 引用仅用于描述现象,非该领域开发需求 |
实现方式上,我们要求 AI 进行语义二次判断:关键词匹配只是初筛,必须结合用户意图做二次判断。判断原则是三句话------"关键词出现在否定语境、类比语境、已关闭语境中时,不触发"。
这个设计让误触发率显著下降。更重要的是,它让用户感受到 AI 在"理解"他们而不是机械响应。
6. References 体系:"先查后写"如何抑制幻觉
AI 编造不存在的类名/方法名是我们遇到的最常见问题之一。根本上,这是因为 AI 的训练数据中没有我们的项目代码。
我们的应对策略是建立一个完整的 references 体系,并强制要求 AI 先查后写。
每模块一份文档
项目的每个模块在 .qoder/references/ 下都有一份对应的 markdown 文档。文档内容包括:
- 模块的包名和依赖关系
- 真实的目录结构(package tree),让 AI 知道这个模块里有哪些包、每个包下有哪些类
- 核心类详解:关键类的方法签名、获取方式(单例/ServiceManager/ARouter)
- 该模块特有的注意事项
以核心基础库模块为例,它的 reference 文档会列出 application/、arouter/、data/、amber/、widget/、utils/ 等所有子目录,以及每个目录下的关键类名和职责。
三层约束保证"不编造"
在 car_project_rule.md 的行为准则章节,我们写了三条硬约束:
- 先查后写:生成代码前,先查阅目标模块的 reference 文档,确认类名、方法名、路径真实存在
- 禁止虚构:不得使用项目中不存在的类/方法/常量/路径;不确定时必须用搜索工具验证
- 禁止引入新依赖:仅使用 dependencies.md 中已列出的第三方库和模块依赖
这三条约束配合完整的 references 文档,把 AI 从"凭记忆猜测"变成了"按文档查询"。幻觉率明显下降。
conventions.md 的反模式教学
除了正向文档,我们还有一份 conventions.md,用"错误示例 vs 正确示例"的对照方式,展示常见的违规写法。比如:
- ❌ 业务模块间直接 import → ✅ 用 ARouterManager / ServiceManager
- ❌
Gson().fromJson()→ ✅GsonUtil.jsonToBean()+ try-catch - ❌ 主线程网络请求 → ✅ Observable 自动线程切换 / HttpCallback 手动 IO 线程
这种"反面教材"式的呈现,对 AI 的效果比纯正向陈述更好------AI 更容易记住"不要这样做"的明确边界。
7. 自查清单:AI 生成代码后的质量自检闭环
规则写得再多,AI 也不一定每次都遵守。我们的经验是:规则定义"应该怎么做",自查清单保证"确实做到了" 。
car_project_rule.md 的末尾有一份 23 项自查清单,每项都是一个可验证的检查点:
| # | 检查项 |
|---|---|
| 1 | 引用的类/方法在项目中真实存在?(搜索确认) |
| 2 | 模块依赖方向正确?(禁止 import 无依赖关系的模块包) |
| 3 | 业务模块间无直接 import? |
| 4 | 新 Activity 继承 ChannelPlayActivity? |
| 5 | 新路由四处注册? |
| 6 | SP 通过 SPHelper(优先)或 SharedPreferUtil? |
| 7 | JSON 解析使用 GsonUtil + try-catch? |
| ... | ... |
| 23 | contentDescription 已设置? |
配合 TV 焦点规则,还有额外的 12 项专项检查(T1T12);配合性能技能,有 17 项性能检查(P1P17)。
自查清单的设计有几个原则:
- 可验证:每项检查的答案只能是"是"或"否",不存在"差不多"
- 可搜索 :大部分检查项可以直接通过 grep 验证(如搜索
Gson()检查是否有违规使用) - 分层次:通用检查 + 专项检查,不同场景加载不同的检查项子集
在实践中,自查清单还有一个额外的好处:它可以作为团队 Code Review 的辅助 checklist,人机共用。
8. Git Hook 集成:提交追踪的知识沉淀
我们在 .git/hooks/post-commit 中集成了 Qoder CLI:
bash
#!/bin/sh
# BEGIN Qoder AI tracker
"qodercli" commit --hook 2>/dev/null || true
# END Qoder AI tracker
每次 git commit 后,这个 hook 会调用 Qoder CLI 记录本次提交的信息。这样做的目的有三:
- 追踪 AI 参与度:哪些提交是 AI 辅助完成的?占比如何?
- 知识反哺:AI 参与的提交如果后续发现 bug,可以回溯到对应的 prompt 和上下文,定位是规则没写好还是 AI 没遵守
- 规则效果评估:结合代码质量指标(Crash 率、bug 密度),评估规则体系的实际效果,找到需要加强的约束维度
这个设计目前还比较轻量,但方向是对的------规则体系本身也需要迭代,而迭代需要数据。
9. 待优化点
坦诚地说,当前的规则体系还有很多可以改进的地方:
References 自动生成。 目前每份模块文档都是手动维护的。理想情况下,应该有一个脚本扫描模块的目录结构和 build.gradle,自动生成基础骨架,人工只补充核心类的详解。否则随着模块增加,维护成本会线性增长。
规则冲突检测。 当 car_project_rule 和 tv_focus_rule 对同一件事有不同约束时(比如 Handler 的使用方式),目前靠 AI 自行判断优先级。一旦规则多了,冲突不可避免,需要一套显式的优先级或合并机制。
自动化测试。 很多自查清单里的检查项其实是可以通过静态分析工具自动检查的。比如"是否使用了 Gson() 而非 GsonUtil"、"是否硬编码了 dp/sp 值"。把这些检查做成 lint 规则或自定义脚本,可以在 AI 生成代码后立即给出反馈,不依赖 AI 的"自觉"。
规则版本管理。 规则文件在 git 中随项目代码一起版本管理,但当多个团队成员同时调整规则时,还没有合并冲突的解决规范。规则变更的影响面评估(改了这条规则会影响哪些模块的 AI 生成质量)也缺乏工具支撑。
效果度量体系。 目前只有 Git Hook 在做基础的提交追踪,还缺少系统性的效果度量------比如 AI 生成代码的一次通过率、修改轮次分布、不同规则加载方案的效果对比等。
这些点的优先级取决于团队规模和 AI 使用深度。小团队可以先忽略,几十人的团队可能需要认真考虑。
10. 总结
回顾最近的实践,我们认为一个核心认知是:AI 辅助开发的效果,上限不是模型的能力,而是你给它的上下文设计。
模型本身的推理能力和代码生成能力已经够强了。真正拉开差距的,是你能不能把项目的隐性知识(架构约束、命名约定、反模式、历史踩坑)结构化地组织起来,让 AI 在正确的时刻、以正确的方式获取到正确的信息。
我们的三层体系(调度层 → 约束层 → 参考层)+ 否定词保护 + References 反幻觉 + 自查清单闭环,是这个思路的一个具体实践。它不是银弹,但确实让 AI 在复杂 Android 项目中的可用性提升了一个台阶。
如果你也在做类似的事情,希望这些经验能帮到你。如果你们有更好的做法,也欢迎交流。
本文基于一个真实 Android 车载项目的 AI 辅助开发实践撰写,涉及的具体包名基于代码安全性问题已做泛化处理。