# 2026-09-02（a）· 出错的不是判断，是那些一次性脚本

> owner 在本轮收尾时的原话：**「老是出错，在新的 Session 继续」**。
> 他是对的，而且这条反馈值得单独立文档 —— 因为**错的位置高度集中**，不是散落的粗心。

---

## 一 · 七次失误，逐条列出来看它们的共同点

| # | 我写的东西 | 症状 | 真因 | 代价 |
|---|---|---|---|---|
| 1 | `awk '/^```/{f=!f}'` 判某段在不在 fenced block | 四行全 `in_fence=NO` | 围栏**带缩进**，`^```` 匹配不到，状态机从未翻转 | 差点写下「闸的头注释在撒谎」，去**指控一个做对了的东西** |
| 2 | `JSON.stringify(j,null,2)` 回写 divergences | diff 110 行无关改动 | 原文件短数组写单行，序列化把它们展开了 | 险些把格式漂移混进 commit |
| 3 | `node -e '…new RegExp("^\\\\s*"+t)…'` 读 CSS token | **8/8 全 ❌** | shell 单引号里多转义一层 ⇒ 正则里成了「字面反斜杠 + s」 | 假的「值全不相等」 |
| 4 | 同一脚本的段切分 `indexOf('[data-theme="light"]')` | dark 读到 null、light 读到 dark 的值 | 前两次出现**在文件开头的注释里**，真选择器在第 455 行 | 同上，又一轮假 ❌ |
| 5 | `str.replace(anchor, …)` 注入主题切换 JS | CSS/HTML 进去了、JS 没有 | 锚点文本记错（实际是 `]) }).mount(…)`），**replace 静默跳过** | 给 owner 的切换按钮是死的 |
| 6 | 预览页命名 `.r87-preview.html` | 页面渲染出 docs 站首页 | dotfile 被 vite 的 SPA fallback 接管 | 对着**错误的页面**截了图 |
| 7 | 预览页 `background: var(--bg-1)` | light 截图底色仍是深色 | `--bg-1` 这个 token 不存在，走了 fallback | **把一张误导的效果图发给了 owner** |

**共同点一：七次全部发生在「一次性取证 / 编辑脚本」里，零次发生在产品代码里。**
本轮真正交付的 `Button.vue` 改动一次过 —— 类型、三个 fill 的 PALETTE_SPEC、opacity 分支，
全量 3067 passed、九闸全绿、两次故障注入精确命中。**判断力不是问题，工具使用是。**

**共同点二：失败形态是「整齐的假象」，不是报错。**
`8/8 全 ❌` · `四行全 NO` · `全部 null` · HTTP 200 但内容是别的页面 · replace 悄悄什么都没做。
⇒ 没有一次是 stack trace。**它们看起来都像「测量成功了，结论是坏消息」。**

**共同点三：三次（#1 #3 #4）的假结论方向都是「去否定一个其实正确的东西」。**
最贵的是 #1：当时另有三条独立证据都指向「已修」，是那**一个**错读数差点推翻三条对的。

---

## 二 · 可执行的四条（不是「更仔细一点」）

1. **⛔ 一次性脚本不写进 `-e '…'`。** #3 的多转义、#1 的正则，都是 shell 引号层造成的。
   写成 `.mjs` 文件再 `node file.mjs` —— 本轮后半段改用文件后，同类错误归零。
   （本仓 memory `local-env-tool-quirks` 已有「`commit -F` 避 shell 崩」，这是同一条的推广。）

2. **⛔ 任何 `replace` / `splice` / 文本注入必须带断言。** #5 的 `str.replace` 静默跳过是
   Python/JS 共有的坑。写法固定为 `assert anchor in s`（改前）+ `assert 新内容 in s`（改后）。
   同族：#2 的格式漂移应当以 `git diff --numstat` 的**预期行数**作为收尾判据，而不是「看起来对」。

3. **🔴 比对结果「全 ❌ / 全 0 / 全 null」时，先证明量具活着。** 这是本轮最贵的一条。
   判据：**在比对里放一个必然相等的对照行**（例如拿一个已知正确的 token 跟自己比）。
   对照也 ❌ ⇒ 量具坏了；对照 ✅ 而目标 ❌ ⇒ 才是真差异。
   ⚠️ 这是 [[regression-pass-needs-fault-proof]] 的**镜像面**：那条治「全绿可能是空过」，
   这条治「全红可能是量具死了」。两边都需要一个已知结果的锚。

4. **⛔ 给 owner 看的效果图，先自证渲染环境正确。** #6 #7 各错一次，第二次直接把误导图发了出去。
   判据是**机检而非目测**：截图前先读回一个能证明环境对的量（本轮最后用的是
   `body backgroundColor` + `--blue` 的 computed 值，两个主题各一次），读数对了再截。

---

## 三 · 一条不该被这七次盖住的事

owner 的 `Code ⊇ Figma` 裁定本身、以及它当场清空「等 owner 进 Figma」的效果，是本轮的主线产出；
Button blue 是它下面的第一件落地工程，**交付质量没有被上述失误影响**（证据见 §一 共同点一）。
⇒ 记这份复盘不是为了自责，是因为**失误集中在一个可以用规则消掉的面上** —— §二 那四条就是。

⚠️ 也如实记一条**没有被这些失误伤到的判断**：`darkMAxes` / `loadingMembers` 不加 blue
（它们声称的是「Figma 导出了什么」），以及 owner 的**条件同意**必须先核条件再当批准用
（8/8 逐值机检）—— 这两处如果做错，代价比七次脚本失误加起来都大。
