18-模块三-AI编码规范体系 第18讲-规范文件的架构 - 项目上下文 目录结构 编码标准的结构化表达

1 阅读17分钟

模块三-AI编码规范体系 | 第18讲:规范文件的架构 - 项目上下文、目录结构、编码标准的结构化表达

开场:为什么“写了很多字”,AI 仍然生成不合群代码

很多团队的第一版规范是 README 里随手追加的几段话:技术栈介绍、如何启动、再加几句“请注意分层”。对人类新同学,这勉强够用;对 AI 代理,这往往不够,因为代理需要的是 可定位、可执行、可组合 的结构化信息。更麻烦的是,规范一旦超过一定长度,如果缺少 稳定的章节骨架,模型会只“记住”开头几段,后面的安全与测试要求被悄悄忽略。

本讲给出一套可复用的 六大支柱 架构:项目上下文、仓库结构、架构规则与设计模式、编码标准、测试要求、安全与纪律。你会学到每一节应该怎么写、常见模板是什么、以及如何把 CodeSentinel 的规范写成一份 可直接放进仓库 的完整文档。我们还会讨论:结构化规则如何提升生成质量,以及如何用 前后对比指标 验证规范真的有效。最后列出 写 AI 编码规范时的典型错误,帮你避开“越写越长但越来越没用”的陷阱。


全局视角:六大支柱与信息 hierarchy

1. 结构化规范的层次模型

flowchart TB
  P1["① 项目上下文<br/>类型/栈/版本"] --> P2["② 仓库结构<br/>目录职责"]
  P2 --> P3["③ 架构规则<br/>模式/边界"]
  P3 --> P4["④ 编码标准<br/>格式/日志/异常"]
  P4 --> P5["⑤ 测试要求<br/>分层/覆盖/命名"]
  P5 --> P6["⑥ 安全与纪律<br/>密钥/合规/评审"]
  P6 --> OUT["AI 生成代码质量提升"]

2. 规范如何进入代理的决策链(简化)

flowchart LR
  S["结构化规范文档"] --> E["抽取 MUST 条目"]
  E --> C["合并工具规则文件"]
  C --> M["模型生成补丁"]
  M --> V["本地验证命令"]
  V --> R["PR 评审对照规范"]
  R --> K["合并主干"]

3. CodeSentinel 规范与 Clean Architecture 的对照关系

flowchart TB
  subgraph Doc["规范文档章节"]
    D1["上下文:Python FastAPI"]
    D2["结构:domain/app/..."]
    D3["架构:端口适配器"]
    D4["编码:ruff/logging"]
    D5["测试:domain 离线"]
    D6["安全:无密钥"]
  end

  subgraph Code["codesentinel-clean-lab"]
    C1["domain"]
    C2["application"]
    C3["infrastructure"]
    C4["presentation"]
    C5["tests"]
  end

  D2 --> C1
  D3 --> C2
  D3 --> C3
  D3 --> C4
  D5 --> C5

核心原理:六大支柱分别解决什么问题、怎么写才有效

支柱 ①:项目上下文(Project Context)

目标:让代理在第一次生成代码前就知道“这是什么系统”,避免用错框架与语言特性。

应包含

  • 项目类型:单体服务、微服务之一、库、CLI、批处理作业等;
  • 技术栈:Python 版本、Web 框架、ORM、消息系统、主要部署方式;
  • 运行环境假设:是否需要 Docker、是否有 GPU、是否只允许 Linux;
  • 依赖管理:uv/poetry/pip,锁文件策略。

写作要点:用短句列出事实,不要写历史故事。上下文段落建议控制在 20~40 行 内。

模板示例

## 1. 项目上下文
- 项目类型:后端服务(HTTP API)
- 语言运行时:Python 3.12+
- Web 框架:FastAPI
- 持久化:PostgreSQL(SQLAlchemy)
- 事件:Redis Streams(教学替代 Kafka)
- 依赖管理:pip + requirements.txt(教学仓库)
- 部署:Docker Compose(本地一体化)

支柱 ②:仓库结构(Repository Structure)

目标:让代理知道文件该放哪,减少“随手新建 util.py”的灾难。

应包含

  • 顶层目录树说明;
  • 每个目录允许出现什么、禁止出现什么;
  • 新功能落地路径(先端口后用例再实现)。

