name: 前后验证 description: 为 loom 计划生成前后验证对。通过捕获实施前后的状态,证明一个阶段实际上改变了系统行为。用于 delta-proof 验证——通过比较系统状态来证明新命令、端点、模块或 bug 修复有效。 allowed-tools: 读取、Grep、Glob、编辑、写入、Bash trigger-keywords: 前 后, 前后, delta 证明, 证明变化, 证明新, 验证 delta, 状态转换, 实施前, 实施后
前后验证技能
概述
前后验证是一种技术,用于证明一个阶段 实际上改变了 系统行为。不仅仅检查最终状态是否有效,而是捕获实施前为真和实施后应为真的事实。这对证明你的阶段导致了变化至关重要。
这很重要,因为如果没有前后思考,你无法区分:
- “功能已经有效”与“我的阶段使其有效”
- “bug 已经修复”与“我的修复解决了它”
- “端点已存在”与“我创建了端点”
Delta-Proof 概念
delta-proof 是证明状态转换发生的验证。
模式
-
前状态: 捕获实施前的系统行为
- 对于新功能:预期失败(功能尚不存在)
- 对于 bug 修复:预期成功(bug 复现器展示问题)
-
后状态: 捕获实施后的系统行为
- 对于新功能:预期成功(功能现在存在)
- 对于 bug 修复:预期失败(bug 复现器不再触发 bug)
-
配对: 前后结合,证明实施导致了变化
为什么重要
没有 delta-proof 思考,验证可能误导:
坏例子:
# 阶段: 添加用户认证
truths:
- "cargo test" # 所有测试通过
问题: 测试可能在此阶段前已通过。这未证明认证被添加。
好例子:
# 阶段: 添加用户认证
description: |
实现基于 JWT 的用户认证。
前: curl -f localhost:8080/api/protected 返回 200(无需认证)
后: curl -f localhost:8080/api/protected 返回 401(现在需要认证)
后: curl -f -H "Authorization: Bearer <token>" localhost:8080/api/protected 返回 200
truths:
- "curl -sf localhost:8080/api/protected | grep -q 401"
- "curl -sf -H 'Authorization: Bearer fake' localhost:8080/api/protected && exit 1 || exit 0"
wiring:
- source: "src/middleware/auth.rs"
pattern: "pub fn require_auth"
description: "认证中间件已注册"
这证明认证被此阶段添加(而非已存在)。
何时使用前后思考
在以下情况使用 delta-proof 验证:
- 添加新功能 — 证明功能之前不存在
- 修复 bug — 证明 bug 之前存在且之后消失
- 改变行为 — 证明旧行为被新行为替换
- 创建端点/命令 — 证明它们新可用
- 重构伴随行为变化 — 证明行为实际改变
不要在以下情况使用:
- 验证直接简单(仅检查文件存在)
- 阶段仅为知识性(无实施)
- 仅检查代码质量(格式化、linting)
常见场景模板
场景 1: 新 CLI 命令
添加新 CLI 命令时,证明之前不存在。
前状态: 命令不存在(帮助失败或命令未找到) 后状态: 命令存在(帮助成功,基本调用有效)
- id: add-verify-command
name: "添加 loom verify 命令"
stage_type: standard
working_dir: "loom"
description: |
实现 `loom verify <stage-id>` CLI 命令。
DELTA PROOF:
- 前: `loom verify --help` 失败(命令未注册)
- 后: `loom verify --help` 成功
- 后: `loom verify test-stage` 运行验证逻辑
truths:
- "loom verify --help"
- "loom verify nonexistent-stage 2>&1 | grep -q 'Stage not found'"
wiring:
- source: "src/main.rs"
pattern: "verify"
description: "验证命令在 CLI 中注册"
- source: "src/commands/verify.rs"
pattern: "pub fn execute"
description: "验证命令实施存在"
artifacts:
- "src/commands/verify.rs"
场景 2: 新 API 端点
添加 API 端点时,证明之前返回 404 且之后返回数据。
前状态: 端点返回 404(未注册) 后状态: 端点返回预期状态/数据
- id: add-status-endpoint
name: "添加 /api/status 端点"
stage_type: standard
working_dir: "."
description: |
实现 GET /api/status 端点返回系统健康状态。
DELTA PROOF:
- 前: curl localhost:8080/api/status 返回 404
- 后: curl localhost:8080/api/status 返回 200 带 JSON 健康数据
truths:
- "curl -sf localhost:8080/api/status | jq -e '.healthy'"
- "curl -sf -o /dev/null -w '%{http_code}' localhost:8080/api/status | grep -q 200"
wiring:
- source: "src/routes/mod.rs"
pattern: "/api/status"
description: "状态端点在路由器中注册"
- source: "src/handlers/status.rs"
pattern: "pub async fn status_handler"
description: "状态处理程序实施"
artifacts:
- "src/handlers/status.rs"
场景 3: 新模块/库
添加新模块时,证明导入之前失败且之后成功。
前状态: 导入/使用失败(模块不存在) 后状态: 导入/使用成功
- id: add-retry-module
name: "添加重试模块"
stage_type: standard
working_dir: "loom"
description: |
创建带指数退避的重试模块。
DELTA PROOF:
- 前: `use crate::retry::RetryPolicy;` 会失败(模块不存在)
- 后: 模块编译,导出可用
truths:
- "cargo check"
- "cargo test --lib retry"
wiring:
- source: "src/lib.rs"
pattern: "pub mod retry"
description: "重试模块从 lib.rs 导出"
- source: "src/orchestrator/core/orchestrator.rs"
pattern: "use crate::retry"
description: "重试模块在协调器中导入"
artifacts:
- "src/retry.rs"
- "tests/retry_tests.rs"
场景 4: Bug 修复(反直觉)
修复 bug 时,证明 bug 复现器之前成功(bug 存在)且之后失败(bug 修复)。
前状态: Bug 复现器成功(展示 bug) 后状态: Bug 复现器失败(bug 不再触发)
这是反直觉但正确:复现器“工作”表示 bug 存在。
- id: fix-crash-on-empty-plan
name: "修复计划为空时崩溃"
stage_type: standard
working_dir: "loom"
description: |
修复初始化空计划时的崩溃。
DELTA PROOF(注意: 对于 bug,前后反转):
- 前: 空计划导致恐慌(bug 复现器成功找到 bug)
- 后: 空计划优雅返回错误(bug 复现器失败找到 bug)
验证方法:
1. 创建复现崩溃的测试用例
2. 测试应在修复后通过(优雅捕获崩溃)
3. 当恐慌不再发生时,证明 bug 修复
truths:
- "cargo test test_empty_plan_no_crash"
- "cargo test --lib plan::parser"
wiring:
- source: "src/plan/parser.rs"
pattern: "if stages.is_empty()"
description: "添加空阶段列表检查"
- source: "src/plan/parser.rs"
pattern: 'Err.*"Plan must contain at least one stage"'
description: "返回错误而非恐慌"
artifacts:
- "tests/empty_plan_tests.rs"
重要: 对于 bug 修复,测试应在修复前失败(复现 bug)且修复后通过。接线验证证明防御代码被添加。
常见陷阱
1. 测试错误内容
坏:
# 添加新用户注册端点
truths:
- "cargo test" # 太宽泛 - 未证明端点存在
好:
truths:
- "curl -sf -X POST localhost:8080/api/register -d '{\"email\":\"test@example.com\"}' | jq -e '.user_id'"
2. 未捕获足够状态
坏:
# 添加命令输出
truths:
- "loom status" # 仅检查它运行
好:
truths:
- "loom status | grep -q 'Active Plan:'"
- "loom status | grep -q 'Executing:'"
3. 忘记这是关于实施
前后是关于你的阶段改变什么,而非测试设置。
坏思维: “测试运行前,我需要设置数据。测试运行后,我清理。” 好思维: “我的阶段前,功能 X 不存在。我的阶段后,功能 X 工作。”
4. 当简单事实足够时使用前后
过度:
# 仅添加配置文件
description: |
前: config.toml 不存在
后: config.toml 存在
truths:
- "test -f config.toml"
更好:
artifacts:
- "config.toml"
保留前后思维用于行为变化,非简单文件添加。
5. Bug 修复方向混淆
错误:
# 修复无限循环 bug
description: |
前: 测试通过
后: 测试失败展示 bug
正确:
# 修复无限循环 bug
description: |
前: 代码进入无限循环(bug 存在)
后: 代码成功完成(bug 修复)
truths:
- "timeout 5s cargo test test_no_infinite_loop"
YAML 结构参考
Loom 有显式 before_stage 和 after_stage 字段接受 TruthCheck 定义。这些在阶段生命周期特定点运行:
before_stage: 在代理开始工作前运行(验证新工作树中的先决条件)after_stage: 当代理调用loom stage complete时运行(验证后置条件)
1. 前后阶段字段(显式 Delta Proof)
before_stage:
- command: "cargo test test_feature"
exit_code: 1
description: "功能测试在实施前失败"
after_stage:
- command: "cargo test test_feature"
exit_code: 0
description: "功能测试在实施后通过"
每个条目是 TruthCheck,字段: command(必需), exit_code(默认 0), description, stdout_contains, stdout_not_contains, stderr_empty。
2. Truths(捕获后状态)
truths:
- "证明功能有效的命令"
- "验证行为的测试"
Truths 在实施后运行,应成功。
3. Wiring(证明集成点)
wiring:
- source: "src/main.rs"
pattern: "register_feature"
description: "功能在主入口点注册"
4. Artifacts(证明文件存在)
artifacts:
- "src/feature/implementation.rs"
- "tests/feature_tests.rs"
5. 阶段描述(记录 Delta)
也在阶段描述中记录 delta-proof 思维供人阅读:
description: |
实现功能 X。
DELTA PROOF:
- 前: <此阶段前为真的事实>
- 后: <此阶段后应为真的事实>
[实施详情...]
完整例子
- id: add-metrics-endpoint
name: "添加 /metrics 端点"
stage_type: standard
working_dir: "."
description: |
添加 Prometheus 兼容的 /metrics 端点。
DELTA PROOF:
- 前: curl localhost:8080/metrics 返回 404
- 后: curl localhost:8080/metrics 返回 Prometheus 格式
- 后: 指标包括 request_count, response_time
实施:
- 创建指标中间件
- 注册 /metrics 端点
- 导出 request_count 和 response_time 测量器
dependencies: ["add-middleware-support"]
before_stage:
- command: "curl -sf localhost:8080/metrics"
exit_code: 1
description: "指标端点尚不存在"
after_stage:
- command: "curl -sf localhost:8080/metrics | grep -q 'request_count'"
exit_code: 0
description: "指标端点返回 request_count"
- command: "curl -sf localhost:8080/metrics | grep -q 'response_time'"
exit_code: 0
description: "指标端点返回 response_time"
truths:
- "curl -sf localhost:8080/metrics | grep -q 'request_count'"
- "curl -sf localhost:8080/metrics | grep -q 'response_time'"
- "curl -sf localhost:8080/metrics | grep -q 'TYPE request_count counter'"
wiring:
- source: "src/routes/mod.rs"
pattern: "Router.*metrics"
description: "指标端点已注册"
- source: "src/middleware/metrics.rs"
pattern: "pub fn track_metrics"
description: "指标中间件已实施"
artifacts:
- "src/middleware/metrics.rs"
- "src/routes/metrics.rs"
acceptance:
- "cargo test"
- "cargo clippy -- -D warnings"
与 Loom 计划集成
计划阶段
编写阶段描述时:
- 思考: “系统现在能做什么?”
- 思考: “系统在此阶段后应做什么?”
- 显式记录 delta
- 编写捕获后状态的验证
阶段描述模板
description: |
[此阶段作用的单行摘要]
DELTA PROOF:
- 前: [此阶段前的状态 - 预期失败/通过]
- 后: [此阶段后的状态 - 预期通过/失败]
[详细实施指导]
EXECUTION PLAN:
[如果使用子代理,描述并行工作]
验证策略
对于每个阶段,选择验证机制:
| 验证类型 | 使用时机 | 证明 |
|---|---|---|
truths |
行为可通过 shell 命令观察 | 功能在运行时工作 |
wiring |
功能必须与现有代码集成 | 代码已连接/注册 |
artifacts |
新文件必须存在 | 文件已创建 |
acceptance |
标准检查(构建、测试、lint) | 代码编译且测试通过 |
结合使用 truths 和 wiring 进行强 delta-proofs。
例子: 带 Delta Proof 的完整阶段
- id: add-stage-complete-command
name: "添加 loom stage complete 命令"
stage_type: standard
working_dir: "loom"
description: |
实现 `loom stage complete <stage-id>` 命令以标记阶段为完成。
DELTA PROOF:
- 前: `loom stage complete --help` 失败(命令不存在)
- 后: `loom stage complete --help` 显示用法
- 后: `loom stage complete test-stage` 将阶段转换为完成状态
实施:
- 添加 StageComplete 命令到 CLI
- 实现状态转换逻辑
- 添加阶段存在验证
- 用完成时间戳更新阶段文件
dependencies: ["knowledge-bootstrap"]
truths:
- "loom stage complete --help"
- "loom stage list | grep -q complete"
wiring:
- source: "src/main.rs"
pattern: "Commands::StageComplete"
description: "StageComplete 命令在 CLI 中注册"
- source: "src/commands/stage.rs"
pattern: "pub fn complete"
description: "阶段完成实施存在"
- source: "src/models/stage/transitions.rs"
pattern: "fn transition_to_completed"
description: "状态转换逻辑已实施"
artifacts:
- "src/commands/stage.rs"
acceptance:
- "cargo test"
- "cargo test stage_complete"
- "cargo clippy -- -D warnings"
工作目录和路径
所有验证路径相对于 working_dir:
working_dir: "loom" # 命令从 loom/ 目录执行
truths:
- "cargo test" # 在 loom/ 中运行(Cargo.toml 所在处)
artifacts:
- "src/commands/verify.rs" # 解析为 loom/src/commands/verify.rs
wiring:
- source: "src/main.rs" # 解析为 loom/src/main.rs
如果 working_dir: ".",路径相对于工作树根目录。
最佳实践
- 记录 delta 在阶段描述中 - 使前后显式
- 使用 truths 进行运行时行为 - 证明功能在调用时有效
- 使用 wiring 进行集成 - 证明功能已连接
- 谨慎使用 artifacts - 优先 truths/wiring 而非文件存在
- 测试 delta - 针对实际实施运行 truths
- 从用户角度思考 - 用户会尝试什么来证明它有效?
摘要
前后验证证明你的阶段改变了系统:
- 新功能: 前失败 → 后成功
- Bug 修复: 前成功(bug 存在) → 后失败(bug 消失)
- 行为变化: 前显示旧行为 → 后显示新行为
使用 before_stage/after_stage 进行显式自动化 delta-proof,truths 捕获后状态,wiring 证明集成,artifacts 证明文件存在。
始终思考: “我能测量什么来证明此阶段有差异?”