Commit 3d5db4b1abe98deeb65eb7cdc0d92cd09adb52e7

Authored by yibo
1 parent 70b4a112

docs(34/32): 查清 coder-validator 有没有真的做浏览器级检查——没有工具,但有真实静态脚本兜底

34 号文档追加调查(§五):
- coder-validator(预置 active 本体)的 agent.md 通篇是代码/契约正确性验证协议
  (npx vitest run + 抓假绿五件套),压根不涉及视觉/交互检查;这次任务新招的
  coder/unit-tester 两个本体 toolPolicy 都只有 bash/read_file/str_replace,
  没有浏览器/截图工具——goal-benchmark.json 的 evidence_hint 要求"打开浏览器",
  在给定工具权限下物理上做不到,不是 agent 偷懒。
- 但也不是纯粹空手套白狼:data/companies/e2e-demo/projects/p-v82tpc/tests/
  unit-tester.check.js 是一份真实可运行的零依赖静态断言脚本,对维度 1-3 的检查
  (字号比例真解析 CSS clamp() 算出数字、三个卖点区块标题顺序、锚点跳转/平滑滚动)
  与浏览器版本基本等价甚至更精确;维度 4/5(响应式断点、资源完整性)的静态版本
  明显更弱,会放过断点内样式写错、本地资源路径错误这类情况。

