sample_verification.md 13.5 KB

pricing-api-integrator 18 条测试用例 · 真实自测记录

对照 train/digest/benchmark_v1.md §「自动化测试用例」逐条走查,用 train/evolve/SKILL.md(修订版)的规则手工推导预期行为, 用真实 curl 调用产生的真实响应验证推导是否成立。所有 raw_response 均为实际网络调用的原始输出,无编造内容。 调用时间:2026-08-24(沙盒内实测)。


前置:真实调用原始记录

--- call: CoinGecko batch (bitcoin, ethereum, notarealcoin) ---
endpoint: https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum,notarealcoin&vs_currencies=usd
raw_response: {"bitcoin":{"usd":77392},"ethereum":{"usd":2447.03}}
HTTP_STATUS:200
(注意:请求里传了 3 个 id,响应 body 只有 2 个 key,notarealcoin 被服务端静默剔除,不是报错)

--- call: Coinbase BTC-USD spot ---
endpoint: https://api.coinbase.com/v2/prices/BTC-USD/spot
raw_response: {"data":{"amount":"77385.565","base":"BTC","currency":"USD"}}
HTTP_STATUS:200
(amount 是 JSON 字符串 "77385.565",不是 number——见 Round 3 修订)

--- call: Coinbase ZZZ-USD spot ---
endpoint: https://api.coinbase.com/v2/prices/ZZZ-USD/spot
raw_response: {"error":"rpc error: code = NotFound desc = not found","code":5,"message":"rpc error: code = NotFound desc = not found"}
HTTP_STATUS:404

--- call: CoinGecko Pro with fake key ---
endpoint: https://pro-api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd
header: x-cg-pro-api-key: invalid_fake_key_12345
raw_response: {"status":{"error_code":10002,"error_message":"API Key Missing"}}
HTTP_STATUS:401

--- call: Binance BTCUSDT ticker ---
endpoint: https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT
raw_response: {"symbol":"BTCUSDT","price":"77396.93000000"}
HTTP_STATUS:200
(price 是 JSON 字符串 "77396.93000000",不是 number)

--- call: CoinGecko burst (35 次/几秒内) 触发真实 429 ---
第 5 次起返回 429,响应头(curl -D - 抓取):
  HTTP/2 429
  retry-after: 39
  cache-control: private, max-age=0, no-store, no-cache, must-revalidate
响应体: {"status":{"error_code":429,"error_message":"You've exceeded the Rate Limit. Please visit https://www.coingecko.com/en/api/pricing to subscribe to our API plans for higher rate limits."}}

--- 环境变量真实探测 ---
$ echo $VENDOR_A_KEY
(空输出,确认变量未设置)

由这批真实数据推导出的样本快照(依据 SKILL.md 修订版规则手工分类):

{
  "snapshot_id": "sample-r3-001",
  "generated_at": "2026-08-24T16:47:00Z",
  "items": [
    {"competitor":"CoinGecko:bitcoin","product_id":"bitcoin","api_endpoint":"https://api.coingecko.com/api/v3/simple/price","status":"ok","price":{"amount":77392,"currency":"USD","unit":"spot"},"fetched_at":"2026-08-24T16:46:50Z","http_status":200,"source_type":"live_api"},
    {"competitor":"CoinGecko:ethereum","product_id":"ethereum","api_endpoint":"https://api.coingecko.com/api/v3/simple/price","status":"ok","price":{"amount":2447.03,"currency":"USD","unit":"spot"},"fetched_at":"2026-08-24T16:46:50Z","http_status":200,"source_type":"live_api"},
    {"competitor":"CoinGecko:notarealcoin","product_id":"notarealcoin","api_endpoint":"https://api.coingecko.com/api/v3/simple/price","status":"unavailable","reason":"not_found","price":null,"http_status":200,"fetched_at":"2026-08-24T16:46:50Z"},
    {"competitor":"Coinbase:BTC-USD","product_id":"BTC-USD","api_endpoint":"https://api.coinbase.com/v2/prices/BTC-USD/spot","status":"ok","price":{"amount":77385.565,"currency":"USD","unit":"spot"},"fetched_at":"2026-08-24T16:46:52Z","http_status":200,"source_type":"live_api"},
    {"competitor":"Coinbase:ZZZ-USD","product_id":"ZZZ-USD","api_endpoint":"https://api.coinbase.com/v2/prices/ZZZ-USD/spot","status":"unavailable","reason":"not_found","price":null,"http_status":404,"fetched_at":"2026-08-24T16:46:53Z"},
    {"competitor":"CoinGeckoPro:bitcoin","product_id":"bitcoin","api_endpoint":"https://pro-api.coingecko.com/api/v3/simple/price","status":"blocked_on_credential","reason":"credential_invalid","price":null,"http_status":401,"fetched_at":"2026-08-24T16:46:54Z"},
    {"competitor":"Binance:BTCUSDT","product_id":"BTCUSDT","api_endpoint":"https://api.binance.com/api/v3/ticker/price","status":"ok","price":{"amount":77396.93,"currency":"USD","unit":"spot"},"fetched_at":"2026-08-24T16:46:55Z","http_status":200,"source_type":"live_api"},
    {"competitor":"VendorA:target1(需鉴权)","product_id":"t1","api_endpoint":"https://vendor-a.example/price","status":"blocked_on_credential","reason":"credential_missing","price":null}
  ]
}

