AI 编程规则引擎深度解读:从零理解工程化设计
面向新人的体系化培训文档。读完本文,你应该能完整回答:"这套规则解决什么问题、由几部分组成、每部分如何工作、它们如何协作、我作为新人该怎么用。"
第一部分 · 全景概览
1.1 为什么需要这套规则引擎
没有规则时,AI 编程的真实样貌:
| 痛点 | 表现 |
|---|---|
| 跳步开工 | 用户说"实现一下",AI 直接写代码,没有规范、没有方案、没有任务拆分 |
| 上下文遗失 | 同一个流程,今天写在 A 文件、明天写在 B 文件,缺乏全局视角 |
| 安全裸奔 | SQL 字符串拼接、日志打印 Token、控制器里 try-catch 业务异常 |
| 风格漂移 | 同一个项目,后端用 PascalCase、前端又混杂下划线,注释一会儿英文一会儿中文 |
| 提交失控 | AI 自作主张 git add . && git commit -m "fix",把工作区改坏了还不知道 |
| 文档与代码分裂 | 项目说明还写着旧目录,实际目录早就重构过了 |
| 知识孤岛 | 上次定义的功能规范,AI 再写时完全忘了,重新发明轮子 |
核心矛盾: AI 的能力是"输出代码",但工程项目的真正成本是 "维持长期一致性" 。一致性不会自动产生,它必须被显式编码为规则。
有了规则引擎之后的改变:
- AI 写代码前 先看规范 → 没有规范文档就停下补文档
- AI 在每一步都 被自动 Hook 检查 → 写实现代码时若近期无规范,立即向用户确认
- AI 知道 领域知识在哪里 → 通过 Skills 找到业务领域映射
- AI 不擅自提交 → 必须用户明确说"提交"才执行 git
- AI 在每次回复中 声明知识图谱命中情况 → 给团队留下可审计的痕迹
设计决策 :把"质量保障"从"靠经验"升级为"靠流程 + 自动化"。规则不是束缚,而是让 AI 在巨型代码库里不丢方向的导航系统。
1.2 整体架构图
#mermaid-svg-kZnHgKsPze54cc7Y{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kZnHgKsPze54cc7Y .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kZnHgKsPze54cc7Y .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kZnHgKsPze54cc7Y .error-icon{fill:#552222;}#mermaid-svg-kZnHgKsPze54cc7Y .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kZnHgKsPze54cc7Y .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kZnHgKsPze54cc7Y .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kZnHgKsPze54cc7Y .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kZnHgKsPze54cc7Y .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kZnHgKsPze54cc7Y .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kZnHgKsPze54cc7Y .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kZnHgKsPze54cc7Y .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kZnHgKsPze54cc7Y .marker.cross{stroke:#333333;}#mermaid-svg-kZnHgKsPze54cc7Y svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kZnHgKsPze54cc7Y p{margin:0;}#mermaid-svg-kZnHgKsPze54cc7Y .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kZnHgKsPze54cc7Y .cluster-label text{fill:#333;}#mermaid-svg-kZnHgKsPze54cc7Y .cluster-label span{color:#333;}#mermaid-svg-kZnHgKsPze54cc7Y .cluster-label span p{background-color:transparent;}#mermaid-svg-kZnHgKsPze54cc7Y .label text,#mermaid-svg-kZnHgKsPze54cc7Y span{fill:#333;color:#333;}#mermaid-svg-kZnHgKsPze54cc7Y .node rect,#mermaid-svg-kZnHgKsPze54cc7Y .node circle,#mermaid-svg-kZnHgKsPze54cc7Y .node ellipse,#mermaid-svg-kZnHgKsPze54cc7Y .node polygon,#mermaid-svg-kZnHgKsPze54cc7Y .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kZnHgKsPze54cc7Y .rough-node .label text,#mermaid-svg-kZnHgKsPze54cc7Y .node .label text,#mermaid-svg-kZnHgKsPze54cc7Y .image-shape .label,#mermaid-svg-kZnHgKsPze54cc7Y .icon-shape .label{text-anchor:middle;}#mermaid-svg-kZnHgKsPze54cc7Y .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kZnHgKsPze54cc7Y .rough-node .label,#mermaid-svg-kZnHgKsPze54cc7Y .node .label,#mermaid-svg-kZnHgKsPze54cc7Y .image-shape .label,#mermaid-svg-kZnHgKsPze54cc7Y .icon-shape .label{text-align:center;}#mermaid-svg-kZnHgKsPze54cc7Y .node.clickable{cursor:pointer;}#mermaid-svg-kZnHgKsPze54cc7Y .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kZnHgKsPze54cc7Y .arrowheadPath{fill:#333333;}#mermaid-svg-kZnHgKsPze54cc7Y .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kZnHgKsPze54cc7Y .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kZnHgKsPze54cc7Y .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kZnHgKsPze54cc7Y .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kZnHgKsPze54cc7Y .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kZnHgKsPze54cc7Y .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kZnHgKsPze54cc7Y .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kZnHgKsPze54cc7Y .cluster text{fill:#333;}#mermaid-svg-kZnHgKsPze54cc7Y .cluster span{color:#333;}#mermaid-svg-kZnHgKsPze54cc7Y div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kZnHgKsPze54cc7Y .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kZnHgKsPze54cc7Y rect.text{fill:none;stroke-width:0;}#mermaid-svg-kZnHgKsPze54cc7Y .icon-shape,#mermaid-svg-kZnHgKsPze54cc7Y .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kZnHgKsPze54cc7Y .icon-shape p,#mermaid-svg-kZnHgKsPze54cc7Y .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kZnHgKsPze54cc7Y .icon-shape .label rect,#mermaid-svg-kZnHgKsPze54cc7Y .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kZnHgKsPze54cc7Y .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kZnHgKsPze54cc7Y .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kZnHgKsPze54cc7Y :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 触发
触发
触发
目录变更
被引用
被引用
触发
数据源
update --force
用户需求/对话
conversation-principles
双轨回答 + 目标澄清
graphify.mdc
入口 query 必经之路
01-sdd-spec
规范先行四阶段
阶段1 规范
docs/specs · docs/change
阶段2 技术方案
docs/plans
阶段3 任务
TodoWrite + ## Tasks
阶段4 实施
代码 + 测试
sdd-chg-spec-reminder
变更历史同步
sdd-impl-guard
规范先行守门
sdd-security-hint
安全自检注入
check-claude-shell-guard
结构变更守卫
02-code-style
命名/注释/函数
03-testing
测试框架
04-security
四大安全域
05-backend
后端分层
06-frontend
前端规范
07-git
提交授权
Skills 领域知识沉淀
业务领域 · 数据查询
Commands 命令系统
/new-spec · /change-spec
08-knowledge-graph
图谱产物
五大组件分工:
| 组件 | 角色 | 类比 |
|---|---|---|
| Rules(规则文件) | 法律条文,告诉 AI "什么该做、什么不该做" | 宪法 + 部门法 |
| Hooks(自动化脚本) | 自动化守卫,在文件读写时机切入做检查 | 海关 / 检查站 |
| Commands(slash 命令) | 用户主动触发的标准化任务模板 | 申请表模板 |
| Skills(领域分册) | 项目特定的领域知识库,按需加载 | 业务百科全书 |
| Graphify(知识图谱) | 跨模块影响面的可查询索引 | 项目的"地图册" |
1.3 目录结构与一句话定位
rules/
├── rules/ # 规则层(核心)
│ ├── 00-global.mdc # 五大原则 + 优先级裁决表(总章程)
│ ├── 01-sdd-spec.mdc # 规范先行四阶段(最重要,一切流程的根)
│ ├── 02-code-style.mdc # 命名 + 注释 + 函数风格
│ ├── 03-testing.mdc # 测试框架 + 覆盖率 + AC 映射
│ ├── 04-security.mdc # 输入/认证/数据/依赖 四大安全域
│ ├── 05-backend.mdc # 后端分层架构
│ ├── 06-frontend.mdc # 前端框架规范
│ ├── 07-git.mdc # 提交授权(最高业务优先级)
│ ├── 08-knowledge-graph.mdc # 图谱白名单与更新策略
│ ├── conversation-principles.mdc # 双轨回答 + 目标澄清
│ └── graphify.mdc # 入口 query 流程与回复模板
├── hooks/ # 自动化守卫层
│ ├── check-claude-shell-guard.ps1 # 监听目录变更命令 → 提醒同步项目文档
│ ├── sdd-chg-spec-reminder.ps1 # 写变更文档后提醒回填变更历史
│ ├── sdd-impl-guard.ps1 # 写代码前检查近期是否有规范
│ └── sdd-security-hint.ps1 # 后端写敏感关键词时注入安全清单
├── commands/ # 用户命令层
│ ├── 00-sdd/change-spec.md # /change-spec:变更文档生成模板
│ ├── 00-sdd/new-spec.md # /new-spec:规范文档生成模板
│ └── README.MD # 命令索引
└── skills/ # 领域知识层
├── business-domain-skill/ # 业务领域知识(术语/流程/Checklist)
└── querying-table-structure/ # 数据库表结构查询工具
1.4 设计哲学:四大支柱
#mermaid-svg-X5wiR6xwH84G7XIE{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-X5wiR6xwH84G7XIE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-X5wiR6xwH84G7XIE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-X5wiR6xwH84G7XIE .error-icon{fill:#552222;}#mermaid-svg-X5wiR6xwH84G7XIE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-X5wiR6xwH84G7XIE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-X5wiR6xwH84G7XIE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-X5wiR6xwH84G7XIE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-X5wiR6xwH84G7XIE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-X5wiR6xwH84G7XIE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-X5wiR6xwH84G7XIE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-X5wiR6xwH84G7XIE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-X5wiR6xwH84G7XIE .marker.cross{stroke:#333333;}#mermaid-svg-X5wiR6xwH84G7XIE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-X5wiR6xwH84G7XIE p{margin:0;}#mermaid-svg-X5wiR6xwH84G7XIE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-X5wiR6xwH84G7XIE .cluster-label text{fill:#333;}#mermaid-svg-X5wiR6xwH84G7XIE .cluster-label span{color:#333;}#mermaid-svg-X5wiR6xwH84G7XIE .cluster-label span p{background-color:transparent;}#mermaid-svg-X5wiR6xwH84G7XIE .label text,#mermaid-svg-X5wiR6xwH84G7XIE span{fill:#333;color:#333;}#mermaid-svg-X5wiR6xwH84G7XIE .node rect,#mermaid-svg-X5wiR6xwH84G7XIE .node circle,#mermaid-svg-X5wiR6xwH84G7XIE .node ellipse,#mermaid-svg-X5wiR6xwH84G7XIE .node polygon,#mermaid-svg-X5wiR6xwH84G7XIE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-X5wiR6xwH84G7XIE .rough-node .label text,#mermaid-svg-X5wiR6xwH84G7XIE .node .label text,#mermaid-svg-X5wiR6xwH84G7XIE .image-shape .label,#mermaid-svg-X5wiR6xwH84G7XIE .icon-shape .label{text-anchor:middle;}#mermaid-svg-X5wiR6xwH84G7XIE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-X5wiR6xwH84G7XIE .rough-node .label,#mermaid-svg-X5wiR6xwH84G7XIE .node .label,#mermaid-svg-X5wiR6xwH84G7XIE .image-shape .label,#mermaid-svg-X5wiR6xwH84G7XIE .icon-shape .label{text-align:center;}#mermaid-svg-X5wiR6xwH84G7XIE .node.clickable{cursor:pointer;}#mermaid-svg-X5wiR6xwH84G7XIE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-X5wiR6xwH84G7XIE .arrowheadPath{fill:#333333;}#mermaid-svg-X5wiR6xwH84G7XIE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-X5wiR6xwH84G7XIE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-X5wiR6xwH84G7XIE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-X5wiR6xwH84G7XIE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-X5wiR6xwH84G7XIE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-X5wiR6xwH84G7XIE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-X5wiR6xwH84G7XIE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-X5wiR6xwH84G7XIE .cluster text{fill:#333;}#mermaid-svg-X5wiR6xwH84G7XIE .cluster span{color:#333;}#mermaid-svg-X5wiR6xwH84G7XIE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-X5wiR6xwH84G7XIE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-X5wiR6xwH84G7XIE rect.text{fill:none;stroke-width:0;}#mermaid-svg-X5wiR6xwH84G7XIE .icon-shape,#mermaid-svg-X5wiR6xwH84G7XIE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-X5wiR6xwH84G7XIE .icon-shape p,#mermaid-svg-X5wiR6xwH84G7XIE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-X5wiR6xwH84G7XIE .icon-shape .label rect,#mermaid-svg-X5wiR6xwH84G7XIE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-X5wiR6xwH84G7XIE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-X5wiR6xwH84G7XIE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-X5wiR6xwH84G7XIE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 规范先行
分层管控
自动化辅助
知识沉淀
| 支柱 | 含义 | 典型体现 |
|---|---|---|
| 规范先行 | 规范文档是唯一真实来源,代码依据规范产出 | 四阶段顺序不可颠倒 |
| 分层管控 | 不同变更量级走不同流程,不一刀切 | hotfix / feature / structural 三档分级 |
| 自动化辅助 | 守卫由脚本执行,不依赖人为自觉 | Hooks 在文件 IO 时机自动触发 |
| 知识沉淀 | 每次产出都进入规范/变更文档/图谱/Skill | Implement 完成必更新图谱 |
核心信念:规则的目的不是"管住 AI",而是"让 AI 输出可审计、可回溯、可继承"------任何一行代码都能追溯到 AC,任何一次决策都有文档留痕。
第二部分 · 规则文件逐个深度解读
2.1 全局总章程
解决什么问题:在所有规则中"谁说了算"------当不同规则冲突时,必须有一张优先级裁决表。
Front Matter 解读:
yaml
description: 全局开发规范
alwaysApply: true # 关键:每次对话都加载,不靠 globs 触发
alwaysApply: true表示这是基础常驻规则;与globs配置不同,后者只在匹配文件时激活。
五大核心原则(背下来):
| 编号 | 原则 | 落地方式 |
|---|---|---|
| 1 | 规范先行 | 四阶段顺序:规范 → 方案 → 任务 → 实施 |
| 2 | 逐阶段评审 | 每阶段含评审门,feature/structural 须用户显式通过 |
| 3 | 可验证 | 每条 AC 至少一个测试用例 |
| 4 | 可追踪 | 代码注释含 @spec 或 @change |
| 5 | 文档同步 | 结构性变更必须同步项目总览文档 |
规则优先级层级表(解决冲突的圣经):
1 系统/安全/工具限制、当前模式约束
2 git 提交授权
3 安全规范
4 SDD 流程门禁
5 代码风格与命名
6 交互规范
巧妙设计点 :把 Git 提交授权提到第 2 位(业务规则中最高),高于安全和流程。因为 Git 操作是不可逆的------可以接受违反规范但能改正,不能接受 AI 把代码 push 到错误分支后撤不回来。
对话规范检查清单:
当用户说"帮我实现"、"调整功能"等隐性指令时,AI 必须依次确认:
□ 0. 知识图谱入口查询
□ 1. 是否有规范文档
□ 2. 无 → 先写规范
□ 3. 规范通过 → 写技术方案
□ 4. 方案通过 → Implement
□ 5. 用户说"可以"≠ 跳过 2-4
常见误区 :把"用户说
就这么做"误解为提交了三阶段评审。真相是------必须有书面文档落档(变更文档/规范文档/方案文档)才算通过。口头"可以"只对最后一道用户评审门有效。
项目文档同步治理:哪些算"结构性变更"?
- 一级或关键二级目录的增删改名
- 前后端入口路径变化
- 测试/接口/服务目录职责变化
- Service / Repository / Store 分层迁移
存量代码策略:
| 场景 | 策略 |
|---|---|
| 不动存量 | 已上线功能不主动回溯补规范和测试 |
| 触碰即纳入 | 一旦修改存量,先补简化版规范(状态 Deployed),再走四阶段 |
巧妙设计点 :避免"补救式工程"------不强迫团队为了规范而停下手头工作回头补几百个文档。但手伸到哪儿就规范到哪儿,渐进式覆盖。
禁止行为(黑名单):
- ❌ 缺规范就编码
- ❌ 颠倒规范先行顺序
- ❌ 把草稿目录当正式方案
- ❌ 借口"小改动"跳过变更文档
- ❌ 无 AC 对应测试
- ❌ 跳过安全自检
- ❌ 绕过类型检查
- ❌ 注释/日志写敏感信息
2.2 SDD 规范先行四阶段(重点)
解决什么问题 :定义从需求到代码的标准化流水线,并为不同量级提供分级流程。
Front Matter: alwaysApply: true,意味着 SDD 是常驻"宪法"。
总流程
#mermaid-svg-pj0YdpO9vqo6cU81{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pj0YdpO9vqo6cU81 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pj0YdpO9vqo6cU81 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pj0YdpO9vqo6cU81 .error-icon{fill:#552222;}#mermaid-svg-pj0YdpO9vqo6cU81 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pj0YdpO9vqo6cU81 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pj0YdpO9vqo6cU81 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pj0YdpO9vqo6cU81 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pj0YdpO9vqo6cU81 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pj0YdpO9vqo6cU81 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pj0YdpO9vqo6cU81 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pj0YdpO9vqo6cU81 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pj0YdpO9vqo6cU81 .marker.cross{stroke:#333333;}#mermaid-svg-pj0YdpO9vqo6cU81 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pj0YdpO9vqo6cU81 p{margin:0;}#mermaid-svg-pj0YdpO9vqo6cU81 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pj0YdpO9vqo6cU81 .cluster-label text{fill:#333;}#mermaid-svg-pj0YdpO9vqo6cU81 .cluster-label span{color:#333;}#mermaid-svg-pj0YdpO9vqo6cU81 .cluster-label span p{background-color:transparent;}#mermaid-svg-pj0YdpO9vqo6cU81 .label text,#mermaid-svg-pj0YdpO9vqo6cU81 span{fill:#333;color:#333;}#mermaid-svg-pj0YdpO9vqo6cU81 .node rect,#mermaid-svg-pj0YdpO9vqo6cU81 .node circle,#mermaid-svg-pj0YdpO9vqo6cU81 .node ellipse,#mermaid-svg-pj0YdpO9vqo6cU81 .node polygon,#mermaid-svg-pj0YdpO9vqo6cU81 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pj0YdpO9vqo6cU81 .rough-node .label text,#mermaid-svg-pj0YdpO9vqo6cU81 .node .label text,#mermaid-svg-pj0YdpO9vqo6cU81 .image-shape .label,#mermaid-svg-pj0YdpO9vqo6cU81 .icon-shape .label{text-anchor:middle;}#mermaid-svg-pj0YdpO9vqo6cU81 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pj0YdpO9vqo6cU81 .rough-node .label,#mermaid-svg-pj0YdpO9vqo6cU81 .node .label,#mermaid-svg-pj0YdpO9vqo6cU81 .image-shape .label,#mermaid-svg-pj0YdpO9vqo6cU81 .icon-shape .label{text-align:center;}#mermaid-svg-pj0YdpO9vqo6cU81 .node.clickable{cursor:pointer;}#mermaid-svg-pj0YdpO9vqo6cU81 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pj0YdpO9vqo6cU81 .arrowheadPath{fill:#333333;}#mermaid-svg-pj0YdpO9vqo6cU81 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pj0YdpO9vqo6cU81 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pj0YdpO9vqo6cU81 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pj0YdpO9vqo6cU81 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pj0YdpO9vqo6cU81 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pj0YdpO9vqo6cU81 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pj0YdpO9vqo6cU81 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pj0YdpO9vqo6cU81 .cluster text{fill:#333;}#mermaid-svg-pj0YdpO9vqo6cU81 .cluster span{color:#333;}#mermaid-svg-pj0YdpO9vqo6cU81 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pj0YdpO9vqo6cU81 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pj0YdpO9vqo6cU81 rect.text{fill:none;stroke-width:0;}#mermaid-svg-pj0YdpO9vqo6cU81 .icon-shape,#mermaid-svg-pj0YdpO9vqo6cU81 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pj0YdpO9vqo6cU81 .icon-shape p,#mermaid-svg-pj0YdpO9vqo6cU81 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pj0YdpO9vqo6cU81 .icon-shape .label rect,#mermaid-svg-pj0YdpO9vqo6cU81 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pj0YdpO9vqo6cU81 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pj0YdpO9vqo6cU81 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pj0YdpO9vqo6cU81 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 评审门
评审门
评审门
不符合规范
需求
1·规范
docs/specs
docs/change
2·技术方案
docs/plans
3·任务
TodoWrite
4·实施验证
代码+测试
规范状态
Implemented
产物映射表
| 阶段 | 产物 | 路径 |
|---|---|---|
| 1 规范 | 唯一真实来源 | docs/specs/FR-XXX.md 或 docs/change/CHG-*.md |
| 2 技术方案 | 架构、技术栈、影响面 | docs/plans/YYYY-MM-DD-*.md |
| 3 任务 | 可执行单元 | Plan「## Tasks」+ TodoWrite |
| 4 实施 | 代码 + 测试 | 源码 + 测试文件 |
巧妙设计点 :规范文档不进
docs/plans/。两者职责严格分离------规范回答"做什么、为什么",方案回答"怎么做"。工具草稿目录不能当正式方案。
变更量级判定表(最精妙的部分)
| 量级 | 判定 | 规范深度 | 方案深度 | 评审门 | 测试 |
|---|---|---|---|---|---|
| hotfix | 单字段/文案/配置 | CHG 一段话 | 免建 plan | agent 自评 | 见 hotfix 测试判定 |
| feature | 新能力或行为变更 | FR Spec 含 AC | 完整架构/影响面 | 用户显式通过 | 每 AC 至少一测 |
| structural | 目录/入口/职责变更 | CHG 标"影响项目文档" | 含同步文档一节 | 用户显式通过 | 同 feature + sync 检查 |
hotfix 测试判定(客观标准):
| 变更类型 | 测试要求 |
|---|---|
| 纯新增字段,无分支 | 最小单测:序列化/反序列化/落库 |
| 修改条件判断或计算逻辑 | 必须覆盖新分支,用例名含 AC-XXX |
| 纯文案/配置 | 可免测,CHG 标注「免测原因:纯文案/配置」 |
设计决策 :变更量级不决定是否做文档 (文档总要做),只决定深度和评审力度。这是务实主义的核心------既不让 hotfix 被流程拖累,也不允许 feature 借口"小改动"逃避评审。
常见误区 :以为 hotfix 完全不用文档。错------hotfix 至少要有 CHG 一段话 + 安全自检,只是免 plan、免评审门。
三阶段评审门
性质:流程约定 + 文档状态留痕;无 CI/Hook 自动拦截,仅靠规则约束。
| 阶段 | 评审对象 | 通过条件(满足其一) | 文档留痕 |
|---|---|---|---|
| 1 规范 | CHG/Spec | 用户对话「通过」;或随 Plan Build 一并通过 | 状态升 Approved |
| 2 方案 | docs/plans/*.md | 对话「通过」;或 Plan → Build | Plan 含 ## 评审记录 |
| 3 任务 | Plan 末「## Tasks」 | 对话「通过」;或随 Plan Build | Tasks 已写入 Plan |
合并确认(推荐):用户 Plan → Build 视为三阶段一并通过,Agent 必须在同一轮:
- 把变更/规范文档状态从
Draft升Approved - 在 Plan 写
## 评审记录(三行:规范/方案/任务) - 才能进 Implement
第四阶段实施五道门(每个 Task 必经)
4a. [TDD] 先写测试,用例名含 AC-XXX
4b. [实现] 编码 + @spec/@change 注释
4c. [测试通过] 运行测试全部通过
4d. [安全自检] SQL注入/权限/敏感信息/输入验证
4e. [AC 验收] 逐条对照标注测试用例名
Task 全部完成后还有"规范验证门":
□ 5. 回归测试
□ 6. 跨 Task 安全整体复查
□ 7. 规范符合验证(不符合 → 回 Implement 修正)
□ 8. 规范状态升 Implemented + 填测试映射
□ 9. 知识图谱 update --force + polish
巧妙设计点 :四道阶段评审门 + 五道实施 Task 门 + 规范验证门,构成深度防御。任意一道门可以单独被 Hook 强制,任意一道门也可以由用户显式审查。门多但每道都有明确职责。
规范状态流
Draft → Approved → Implemented → Verified → Deployed
常见误区 :以为
Approved= "已上线"。错------Approved只是说"规范评审通过、可以进 Implement",离 Deployed 还有 Implemented / Verified 两步。
变更历史同步
创建变更文档后必须在关联规范末尾的「## 变更历史」表格追加一行。约束:
- 变更历史必须是规范的最后章节
- 一个 CHG 只关联一个规范
- 写了 CHG 但未更新历史 → 视为第一阶段未完成
2.3 代码风格
解决什么问题:跨语言保持命名与注释风格一致。
Front Matter:
yaml
alwaysApply: false
globs: "**/*.{cs,js,vue}" # 仅在编辑代码文件时激活
与全局规则不同,代码风格用 globs 触发------只在写代码时加载,节省 prompt 预算。
命名规范表(必背):
| 类型 | 规范 | 示例 |
|---|---|---|
| 变量/函数 | 驼峰 | getUserInfo, isValid |
| 类/组件 | 大驼峰 | UserService, LoginForm |
| 常量 | 大写蛇形 | MAX_RETRY_COUNT |
| 文件(非组件) | 小写短横线 | user-service.js |
| 组件文件 | 大驼峰 | OrderList.vue |
规范注释(追溯链路的核心):
csharp
// Change: CHG-YYYY-MMDD-xxx (后端变更)
javascript
// @change CHG-YYYY-MMDD-xxx (前端变更)
/**
* @spec FR-001
* @implements AC-001, AC-002 (新功能)
*/
设计决策 :通过
@spec/@change注释,把代码和规范做双向绑定------规范里有"测试用例映射表",代码里有规范 ID。任何一段代码都能问:"你来自哪条 AC?"
函数规范:单一职责、≤ 50 行、≤ 5 参数。
2.4 测试规范
解决什么问题:让"每条 AC 都有测试"从口号变成可执行约束。
框架选型(示例):
| 端 | 框架 |
|---|---|
| 前端 | Vitest + 组件测试工具 + 轻量 DOM 环境 |
| 后端 | xUnit + Moq |
测试文件位置:
- 前端测试与被测文件同目录
- 后端测试集中在独立测试项目
设计决策:前端选"同目录" → 修改时改测试方便;后端选"集中项目" → 便于统一运行。两者都对,差异由生态决定。
覆盖率分层:
| 类型 | 要求 | 适用 |
|---|---|---|
| 单元测试 | ≥ 80% | 新建模块 |
| 集成测试 | ≥ 70% | 新建模块 |
| Spec 验证测试 | 100% | 每 AC 至少一测 |
存量豁免 :变更已上线模块 → 仅要求 diff 覆盖,不强求整模块达 80%。
巧妙设计点:"Spec 验证测试 100%" 永不豁免,因为它是 SDD 的命脉;但模块级覆盖率允许豁免,体现务实主义------不要求把存量历史债务全还掉。
禁止行为: 无测试代码提交、无断言的测试、硬编码敏感信息。
2.5 安全规范 --- 四大安全域
解决什么问题:把"安全检查"从模糊词变成可逐项打勾的清单。
#mermaid-svg-jpT3lJTRdMScvwjO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jpT3lJTRdMScvwjO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jpT3lJTRdMScvwjO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jpT3lJTRdMScvwjO .error-icon{fill:#552222;}#mermaid-svg-jpT3lJTRdMScvwjO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jpT3lJTRdMScvwjO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jpT3lJTRdMScvwjO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jpT3lJTRdMScvwjO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jpT3lJTRdMScvwjO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jpT3lJTRdMScvwjO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jpT3lJTRdMScvwjO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jpT3lJTRdMScvwjO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jpT3lJTRdMScvwjO .marker.cross{stroke:#333333;}#mermaid-svg-jpT3lJTRdMScvwjO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jpT3lJTRdMScvwjO p{margin:0;}#mermaid-svg-jpT3lJTRdMScvwjO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jpT3lJTRdMScvwjO .cluster-label text{fill:#333;}#mermaid-svg-jpT3lJTRdMScvwjO .cluster-label span{color:#333;}#mermaid-svg-jpT3lJTRdMScvwjO .cluster-label span p{background-color:transparent;}#mermaid-svg-jpT3lJTRdMScvwjO .label text,#mermaid-svg-jpT3lJTRdMScvwjO span{fill:#333;color:#333;}#mermaid-svg-jpT3lJTRdMScvwjO .node rect,#mermaid-svg-jpT3lJTRdMScvwjO .node circle,#mermaid-svg-jpT3lJTRdMScvwjO .node ellipse,#mermaid-svg-jpT3lJTRdMScvwjO .node polygon,#mermaid-svg-jpT3lJTRdMScvwjO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jpT3lJTRdMScvwjO .rough-node .label text,#mermaid-svg-jpT3lJTRdMScvwjO .node .label text,#mermaid-svg-jpT3lJTRdMScvwjO .image-shape .label,#mermaid-svg-jpT3lJTRdMScvwjO .icon-shape .label{text-anchor:middle;}#mermaid-svg-jpT3lJTRdMScvwjO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jpT3lJTRdMScvwjO .rough-node .label,#mermaid-svg-jpT3lJTRdMScvwjO .node .label,#mermaid-svg-jpT3lJTRdMScvwjO .image-shape .label,#mermaid-svg-jpT3lJTRdMScvwjO .icon-shape .label{text-align:center;}#mermaid-svg-jpT3lJTRdMScvwjO .node.clickable{cursor:pointer;}#mermaid-svg-jpT3lJTRdMScvwjO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jpT3lJTRdMScvwjO .arrowheadPath{fill:#333333;}#mermaid-svg-jpT3lJTRdMScvwjO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jpT3lJTRdMScvwjO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jpT3lJTRdMScvwjO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jpT3lJTRdMScvwjO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jpT3lJTRdMScvwjO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jpT3lJTRdMScvwjO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jpT3lJTRdMScvwjO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jpT3lJTRdMScvwjO .cluster text{fill:#333;}#mermaid-svg-jpT3lJTRdMScvwjO .cluster span{color:#333;}#mermaid-svg-jpT3lJTRdMScvwjO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jpT3lJTRdMScvwjO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jpT3lJTRdMScvwjO rect.text{fill:none;stroke-width:0;}#mermaid-svg-jpT3lJTRdMScvwjO .icon-shape,#mermaid-svg-jpT3lJTRdMScvwjO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jpT3lJTRdMScvwjO .icon-shape p,#mermaid-svg-jpT3lJTRdMScvwjO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jpT3lJTRdMScvwjO .icon-shape .label rect,#mermaid-svg-jpT3lJTRdMScvwjO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jpT3lJTRdMScvwjO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jpT3lJTRdMScvwjO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jpT3lJTRdMScvwjO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 安全规范
输入验证
白名单 + 禁拼接 SQL
认证授权
Token + 鉴权中间件
数据安全
敏感字段加密 + 日志脱敏
依赖安全
更新依赖 + 禁用漏洞版本
实施第四阶段 4d 的 4 项强制自检:
✓ SQL 注入防护:参数化查询,无拼接
✓ 权限验证:API 有鉴权
✓ 无敏感信息泄露:日志/响应不含密码/Token
✓ 输入验证:白名单(非黑名单)
设计决策:选白名单不选黑名单------黑名单永远漏、白名单永远全。特殊字符黑名单挡不住 Unicode 同形字符攻击,但"只允许字母数字和一组特定符号"的白名单挡得住。
代码审查检查点:SQL 注入 / XSS / CSRF / 敏感信息泄露。
2.6 后端规则
解决什么问题:约束后端代码的分层架构和数据访问方式。
Front Matter: 通过 globs 匹配后端文件路径,仅后端文件激活。
架构约定:
Controller → Service → Repository
只参数校验 通过接口注入 ORM 数据访问
不含业务逻辑 禁止 new 禁止拼 SQL
参数化查询:
csharp
// ✓ 正确
WHERE ORDER_NO = :orderNo
// ✗ 错误
WHERE ORDER_NO = '" + orderNo + "' // 字符串拼接
返回值约定:
csharp
public Task<ApiResult<OrderDto>> GetOrderAsync(...) // ✓
- 全部走
ApiResult<T>统一包装 - 异步方法以
Async结尾 - 异常由全局过滤器捕获,禁止控制器中 try-catch
实体类约定:
csharp
[Table("T_MAIN_ORDER")]
public class MainOrder : BaseEntity {
[Column(ColumnName = "ORDER_NO", Description = "单据编号", Length = 50)]
public string OrderNo { get; set; }
[Column(ColumnName = "REMARK", Description = "备注", ColumnDataType = "CLOB")]
public string Remark { get; set; } // 大文本字段必须显式声明类型
public int? Status { get; set; } // 可空字段用 ?
}
常见误区 :忘记设大字段的
ColumnDataType,数据库插入超过长度限制立即报错。
2.7 前端规则
解决什么问题:约束前端组件开发的标准写法。
Front Matter: 通过 globs 匹配前端组件文件路径。
组件规范:
- 用
<script setup>语法糖 - Props 必须有类型和默认值
- Emit 必须用
defineEmits - 单文件组件 ≤ 300 行
状态管理三层策略:
| 层级 | 适用 |
|---|---|
ref/reactive |
组件内状态 |
全局 Store |
全局状态、跨组件共享 |
props/emit |
父子组件通信(避免全局事件总线) |
设计决策:禁用全局事件总线是因为它制造"全局耦合",发出方和接收方在代码上看不见联系,调试地狱。全局 Store 至少有文件可查。
API 调用统一在 src/api/,命名 动词+名词:getOrderList、createOrder。
2.8 提交授权机制(重点)
解决什么问题 :把"git 操作"从 AI 的常规能力中抽离为"用户专属授权动作"。
最高优先级声明:
Agent 禁止自动执行 git add / git commit / git push / git stash
仅当用户明确说「提交 / commit / push / 帮我写 commit message」才可执行
绝不允许的"暗示提交"行为:
- ❌ Implement 结束甩出可复制的
git add && git commit命令块 - ❌ 用"需用户授权后执行"+ 命令示例 结尾
- ❌ 因为方案里写了"提交"一节就把它当授权
没有授权时 Agent 应该做的:
- 简要说改动了哪些文件(
git status内部核对,不必贴满输出) - 一句话「未提交,需要时请说提交」即可
- 不给 commit message 模板(除非用户问)
用户授权一次只对一个 commit 生效------这是另一个精妙处。授权不是一张通票,而是一次性凭证。
设计哲学 :Git 是人机协作的最后一道防火墙。AI 可以写错代码(IDE 能撤销),可以违反规范(Hook 能拦截),但 push 到远程仓库后是物理意义上的不可逆。所以提交权 100% 留在人手里。
Conventional Commits + Spec 关联:
feat(FR-012): 新增业务单据导出功能
fix(FR-003): 修复列表分页异常
chore: 升级 UI 组件库至最新版本
结构性变更附加检查: 提交前跑项目文档同步检查脚本,不一致就先处理。
常见误区 :把"用户说
实施 Implement 阶段"理解为提交授权。错------这是开发授权,不是 Git 授权。后者必须显式包含"提交/commit/push"这些词。
2.9 知识图谱基础设施
解决什么问题 :为知识图谱提供位置约定 + 更新策略 + 白名单机制。
图谱产物位置:
| 产物 | 路径 |
|---|---|
| 持久图 | graphify-out/graph.json |
| 业务精简图 | graphify-out/graph-business.json |
| 标签缓存 | graphify-out/.graphify_labels*.json |
| 概览报告 | graphify-out/GRAPH_REPORT.md |
| 交互 HTML | graphify-out/graph-business.html |
| 语料白名单 | .graphifyignore |
白名单(非黑名单) :.graphifyignore 只列出会被纳入图谱的路径:
docs/**
前端核心业务目录/**
后端服务层/**
后端控制器层/**
数据模型层/**
禁止行为:
- ❌ 用图谱结论替代规范 AC(图谱是导航,规范才是真理)
- ❌ 把
INFERRED边直接写入规范(须先与用户确认)
巧妙设计点 :用白名单而不是黑名单------大部分仓库文件都不该进图谱(
node_modules、dist、临时脚本等)。白名单"一目了然你纳入了什么",黑名单"永远不知道漏没漏"。
2.10 双轨回答
解决什么问题:让 AI 既能"听话",又能"提醒"。
双轨回答结构(核心创新):
回答
├── 直接执行 ← 按用户当前要求快速给结果
└── 深度交互 ← 回到原始目标做审慎分析
├── 目标偏移检测
├── XY 问题识别
├── 路径依赖审视
└── 过度设计预警
设计决策:单轨回答的两个失败模式------
- 只「直接执行」:用户问错了 AI 也照办,最后做出无用功能
- 只「深度交互」:用户问个语法 AI 反复确认目标,体验灾难
双轨用结构化分割解决:先给答案,再可选地给"思考"。
交互力度控制:
| 任务类型 | 力度 |
|---|---|
| 小任务/低风险/纯确认 | 轻量,只指出明显更优路径 |
| 大任务/高风险/需求模糊 | 严格目标审视 + 方案比较 + 边界确认 |
常见误区 :以为 AI 反问就是"不听话"。其实合规的 AI 在高风险任务前应该先澄清再动手------这是规则要求的。
2.11 知识图谱入口查询
解决什么问题 :把"全库搜索"升级为"图谱定向查询",并且强制每次对话都做。
MCP 与 CLI 双通道:
1. 优先工具内置 MCP 查询
2. 不可用 → 终端 CLI 查询
入口查询完整六步流程:
#mermaid-svg-9ZZN0xBbB12ICmqu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9ZZN0xBbB12ICmqu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9ZZN0xBbB12ICmqu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9ZZN0xBbB12ICmqu .error-icon{fill:#552222;}#mermaid-svg-9ZZN0xBbB12ICmqu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9ZZN0xBbB12ICmqu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9ZZN0xBbB12ICmqu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9ZZN0xBbB12ICmqu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9ZZN0xBbB12ICmqu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9ZZN0xBbB12ICmqu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9ZZN0xBbB12ICmqu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9ZZN0xBbB12ICmqu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9ZZN0xBbB12ICmqu .marker.cross{stroke:#333333;}#mermaid-svg-9ZZN0xBbB12ICmqu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9ZZN0xBbB12ICmqu p{margin:0;}#mermaid-svg-9ZZN0xBbB12ICmqu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-9ZZN0xBbB12ICmqu .cluster-label text{fill:#333;}#mermaid-svg-9ZZN0xBbB12ICmqu .cluster-label span{color:#333;}#mermaid-svg-9ZZN0xBbB12ICmqu .cluster-label span p{background-color:transparent;}#mermaid-svg-9ZZN0xBbB12ICmqu .label text,#mermaid-svg-9ZZN0xBbB12ICmqu span{fill:#333;color:#333;}#mermaid-svg-9ZZN0xBbB12ICmqu .node rect,#mermaid-svg-9ZZN0xBbB12ICmqu .node circle,#mermaid-svg-9ZZN0xBbB12ICmqu .node ellipse,#mermaid-svg-9ZZN0xBbB12ICmqu .node polygon,#mermaid-svg-9ZZN0xBbB12ICmqu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9ZZN0xBbB12ICmqu .rough-node .label text,#mermaid-svg-9ZZN0xBbB12ICmqu .node .label text,#mermaid-svg-9ZZN0xBbB12ICmqu .image-shape .label,#mermaid-svg-9ZZN0xBbB12ICmqu .icon-shape .label{text-anchor:middle;}#mermaid-svg-9ZZN0xBbB12ICmqu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9ZZN0xBbB12ICmqu .rough-node .label,#mermaid-svg-9ZZN0xBbB12ICmqu .node .label,#mermaid-svg-9ZZN0xBbB12ICmqu .image-shape .label,#mermaid-svg-9ZZN0xBbB12ICmqu .icon-shape .label{text-align:center;}#mermaid-svg-9ZZN0xBbB12ICmqu .node.clickable{cursor:pointer;}#mermaid-svg-9ZZN0xBbB12ICmqu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9ZZN0xBbB12ICmqu .arrowheadPath{fill:#333333;}#mermaid-svg-9ZZN0xBbB12ICmqu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9ZZN0xBbB12ICmqu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9ZZN0xBbB12ICmqu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9ZZN0xBbB12ICmqu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9ZZN0xBbB12ICmqu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9ZZN0xBbB12ICmqu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9ZZN0xBbB12ICmqu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9ZZN0xBbB12ICmqu .cluster text{fill:#333;}#mermaid-svg-9ZZN0xBbB12ICmqu .cluster span{color:#333;}#mermaid-svg-9ZZN0xBbB12ICmqu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9ZZN0xBbB12ICmqu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9ZZN0xBbB12ICmqu rect.text{fill:none;stroke-width:0;}#mermaid-svg-9ZZN0xBbB12ICmqu .icon-shape,#mermaid-svg-9ZZN0xBbB12ICmqu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9ZZN0xBbB12ICmqu .icon-shape p,#mermaid-svg-9ZZN0xBbB12ICmqu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9ZZN0xBbB12ICmqu .icon-shape .label rect,#mermaid-svg-9ZZN0xBbB12ICmqu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9ZZN0xBbB12ICmqu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9ZZN0xBbB12ICmqu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9ZZN0xBbB12ICmqu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 不存在
存在
命中
未命中
用户消息涉及业务代码
1·确认图谱存在
未命中分级入图
2·提取查询词 1-3 个
Spec/CHG ID → 文件名 → 领域词
3·执行 query
需链路用 path/explain
4·判定命中
6·回复模板可见行
5·分级入图 L1/L2/L3
图谱:查询词 | 命中/L1/L2/L3 | 关联 FR/路径
未命中三级处理(精妙):
| 级别 | 触发条件 | 操作 |
|---|---|---|
| L1 | 一般未命中 | 增量更新 + polish → 重 query |
| L2 | 仍无命中 + 功能性需求 | 先补规范文档 → 强制更新 + polish → query |
| L3 | 路径不在白名单 | 扩白名单 → 强制更新 + polish |
巧妙设计点:L1/L2/L3 区分了三种"未命中根因"------图谱过时(增量更新)、知识缺失(补文档)、白名单不够(扩边界)。不同根因有不同代价,分级避免每次都用最重的全量重建。
禁止行为:
- ❌ 图谱存在时跳过 query 直接全库搜索
- ❌ 用图谱结论替代规范 AC
- ❌ 每次未命中默认全量重建(仅 L2/L3 或 Implement 结束用)
第三部分 · Hooks 自动化机制深度解读
3.1 Hooks 的角色:自动化守卫
Hooks 是文件读写时机点 的脚本,由工具在写文件、执行命令时自动触发。它们读取 stdin 的 JSON payload,输出 JSON 决定 permission(allow / ask / deny)或注入 additional_context。
FileSystem Hook 脚本 Agent FileSystem Hook 脚本 Agent #mermaid-svg-Ky9iV12DyrIPgInp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ky9iV12DyrIPgInp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ky9iV12DyrIPgInp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ky9iV12DyrIPgInp .error-icon{fill:#552222;}#mermaid-svg-Ky9iV12DyrIPgInp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ky9iV12DyrIPgInp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ky9iV12DyrIPgInp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ky9iV12DyrIPgInp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ky9iV12DyrIPgInp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ky9iV12DyrIPgInp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ky9iV12DyrIPgInp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ky9iV12DyrIPgInp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ky9iV12DyrIPgInp .marker.cross{stroke:#333333;}#mermaid-svg-Ky9iV12DyrIPgInp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ky9iV12DyrIPgInp p{margin:0;}#mermaid-svg-Ky9iV12DyrIPgInp .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Ky9iV12DyrIPgInp text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-Ky9iV12DyrIPgInp .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Ky9iV12DyrIPgInp .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-Ky9iV12DyrIPgInp .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-Ky9iV12DyrIPgInp .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-Ky9iV12DyrIPgInp #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-Ky9iV12DyrIPgInp .sequenceNumber{fill:white;}#mermaid-svg-Ky9iV12DyrIPgInp #sequencenumber{fill:#333;}#mermaid-svg-Ky9iV12DyrIPgInp #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-Ky9iV12DyrIPgInp .messageText{fill:#333;stroke:none;}#mermaid-svg-Ky9iV12DyrIPgInp .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Ky9iV12DyrIPgInp .labelText,#mermaid-svg-Ky9iV12DyrIPgInp .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-Ky9iV12DyrIPgInp .loopText,#mermaid-svg-Ky9iV12DyrIPgInp .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-Ky9iV12DyrIPgInp .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Ky9iV12DyrIPgInp .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Ky9iV12DyrIPgInp .noteText,#mermaid-svg-Ky9iV12DyrIPgInp .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-Ky9iV12DyrIPgInp .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Ky9iV12DyrIPgInp .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Ky9iV12DyrIPgInp .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Ky9iV12DyrIPgInp .actorPopupMenu{position:absolute;}#mermaid-svg-Ky9iV12DyrIPgInp .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-Ky9iV12DyrIPgInp .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Ky9iV12DyrIPgInp .actor-man circle,#mermaid-svg-Ky9iV12DyrIPgInp line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-Ky9iV12DyrIPgInp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} alt不涉及关心场景涉及关心场景 即将写业务代码(payload: path, contents)读 stdin JSON检测条件{"permission":"allow"}{"permission":"ask","user_message":"...","agent_message":"..."}实际写入(被允许后)
触发机制总览:
| Hook 脚本 | 触发时机 | 触发条件 |
|---|---|---|
| 规范先行守门 | 写代码文件之前 | 路径不在测试/docs/配置/node_modules/dist/build |
| 变更历史同步 | 写完变更文档之后 | 路径匹配变更文档模式 |
| 安全提醒注入 | 写后端文件之后 | 路径含控制器/服务层,且内容含敏感关键词 |
| 结构变更守卫 | 执行 shell 命令之前 | 命令含目录变更操作 |
3.2 规范先行守门
职责:写实现代码前检查"近 3 天"是否有规范文档。
为什么排除这些目录:
| 排除项 | 理由 |
|---|---|
| 测试文件 | 测试文件本身就是规范的产物,不需要再检查规范 |
docs/ |
文档区,不是实现代码 |
| 工具配置目录 | 配置目录 |
node_modules/ / dist/ / build/ |
依赖与构建产物 |
为什么"近 3 天":
设计决策 :"近 3 天"是个启发式阈值------
- 不太短(避免周末停工后周一所有文档都"过时")
- 不太长(避免很久前的旧规范被当成本次开发的证据)
它不 严格校验"这个文件是不是真和这个规范相关",因为做严格关联分析成本太高。3 天窗口是90% 场景够用、10% 误放/误拦的工程权衡。
常见误区 :以为Approved状态会被自动检查。错------守门脚本不检查文档状态字段,只看时间戳。状态评审完全靠人 + 规则 + 文档留痕保证。
3.3 变更历史同步
职责:写完变更文档后自动提醒回填关联规范的变更历史。
核心逻辑: 从变更文档内容里抓取关联的规范 ID 引用(如 FR-001)。
注入的提醒:
【SDD Hook】变更文档已写入:<path>(关联规范:FR-XXX)
下一步(必须完成,否则 Specify 阶段视为未退出):
1. 打开关联规范文档(docs/specs/ 目录)
2. 找到末尾的「## 变更历史」表格,追加一行
3. 若表格不存在,在文档最后新增该表格后再追加
设计哲学 :变更历史是规范的尾部"日记",不是变更文档的一部分。这种"尾部追加"的设计让规范阅读时一眼能看到全部历史,而各变更文档可被删/重命名而不污染主文档。
为什么是"提醒"而不是"拦截" :输出 additional_context 而非 permission: ask------不阻断写入,只是把消息塞进 Agent 的下一轮上下文。Agent 会看到提醒、记得回填,但用户不会被打断。
3.4 安全提醒注入
职责:写后端文件、且内容含敏感关键词时,注入安全自检清单。
触发条件: 路径含控制器或服务层,排除测试文件和配置目录。
敏感关键词列表(设计精妙):
| 类别 | 关键词示例 |
|---|---|
| API 输入绑定 | FromBody, FromQuery, FromRoute |
| HTTP 写操作 | HttpPost, HttpPut, HttpPatch, HttpDelete |
| 直 SQL 关键词 | INSERT , UPDATE , DELETE |
| ORM 写操作 | Insertable, Updateable, ExecuteCommand |
| 敏感字段 | password, Password, token, Token, secret |
巧妙设计点 :关键词覆盖输入面、操作面、数据面 三个维度。任一命中即触发------宁可多提醒不要漏。注意
INSERT/UPDATE/DELETE末尾带空格,避免误匹配无害变量名。
注入的自检清单:
✓ SQL 注入防护:使用参数化查询,无字符串拼接
✓ 权限验证:API 端点已有鉴权中间件或标注
✓ 无敏感信息泄露:响应体/日志不含密码、Token、密钥
✓ 输入验证:用户传入参数已做白名单校验或 DTO 验证
任一项 ❌ → 禁止标记 Task 完成
为什么排除测试文件:测试代码可能故意写"不安全 SQL"做反例验证,没必要每次提醒。
3.5 结构变更守卫
职责:在执行 shell 命令前检测目录变更类命令,提醒可能需要同步项目总览文档。
模式列表: 包括 git mv、move-item、rename-item、mkdir、mv、ren 等目录操作命令。
设计决策 :这里用
permission: ask(不像变更提醒用 additional_context),因为目录改动的影响面更大也更不可逆。让用户在执行前看到提示框,而不是事后追溯。
3.6 崩溃放行(fail open)的设计决策
所有 Hook 在异常块都返回 permission: allow。
设计决策:"崩溃放行"而非"崩溃拦截"------
选项 优点 缺点 failClosed: true 安全更强 Hook 一崩溃整个 IDE 卡住,用户无法工作 failClosed: false 可用性更强 极端情况下漏检一次 Hook 是辅助,不是唯一防线。规则、评审、测试、人工 review 都还在,少一次自动检查不致命;但 Hook 崩溃挡住所有写文件操作就是灾难。
第四部分 · Commands 命令系统解读
4.1 Slash 命令的概念
Slash 命令是用户主动触发的标准化提示模板 ------在聊天框输入 /new-spec 或 /change-spec,工具会自动加载对应 .md 文件作为系统提示。
当前可用:
| 命令 | 描述 | 文件 |
|---|---|---|
/new-spec |
创建新规范文档 | commands/00-sdd/new-spec.md |
/change-spec |
创建变更文档 | commands/00-sdd/change-spec.md |
4.2 变更文档命令执行流程
信息来源优先级(关键):
1. 已存在的 docs/plans/*.md ← 最权威
2. 工具草稿目录中的 plan ← 草稿也可参考
3. 关联的现有规范
4. 用户当前消息、附件、上下文
设计哲学 :从已有文档出发优先于反复问用户。AI 应当主动归纳信息而不是机械式 Q&A。
模板结构(必须包含 7 章节):
markdown
# [变更标题] Design
**关联规范**:FR-XXX
**状态**:Draft / Review / Approved / Implemented / Verified / Deployed
**版本**:v1.0
**日期**:YYYY-MM-DD
**提出人**:[姓名/角色]
**优先级**:高 / 中 / 低
## 1. 变更背景
## 2. 变更目标
## 3. 变更内容
## 4. 涉及范围(前端 / 后端 / 数据库)
## 5. 接口变更(如有)
## 6. 验收标准
## 7. 注意事项
输出规范:
- 文件路径:
docs/change/CHG-YYYY-MMDD-简要描述.md - 初始状态
Draft,版本v1.0 - 不要默认进入逐步问答;优先从 Plan/上下文直接成稿
生成后符合性检查清单:
[ ] 已填写关联规范 ID (FR-XXX)
[ ] 状态已设为 Draft
[ ] 变更背景已说明业务上下文
[ ] 变更内容已列出具体变更点
[ ] 涉及范围已标注文件路径
[ ] 验收标准可量化、可验证
评审门联动(与 Plan Build 衔接):
- 新建变更文档初始
Draft;实施前须Approved - 用户 Plan → Build 且正式方案已落档 → Agent 须把状态改
Approved并填## 评审记录 - 也可分阶段确认:先对话「通过」,再写 Plan,再 Build
4.3 命令与 SDD 四阶段的关系
#mermaid-svg-BNHsQwgsOVtCQvA6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BNHsQwgsOVtCQvA6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BNHsQwgsOVtCQvA6 .error-icon{fill:#552222;}#mermaid-svg-BNHsQwgsOVtCQvA6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BNHsQwgsOVtCQvA6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BNHsQwgsOVtCQvA6 .marker.cross{stroke:#333333;}#mermaid-svg-BNHsQwgsOVtCQvA6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BNHsQwgsOVtCQvA6 p{margin:0;}#mermaid-svg-BNHsQwgsOVtCQvA6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BNHsQwgsOVtCQvA6 .cluster-label text{fill:#333;}#mermaid-svg-BNHsQwgsOVtCQvA6 .cluster-label span{color:#333;}#mermaid-svg-BNHsQwgsOVtCQvA6 .cluster-label span p{background-color:transparent;}#mermaid-svg-BNHsQwgsOVtCQvA6 .label text,#mermaid-svg-BNHsQwgsOVtCQvA6 span{fill:#333;color:#333;}#mermaid-svg-BNHsQwgsOVtCQvA6 .node rect,#mermaid-svg-BNHsQwgsOVtCQvA6 .node circle,#mermaid-svg-BNHsQwgsOVtCQvA6 .node ellipse,#mermaid-svg-BNHsQwgsOVtCQvA6 .node polygon,#mermaid-svg-BNHsQwgsOVtCQvA6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BNHsQwgsOVtCQvA6 .rough-node .label text,#mermaid-svg-BNHsQwgsOVtCQvA6 .node .label text,#mermaid-svg-BNHsQwgsOVtCQvA6 .image-shape .label,#mermaid-svg-BNHsQwgsOVtCQvA6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-BNHsQwgsOVtCQvA6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BNHsQwgsOVtCQvA6 .rough-node .label,#mermaid-svg-BNHsQwgsOVtCQvA6 .node .label,#mermaid-svg-BNHsQwgsOVtCQvA6 .image-shape .label,#mermaid-svg-BNHsQwgsOVtCQvA6 .icon-shape .label{text-align:center;}#mermaid-svg-BNHsQwgsOVtCQvA6 .node.clickable{cursor:pointer;}#mermaid-svg-BNHsQwgsOVtCQvA6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BNHsQwgsOVtCQvA6 .arrowheadPath{fill:#333333;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BNHsQwgsOVtCQvA6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BNHsQwgsOVtCQvA6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BNHsQwgsOVtCQvA6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BNHsQwgsOVtCQvA6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BNHsQwgsOVtCQvA6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BNHsQwgsOVtCQvA6 .cluster text{fill:#333;}#mermaid-svg-BNHsQwgsOVtCQvA6 .cluster span{color:#333;}#mermaid-svg-BNHsQwgsOVtCQvA6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BNHsQwgsOVtCQvA6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BNHsQwgsOVtCQvA6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-BNHsQwgsOVtCQvA6 .icon-shape,#mermaid-svg-BNHsQwgsOVtCQvA6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BNHsQwgsOVtCQvA6 .icon-shape p,#mermaid-svg-BNHsQwgsOVtCQvA6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BNHsQwgsOVtCQvA6 .icon-shape .label rect,#mermaid-svg-BNHsQwgsOVtCQvA6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BNHsQwgsOVtCQvA6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BNHsQwgsOVtCQvA6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BNHsQwgsOVtCQvA6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Hook 自动提醒
用户输入 /change-spec
命令模板
阶段1·规范
生成变更文档
阶段2·方案
阶段3·任务
阶段4·实施
巧妙设计点 :命令系统不是"独立工具",而是 SDD 四阶段的入口 之一。
/new-spec进 feature 流程,/change-spec进变更流程,从命令到 Hook 形成闭环。
第五部分 · Skills 技能系统深度解读
5.1 Skills 的定位
Skills = 领域知识沉淀分册。和规则不同,规则是"放之四海而皆准"的工程纪律,Skills 是"这个项目特有"的业务知识。
| 维度 | Rules | Skills |
|---|---|---|
| 加载方式 | alwaysApply 或 globs 自动 | 触发词或显式引用 |
| 内容性质 | 工程纪律 | 业务领域知识 |
| 跨项目可移植 | 高 | 低(项目特定) |
5.2 业务领域 Skill 解读
入口导航
Front Matter 含触发词:
yaml
---
name: business-domain-skill
description: >-
某业务系统的架构、领域词汇、核心组件绑定、业务流程与代码定位。
触发词:业务单据、数据绑定、主业务模块、状态管理、知识图谱、影响面、表结构...
---
设计决策 :触发词是 Skill 的"召唤密码"。当用户消息含这些词时,工具自动加载本 Skill。让 AI 按需访问知识而非每次都灌满全部。
阅读顺序表(精妙):
| 场景 | 打开 |
|---|---|
| 不熟悉项目 | SKILL.md → 领域词汇表 → 项目总览 |
| 改核心组件绑定 | 组件绑定机制文档 |
| 改业务流程 | 业务流程与代码锚点文档 |
| 实施新需求 | 开发任务 Checklist |
| 查数据库表 / 写 SQL | 数据查询工具 |
巧妙设计点:用"场景表"代替"目录树"------新人不知道有哪些文件,但一定知道自己要做什么。从场景出发的索引降低使用成本。
领域词汇表
核心实体表把业务术语 ↔ 代码符号 ↔ 数据库表三者对齐:
| 术语 | 说明 | 代码/表 |
|---|---|---|
| 主业务对象 | 在线填写的核心业务单据 | T_MAIN_ORDER、MainOrder.cs、mainStore |
| 关联单据 | 与主单据关联的明细 Spread | DetailData.js、SubmitDetailServiceAsync |
| 业务线 | 不同业务分支入口 | BusinessArgs.js、后端 BusinessLine 判断 |
| 模板配置 | 组件模板版本与加载 | requestTemplateVersion、Sheet.vue |
设计决策 :术语表的价值不是定义业务名词,而是把"业务词"映射到"代码搜索关键词"。AI 看到"业务单据"立刻知道去搜主业务表和主 Store。
业务流程与代码锚点
每个业务流程都给出"步骤 → 位置"映射:
| 步骤 | 位置 |
|---|---|
| 页面入口 | 主视图组件 |
| 加载模板 | 主 Store、模板组件 |
| 绑定扫描 | 绑定工具模块 |
| 保存请求 | API 层 → 保存接口 → 后端控制器 |
| 保存服务 | 控制器 → 业务服务层 → 数据访问层 |
巧妙设计点:把"流程"和"代码锚点"用表格强对齐。新人改一个 bug,沿着表格就能从前端走到数据库。
开发任务 Checklist
各类任务都有专属 checklist,以"新后端 API"为例:
[ ] 服务接口层声明
[ ] 服务实现层
[ ] 控制器端点
[ ] 前端 API 方法
[ ] 参数化查询;数据访问层;DI 注册
[ ] 测试覆盖主要 AC
调试速查表(金子):
| 现象 | 优先检查 |
|---|---|
| 401 / 登录失效 | JWT、认证拦截器 |
| 保存无数据 | 数据提取是否走到正确方案分支 |
| 绑定为空 | 绑定扫描结果、模板配置 |
| DI 报错 | 依赖注入注册配置 |
| CORS | 开发代理、CORS 配置 |
| 提交失败 | 数据格式化、提交参数 |
5.3 数据库查询工具 Skill
提供类型映射表(数据库类型 ↔ 后端类型 ↔ ORM 注解),以及一个独立的命令行工具,连接数据库查询表结构并输出结构化 JSON。
调用方式:
bash
DbStructureTool --conn-from appsettings.json --owner SCHEMA --tables T_MAIN_ORDER,T_DETAIL
巧妙设计点:
- 参数化查询,仍是安全的(避免 SQL 注入)
- 支持从配置文件读取连接串,不裸传
- 输出 JSON 而不是文本,便于 AI 解析和回填到实体类
5.4 Skills 如何与规则和图谱协作
#mermaid-svg-IVkxzLFijniiQA3O{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IVkxzLFijniiQA3O .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IVkxzLFijniiQA3O .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IVkxzLFijniiQA3O .error-icon{fill:#552222;}#mermaid-svg-IVkxzLFijniiQA3O .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IVkxzLFijniiQA3O .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IVkxzLFijniiQA3O .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IVkxzLFijniiQA3O .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IVkxzLFijniiQA3O .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IVkxzLFijniiQA3O .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IVkxzLFijniiQA3O .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IVkxzLFijniiQA3O .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IVkxzLFijniiQA3O .marker.cross{stroke:#333333;}#mermaid-svg-IVkxzLFijniiQA3O svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IVkxzLFijniiQA3O p{margin:0;}#mermaid-svg-IVkxzLFijniiQA3O .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IVkxzLFijniiQA3O .cluster-label text{fill:#333;}#mermaid-svg-IVkxzLFijniiQA3O .cluster-label span{color:#333;}#mermaid-svg-IVkxzLFijniiQA3O .cluster-label span p{background-color:transparent;}#mermaid-svg-IVkxzLFijniiQA3O .label text,#mermaid-svg-IVkxzLFijniiQA3O span{fill:#333;color:#333;}#mermaid-svg-IVkxzLFijniiQA3O .node rect,#mermaid-svg-IVkxzLFijniiQA3O .node circle,#mermaid-svg-IVkxzLFijniiQA3O .node ellipse,#mermaid-svg-IVkxzLFijniiQA3O .node polygon,#mermaid-svg-IVkxzLFijniiQA3O .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IVkxzLFijniiQA3O .rough-node .label text,#mermaid-svg-IVkxzLFijniiQA3O .node .label text,#mermaid-svg-IVkxzLFijniiQA3O .image-shape .label,#mermaid-svg-IVkxzLFijniiQA3O .icon-shape .label{text-anchor:middle;}#mermaid-svg-IVkxzLFijniiQA3O .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IVkxzLFijniiQA3O .rough-node .label,#mermaid-svg-IVkxzLFijniiQA3O .node .label,#mermaid-svg-IVkxzLFijniiQA3O .image-shape .label,#mermaid-svg-IVkxzLFijniiQA3O .icon-shape .label{text-align:center;}#mermaid-svg-IVkxzLFijniiQA3O .node.clickable{cursor:pointer;}#mermaid-svg-IVkxzLFijniiQA3O .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IVkxzLFijniiQA3O .arrowheadPath{fill:#333333;}#mermaid-svg-IVkxzLFijniiQA3O .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IVkxzLFijniiQA3O .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IVkxzLFijniiQA3O .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IVkxzLFijniiQA3O .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IVkxzLFijniiQA3O .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IVkxzLFijniiQA3O .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IVkxzLFijniiQA3O .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IVkxzLFijniiQA3O .cluster text{fill:#333;}#mermaid-svg-IVkxzLFijniiQA3O .cluster span{color:#333;}#mermaid-svg-IVkxzLFijniiQA3O div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IVkxzLFijniiQA3O .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IVkxzLFijniiQA3O rect.text{fill:none;stroke-width:0;}#mermaid-svg-IVkxzLFijniiQA3O .icon-shape,#mermaid-svg-IVkxzLFijniiQA3O .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IVkxzLFijniiQA3O .icon-shape p,#mermaid-svg-IVkxzLFijniiQA3O .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IVkxzLFijniiQA3O .icon-shape .label rect,#mermaid-svg-IVkxzLFijniiQA3O .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IVkxzLFijniiQA3O .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IVkxzLFijniiQA3O .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IVkxzLFijniiQA3O :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户消息含触发词
加载领域 Skill
领域词汇表找术语映射
业务流程找代码锚点
配合图谱查询验证影响面
按 SDD 规范进入四阶段
按后端/前端规则编码
按测试规则写测试
协作要点:
- Skills 提供领域知识 ,规则 提供工程纪律 ,图谱 提供跨模块影响面。
- 触发词驱动 Skill 加载,globs 驱动规则加载,对话入口驱动图谱查询。
- 三者都是给 AI 的上下文增强,但来源不同、生命周期不同。
第六部分 · 各组件联动关系与协作流程
6.1 完整 feature 开发场景
场景 :用户说"给业务单据加一个优先级字段,前端可选高/中/低,后端落库,提交时校验非空"。
文件系统 Hooks 知识图谱 Agent 用户 文件系统 Hooks 知识图谱 Agent 用户 #mermaid-svg-FyuT47hqpUNJbLjY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FyuT47hqpUNJbLjY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FyuT47hqpUNJbLjY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FyuT47hqpUNJbLjY .error-icon{fill:#552222;}#mermaid-svg-FyuT47hqpUNJbLjY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FyuT47hqpUNJbLjY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FyuT47hqpUNJbLjY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FyuT47hqpUNJbLjY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FyuT47hqpUNJbLjY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FyuT47hqpUNJbLjY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FyuT47hqpUNJbLjY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FyuT47hqpUNJbLjY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FyuT47hqpUNJbLjY .marker.cross{stroke:#333333;}#mermaid-svg-FyuT47hqpUNJbLjY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FyuT47hqpUNJbLjY p{margin:0;}#mermaid-svg-FyuT47hqpUNJbLjY .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-FyuT47hqpUNJbLjY text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-FyuT47hqpUNJbLjY .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-FyuT47hqpUNJbLjY .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-FyuT47hqpUNJbLjY .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-FyuT47hqpUNJbLjY .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-FyuT47hqpUNJbLjY #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-FyuT47hqpUNJbLjY .sequenceNumber{fill:white;}#mermaid-svg-FyuT47hqpUNJbLjY #sequencenumber{fill:#333;}#mermaid-svg-FyuT47hqpUNJbLjY #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-FyuT47hqpUNJbLjY .messageText{fill:#333;stroke:none;}#mermaid-svg-FyuT47hqpUNJbLjY .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-FyuT47hqpUNJbLjY .labelText,#mermaid-svg-FyuT47hqpUNJbLjY .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-FyuT47hqpUNJbLjY .loopText,#mermaid-svg-FyuT47hqpUNJbLjY .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-FyuT47hqpUNJbLjY .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-FyuT47hqpUNJbLjY .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-FyuT47hqpUNJbLjY .noteText,#mermaid-svg-FyuT47hqpUNJbLjY .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-FyuT47hqpUNJbLjY .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-FyuT47hqpUNJbLjY .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-FyuT47hqpUNJbLjY .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-FyuT47hqpUNJbLjY .actorPopupMenu{position:absolute;}#mermaid-svg-FyuT47hqpUNJbLjY .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-FyuT47hqpUNJbLjY .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-FyuT47hqpUNJbLjY .actor-man circle,#mermaid-svg-FyuT47hqpUNJbLjY line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-FyuT47hqpUNJbLjY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 新增字段需求1关键词图谱检索2返回关联业务信息3加载业务Skill,启动SDD四阶段4编写规范(Draft)→方案→任务5评审通过(Plan Build)6规范标为Approved、归档评审记录7TDD编写测试+前后端代码8Hook校验合规放行、注入安全自检9自测+安全校验通过10规范变更为Implemented11强制更新知识图谱12开发完毕,待提交授权13确认提交14代码检查+Git提交15
关键节点的规则/Hook 触发:
| 步骤 | 触发的规则/Hook |
|---|---|
| 入口 query | 图谱查询规则 |
| 双轨回答 | 交互原则 |
| 加载 Skill | 领域 Skill(触发词命中) |
| 写规范 | SDD 阶段1 |
| 写代码前 | 规范先行守门检查 → allow |
| 写后端 | 安全提醒注入自检清单 |
| 写代码内容 | 代码风格 + 后端规则 + 前端规则 |
| 写测试 | 测试规则 |
| 安全自检 | 安全规则 |
| 提交 | Git 授权规则,授权后才执行 |
| Implement 结束 | 知识图谱强制更新 |
6.2 hotfix 简化流程场景
场景:用户说"业务单据备注字段最大长度从 200 改成 500"。
1. Agent 识别为 hotfix(纯字段调整,无分支)
2. 写变更文档(一段话)
3. Agent 自评通过
4. 跳过方案文档(hotfix 免)
5. 阶段4:直接改实体字段长度 + 数据库迁移
6. 写最小单测:500字能落库
7. 变更文档注「免 plan、自评通过」
8. 不更规范状态(hotfix 豁免)
巧妙设计点 :hotfix 流程短到 8 步,但变更文档与最小测试不能省。这就是"分层管控"------简单事简单做,但不允许零纪律。
第七部分 · 设计精髓与巧妙之处总结
7.1 变更量级分级 --- 兼顾效率与质量
不同量级走不同流程:hotfix 8 步搞定、feature 完整四阶段、structural 加文档同步检查。
本质:把"质量保障"做成可调档的旋钮,而不是一刀切的开关。
7.2 规则优先级层级表 --- 解决冲突的圣经
6 级优先级让任意冲突都能裁决,不会出现"两个规则都说我对"的死锁。
本质:明确"谁是终审"。
7.3 存量代码策略"触碰即纳入" --- 渐进式覆盖
不强迫历史回填,但不允许新增混乱。
本质:尊重沉没成本,但守住增量纪律。
7.4 测试覆盖率"只要求 diff 覆盖" --- 务实而非教条
存量改动不强求整模块 80%,只要求新增/变更的代码行被覆盖。
本质:避免"为了 80% 而 80%"的反向价值------测试服务于质量,不是服务于报表。
7.5 Git 提交授权机制 --- 人始终掌握最终控制权
git add / commit / push 必须用户显式说"提交",授权一次只对一个 commit。
本质:不可逆动作的钥匙永远在人手里。
7.6 知识图谱入口查询 --- 给 AI 上下文记忆
每次对话先 query,回复必含图谱声明行。
本质 :让 AI 在大型代码库里记得自己在哪。
7.7 Hooks 的崩溃放行 --- 容错优先
崩溃放行而非崩溃拦截。
本质:辅助工具不能成为开发瓶颈。
7.8 双轨回答设计 --- 适配不同复杂度
直接执行 + 深度交互,按需展开。
本质:既不机械顺从,也不喋喋不休。
7.9 四阶段评审门 --- 每步检查、可分级简化
feature 严、hotfix 简,但都有留痕。
本质:流程是骨架,不是束缚。
7.10 规范状态流 --- 全生命周期管理
Draft → Approved → Implemented → Verified → Deployed
本质:从需求到上线的每一步都有名字、有责任人、有可审计的痕迹。
第八部分 · 新人快速上手指南
8.1 五分钟理解核心概念
| 概念 | 一句话 |
|---|---|
| SDD 四阶段 | 规范 → 方案 → 任务 → 实施,顺序不可颠倒 |
| 变更量级 | hotfix(小改动)/ feature(新能力)/ structural(架构调整) |
| 三阶段评审门 | 规范、方案、任务三道门;feature/structural 须用户显式通过 |
| 规则优先级 | Git 提交授权 > 安全 > 流程 > 风格 > 交互 |
| 入口图谱查询 | 每次对话先 query,回复必含图谱声明行 |
| 存量策略 | 不动存量,触碰即纳入(先补简化规范) |
| 提交授权 | AI 不主动 git,必须用户显式说「提交/commit/push」 |
8.2 第一次使用的注意事项
- 不要跳过图谱查询------即便你觉得你知道怎么改,仍然要 query。这不是为了 AI,是为了团队留痕。
- 不要跳过规范文档------hotfix 也要写变更文档,再小都不能省。
- Plan Build 时记得让 AI 改状态 ------
Draft → Approved+ 写评审记录是同一轮的事。 - 测试用例名必须含
AC-XXX------这是 SDD 验证门的命脉。 - 结构性变更必看项目总览文档------目录改名、入口改路径都要同步。
- 不要被 Hook 的 ask 吓到------它在保护你。看清楚消息后再决定继续还是退回。
- 提交前跑 lint ------前端涉及业务模块时,lint 检查是
git add前的必跑动作。
8.3 常见问题 FAQ
Q1: AI 写完代码就给我贴 git 命令了,我能直接复制粘贴吗?
A: 这违反 Git 授权规则。如果用户没说"提交",AI 不应给命令块。看到这种情况可以说"我没要求提交"提醒它。
Q2: hotfix 还要写文档?太麻烦了吧?
A: hotfix 只要变更文档一段话+ 最小测试,5 分钟就能搞定。但这一段话能让半年后的同事知道"为什么改、改了什么",价值远大于成本。
Q3: 我看规范状态是 Draft,但 AI 已经在写代码了,怎么回事?
A: 检查评审记录是否已有"规范阶段通过"的记录。若用户 Plan → Build 时 AI 漏改 Approved,是 AI 的失误,让它补改即可。
Q4: 图谱查询返回"未命中",怎么办?
A: 按 L1/L2/L3 分级处理:先增量更新(L1),仍无 → 先补规范再强制更新(L2),路径不在白名单 → 扩白名单(L3)。
Q5: 后端文件每次都被安全提醒注入清单,烦不烦?
A: 烦才好。这清单逼你每次都做安全自检,而不是写完就忘。测试文件已被排除,正常业务文件不应豁免。
Q6: AI 在回答里反问目标,是不是不听话?
A: 不是。交互原则要求高风险任务先澄清目标。短任务可直接做,但目标模糊就该先问。
Q7: 项目总览文档是什么?我需要维护它吗?
A: 这是项目的"总览地图",结构性变更(增删一级目录、改入口路径、改分层职责)必须同步。日常 feature 不涉及。
Q8: 我可以新增一个 Skill 吗?
A: 可以。Skill 适合放"项目特定的领域知识"(业务术语、流程锚点、模板配置)。新增后在描述里加触发词,让工具能自动加载。
Q9: 工具草稿方案和正式方案有什么区别?
A: 前者是草稿 (工具临时生成),后者是正式技术方案。第四阶段实施只认正式方案。
Q10: 测试覆盖率必须 80% 才能合并吗?
A: 仅新建模块强制 80%。存量改动只要求 diff 覆盖------你这次改的代码行被覆盖即可。
结语
这套规则引擎的本质,是把"工程师的经验"翻译为"AI 可执行的纪律"。它不是为了限制 AI,而是为了让 AI 在大型项目中保持长期一致性------这正是工程化和原型实验的本质区别。
读完本文后,你下一步应该做的:
- 打开任意一个规则文件,对照本文找到对应解读
- 在工具里输入
/change-spec,体验完整的 SDD 流程 - 观察 Hook 的 ask 提示,理解它在保护什么
- 在新需求时主动说一句"先做图谱查询",培养 SDD 直觉
- 提交前必看
git status,确认 AI 没有越权
最后的话:规则不是天花板,是脚手架。当你熟悉到能解释"为什么这样设计"的时候,你已经具备扩展和优化它的能力。这套系统是开放的,期待你的贡献。