写作要点:结构说明要与真实目录一致;若目录变更,必须同步更新,否则模型会生成“看起来很对但路径不存在”的 import。

模板示例

## 2. 仓库结构
- `app/domain/`:聚合、值对象、领域异常、领域事件
- `app/application/`:用例、端口(Protocol)
- `app/infrastructure/`:ORM、仓储实现、外部系统集成
- `app/presentation/`:FastAPI 路由、DTO、错误映射
- `tests/`:测试代码;领域测试与集成测试分文件

支柱 ③:架构规则与设计模式(Architecture Rules & Patterns)

目标:把架构从“愿景”变成 可违反就可见 的边界。

应包含

  • 依赖方向与分层图(可用 Mermaid);
  • 允许的设计模式(端口适配器、仓储、领域事件);
  • 明确禁止(跨层 import、领域层 IO、路由内业务规则)。

写作要点:每条规则尽量 可检测。例如“禁止 presentation import infrastructure 的具体类”比“保持整洁架构”更有效。

模板示例

## 3. 架构规则(MUST)
- MUST-001:依赖方向 presentation → application → domain;infrastructure 实现 application ports
- MUST-002:domain 不得依赖 FastAPI/SQLAlchemy/Redis SDK
- MUST-003:LLM 调用只能出现在基础设施适配器或明确标注的 application 服务中,不得进入 domain

支柱 ④:编码标准(Coding Standards)

目标:统一可读性与可维护性,让生成代码在风格上像同一人所写。

应包含

  • 格式化与 lint 命令;
  • 命名约定;
  • 日志规范(结构化字段、级别);
  • 异常处理策略(哪里抛、哪里翻译、哪里记录)。

写作要点:编码标准不要复制整本 PEP,只选团队 最常出分歧 的 10~20 条。

模板示例

## 4. 编码标准
- 格式化:`ruff format`
- 静态检查:`ruff check`
- 命名:函数用动词短语,类用名词;避免无意义缩写
- 日志:使用模块 logger;关键字段包含 `review_id`/`trace_id`
- 异常:禁止 `except Exception: pass`

支柱 ⑤:测试要求(Testing Requirements)

目标:让代理知道“完成”的定义包含哪些测试义务。

应包含

  • 测试分层策略;
  • 覆盖率目标(若你有);
  • 集成测试启动条件与跳过策略;
  • 测试数据与 fixture 约定。

写作要点:把“必须写哪些测试”与“如何运行”写在一起,降低代理跳过测试的概率。

模板示例

## 5. 测试要求
- 新增用例:至少 1 个 domain 或 integration 测试
- 领域测试:不得依赖 Docker
- 集成测试:需要 docker 时,若不可用必须 skip 并说明原因
- 命名:`test_<场景>_<期望>`

支柱 ⑥:安全与纪律(Security & Discipline)

目标:把安全默认内建到生成过程,减少“先上线再补”的侥幸心理。

应包含

  • 密钥管理;
  • 输入校验与输出编码;
  • 依赖漏洞治理(可选:扫描命令);
  • PR 纪律(小步、可回滚、必须贴验证结果)。

写作要点:安全条款尽量 具体。例如明确“日志字段白名单”,比“注意隐私”更可执行。

模板示例

## 6. 安全与纪律
- 禁止硬编码密钥;使用环境变量
- SQL 必须参数化
- 对外错误响应不得返回堆栈
- PR:描述包含运行过的命令与结果摘要

综合应用:六大支柱的依赖关系与写作顺序

推荐的写作顺序不是随意的:先写 上下文与结构,因为它们是“地图”;再写 架构 MUST,因为它们是“交通规则”;然后写 编码标准,解决日常风格一致;接着写 测试要求,定义完成定义;最后写 安全与纪律,把红线钉死。若顺序颠倒,常见后果是:安全要求写得很早,但目录结构还没定义,代理不知道该把密钥管理代码放在 infrastructure 还是 presentation,最终又是一次跨层混乱。

另一个实践技巧是 每一根支柱都对应一个 owner:不是一个人写完所有内容,而是每个 owner 只对自己那一块负责。这样规范文档会像模块化系统一样演进,而不是变成某个架构师的独白。评审时也可以分块通过,降低一次性大文档评审的心理成本。

