# v0.5.0 Release Retrospect — 2026-05-18

> **One-liner**：Button canonical 完整化（canonicalTheme axis）+ Tier 2-E/F tooling CLI + CANONICAL-007 + EXTRACT-006 + INFRA-F32（解锁 Tier 1-B 数据源）。实跑 ~6h（含 2 CI hotfix）。
>
> **Ship evidence**：
> - Tag: `v0.5.0` → release commit `2b54a73b` (+ hotfix `4f18a065` `4b7de2ed`)
> - CI run: [26024995380](https://github.com/NancyZeng0210/TVU-Design-System/actions/runs/26024995380) green (3rd attempt)
> - Packages registry: [`@nancyzeng0210/tvu-design-system@0.5.0`](https://github.com/users/NancyZeng0210/packages/npm/package/tvu-design-system) created 2026-05-18T09:28:01Z

---

## Scope shipped

| Sprint | Commit | 内容 | 实际 / 估 |
|---|---|---|---|
| A.1 baseline | — | Phase 6.8 实证 baseline：8 主 sets × ~400 variants = 3,224 variants；ButtonBridge 唯一缺口 = canonicalTheme axis | ~30min / — |
| A.2 SoT drift | `d48cfc81` | 实证数字同步 5 个文件，修正历史 "21 sets / 8400 variants" | ~1h / — |
| A.3 Phase 6.8 | `136ddc4b` | ButtonBridge inject + resolvedTheme + canonicalTheme prop + data-figma-theme + @deprecated + 3 vitest cases | ~3h / ~20-30h |
| Sprint C Tier 2-E | `27c90388` | `scripts/figma-url-to-canonical.mjs` CLI | ~30min / ~4-6h |
| Sprint D Tier 2-F | `27c90388` | `scripts/lint-skills.mjs` CLI, 11th strict gate | ~30min / ~3-5h |
| CANONICAL-007 | `63a9cdaf` | Pagination native button → DS Button (`canonicalStyle/Color/Size/Radius` + `:deep(.btn)` compact) | ~30min / ~2h |
| EXTRACT-006 | `a668e524` | `getFileStyles()` + `extractStyles()`；live 14 text (7 PingFang SC new) / 4 effect / 0 fill / 0 grid；normalized-key prev merge | ~30min / 3-4h |
| INFRA-F32 | `2b54a73b` | api.mjs 5 helpers parametrized fileKey；`sync-mockup-data.mjs` + `pnpm sync:mockup`；`.gitignore figma-data/mockup/`；live verified w/ MicroApps fileKey (~65MB) | ~30min / 2-3h |
| CI hotfix #1 | `4f18a065` | token-aliases.ts `Mask blur8` single→double-space match figma 真源 | ~10min |
| CI hotfix #2 | `4b7de2ed` | drop `globSync` import (Node 22+ only); readdirSync fallback unconditional | ~10min |

**总 ~6h shipped**；7 milestones + 2 hotfix；Tier 1-B unblocked (audit 实现仍 v0.6.0 ~6-10h)。

---

## 关键决策点

### v0.5.0 scope 反复 (X → Z)

**Pickup 计划** (X): 4 项 bundle = Phase 6.8 + Tier 2-E/F + CANONICAL-007 + EXTRACT-006

**User pushback** ("为什么又让推 0.5？0.6 的东西做不了了吗"): 提示版本边界值得重审；用户更关心"还能再塞什么"。

**User 拍板 → Z 路线**: 把 INFRA-F32 也做完一起发，unblock Tier 1-B 数据源（audit 实现仍 v0.6.0）。

**结论**: F32 实跑 ~30min（远低于估 2-3h），ROI 极好——一个 session 解锁未来 Tier 1-B audit；Z 路线判断对，X 过度保守。

### plan owner direct（path B）

EXTRACT-006 + INFRA-F32 + Tier 2-E/F 均由 plan owner 直接实现，不过 executor 流程。
- EXTRACT-006: ~30min vs 估 3-4h
- INFRA-F32: ~30min vs 估 2-3h
- Tier 2-E/F: ~30min each vs 估 4-6h / 3-5h

历史规律：plan owner direct path 对简单 CLI / 单文件 infra 一贯 4-10× 优于估值。

### .gitignore figma-data/mockup/

产品 mockup 文件属于消费者 repo，drift 频繁，~65MB+ 单文件 — 不入设计系统库 git history。CI/local audit 依赖 FIGMA_TOKEN 现拉。

---

## 教训

### 1. Local prepublishOnly 跑过 ≠ CI 一定过（Node 版本差异）

**实证**:
- 本地 Node 22+ 有 `node:fs.globSync`，CI runner Node 20 没有 → `SyntaxError: globSync not exported` at module load (try/catch 来不及 fallback)
- 本地 lint-skills 跑过，CI 直接 import fail

**推荐**：
- script 用稳定 Node API（不依赖 Node 22+ stdlib），或 dynamic import + 兜底
- 长期：CI matrix 加 Node 20 + 22 双版本测，或 prepublishOnly 改用 nvm pin 到 CI 同版本

### 2. extract pipeline normalized-key match 是 schema migration 必备

**实证**:
- EXTRACT-006 把 `figma-styles.json` 从手动 export 切换到 figma API pipeline
- figma 真源 `Mask blur8  #000-60%`（双空格）vs 之前手动维护 `Mask blur8 #000-60%`（单空格）
- 不做 normalized-key match → 旧 entry 的 canonicalToken/usage 丢失
- 不修 token-aliases.ts → audit:translation-completeness `token-figma-reference` 抓 missing alias → CI fail

**做对了**：extract 端用 `normKey = k => k.replace(/\s+/g, ' ').trim()` 做 prev lookup，保留 prev 字段
**漏了**：token-aliases.ts 反向（code → figma）也用单空格 → audit fail；release CI 抓出来

**推荐**：figma 真源 migration 时，所有引用 figma name 的代码点（token-aliases / divergences / prop-aliases）都要 grep + 修一遍，不只 extract output

### 3. Pickup 不是合同，scope 该改就改

**模式**: 上 session 写 pickup 决定版本 scope；下 session 起手照办；用户 push back 时及时调整。

**反模式**: 因为"pickup 写了"就拒绝 scope 调整，导致小项目延期到下一 release（违反排期 SoT "依赖解锁" 原则）。

**实证本 session**: Z 路线把 F32 加入 → Tier 1-B 解锁 → 下 session 直接做 audit 而不再等"前置 sync 机制"。

---

## 与历史 release 比较

| Release | 内容数 | 实跑 | 估时 | 比率 | CI 一次过？ |
|---|---|---|---|---|---|
| v0.2.0 | 5 (Chart 大 + 4 infra) | ~2h | TBD | — | 否（re-tag 1 次）|
| v0.3.0 | 8 (Tier 1-A 4 sprints + SoT cleanup + 3 项) | ~8h | 1-2 周 | 4-8x | 是 |
| v0.4.0 | 4 (dual-form 2 + Phase 6.7 + 2-D) | ~4h | 12-18h | 3-4x | 是 |
| **v0.5.0** | **7 + 2 hotfix** | **~6h** | 1-2 周 | **3-4x** | **否（2 hotfix）** |

**Pattern**: estimation drag 3-8x；CI 一次过率 ~60% (3/5)——release CI 仍是质量门，本地 prepublishOnly 不能完全替代。

---

## v0.6.0 起手清单（下 session）

按 STATUS.md "Active 后续工作" 段：
- **Tier 1-C** ESLint plugin (~2-3 周 大项)
- **Tier 1-B** audit:mockup-conformance.mjs（now unblocked by F32, ~6-10h）
- **Tier 2-G** STATUS.md 一致性 lint（顺路 ~2-3h）
- **hook allow-list 升级**（顺路 ~30min — 把 figma-styles.json 移出 pre-commit block）

排期建议：先做 hook 升级 + Tier 2-G 顺路项，然后 Tier 1-B 或 Tier 1-C 选一作主线。
