跳到主要内容
左猫娘右猫娘

自用AI代码质量规范

· 阅读需 19 分钟
Heng_Xin
ここから先は一方通行だ!

我已经受不了AI发挥了, 说好的把AI当人一样用呢? 但它做的根本就不是人做的

为了能许愿式编程(我是老板, AI你自己揣摩吧), 需要用 Hook 去限制它

本笔记用于给ai生成skill的人类编写的大纲

一、总览​

skill 定位: 一个全能的、一次性的代码质量红线安装与完善工具, 发挥ai具体情况具体分析的能力, 为项目定制、补充符合我需求的代码质量检查工具. 必须由用户主动触发

包括:

  • 代码质量
    • 编码规范
      • 架构推荐
      • 格式化
      • lint
      • 自定义规则
      • 注释
      • 第三方库推荐
    • 文档规范
    • 项目AI上下文
    • github特有: 工作流CI
    • github特有: 协作规范
  • 测试
    • 仅后端API的测试 (区分使用假数据 和 真数据)
    • 仅前端请求后端API的测试
    • 仅前端UI的测试 (使用假数据)
    • e2e的测试
    • 性能测试
    • 构建测试 & 历史兼容性测试
  • 元门禁 (对于这些门禁的代码质量检查)

特别的, 本地开发仅会对当前工作区的diff内容进行代码质量检查和测试. 另外禁止一边开发一边测试. 必须一次性开发完成后再跑一轮对应测试 (否则效率太低了)

评级:

  • 警告: 表述需要注意, 静态工具无法断定的. 比如 内容的关联变更. 这是需要 review 的 (需要汇总为一个待review文件, md + json文件, 方便人与机器阅读), 这部分仅警告. 不会拦截.

  • 错误: 明确被工具扫描到的问题, 如果不修改则会: (Agent运行时: 任务未完成, 需要返工)、禁止push、CI拦截. 同理会产出md/json

Tip

如果下文没有明确提及, 则默认都是 错误 评级!

二、代码质量​

2.1 编码规范​

技术选型, 后端推荐 py + FastApi (协程) (必须使用uv包管理), 前端只能使用 React + Ts (必须使用pnpm包管理), 禁止任何的 mjs/js 出现 (除非是框架工具等)

2.1.1 架构推荐​

对于快速开发, 应优先复用已有代码, 复用顺序为:

本项目已有代码 > 标准库 > 已使用的第三方库 > 新增第三方库
text

引入新的第三方库需要人工决策, 记为 Warning.

2.1.1.1 接口与实现​

业务模块对外只暴露稳定的公共接口, 调用方不应依赖具体实现.

优先使用简单的函数式接口, 将校验、业务流程与具体实现分离:

async def get_user_data(user_id: int) -> UserData:
if not _validate_user_id(user_id):
return UserData.IdErr

return await _find_user_by_id(user_id)
py

调用方只依赖 get_user_data, 不关心 _find_user_by_id 的具体实现.

实现细节应放入 impl/ 或其他明确的内部目录:

user/
├── init.py # 公共接口
└── impl/
├── database.py # 数据库实现
└── mock.py # 假数据实现
text

其中:

  • 公共代码只能依赖公共接口
  • 禁止跨模块直接依赖其他模块的 impl/
  • impl/ 内部可以依赖本模块其他实现
  • 需要替换实现时, 应尽量只修改模块内部代码
2.1.1.2 API 与数据来源分离​

需要明确区分:

API
├── 纯数据 / 假数据实现
└── 真实依赖实现
text

业务逻辑不应直接绑定数据库、远程服务等具体依赖, 以便分别进行无真实依赖测试和真实依赖测试.

2.1.1.3 依赖方向​

项目整体优先保持 有向无环 依赖:

上层业务
↓
公共模块
↓
底层实现
text

禁止无明确边界的循环依赖和网状依赖.

跨模块导入时, 默认只允许依赖目标模块的公共接口.

以下情况可以直接导入:

  • 工具库
  • 常量库
  • 类型定义库
  • 明确声明为公共基础模块的代码

禁止直接导入其他业务模块的内部实现.

例如:

aLib/
├── init.py
└── impl/
├── a.py
└── ai.py

bLib/
├── init.py
└── impl/
└── b.py
text

允许:

aLib/init.py      → aLib/impl/a.py
aLib/impl/ai.py → aLib/impl/a.py
bLib/impl/b.py → aLib/init.py
text

禁止:

bLib/impl/b.py    → aLib/impl/a.py
bLib/impl/b.py → aLib/impl/ai.py
text
2.1.1.4 目录规模​

单个目录建议不超过 6 个文件.

超过 6 个文件时:

  • 默认 Warning
  • 若目录职责已经混杂, 则为 Error
  • 若确有合理原因, 可以申请豁免

豁免必须记录:

{
"path": "src/user",
"reason": "该目录承担同一职责, 拆分后反而增加依赖复杂度",
"expires_on_change": true
}
json

