前言
agent-spec 是一个意图编译器(Intent Compiler):人类的意图经它编译为结构化 需求(IR),再降低为可机械验证的任务合同(Task Contract),最后由确定性管线证明 “代码仍然遵守着当初的意图”。它是给 AI 协作时代准备的工程底座——当实现代码越来越 多地由 Agent 写出,人类的注意力应该花在定义正确上,而把验证正确交给机器。
本书基于 agent-spec 1.0.0(兼容性承诺生效版)写成,中文先行;英文版作为 后续工作,将在本书结构稳定后启动。全书由浅入深,以用法为主线:第一、二部分让你 从零跑通并精通合同工作流;第三、四部分进入意图编译与知识层;第五部分收束于设计 哲学与架构全景。
本书自身就是 agent-spec 工作流的展品:它有自己的 KLL 需求(REQ-AGENT-SPEC-BOOK)
与任务合同,每一章的定位锚、Mermaid 图、目录完整性都由绑定测试机械守卫——细节见
附录 C。
阅读准备
前置知识
- 命令行基础:会在终端运行命令、读输出。
- Git 常识:知道 commit / branch / staged 是什么。
- 不需要:Rust 编程能力(除非你读第 16 章 Atlas 的实现细节)、任何特定 AI 工具的经验——agent-spec 是 agent-agnostic 的。
推荐阅读路径
路径 A:实践者速通(今天就要用起来)
前言 → 第 1 章 → 第 2 章 → 第 3 章 → 第 4 章 → 第 5 章 → 第 6 章 → 第 7 章 → 第 8 章 → 附录 A
读完你能独立写合同、过质量门、跑验证、看懂五种 verdict,并把 guard 挂进 CI。
路径 B:架构师深读(评估它是否值得引入团队)
前言 → 第 1 章 → 第 18 章 → 第 19 章 → 第 10 章 → 第 11 章 → 第 13 章 → 附录 D
这是一条评估用的跳读路径:刻意越过各章声明的前置依赖,先看哲学与架构, 再抽查编译管线,最后用两条端到端轨迹验证叙事完整性。读不顺处按定位锚补课即可。
全书知识地图
graph TD
subgraph P1["第一部分 入门"]
C1[ch01 意图编译器] --> C2[ch02 第一个合同] --> C3[ch03 七步工作流]
end
subgraph P2["第二部分 合同"]
C4[ch04 四要素] --> C5[ch05 场景 DSL] --> C6[ch06 lint]
C6 --> C7[ch07 lifecycle] --> C8[ch08 边界与守卫] --> C9[ch09 验收追溯]
end
subgraph P3["第三部分 意图编译"]
C10[ch10 PRD→IR] --> C11[ch11 治理三轴] --> C12[ch12 计划]
C12 --> C13[ch13 溯源重放] --> C14[ch14 编译束]
end
subgraph P4["第四部分 知识与生态"]
C15[ch15 KLL] --> C16[ch16 Atlas] --> C17[ch17 Wiki与MCP]
end
subgraph P5["第五部分 理念与架构"]
C18[ch18 哲学] --> C19[ch19 架构全景]
end
C3 --> C4
C9 --> C10
C14 --> C15
C17 --> C18
C8 -.符号验证.-> C16
C13 -.证据链.-> C15
图例:实线为阅读顺序(部分之间的推荐先后),虚线为跨部分的主题关联; 各章严格的前置依赖以每章定位锚为准。
标记约定
- 标注为真实运行的命令输出来自 agent-spec 1.0.0,未经虚构;教程性示例 (如第 2 章的“用户注册API“演练)会注明“示例“。仓库快照数字(合同数、 文档数等)以写作时为准,仓库会继续生长。
- “详见第 N 章” 是交叉引用的规范格式(行文中也会自然使用“上一章/下一章“)。
- 每章开篇的
> **定位**告诉你这一章讲什么、依赖哪一章(必要时含适用场景)。
第 1 章 意图编译器是什么
定位:本章用一次对比和一张图讲清 agent-spec 的核心命题——审查点位移。 无前置依赖。适用于所有读者的第一站。基于 agent-spec 1.0.0。
一个熟悉的困境
你让 AI Agent 实现一个用户注册接口。十分钟后它交回 500 行 diff。现在轮到你了: 逐行读代码、猜它有没有处理重复邮箱、担心它偷偷改了不该动的文件。你的时间花在了 读实现上,而实现恰恰是 Agent 最擅长产出的东西。
传统协作与 agent-spec 协作的注意力分配对比:
传统: 写 Issue (10%) → Agent 写码 (0%) → 读 diff (80%) → 批准 (10%)
agent-spec: 写合同 (60%) → Agent 写码 (0%) → 读 explain (30%) → 批准 (10%)
这就是审查点位移(Review Point Displacement):人类的高价值时间从“读 500 行 代码 diff“移动到“写 50-80 行自然语言合同“。合同定义什么是正确;机器验证代码是否 正确;人类最后做的是合同验收,不是代码审查。
为什么叫“编译器“
编译器的本质是:把一种表达(源语言)确定性地变换为另一种表达(目标语言),并在 每一步给出可检查的中间产物。agent-spec 对“意图“做同样的事:
graph LR
A[人类意图<br/>PRD·对话·Issue] -->|intake| B[需求 IR<br/>REQ-* 文档]
B -->|lower| C[任务合同<br/>Task Contract]
C -->|Agent 实现| D[代码]
D -->|lifecycle 验证| E[五种 verdict]
E -.liveness 回灌.-> B
- 需求 IR:人类确认后的结构化需求(
knowledge/requirements/REQ-*.md),是 编译器的中间表示——就像编译器的 IR 一样,它是后续一切变换的锚点。 - 任务合同:需求降低(lower)后的可执行契约,四要素齐备(详见第 4 章)。
- 验证:lint → 结构 → 边界 → 测试的确定性四层管线(详见第 7 章),零 token 成本,无假阴性。
- liveness 回灌:验证结果实时回答“这条需求现在还被守着吗“——honored / violated / unproven,永远重算,从不落盘(详见第 15 章)。
它不做什么
诚实是这个工具的性格。agent-spec 不替你判断产品方向(合同写错了它只能证明“错的 被实现了“);不评审命名品味;不承诺性能验证(NFR 需要专门 runner);也不托管审批 工作流——谁批准了什么,是编排系统的事,编译器只提供事实与摘要(ADR-001,详见 第 18 章)。
从下一章开始动手。五分钟后你会有第一个被机器证明的合同。
第 2 章 安装与第一个合同
定位:本章带你在五分钟内完成安装、初始化第一个合同并跑通第一次验证。 前置依赖:第 1 章的心智模型。基于 agent-spec 1.0.0。
安装
安装需要 Rust 工具链(rustup.rs);使用则不需要任何 Rust 知识——装完就是一个普通 CLI。
cargo install agent-spec
agent-spec --version
agent-spec 1.0.0
也可以克隆仓库一键安装 CLI + 全部技能文件(供 Claude Code / Codex / Cursor 等 Agent 使用):
git clone https://github.com/ZhangHanDong/agent-spec && cd agent-spec && ./install-skills.sh
初始化第一个合同
init 在当前目录生成合同文件(保留你给的大小写),所以先进入 specs/:
mkdir -p specs && cd specs
agent-spec init --level task --lang zh --name "用户注册API"
cd ..
生成的 specs/用户注册API.spec.md 是一个骨架。合同的完整语法在第 4、5 章展开,
这里先感受最小可用形态:
spec: task
name: "用户注册API"
---
## 意图
为认证模块添加注册端点:邮箱+密码注册,成功后发送验证邮件。
## 边界
### 允许修改
- src/auth/**
- tests/auth/**
## 完成条件
场景: 注册成功
测试: test_register_returns_201
假设 不存在该邮箱的用户
当 客户端提交注册请求
那么 响应状态码为 201
场景: 重复邮箱被拒绝
测试: test_register_rejects_duplicate
假设 已存在该邮箱的用户
当 客户端提交相同邮箱的注册请求
那么 响应状态码为 409
注意两点纪律:每个场景都绑定一个测试(测试: 行),异常场景不少于正常场景
——这两条会被质量门强制(详见第 6 章)。
第一次质量门与验证
agent-spec lint specs/用户注册API.spec.md --min-score 0.7
agent-spec lifecycle specs/用户注册API.spec.md --code . --format json
lifecycle 是主质量门:先重跑 lint(防合同被篡改),再依次跑结构、边界、测试三层
验证。此刻测试还没写,你会看到 skip verdict——skip 不等于 pass,五种 verdict
各司其职(详见第 7 章)。当 Agent(或你)补上实现与测试后,摘要会收敛为(示例,字段与真实输出一致——
真实摘要固定六键,按字母序):
"summary": { "failed": 0, "passed": 2, "pending_review": 0, "skipped": 0, "total": 2, "uncertain": 0 }
你刚刚经历了什么
sequenceDiagram
participant H as 人类
participant CLI as agent-spec
participant A as Agent
H->>CLI: init(骨架)
H->>H: 填四要素(高价值时间在这里)
H->>CLI: lint(合同质量门)
A->>CLI: contract(读执行计划)
A->>A: 实现 + 测试
A->>CLI: lifecycle(自检重试循环)
CLI-->>H: explain(合同级摘要,验收)
这条链路的完整版就是下一章的七步工作流。
第 3 章 七步工作流
定位:本章给出 agent-spec 协作的全景流程:谁在哪一步做什么、用什么命令。 前置依赖:第 2 章。适合建立整体骨架后再深入各章。基于 agent-spec 1.0.0。
三个角色,七个步骤
人类定义正确(合同),Agent 实现代码,机器验证正确性。每一步都有明确的所有者:
graph TD
S1["① 人写合同<br/>agent-spec init"] --> S2["② 合同质量门<br/>agent-spec lint --min-score 0.7"]
S2 --> S3["③ Agent 读合同<br/>agent-spec contract"]
S3 --> S4["④ Agent 自检循环<br/>agent-spec lifecycle --code ."]
S4 -->|fail → 修码重试| S4
S4 --> S5["⑤ 守卫门<br/>agent-spec guard(pre-commit/CI)"]
S5 --> S6["⑥ 合同验收<br/>agent-spec explain --format markdown"]
S6 --> S7["⑦ 盖章归档<br/>agent-spec stamp / archive"]
style S1 fill:#2a2a35,stroke:#e8a845
style S6 fill:#2a2a35,stroke:#e8a845
琥珀色的两步(①⑥)是人类注意力所在;其余全部机械化。
每一步一句话
| 步 | 所有者 | 命令 | 要点 |
|---|---|---|---|
| ① 写合同 | 人 | init 后手写四要素 | 异常场景 ≥ 正常场景 |
| ② 质量门 | 机器 | lint --min-score 0.7 | 对合同做“代码审查“(详见第 6 章) |
| ③ 读合同 | Agent | contract <spec> | 决策、边界、完成条件三重约束 |
| ④ 自检循环 | Agent | lifecycle --code . --format json | fail→读证据→修码→重跑,不许改合同 |
| ⑤ 守卫 | 机器 | guard --spec-dir specs --code . | 全仓合同一次验证,CI 阻断 |
| ⑥ 验收 | 人 | explain --format markdown | 读合同级摘要,不读 diff |
| ⑦ 盖章 | 机器 | stamp --dry-run / archive | Git trailer 建立合同↔提交溯源 |
第④步的纪律(一句话版)
lifecycle 失败时,Agent 的义务是修代码,不是改合同——改合同让验证变绿 是谄媚(sycophancy),不是修复。逐 verdict 的完整重试协议详见第 7 章。
何时不用它
探索性原型(还不知道“做完“长什么样)、大型架构重构(边界难以定义)——这些先 自由写码,等能回答“什么是完成“了再立合同。合同适合边界清晰的功能与可复现的 bug 修复。
第 4 章 合同四要素
定位:本章逐一拆解任务合同的四个组成部分——意图、决策、边界、完成条件。 前置依赖:第 3 章。这是全书最值得反复翻的用法章之一。基于 agent-spec 1.0.0。
合同不是模糊的 Issue,而是一份精确的规格。四要素各自回答一个问题:
graph LR
I["意图 Intent<br/>做什么、为什么"] --> D["决策 Decisions<br/>怎么做(已定,不再讨论)"]
D --> B["边界 Boundaries<br/>能动什么、不能动什么"]
B --> C["完成条件 Completion Criteria<br/>怎样才算做完(可机械判定)"]
意图(Intent)——2 到 4 句话
聚焦“做什么和为什么“,带上下文(现状、这件事在整体中的位置),不写成小说:
## 意图
为现有认证模块添加用户注册端点。新用户通过邮箱+密码注册,成功后发送验证
邮件。这是用户体系的第一步,后续在此基础上添加登录与密码重置。
决策(Decisions)——已定的技术选择
只写已经定死的选择:具体技术、版本、参数。Agent 照做,不再购物:
## 已定决策
- 路由: POST /api/v1/auth/register
- 密码哈希: bcrypt, cost factor = 12
- 验证 Token: crypto.randomUUID(), 存数据库, 24h 过期
- 邮件: 使用现有 EmailService,不新建
三条纪律(lint 会盯着,详见第 6 章):每条决策至少被一个场景覆盖
(decision-coverage);说“所有入口/每个二进制“这类全称断言需要成比例的场景
(universal-claim);平台特定的照抄决策要打 [platform-specific] 标记。
边界(Boundaries)——三重约束
## 边界
### 允许修改
- src/auth/**
- tests/auth/**
- migrations/
### 禁止
- 不要添加新依赖
- 不要修改现有登录端点
## 排除范围
- 登录、密码重置、OAuth(后续任务)
- 路径 glob 是机械执法的:BoundariesVerifier 用实际变更文件对照 glob (详见第 8 章)。
- 自然语言禁令由 lint 检查、结构验证器模式匹配,但不做文件级执法——两者 配合使用。
- 排除范围防止范围蔓延:Agent 明确知道什么不该碰。
- 1.0 还支持第四个子节
### Symbols——把合同钉到真实代码符号上(详见第 8 章)。
完成条件(Completion Criteria)——确定性的通过/失败
BDD 场景 + 显式测试绑定。核心原则:异常场景 ≥ 正常场景——这逼你在写码之前 想清楚边缘情况:
## 完成条件
场景: 注册成功 ← 1 条正常路径
测试: test_register_returns_201
...
场景: 重复邮箱被拒绝 ← 异常路径 ×3
场景: 弱密码被拒绝
场景: 缺少必填字段
每个场景没有 测试: 选择器就无法被 TestVerifier 执行,结果是 skip——而
skip 永远不等于 pass。场景 DSL 的全部细节在下一章。
写合同前的自检
| 问题 | 若答“否“ |
|---|---|
| 能定义“做完“长什么样吗? | 先自由探索,之后再立合同 |
| 能写出至少一个确定性测试吗? | 还没到合同阶段 |
| 范围小到能列出允许修改的路径吗? | 拆成多个任务 |
| 关键技术决策已定吗? | 先做 spike |
第 5 章 场景 DSL 与测试绑定
定位:本章是完成条件的语法手册:BDD 关键字、测试选择器、步骤表格、 标签与场景依赖。前置依赖:第 4 章。基于 agent-spec 1.0.0。
BDD 关键字(中英等价)
| English | 中文 | 语义 |
|---|---|---|
Given | 假设 | 前置条件 |
When | 当 | 动作 |
Then | 那么 | 期望结果 |
And | 并且 | 同类补充步骤 |
But | 但是 | 反向补充步骤 |
措辞必须确定性:“返回 201“而不是“可能返回 201”——可能/大约/有时/ might/could/maybe 这类非确定词会被 determinism linter 拦下(“应该“不在
拦截名单里,但同样别用:确定性是给机器读的纪律)。
测试选择器
场景: 正常路径
测试: test_happy_path # 简单形式
场景: 跨包验证
测试: # 结构化形式
包: spec-gateway
过滤: test_contract_prompt_format
层级: integration
选择器过滤的是真实测试名。改了测试函数名合同就会 skip——这是特性不是缺陷: 溯源链宁断勿假。
步骤表格
结构化输入用表格,别发明散文格式:
场景: 批量校验
测试: test_batch_validation
假设 如下输入记录:
| name | email | valid |
| Alice | alice@test.com | true |
| Bob | invalid | false |
当 校验器处理该批次
那么 "1" 条通过且 "1" 条失败
标签与模式
graph TD
S[场景] --> T1["标签: critical<br/>失败 ⇒ gate_blocked=true, exit 2"]
S --> T2["审核: human<br/>测试过 ⇒ pending_review"]
S --> T3["模式: optimize<br/>通过进 optimization_candidates,失败仍阻断"]
S --> T4["前置: 另一场景名<br/>前置失败 ⇒ 本场景自动跳过"]
critical:必须通过的场景,CI 友好的硬门。审核: human:测试通过后仍需人签——--review-mode strict下不算通过。前置:声明场景执行顺序;循环依赖由 lint 检出。
Rule 分组(BDD-spine)
相关场景可组织在 ### Rule: 下——一条系统承诺,由一组例子证明:
### Rule: reject-invalid-input — 拒绝非法输入
场景: 空邮箱被拒绝
测试: test_rejects_empty_email
...
场景: 弱密码被拒绝
测试: test_rejects_weak_password
...
Rule 的 kebab-case id 是稳定锚(改显示名随意,id 不动),成熟后可用
agent-spec promote 升入能力库(specs/capabilities/,命令详见附录 A)。id 与显示名之间用
em dash — 或两个以上空格分隔——普通 -- 会被吞进 id。
一份体检清单
写完场景过一遍:每个场景都有选择器吗?异常 ≥ 正常吗?措辞确定吗?表格代替了 自造格式吗?关键场景打了 critical 吗?——这五问的机械版就是下一章的 lint。
第 6 章 质量门:lint
定位:本章讲合同自身的“代码审查“——linter 家族、评分门槛与 lint-ack 豁免机制。前置依赖:第 5 章。基于 agent-spec 1.0.0。
合同是要交给 Agent 执行的输入,输入的质量决定输出的上限。agent-spec lint
对合同做机械审查:
agent-spec parse specs/task.spec.md # 先确认结构:段落数、场景数非零
agent-spec lint specs/task.spec.md --min-score 0.7
Spec: agent-spec 1.0 Book (Chinese Edition)
Quality: 100% (determinism: 100%, testability: 100%, coverage: 100%)
No issues found.
上面这段输出来自本书自己的合同——真实运行,未经修饰。
linter 家族一览
mindmap
root((lint))
结构
bdd-rule-id 规则 id 畸形
scenario-presence 零场景验收段
explicit-test-binding 缺测试选择器
implicit-dep 参数未在 Given 定义
语言
vague-verb 模糊动词
unquantified 未量化
determinism 非确定措辞
sycophancy 谄媚偏置
覆盖
coverage 约束未覆盖
decision-coverage 决策未覆盖
error-path 缺异常路径
universal-claim 全称断言场景不足
flag-combination-coverage 旗标组合未测
边界
boundary-entry-point 多入口未逐一验证
platform-decision-tag 平台决策未标记
几个高频警告的修法:
| 警告 | 症状 | 修法 |
|---|---|---|
vague-verb | “处理邮箱” | 改为“校验邮箱格式“ |
unquantified | “响应要快” | 改为“200ms 内响应“ |
error-path | 全是正常路径 | 补异常场景至 ≥ 正常场景 |
decision-coverage | 决策没人验证 | 为该决策补一个场景 |
lint-ack:有理由的豁免
当某条 Warning 确属正当例外,用带强制理由的行内确认,而不是扭曲合同:
<!-- lint-ack: error-path — 本任务是只读查询,无失败路径 -->
三条规则:lint-ack: 后的码与理由必须用 em dash — 或冒号分隔(否则整串被
当作码,什么也没确认);被确认的 lint 从报告中过滤但计入 audit(豁免上了
台账,不是消音);Error 永远不可确认——机械硬失败没有商量余地。
Questions:诚实的未完成
合同成形前,把未决问题放进 ## 问题 段(非阻塞,Info/Warning 级):
## 问题
- 折扣能否叠加?
- [x] 退款按折后价(已确认)
agent-spec discover --from-codebase 反向生成草稿合同时也会播种这一段——
一份冷启动草稿诚实地标着“已知不完整“,好过伪装成品。
第 7 章 验证与重试:lifecycle
定位:本章是验证管线的完整手册——四层验证器、五种 verdict、重试协议与 AI caller 模式。前置依赖:第 6 章。基于 agent-spec 1.0.0。
四层确定性管线
agent-spec lifecycle specs/task.spec.md --code . --format json --run-log-dir .agent-spec/runs
graph LR
L1["lint<br/>合同质量复检"] --> L2["StructuralVerifier<br/>Must NOT 模式匹配"]
L2 --> L3["BoundariesVerifier<br/>变更文件 × 允许路径"]
L3 --> L4["TestVerifier<br/>执行绑定测试"]
L4 --> L5["AI Verifier<br/>可选,默认 off"]
style L1 fill:#16321f
style L2 fill:#16321f
style L3 fill:#16321f
style L4 fill:#16321f
style L5 fill:#2a2440,stroke-dasharray:4
绿色四层是确定性的:零 token 成本、无假阴性。AI 层只处理机械层够不着的残余,
且默认关闭。管线里还有两个按需激活的确定性成员:Atlas 符号验证器插在边界层与
测试层之间(合同声明 ### Symbols 时激活,详见第 8 章);复杂度验证器在
合同声明质量约束且存在变更时运行。
五种 verdict
| verdict | 含义 | 动作 |
|---|---|---|
pass | 场景被证实 | 无 |
fail | 绑定测试跑了且失败 | 读证据,修代码 |
skip | 测试没找到/没跑 | 补测试或修选择器 |
uncertain | AI 桩/待人工评审 | 人工看或接 AI 后端 |
pending_review | 测试过了但要人签 | 走人工签核 |
skip ≠ pass 是这套体系的第一铁律。is_passing 要求 total>0 且
failed=skipped=uncertain=0——任何“没验证“都不会被静默当作“验证通过“。
重试循环
sequenceDiagram
participant A as Agent
participant L as lifecycle
A->>L: 第 1 次运行
L-->>A: fail (2/5) + evidence
A->>A: 读证据 → 修代码(不改合同!)
A->>L: 第 2 次运行
L-->>A: fail (4/5)
A->>A: 再修
A->>L: 第 3 次运行
L-->>A: pass (5/5) ✓
--run-log-dir 记下每一次运行——explain --history 能给出“这份合同重试了
几次才过“的表格(详见第 9 章)。长合同用 --resume 跳过已过场景;
--resume=conservative 全部重跑但检测回归。
逐 verdict 的重试纪律(全书唯一权威版):fail 读证据修码;skip 检查选择器
是否对得上真实测试名;uncertain 走人工或 caller 模式;同一场景连续三次失败,
停下来升级给人类;任何时候都不许为了变绿而改合同——合同真错了就显式切回写作
模式修订。
AI caller 模式
机械层覆盖不了的场景(设计意图、代码品质)可以让调用方 Agent 自己当验证器:
agent-spec lifecycle specs/task.spec.md --code . --ai-mode caller --format json
# 输出含 "ai_pending": true 与 pending 请求文件
# Agent 逐场景分析后写 decisions.json(scenario/verdict/confidence/reasoning)
agent-spec resolve-ai specs/task.spec.md --code . --decisions decisions.json
合并后的报告里,skip 被 Agent 的判定替换——但 provenance 会标注这是
Inferential(推理证据),与 Computational(机械证据)在 matrix 中泾渭分明。
第 8 章 边界、守卫与符号
定位:本章覆盖变更集执法(BoundariesVerifier)、全仓守卫(guard)与 1.0 的符号验证(
### Symbols,Intent-Code Linker 的入口)。 前置依赖:第 7 章。基于 agent-spec 1.0.0。
变更集从哪来
边界执法需要知道“这次改了哪些文件“:
| 旗标 | 行为 |
|---|---|
--change <path> | 显式指定文件/目录 |
--change-scope staged | Git 暂存区(guard 默认) |
--change-scope worktree | 全部工作区变更 |
--change-scope jj | Jujutsu 变更(jj 仓库自动适用) |
--change-scope none | 不做变更检测(lifecycle 默认) |
BoundariesVerifier 把每个变更文件对照合同的 glob:命中禁止 → fail;有允许清单 却不在其中 → fail;证据(PatternMatch)逐文件记录。
guard:全仓一次验证
agent-spec guard --spec-dir specs --code . --change-scope staged # pre-commit
agent-spec guard --spec-dir specs --code . --change-scope worktree # CI
agent-spec guard: 55 spec(s) passed
这行输出来自 agent-spec 自己的仓库(写作时快照;活跃合同数会随仓库生长)—— 全部活跃合同在每次提交前复验。 任何一份合同 lint 不过或验证不过,提交被阻断。
### Symbols:把合同钉到真实符号上
1.0 的合同可以在边界下声明代码符号引用:
## Boundaries
### Allowed Changes
- src/**
### Symbols
- rust-atlas: spec_verify::Verifier
- rust-atlas: spec_knowledge::build_work_units
lifecycle 管线中的 Atlas 符号验证器会拿新鲜图逐一核对:
graph TD
A[合同声明 Symbols] --> B{图存在且新鲜?}
B -->|图缺失/滞后| S["atlas-stale<br/>先失败,绝不产生假的 symbol-missing"]
B -->|新鲜| C{每个符号都在图里?}
C -->|缺失| M["atlas-symbol-missing<br/>逐符号 step verdict"]
C -->|全部命中| P["静默通过<br/>报告形状不变"]
N[未声明 Symbols] --> Z["验证器隐身<br/>非 Rust 项目零负担"]
三条语义值得背下来:stale 优先(图滞后时不指控符号缺失);全对即静默 (不给报告添噪音);不声明即免税(没有 Symbols 的合同永远不需要图)。 “合同里提到的符号已经不存在了“从此是机械诊断,不是考古发现——这是 Intent-Code Linker 的第一块(架构全景详见第 19 章,图的构建详见第 16 章)。
VCS 感知
.jj/ 存在(哪怕同时有 .git/)就用 --change-scope jj,且不要跑
git add——jj 自动快照。stamp 在 jj 仓库会带 Spec-Change: trailer;
explain --history 可通过 operation id 给出运行间的文件级 diff
(这两个命令详见第 9 章)。
第 9 章 验收与追溯
定位:本章讲人类在环的最后一步(合同验收)与合同↔提交的溯源链: explain、stamp、matrix、audit、archive。前置依赖:第 7、8 章。 基于 agent-spec 1.0.0。
合同验收,不是代码审查
agent-spec explain specs/task.spec.md --code . --format markdown
产出一份可直接贴进 PR 的合同级摘要。评审者只回答两个问题:
- 合同定义对吗?(意图、决策、边界讲得通吗)
- 验证全过了吗?(含异常路径的 N/N pass)
两个“是“就批准。这比读 500 行 diff 快一个数量级,而且注意力落在真正需要人类
判断的地方。想看过程再加 --history(真实渲染形状):
=== Run History (2 runs) ===
First pass: run #2 (timestamp 1783453380)
Failed runs: 1
| run #1 | FAIL | 3 pass 2 fail 0 skip 0 uncertain | |
| run #2 | PASS | 5 pass 0 fail 0 skip 0 uncertain | +2 pass |
stamp:合同 ↔ 提交
agent-spec stamp specs/task.spec.md --dry-run
Spec-Name: 用户注册API
Spec-Passing: true
Spec-Summary: 4/4 passed, 0 failed, 0 skipped, 0 uncertain
trailer 进 commit message,溯源链完成:从任意提交都能回答“它兑现的是哪份合同、 当时的验证状态如何“。
matrix 与 audit:证据的台账
graph LR
M["matrix<br/>Rule × Scenario × Test × Verdict × Provenance"] --> P["Computational<br/>机械证据"]
M --> I["Inferential<br/>AI 证据"]
A["audit<br/>库健康度:未证明的 Rule·未分组场景·打开的问题·lint-ack 台账"] -.只观察,永不阻断.- M
matrix 回答“哪条规则由哪些测试以何种证据证明“;audit 是周期性健康快照——
它只观察从不阻断,包括 lint-ack 的豁免记录也在这里可查。
archive:完成即出场
验收后的合同应该离开活跃扫描集:
agent-spec archive --spec-dir specs --archive-dir .agent-spec/archive/specs \
--summary knowledge/context/spec-archives.md --run-log-dir . --dry-run
先 --dry-run 审阅压缩摘要,再对 done/completed 且最新 lifecycle 证据仍然
通过的合同实际归档。证据缺失或失败会阻断归档并给出诊断——归档不是遗忘,
归档处的合同内容与证据依旧可查(三轴状态里 archived 是执行阶梯的顶端,
详见第 11 章)。
第 10 章 从 PRD 到需求 IR
定位:本章进入意图编译的入口——原始 PRD/Issue 如何变成人类确认的需求 IR, 以及 YAML 方言侧门。前置依赖:第 3 章;建议先读第 4 章。基于 agent-spec 1.0.0。
谁拥有需求:所有权规则
正常流程是:人和 AI 聊需求 → 聊出一份手写的自然语言文档 → 人类确认 →
这份文档(knowledge/requirements/req-*.md)成为手工拥有的规范 IR → 之后
才交给编译器降低。两条铁律:
- 确认后的需求文档是唯一真相。YAML 只是侧门输入方言与导出投影,永远不是 已确认需求的源头。
- 编译只读治理状态。
import/graph/work-units/plan任何一步都不会改动 需求文档一个字节。
graph LR
RAW["原始材料<br/>PRD·Issue·对话"] -->|"AI 起草候选块<br/>(人审)"| MARK["标记块<br/><!-- agent-spec:requirement -->"]
MARK -->|requirements import| IR["需求 IR<br/>req-*.md · status: proposed"]
YAML["requirements.yaml<br/>(侧门方言)"] -->|import --from *.yaml| IR
IR -->|人类 transition| ACC["status: accepted"]
IR -.export 投影.-> YAML
标记块 intake
requirements import 只消费显式标记块——它从不静默解读散文:
<!-- agent-spec:requirement id=REQ-NOTE-CREATE title="创建笔记" -->
## Problem
用户需要快速创建笔记。
## Requirements
[REQ-NOTE-CREATE] 系统 MUST 在 200ms 内完成笔记创建。
<!-- /agent-spec:requirement -->
agent-spec requirements import --from docs/prd.md --out knowledge/requirements
生成的文档带 status: proposed——候选身份,直到人类显式接受(下一章)。
原始散文的结构化由 agent-spec-requirements-compiler 技能辅助起草:候选块必须
带源摘录、置信度、场景与打开的问题,人审后才进 import。
YAML 方言(v1.1)
对接外部生态时,requirements.yaml 树可以直接导入:
requirements:
- id: booking
title: "Booking"
type: FOLDER
status: accepted
scenarios:
- name: "booking succeeds"
given: "an available slot"
when: "a visitor books it"
then: "the slot is reserved"
children:
- id: reserve
title: "Reserve"
type: ATOMIC
statement: "The system MUST reserve a slot exactly once."
方言是受约束的子集:两空格缩进、无锚点、无 flow 集合([] 也不行)——
超出子集的构造会得到指名道姓的 yaml-unsupported-construct 诊断,而不是猜测性
解析。导入产物带 source: imported-yaml 溯源标记;再次导入只会刷新带此标记的
文件,任何不带标记的既有文档一律拒绝覆盖(没有强制开关——手写文档的所有权
不容侵犯)。
ARC 原生形状(1.1.0+)
参照编译器(ARC)的真实输入是单根树:顶层就是根节点字段、name: 而非
title:、场景是 steps: [{keyword, content}]、ATOMIC 用 description: 携带
语句、id 允许点号层级(REQ-1.1)。requirements import 自动识别这种形状并
映射进 IR——点号 id 规范化为连字符,同时以 source-id: 保真行记录原始 id;
折叠块标量(>-)与空 flow 列表([])在此路径下被解析。反向的
requirements export --dialect arc-native 把 IR 投影为参照装载器可直接消费的
单根树并还原点号 id——agent-spec 编译的需求从此可以直接喂给 ARC。
反方向的导出(requirements export --out requirements.yaml)是派生投影:
往返是不动点(导出→导入→再导出逐字节相同),--check 做漂移门,装不下的内容
(Source Trace、tags 等)进 lossiness 清单而非静默丢弃。
第 11 章 治理与三轴状态
定位:本章讲需求的生命周期治理——显式人类转换、原子替换与一条命令看清 三个独立状态轴。前置依赖:第 10 章。基于 agent-spec 1.0.0。
状态机:接受是显式动作
stateDiagram-v2
[*] --> proposed: intake 产出
proposed --> accepted: transition --to accepted
proposed --> rejected: transition --to rejected
accepted --> deprecated: transition --to deprecated
accepted --> superseded: supersede --by NEW
note right of accepted: 缺失 status 会让 plan --gate 直接失败
agent-spec requirements transition REQ-BOOKING --to accepted
REQ-BOOKING: proposed -> accepted (knowledge/requirements/req-booking.md)
三条纪律:改写是行精确的(只动 frontmatter 的 status: 行);非法转换是
诊断(accepted 回不到 proposed);superseded 只能经 supersede 命令到达——
它原子地改写两份文档(旧文档标 superseded,新文档记 supersedes:),第二次
写入失败会回滚第一次。
机器消费加 --format json——输出带改写后文档的 blake3 摘要,且没有
actor/authority/approval 字段(谁批准的由编排系统在自己的证据链里绑定到摘要上,
详见第 18 章 ADR-001):
{
"document": "knowledge/requirements/req-provenance-run-hardening.md",
"document_digest": "4a974a05742095071661737b5b676ef50a5bc07ce8f24c60486518a47b60f28f",
"from": "proposed",
"id": "REQ-PROVENANCE-RUN-HARDENING",
"to": "accepted"
}
三轴状态:一条命令回答“REQ-X 现在怎么样了“
治理(人定、持久化)、执行(从工件推导)、liveness(从当前 verdict 重算)是 三个独立的轴:
agent-spec requirements status REQ-INTENT-CODE-LINKER
REQ-INTENT-CODE-LINKER
governance: accepted
execution: verified (work unit: ready)
liveness: honored
执行阶梯自底向上:unplanned → planned → ready → active → verified → archived
——staged 合同是 planned,工作单元就绪是 ready,活跃合同是 active,活跃且
honored 是 verified,归档是 archived。liveness 三值 honored / violated / unproven(外加声明性的 na),
永远重算,从不存储(详见第 15 章)。
开工仪式
接受一条需求意味着排期义务。plan 门会强制配对:accepted 而无活跃合同 →
requirement-uncovered 失败。因此标准开工动作是一次变更里同时完成——
agent-spec requirements transition REQ-X --to accepted
git mv specs/roadmap/task-x.spec.md specs/
这套仪式在本书自己的写作中如实上演过(详见附录 C)。
第 12 章 计划与工作单元
定位:本章讲需求 IR 的降低(lowering):验证需求图、生成工作单元、 汇成计划 DAG,直至可评审的合同草稿。前置依赖:第 11 章。基于 agent-spec 1.0.0。
降低管线
graph TD
IR["需求 IR<br/>knowledge/requirements/"] --> G["requirements graph --gate<br/>结构校验:悬空依赖·环·治理缺失"]
G --> W["requirements work-units<br/>WU-REQ-*:ready/blocked/informational"]
W --> P["requirements plan --gate<br/>需求×工作单元×合同 三层 DAG"]
P --> D["requirements draft-specs<br/>可评审的任务合同草稿"]
P --> Q["requirements questions<br/>从诊断生成澄清问题"]
P --> T["requirements test-obligations<br/>独立于代码的测试义务"]
graph 与 work-units
agent-spec requirements graph --knowledge knowledge --format json --gate
agent-spec requirements work-units --knowledge knowledge --out .agent-spec/work_units.json
graph 校验依赖 DAG(悬空引用、环)与治理完整性——没有 status 的需求会直接 让 gate 失败。work-units 把每条需求降低为工作单元并给出状态:
ready:accepted + 场景齐备 + 可排期;blocked:缺场景等(blocked: missing_scenarios);informational:proposed/缺状态——治理未接受的工作永不 ready。
plan:一个 DAG 看三层
agent-spec requirements plan --knowledge knowledge --specs specs --gate
batch 1: REQ-CODE-LIVE-WIKI, REQ-INTENT-CODE-LINKER, REQ-KLL-WORK-UNITS, REQ-RUST-ATLAS
batch 2: REQ-AGENT-SPEC-BOOK, REQ-CODE-LIVE-WIKI-DEEPENING, REQ-REQUIREMENTS-COMPILER-PLAN-DAG
batch 3: REQ-CROSS-PROJECT-WIKI
(写作时快照——批次会随需求图生长;batch N: 行格式是稳定的。)
批次即拓扑序:同批次可并行。gate 语义里最重要的一条是 requirement-uncovered——即上一章“开工仪式“的
机械依据(详见第 11 章,此处不再展开)。
draft-specs:草稿不是成品
agent-spec requirements draft-specs --knowledge knowledge --out specs/generated
只有 ready 单元会生成草稿。草稿自带 satisfies: [REQ-*](satisfies 边详见第 15 章)与占位选择器
(pending_...)——lifecycle 对草稿本来就应该失败,直到人类评审、补上真实
测试选择器并提升到 specs/。草稿是起点,不是可以直接执行的合同。
worktree 并行开发的机械配套:
agent-spec requirements worktrees --base main --path-prefix ../ws --out .agent-spec/worktrees.json
为每个 ready 单元生成确定性的 git worktree 条目(路径、分支名),供编排系统 直接消费。
第 13 章 溯源与重放
定位:本章讲证据链——一条需求的可追溯投影、编译的可重放清单与漂移检测。 前置依赖:第 11 章;trace ledger 细节关联第 15 章。基于 agent-spec 1.0.0。
traceability:一个文档看完整证据链
agent-spec requirements traceability REQ-X --format json --out trace.json
投影是纯读且字节稳定(同输入两次运行逐字节相同):条款 → 满足它的合同
→ 场景 → 绑定测试 → 最近记录的 verdict → 派生 liveness,一次给全。verdict 来自
存储的 trace ledger(不重跑测试),schema 为 requirement-traceability-v1。
仪表盘和编排系统消费这一个文档就够了,不必自己重推导。
编译运行清单(provenance v2)
每个写 --out 工件的 requirements 命令都能附带清单:
agent-spec requirements work-units --out wu.json --provenance wu.compilation.json
provenance: wu.compilation.json (build 85b8f4f5dba5cf19c1d6c8ba34e9777d0e01cba8)
v2 清单绑定四件事:编译器构建身份(crate 版本 + 构建期嵌入的 git commit,
无 git 环境则为 unknown)、生效配置(子命令 + 旗标数组)、输入语料摘要
(知识树 blake3)、输出摘要。v1 清单(import/export)继续有效。
verify-run:确定性成为可执行检查
agent-spec requirements verify-run --manifest wu.compilation.json
verify-run requirements work-units: 0 output(s) drifted
重放在内存中进行(什么都不写——最强形式的沙箱):按清单记录的命令与配置 重新渲染,逐字节对照记录的摘要,漂移的输出逐个点名、非零退出。记录与重放共用 同一渲染函数,字节奇偶性是构造保证而非测试巧合。
sequenceDiagram
participant C as 编译命令
participant M as v2 清单
participant V as verify-run
C->>M: 记录(构建身份+配置+输入/输出摘要)
Note over C,M: 时间流逝,有人改了知识树?
V->>M: 读清单
V->>V: 内存重渲染(同一函数)
V-->>M: 逐字节对照
V-->>C: 0 drifted / 点名漂移文件,exit≠0
trace / replay / explain-failure
需求级证据的三个读命令:trace REQ-X 列出全部 trace 记录;replay REQ-X 取
最近一次运行的证据链(是证据重放,不是“确定性 LLM 重放“);
explain-failure REQ-X 聚焦非 pass 链并解释。这些记录从 lifecycle 的
--run-log-dir/trace 写入,1.0 起还携带类型化代码目标(详见第 14 章)。
第 14 章 编译束与代码绑定
定位:本章讲编译器的打包出口:per-requirement 四件套编译束、工作单元的 代码绑定与一体化执行束。前置依赖:第 12、13 章;符号语义见第 8 章。 基于 agent-spec 1.0.0。
requirements compile:四件套
agent-spec requirements compile --out bundles/ --layout arc-v1
compiled REQ-PARITY-BOOKING: 4 files (bundle eabda2986cdcdeced70613b89e1ec500...)
bundles written: 1 -> bundles/
每条 accepted 需求产出:需求文档、合同草稿、traceability 投影、编译清单 (含逐工件摘要 + bundle 总摘要——外部准入检查可以钉住整个束)。两种布局:
agent-spec-v1(默认,中立):<id>/requirements.md、spec.md、traceability.json、compilation.json;arc-v1(边缘兼容投影):<id>.requirements.md、<id>.spec.md、<id>.arc.traceability.json、<id>.arc.compilation.json——内容与中立布局 完全相同,只有文件命名不同。像 SARIF/SCIP 一样,兼容是文件布局层面的事, 核心 schema 里没有任何外部项目的词汇(有机械测试守着这条纪律)。
写入是原子的:全部工件先在内存渲染校验,任何失败什么都不落盘;已有文件
不带 --force 拒绝覆盖并逐个点名。compile 清单同样可 verify-run 重放。
requirements bind:把工作单元钉到代码
agent-spec requirements bind --code . --graph .agent-spec/graph
对每个 ready 工作单元,取其合同声明的 ### Symbols,在 provider 图(首个
provider 是 rust-atlas,详见第 16 章)中解析成真实代码目标,写出
.agent-spec/code-bindings.json:需求 id、工作单元 id、provider、图指纹、
排序后的目标(node id / kind / file / provenance)。三条硬语义:
- 图滞后即失败:stale 文件逐个点名,绝不产出绑定;
- 未知 provider 即诊断:指名 spec 与注册表;
- 绑定是派生工作数据,永远不是 KLL 真相——随时可从图重新生成。
requirements bundle:一个工件给 Agent 全部上下文
agent-spec requirements bundle --unit WU-REQ-X --out bundle.json
graph TD
B[Execution Bundle] --> W[work_unit]
B --> K["contracts<br/>(内嵌全文+blake3)"]
B --> CB["code_bindings<br/>(本单元的绑定)"]
B --> QP["quality_profile<br/>(argv 数组,永不 shell 字符串)"]
B --> SK["required_skills + receipts<br/>(id/版本/源/内容哈希)"]
B --> FC["fast_checks<br/>(clippy/fmt 先跑)"]
B --> AG["acceptance_gates<br/>(lifecycle + 必需验证 provider)"]
质量 provider 有类型化角色(code-intelligence / diagnostic / verification / transformation / agent-guidance)与归一化 outcome(pass / fail / unavailable / error / 授权 skip)。两条被类型层面固化的纪律:必需 provider 不可用永远不算 通过证据;技能回执是来源凭证,永远不是验收证据——验收只认确定性工具输出 与 lifecycle verdict。
第 15 章 KLL 与 liveness
定位:本章讲合同之外的持久知识层:四类知识文档、satisfies 边与永远重算的 liveness。前置依赖:第 9 章。基于 agent-spec 1.0.0。
知识为什么需要一层
合同验证任务,但团队的持久知识——为什么这么决定、哪些需求还活着、给 AI 的
指导——散落在 PR 描述和聊天记录里会腐烂。KLL(Knowledge & Liveness Layer)
把它们放进 knowledge/,用类型化文档承载,用 satisfies: 边连回合同:
graph LR
subgraph knowledge/
D["decision<br/>ADR-*"]
R["requirement<br/>REQ-*"]
G["guidance<br/>给 AI 的指导"]
P["proposal<br/>提案,恒 na"]
end
S["specs/*.spec.md<br/>satisfies: [REQ-*, ADR-*]"] -->|守护| R
S -->|守护| D
P -->|"Produces: ADR-x"| D
V["当前 verdict"] -.重算.-> L["liveness<br/>honored/violated/unproven/na"]
R -.-> L
D -.-> L
- decision(ADR):accepted 的决策强制
Alternatives Considered非空、Consequences正反两面(forcing functions)——写决策时就被迫诚实。 - requirement(REQ):BCP-14 规范句(MUST/SHOULD/MAY),一行一条款。
- guidance:作用域化的 AI 指导(
Applies Toglob +Skills指定)。 - proposal:治理型提案,liveness 恒
na,永不进代码门,经## Produces:链到它催生的决策。
liveness:从不存储的答案
agent-spec trace REQ-X --gate
回答“这条知识现在还被通过中的合同守着吗“:
| liveness | 含义 |
|---|---|
honored | 有满足它的合同且全部通过 |
violated | 有合同在失败 |
unproven | 没有合同守护或证据不足 |
na | 声明性不适用(如 proposal) |
关键设计:它是派生值,重算于每次询问,从不落盘。不存在“数据库里记着绿色
但代码早烂了“的陈旧状态。--gate 让 violated 退出码 2,可直接进 CI。
治理 lint
agent-spec lint-knowledge --knowledge knowledge --gate
20 docs, 204 findings (0 errors)
(写作时快照;语料会生长,0 errors 是门的语义所在。)
语料级校验:id 冲突、supersession 完整性(superseded 必须有对应的
supersedes: 回链)、陈旧引用;文档级 forcing functions(上文的 ADR 规则等)。
--format sarif 可直接喂 GitHub Code Scanning。
一键铺设整个知识工作区:agent-spec init --workspace(幂等)。
第 16 章 Rust Atlas
定位:本章讲代码图 provider——查结构而非查文本:构建、查询、新鲜度与 冻结模式。前置依赖:第 8 章的符号语义。基于 agent-spec 1.0.0 (rust-atlas crate 0.1.0)。
为什么不用 grep
Agent 理解代码时反复 grep 是在用文本近似结构。Atlas 用 syn 在 stable 工具链
上把 Rust 源码提取成项目图:模块、类型、trait、impl、调用边——每条边带
provenance(syn / scip / mir),每个分片带源文件 blake3。
agent-spec atlas build --code . # 构建/增量刷新(逐文件分片+blake3)
agent-spec atlas query spec_verify::Verifier --format json
agent-spec atlas refs Verifier # 谁引用/调用它
agent-spec atlas impls Verifier # 哪些 impl 触及该 trait/类型
agent-spec atlas tree --code . # 确定性模块大纲
agent-spec atlas check --code . # 新鲜度门:任何分片滞后即非零退出
graph TD
SRC["src/**.rs"] -->|syn 提取| SH["逐文件分片<br/>nodes+edges+源文件 blake3"]
SCIP["SCIP 索引(可选)"] -.叠加锐化边.-> SH
SH --> Q["query/refs/impls/tree"]
SH --> CK["check:分片 hash × 当前文件 hash"]
CK -->|滞后| STALE["点名 stale 文件,exit≠0"]
Q -->|"--frozen"| FR["拒绝静默陈旧答案"]
新鲜度是门,不是提示
分片记录它来自哪个字节状态的源文件。check 在 CI 里把“图落后于代码“变成硬失败;
读命令加 --frozen 则拒绝在陈旧图上给出答案。第 8 章的 atlas-stale 优先语义、
第 14 章 bind 的滞后即失败,根源都在这里:宁可说“我不知道“,不给过期事实。
图的消费者们
- 合同符号验证(第 8 章):lifecycle 拿新鲜图核对
### Symbols。 - 代码绑定(第 14 章):ready 工作单元解析成带图指纹的代码目标。
- 类型化 trace 目标:通过验证的运行把 provider/node/kind/file/provenance/ 图指纹写进 trace 证据。
- MCP:
atlas_tree / atlas_query / atlas_refs / atlas_impls / atlas_status五个只读工具,任何 MCP 客户端“问谁调用了它“得到的是带 provenance 的边, 不是 grep 命中(详见第 17 章)。
增量与自托管
分片只在源文件 hash 变化时重建——大仓库重索引的成本是一个文件而不是全世界。 agent-spec 仓库自托管:写作时 85 个源文件全图零 unparsed。MIR 层(rustc 驱动 的深度事实)是 0.7 弧的 additive 深化,已列入路线图合同。
版本演化说明
本章核心分析基于 rust-atlas 0.1.0。截至 rust-atlas 0.2.0(schema v4), 本章的构建、查询、新鲜度与冻结模式语义不变,有两处 additive 演化:节点 id 带上了
#消歧后缀(裸名引用仍可解析);语法基线之上新增可选的 SCIP 语义 叠加层——atlas scip-gen调 rust-analyzer 产出index.scip,叠加Calls/UsesType等语义边(provenance=Scip,syn 基线永不改写)。 路线图见仓库docs/atlas-roadmap.md。
第 17 章 Live Wiki 与 MCP
定位:本章讲 Agent 的工作记忆(源码溯源的 live wiki)与知识层的在线服务 (只读 MCP)。前置依赖:第 15 章。基于 agent-spec 1.0.0。
Live Wiki:会过期报警的工作记忆
.agent-spec/wiki 是仓库内被 git 跟踪的 wiki——不是 KLL 真相,不是发布文档,
而是 Agent 的工作记忆:模块页、概念页、决策页、架构清单、跨项目地图。
每篇文章声明 source_files,源码一变即被标记陈旧:
agent-spec wiki init --code . # 铺目录(各文章目录带 .gitkeep)
agent-spec wiki seed --code . # 聚焦式草稿页,不覆盖手工维护页
agent-spec wiki status # 哪些页陈旧了(含 worktree 未提交变更)
agent-spec wiki query "requirements compiler"
agent-spec wiki inspect src/spec_wiki/live.rs
agent-spec wiki check # 索引新鲜度+lint+陈旧状态,CI 结构门
graph LR
CODE[源码] -->|source_files| ART[wiki 文章]
ART -->|"wiki status"| STALE{源码变了?}
STALE -->|是| WARN[标记陈旧页]
PROJ["projects/*.md<br/>外部项目页"] --> MAP["project-map.json/.mmd<br/>派生地图"]
FLOW["flows/*.md<br/>跨项目数据流"] --> MAP
MAP -.lint 要求与文章精确一致.- ART
跨项目场景用 project/flow 文章:projects 列表的相邻对构成有向边,仓库外的
路径只进 external_sources 证据标签(agent-spec 不扫描外部仓库)。派生的
project-map 必须与维护文章精确一致,wiki lint 守着。工作纪律:大量读源码前
先 wiki query;旧内容移入 learnings/ 存档而非粗暴删除。
只读 MCP:项目真相在线可查
agent-spec mcp --knowledge knowledge
通过 stdio JSON-RPC 提供 11 个确定性只读工具(无 RAG、无网络):
| 组 | 工具 |
|---|---|
| 知识 | knowledge.find / knowledge.governing / context.read |
| 活性 | liveness.status |
| 合同 | spec.contract |
| 指导 | guidance.for |
| 代码图 | atlas_tree / atlas_query / atlas_refs / atlas_impls / atlas_status |
任何 MCP 客户端(Claude Code、Codex、自研编排器)都能实时查询项目真相,而 不是反复重读文件。只读是边界承诺:审批、治理转换等写操作永远走 CLI—— 这与第 18 章的 ADR-001 一脉相承。
第 18 章 设计哲学
定位:本章把散在前十七章里的设计选择收拢成五条原则——它们解释了这个 工具为什么长这样。前置依赖:通读第一、二部分任意深度。基于 agent-spec 1.0.0。
一、审查点位移
人类时间最贵的用法不是读 Agent 写的代码,而是定义“什么是正确“。整个工具链 围绕这一点组织:合同是人写的(50-80 行自然语言),验证是机器做的(四层确定性 管线),人类最后只回答“合同对吗、验证全过了吗“。
二、确定性优先,AI 在边缘
graph TD
DET["确定性核心<br/>lint·结构·边界·测试·符号<br/>零 token·无假阴性·可重放"] --> AI["AI 只在边缘<br/>intake 起草(人审)·caller 验证(标注 Inferential)"]
style DET fill:#16321f
style AI fill:#2a2440,stroke-dasharray:4
每个新增检查都是传感器(lint/report/audit),从不静默改变 pass/fail 语义。
AI 证据与机械证据在 matrix 里 provenance 分明——Inferential 永远不会被
默默当作 Computational。
三、skip ≠ pass(诚实的五值逻辑)
“没验证“与“验证通过“是两件事。五种 verdict 各司其职,is_passing 只认
“跑了且全过”。同族的诚实还有:required provider 不可用不是 pass;技能
回执不是验收证据;lint-ack 豁免计入台账而非消音;draft-specs 的占位
选择器本来就该失败。工具宁可红着,不给虚假的绿。
四、derived, never stored(派生值从不落盘)
liveness 每次询问都重算;traceability 是纯读投影;代码绑定随时可从图重生成; wiki 的陈旧标记来自当下的源码对照。任何会腐烂的答案都不允许缓存成“真相“。 反过来,被持久化的只有事实:需求文档、trace 记录、编译清单——以及它们的 blake3 摘要。
五、编排器中立(ADR-001)
agent-spec 提供确定性编译产物、稳定机器格式、digest 和重放能力;任何编排器 都可以在命令之间插入审批,但审批身份、权威和工作流永远不进入编译器核心。
CLI 无法可信证明“谁批准了“,所以它不假装能:JSON 输出带文档摘要,外部系统把
审批绑定到摘要上。依赖方向是单向的——编排器依赖 agent-spec 的冻结表面,
agent-spec 不知道任何编排器的存在。schema 里没有 actor/authority/approval/
policy 字段,这条纪律本身有机械测试守着。被否掉的备选方案(审批协议入核、
编排器命名的命令、双 canonical 所有权)连同否决理由记录在
knowledge/decisions/adr-001-orchestrator-neutral-core.md——用它自己要求的
forcing functions 格式写成。
这些原则的代价(诚实清单)
确定性优先意味着 NFR(性能/可靠性)只能给 uncertain;测试选择器改名会让
合同 skip(溯源宁断勿假的代价);编排器中立意味着没有开箱即用的审批 UI;
以及最根本的一条——lifecycle 全绿只证明合同被满足,不证明合同本身全面,
所以周期性的人工与 AI 架构评审仍然必要(audit 自动化了其中一部分)。
工具把这些代价写在 README 的 “What agent-spec doesn’t solve” 里,而不是藏起来。
第 19 章 架构全景
定位:本章是全书的收束——双 IR 收敛架构、五个交付边界与 1.0 兼容性 承诺的完整清单。前置依赖:第 18 章。基于 agent-spec 1.0.0。
双 IR 收敛
agent-spec 1.0 的架构是两条独立编译轨道在 Intent-Code Linker 汇合:
graph TB
subgraph 人类轨道
H["人类意图<br/>PRD·对话"] --> INTAKE["Intake<br/>(AI 起草,人审)"]
INTAKE --> RIR["需求 IR<br/>human-owned KLL 真相<br/>REQ-* · 治理状态机"]
end
subgraph 代码轨道
RS["Rust 源码"] --> ATLAS["Rust Atlas"]
ATLAS --> CIR["代码图 IR<br/>derived · blake3 staleness<br/>provenance 边"]
end
RIR --> LINKER["Intent-Code Linker<br/>### Symbols 验证 · 代码绑定<br/>类型化 trace 目标"]
CIR --> LINKER
LINKER --> PLAN["可验证 Plan DAG<br/>需求×工作单元×合同"]
PLAN --> AGENT["Agent 实现<br/>(边界+符号约束内)"]
AGENT --> LC["lifecycle 验证"]
LC -.liveness 回灌,从不存储.-> RIR
两条铁律贯穿始终:派生的代码事实永远不改写 KLL 真相(Linker 产出的绑定与 trace 事实都是 derived 工作数据);陈旧的图阻断一切定论(stale 优先于任何 symbol 判断)。
五个交付边界(1.0 全部落地)
| 边界 | 交付物 | 章节 |
|---|---|---|
| 1 治理门与转换 | 状态机、transition/supersede、缺状态即失败 | 第 11 章 |
| 2 代码图 IR 与绑定 | CodeGraphProvider 契约、requirements bind | 第 14、16 章 |
| 3 Intent-Code Linker | ### Symbols 验证、类型化 trace 目标 | 第 8 章 |
| 4 质量计划与执行束 | provider 角色/outcome、requirements bundle | 第 14 章 |
| 5 三轴状态查询 | requirements status | 第 11 章 |
Schema 家族
机器格式的每一员都有版本化、命名空间化的 $id
(agent-spec/intent-compiler/*),文件形式为可解析 URL:
requirements-plan-v1 · test-obligations-v1 · worktree-manifest-v1 ·
clarification-questions-v1 · requirement-trace-ledger-v1(含类型化
code_target_facts)· compilation-provenance-v1 / -v2(可重放)·
requirement-traceability-v1 · code-bindings-v1 · execution-bundle-v1
1.0 兼容性承诺
自 1.0.0 起,以下表面破坏性变更只随主版本:
- CLI:全部命令族——从
init/lint/contract/lifecycle/guard/explain/stamp到requirements家族(含traceability|verify-run|compile|bind|bundle)、wiki *、atlas *、mcp。 - 机器格式:lifecycle/verify JSON 顶层键;五种 verdict 与
is_passing语义;上面的全部 schema;YAML 方言 v1.1;编译束双布局 (agent-spec-v1、arc-v1)。 - 治理语义:需求状态机、执行阶梯、derived-never-stored 的 liveness。
之后的路:Atlas MIR 层(0.7 弧,additive 深化)与英文版全书。架构不会重来—— 它已经把自己钉进了机械验证里。
附录 A 命令速查表
基于 agent-spec 1.0.0 的常用表面速查(1.0 兼容性承诺的权威清单以 README “Stability: the 1.0 promise” 为准)。
合同工作流
| 命令 | 用途 |
|---|---|
init --level task --lang zh --name N | 脚手架新合同(--template rewrite-parity 用于迁移/对齐任务) |
parse <spec> | 结构确认(段落数、场景数) |
lint <spec> --min-score 0.7 | 合同质量门 |
contract <spec> | 渲染任务合同(Agent 的执行计划) |
plan <spec> --code . | 生成计划上下文(代码扫描+任务草图) |
lifecycle <spec> --code . --format json | 主质量门:lint+结构+边界+测试(+符号) |
verify <spec> --code . | 仅验证(跳过 lint 门) |
guard --spec-dir specs --code . --change-scope staged | 全仓守卫(pre-commit/CI) |
explain <spec> --format markdown [--history] | 合同级验收摘要(/运行历史) |
stamp <spec> --dry-run | Git trailer 溯源 |
matrix <spec> --code . | Rule×场景×测试×verdict×provenance 矩阵 |
audit --spec-dir specs | 库健康度(只观察不阻断) |
promote <spec> --rule <id> --to <cap> --code . | 成熟 Rule 升能力库 |
discover --from-codebase --code . --name N | 从测试反推草稿合同 |
archive --dry-run | 完成合同归档(证据不绿则阻断) |
graph --spec-dir specs | 合同依赖 DAG 与关键路径 |
check-structure --code . --forbid X --in glob | 分层架构守卫 |
意图编译(requirements 家族)
| 命令 | 用途 |
|---|---|
requirements import --from prd.md [--provenance m.json] | 标记块/YAML → 需求 IR(proposed) |
requirements transition <ID> --to accepted [--format json] | 显式治理转换(带摘要 JSON) |
requirements supersede <OLD> --by <NEW> | 原子替换链 |
requirements status <ID> | 三轴状态(治理/执行/liveness) |
requirements graph / plan --gate | 需求图校验 / 三层计划 DAG |
requirements work-units / draft-specs | 工作单元 / 合同草稿 |
requirements traceability <ID> --format json | 证据链单文档投影 |
requirements verify-run --manifest m.json | 编译重放,逐字节比对 |
requirements compile --out d/ --layout arc-v1 | per-requirement 四件套编译束 |
requirements bind | 工作单元 × 代码符号绑定 |
requirements bundle --unit WU-X --out b.json | 一体化执行束 |
requirements trace/trace-graph/replay/explain-failure <ID> | 证据记录读取与图渲染 |
requirements questions / test-obligations / worktrees | 澄清问题 / 测试义务 / 并行工作树 |
requirements export --out r.yaml --check | YAML 投影(漂移门) |
知识与生态
| 命令 | 用途 |
|---|---|
init --workspace | 铺设 knowledge/ 工作区(幂等) |
trace <id> --gate | 知识 → 合同 → liveness |
lint-knowledge --gate [--format sarif] | 语料治理 lint |
atlas build/tree/query/refs/impls/check [--frozen] | 代码图家族 |
wiki init/seed/status/query/inspect/inventory/index/project-map/inspect-project/lint/check/meta | live wiki 家族 |
mcp | 只读 MCP server(11 工具) |
gen-integrations --check | 集成文件漂移门 |
附录 B 场景 DSL 参考卡
基于 agent-spec 1.0.0。合同段落头(每行恰好一个,不混排双语):
| 中文 | English |
|---|---|
## 意图 | ## Intent |
## 约束 | ## Constraints |
## 已定决策 / ## 决策 | ## Decisions |
## 边界 | ## Boundaries |
## 验收标准 / ## 完成条件 | ## Acceptance Criteria / ## Completion Criteria |
## 排除范围 | ## Out of Scope |
## 问题 / ## 待澄清 | ## Questions |
场景骨架
### Rule: kebab-case-id — 显示名(可改,id 不动)
场景: 名称(critical) # 名称后缀=critical 简写
标签: critical
测试:
包: my-crate
过滤: test_name
级别: integration
前置: 另一场景名
审核: human # 测试过 → pending_review
模式: optimize # 通过进优化候选,失败仍阻断
假设 前置条件:
| 列1 | 列2 |
| a | b |
当 动作
那么 确定性结果("返回 201",不写"应该返回")
并且 补充断言
但是 反向断言
边界子节
## Boundaries
### Allowed Changes # 机械执法的路径 glob
- src/auth/**
### Forbidden # lint 检查的自然语言禁令
- 不要添加新依赖
### Symbols # 1.0:代码符号引用(Linker)
- rust-atlas: crate::module::Item
## Out of Scope
- 显式排除项
frontmatter
spec: task # org | project | task
name: "名称"
inherits: project # 三层继承链 org→project→task
tags: [feature]
satisfies: [REQ-X] # KLL satisfies 边
depends: [task-a] # 合同依赖(graph 用)
estimate: 2d # 0.5d/1d/2d/1w/4h
capability: cap-name # 贡献到哪个能力
risk: A # QA class
---
lint-ack
<!-- lint-ack: error-path — 只读查询无失败路径 -->
码与理由必须用 — 或 : 分隔;Error 永不可豁免;豁免计入 audit 台账。
附录 C 本书的 Spec(自举)
本书不是“讲“spec 驱动,它被 spec 驱动。这一页是证据。
本书的需求
knowledge/requirements/req-agent-spec-book.md 定义了 REQ-AGENT-SPEC-BOOK:
mdbook 工程 + mermaid 渲染、SUMMARY 完整性、章章有定位锚与图、前言双阅读路径
与知识地图、自举附录、双 E2E 轨迹、中文先行。它经历了与任何功能需求相同的
生命周期:intake 起草 → 人类确认 → transition --to accepted → 计划门检查
配对合同。
本书的合同
specs/task-agent-spec-book.spec.md 把需求降低为七个可机械验证的场景,每个
绑定一个真实的结构守卫测试:
| 场景 | 绑定测试 |
|---|---|
| SUMMARY 完整且章节文件齐备 | test_book_summary_lists_chapters_and_files_exist |
| 章章有定位锚与 Mermaid 图 | test_book_chapters_carry_anchor_baseline_and_mermaid |
| mdbook-mermaid 已配置 | test_book_toml_configures_mermaid_preprocessor |
| 前言含阅读路径与知识地图 | test_book_preface_has_reading_paths_and_knowledge_map |
| 自举附录收录本书契约 | test_book_dogfood_appendix_embeds_own_contract |
| E2E 轨迹跨章且有图 | test_book_traces_span_chapters_with_diagrams |
| 缺失章节被机械拒绝 | test_book_guard_fails_on_missing_chapter_fixture |
第七个场景是异常路径:给结构校验函数一份引用了不存在文件的 SUMMARY 副本, 断言缺失清单指名该文件——守卫自己也被验证会叫。
写作即工作流
sequenceDiagram
participant W as 写作者
participant K as KLL
participant T as 结构测试
participant L as lifecycle
W->>K: req-agent-spec-book.md (proposed)
W->>W: 写合同,lint 至 100%
W->>T: 先写七个测试 → RED(书不存在)
W->>W: 写书稿(骨架→章节→附录)
W->>T: cargo test → GREEN
W->>K: transition --to accepted + 合同已在 specs/
W->>L: lifecycle → 7/7 pass
Note over W,L: explain 输出即本书的"验收报告"
有趣的推论:从今往后任何人删掉一章、忘了画图、改坏目录,CI 的 Contract Guard 都会在提交时拦下——这本书的结构质量不靠自觉,靠机器。这正是第 1 章说的 审查点位移在文档工程上的应用。
读者可以复刻
给你自己的项目文档立一份这样的合同,只需要:一条需求(写清结构承诺)、几个
文本形状测试(SUMMARY 解析 + grep 锚点)、satisfies: 连线。从此文档腐烂
是机械诊断,不是季度回顾时的叹气。
附录 D 端到端轨迹
单章讲的是模块,轨迹讲的是系统。两条 E2E trace 把分散的章节串成完整的因果链。
轨迹一:一条需求从 PRD 到 honored
贯穿:第 10 章(intake)→ 第 11 章(治理)→ 第 12 章(计划)→ 第 7 章 (lifecycle)→ 第 13 章(溯源)→ 第 15 章(liveness)。
sequenceDiagram
participant PRD as PRD 文档
participant IR as 需求 IR
participant Plan as 计划 DAG
participant Spec as 任务合同
participant LC as lifecycle
participant KLL as liveness
PRD->>IR: requirements import(标记块→REQ-X, proposed)
IR->>IR: 人类 transition --to accepted(行精确改写+digest)
IR->>Plan: graph --gate → work-units(WU-REQ-X ready)
Plan->>Spec: draft-specs → 人审 → 提升 specs/(占位选择器换真实测试)
Note over Plan,Spec: plan --gate 强制:accepted 必须有活跃合同
Spec->>LC: Agent 实现 → lifecycle 重试循环 → N/N pass
LC->>KLL: trace 记录落盘(带类型化代码目标)
KLL-->>IR: requirements status REQ-X → accepted/verified/honored
每一步的产物都可独立审计:transition 的 JSON 带文档摘要(第 11 章);plan 的
批次是拓扑序(第 12 章);lifecycle 的 run log 记录每次重试(第 7 章);
traceability 一个文档投影整条链(第 13 章);最后 status 的三轴回答是
派生的,问一次算一次(第 15 章)。没有任何一步依赖“某人记得“。
这条轨迹在真实世界完整跑过:agent-spec 1.0 的三个集成需求 (REQ-COMPILER-MACHINE-SURFACE 等)就是沿着它从 proposed 走到 accepted/verified/honored 的。
轨迹二:一次合同验证之旅(含符号与边界)
贯穿:第 4 章(四要素)→ 第 6 章(lint)→ 第 7 章(四层管线)→ 第 8 章 (边界与符号)→ 第 16 章(Atlas 图)→ 第 9 章(验收与盖章)。
flowchart TD
A["合同就绪(四要素+### Symbols)"] --> B["lint --min-score 0.7"]
B -->|通过| C[StructuralVerifier<br/>Must NOT 模式匹配]
C --> D[BoundariesVerifier<br/>变更文件×允许 glob]
D --> E{声明了 Symbols?}
E -->|否| F[TestVerifier 执行绑定测试]
E -->|是| G{"atlas check:图新鲜?"}
G -->|滞后| H["atlas-stale 失败<br/>(绝不假报 symbol-missing)"]
G -->|新鲜| I{"每个符号在图中?"}
I -->|缺失| J[atlas-symbol-missing<br/>逐符号 step verdict]
I -->|全中| F
F --> K{五种 verdict 汇总}
K -->|is_passing| L["explain 验收 → stamp 盖章<br/>trace 记录带图指纹"]
K -->|fail/skip| M[Agent 读证据修码重试]
M --> C
注意两个设计细节如何在全链路里呼应:stale 优先(第 8 章)依赖 Atlas 的 blake3 新鲜度模型(第 16 章);最终 trace 记录里的图指纹让“当时对着哪个代码 状态验证的“永远可答(第 13 章)。验收时人类读到的 explain 摘要(第 9 章), 背后是这整条机械链的汇总——这就是为什么两个“是“就可以放心批准。
轨迹揭示的原则
两条轨迹的共同点:每个箭头都是一条命令,每个节点都有可校验的产物。系统的 可信不来自某个环节的聪明,而来自链条上没有一环允许“口头承诺“。