# Audit Iteration Ledger — finding count 趋势

> 用途：每次 Codex 跑完一波改动 / audit 升级后，plan owner 在这里追加一行，方便用户**实时对比**修复方向是否真的在减问题，还是在制造新问题。
>
> 规则：
> - 一行一次实测，按时间倒序排（最新在上）
> - 数字来自 `figma-data/normalized/component-attributes.audit.json` + a11y inspector JSON
> - **Δ vs prev** 列：负数（绿色）= 减少；正数（红色）= 增加；0 = 不变
> - 任何"修了反而涨"的趋势立刻 STOP 并复盘，不要继续下一波

---

## 主表 — component-attributes audit

| # | When | Iteration | Total findings | Non-allowlisted | color-token-mismatch total | non-equivalent | theme-asym | name-drift | size-drift | padding-drift | gap | opacity | size-mode | color-missing | Δ non-allow vs prev |
|---|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| 20 | 2026-05-28 | **P16 padding cluster 一轮收口 ✅ executed (Discovery + Apply + Apply-fix) + AGENTS.md task-type 矩阵 codify** — 1 fix commit `eb0df4bb` 含 3 协作 sub-fix + 1 meta-rule codify。**(0) P16 Discovery** (`p16-padding-cluster-discovery.{prompt,report}.md`) — Codex grep 实证 196 rootPadding field FAIL / 48 cluster / 三类形态：(a1) Input text-count XL bottom 40 fields / 12 clusters · (a2) Select multi-select vertical 84 fields / 24 clusters · (b) Input feature=yes overlay horizontal 72 fields / 12 clusters。Plan owner 凭记忆喂的 "~48" 是 cluster count 被 Codex 抓出歧义。**(1) P16a Apply** — `SelectBoxBase.vue` `.select-wrap--multiple .select-trigger { padding-block: var(--sp-xxs) }` (84 fields) + `InputBoxBase.vue` template `input-wrap--text-count` 类 + `:deep(textarea.tvu-input--xl) { padding-bottom: var(--sp-l) }` (40 fields)。Codex 严格 Apply 协议 — target cluster 清零，§3.3 dump 偏差不自修。**(2) P16a regression 发现 + P16a-fix narrow exclusion** — P16a 引入 12 新 fail：SelectBoxFilled × dark theme=on × size=L × multi-select pV=8/pB=8 (其他 7/8 个 (theme,size,family) 组合统一 4/4)。Plan owner 独立 grep `figma-data/normalized/components-tokenized/` verify 是 Figma asymmetric outlier 不是 P16a spec 错。`SelectBoxBase.vue` 加 `.select-wrap--filled.select-wrap--multiple.select-wrap--l[data-figma-dark-theme='on'] .select-trigger { padding-block: var(--sp-xs) }` (specificity 0,5,1 vs 0,2,1 高三级) 1:1 还原 Figma 真源。同时 file BRIDGE-DESIGN-REVIEW backlog 追加 ask 设计师 confirm intent。**(3) AGENTS.md §Task-type 分工矩阵 codify** — 6 行矩阵 (Discovery / Apply / Design / Refactor / Infrastructure / Audit) + 跨 task-type 4 条不变约束 (executor 永不 commit / plan owner 必独立 verify / 不动 source code / §Mode 必明示)；实证 P15.1 / P15.2 / P15.2-extend / P16 discovery 4 次实跑驱动；executor + plan owner 角色行为约束同步加 §Mode confirm + Discovery 不写死数字 + Apply 必写死 spec + 审报告必独立 verify。**总 cleanup** vs P15.2 baseline: Entry PASS 232→**251** (+19) / SKIP 207→**270** (+63) / FAIL 196→**114** (-82); field A 241→**116** (-125 真清，**68% cleared** vs c7aaa8a5 baseline A=398); B 10 不变。Guards 全保留。剩余 116 A: rootPadding.left/right 72 (P16b verifier topology) + DropDownListSelect 31 (调研) + 散落 textFillHex 12 (新 cluster) + 10 真 B residual。Commit eb0df4bb (Owner direct master per [[feedback_owner-direct-master-ok]])。**原则记忆**：(i) Discovery / Apply 分工差异：Codex 跑 discovery 时给规则不给数字 = 抓 plan owner 凭记忆错；Codex 跑 apply 时给死 spec = 5min 干净；(ii) Figma asymmetric outlier 必 1:1 还原 code（FIGMA_AS_SOURCE_OF_TRUTH）+ 同时 file BRIDGE-DESIGN-REVIEW 不互斥；(iii) commit 边界跟 session 边界对齐 — 不主动消化并行 session dirty (backlog.md BRIDGE-MOCKUP-008 entry 留并行 session 一起 commit). | — | — | — | — | — | — | — | — | — | — | — | — | manifest path A |
| 19 | 2026-05-27 | **P15.2 + P15.2-extend ✅ executed (B1 semantic tokens + ::placeholder pseudo verifier)** — 1 fix commit 含 2 协作 sub-fix。**(1) P15.2** 加 5 个 semantic token (`--select-disabled-border` / `--select-line-border` / `--select-multi-line-border` / `--input-line-border` / `--input-disabled-border`) 在 `variables.css` :root + [data-theme='light']，dark=grey-8 / light=grey-5 (multi=grey-4)，落 Figma 跨 theme 不对称为 code 端 B1 还原；`SelectBoxBase.vue` + `Input.vue` 改 component CSS 用 semantic token；`Input.vue` 加 `.tvu-input--filled:disabled/...:not(...)` `border-color: transparent` 单 theme drift；verifier classifyFailedCheck 加 P14d-style placeholder-visible textFillHex B 归类（中间形态，被 extend 撤回）。**(2) P15.2-extend** 真修 verifier — `tests/visual-verify/manifest-verifier.spec.ts` evaluate 加 `getComputedStyle(el, '::placeholder')` when `isShowingPlaceholder` (`modelValue=''` + `state!=='disabled'`)，74 个 textFillHex false B → 真 PASS；撤回 P15.2 中间 P14d-style B 归类（已 obsolete）。新立 `docs/working-principles.md` 原则 7（Figma 跨 theme 不对称 B1 token） + 新建 `docs/internal/figma-cross-theme-asymmetries.md` 清单 4 rows initial。**总 cleanup** vs master baseline c7aaa8a5: Entry PASS 209→**232** (+23) / SKIP 138→**207** (+69) / **FAIL 288→196** (-92); field A 398→**241** (-157, 真清非记账); B 34→**10** (-24, 治超记)。Guards 全保留 (P10a SKIP 83 / P11 SKIP 224 / P12 XL 80/80 / P13 disabled text 104/8 / P14 hover/focus/editable rootBorderHex 0/0/0)。Commit b7448843。剩余 196 FAIL pattern: rootPadding cluster ~48 (P16 候选) + DropDownListSelect Unknown 5 cluster ~29 (node-id lookup pipeline 调研) + 2 XL feature=text-count outlier + 10 残留 B (真 schema gap)。**原则记忆**："记录限制 ≠ 解决问题"——本轮先把 74 个误归 B 真修升 PASS（getComputedStyle pseudo 元素），不让 B 抽屉膨胀变僵尸 ledger。 | — | — | — | — | — | — | — | — | — | — | — | — | manifest path A |
| 18 | 2026-05-26 | **P14 + P14b + P14c ✅ executed (full :hover/:focus pseudo-class 闭环)** — 1 fix commit 含 3 协作 sub-fix。**(1) P14** verifier `tests/visual-verify/manifest-verifier.spec.ts` collectActual 加 `locator.hover({force:true})` for hover state + `el.focus()` for focus/editable，结构对但 cleanup 仅 +10（code 端缺 CSS pseudo 规则）。**(2) P14b** `src/components/Input/Input.vue` 补 `.tvu-input:hover:not(:disabled)` + `.tvu-input--filled:hover:not(:disabled)` brand border；`src/canonical/SelectBoxBase.vue` 补 `.select-trigger:hover/:focus:not(:disabled)` + filled override（Vue state class `.select-wrap--interactive` 保留，浏览器 pseudo 走 CSS 真源），cleanup +25 但仍读到 transition 中途 `#344338` mid-blend 色。**(3) P14c** verifier 触发 pseudo **之前**给 locator `style.setProperty('transition','none','important')` 破 0.15s transition race（数学反推 verified `#344338 = brand×0.1 + bg×0.9`），删 P14b 的 RAF wait。Evidence: select box/filled focus rootBorderHex exp=#2fb54e act=**#2fb54e** PASS。**总 cleanup** vs P14 baseline: Entry PASS 148→**209** (+61) / SKIP 105→**138** (+33) / **FAIL 382→288** (-94); field A 557→**398** (-159). rootBorderHex hover/focus/editable: **104+46+24 → 0/0/0** 完全清零；rootFillHex 同样 hover/focus/editable→0。Guards 全保留 (P10a SKIP=83, P9.1 Op FAIL=12, P12 XL 80/80, P11 rootGap SKIP=224, P13a+P13b disabled text 86/2)。Commit 09f8508e。剩余 288 FAIL 不同 pattern: textFillHex hover/focus 53 (placeholder pseudo 延伸限制) + rootPadding 196 (P16 cluster) + rootBorderHex disabled 38 (P15 候选) — 后续逐 pattern 拆。 | — | — | — | — | — | — | — | — | — | — | — | — | manifest path A |
| 17 | 2026-05-25 | **P10bc + P11 + P12 + P13a + P13b ✅ executed (dropdown axis + input/select 系统性收敛)** + schema backfill chore — 5 fix commits + 1 chore commit. **(0) chore(translation)** schema backfill 2026-05-21/22 entries (status/category/verifyHint 合规)，audit:translation-completeness activeFindings 3→0。**(1) P10bc** `src/canonical/DropDownListSelect.vue` template `--checked` type-aware (排除 Multi + disabled) + CSS brand color 从 `--active` 迁到 `--checked` + `:hover:not(--disabled)` 共享 green-bg；divergence `dropdown-type-selected-alias-radio-2026-05-25`。**(2) P11** `scripts/generate-render-verification-manifest.mjs` `HTML_VOID_ROOT_SELECTORS={'.tvu-input'}` 短路 rootGapMeaningful；rootGap FAIL 171→**0**。**(3) P12** base `Input.vue` Size+'xl' + textarea v-if + `--xl{height:100px;resize:vertical}` + InputBoxBase mappedSize XL→'xl' + Canonical.test contract + InputPage.vue 新 XL Textarea section 4 demo cards；XL rootHeight 0/80→**80/80** PASS。**(4) P13a+P13b** generator status=default 短路保留 Figma placeholder 子状态 + Input.vue 4-rule CSS (`:disabled`→tips / `:disabled:placeholder-shown`→disabled / `--xl:disabled`→disabled / `--xl.--filled:disabled:not(:placeholder-shown)`→tips) + SelectBoxBase root + `.select-value` + `.--placeholder` 三层 + divergence `input-select-disabled-text-figma-single-variant-outliers-2026-05-25`；disabled textFillHex 93 FAIL → **86 PASS / 2 FAIL outlier**；multi-select disabled **8/8 PASS**。**总 cleanup**: Entry PASS 84→**148** (+64) / SKIP 90→**105** (+15) / FAIL 461→**382** (-79); field A 951→**557** (-394). Guards 全保留 (dropdown rootBorderHex SKIP=83, Operation FAIL=12)。Out-of-scope: 2 input-box-filled M/L flake (renderTarget/ERR_ABORTED) 本地复现仍存在。Commits 43d24b10/40c586e9/3d99cd62/355545a0/08a9706d。**重要 process gap**: pre-commit hook 未挂 audit:translation-completeness, 导致 2026-05-21/22 schema 违例 entries 一路 push 没被拦, follow-up backlog 候选。 | — | — | — | — | — | — | — | — | — | — | — | — | manifest path A |
| 16 | 2026-05-25 | **P10a ✅ executed (verifier `rootBorderHex` zerowidth skip)** — `tests/visual-verify/manifest-verifier.spec.ts` line 235 单 `pushExact` → conditional `pushSkipped` 双门控 `numberFromPx(actual.borderWidth) === 0 && expected.rootBorderHex === null`，复用 rootGap pushSkipped 先例。Manifest verifier: PASS 84 / PASS_BY_MODE_SKIP 50→**78** (+28) / **FAIL 501→473** (-28); field-level A 1021→**963** (-58) / B 94→**65** (-29); dropdown `rootBorderHex` FAIL 83→**0** ✓; 83 entries PASS_BY_MODE_SKIP 100% 是 "Drop down List/Item" (零非 dropdown 误伤); 双门控 0 违反; 266 rootBorderHex FAIL 在 input box/select box 等保留 (借助 borderWidth>0 仍走 drift 检测). Divergence 登记 `dropdown-borderhex-zerowidth-currentcolor-noise-2026-05-22` (verifier-schema-gap 同 input-html-leaf 族). Commit [5e6e690e](https://github.com/NancyZeng0210/TVU-Design-System/commit/5e6e690e). Out-of-scope: 2 个 input-box-filled click M/L flake (renderTarget missing + ERR_ABORTED) 本地复现, 非 P10a 引入, 另起调研. 下一步: P10c 用户拍板 2 问 → 写 prompt → dispatch. | — | — | — | — | — | — | — | — | — | — | — | — | manifest path A |
| 15 | 2026-05-22 | **P9.1 ✅ executed (Operation type padding-right override)** — `.dropdown-select--operation-list .dropdown-item { padding-right: var(--sp-s) }` (3 lines added). Manifest verifier: PASS 84 / PASS_BY_MODE_SKIP 50 / **FAIL 501** (entry-level 维持); field-level A 1026→**1021** / B 99→**94** / dropdown rootPadding.* fail **0** (含 P9 reverse regression 全清). Commit [4f770f13](https://github.com/NancyZeng0210/TVU-Design-System/commit/4f770f13). P10 调研后拆 P10a/b/c：P10a (verifier `rootBorderHex` zerowidth skip, ~83 fail false positive) prompt 已 dispatch Codex in-flight；P10b (hover bg ~26) / P10c (type-aware checked, ~22, 2 用户拍板项) 待 P10a 跑完。| — | — | — | — | — | — | — | — | — | — | — | — | manifest path A |
| 14 | 2026-05-22 | **P9 ✅ executed (dropdown padding.right)** — `.dropdown-item padding: 0 12 → 0 8 0 12`. Manifest verifier: PASS 84 / PASS_BY_MODE_SKIP 50 / **FAIL 501** (entry-level unchanged from P8; 71 padding.right fixed but 12 Type=Operation regressions introduced because Figma binds pR=12 for Operation). Net field-level +59. P9.1 next session: add `.dropdown-select--operation .dropdown-item` override. | — | — | — | — | — | — | — | — | — | — | — | — | manifest path A |
| 13 | 2026-05-21 | **P8 ✅ executed (form-input vertical padding)** — `.select-trigger` + `.tvu-input` `padding 0 12 → var(--sp-xs) var(--sp-s)`. Manifest verifier: PASS 0→**84** / FAIL 595→**501** (entry-level). Field-level rootPadding.top/bottom 0→8 pattern: **0 remaining** (cleared ~700 findings). Path A first deterministic fix pattern closed-loop. Input gap divergence registered (`input-html-leaf-no-flex-children-2026-05-21`, accepted-divergence). | — | — | — | — | — | — | — | — | — | — | — | — | manifest path A |
| 12 | 2026-05-20 | **P5 ✅ executed (Badge 100% PASS)** + manifest A.1 schema 升级 (PASS_BY_MODE_SKIP for <2-subnode gap + width hug). Badge 40/40 PASS_BY_MODE_SKIP. Manifest 扩张 form-input cluster: 595 entries added (total 635). | — | — | — | — | — | — | — | — | — | — | — | — | manifest path A |
| 11 | 2026-05-20 | **A MVP ✅ executed** (Badge manifest verification) — 新增 manifest 生成器 + render harness + Playwright verifier；Badge **0/20 PASS** 但实证全部是 schema 漏字段（gap on 0-subnode + width hug-vs-fixed），不是 code drift。下一步 A.1 schema 升级。 | 6093 | 2204 | 480 | 410 | 57 | 13 | 695 | 224 | 0 | 288 | 162 | 355 | 0 (A 不动 audit) |
| 10 | 2026-05-20 | **P4 ✅ executed, then plan owner reverted** — 3 处 `:disabled opacity → token`，Figma 自验证 dark theme 全对齐 + light theme 4 处偏差（`--control-disabled-bg/border` token 自身 light 值跟 Figma 不齐）。Revert 等 A 出 deterministic 数据再做。 | 6093 | 2204 | 480 | 410 | 57 | 13 | 695 | 224 | 0 | 288 | 162 | 355 | 0 (reverted) |
| 9 | 2026-05-20 | **P3 ✅ executed (Fix 1+2 kept, Fix 3 reverted by plan owner)** — 2 valid fixes in SelectBoxBase.vue: `.select-chip gap 4→8px (var(--sp-xs))`, `.select-wrap--l .select-dropdown width=300px` (L-size override). Fix 3 (operation-list 200→240) was reverted. | 6093 | 2204 | 480 | 410 | 57 | 13 | 695 | 224 | 0 | 288 | 162 | 355 | -144 |
| 8 | 2026-05-20 | **Triage ✅ executed** — 4 桶分类（不改 finding，纯分析）| 6237 | 2348 | 480 | 410 | 57 | 13 | 695 | 224 | 144 | 288 | 162 | 355 | 0 (audit 不变)|
| 7 | 2026-05-20 | **P2.2 ✅ executed** `.dropdown-item__check--checked` background var(--brand)→var(--brand-match) (1 line diff) | ~6199 | 2310 | 442 | 372 | 57 | 13 | 695 | 224 | 144 | 288 | 162 | 355 | -38 |
| 6 | 2026-05-20 | **R1.2 ✅ executed** (hex-equality + name-drift category) | 6237 | 2348 | 480 | 410 | 57 | 13 | 695 | 224 | 144 | 288 | 162 | 355 | -278 |
| 5 | 2026-05-19 | R1.1 ✅ executed + P2 chip fix (1 line) | 6515* | 2626 | 518 | 462 | 56 | — | 695 | 224 | 144 | 288 | 162 | 1857* | 0 |
| 4 | 2026-05-19 | P2.1 ✅ executed — 0 new fixes（前置 R1.1 OK 后跑，但 462 都被标 case C）| 6515 | 2626 | 758→518 | 462 | 56 | — | — | — | — | — | — | — | 0 |
| 3 | 2026-05-19 | P2 ✅ executed — 1 line chip fix (--bg-layer3 → --input-filled-bg) | 6515 | 2626 | 758 | 462 | **296** | — | 695 | 224 | 144 | 288 | 162 | 1857 | 0 (chip misclassified theme-asym) |
| 2 | 2026-05-19 | R1 ✅ executed — equivalence map + 三分判定 | 6515 | 2626 | 758 | **606** | 152 | — | 695 | 224 | 144 | 288 | 162 | 1857 | 0 (just reclassification) |
| 1 | 2026-05-19 | **Baseline** — audit:component-attributes 首跑 | 6515 | 2626 | 3145 | — | — | — | 695 | 224 | 144 | 288 | 162 | 1857 | — |

\* color-token-missing 数字在 R1.1 / R1.2 后只是 finding **distinct subset** 显示（每跑都重算），实际"缺 token" 物理位置数量没动；用 audit.json 内 summary 为准。

---

## 关键趋势观察（截至 R1.2）

### 已减少 / 已分类清晰
- **color-token-mismatch total**: 3145 → 480（**-2665**）—— 大头降幅来自 R1 的 allowlist 机制（Button 8-set 等设计意图）+ R1.1 chain 解析 + R1.2 hex equality
- **non-equivalent**（真要 fix 的）: 实际从 758 baseline blocker 收敛到 410 真 hex 不等的 finding —— 这是真"修了"
- **name-drift = 13**: R1.2 新分类捕获的"视觉对但 token 名跟 Figma 不齐"，severity info（非 blocker）

### 仍未动 / 待 P2.2 / 待 P3
- **non-equivalent 410**：含 44 条 `.dropdown-item__check--checked` background 待 P2.2 修；剩 ~366 是真 case C 需要更细分析或加 modifier
- **size-drift 695 / padding-drift 224 / gap-drift 144 / opacity-drift 288 / size-mode-mismatch 162**：本 session 完全没动；它们是后续波次范围
- **color-token-missing 355**（汇总 1857）：Figma 绑了 token 但 code selector 找不到对应 declaration —— 部分是 selector 推断启发式误报，部分是真缺

### 警戒灯（任何回升要立刻 STOP）
- 任一 non-allowlisted 数字单波**涨** ≥ 5% → STOP + 复盘改错方向
- exact 桶**降**（应当只涨不降）→ STOP，说明改动让原对齐变 drift
- 新出现 `category` 类型 → 检查 audit script 是否引入了误报

---

## 配套指标 — a11y inspector library scope

| # | When | Library nodes | docs-chrome | demo-local | 总 | Δ library vs prev |
|---|---|---:|---:|---:|---:|---:|
| 4 | 2026-05-20 (after P2.2 brand-match) | 215 | — | — | — | +8 vs #3 (brand-match 视觉本就比 brand 弱，预期内) |
| 3 | 2026-05-19 (after P2 chip + B docs cleanup) | 207 | 478 | 1427 | 2112 | +6 vs #2 |
| 2 | 2026-05-19 (after a11y scope 分类落地) | 201 | 478 | 1427 | 2106 | — |
| 1 | 2026-05-19 baseline (scope 加之前) | 196* | — | — | 1997 | — |

\* baseline 没 scope 分类时统一在一起计；引入 scope 后 196 = library 部分

> Library scope 微涨不必紧张（≤ +5% 接受），只要 P2.2 后 brand-match rebind 在视觉上能匹配 Figma 真源即可。**contrast 数字最终回归靠设计师改 Figma token 值，不是 P2.2 范围**。

---

## Triage 桶分布（row #8）

| Bucket | Count | % | 后续 action |
|---|---:|---:|---|
| **audit-noise** | 481 | 20.5% | audit script 启发式升级 |
| **real-drift** | 300 | 12.8% | **P3 prompt** — ~5 处 selector 修 |
| **strategy-gap** | 288 | 12.3% | divergences-decisions.json 登记 1 条（opacity 策略）|
| **figma-drift** | 230 | 9.8% | designer 复审（含 code 缺状态 declaration 可能性）|
| **unclassified** | 1049 | 44.7% | triage 规则需补（:deep svg / neutral color-missing 等）|

**关键发现**：
- 真 code drift 集中在 ~5 处 (selector, property)：select-chip gap 8→4 / dropdown-select width 300→240 / dropdown-select--operation-list width 240→200
- **300 finding 实际 = 5-6 行 code 修复**
- audit script 噪声 + unclassified = 1530 条（65%），都是 audit 自身覆盖面问题，跟 code 无关
- **A vs B 决策依据**：B (codegen) 不能减 audit 噪声；A 增量收敛仍是对的

## P3 verification (plan owner self-check via Figma source + git history)

Plan owner 用 Figma API + git HEAD 实证验证每条 Codex P3 改动（user 2026-05-20 新规则：不让用户做视觉审）：

| Fix | Codex 改动 | Figma 真源 | git HEAD | 结论 |
|---|---|---|---|---|
| 1 | `.select-chip gap: 4 → var(--sp-xs)` (8px) | size=L/M gap=8 | code 4 | ✅ 保留 |
| 2 | `+.select-wrap--l .select-dropdown { width: 300px }` | size=L w=300, size=M w=240 | code base width 240 | ✅ 保留（L 走 override, M 保 240，都对齐 Figma）|
| 3 | `.dropdown-select--operation-list 200→240` | w=200 | code **200** (已对齐) | ❌ plan owner P3 prompt 误读 triage direction → 回滚到 200 |

教训：triage 报告 "X -> Y" 文本格式有歧义（X 是 Figma 还是 code？），plan owner 直接读 JSON `figma.value` vs `code.value` 不易出错。后续 prompt 改用结构化数字而不是 "X -> Y" 缩写。

## 下一次更新

P3 commit 后下一波待定。剩余 real-drift 桶 ~140 多数是 audit script 不追跨组件 class merge 的限制（实际渲染对，audit 误报），需要 audit 启发式升级 prompt（不是 code fix）。