面向 AI 的“信息密度”:如何避免堆砌却不说清

人类读者能容忍一点文学性,但 AI 代理对 信号密度 更敏感。建议每个小节遵循格式:标题下一行是“目的”,接着是“MUST/SHOULD 列表”,最后是“VERIFY 命令”。中间不要插入大段背景,除非背景会改变规则解释。需要背景时,用链接指向 ADR 或设计文档,把主规范保持在高压缩率状态。

规范与示例代码的关系:示例要“朴素而正确”

示例代码是双刃剑:好的示例能稳定引导生成;坏的示例会教会模型抄捷径。示例应尽量 朴素:展示正常路径,不要堆满高级技巧;同时必须 正确:示例本身应能通过 CI。若示例只是为了说明概念,建议明确标注“伪代码,不可直接运行”,否则代理会把它当真相。

多语言/多模块仓库的扩展:六大支柱是否仍然适用

适用,但需要增加一层 模块索引:在支柱②里用表格列出每个子模块的根路径、入口命令、测试命令。支柱③的 MUST 可能要分“全局 MUST”和“模块 MUST”。否则 monorepo 里会出现“规范说 domain 禁止 IO,但某数据科学子模块其实允许 pandas IO”的合法例外。例外必须显式写出,并给出范围边界,避免被滥用。

CodeSentinel 场景下的特别补充:LLM 相关条款应独立成子节

由于 CodeSentinel 贯穿项目包含 LangChain/LLM 适配,建议在支柱③或单独附录增加 LLM 适配规则:提示词模板位置、温度与采样策略谁负责、审计日志记录什么、如何避免把用户数据写入不该写的存储。LLM 条款不要散落在安全章节里,否则评审时很难找全。

与人力资源流程结合:规范是新同学 on-call 前的门槛

把阅读六大支柱规范加入 on-call 或独立负责模块前的 checklist,可以显著减少“第一次上线就踩架构边界”的事故。对 AI 代理也同样成立:新会话第一件事应是确认规范版本(git sha 或文档日期),避免用过期规则指导新代码。


代码实战:CodeSentinel《AI 编码规范》完整示例(可直接落地)

下列文档可作为 docs/AI_CODING_STANDARD.md 或拆入 AGENTS.md 的主体章节。为教学清晰,这里用中文撰写;真实企业可按内外部读者混合中英文。

# CodeSentinel AI 编码规范(结构化版)

## 1. 项目上下文
CodeSentinel 是 AI 驱动的代码审核与架构治理平台教学实现:Python 3.12+、FastAPI、
PostgreSQL、Redis Streams、pytest、ruff。本地验证以 `docker compose` 为可选增强。

## 2. 仓库结构(权威)
- `app/domain/`:纯领域逻辑与事件;禁止 IO
- `app/application/`:用例编排与端口
- `app/infrastructure/`:ORM、仓储、Redis 发布器、DB 引擎工厂
- `app/presentation/`:路由与 HTTP 错误映射
- `tests/``test_domain.py`(离线),`test_integration.py`(可依赖服务)

## 3. 架构规则(MUST)
- MUST-101:展示层只能调用应用层用例;不得直接访问 ORM Session
- MUST-102:应用层依赖 domain + Protocol;不得依赖具体基础设施类
- MUST-103:领域层不得出现 LLM SDK、HTTP Client、数据库 API
- MUST-104:领域事件由聚合产生;发布在成功持久化之后(教学路径)

## 4. 编码标准
- 使用 `ruff format``ruff check`
- 异常映射:`KeyError`→404,`InvalidTransitionError`→409,`ValueError`→400(与项目一致)
- 日志:结构化键值;禁止打印密钥

## 5. 测试要求
- 修改聚合状态机:必须更新 `test_domain.py`
- 修改 HTTP 行为:必须更新集成测试或新增用例
- 不得引入依赖真实外网的测试

## 6. 安全与纪律
- 禁止把 OpenAI Key 写入仓库
- 输入校验:对路径参数与 body 字段做类型与范围约束
- PR:列出 `ruff``pytest` 结果

## 7. 变更流程
- MUST 变更需要 Tech Lead 评审
- gotchas 允许快速补充,但不得与 MUST 冲突

生产环境实战:结构化如何提升质量,以及如何度量

