规则即代码——用 Rules 让 AI 自动遵守团队规范

📅 2026/6/29 17:51:34
规则即代码——用 Rules 让 AI 自动遵守团队规范
核心论点Rules 是三层漏斗中投入产出比最高的一层——写一次永久生效。但写 Rules 本身有门槛太泛了没约束力太细了维护不了。关键是找到刚好够用的粒度。Rules 是什么CodeBuddy 的 Rules 系统本质上是一个上下文注入器。你在.codebuddy/rules/下写的 markdown 文件AI 在编辑匹配的文件时会自动读入。# 规则文件的头部元数据---description:Python 代码规范globs:**/*.py# 匹配 Python 文件时自动加载alwaysApply:false# false 按 glob 匹配加载true 每次对话都加载---关键字段字段作用适用场景globs: **/*.py编辑 .py 文件时加载语言级规范日志、异常处理globs: **/*.tsx,**/*.vue编辑前端文件时加载前端规范组件结构、状态管理alwaysApply: true每次对话都加载项目级通用规范禁止硬编码、统一配置入口一个反面教材规则太泛等于没有规则Shop-Agent 项目最初只有一份通用规则——“遵循对应语言/框架的代码风格规范”、“配置文件外部化环境变量管理敏感信息”、“避免硬编码”。效果AI 确实不硬编码了但该重造轮子还是重造轮子。因为避免硬编码太泛了——用 os.getenv(‘REDIS_HOST’)也是没硬编码但它绕过了你项目里的Settings类。规则要精确到用项目中哪个具体组件做这件事而不是要遵循什么原则。正确写法三种规则类型经过 Shop-Agent 项目的反复迭代我们沉淀了三种有效规则类型 1禁止清单Forbidden List告诉 AI绝对不能做什么。这种规则最容易写也最立竿见影。# 禁止重复实现 ## 禁止事项 - 禁止新建 cache 类 → 用 src/modules/chat/core/redis_cache_service.py - 禁止直接调 openai.ChatCompletion.create → 用 src/modules/chat/core/llm_service.py - 禁止在 router 里写内联业务逻辑 → 必须在 core/ 下用 service 层 - 禁止硬编码配置API Key、URL、阈值→ 全部通过 src/core/config.py 的 Settings 读取 - 禁止 print() 打日志 → 用 structlog / logger - 禁止自创 JSON Schema 生成 → 用 Pydantic model_json_schema() - 禁止新增 pip install 依赖 → 先检查 requirements.txt 是否已有为什么有效AI 的默认行为是写通用代码禁止清单直接拦截了最常见的几种默认行为→不兼容路径。比如 AI 本能的写个 cache 类被第一条拦截后它就会去搜索或询问现有的缓存方案。类型 2组件清单Component Catalog告诉 AI项目里有什么可以用的。相比禁止清单的不能做 X组件清单是用 Y 来做。# 已注册可复用组件 ## 核心基础设施 | 组件 | 路径 | 用途 | API | |------|------|------|-----| | 配置管理 | src/core/config.py | 所有配置统一入口 | Settings() | | 限流器 | src/core/rate_limiter.py | 并发控制 | await rate_limiter.acquire() | | Redis 缓存 | src/modules/chat/core/redis_cache_service.py | 对话缓存向量缓存 | get/set/delete | | LLM 服务 | src/modules/chat/core/llm_service.py | 统一 LLM 调用 | await llm.chat() | | 工具注册 | src/modules/chat/core/tool_registry.py | 工具发现/调度 | ToolService.dispatch() | | 参数抽取 | src/modules/chat/core/param_extractor.py | 意图参数提取 | extract() | | 意图识别 | src/modules/chat/core/intent_recognizer.py | 意图分类 | recognize() | | 安全审查 | src/modules/chat/core/content_filter.py | 输入/输出过滤 | filter() | | 重排序 | src/modules/chat/core/reranker_service.py | 检索结果精排 | rerank() |关键设计最后一列写了 API 入口。AI 看到model/embed就知道调用方式不需要再去翻源码理解接口。类型 3编码约定Coding Convention编程风格的硬性规定。这类规则最容易被写成泛泛的遵循 PEP 8但真正有用的是项目中实际踩过的坑。# Python 编码约定 ## 异步 - 所有 I/O 操作必须用 async/await - 禁止用 time.sleep() → 用 asyncio.sleep() - 禁止用 requests 库 → 用 httpx.AsyncClient ## 日志 - 禁止 print()统一用 structlog / logger ## 异常处理 - 禁止吞异常bare except - 业务异常抛 BusinessException(code, message)不要抛裸 Exception - HTTP 异常统一由中间件捕获service 层不要 try/except HTTPException ## 类型 - 所有函数必须有类型注解含返回值类型 - disallow_untyped_defsTruemypy 配置规则粒度什么时候拆成独立文件从 Shop-Agent 的经验一个很实用的原则规则类型独立文件理由禁止清单独立会被频繁增删条目隔离修改组件清单独立内容多表格且需要自动化同步编码约定不独立和语言绑定自然放在python-code/RULE.mdc里项目通用规范独立alwaysApply: true跨语言所以我们项目的 Rules 目录最终是这样的.codebuddy/rules/ python-code/RULE.mdc ← 编码约定 通用 Python 规范 forbidden-list.mdc ← 禁止重复实现独立维护 component-catalog.mdc ← 组件清单自动化同步 project-rules/RULE.mdc ← 跨语言项目规范alwaysApply为什么要拆禁止清单和组件清单变更频繁加新组件、发现新的常见错误和编码约定放在一起会导致每次改一行就要 touch 整个文件——Git diff 噪音大AI 上下文也膨胀。拆开后各司其职维护成本最低。规则维护自动化而非手动这是很容易被忽略的一点。手写的组件清单两周后就过时了——新加了a2a_task_service、改了一个类的签名清单没跟上。方案脚本扫描 Automation 定时同步创建scripts/generate_component_catalog.py通过静态分析扫描src/下所有公共类/函数自动输出组件清单 markdown。然后用 CodeBuddy Automation 每周一自动跑名称: 同步组件清单 调度: FREQWEEKLY;BYDAYMO;BYHOUR9;BYMINUTE0 任务: 运行 scripts/generate_component_catalog.py 输出到 .codebuddy/rules/component-catalog.mdc这样组件清单永远和代码同步不需要人工维护。三条规则的生效场景对比场景禁止清单起作用组件清单起作用编码约定起作用AI 要加缓存逻辑拦截新建 cache 类提供 redis_cache_service-AI 要调大模型拦截裸调 openai提供 llm_service.chat()-AI 写了time.sleep(5)--要求 asyncio.sleep()AI 写了except: pass--禁止吞异常AI 要在 router 里写 50 行业务拦截router 内联--三条规则各管一片互不重叠。禁止清单和编码约定有少量交集比如都涉及不要做什么但禁止清单面向组件级复用编码约定面向语言级规范。立即可用的实操清单如果你只做一件事按这个顺序来先写禁止清单10 分钟列出你项目里最常见的前 5 个AI 重造轮子场景在编码规则里加 3 条硬约定5 分钟日志方式、异常类型、类型注解要求观察一周看看 AI 又出现了哪些想重复实现的倾向加到禁止清单第二周开始做组件清单有了前一周的积累你知道哪些组件最常被 AI 忽略别一开始就追求完整组件清单——那是第二周的事。第一周先把最痛的重造轮子场景堵住。核心要点规则要精确到用哪个组件不是遵循什么原则。禁止清单 组件清单 编码约定按这个优先级投入——禁止清单立竿见影编码约定是锦上添花。拆成独立文件——禁止清单和组件清单变更频繁不要和编码约定混在一起。组件清单用 Automation 自动同步——手写的清单两周就过时了。从最痛的前 5 条开始别追求大而全。AI 在你项目里最常重造的 5 个轮子写进禁止清单即可见效。