概述
系列定位:在项目中要搭建出完整的Harness Engineering四层文档体系,基本分为6步,接下来我会通过本系列共 6 篇文章,指导从零搭建 Harness Engineering 四层文档体系,最终实现从 BRD/PRD 到代码交付的一站式 AI 开发与自检闭环。
本篇定位:第 2 步------将 Step 1 定义的架构基线转化为 AI Agent 必须遵守的硬性规则,确保 AI 生成的代码符合项目技术栈和架构规范。
1. 什么是 Rules 层
1.1 定位
Rules 层是 Harness Engineering 四层体系中的约束层核心 ,位于 .qoder/rules/ 目录下。这些文件由 IDE 自动注入 AI Agent 的上下文,在所有任务中始终生效,无需手动加载。
1.2 与其他层的关系
Rules 层(本步) ← 硬性约束,始终生效,不可违反
Skills 层(Step 4) ← 操作手册,按需触发,教 AI "怎么干"
Wiki 层(Step 3) ← 知识库,按需加载,提供上下文
Changes 层(Step 5) ← 变更管理,保障交付质量
关键区别 :Rules 层是"不可逾越的红线 ",Skills 层是"推荐的操作步骤"。Rules 违反时 AI 必须修正,Skills 建议不采纳时 AI 可以调整。
1.3 为什么必须先建 Rules 层
| 场景 | 没有 Rules 层 | 有 Rules 层 |
|---|---|---|
| JSON 库选择 | AI 可能用 Jackson | AI 必须用 FastJSON |
| 数据库访问 | AI 可能直接注入 Mapper | AI 必须用 DalManager.of() |
| 事务管理 | AI 可能用 @Transactional | AI 必须用 TransactionTemplate |
| 日志方式 | AI 可能用 LoggerFactory | AI 必须用 @Slf4j |
| 模块依赖 | AI 可能产生反向依赖 | AI 必须遵守依赖方向 |
没有 Rules 层,AI 生成的代码会"看起来对"但不符合项目规范。
2. 需要创建的文件清单
.qoder/
└── rules/
├── always-on.md # 技术硬约束(始终生效)
├── agent-workflow.md # AI Agent 工作流约束
├── java-code-style.md # Java 代码风格规则
└── java-testing.md # 测试规则
共 4 个文件 ,全部位于 .qoder/rules/ 目录下。
3. 逐个文件编写指南
3.1 always-on.md --- 技术硬约束
定位
这是最核心的规则文件。AI Agent 在生成任何代码时都会参考此文件。每一条规则都是"违反即必须修正"的硬性约束。
编写策略:从架构基线推导规则
Step 1 中你定义了架构基线(技术栈、模块边界、数据流转)。现在将这些基线转化为可执行的规则:
架构基线(Step 1) → 硬性规则(本步)
────────────────────── ──────────────────
overview.md 技术栈表 → 第 1 节:技术栈锁定
boundaries.md 依赖方向图 → 第 2 节:模块依赖方向
overview.md 技术选型(HTTP/JSON) → 第 4~5 节:日志/HTTP 规范
boundaries.md 跨模块约束 → 第 6 节:数据库访问
data-flow.md 跨线程传播 → 第 9 节:traceId 传播
建议包含的约束条目(按编号)
| 编号 | 约束名 | 核心内容 | 推导来源 |
|---|---|---|---|
| 1 | 技术栈锁定 | 锁定 JDK/框架/库版本,禁止升级 | overview.md 技术栈表 |
| 2 | 模块依赖方向 | 依赖只能向上流动 | boundaries.md 依赖方向图 |
| 3 | 依赖注入 | 优先 @Resource,禁止字段级 @Autowired | 通用最佳实践 |
| 4 | 日志规范 | @Slf4j,占位符格式 | 通用最佳实践 |
| 5 | HTTP 调用 | 统一 HTTP 客户端 | overview.md 技术选型 |
| 6 | 数据库访问 | 统一访问方式 | boundaries.md 跨模块约束 |
| 7 | 线程池 | 统一线程池工厂 | 通用最佳实践 |
| 8 | 限流 | 统一限流框架 | overview.md 技术选型 |
| 9 | traceId 传播 | 跨线程显式传递 | data-flow.md 跨线程传播 |
| 10 | 事务 | 编程式事务 | 通用最佳实践 |
| 11 | 配置管理 | 配置中心统一管理 | overview.md 配置中心 |
| 12 | 注释语言 | 中文注释 | 团队约定 |
| 13 | 代码行数限制 | 单文件 ≤ 300 行,单方法 ≤ 80 行 | 阿里规范 |
编写模板
markdown
# Always-On Rules
这些规则在所有任务中始终生效,AI Agent 必须严格遵守。
## 1. 技术栈锁定
- JDK 1.8:禁止使用 var、record、text block 等 Java 9+ 语法
- Spring Boot {版本}:禁止升级到 3.x
- {JSON 库} {版本}:禁止引入其他 JSON 库
{...}
## 2. 模块依赖方向
依赖只能向上流动,严禁反向依赖或跨层引用:
{ASCII 依赖方向图}
- {模块 A} 不允许依赖任何项目内模块
- {模块 B} 只能依赖 {模块 A}
{...}
## 3. 依赖注入
- 优先使用 @Resource
- 新代码推荐构造器注入
- 禁止字段级 @Autowired 扩散
## 4. 日志规范
- 统一使用 Lombok @Slf4j,禁止 LoggerFactory.getLogger()
- 禁止 System.out.println() 和 e.printStackTrace()
- 日志使用占位符格式:log.error("描述,param={}", param, e)
- 禁止字符串拼接日志
## 5. HTTP 调用
- 统一使用 {HTTP 客户端} + {工厂类}
- 禁止直接 new {HTTP 客户端}
- 禁止使用其他 HTTP 客户端
## 6. 数据库访问
- 必须通过 {统一访问方式} 获取 Manager 实例
- 禁止直接注入 Mapper
- Entity 使用 @TableName + @Data + @Builder + @TableId(type = IdType.AUTO),字段使用 @TableField 映射蛇形列名
- 逻辑删除使用 yn 字段(0=有效, 1=删除)
## 7. 线程池
- 使用 {线程池工厂}({模块路径})
- 禁止裸 new ThreadPoolExecutor
## 8. 限流
- 使用 {限流框架}
- 禁止自行实现限流逻辑
## 9. traceId 传播
- 主线程使用 {注解} 注入 traceId
- 子线程使用 {工具类} 显式传递 traceId
- 禁止在线程切换时丢失 traceId 上下文
## 10. 事务
- 使用 {编程式事务工具}
- 禁止使用 @Transactional 注解
- 事务内异常必须 setRollbackOnly() + 返回 false
## 11. 配置管理
- 配置统一走 {配置中心}(namespace: dev1 / test1 / pre / prod)
- 禁止硬编码环境地址、数据库连接、密钥
## 12. 注释语言
- 类/方法/字段注释使用中文
- 注释需说明业务含义,禁止无意义注释
编写要点
- 每条规则用"必须 / 禁止"的祈使句:AI Agent 对祈使句的遵守率远高于陈述句
- 给出正面和反面示例:如日志规则同时写"正确:占位符格式"和"错误:字符串拼接"
- 标注推导来源:在注释中标注此规则来自哪个架构文档,便于后续维护
- 控制在 100~120 行:规则太多会导致 AI 上下文膨胀
实际示例
markdown
---
last_updated: 2026-06-29
status: active
owner: @zhangsan
---
# Always-On Rules
这些规则在所有任务中始终生效,AI Agent 必须严格遵守。
## 1. 技术栈锁定
- JDK 1.8:禁止使用 var、record、text block、switch yield、Stream.toList() 等 Java 9+ 语法
- Spring Boot 2.3.12.RELEASE:禁止升级到 3.x,禁止使用 Spring 6 的jakarta包名
- MyBatis-Plus 3.4.3:禁止使用 3.5+ 的静态链式查询等新 API
- FastJSON 1.2.83:JSON 序列化/反序列化统一使用 com.alibaba.fastjson.JSON,禁止引入 Jackson / Gson
- OkHttp 3.14.9:统一 HTTP 客户端(详见第 5 节)
- Lombok 1.18.12:统一注解处理器
- MapStruct 1.5.2.Final:DTO 转换统一使用 MapStruct,禁止手写 convert 方法
- XXL-JOB 2.2.0:分布式调度框架
## 2. 模块依赖方向
依赖只能向上流动,严禁反向依赖或跨层引用:
\```
common → dal → business → ext → app → runner
common → dal → business → ext → soa-service → app-soa → deploy-set
\```
- exchange-common 不允许依赖任何项目内模块
- exchange-dal 只能依赖 exchange-common
- exchange-business 只能依赖 exchange-dal + exchange-common
- exchange-ext 子模块只能依赖 exchange-business,ext 子模块之间禁止互相依赖
- exchange-app 依赖全部 ext 子模块
- exchange-runner 依赖 exchange-app
- exchange-api 独立发布,仅依赖 Lombok
## 3. 依赖注入
- 优先使用 @Resource(javax.annotation.Resource)
- 新代码推荐构造器注入
- 禁止字段级 @Autowired 扩散
- 禁止在构造器中使用 @Autowired(Spring 4.3+ 单构造器自动注入)
- 例外:DAL 层 BaseManager 泛型基类的 Mapper 注入(泛型类型由子类决定,@Resource 不支持泛型推断)
## 4. 日志规范
- 业务代码统一使用 Lombok @Slf4j,禁止 LoggerFactory.getLogger()
- 例外:exchange-common 基础设施层需要命名 Logger 的场景(如 "BatchExecutor"、"RateLimit"、"MDC"),@Slf4j 以类名为 Logger 名无法满足跨类统一命名
- 例外:DAL 层 BaseManager 继承 MyBatis-Plus 框架,使用 LogFactory.getLog(getClass())
- 禁止 System.out.println() 和 e.printStackTrace()
- 日志使用占位符格式:log.error("描述,planId={}", planId, e)
- 禁止字符串拼接日志:log.error("planId:" + planId)
## 5. HTTP 调用
- 统一使用 OkHttp3 3.14.9 + HttpClientFactory(exchange-common/http)
- 禁止直接 new OkHttpClient()
- 禁止使用 RestTemplate / HttpURLConnection / Apache HttpClient
- 例外(历史债务):FeiShuNoticeProcessor 自建 OkHttpClient.Builder()。HttpClientFactory 已支持自定义超时/连接池配置(通过 HttpConfig),新通知组件必须使用 HttpClientFactory.getOrBuildOkHttpClient(),禁止重复此例外
## 6. 数据库访问
- 必须通过 DalManager.of(beanName) 获取 Manager 实例
- 禁止直接注入 Mapper
- Entity 使用 @TableName + @Data + @Builder + @TableId(type = IdType.AUTO),字段使用 @TableField 映射蛇形列名
- 逻辑删除使用 yn 字段(0=有效, 1=删除)
## 7. 线程池
- 使用 BatchExecutorTemplate / ThreadPoolExecutorBuilder(exchange-common/juc)
- 禁止裸 new ThreadPoolExecutor / new ForkJoinPool / CompletableFuture.supplyAsync 无自定义线程池
## 8. 限流
- 使用 Resilience4j + RateLimitFactory(exchange-common/sentinel/limit)
- 禁止自行实现限流逻辑
## 9. traceId 传播
- 主线程使用 @MDC(types = {TraceType.TIMER, TraceType.LOG}) 注解
- 子线程使用 ContextHolder / MDCTemplate 显式传递 traceId
- 禁止在线程切换时丢失 traceId 上下文
## 10. 事务
- 使用 TransactionTemplate 编程式事务
- 事务内异常必须 transaction.setRollbackOnly() + 返回 false
- 禁止使用 @Transactional 注解(与动态数据源不兼容)
- 例外:DAL 层 BaseManager 继承 MyBatis-Plus IService 的批量操作方法(saveBatch/saveOrUpdate/updateBatchById),使用 @Transactional 是框架标准实现
## 11. 配置管理
- 配置统一走 Nacos(namespace: dev1 / test1 / pre / prod)
- 禁止硬编码环境地址、数据库连接、Redis 地址
- 禁止在代码中写入密钥、token、密码
## 12. 注释语言
- 类/方法/字段注释使用中文
- 注释需说明业务含义,禁止无意义注释
## 13. 代码行数限制(阿里规范)
遵循《阿里巴巴 Java 开发手册》编码规约:
- 单个 .java 文件总行数 ≤ 300 行(含注释和空行)
- 单个方法体行数 ≤ 80 行(不含方法签名和注解)
- 超过限制时必须拆分:文件按职责拆分为多个类,方法按逻辑拆分为多个私有方法
- 禁止通过减少注释或空行来人为压缩行数
> 自动化层门禁规则已迁移至 `agent-workflow.md` 第 8 节(避免重复定义浪费 token)
3.2 agent-workflow.md --- AI Agent 工作流约束
定位
约束 AI Agent 的开发流程行为 ,确保 PRD → 设计 → 编码全链路可控。与 always-on.md 互补:前者约束"代码怎么写 ",后者约束"流程怎么走"。
必须包含的章节
| 章节 | 内容 | 核心约束 |
|---|---|---|
| 1. 强制流程顺序 | PRD 到交付的完整步骤 | 禁止跳步 |
| 2. 技术设计文档要求 | 设计文档的格式和保存位置 | 必须基于模板生成 |
| 3. 设计评审门禁 | 评审通过后才能写代码 | 人工确认门禁 |
| 4. 按需加载策略 | 每步加载哪些文档 | 禁止预读后续步骤 |
| 5. 代码生成约束 | 代码生成的顺序和规范 | 自底向上生成 |
| 6. 交付前自检 | 交付前的检查要求 | 禁止跳过自检 |
| 7. 文档同步 | 代码变更后同步哪些文档 | 必须同步 |
| 8. 自动化层自我验证 | 编译/测试/治理的客观验证 | 客观数据优先 |
关键设计:强制流程顺序
markdown
## 1. 强制流程顺序
PRD 驱动开发必须按以下顺序执行,禁止跳步:
Step 0: 环境检查与输入校验(BRD→PRD + PRD 完整性)
→ Step 1: PRD 解析 → Step 2: 影响分析 → Step 3: 技术设计文档
→ Step 4: 设计评审(门禁)→ Step 5: 代码生成 → Step 5.5: 编译验证(门禁)
→ Step 6: 配置与文档同步 → Step 7: 自动治理巡检 + PR 自检 → 交付
- 禁止跳过环境检查与输入校验直接开始 PRD 解析
- 禁止跳过 PRD 解析直接进行影响分析
- 禁止跳过影响分析直接生成技术设计文档
- 禁止跳过技术设计文档直接写代码
- 禁止跳过设计评审直接生成代码
- 禁止跳过编译验证直接配置同步
- 禁止跳过自动治理巡检直接自检
- 禁止跳过自检直接交付
关键设计:人工确认门禁
这是 Harness Engineering 的核心理念------"AI 生成,人类驾驭"。在设计评审环节设置人工门禁:
markdown
## 3. 设计评审门禁
**⚠️ 人工确认门禁**:
- 评审完成后,必须将设计文档摘要 + 评审报告输出给用户
- **必须暂停等待用户明确确认**(「通过」/「需要修改」/「重新设计」)
- 禁止在未获得用户确认前自动进入代码生成阶段
- 评审通过后将设计文档 `status` 改为 `active`
关键设计:按需加载策略
为避免 AI 上下文膨胀,每个步骤只加载该步骤所需的文档:
markdown
## 4. 按需加载策略
### 始终加载(IDE 自动注入,不占额外 token)
- .qoder/rules/*.md(4 个文件)
### 分步按需加载
| 步骤 | 按需加载 | 预估 token |
|------|---------|------------|
| Step 0 环境检查 | pre-check.ps1 + prd-template.md §0 + brd-to-prd-guide.md(如 BRD) | ~400~1600 |
| Step 1 PRD解析 | AGENTS.md + prd-template.md + code-assets.md | ~2000 |
| Step 2 影响分析 | boundaries.md + impact-analysis.md | ~1500~3500 |
| Step 3 设计文档 | _template.md + data-flow.md | ~3000 |
| Step 4 设计评审 | design-review.md | ~1000 |
| Step 5 代码生成 | 按需触发 add-*.md | ~800 |
| Step 5.5 编译验证 | 无需加载文档 | 0 |
| Step 6 文档同步 | error-codes.md + api.spec.yaml | ~1500 |
| Step 7 自检 | auto-governance.md + pr-checklist.md | ~1600 |
### 加载规则
1. 禁止在 Step 1 预读后续步骤文档
2. 每步完成后可释放前序步骤的文档上下文
3. 单步加载总量控制在 3000 token 以内
编写要点
- 流程顺序是铁律:用"禁止跳步"的措辞,不要用"建议按序"
- 门禁要明确:写清楚"暂停等待用户确认"的动作,防止 AI 自行跳过
- 按需加载表要精确:每步标注预估 token,帮助 AI 理解加载边界
- 文档同步表要完整:列出所有变更类型和对应的需更新文档
实际实例
markdown
---
last_updated: 2026-06-29
status: active
owner: @zhangsan
---
# AI Agent 工作流规则
这些规则约束 AI Agent 的开发流程行为,确保 PRD → 设计 → 编码全链路可控。
## 1. 强制流程顺序
PRD 驱动开发必须按以下顺序执行,禁止跳步:
\```
Step 0: 环境检查与输入校验(BRD→PRD + PRD 完整性)
→ Step 1: PRD 解析与上下文加载
→ Step 2: 影响分析
→ Step 3: 技术设计文档
→ Step 4: 设计评审(门禁)
→ Step 5: 代码生成
→ Step 5.5: 即时编译验证(门禁)
→ Step 6: 配置与文档同步
→ Step 7: 自动治理巡检 + PR 自检
→ 交付
\```
- 禁止跳过环境检查与输入校验直接开始 PRD 解析
- 禁止跳过 PRD 解析直接进行影响分析
- 禁止跳过影响分析直接生成技术设计文档
- 禁止跳过技术设计文档直接写代码
- 禁止跳过设计评审直接生成代码
- 禁止跳过即时编译验证直接配置同步
- 禁止跳过自动治理巡检直接自检
- 禁止跳过自检直接交付
## 2. 技术设计文档要求
- 必须基于 `docs/design/_template.md` 模板生成
- 生成后保存到 `docs/design/feature-{功能名}.md`
- 初始 `status` 设为 `draft`
- 必须包含:目标、范围、关联文档、分层设计、数据库约束、API约定、配置项、测试要求、风险与对策、自检清单
- 必须引用 PRD 来源路径
- 必须列出关联的影响分析(参考 `docs/changes/impact-analysis.md`)
## 3. 设计评审门禁
代码生成前,必须完成设计评审(参考 `.qoder/skills/design-review.md`),并**通过人工确认后**方可进入代码生成阶段:
- 模块归属是否正确(不能违反依赖方向)
- 类设计是否复用已有基类和接口
- 数据库表设计是否符合命名规范(tb_ 前缀、yn 字段、create_time/update_time)
- API 设计是否需要更新 `api.spec.yaml`
- 错误码是否需要新增并登记到 `error-codes.md`
- 测试方案是否覆盖正常/异常/边界场景
**⚠️ 人工确认门禁**:
- 评审完成后,必须将设计文档摘要 + 评审报告输出给用户
- **必须暂停等待用户明确确认**(「通过」/「需要修改」/「重新设计」)
- 禁止在未获得用户确认前自动进入代码生成阶段
- 评审通过后将设计文档 `status` 改为 `active`
## 4. 按需加载策略(节省 token)
### 4.1 始终加载(IDE 自动注入,不占额外 token)
以下文件由 IDE 自动加载到 Agent 上下文,无需手动读取:
- `.qoder/rules/always-on.md`
- `.qoder/rules/agent-workflow.md`(本文件)
- `.qoder/rules/java-code-style.md`
- `.qoder/rules/java-testing.md`
### 4.2 分步按需加载(Agent 按步骤读取,禁止一次性全量加载)
Agent 在执行 `prd-to-code` 技能时,**每个 Step 只加载该步骤所需文档**,禁止在 Step 1 预读后续步骤的文档:
| 步骤 | 按需加载 | 目的 | 预估 token |
|------|---------|------|------------|
| Step 0 环境检查 | `build/automation/scripts/pre-check.ps1` + `worktree-manager.ps1` + `docs/reference/prd-template.md` 第 0 节 + **条件:`docs/reference/brd-to-prd-guide.md`(仅输入为 BRD 时)** | 环境校验 + Worktree 创建 + BRD→PRD 转换 + PRD 完整性校验 | ~400~1600 |
| Step 1 PRD解析 | `AGENTS.md` + `docs/reference/prd-template.md` + `docs/architecture/code-assets.md` + 知识卡 | 项目基线 + PRD格式 + 代码资产 + 模块知识 | ~2000 |
| Step 2 影响分析 | `docs/architecture/boundaries.md` + `docs/changes/impact-analysis.md` + **条件:`docs/reference/api.spec.yaml`(仅 PRD 涉及 API 变更时读取相关段)** | 模块边界 + 影响分析模板 + 现有API契约 | ~1500~3500 |
| Step 3 设计文档 | `docs/design/_template.md` + `docs/architecture/data-flow.md` + 1~2个相关 `feature-*.md` | 设计模板 + 数据流 + 相似设计参考 | ~3000 |
| Step 4 设计评审 | `.qoder/skills/design-review.md`(斜杠命令触发) | 7维度评审检查 | ~1000 |
| Step 5 代码生成 | 按需触发相关 `.qoder/skills/add-*.md`(如需新增供应商/Entity/API) | 具体操作手册 | ~800 |
| Step 5.5 编译验证 | 无需加载文档 | 即时编译检查 | 0 |
| Step 6 文档同步 | `docs/reference/error-codes.md` + `docs/reference/api.spec.yaml`(全量读取,写入新API段) | 同步错误码与API | ~1500 |
| Step 7 自检(含自动治理门禁) | `.qoder/skills/auto-governance.md` + `docs/changes/pr-checklist.md` | 自动治理巡检 + PR检查清单 | ~1600 |
### 4.3 加载规则
- 禁止在 Step 1 预读 Step 2~7 的文档
- 每个 Step 完成后,可释放前序步骤的文档上下文(无需保持)
- 如某 Step 发现需要回溯前序文档,按需补读即可
- Rules 层始终在上下文中(IDE 自动注入),不计入按需加载
- Skills 层仅在对应 Step 触发时加载
- 单个 Step 的按需加载总量控制在 3000 token 以内
## 5. 代码生成约束
- 必须严格遵守 `.qoder/rules/` 下的全部规则文件
- 必须按模块依赖方向自底向上生成:
- Web 链路:dal → business → ext → app → runner
- SOA 链路:dal → business → ext → soa-service → app-soa → deploy-set
- 每个新增 Java 文件必须有中文类注释 + @author 标注
- 必须同步生成 JUnit 5 + Mockito 单元测试
- 必须同步更新受影响的文档(error-codes.md / api.spec.yaml / CHANGELOG.md)
- **代码生成完成后必须执行自动治理巡检**(见第 8 节),禁止直接进入自检
## 6. 交付前自检
代码生成完成后,必须先执行自动治理巡检(第 8 节),再执行 `docs/changes/pr-checklist.md` 中的全部检查项,逐项确认通过后方可交付。
**顺序要求**:自动治理巡检 → PR 自检清单。禁止跳过自动治理巡检直接执行 PR 自检清单。
## 7. 文档同步
每次代码变更必须同步更新:
| 变更类型 | 需更新的文档 |
|---------|-------------|
| 新增/修改错误码 | docs/reference/error-codes.md |
| 新增/修改 API | docs/reference/api.spec.yaml |
| 新增功能 | docs/design/feature-{name}.md + CHANGELOG.md |
| 修改模块结构 | docs/architecture/boundaries.md |
| 修改数据流转 | docs/architecture/data-flow.md |
| 新增 SOA 服务 | exchange-deploy-set/exchange-soa-runner/.../spring/spring-dubbo-provider.xml(Dubbo 服务暴露配置) |
| 新增/删除 .md / .yaml / .ps1 / .xml 文件 | docs/ai-coding-guide.md §5 文档全景索引(同步新增/删除文件条目) |
> **全景索引同步规则**:凡是在 `.qoder/rules/`、`.qoder/skills/`、`docs/`、`build/automation/scripts/`、`build/linter/` 目录下新增或删除 .md/.yaml/.ps1/.xml 文件时,
> **必须同步更新** `docs/ai-coding-guide.md` 第 5 节「文档全景索引」中对应的文件树。
> 可运行 `build/automation/scripts/index-sync-check.ps1` 验证索引一致性。
## 8. 自动化层自我验证(强制)
代码生成完成后、PR 自检前,Agent **必须**执行自我验证,基于客观数据决策而非主观判断:
### 8.1 强制巡检
- 必须执行 `/auto-governance`(或手动运行 `collect-sidecar.ps1` + `decay-detector.ps1`)
- 必须读取 `build/automation/sidecar/sidecar-summary.json` 获取客观数据
- 禁止仅凭读代码做"应该没问题"的主观判断后直接交付
### 8.2 门禁阻断规则
| 条件 | 动作 |
|------|------|
| `build-status.json` 中 `compileSuccess = false` | **禁止交付**,返回修复编译错误 |
| `test-results.json` 中 `failed > 0` | **禁止交付**,返回修复失败测试 |
| `decay-report.json` 中 `overallScore < 60` | **需人工确认**后方可交付 |
| `sidecar-summary.json` 不存在或 `timestamp` 超过 24 小时 | 必须重新采集后再交付 |
### 8.3 客观侧性优先原则
当 Agent 的主观判断与 sidecar JSON 客观数据冲突时,以客观数据为准:
- Agent 认为"代码没问题"但 `build-status.json` 显示编译失败 → 以客观数据为准,修复编译错误
- Agent 认为"测试应该通过"但 `test-results.json` 显示失败 → 以客观数据为准,修复失败测试
3.3 java-code-style.md --- Java 代码风格
定位
约束 Java 代码的包结构、命名、注解使用和异常处理 。与 always-on.md 互补:前者是"技术选型约束",后者是"代码风格约束"。
必须包含的章节
| 章节 | 内容 |
|---|---|
| 包结构 | 每个模块的包前缀规则 |
| 类命名 | 各类型类的后缀/前缀规则 |
| Lombok 使用 | 哪些注解用在哪里 |
| 异常处理 | catch 块的处理规范、Controller 异常约定 |
| import 规范 | 禁止通配符 import |
| 供应商扩展 | 新增供应商的代码规范 |
编写模板
markdown
# Java 代码风格规则
适用于所有 `.java` 文件。
## 包结构
| 层 | 包前缀 | 示例 |
|----|--------|------|
| common | `com.{org}.{模块}` | `com.jzsk.trace` |
| dal | `com.{org}.exchange.dal.{子层}` | `com.jzsk.exchange.dal.entity` |
| business | `com.{org}.exchange.{子域}` | `com.jzsk.exchange.core.async` |
| ext | `com.{org}.exchange.ext.{供应商缩写}` | `com.jzsk.exchange.ext.tc` |
## 类命名
| 类型 | 后缀/前缀 | 示例 |
|------|----------|------|
| Entity | 无特殊后缀 | `SourceData` |
| Mapper | `*Mapper` | `SourceDataMapper` |
| Manager | `*Manager` | `SourceDataManager` |
| Processor | `*Processor` | `AsyncProcessor` |
| Trigger | `*Trigger` | `PlanLifecycleTrigger` |
| Scheduler | `*Scheduler` | `AsyncScheduler` |
| Service | `*Service` | `SyncSingleService` |
| Convertor | `*Convertor` | `TCInputConvertor` |
| Parser | `*HttpResultParser` | `TCHttpResultParser3605` |
| Config | `*Config` | `BizConfiguration` |
| DTO | `*DTO` | `RequestDTO` |
| Context | `*Context` | `AsyncContext` |
| Event | `*Event` | `FileRecordEvent` |
| Enum | `*Enum` | `CodeEnum` |
## Lombok 使用
- Entity / DTO:@Data
- 日志类:@Slf4j
- 构造器:@Builder + @Builder.Default
- @SneakyThrows 仅限 Scheduler / Trigger 等框架适配场景
- Entity / DTO 禁止用 @AllArgsConstructor + @NoArgsConstructor 替代 @Data
- Event / Enum / Context 等不可变值对象允许使用 @AllArgsConstructor
## 异常处理
- catch 块必须记录日志或向上抛出,禁止空 catch
- 异常日志格式:log.error("描述,param={}", param, e)
- 业务异常返回错误码,不抛异常
- Controller 层必须 try-catch
- 不使用 @ControllerAdvice,每个 Controller 方法手动 try-catch
## import 规范
- 禁止通配符 import(import xxx.*),必须逐个导入
编写要点
- 命名规则要给出正反示例 :如 "✅
SourceDataManager,❌SourceDataServiceImpl" - 供应商前缀规则要明确 :如 "天创用
TC*,友盟用Ym*" - 控制在 50~60 行:代码风格规则不宜太长,AI 需要快速匹配
实际实例
markdown
---
last_updated: 2026-06-29
status: active
owner: @zhangsan
---
# Java 代码风格规则
适用于所有 `.java` 文件。
## 包结构
- common 模块包前缀:`com.jzsk.{模块}`
- dal 模块包前缀:`com.jzsk.exchange.dal.{子层}`
- business 模块包前缀:`com.jzsk.exchange.{子域}`
- ext 模块包前缀:`com.jzsk.exchange.ext.{供应商缩写}`
- app 模块包前缀:`com.jzsk.exchange.app.{子域}`
- runner 模块包前缀:`com.jzsk.exchange` / `com.jzsk.exchange.controller`
- soa 模块包前缀:`com.jzsk.exchange.soa.service`
## 类命名
- Entity:无特殊后缀,如 `SourceData`
- Mapper:`*Mapper`,如 `SourceDataMapper`
- Manager:`*Manager`,如 `SourceDataManager`
- Processor:`*Processor`,如 `AsyncProcessor`
- Trigger:`*Trigger`,如 `PlanLifecycleTrigger`
- Scheduler:`*Scheduler`,如 `AsyncScheduler`、`ShardingScheduler`
- Service:`*Service`,如 `SyncSingleService`、`AdminService`
- Delegate:`*Delegate`,如 `HttpJsonPostRateLimitDelegate`
- Convertor:`*Convertor`,如 `TCInputConvertor`
- Parser:`*Parser` / `*HttpResultParser`,如 `TCHttpResultParser3605`
- Strategy:`*Strategy`,如 `HttpResultParserStrategy`
- Facade:`*Facade`,如 `CommonQueryFacade`
- Config:`*Config` / `*Configuration`
- DTO:`*DTO`,如 `RequestDTO`
- Context:`*Context`,如 `AsyncContext`
- Event:`*Event`,如 `FileRecordEvent`、`NoticeAfterEvent`
- Enum:`*Enum`,如 `CodeEnum`、`YesOrNoEnum`
- Constants:`Constants`(放在对应模块根包),如 `com.jzsk.exchange.ext.tc.Constants`
- 供应商适配类加前缀:`TC*` / `Ym*` / `Bh*`
- 接口解析器带接口编号:`TCHttpResultParser3605`(天创 3605 接口)
- 详细方法命名/数据库命名/常量命名参见 `docs/conventions/naming.md`
## Lombok 使用
- Entity / DTO:`@Data`
- 日志类:`@Slf4j`
- 构造器:`@Builder` + `@Builder.Default`
- 异常包装:`@SneakyThrows`(仅限 Scheduler / Trigger 等需适配 XXL-JOB / Spring 框架签名的场景,禁止在 business 层核心逻辑中使用)
- Entity / DTO 禁止用 `@AllArgsConstructor` + `@NoArgsConstructor` 替代 `@Data`
- Event / Enum / Context 等不可变值对象允许使用 `@AllArgsConstructor`(非替代 @Data,而是需要全参构造器)
## 异常处理
- catch 块必须记录日志或向上抛出,禁止空 catch
- 异常日志格式:`log.error("描述,param={}", param, e)` --- 异常对象放最后一个参数
- 业务异常返回错误码(CodeEnum),不抛异常
- 系统异常 catch 后返回 CodeEnum.UNKNOWN
- Controller 层必须 try-catch,禁止异常暴露给调用方
- 项目不使用 `@ControllerAdvice` / `@ExceptionHandler`,每个 Controller 方法手动 try-catch
- REST API 用 `@RestController`,页面渲染用 `@Controller`
## import 规范
- 禁止通配符 import(`import xxx.*`),必须逐个导入
## 供应商扩展
- 新增供应商必须在 exchange-ext 下新建子模块
- 子模块必须继承 business 中的抽象基类:InputConvertor / HttpResultParser / PortResultConvertor
- 供应商配置必须在 BizConfiguration.preInitAppConfig() 中注册到 PortConfigFactory / PlanConfigFactory
- 使用 putIfAbsent 注册,禁止覆盖已有配置
3.4 java-testing.md --- 测试规则
定位
约束测试代码的分类、框架选择、命名、Mock 策略和覆盖要求。区分单元测试与集成测试,确保单元测试可独立运行、不依赖外部环境,同时为集成测试和架构测试留出合理空间。
必须包含的章节
| 章节 | 内容 |
|---|---|
| 测试分类 | 单元测试 / 集成测试 / 架构测试,明确各自适用规则 |
| 框架 | JUnit 5 + Mockito + ArchUnit,禁止 JUnit 4(含 @RunWith 和 org.junit.Assert.*) |
| 命名 | 单元测试 {被测类}Test.java,集成测试 {被测类}IntegrationTest.java,推荐 @DisplayName + @Nested |
| Mock 策略 | 静态方法 mockStatic、依赖 @Mock + @InjectMocks、@MockitoSettings |
| 集成测试规则 | @RunWithSpring + @Resource 注入,允许外部依赖 |
| 架构测试规则 | ArchUnit @AnalyzeClasses + @ArchTest,失败消息含三要素 |
| 覆盖要求 | 正常路径、参数校验失败、异常路径、边界条件 |
| 禁止项(单元测试) | 禁止 new Spring Context、禁止外部依赖、禁止 Thread.sleep、禁止 JUnit 4 导入 |
编写模板
markdown
# 测试规则
适用于所有 `*Test.java` 和 `Test*.java` 文件。
## 测试分类
| 类型 | 所在模块 | 核心注解 | Spring 上下文 | 外部依赖 |
|------|---------|---------|-------------|---------|
| 单元测试 | {业务模块} | `@ExtendWith(MockitoExtension.class)` | 禁止 | 禁止 |
| 集成测试 | {集成测试模块} | `{项目自定义 Spring 注解}` | 允许 | 允许 |
| 架构测试 | {架构测试模块} | `@AnalyzeClasses` + `@ArchTest` | 不需要 | 不需要 |
## 框架
- 测试框架:JUnit 5 (Jupiter {版本})
- Mock 框架:Mockito {版本}(含 mockito-inline 支持静态方法 Mock)
- 架构测试:ArchUnit {版本}
- 禁止使用 JUnit 4 的 `@RunWith` 注解
- 禁止导入 `org.junit.Assert.*`,必须使用 `org.junit.jupiter.api.Assertions.*`
## 命名
- 单元测试类:`{被测类名}Test.java`,与被测类同包
- 集成测试类:`{被测类名}IntegrationTest.java`,与被测类同包
- 推荐使用 `@DisplayName` + `@Nested` 分组
## Mock 策略(单元测试)
- `{项目数据访问入口}`:必须 `mockStatic()` + `when().thenAnswer()`
- 依赖:`@Mock` + `@InjectMocks`
- 需要部分真实行为:`@Spy` 替代 `@Mock`
## 集成测试规则
- 使用项目自定义注解启动 Spring 上下文
- 允许依赖外部环境
## 架构测试规则
- ArchUnit 校验模块依赖方向
- 失败消息包含三要素:问题 / 修复 / 文档路径
## 覆盖要求
- 正常路径、参数校验失败、异常路径、边界条件
- 新增代码行覆盖率 >= 95%
## 禁止(单元测试)
- 禁止 new Spring ApplicationContext
- 禁止依赖外部环境运行单元测试
- 禁止 `Thread.sleep()` 等待异步结果
- 禁止导入 JUnit 4 的 `org.junit.Assert.*`
编写要点
- 区分测试类型是关键:单元测试禁止外部依赖,集成测试允许,架构测试不需要 Spring 上下文
- Mock 策略要具体到方法级别 :如
DalManager.of()必须用mockStatic+when().thenAnswer() - 集成测试用项目自定义注解 :
@RunWithSpring而非@MockBean,与项目实际一致 - 禁止项明确限定单元测试:标题写"禁止(单元测试)",避免集成测试被误判违规
- 覆盖要求可量化:如"行覆盖率 >= 95%",便于后续自动化层检测
实际实例
markdown
---
last_updated: 2026-06-29
status: active
owner: @zhangsan
---
# 测试规则
适用于所有 `*Test.java` 和 `Test*.java` 文件。
## 测试分类
项目区分两类测试,适用不同规则:
| 类型 | 所在模块 | 核心注解 | Spring 上下文 | 外部依赖 |
|------|---------|---------|-------------|---------|
| 单元测试 | exchange-common/dal/business/ext/app/runner/soa-service | `@ExtendWith(MockitoExtension.class)` | ❌ 禁止 | ❌ 禁止 |
| 集成测试 | exchange-test、exchange-deploy-set | `@RunWithSpring` | ✅ 允许 | ✅ 允许 |
| 架构测试 | exchange-test | `@AnalyzeClasses` + `@ArchTest` | ❌ 不需要 | ❌ 不需要 |
## 框架
- 测试框架:JUnit 5 (Jupiter 5.6.3)
- Mock 框架:Mockito 3.12.4(含 mockito-inline 支持静态方法 Mock)
- 架构测试:ArchUnit 0.23.1(archunit-junit5)
- 单元测试注解:`@ExtendWith(MockitoExtension.class)`
- 禁止使用 JUnit 4 的 `@RunWith` 注解
- 禁止导入 `org.junit.Assert.*`,必须使用 `org.junit.jupiter.api.Assertions.*`
## 命名
- 单元测试类:`{被测类名}Test.java`,与被测类同包
- 集成测试类:`{被测类名}IntegrationTest.java`,与被测类同包
- 测试方法:`test{场景描述}()` 或 `test{被测方法}_{条件}()`
- 推荐使用 `@DisplayName("中文场景描述")` 增强可读性
- 推荐使用 `@Nested` 对测试方法分组(如:参数校验/正常流程/异常路径/边界条件)
- 参数化测试使用 `@ParameterizedTest`
## Mock 策略(单元测试)
- `DalManager.of(beanName)`:必须 `mockStatic(DalManager.class)` + `when().thenAnswer()`
- Manager / Service 依赖:`@Mock` + `@InjectMocks`
- 需要部分真实行为:`@Spy` 替代 `@Mock`
- 静态方法 Mock:使用 `mockStatic()`(try-with-resources 或 `@BeforeEach` open / `@AfterEach` close)
- 严格模式默认开启,如需宽松匹配:`@MockitoSettings(strictness = Strictness.LENIENT)`
## 集成测试规则
- 使用项目自定义 `@RunWithSpring` 注解启动 Spring 上下文
- 依赖注入使用 `@Resource`
- 允许依赖外部 Nacos / Redis / MySQL 环境
- 允许使用 `Thread.sleep()` 模拟时间流逝(限流/超时场景)
## 架构测试规则
- 使用 ArchUnit(`@AnalyzeClasses` + `@ArchTest`)
- 位于 exchange-test 模块,校验模块依赖方向不可逆
- 失败消息必须包含三要素:问题 / 修复 / 文档路径
## 覆盖要求
新功能必须有单元测试,覆盖以下场景:
- 正常路径
- 参数校验失败(空值、非法值)
- 异常路径(catch 分支)
- 边界条件(空集合、null 返回)
- 新增代码行覆盖率>=95%
## 禁止(单元测试)
- 禁止测试方法中直接 new Spring ApplicationContext(使用 Mockito 替代)
- 禁止依赖外部 Nacos / Redis / MySQL 环境运行单元测试
- 禁止使用 `Thread.sleep()` 等待异步结果(使用 CountDownLatch 或同步执行)
- 禁止导入 JUnit 4 的 `org.junit.Assert.*`(使用 `org.junit.jupiter.api.Assertions.*`)
4. Rules 层设计原则
4.1 祈使句原则
每条规则使用"必须 / 禁止"的祈使句,而非陈述句:
| ❌ 陈述句 | ✅ 祈使句 |
|---|---|
| 日志推荐使用 @Slf4j | 统一使用 @Slf4j,禁止 LoggerFactory.getLogger() |
| 建议通过 DalManager 访问 | 必须通过 DalManager.of() 获取,禁止直接注入 Mapper |
| 尽量避免 @Transactional | 禁止使用 @Transactional 注解 |
4.2 正反示例原则
每条规则同时给出"正确做法"和"错误做法":
markdown
- 日志使用占位符格式:log.error("描述,param={}", param, e) ← ✅ 正确
- 禁止字符串拼接日志:log.error("param:" + param) ← ❌ 错误
4.3 可验证原则
规则必须是可通过 Linter 或人工检查验证的:
| ❌ 不可验证 | ✅ 可验证 |
|---|---|
| 代码要写得好 | 单文件 ≤ 300 行 |
| 注释要有意义 | 每个 Java 文件必须有中文类注释 + @author |
| 异常处理要合理 | catch 块必须记录日志或向上抛出,禁止空 catch |
4.4 推导可追溯原则
每条规则标注推导来源,便于后续维护和更新:
markdown
## 2. 模块依赖方向
<!-- 推导来源: docs/architecture/boundaries.md 依赖方向图 -->
依赖只能向上流动...
5. 完成验证清单
完成本步后,逐项检查:
-
.qoder/rules/always-on.md存在,包含 13 条硬性约束(技术栈/依赖方向/注入/日志/HTTP/数据库/线程池/限流/traceId/事务/配置/注释/代码行数限制) -
.qoder/rules/agent-workflow.md存在,包含强制流程顺序(含 BRD→PRD)、设计评审门禁、按需加载策略、代码生成约束、交付前自检、文档同步、自动化层自我验证 -
.qoder/rules/java-code-style.md存在,包含包结构、类命名、Lombok 使用、异常处理、import 规范、供应商扩展规范 -
.qoder/rules/java-testing.md存在,包含框架选择、命名规范、Mock 策略、覆盖要求、禁止项 - 所有规则使用"必须 / 禁止"祈使句
- 关键规则有正反示例
-
AGENTS.md的快速导航表中已注册 4 个 Rules 文件 - 每条规则可追溯到 Step 1 的架构文档
6. 与下一步的衔接
本步建立了 Rules 层硬性约束,锁定了技术栈和代码规范。下一步需要编写 Wiki 层(编码规范与参考资料)------Rules 层的"详细展开版",提供更丰富的上下文知识。
Step 2(本步) Step 3(下一步)
┌─────────────────┐ ┌─────────────────────┐
│ always-on.md │ 约束展开 │ conventions/ │ ← 编码规范详细版
│ agent-workflow │ ──────────▶ │ naming.md │ ← 命名细则
│ java-code-style │ 规则细化 │ error-handling.md │ ← 错误处理细则
│ java-testing │ │ logging.md │ ← 日志细则
└─────────────────┘ │ reference/ │ ← 参考资料库
│ prd-template.md │ ← PRD 输入模板
│ design/_template.md │ ← 设计文档模板
└─────────────────────┘
衔接关系:
java-code-style.md的命名规则 →conventions/naming.md的详细命名表java-testing.md的测试规则 →conventions/testing.md的详细测试实践always-on.md的日志规范 →conventions/logging.md的日志格式细则agent-workflow.md的设计文档要求 →design/_template.md的设计文档模板agent-workflow.md的 PRD 输入 →reference/prd-template.md的 PRD 模板
说明
- 实际示例的格式是markdown格式,在示例中出现\符号是因为格式采用markdown编辑的,若不转译就会直接markdown格式断裂。使用时将\去掉即可