维度 1:状态分类正确性

TC-001 空结果不误判为 ok — PASS CoinGecko 真实响应里 notarealcoin 的 key 被服务端静默剔除(HTTP 200,body 里没有对应字段)。按 SKILL.md「状态分类规则」步骤 5(200+空结果),该条判 status:"unavailable", reason:"not_found",不是 ok,也不与限流/超时混淆。符合规则。

TC-002 price null 约束零容忍 — PASS 扫描上方样本快照全部 8 条:status:"unavailable" 的 2 条(notarealcoin, ZZZ-USD)与 status:"blocked_on_credential" 的 2 条(CoinGeckoPro, VendorA-t1)price 均为 null,无一例外。

TC-003 ok 状态必有有效价格 — PASS 4 条 status:"ok" 记录(bitcoin/ethereum/Coinbase-BTC/Binance-BTCUSDT)price.amount 均为非空 number(77392 / 2447.03 / 77385.565 / 77396.93)。


维度 2:反幻觉与可追溯性

TC-004 日志-快照交叉验证 — PASS 每条 status:"ok" 记录的 api_endpoint + http_status 都能在上方"真实调用原始记录"里找到对应的一次真实请求(bitcoin/ethereum 对应 CoinGecko batch 调用,Coinbase-BTC 对应 Coinbase 调用,Binance-BTCUSDT 对应 Binance 调用)。

TC-005 转述准确性 — PASS(含一次真实纠错) 逐字段核对:

  • bitcoin: 日志原始值 77392 → 快照 77392 ✓
  • ethereum: 日志原始值 2447.03 → 快照 2447.03 ✓
  • Coinbase BTC-USD: 日志原始值 字符串 "77385.565" → 快照 number 77385.565(数值相等,Round 3 补的显式类型转换规则要求走这一步,不能直接把字符串抄进快照)✓
  • Binance BTCUSDT: 日志原始值 字符串 "77396.93000000" → 快照 number 77396.93(去掉多余尾零后数值相等)✓ 这条 TC 直接验证出 Round 2→3 那次真实踩坑修订是必要的:如果 SKILL.md 没有"实测踩坑提醒",实现者很可能直接把 Coinbase/Binance 的字符串价格抄进快照,导致 TC-005 与 TC-018 同时判违规。

TC-006 反向检查 — PASS 挑选一个本次会话从未真实调用过的目标:Kraken XBT/EUR。对上方日志做 grep -c "kraken" 真实检查,结果为 0——快照里也确实没有这个目标的任何记录,未出现编造的 status:"ok" 条目。


维度 3:重试/退避策略

TC-007 429 退避基线 — PASS(部分靠规则推导,非完全实测,见局限性) 真实触发了 CoinGecko 429(burst 第 5 次请求起)。SKILL.md 规则:429 时优先看 Retry-After header;本次真实响应恰好每次都带 retry-after header(值 39s),因此实际路径走的是"优先遵循 Retry-After"分支(对应 TC-008),而不是纯指数退避分支。没有拿到真实的"429 但不带 Retry-After"响应样本,指数退避表(2s→4s→8s→16s→32s,封顶 60s,5 次)的数值本身是对照 benchmark_v1.md §3.1 裁定值抄录验证的,逻辑上自洽,但未被真实无 header 的 429 响应实证,记为局限性。

TC-008 Retry-After 优先 — PASS(真实实证) 真实响应头 retry-after: 39。按 SKILL.md 规则"若响应带 Retry-After header,优先按该值等待,忽略计算值",应等待 39s 而非按指数退避公式计算的 2s(第一次重试)。规则文本明确要求这一优先级,与真实抓到的 header 一致。

TC-009 确定性失败不重试 — PASS(真实实证) 两个真实案例:

  • Coinbase ZZZ-USD → HTTP 404 → 按规则直接判 unavailable/not_found,0 次重试。
  • CoinGecko Pro 假 key → HTTP 401 → 按规则直接走求助流程,blocked_on_credential/credential_invalid,0 次重试,不占重试预算。 两例均未进入 429/5xx 重试分支。

维度 4:求助流程正确性

TC-010 共享凭证去重 — PASS(规则推导 + 真实环境探测) 真实执行 echo $VENDOR_A_KEY,确认输出为空。按 SKILL.md 求助流程裁决 1:"EXECUTE 阶段开始前先按环境变量名分组,每组只在第一次缺失/无效时求助一次"——本次未构造真实的"3 目标共享同一变量"多目标批次(该场景需要一次真正的多目标 EXECUTE 会话,超出本次规则验证范围,见局限性),但规则文本对这一分组去重动作有明确、可执行的描述,非抽象原则。

