关于 trace
trace 是面向仓库的需求追踪检查技能,通过确定性扫描比对需求定义、任务引用与测试覆盖,并按固定规则报告错误和警告。
主要功能
- 01检查需求 ID 定义、引用与测试覆盖
- 02报告重复定义和缺失引用
- 03验证状态对应的任务或测试要求
- 04检查架构不变量及 Respects 引用
- 05可纳入决策记录验证结果
适用场景
- 01发布前检查需求追踪是否完整
- 02定位任务或测试中的未知需求 ID
- 03确认已实现需求是否有测试覆盖
- 04核对设计引用的架构不变量
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jayden-dang/ skills --skill trace安装后在 Claude Code 中输入/trace确认已加载。
详细介绍
Trace
垂直可追溯性检查。它通过证据回答一个问题:每个需求 ID 在定义、引用和测试中的内容是否一致?
这不是主观判断。每项输入都通过 grep 收集和读取——采用确定性流程——且每项发现都遵循固定规则。两个 Agent 在同一个仓库中运行此检查,会得到相同的发现集合。
生成内容
一组发现,每项均为 ERROR 或 WARNING:
| 代码 | 级别 | 条件 |
|---|---|---|
| E1 | 错误 | 某个任务或测试引用的 ID 未在任何需求文件中定义 |
| E2 | 错误 | 某个状态为 Implemented 或 Shipped 的需求没有对应的测试 |
| E3 | 错误 | 同一个 ID 在多个文件中以粗体定义 |
| W1 | 警告 | 某个状态为 Approved 的需求没有被任何任务引用 |
| W2 | 警告 | 某个 requirements.md 缺少 Status: 或 Feature code: 行 |
| E4 | 错误 | 某个 Respects: 行引用了 docs/architecture/ 中没有定义的 ARCH-N |
| E5 | 错误 | 某个 Respects: 行引用了已弃用(已删除线标记)的 ARCH-N |
| W3 | 警告 | 某个有效的 **ARCH-N** 不变量没有被任何 design.md 引用 |
E4/E5/W3 来自不变量检查流程,只有存在主干时才会运行。
错误意味着追踪链断裂。警告意味着追踪链不完整,但没有错误。verify/release 会将任何错误视为失败的门禁;警告会报告,但不会导致失败,除非调用方另有要求。
输入
- 规格说明位于
docs/specs/下(或docs/agents/project.md中指定的specsDir)。定义来自以requirements.md或fixes.md结尾的文件;任务引用来自以tasks.md结尾的文件。 - 测试位于仓库的测试目录中。默认搜索根目录:
tests test e2e src src-tauri crates app lib packages(跳过不存在的目录)。其中,测试文件指路径符合以下任一模式的文件:\.(test|spec)\.[cm]?[jt]sx?$· 包含/tests?/或/e2e/路径段 ·_test\.(rs|go|py)$· 或任何.rs文件(Rust 会在文档注释中引用 ID)。 - 如果
docs/agents/project.md指定了不同的测试 glob 或忽略列表,则使用该设置。如果该文件不存在,请说明这一点并使用默认设置。 - 跳过
node_modules .git dist build target coverage .next .skills vendor以及任何点文件/点目录。
检查流程
对仓库根目录运行以下检查,并读取每项检查的完整输出——遵守下文 NON-NEGOTIABLE 部分中的全树规则。
1. 定义——需求/修复文件中的粗体 ID,排除已弃用的 ID。
# every bold **CODE-N.M** in a requirements/fixes file, retired (~~struck~~) ones deleted first
grep -rnE '\*\*[A-Z][A-Z0-9]{1,11}-[0-9]+\.[0-9]+\*\*' docs/specs \
--include='*requirements.md' --include='fixes.md' \
| sed -E 's/~~[^~]*~~//g' \
| grep -E '\*\*[A-Z][A-Z0-9]{1,11}-[0-9]+\.[0-9]+\*\*'
每行保留的结果格式为 path:line:text;该行中剩余的每个粗体 ID 都是定义,归属路径为 path。sed 会删除 ~~ … ~~ 跨度,因此已弃用的 ID 不会出现在结果中。需求文件中的普通(非粗体)ID 属于正文,不是定义。
2. 状态和功能代码——逐个检查需求文件。
grep -rnE '^(Status:|Feature code:)' docs/specs --include='*requirements.md'
Status: 的值为 Draft | Approved | Implemented | Shipped 之一(采用首次匹配结果)。
3. 任务引用——_Requirements: 行上的 ID。
grep -roE '_Requirements:.*' docs/specs --include='*tasks.md' \
| grep -oE '^[^:]+:|[A-Z][A-Z0-9]{1,11}-[0-9]+(\.[0-9]+)+' \
| grep -E '^[^:]+:$|^[A-Z][A-Z0-9]{1,11}-[0-9]+\.[0-9]+$'
只有包含字面文本 _Requirements: 的行上的 ID 才是任务引用。输出会交替出现一行 path: 和该行引用的 ID——每个 ID 都属于其上方的 path:。末尾的 grep 只保留完整的两级标记,因此三级 CODE-1.2.3 不会被误读为对 CODE-1.2 的引用。
4. 测试覆盖——出现在测试文件任意位置的每个 ID 字符串。搜索所有存在的测试根目录;以下为 JS/TS 和 Rust 的默认设置:
grep -roE '[A-Z][A-Z0-9]{1,11}-[0-9]+(\.[0-9]+)+' \
$(printf '%s ' tests test e2e src src-tauri crates app lib packages) 2>/dev/null \
--include='*.test.*' --include='*.spec.*' --include='*_test.rs' \
--include='*_test.go' --include='*_test.py' --include='*.rs' \
| grep -E ':[A-Z][A-Z0-9]{1,11}-[0-9]+\.[0-9]+$' \
| sort -u
每行输出格式为 path:ID——覆盖该 ID 的测试文件及其覆盖的 ID。根据仓库的实际布局调整根目录/包含项。ID 语法与流程 3 相同,仅支持两级 ID。
不变量检查 — 仅在存在 docs/architecture/ 时执行
如果仓库中没有 docs/architecture/ 目录,则完全跳过检查 5–6;发现项仍为检查 1–4,不变。存在主干文档时,增加:
5. 不变量定义 — 主干文档中加粗的 **ARCH-N**,分为 已废弃 集合(带删除线)和 有效 集合(未废弃项),处理方式与检查 1 处理需求完全相同。
# retired invariants — the E5 set (struck-through, captured BEFORE deletion)
grep -rhoE '~~\*\*ARCH-[0-9]+\*\*~~' docs/architecture | grep -oE 'ARCH-[0-9]+' | sort -u
# live invariants — strike spans deleted first, then match (as in pass 1)
grep -rh '' docs/architecture --include='*.md' \
| sed -E 's/~~[^~]*~~//g' \
| grep -oE '\*\*ARCH-[0-9]+\*\*' | grep -oE 'ARCH-[0-9]+' | sort -u
第一个 grep 得到的是已废弃集合;第二个 grep(移除带删除线的内容)得到的是有效集合。既不在其中一个集合、也不在另一个集合中的 ARCH-N 均未定义。
6. Respects 引用 — 任意 design.md 中 Respects: 行上的每个 ARCH-N。
grep -rnE 'Respects:.*ARCH-[0-9]+' docs/specs --include='*design.md' \
| grep -oE '^[^:]+:|ARCH-[0-9]+'
每个被引用的 ARCH-N 都归属于它所在的 design.md。
规则
拿到这四个集合后——defined(ID → {file, status})、taskCited、testCovered——应用以下规则:
- E1 — 对于
taskCited ∪ testCovered中不在defined里的每个 ID:报告该 ID 及引用它的文件。 - E2 — 对于
defined中状态为Implemented或Shipped且不在testCovered里的每个 ID:报告该 ID。(任务引用不能满足 E2,只有测试可以。) - E3 — 对于在两个或更多不同文件中被加粗定义的每个 ID:报告这些文件。(同一文件中出现两次加粗定义不算重复。)
- W1 — 对于
defined中状态恰好为Approved且不在taskCited里的每个 ID:报告该 ID。 - W2 — 对于每个缺少
Status:或Feature code:行的requirements.md(绝不包括fixes.md):报告缺少哪一行。
当存在 docs/architecture/ 时,拿到 liveArch、retiredArch 和 respectsCited(ARCH-N → 引用它的 design)后,还要执行:
- E4 — 对于
respectsCited中既不在liveArch、也不在retiredArch里的每个ARCH-N:报告该 ID 及引用它的design.md。 - E5 — 对于
respectsCited中在retiredArch里的每个ARCH-N:报告该 ID 及引用它的design.md。 - W3 — 对于
liveArch中不在respectsCited里的每个ARCH-N:报告该 ID。
状态要求一览:
| 状态 | 需要测试(E2) | 需要任务(W1) |
|---|---|---|
| Draft | 否 | 否 |
| Approved | 否 | 是 |
| Implemented / Shipped | 是 | 否 |
覆盖只看文本是否出现——不要作判断
当某个 ID 字符串出现在测试文件中时,该 ID 就算已覆盖。仅此而已。不要阅读测试来判断它是否“真正”测试了该需求、断言是否有意义,或注释掉的行是否应计入。此类判断不属于这项检查;加入这些判断会使结果取决于读者,而这正是这项检查要避免的唯一问题。
唯一允许的排除方式,是在 docs/agents/project.md 中设置忽略列表:在其中列出的文件(例如将 ID 作为数据保存的 fixture 或测试辅助文件)会整体从测试搜索中排除,而不是由人工逐个 ID 排除。
同样,务必收集所有匹配文件。漏掉一个测试文件就会产生错误的 E2;漏掉一个需求文件就会产生错误的 E1。对整个目录树执行 grep;不要抽样,也不要根据哪些文件“可能”相关来判断。
同一规则也适用于不变量检查:E4/E5/W3 只检查 Respects: ARCH-N 引用的名称是否对应一个有效不变量——即是否存在且仍有效。绝不要判断设计是否真正遵守该不变量;这种语义判断属于 check-invariants / code-review,不属于 trace。
决策记录检查 — 仅当存在 .skills/decisions/ 时运行
如果仓库中不存在 .skills/decisions/ 目录,则完全跳过本节;检查结果仍为第 1–6 轮(或第 1–4 轮),不作更改。
当 .skills/decisions/ 存在时,运行随附的验证器(相对于此技能集安装路径,与 record-decision 位于同一目录):
sh skills/ship/record-decision/validate-records.sh --mode=trace
将其诊断行原样合并到报告中。退出码为 1 → 视为跟踪错误(门禁失败)。退出码为 2 → 决策记录检查标记为未运行(绝不能标记为“已通过”)。退出码为 0 → 没有决策记录错误(仍可能出现警告)。
不要重新解读验证器的发现。越界操作未留记录:验证器不会自动报告“生产环境越界操作缺少记录”,因为它无法区分由技能介导的判定与直接的人为操作或外部贡献。如果 Agent 或人工发现缺少记录,只能将其视为警告级别的问题——绝不能视为错误,也不能导致发布/验证门禁失败。E1–E5 / W1–W3 的语义保持不变。
输出
报告计数,然后列出发现:
trace: 24 requirements · 24 task-cited · 22 tested · 18 test files
ERROR E1 test cites unknown requirement SHELL-9.9 (src/shell.test.ts)
ERROR E2 SHELL-1.4 (docs/specs/2026-07-01-shell/requirements.md, Implemented) has no covering test
warn W1 NOTES-2.1 (…/requirements.md, Approved) is not cited by any task
具体措辞和顺序不作要求,发现集合才是判断依据。如果 docs/specs/ 不存在,说明没有内容需要检查,然后停止。当调用方(verify、release)需要判定通过/失败时,门禁规则为:错误数为零。