豁免信息纳入 Git, 并在该目录再次发生变更时重新检查.

2.1.1.5 前后端接口对应​

前端请求层与后端路由层应保持清晰的一一对应关系.

例如:

frontend/api/user.ts
↕
backend/router/user.py
text

同一业务模块的前端请求接口, 应能在对应的后端路由中找到.

若一个模块无法建立明确对应关系, 应进行架构检查.

部分情况下可以配置白名单 (比如通用权限检查等接口)

2.1.2 格式化​

项目应该需要成熟的第三方格式化工具.

强制要求, 大括号和换行规范如下:

int main() {  // 这种 `{` 的写法; 禁止 `\n{`
if (true) // 禁止缩行, 如 if (...) todo
print("Good");
else
print("Bad");
}
cpp

行长度 120 字符. 缩进只能使用4空格, 注释: 空格一格 (连续2行单行注释, 使用右对齐)

逻辑代码 (如后端、ts), 单文件限制 300 行 (格式化后)

前端/UI代码, 单文件限制 500 行 (格式化后)

Note

调用层归一为脚本. 在 AI 执行完写入/Bash工具后调用 Hook

在 commit 前也会对 diff 的文件执行一次

Tip

可以提供一个默认排查git提交的脚本目录, 如 scripts/.hx_code_quality, 存放当前工作区的格式化过的文件的md5, 到时候直接看 md5 是否正确就知道哪些是已经格式化的, 哪些是没有覆盖的. 这样可以加快速度 (其他任务同理, 不再提及)

当commit了后, 就把对应的文件在 .hx_code_quality 的缓存中删除

2.1.3 lint​

使用现代的 lint 检查工具, 附上常见的现代检查规则即可. 必须要有类型检查.

2.1.4 自定义规则​

Python:

  1. 禁止在局部导入任何内容. 所有的导入只能在文件头部
  2. 普通文件禁止定义任何常量. 常量必须集中存放在常量文件夹

通用AST:

  1. 函数注释, 必须和参数、返回值对应, 如:
/**
* @brief 加法
*
* @param a
* @param b
* @return int
*/
int add(int a, int b);
cpp

如果函数内有diff, 那么它的注释可能需要变化(已经是双方都要同步变化). 需要警告

2.1.5 注释​

在日常代码编写中, 就要确保代码如注释的风格. 此处更多的是约束 函数签名等大范围的注释 (但是依旧全局适用)

  • 文件开头 禁止 大于 10 行的注释

  • 注释只说明代码本身无法表达的 意图、原因、约束和特殊情况, 不要重复代码行为

  • 优先解释 Why 而非 What; 简单、直观的代码无需注释

  • 注释必须简洁、准确并与代码同步, 避免无意义或过时的注释

  • 对于用户的决策, 应该引用其 note, 而不是长篇大论来龙去脉; (参考 skill: hx-agent-notes)

2.1.6 第三方库推荐​

具体情况具体分析, 引入第三方库必须要用户决策 (包管理的包出现diff, 是警告. 需人工评审)

2.2 文档规范​

Tip

所有的地方 (包括注释), 禁止 emoji 和中文标点, 统一使用 ASCII 标点

核心规则:

  1. 一篇文档只讲一个主题, 不要写成百科全书
  2. 当前事实和历史原因分开: 现在是什么放 reference/, 为什么这么做放 decisions/
  3. 不要重复写: 已有文档能更新就直接更新, 不要创建 xxx-v2.md
  4. 上层讲整体, 下层讲细节; 不要跨文档重复维护同一知识
  5. 文档写"规则、约束、行为、契约", 不要写大量思考过程和废话
  6. 失效文档移到 archive/, 不要和当前文档混在一起
docs/
├── tutorials/ # 怎么做
├── reference/ # 现在是什么、怎么用
├── reference/api # 契约, 里面存放如: user.yaml/user.md 的文件, 其中 yaml 是API契约, 会被门禁检验
├── architecture/ # 整体怎么设计
├── decisions/ # 为什么这么设计
└── archive/ # 废弃文档, 如何判断废弃? 它描述的东西现在还成立
sh

文档行数需要在 1500 行内

2.3 项目AI上下文​

上下文定义:

项目上下文=AGENTS.md+skill引导注入项目上下文 = AGENTS.md + skill引导注入

参考 dsh, 我们要求 AGENTS.md 小于 150 行, 大小小于 16KB

另外, 我们要求每一个存在 README.md 的地方, 必须编写一个 AGENTS.md (反之同理)

AGENTS.md 按照披露式加载, 仅有该目录用到的上下文才需要写入 AGENTS 中

因此有质量检查红线:

  • 所有文件的dfs路径上, ∑AGENTS上下文+skill上下文<=64KB\sum{AGENTS_{上下文}} + skill_{上下文} <= 64 KB

2.4 工作流CI​

Tip

