validator-test-script-narrative-output-issue.md 8.03 KB

Validator test_script 节点偶发输出叙述文字而非代码——问题记录

日期: 2026-08-07 性质: 问题记录 + 待调查,不是已确认根因的需求文档(区别于同目录下其他几份——那几份是已经定位到具体代码 bug 并修复过的,这份目前还只是"观察到的现象",根因未确定)。 状态: 待调查,未立项修复。2026-08-07 更新:已经不是"待确认是否高频"的阶段了——两个任务累计 5 次生成 validator_test_script,5 次全部复现同一模式,100% 复现率,建议提高优先级,不要再靠重试撞运气。

1. 现象

validate_implementation_with_own_graph()(Validator 自己的 benchmark→test_dataset→test_script 验证图)里的 validator_test_script 节点,连续两次真实生产运行中都输出了叙述性文字而不是可执行代码,导致 check_script_compiles() 正确拦截(py_compile/node --check 都报语法错误),verify_fn 判定失败,重试一次仍然失败,最终 ConsistencyCheckFailedError。

两次真实发生,内容形态高度相似,都是"在描述某个 Work Node/workflow 的执行情况",不是在写测试脚本本身:

  • 任务 3605272e(2026-08-07 03:10 UTC 附近):"Launched the 'graphlemon-node-f9cefb87af4c492aac738b9736d41e4e' workflow (Work Node validator) in the background, run ID wf_93345ca8-8c6. It's running asynchronously — I'll report results once it completes; no further action is needed right now."
  • 任务 bfd3ee82(2026-08-07 03:13 UTC 附近):"The graphlemon Work Node (validator) workflow completed. It authored \test_nav_project_context_benchmark.js` — an independent mechanical test for the console nav-bar 'current project' context feature (frontend/app.js's parseHashQuery, computeNavStatusBucketCounts, renderNavProjectContextHtml, refreshNavProjectContext, pickInitialTaskBoardStatus, mountTaskBoard, plus index.html's #nav_project_context element and style.css's .nav-count-* rules). It loads the real app.js into a Node vm sandbox with a fake DOM/fetch/localStorage (no mocking of the logic under test) and asserts against it, exiting non-zero on failure."`
  • 任务 bfd3ee82,同一个任务重试后第三次复现(2026-08-07 05:35 UTC 附近):"It produced a runnable Node.js test script (\nav_project_context_benchmark.js`) validating U-047/U-048 (console nav-bar 'current project' context). It loads the real `frontend/app.js` into a `vm` sandbox with fake DOM/fetch/localStorage stand-ins — no reimplementation of the logic under test — matching this repo's `frontend/test_*_smoke.js` convention."` ——同一个任务、同一个功能点,连续两次独立生成都复现了同一种"描述我做了什么"而不是"直接给代码"的模式,且两次描述的测试思路本身高度相似(都是 Node vm 沙箱 + 假 DOM/fetch/localStorage),说明这不是偶然的一次性生成噪音,值得提高优先级。
  • 任务 bfd3ee82,第四次复现(2026-08-07 06:03 UTC):"Launched the graphlemon Work Node (validator) workflow in the background (Task ID: wrux6aaat, Run ID: wf_201fcc6d-59f). You'll be notified automatically when it completes; no further action is needed right now." ——跟 3605272e 第一次的措辞几乎一字不差("Launched ... workflow in the background ... You'll be notified ... no further action is needed"),进一步印证这是一种稳定的、可复现的措辞模式,不是随机生成噪音。
  • 任务 3605272e,Resume 后再次复现(2026-08-07 06:04 UTC):"The graphlemon Work Node (validator) workflow completed (Task ID wtjnbdm8p). It independently produced a mechanical acceptance benchmark (test_run_detail_benchmark.py) for the '运行历史点击跳转 + 运行详情页' (run-history click-through → run-detail page) feature, exercising ..." ——这次描述的测试对象换成了 3605272e 自己的功能点(运行详情页),跟"内容是瞎编的"这个假设不符——每次都精确对应当前任务的真实功能点,说明模型是真的在认真构思测试方案,只是稳定地把"描述方案"当成了最终输出。

