Skip to content

Commit b9f8077

Browse files
os-zhuangclaude
andauthored
docs(skills): state the ablation-on-dist hazard as a resolution property (#9509)
The dev-agent definition and the dogfood skill both scoped the "rebuild before you believe an ablation" rule to `packages/qa/dogfood`. The condition is not the suite, it is the resolution path: any test whose subject resolves through the dependency's `exports` (which point at that package's built `dist/`, not `src/`) with no vitest alias redirecting the specifier back to source. That set is already enumerated as `KNOWN_UNALIASED_TEST_IMPORTS` in `scripts/check-test-source-alias.mjs`, and dogfood is one instance of it rather than the definition. Read narrowly, an ablation run in a plain unit suite gets trusted when it proves nothing. Two measured pairs are carried as the shortest possible provenance: `plugin-email` to `platform-objects` (375 passes on an ablated field, 4 red once the dep was rebuilt) and `plugin-auth` to `core`, whose legs existed to prove a new gate can fail. The second shape is why both copies now name it: an un-rebuilt ablation there returns "the gate did not fire", which reads as evidence the gate is broken rather than the harness, and the expensive outcome is weakening a working gate until it fires. Both halves of the mechanical rule are now explicit in both files -- the mutate leg and the restore leg each rebuild and each prove the artifact. The restore half is the one that gets skipped, and a marker left in `dist/` keeps mutated code live for every later run in that worktree. The authority for this framing is the preflight script's own header, which already carries it; these two files were the lagging copies. The script is deliberately untouched here. Claude-Session: https://claude.ai/code/session_01Rn7aaamsR99FXRqLcpL99q Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5909307 commit b9f8077

2 files changed

Lines changed: 31 additions & 17 deletions

File tree