1. 机制解释:为什么“结构化”会提升 AI 生成质量

结构化规范带来三类收益。第一,检索更准:模型更容易匹配到与当前文件相关的 MUST 条目(尤其配合工具侧按路径注入规则)。第二,约束更硬:条目化文本更接近“规范即代码”,可被脚本与人类同时引用。第三,评审更省:评审者可以快速对照编号指出问题,减少情绪化争论。

2. 指标建议:用前后对比验证规范有效

你可以选一组简单指标,在引入结构化规范前后各观察四周(样本量小也要坚持记录):

  • 架构违规密度:每千行新增代码中,跨层 import、路由内业务判断等待处理评论数。
  • CI 首次通过率:代理生成提交首次通过 CI 的比例。
  • 安全告警数:密钥扫描、依赖扫描、或自定义规则命中数。
  • 测试缺口率:新增用例缺测试的 PR 占比。

下表是“教学示例数据”,用于说明如何呈现,不代表真实实验结论:

指标前四周(示例)后四周(示例)
架构违规评论 / 千行3.11.4
CI 首次通过率62%81%
密钥扫描告警20
缺测试 PR 占比28%12%

真实团队应以自己的数据为准,关键是 统一口径固定周期

3. 结构化规范的维护节奏

建议双周做一次 10 分钟维护:核对目录、核对命令、核对 MUST 编号是否仍准确。每月做一次 规范回顾:把 review 里重复出现三次以上的问题上升为新 MUST 或新 gotchas。

4. 与 CodeSentinel 产品路线对齐

CodeSentinel 的目标是把规范 从文档推进到自动检查。因此 MUST 编号越早引入越好:未来规则引擎可以直接映射 MUST-103 到具体 AST 规则或正则规则。文档结构不要频繁改名,否则检查器版本会难以兼容。

5. 多角色协同:架构师、TL、安全、测试如何分工

架构师维护 支柱③ 与 MUST 体系;TL 维护 支柱④⑤ 与 CI 命令一致性;安全同事审核 支柱⑥;测试负责人定义 覆盖率策略与测试分层。AI 代理不是替代这些角色,而是把他们的共识固化成文本与自动化。

6. 对内对外的两套读者:如何减少信息过载

如果仓库对外开源,可将敏感流程放到内部 wiki,在公开规范里保留 MUST 与 VERIFY 命令即可。对内完整版可以更长,但仍建议分文件:公开短、内网长,通过链接贯通。

7. 规范版本化:给文档加 Standard-Version 与变更记录

建议在规范文档顶部增加版本号与日期,例如 Standard-Version: 2025.03.1。每次 MUST 变更递增版本,并在文末维护简短变更记录:改了什么、为什么、影响哪些模块。对 AI 代理来说,版本号能帮助它判断“我缓存的旧规则是否仍有效”;对人类来说,版本号是审计与合规的重要线索。

8. 与培训结合:把六大支柱映射到一小时工作坊

一小时工作坊可以这样切:十分钟讲上下文与结构,二十分钟讲架构 MUST 与案例,十分钟讲编码与测试命令,十分钟讲安全红线,最后十分钟做小组练习:给一段坏代码,要求学员指出违反哪条 MUST。工作坊结束把练习题的答案合并进规范附录,规范会越来越贴近真实痛点。

9. 与研究结合:把实验记录留下,而不是只留结论

如果你做了前后对比实验,请把方法写下:样本区间、统计口径、是否包含周末发布、是否剔除紧急热修。否则两个月后没人解释得清“81% 是怎么来的”。研究记录不必放进主规范,可以放在 docs/research/ 并链接。

10. 反模式:把规范写成“惩罚条款”

规范的目标是降低系统熵,不是制造恐惧。若全文充满“严禁、禁止、扣分”而没有“如何正确做”,代理与人类都会倾向绕过。正确做法是每条禁止项配一条推荐路径:禁止路由查库,推荐用用例 + 仓储;禁止吞异常,推荐边界映射 + 结构化日志。