顺带发现:这份脚本很可能是 unit-tester 在提示词完全没有测试方法论指导的情况下
自己想出来的——它的 agent.md 还是没填充过的 _base 原始骨架(隔壁 coder 正常填充
过),是 32 号文档"招聘装配没填充完"那类问题的又一个真实样本(发生在方案 B
修复提交 6a18379 落地前 1 小时,是旧行为的证据,不是新机制的回归;新机制下
会不会正常完成,仍未验证)。32 号文档 §四追加第 6 条记录这次样本。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
docs/README.md
... ... @@ -49,7 +49,7 @@ Graph Agent 架构重构(27 系列)。**已完成的阶段文档已移入 `d
49 49 | [29-dream-design.md](./todo/system-design/29-dream-design.md) | **dream(经验汇流)**— ✅ 已实现。定时整理所有 agent 在所有公司的记忆,提炼后跨公司沉淀(不泄漏公司信息)。四条取舍已拍板并实现:去敏独立判定、四落点分层写入(经验/`SKILL.md`/`soul.md`/`agent.md`,受管区块+三道闸门)、每日定时(串行+空转保护)、引用真伪自动查、REST+控制台入口(`/api/dream/*`、`/dream`)。`innovator-evolver` 真 CLI 跑通一次。**仍缺的**:「结论对不对」只能人抽查;「套进 org/work graph 来跑」评估后用户选了不做(作用域不匹配,见文内 §5.7) |
50 50 | [30-task-delegation-reliability-gaps.md](./todo/system-design/30-task-delegation-reliability-gaps.md) | **任务委派可靠性现状**— 📝 调研记录,非设计方案。DevLoop `runUnit`、Company 招聘装配、Graph 执行三条链路核对结论一致:都是「失败预算耗尽 → 停等人工」,没有「卡住了主动通知人」这一层;DevLoop 当前还默认走 mock,真实 CLI 成功率无实证数据 |
51 51 | [31-work-graph-fail-fallback-coverage.md](./todo/system-design/31-work-graph-fail-fallback-coverage.md) | work graph 兜底边覆盖不全 — ✅ 已完成(除入口节点外强制兜底边,`planner.json`/`executor-fanout.json` 补 6 条边),978/978 单测通过;2026-08-21 又用真实 LLM 起了一条新任务做端到端回归验证,`org-planner-sdd` 自判失败后自动打回 `org-planner-prd`(3 次,零人工介入),修复确认生效 |
52   -| [34-validator-scored-without-real-deliverable.md](./todo/system-design/34-validator-scored-without-real-deliverable.md) | 📝 **调研记录,原始前提已订正**。最初以为 `org-coder-impl` 从未产出任何 HTML/CSS(`org-coder-validator` 却给六维度全打 100 分),后来发现真实网站其实存在于 `graph_files` 索引不覆盖的「项目根」目录(`data/companies/{cid}/projects/{pid}/`)——这半个发现已经顺手修了(控制台「产物」面板现在会展示项目根)。订正后仍未解决的窄问题:validator 有没有真的照 `evidence_hint` 做浏览器级检查,还是即使产物存在也没真查 |
  52 +| [34-validator-scored-without-real-deliverable.md](./todo/system-design/34-validator-scored-without-real-deliverable.md) | 📝 **调研记录,原始前提已订正**。最初以为 `org-coder-impl` 从未产出任何 HTML/CSS,后来发现真实网站其实存在于 `graph_files` 索引不覆盖的「项目根」目录(已顺手修:控制台「产物」面板现在会展示项目根)。追加查了 validator 有没有真的做浏览器级检查——**没有工具,物理上做不到**,但有一份真实的静态断言脚本代替了 5/6 维度的检查,不是空手套白狼;顺带在新招聘的 `unit-tester` 本体上又撞见一次 [32 号文档](./todo/system-design/32-hire-body-fill-reliability.md) 那类装配未完成的真实样本 |
53 53 | [33-needs-gate-role-filter-bug.md](./todo/system-design/33-needs-gate-role-filter-bug.md) | ✅ **已修复**。`executor.json`/`executor-fanout.json` 里 `produces:["log"]` 声明了一个 test/integration 类节点永远不会被索引到的 kind,导致 `org-coder-validator` 被 `missing_required_input` 反复误判 blocked;改成 `required:false`(对齐 `validator.json` 既有写法)。文档记录了一条**走过的弯路**(按 role 过滤 `inboundContracts` 会削弱 T-mt25ecbd 的产出闸门,已撤回),发现于 31 号文档的真实回归验证过程中,与兜底边问题无关 |
54 54  
55 55 ## todo/future/(暂缓,非当前重心)
... ...
docs/todo/system-design/32-hire-body-fill-reliability.md
... ... @@ -181,6 +181,14 @@ if (existing?.protocol?.isConnected) {
181 181 触发 Innovator 训练)现在拿到的是"第 1 步真的跑完了"的保证,不再是"假设 5 秒内跑完"。
182 182 那个 `setTimeout(5000)` 因此变成了多余的额外延迟(无害,只是白等 5 秒),**没有顺手删掉**——
183 183 不在这次修复评估的范围内,属于"看到了但刻意不处理",留给以后要动第 3 步时再一起看。
  184 +6. **新增:真实撞见的一次样本,时间点在方案 B 修复之前**——`e2e-demo` 公司 2026-08-21
  185 + 17:54 同一分钟内招聘了 `coder`/`unit-tester` 两个本体(真实回归任务 `T-mt2r6fz0-125b`
  186 + 触发,见 [34 号文档](./34-validator-scored-without-real-deliverable.md) §五.2),
  187 + `coder/agent.md` 正常填充过,`unit-tester/agent.md` 却仍是原始 `_base` 骨架
  188 + (带 `LEMONBOSS_BASE_SKELETON` 标记)——本文档描述的正是这一类"装配没做完"的现象。
  189 + 本次修复提交 `6a18379` 是同一天 **18:49** 才落地的,晚于这次招聘,所以这次撞见的是
  190 + **修复前的旧行为**,不代表方案 B 上线后仍有这个缺口——但也没有专门再跑一次去验证
  191 + 新机制下这一步会不会正常完成,这条验证仍然缺失。
184 192  
185 193 ---
186 194  
... ...
docs/todo/system-design/34-validator-scored-without-real-deliverable.md
1 1 # 34-validator-scored-without-real-deliverable. coder-validator 在没有真实产物的情况下给了满分
2 2  
3 3 > **日期**: 2026-08-22
4   -> **状态**: 📝 **调研记录,非设计方案,且 §一/§二的核心前提已被 §零 推翻大半**——
  4 +> **状态**: 📝 **调研记录,非设计方案**。§一/§二的核心前提已被 §零 推翻大半——
5 5 > 原始判断("index.html 从未被写出来")是错的,真实网站文件其实存在,只是不在
6   -> `graph_files` 索引里。修订后的问题更窄:validator 有没有**真的**照 `evidence_hint`
7   -> 做浏览器级检查,还是即使产物存在也照样走了个形式。这一层仍未核实,留待下次。
  6 +> `graph_files` 索引里。§五 追加查过"validator 有没有真的做浏览器级检查":
  7 +> **没有浏览器工具,物理上做不到**,但确实有一份真实可运行的静态断言脚本代替了
  8 +> 5/6 维度的检查(不是空手套白狼),且顺带在 `unit-tester` 本体身上又撞见一次
  9 +> [32 号文档](./32-hire-body-fill-reliability.md)那类"招聘装配没填充完"的真实样本。
  10 +> 剩下没做的:抽查这套"用静态脚本代替浏览器"是不是稳定行为,见 §四剩余 checklist。
8 11 > **触发**: `e2e-demo` 公司真实回归任务 `T-mt2r6fz0-125b`(goal `G-mt2r62ia-73af`,
9 12 > root run `run_0e9074815130`)——[31 号文档](./31-work-graph-fail-fallback-coverage.md)
10 13 > 兜底边修复 + [33 号文档](./33-needs-gate-role-filter-bug.md) 契约修复之后,把这条任务
... ... @@ -117,16 +120,89 @@ contract.json 跨节点契约快照
117 120  
118 121 ## 四、留待下次调查的问题(不在本次范围内动手)
119 122  
120   -- [ ] `coder-validator` 本体(`system/agents/unit-tester/agent.md` 或对应角色)的
121   - 提示词里,评分前有没有一步强制要求"回填 evidence_hint 点名要量的具体数字",
122   - 而不是只回一个分数?没有这一步的话,"真查过"与"没查"从产出上完全无法区分。
123   -- [ ] `coder-validator` 是否有可用的浏览器工具(截图、DOM 检查)去真的执行
124   - `evidence_hint` 里描述的那些检查?如果连工具都没有,让它对着"评分要求打开浏览器"
125   - 的 rubric 打分,本身就是设计上要求了它做不到的事。
  123 +- [x] `coder-validator` 是否有可用的浏览器工具(截图、DOM 检查)去真的执行
  124 + `evidence_hint` 里描述的那些检查?**没有**——见 §五.1,`config.json` 的
  125 + `toolPolicy.allowedTools` 只有 `bash`/`read_file`/`str_replace`,物理上做不到
  126 + "打开浏览器"。
  127 +- [x] `coder-validator` 本体的提示词里,评分前有没有一步强制要求"回填
  128 + evidence_hint 点名要量的具体数字"?**有替代方案,但不是这个形态**——见 §五.2,
  129 + 实际靠的是一份零依赖的静态断言脚本(`unit-tester.check.js`),不是"回填数字",
  130 + 是"跑一个真脚本、贴真实输出",与 `coder-validator/agent.md` Step 2 的既有要求
  131 + ("没跑过的测试等于不存在")同一个纪律,只是换了检查对象。
126 132 - [ ] 抽查其他任务(比如 `p-bkhylu`/`p-v1mpcl` 这两个已存在的项目根)的 validator
127   - 评分记录,看这次的六个满分是个例还是常态。
  133 + 评分记录,看这次"用静态脚本代替浏览器检查"是这条任务的一次性即兴发挥,
  134 + 还是已经是这类骨架的稳定行为——仍未做,见 §五.2 末尾。
128 135 - [ ] 是否需要给"必须打开真实产物检查"的维度加一道**引擎级的前置闸门**:至少确保
129 136 被检查的文件(如 `index.html`)在 `evidence_hint` 点名的路径下真实存在
130   - (现在项目根已经可查,这道闸门补起来比 §零 之前容易),如果连文件都不存在
131   - 就直接拦下不许打分;文件存在之后 validator 有没有真的看,还是只能靠 §四第
132   - 一条的"强制回填具体数字"来间接约束。
  137 + (现在项目根已经可查,这道闸门补起来比 §零 之前容易)。§五.2 的静态脚本已经
  138 + 部分覆盖了这个诉求(1-5 维),但它是 agent **自己想出来**写的,不是引擎强制的——
  139 + 换一次任务、换一个 agent 会话,不保证还会有人主动写这份脚本。
  140 +
  141 +## 五、2026-08-22 追加调查:`coder-validator` 到底有没有真的检查
  142 +
  143 +### 5.1 工具权限:没有浏览器,物理上做不到
  144 +
  145 +`org-coder-validator` 这次跑的本体是 `coder-validator`(预置的 active 本体,非本次
  146 +新招聘)。它的 `agent.md`(10KB,读了全文)通篇讲的是**代码/契约正确性验证**——
  147 +`npx vitest run`、抓"假绿"五件套(空断言/`.skip`/只测 happy path/mock 掉被测对象/
  148 +覆盖率灌水)、逐条核对 `acceptance_criteria`、`fail_reason` 只在
  149 +`impl_bug`/`input_underspecified`/`infra_flake`/`null` 四个取值里选——**整份提示词
  150 +没有一个字提到截图、视口、Console/Network 面板、字号比例这类视觉/交互检查**。
  151 +它的输出格式(`verdict`/`test_run`/`checks`/`fail_reason`/`remediation_note`)也完全
  152 +不是 `attempt-1.scores.json` 那种六维度打分形态(那份分数文件的形态更接近
  153 +`goal-benchmark.json` 的 rubric 结构,猜测是 `goal-contract.js run` 那条工具链算出来
  154 +落盘的,不是 `coder-validator` 手写)。
  155 +
  156 +而这次任务给 `org-coder` 这条支线新招的两个本体(`coder`、`unit-tester`)的
  157 +`config.json` 都是同一句:
  158 +
  159 +```json
  160 +"cli": { "toolPolicy": { "mode": "restricted", "allowedTools": ["bash", "read_file", "str_replace"] } }
  161 +```
  162 +
  163 +**没有浏览器/截图/DOM 检查工具**。`goal-benchmark.json` 的 `evidence_hint` 要求
  164 +"打开 `index.html`"、"开发者工具 Console + Network 面板"、"依次设置视口宽度"——
  165 +在这三个工具的权限范围内,一件都做不到。这不是 agent 偷懒,是**设计上给它的
  166 +rubric 与给它的工具完全对不上**。
  167 +
  168 +### 5.2 但也不是纯粹的空手套:真有一份可运行的静态断言脚本
  169 +
  170 +`data/companies/e2e-demo/projects/p-v82tpc/tests/unit-tester.check.js`——零依赖
  171 +Node 脚本,读 `index.html`/`styles.css`/`script.js` 三个真实文件做静态解析,
  172 +不是猜的,逐条对上 `goal-benchmark.json` 维度 1-5:
  173 +
  174 +- **hero_first_impression**:真解析 CSS 里 `.hero-title`/`.hero-tagline` 的
  175 + `clamp()` 表达式,换算出**真实的字号比例数字**去比 ≥3:1(不是"看起来大概行");
  176 + 另外查 `.hero-visual` 的 `width` 声明是否 ≥90vw。
  177 +- **pitch_sections_completeness**:正则抓三个 `<section class="pitch...">`,
  178 + 核对**数量、顺序、标题原文**("多智能体协作→全链路自动化→Skill 竞技场")
  179 + 与每个区块是否同时有 `<h2>`+`<p>`+`.pitch-visual` 三要素。
  180 +- **smooth_nav_no_anchor_jump**:断言全文没有 `<a href="#...">`,script.js 里没有
  181 + `location.hash =` 赋值、且确实调用了 `scrollIntoView({behavior:'smooth'})`——
  182 + 这组断言的判据与"点击导航不出现 # 片段、且平滑滚动"逐句对应,只是用静态代码
  183 + 特征代替了真的在浏览器里点一下、看地址栏。
  184 + - **`responsive_layout`**:只断言 CSS 里存在 `1024px`/`480px` 两个媒体查询断点,
  185 + **没有验证断点内的样式是否真的消除了横向滚动/重叠**——这条断言比前三条弱,
  186 + 是"有没有做响应式的动作"而不是"响应式做得对不对"。
  187 + - **`resource_integrity`**:断言三个文件里没有外部 URL 引用、有 `<link rel="icon">`
  188 + 声明——覆盖的是"会不会因为外链或缺 favicon 产生 404"这一类,**没有校验本地
  189 + 引用的资源文件是否真实存在**(比如声明了本地图片但文件不存在,这条断言抓不住)。
  190 +
  191 +**结论**:六维度里 5 项确实有真实、可复现的检查支撑,只是形态是"静态断言脚本
  192 ++ 真跑输出",不是 rubric 字面写的"打开浏览器"——两者在**这次任务的具体验收点**上
  193 +基本等价(尤其是前 3 项,静态解析拿到的是比"人肉截图目测"更精确的数字),
  194 +但 `responsive_layout`/`resource_integrity` 两项的静态版本明显弱于浏览器版本,
  195 +真有边界情况(断点内样式写错、本地资源路径错误)会被这份脚本放过。
  196 +
  197 +**这份脚本是谁写的、写它是不是稳定行为,没有查**:`unit-tester` 这个本体
  198 +(写测试的那个角色)的 `agent.md` **是没填充过的 `_base` 原始骨架**(开头带
  199 +`<!-- LEMONBOSS_BASE_SKELETON -->` 标记,见招聘装配可靠性那条——
  200 +[32 号文档](./32-hire-body-fill-reliability.md)),完全没有任何关于"该怎么测试
  201 +这类视觉需求"的角色指导;隔壁 `coder`(实现角色)的 `agent.md` 却正常填充过。
  202 +两个本体在同一次任务里、几乎同一分钟(17:54)被雇进来,一个填了一个没填——
  203 +是 [32 号文档](./32-hire-body-fill-reliability.md) 那次异步装配可靠性问题的又一个
  204 +真实样本(发生在 17:54,32 号文档的修复提交 `6a18379` 在同一天 18:49 才落地,
  205 +所以这次踩到的是修复前的旧行为,不代表新机制仍有这个缺口,但没有再跑一次
  206 +验证新机制)。也就是说,这份相当机灵的静态断言脚本,很可能是 `unit-tester`
  207 +**在没有任何角色指导的情况下、纯靠通用 four-phase 骨架的常识自己想出来的**——
  208 +换一次任务、换一次会话,不保证还会有 agent 主动想到用这种方式弥补工具缺口。
... ...