‎.claude/agents/os-dev.md‎

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,21 @@ dispatch prompt 只携带每单增量(裁决引文、裁决 / PM-机制假设分
190190
(删掉一个喂计数的读取,能让下游门禁*多出*一个发现);反转(canonical-first 的 `??`
191191
链:非法拼写落到 schema 的具名拒收 —— 规则绿、schema 红)。报告你实际观察到的方向;永
192192
不硬套模板的预设。
193-
- **dogfood ablation 跑在 `dist/` 上,所以要重建被 ablate 的包 —— 并在报告里说明你建
194-
了。** `packages/qa/dogfood` 刻意从各包**构建产物 `dist/`** 解析被测代码,且两个方向
195-
不对称:没 build 的修复是会被注意到的假红,没 build 的 **ablation** 跑的是变异前的构
196-
建、保持**绿** —— 给一条可能永远失败不了的断言背书,对 CI 永久隐形。每一腿都是:变异
197-
→ `pnpm --filter <pkg> build` → **证明变异到达了产物** → 运行:
198-
`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'`,ablation 删守卫时用
199-
`--absent` —— 它同时是恢复腿,因为留在 `dist/` 里的 marker 会让变异代码在之后每次运行
200-
里继续生效。
193+
- **ablation 的成立条件是解析路径,不是套件名 —— 变异腿与还原腿都要重建,并在报告里说
194+
明你建了。** 条件:**被测主体经依赖的 `exports` 解析**(那指向该包的 `dist/`,不是
195+
`src/`),且没有 vitest alias 把 specifier 拉回源码;这批 pair 有实测台账 ——
196+
`scripts/check-test-source-alias.mjs` 的 `KNOWN_UNALIASED_TEST_IMPORTS`。
197+
`packages/qa/dogfood` 是最眼熟的一例,不是定义:读成 dogfood 专属,普通单元套件里的
198+
ablation 就会被当真(实测:plugin-email → platform-objects 消融后 375 试全绿,重建后
199+
4 红;plugin-auth → core 那组「证明新门禁能红」的腿跑的是变异前产物)。两个方向不对
200+
称:没 build 的修复是会被注意到的假红;没 build 的 **ablation** 保持**绿**,给一条可
201+
能永远失败不了的断言背书,对 CI 永久隐形(CI 构建正确,那边永远绿)。⚠️ 消融本就为证
202+
明**新门禁能失败**时,这份假绿不是空结果 —— 它读作「门禁没触发」,指向门禁坏了而不是
203+
夹具坏了,于是有人去弱化一条本来正常的门禁。所以每一腿(变异**与**还原)都是:改动 →
204+
`pnpm --filter <pkg> build` → **证明它到达了 `dist/`** → 才读运行结果:
205+
`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'`(删守卫的消融、以及每个
206+
**还原腿**,用 `--absent`)。⛔ 还原腿最常被跳过 —— 留在 `dist/` 里的 marker 会让变异
207+
代码对该树之后的每次运行继续生效,后面的测量量的是错的树。
201208

202209
## Definition of done(按序)
203210

‎.claude/skills/dogfood-verification/SKILL.md‎

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,22 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
6363
watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。
6464
- [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter <pkg...> build` →
6565
`preview_stop` + `preview_start`。不要每修一处就编辑→构建→重启一遍。
66-
- [ ] ⚠️ **消融验证(predict-then-mutate)以最危险的方式继承这一条 —— mutate 与运行
67-
之间要重建,并在报告里写明重建过。** 忘记重建*修复*是假红:费一圈,但会被发
68-
现。忘记重建**消融**跑的是突变前的构建,套件保持**绿**,而这份绿会被记成「测试
69-
已被证明有区分度」—— 给一条可能根本红不了的断言发了证书,之后任何 CI 都暴露不
70-
了它(CI 构建正确,在那边永远绿)。每一腿都是 mutate →
71-
`pnpm --filter <pkg> build` → **证明突变已到达 `dist/`** → 运行:
72-
`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费的
73-
`dist/` 真带着突变时才退 0(消融删除守卫时用 `--absent`;restore 腿也要跑它 ——
74-
留在 `dist/` 里的 marker 会让突变代码对该树之后的每次运行保持生效)。
66+
- [ ] ⚠️ **消融验证(predict-then-mutate)以最危险的方式继承这一条,而且它不是 dogfood
67+
专属 —— mutate 腿与 restore 腿各自都要重建,并在报告里写明重建过。** 判据是解析
68+
路径:任何主体经依赖的 `exports` 解析(→ 该包的 `dist/`,且没有 vitest alias
69+
把 specifier 拉回源码)的测试都中招,普通单元套件一样(这批 pair 的台账是
70+
`scripts/check-test-source-alias.mjs` 的 `KNOWN_UNALIASED_TEST_IMPORTS`)。忘记重
71+
建*修复*是假红:费一圈,但会被发现。忘记重建**消融**跑的是突变前的构建,套件保持
72+
**绿**,而这份绿会被记成「测试已被证明有区分度」—— 给一条可能根本红不了的断言发了
73+
证书,之后任何 CI 都暴露不了它(CI 构建正确,在那边永远绿);消融本就为证明**新门
74+
禁能失败**时更毒 —— 那份绿读作「门禁没触发」,指向门禁坏了而不是夹具坏了,会诱人
75+
去弱化一条本来正常的门禁(实测:plugin-auth → core;plugin-email →
76+
platform-objects 则是消融后 375 试假绿、重建后 4 红)。每一腿(mutate **与**
77+
restore)都是:改动 → `pnpm --filter <pkg> build` → **证明它到达了 `dist/`** → 才
78+
读运行结果:`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费
79+
的 `dist/` 真带着该状态时才退 0(消融删除守卫、以及每个 restore 腿,用
80+
`--absent`)。⛔ restore 腿最常被跳过 —— 留在 `dist/` 里的 marker 会让突变代码对该
81+
树之后的每次运行保持生效,后面的测量量的是错的树。
7582
- [ ] `dist/` 已 gitignore —— 安全;永不提交构建产物。
7683
- [ ] **`/_console` UI 是 *vendored objectui 构建*,与框架 `dist` 是两回事。** 它由
7784
`.objectui-sha` 钉住、按预构建 bundle 提供。已合并的 objectui 修复 —— *甚至

0 commit comments

Comments
 (0)