常见错误清单:写 AI 编码规范时最容易失败的 12 个点

  1. 只写原则不写命令:模型无法自证完成。
  2. 目录结构与真实仓库不一致:生成代码 import 全错。
  3. MUST 过多:超过二十条后执行率下降,建议分层级。
  4. 把历史背景写很长:浪费上下文,关键约束反而被截断。
  5. 安全条款空洞:没有可检测行为,等于没有。
  6. 测试要求不区分层级:导致代理乱写集成测试或乱 mock。
  7. 规范与 CI 不一致:团队失去信任,规范形同虚设。
  8. 没有编号:评审难以引用,检查器难以映射。
  9. 把示例代码写得太“聪明”:模型照抄捷径,破坏边界。
  10. 忽略 Windows 路径与脚本差异:降低本地可复现性。
  11. 忽略数据合规:日志、提示词、标注数据各自有不同要求,混写会误导。
  12. 从不复盘:规范文档一年不改,必然腐烂。

本讲小结:脑图

mindmap
  root((结构化规范))
    上下文
      栈
      版本
      环境
    结构
      目录
      边界
    架构
      MUST
      模式
    编码
      ruff
      日志
      异常
    测试
      分层
      覆盖
    安全
      密钥
      输入输出
    度量
      前后对比
      固定口径

思考题

  1. 你的项目六大支柱里,哪一根最薄弱?为什么?
  2. 你会把 MUST 编号交给谁维护?如何避免编号体系混乱?
  3. 如果规范变长,你更倾向于拆文件还是缩短句子?取舍标准是什么?

下一讲预告

下一讲进入 企业级 AI 编码规范方法论:安全规则清单、测试门槛、反模式黑名单、规范变更审批流,并在 CodeSentinel 中实现可配置的 SecurityRuleChecker(YAML 驱动),把“写下来的规范”推进到“能自动拦截”的治理闭环。


深度补充:把每根支柱写成“可教学、可迁移、可检查”的三段式

建议你为每一个 MUST 条目使用统一的三段式:意图(为什么)、规则(做什么)、验证(怎么证明)。例如 MUST-103 可以展开为:意图是保持领域纯性与可测试性;规则是禁止 import 任何 LLM SDK;验证是在 CI 运行自定义 import 检查或在 pre-commit 里扫描 app/domain。三段式对 AI 与人类都友好,因为它把“原因—行为—证据”一次性说清,减少误读。

在跨团队推广时,三段式还能帮助非 Python 团队迁移:他们只要替换验证命令与目录名,意图与规则仍旧成立。架构治理最难的不是写规范,而是让规范在不同上下文里仍然可执行。结构化表达降低迁移成本,也降低培训成本。新人不必读完所有历史邮件,只要读懂 MUST 表就能开始贡献。代理也不必读取冗长背景,只要命中条目就能自我约束。

最后,结构化规范要与 ADR 形成互补:MUST 是“现在必须怎么做”,ADR 是“当时为什么这么做”。当 MUST 变更涉及取舍,务必引用 ADR 编号,避免未来同事误以为规则是随意拍脑袋。这样做短期内多写几个字,长期会少很多次无意义争论。CodeSentinel 作为治理平台,未来可以把 MUST 与 ADR 的链接关系也纳入知识图谱,实现变更影响分析。你从今天起把编号与链接写对,就是在为未来的自动化治理预埋数据。

再补三条“落地动作”,帮助你从读完到做完:第一,本周就选三件最痛的返工问题,把它们改写成 MUST 条目并编号;第二,把 ruffpytest 命令与 CI 对齐后写进支柱④⑤;第三,找两位同事交叉朗读规范,标记所有歧义句并改写为可测试句。三条做完,你会明显感觉代理输出更稳定。稳定不是偶然,是上下文被结构化之后,模型更少自由发挥空间,更多沿着团队共识前进。共识被写清,就更容易被自动化继承。自动化继承越深,架构师越能把时间花在真正的取舍上,而不是重复解释同一条边界。长期下来,团队会形成“规范驱动交付”的文化,而不是“交付后再补规范”的被动模式。文化一旦形成,工具链只是放大器:同样的 CodeSentinel,在文化弱的团队里只能偶尔提醒,在文化强的团队里会成为默认门禁。你要做的,是从文档结构开始,把文化一点点砌起来。规范写得好,团队就少走弯路;团队少走弯路,平台治理才有抓手。把六大支柱当作产品维护,它会持续复利。这份长期收益往往被低估,但最值得投资。开始行动。