Github工作流CI, 在触发过程中, 还可以使用机器人账号, 进行评论指定代码位置, 然后把总结写到 PR/commit 的评论上.

2.4.1 Push 触发​

用户提交触发, 分为3个工作流:

他们都是扫描 diff级别, 并且不会短路, 一次性扫描所有的问题.

代码质量工作流:

  1. 格式化检查
  2. lint检查
  3. 自定义规则检查
  4. 注释检查
  5. @todo AI CR: 警告级别的内容, 筛选出真问题
  6. @todo AI CR: 基于 diff 上下文 和 commit 语义的代码评审

文档规范工作流:

  1. 无 emoji 和中文标点
  2. 文档行数检查
  3. 文档命名检查
  4. AI 上下文检查: AGENTS.md 与 README
  5. AI 上下文检查: sum(AGENTS.md) + skill引导注入
  6. AI 上下文检查: notes 双链 (参考对应skill)
  7. @todo AI CR 文档 review (暂时没有)

构建测试:

  1. 对应项目需要进行构建, 确保编译能提供. 然后基于此产物走 [测试工作流] (与下面步骤并行)
  2. 兼容性测试 (如有 docker 更新后, 是否能正确启动? 不会和历史版本冲突)

测试工作流:

  1. 后端 无真实数据 的测试
  2. 后端 连接测试数据库 的测试 (ci 可能不好实现)
  3. 前端 API 对接假后端数据 的测试 (UI 测试)
  4. 前端 API 对接真后端数据 的测试 (前端接口测试)
  5. 前后端联调 E2E 测试

2.4.2 PR 触发​

对于测试工作流, 会触发全量测试, 其他和 Push 触发一致

2.5 协作规范​

需要定义:

.github/
├── ISSUE_TEMPLATE/ # Issue 模板 (必须提供: Bug 反馈、功能建议)
├── PULL_REQUEST_TEMPLATE.md # PR 模板
└── CODEOWNERS # 自动分配 Review
CONTRIBUTING.md # 协作说明
sh

三、测试​

测试必须按照 被测试的业务模块 组织, 并在模块内部区分不同测试层级.

3.1 测试层级​

不同测试只验证自己的职责, 不应重复承担其他层级的测试职责:

  • unit: 测试独立业务逻辑, 不依赖真实外部资源
  • api/mock: 测试后端 API, 使用假数据和假依赖
  • api/real: 测试后端 API, 使用测试环境中的真实依赖
  • frontend/api: 测试前端 API 调用、参数处理和异常处理
  • frontend/ui: 使用假数据测试页面展示和交互
  • e2e: 验证完整用户流程以及前后端协同

API 契约应作为前后端接口的统一规范来源. 契约发生变化时, 必须触发对应的契约测试以及相关模块测试.

3.2 测试入口​

统一提供测试入口:

具体实现可以根据项目技术栈选择不同测试工具, 但测试入口和触发规则应保持统一.

3.3 Diff 影响测试​

测试默认按照本次 Diff 选择受影响的测试, 不应每次都执行全量测试.

架构时必须建立:

代码 → 业务模块 → 测试
text

例如:

backend/user/service.py
↓
user
↓
┌──────┼────────┐
↓ ↓ ↓
unit API E2E
↓
frontend/api
text

test:affected 应优先使用依赖关系分析确定影响范围, 路径规则作为兜底.

测试选择遵循:

依赖关系分析
↓
业务模块关系
↓
API / 契约关系
↓
路径规则兜底
↓
无法安全判断
↓
全量测试
text

修改公共工具、公共类型、基础设施、构建配置等无法可靠判断影响范围时, 必须执行全量测试.

3.4 测试触发​

本地开发阶段, 禁止反复执行完整测试集.

AI 完成当前任务后, 根据最终 Diff 一次性选择并执行对应测试:

完成修改
↓
获取 Diff
↓
分析受影响模块
↓
选择测试
↓
统一执行
text

Push 时执行本次 Diff 影响的测试; PR 时执行完整测试集, 作为合并前最终检查.

四、元门禁​

skill 提供 (本身需要遵从代码质量规范)

每个规则设计时候必须:

  • 可单独测试
  • 有正例
  • 有反例
  • 输出稳定
  • 有唯一规则 ID
  • 有明确等级

方便结构化存储和PR中评论.

五、细节​

  1. Diff 级别 ≠ 只看 Diff 那几行:

    检查范围以 Diff 为入口, 但允许读取被修改文件 / 函数 / 类型 / 依赖关系的上下文

  2. Baseline:

    对于新项目我们可以使用这个规则, 对于一个旧项目, 直接引入规则会导致大量问题. 如果目前无法快速重构. 那边就需要区分 历史问题 与 新增问题

本文没有引用站内其它文档。

请作者喝奶茶:
Alipay IconQR Code
Alipay IconQR Code
本文遵循 CC CC 4.0 BY-SA 版权协议, 转载请标明出处
Loading Comments...