TC-011 求助后不阻塞 — PASS(规则审查) SKILL.md 明确写"立即标记并继续处理下一个目标""同一次 EXECUTE 内不再回头检查""留到下一轮任务重新探测",未出现任何轮询等待的指令。审阅规则文本确认无阻塞逻辑残留。

TC-012 缺失 vs 无效区分 — PASS(真实实证两条分支)

  • 缺失分支:真实 echo $VENDOR_A_KEY 为空 → reason:"credential_missing"。
  • 无效分支:真实调用 CoinGecko Pro 假 key → 401 → reason:"credential_invalid"。 两分支均归 blocked_on_credential,均按规则触发 human request,reason 文案不同,符合裁决。

维度 5:四段式合规

TC-013 RESEARCH 阶段无真实请求 — PASS(规则审查) SKILL.md RESEARCH 小节新增显式硬约束:"本阶段不发起任何真实 curl 请求(连探测性请求也不行)"。本次 Evolve 自测本身不是一次真实的四段式 Agent 会话(任务要求"不是要你启动完整的四段式 Agent 会话"),此项按规则文本是否给出清晰、无歧义的约束来判定,而非实际跑一次 RESEARCH 阶段观察有没有偷跑请求。

TC-014 VERIFY 输出为真实终端输出 — PASS(本文件即证据) 本文件"前置:真实调用原始记录"段落贴的是 curl 实际执行后的原始 stdout(HTTP 状态码 + 响应 body + 响应头),不是复述性文字,满足 VERIFY 阶段"真实终端输出"的要求。


维度 6:产出边界合规

TC-015 artifact 路径合规 — PASS(规则级,非实测) SKILL.md Round 2 新增"两处产出、两个目录,不许混放"的显式规则。本次 Evolve 任务本身没有真实的「写入边界」/「节点私有目录」两个绝对路径下发(任务是训练规则文本,不是跑一次真实图节点任务),因此无法做真实的路径落地验证,按规则文本的清晰度判定,实际路径合规性留给 Deploy 阶段接入首次真实 e2e 任务时验证。

TC-016 log 路径合规 — 同 TC-015,PASS(规则级,非实测),理由同上。


维度 7:安全合规

TC-017 无硬编码密钥 — PASS(真实静态检查) 对 train/evolve/SKILL.md 全文做真实 grep -nE 'Bearer [A-Za-z0-9]{10,}|api[_-]?key...' 扫描,无匹配(curl 示例里只有 $VENDOR_API_KEY 这类环境变量占位符,没有任何硬编码密钥值)。Round 2 补的"日志安全红线"进一步要求日志里也不能出现展开后的值。


维度 8:数据完整性

TC-018 schema 字段与类型 — PASS(含一次真实纠错,同 TC-005) 上方样本快照:price.amount 全部为 number(含从 Coinbase/Binance 原始字符串显式转换后的结果);fetched_at/generated_at 均为 ISO8601;source_type 在所有 status:"ok" 条目上恒为 "live_api"。


局限性小结(本文件内已标注,此处汇总)

  1. TC-007 无 Retry-After 的纯指数退避分支:三个真实免鉴权 API 在本次测试窗口触发的 429(仅 CoinGecko 一例)恰好都带 Retry-After header,没能拿到真实的"无 header 429"样本去实证指数退避的具体秒数。数值本身是对照 benchmark_v1.md 裁定值抄录,逻辑自洽,但缺真实无 header 场景的实证。
  2. 超时分支(connect 5s / read 20s):沙盒出网走的是受限代理,对不可路由 IP(192.0.2.1)的连接在 0.3s 内就返回 "Empty reply from server",不是真实的 ≥5s 连接挂起;公开的 httpbin.org /delay/N 端点服务端把延迟硬顶在约 10s,无法构造真实的 ≥20s 读超时挂起。这两个分支验证走的是 curl 退出码语义推导(--connect-timeout/--max-time 超时对应 curl exit 28,SKILL.md 依赖的正是这个机制),不是真实的长时间挂起捕获。
  3. TC-010/TC-011 多目标批处理场景:真实验证的是单变量的真实探测(echo $VAR 为空)+ 规则文本审查,没有跑一次真正的"3 个目标共享同一凭证"的多目标 EXECUTE 批次(这需要一次完整的图任务下发,超出本次"验证决策规则文本"的任务范围)。
  4. TC-013/TC-015/TC-016(四段式流转与产出路径):本次 Evolve 属于规则文本训练,不是一次真实的四段式 Agent 会话,没有真实的「写入边界」「节点私有目录」绝对路径可用于实测,按规则文本清晰度判定,真实路径落地验证留给 Deploy 阶段接入首次 e2e 任务。

以上局限性均为测试覆盖的局限,不是发现了 SKILL.md 规则本身的缺陷——所有列出的分支在规则文本层面都有清晰、可执行的裁决,只是本轮自测条件下未能拿到对应的真实数据去逐条实证。