Skip to content

docs(eval): post-fix validation telemetry report (smoke scope) - #410

Open
ceilf6 wants to merge 1 commit into
developfrom
docs/eval-postfix-validation-report
Open

docs(eval): post-fix validation telemetry report (smoke scope)#410
ceilf6 wants to merge 1 commit into
developfrom
docs/eval-postfix-validation-report

Conversation

@ceilf6

@ceilf6 ceilf6 commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Linked Issue Or Context

Summary

Adds benchmarks/results/2026-07-31-validation-telemetry.md plus the raw
double-arm JSONL under benchmarks/results/2026-07-31-smoke/.

This is not a re-run of the 2026-07-12 ablation, and it deliberately draws no
pass-rate conclusion. It answers a prior question: is the "multi-layer
validation never intercepted anything" finding itself trustworthy?

Answer: partly not — a substantial part of it was an observability artifact.

The load-bearing evidence

A deterministic probe — zero LLM spend, identical input, through the real
runFrontAgentTask entry point the harness uses:

pre-fix (develop @ db42301) post-fix (#402)
validation_failed 0 1 (syntax_validity)
bad file on disk yes (40 B) no
task error Syntax errors found in … Pre-write validation failed: …
step_failed 1 1

step_failed is 1 in both. The check was running and failing all along — it
just emitted no event and left the file on disk. Pre-fix, validation_failed had
no emit site anywhere in the repo, so it could not have been anything but 0.

Three limitations stated up front in the report

  1. validation_failed was not a pure interception signal in this run. The
    numbers were produced on fix(executor): validate writes before disk, wire rollback, emit validation_failed #402's first implementation (543b791), where the
    event compounded pre-execution structural blocks, real content interceptions,
    and pure tool failures (validateAfterExecution returns results: [] on
    success === false). Fixed later in 1a54e25; the report classifies every
    event in this run rather than quoting a raw count.
  2. n=5 per arm. No pass-rate conclusion is drawn.
  3. Bad files still reach disk. Both full-arm failures were TS1127 — model
    prose written into .ts/.tsx. Feeding those exact artifacts to the guard
    returns pass: true ([Bug] Guard syntax check passes prose-as-code — TS1127 corruption reaches disk unflagged #406). The interception bottleneck is now checker
    strength, not the executor pipeline this PR series fixed.

Numbers

full ablation
passed 3/5 2/5
validation_failed (old composite) 0 2
— real content interceptions 0 0
— pre-execution structural blocks 0 2
rollback_started 0 0
wall time 27.2 min 28.6 min
LLM calls (failures) 34 (0) 39 (0)
tokens in/out 112,648 / 137,363 98,101 / 160,163

Full 30-task run: not run

Not blocked by quota — blocked by wall time, so per instruction it was not forced.
Extrapolated from this run against July's same 5 tasks (27.2 / 24.5 ≈ 1.11):
≈ 4.5 h for both arms, ≈ 758K in / 1.33M out tokens, ≈ $10. Backend
availability verified (claude CLI v2.1.220, probe is_error: false, 73 calls
this run with 0 failures). Preconditions recommended before spending it are in
§6 of the report.

Comparability against July

Verified at the July baseline commit 51fd4bb rather than assumed. Same task
set, fixture, and model. Two genuine differences are documented in §5: the
ablation arm's semantics changed once #392 made checks effective, and #402
adds pre-write blocking. #407 degrades both arms and July identically, so it is
not an arm-biasing confound.

Self-correction recorded in the report

I initially misattributed the ablation failures to #407 based on an error message
naming claude-3-5-sonnet-20241022, and filed an incorrect root-cause issue. That
model name is fabricated by formatRunError from resolved config and has nothing
to do with the failure site; the real error was
Cannot apply patch: file not found in context: …. #407 carries a correction
notice, and the true cause is #408. The report keeps this on the record because
the fabricated provider/model/baseURL triple is precisely what makes the
wrong conclusion look well-evidenced.

Impact Scope

  • benchmarks/results/ only — one Markdown report and two JSONL files.
  • No source, config, or workflow changes.

GitNexus Impact Summary

  • Risk level: LOW
  • Critical skeleton changes: no — benchmarks/results/ matches no critical contract rule; this is a documentation and data artifact.
  • GitNexus impact: detect_changes --scope compare --base-ref develop reports 4 files / 15 symbols, 0 affected execution flows, risk low; all symbols are Markdown headings in the new report, and query/impact show no code symbol reachable from these paths.
  • Verification: pnpm quality:precommit exit 0 (turbo 25/25, workflows 34/34); no executable surface touched.

Verification

  • pnpm quality:precommit — exit 0, turbo 25/25 tasks, test:workflows 34/34.
  • Raw JSONL committed alongside the report so every number is recomputable:
    benchmarks/results/2026-07-31-smoke/{full,ablation}.jsonl.
  • The before/after probe is reproducible without LLM spend; its construction is
    described in §2 of the report.

Checklist

  • I have linked an issue or explained why this PR stands alone.
  • I have kept the diff focused on the stated change.
  • I have run pnpm quality:precommit, or explained why it could not run.
  • I have run pnpm quality:local for critical skeleton changes, or explained why it could not run.
  • I have updated docs or tests when behavior, public APIs, or Harness contracts changed.
  • For critical skeleton changes, I have filled the GitNexus impact summary with concrete results.

本轮不是 7-12 消融结论的重跑,而是先回答「多层校验零拦截」这个结论
本身是否可信。确定性对照(零 LLM 消耗、同一输入、真实 runFrontAgentTask
路径)显示:修复前 validation_failed=0 且坏文件落盘,修复后 =1 且不落盘,
而两者的 step_failed 都是 1——校验一直在跑也一直判失败,只是不发事件、
坏文件还留在盘上。故原结论至少在事件维度是观测缺陷造成的假象。

同时记录三条限定:①本轮数字产生于口径修复(1a54e25)之前,
validation_failed 仍是复合值,报告内已逐条归类;②n=5 不支持通过率结论;
③guard 语法检查放行散文(#406),full 臂两条 TS1127 坏文件仍留在磁盘上——
当前拦截率瓶颈是检查器强度而非执行器管线。

全量 30 条双臂未跑:实测外推约 4.5 小时 / ≈$10,按纪律不硬跑,
成本与前置条件写在报告第六节。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ ceilf6/repo-guard

代码评审报告: docs(eval): post-fix validation telemetry report (smoke scope)

风险等级:
处理建议: 评论
决策摘要: 纯 docs/data,无源码与消费方影响,可合并;但合并前建议修正 §三 的事件归类归因(与报告自己引用的错误串矛盾)与 §六 的外推口径(少乘一个因子),否则这份报告一旦被当作后续基线引用,会复制它正在纠正的那类误判。

级联分析

  • 变更符号: 无代码符号。新增 3 个文件均在 benchmarks/results/,仅 Markdown 标题与 JSONL 数据行。
  • 受影响流程: 0。benchmarks/eval/report.mjs 写的是 benchmarks/results/{full,ablation}.jsonl(7 月数据),不读取新增的 2026-07-31-smoke/ 目录;仓库内除 README.md:1312 的目录级链接外无其他引用(text search)。
  • 变更集外调用方: 无。
  • 置信度: high(对合并风险而言);对报告内容正确性为 medium — 支撑 §二 探针与 §三 归类的原始事件负载未提交,无法从 diff 内复算。

已复算并全部对上(证据来自本 PR 提交的 JSONL 与仓库内 7 月原始数据):

  • full 3/5、ablation 2/5;validation_failed 0 / 2;rollback_started 0 / 0。
  • LLM 调用 34 / 39,合计 73,失败 0。
  • token 112,648/137,363 与 98,101/160,163,逐条累加精确相符。
  • 耗时 1,632,623 ms = 27.2 min、1,718,037 ms = 28.6 min。
  • 逐任务 PASS/FAIL 表与 pass 字段一致。
  • §六 的 27.2 / 24.5 ≈ 1.11:7 月 full.jsonl 同 5 条任务合计 1,471,801 ms = 24.53 min,比值 1.109,可复算。

代码层断言也逐条核对通过:validateAfterExecutionsuccess === false 时返回 results: []packages/core/src/executor/executor.ts:531);本 checkout 内 validation_failed 确实只存在于 packages/core/src/types.ts:793apps/desktop/src/state/executionReducer.ts:279,无发射点;cleanGeneratedCode 的围栏正则无 gpackages/core/src/llm/code-generation.ts:32);checkJavaScriptSyntaxcheckBrackets + checkCommonPatternspackages/hallucination-guard/src/checks/syntax-validity.ts:79,83);formatRunError 子串匹配(packages/runtime-node/src/run.ts:90);子代理 enabled ?? true / isolationMode ?? 'process' / worker JSON.parsepackages/core/src/agent/agent.ts:171,173packages/core/src/sub-agents/code-quality-subagent-worker.ts:61)。