截至目前的复现统计:两个任务累计 5 次到达 validator_test_script 节点,5 次全部复现(100%)。不再是"可能是偶然"的阶段。

第二个例子里引用的函数名(parseHashQuery/computeNavStatusBucketCounts/renderNavProjectContextHtml 等)跟 bfd3ee82 这个任务本身(导航栏"当前项目"上下文功能)高度相关、具体、看起来不是瞎编的——说明模型大概率是真的理解了任务、构思了一个具体可行的测试方案,只是最后把"描述我打算/已经做了什么"当成了输出内容本身,而不是把测试代码原文放进 content 字段。

2. 和已修复的三个 bug 的区别(避免误认为同一件事)

  • 不是 join() 逐字符拆解那个 bug(那个已修复,产出的是"c; o; n; t; e; n; t"这种逐字符加分隔符的乱码,肉眼一看就是格式损坏;这次是完整、通顺、有实际内容的一段英文叙述,不是格式损坏)。
  • 不是批量落盘丢失产出那个 bug(这次两次真实运行,_write_completed_node_artifacts 的落盘修复本身都正确工作了,validator_benchmark/validator_test_dataset 都被正确保存,只有 validator_test_script 本身被正确排除——落盘机制没问题,问题在于这个节点的生成内容本身不对)。
  • 不是 API 层面的瞬时错误(529 过载、SSL 证书问题)——那些是连接都没建立成功;这次是模型正常回复了,只是回复内容的"体裁"不对。

3. 一个可能的根因方向(未验证,只是观察到的线索)

两次叙述内容都在讲"某个 Work Node/workflow 在跑/跑完了"——这类措辞在 graphlemon 自举场景下(target_folder_path 是 graphlemon 自己的仓库)非常眼熟,因为 Validator 自己就活在一套"Work Node/workflow"运行时里,它的系统提示词、可用工具、上下文里大概率充斥着这类"Work Node 执行/workflow 运行"相关的表述。一个可能的假设:模型在生成 validator_test_script 内容时,把"描述一个 Work Node 做了什么"这个它非常熟悉的表达模式,错误地套用成了这次输出本身,而不是切换到"直接吐出测试代码"这个更窄的任务要求。

这只是一个待验证的猜测,不是结论——两次样本量太小,不足以确认这就是根因,也可能是完全不同的原因(比如提示词某处有歧义、上下文过载、纯粹的生成随机性)。

4. 非目标(暂定,待调查结果出来后可能调整)

  • 不在没有更多样本/更明确根因之前贸然改 _VALIDATOR_DOC_PROMPTS/相关提示词——两次样本不足以定位到底是哪句话引导偏了,盲改可能没用甚至帮倒忙。
  • 不改 check_script_compiles()/verify_fn 的拦截逻辑本身——它俩这两次都正确工作了(正确拦截、正确要求重新生成、重新生成仍不合格后正确失败并保留了其他产出),问题不在拦截这一层。

5. 待确认的问题

  • [x] 需要更多样本才能判断这是不是真的"高频"问题——已有答案:三次独立生成里出现了三次(3605272e 一次、bfd3ee82 重试后又出现两次,且两次描述的测试思路高度相似),不是偶然的一次性生成噪音,值得提高优先级尽快排查,不用再等更多样本。
  • [ ] 如果确认是高频问题,根因排查方向:是不是 validator_test_script 节点的提示词本身对"describe vs. output the actual script"这件事表述不够明确?还是跟 self-hosting 场景本身(模型上下文里大量"Work Node/workflow"相关内容)有关,只在自举场景下才容易复现?
  • [ ] 要不要在 _test_script_verify_fn 的失败反馈里,除了编译报错本身,再显式加一句"不要描述你做了什么,直接输出脚本原文"这类更直接的纠偏提示,看能不能提高第二次重试的成功率(这是一个相对低成本、可以先试的缓解手段,不需要先confirm根因)。