问题发现

  1. [中] §三 把两条 validation_failed 归为 validateBeforeExecution 前置拦截,与 §七 引用的真实错误串不自洽

    • 证据: §三(第 113 行)称事件来自 validateBeforeExecutionapply_patch 前置检查;§七(第 222 行)与 issue #408 则称真实错误是 Cannot apply patch: file not found in context: ...。该字符串在仓库中只有一处产生点:packages/core/src/skills/executor-skills.ts:242,由 prepareToolParams步骤执行期抛出。validateBeforeExecutionapply_patch 分支产生的是另外两种文案(executor.ts:358 的 "file ... does not exist (confirmed by previous directory listing)" 与 executor.ts:394 的 "failed to auto-read file ...")。
    • 受影响调用方/流程: §三的分类表("真·内容拦截 0 / 执行前结构性拦截 2")与第 116 行"按 1a54e25 的新口径这两条仍会上报"。若事件实际来自技能抛错路径,它落入 §一 表中的第 ③ 类(validateAfterExecution 纯工具失败,results: []),新口径下不会上报,结论正好反转,且该行应改写为"纯工具失败 2"。这会直接影响 §六 前置条件 1 的判断。
    • 最小可行修复: 在报告中给出这两条事件的实际 ValidationResulttype + message,或 blockedBy 文本)作为归类依据;若该负载未留存,把 §三 该段降级为"归类无法从已提交数据判定",并相应弱化第 116–118 行。
  2. [中] §六 外推对时间与 token 用了不同因子,输入 token 估算偏低约 30%

    • 证据: 758K/1.33M 恰等于 7 月双臂 27 条合计(输入 682,559、输出 1,198,023,可从仓库内 benchmarks/results/{full,ablation}.jsonl 复算)× 1.11 —— 只乘了一个因子;而 135 min = 7 月单臂 109.5 min × (30/27) × 1.11,乘了两个。另外 1.11 只是 full 臂比值:ablation 同 5 条任务 7 月为 32.3 min、本轮 28.6 min,比值 0.89;同 5 条任务实测 token 比值是输入 1.30 / 输出 1.08,都不是 1.11。口径统一后约为 990K 输入 / 1.43M 输出,双臂耗时也可能低于 4.5 h。
    • 受影响调用方/流程: §六 是"是否值得花这笔钱跑全量"的决策依据。$10 与"数小时"的量级结论不变,但数字目前不可按报告自述的方法复算。
    • 最小可行修复: 第 178 行写清两个因子(27→30 任务缩放 × 每任务实测比值),并对 token 用 token 自己的实测比值、对两臂分别取比值。
  3. [低] §二 的载荷性证据未提交任何可复现物

    • 证据: 第 62–71 行的修复前/后对照被明确称为"本轮最可靠的一组数据",PR 描述也称其"reproducible without LLM spend",但仓库中只有散文描述,没有探针脚本、没有事件转储,2026-07-31-smoke/ 下只有两臂 JSONL。
    • 受影响调用方/流程: 报告的核心结论("零拦截是观测假象")唯一依赖这组数据,后续任何人想复核只能重写探针。
    • 最小可行修复: 把探针脚本(含那段未闭合 { 的固定输入)与两次运行的事件输出一并提交到 benchmarks/results/2026-07-31-smoke/
  4. [低] README.md:1312 仍以未加限定的口径陈述"guard 记录零拦截"

    • 证据: README 顶层指向 benchmarks/results/,并断言 "the hallucination guard recorded zero interceptions";本报告已证明该计数在事件维度不可能非零。
    • 受影响调用方/流程: 读者的第一入口仍是被本报告限定过的旧结论。
    • 最小可行修复: 在该行补一句指向 2026-07-31-validation-telemetry.md 的限定说明(本 PR 内一行改动,或另开 PR)。

行级发现

  • [benchmarks/results/2026-07-31-validation-telemetry.md:113] 归因写的是 validateBeforeExecution 前置检查,但 §七 引用的 Cannot apply patch: file not found in context: 只由 packages/core/src/skills/executor-skills.ts:242 在执行期抛出;请补上这两条事件实际的 ValidationResult.type/message 作为依据,或声明归类不可判定。
  • [benchmarks/results/2026-07-31-validation-telemetry.md:116] "按 1a54e25 的新口径这两条仍会上报"依赖上一条归因;若事件实为工具失败(results: []),新口径下会被丢弃,结论相反,需与归因一并确认。
  • [benchmarks/results/2026-07-31-validation-telemetry.md:178] 该比值只来自 full 臂(ablation 同 5 条任务为 28.6/32.3 ≈ 0.89),且未说明 27→30 的任务数缩放;建议写明两个因子并按臂分别取值。
  • [benchmarks/results/2026-07-31-validation-telemetry.md:184] 758K/1.33M 相当于 7 月双臂 27 条合计只乘了一个因子;按同 5 条任务实测 token 比值(输入 1.30 / 输出 1.08)并叠加 30/27 缩放,应约为 990K 输入 / 1.43M 输出。
  • [benchmarks/results/2026-07-31-validation-telemetry.md:64] 这段确定性探针是全报告的载荷性证据,但仓库内未提交脚本或事件转储,无法复现;建议随 JSONL 一并提交。

Karpathy 评审

  • 假设: 报告把"本轮数字产生于 #402 初版 543b791、口径已被 1a54e25 改变"这一关键假设前置声明了,做得对。未声明的假设是 §六 外推把 full 臂的时间比值当作两臂通用的 token 比值。
  • 简洁性: 结构合理,先限定后数字,未越权给出通过率结论,与 n=5 的证据强度匹配。
  • 结构质量: 纯新增数据资产,无共享路径改动、无抽象引入、无文件膨胀问题。原始 JSONL 与报告同目录并置,可复算路径清晰。
  • 变更范围: 严格是 docs/data,无夹带。仅 README.md 的旧口径未同步(见发现 4),属可另行处理。
  • 验证: 报告内所有聚合数字均可从提交的 JSONL 精确复算,实测已逐项核对通过;不可复算的是 §二探针与 §三 事件归类——恰好是两处结论最重的地方。

缺失覆盖

  • §二 探针的脚本与事件输出(当前完全不可复现)。
  • §三 两条 validation_failed 的原始事件负载(type/message),否则分类表不可校验。
  • §六 外推的分步算式(基数、任务数缩放因子、每指标实测比值),使 758K/1.33M/135 min 可复算。


均出现在 ablation 臂,且该臂 guard 四项检查全关,**因此不可能是内容拦截**。
两条事件都伴随目标文件从未生成(`file_exists` 失败)与
`validateBeforeExecution` 的 `apply_patch` 前置检查失败——即规划把新建文件

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

归因写的是 validateBeforeExecution 前置检查,但 §七 引用的 Cannot apply patch: file not found in context: 只由 packages/core/src/skills/executor-skills.ts:242 在执行期抛出;请补上这两条事件实际的 ValidationResult.type/message 作为依据,或声明归类不可判定。

`validateBeforeExecution` 的 `apply_patch` 前置检查失败——即规划把新建文件
排成了 `apply_patch`,目标文件读不到,执行前被结构性拦下。

按 `1a54e25` 的新口径,这两条**仍会**上报(它们的 `results` 中确有

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"按 1a54e25 的新口径这两条仍会上报"依赖上一条归因;若事件实为工具失败(results: []),新口径下会被丢弃,结论相反,需与归因一并确认。


**未跑**。不是因为额度耗尽,而是耗时超出可完成范围,按纪律不硬跑。

实测外推(基于本轮 smoke 与 7 月同 5 条任务的比值 27.2 / 24.5 ≈ 1.11):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

该比值只来自 full 臂(ablation 同 5 条任务为 28.6/32.3 ≈ 0.89),且未说明 27→30 的任务数缩放;建议写明两个因子并按臂分别取值。

|---|---|
| 单臂 30 条 | ≈ 135 min |
| 双臂 30 条 | **≈ 4.5 小时** |
| token(双臂 30 条) | ≈ 758K 输入 / 1.33M 输出 |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

758K/1.33M 相当于 7 月双臂 27 条合计只乘了一个因子;按同 5 条任务实测 token 比值(输入 1.30 / 输出 1.08)并叠加 30/27 缩放,应约为 990K 输入 / 1.43M 输出。


这是本轮最可靠的一组数据:**零 LLM 消耗、输入完全相同、走真实
`runFrontAgentTask` 路径**(与评测 harness 同一入口、同一事件采集方式)。
用一段确定性坏代码(未闭合 `{`,必然触发 guard 的括号匹配检查):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这段确定性探针是全报告的载荷性证据,但仓库内未提交脚本或事件转储,无法复现;建议随 JSONL 一并提交。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant