# 2026-05-11 — v0.1 publish flow 完整闭环（INFRA-F27 + NPM-001/002/003 + GitHub Packages 发布）

## TL;DR

- **v0.1 publish 4/4 阻塞物全部解锁** → `@tvu/design-system@0.1.0` 已发到 GitHub Packages
- 落 commit chain（跨 2-3 个 plan owner session）：`5125e625` (INFRA-F27) → `7e54d50d` (NPM-001) → `babee0fd` (NPM-002) → `520bb15a` (NPM-003) → `26122ad3` (收尾) → `v0.1.0` tag → `45ef1aa2` (pickup 归档) → `1c23bf28` (collision 修复)
- 项目目标里程碑：design system 跨工具消费链路通了（外部 dev 可 `pnpm add @tvu/design-system`；CI 自动 audit + publish）
- **4 个 anti-pattern 现场暴露 + 修正落 memory；7 个可复用工程技巧固化**

---

## Lineage

```
META-F27 系统性 review (2026-05-09, commit ee999c0e)
  └── 发现 v0.1 真正阻塞 = npm 发布链路（CHANGELOG / README / publish CI 全缺）
      └── 派生 NPM-001/002/003 + INFRA-F27 backlog
          ├── INFRA-F27 build-icon-dist currentColor patch (5125e625, 2026-05-09)
          │     └── 解锁 publish 链 — generated icon 不再倒退 hardcoded 灰色
          ├── NPM-001 CHANGELOG + changesets 工具链 (7e54d50d, 2026-05-09)
          │     └── 解锁 0.1.1+ version mgmt
          ├── NPM-002 README registry install + GETTING_STARTED (babee0fd, 2026-05-11)
          │     └── 解锁 external consumer 文档
          └── NPM-003 publish workflow + RELEASING.md (520bb15a, 2026-05-11)
                ├── Phase 1 baseline check (READ-ONLY) — 7 PASS / 2 FAIL
                ├── Plan owner propose gate 分层 + Version 模型 + Tag 处理
                ├── User: "一步到位 不要分阶段" ← 反模式现场
                ├── 重写为一步到位 prompt → executor 落 publish.yml + package.json + RELEASING.md
                └── plan owner 收尾：2 follow-up backlog entry + pickup 更新 (26122ad3)
                      └── user 手动 git tag -d v0.1.0 && git tag v0.1.0 && git push --tags
                            └── CI publish workflow → @tvu/design-system@0.1.0 到 GitHub Packages 🎉
                                  └── pickup 归档 (45ef1aa2)
                                        └── 发现 CANONICAL-007 ID collision (我新加 entry 撞 existing ID)
                                              └── 修 backlog + RELEASING.md 引用链 (1c23bf28)
```

---

## 关键决策

### D1 — License 与发布渠道：B 路线（GitHub Packages）

| 候选 | 决策 |
|---|---|
| A — 公共 npm registry | ❌ 需 TVU 法务批 OSS license (MIT/Apache/BSD)，引入交涉成本；且当前受众是内部团队 |
| **B — GitHub Packages** | ✅ 私域；license 保 `UNLICENSED`；外部 consumer 需配 `.npmrc` GitHub PAT auth，但本阶段受众内部，可接受 |
| C — 保持 git+url install | ❌ 等于 v0.1 "npm 包化"目标不达成 |

**Why B**：仓库内部分发场景 + license 不交涉 + scope `@tvu` 与 GitHub Packages auto-link 一致。**未来如需开源**：迁公共 npm（A 路线）是单点改动（改 license + `publishConfig.registry` + scope policy）。

### D2 — publish 触发模式：tag-triggered + changesets 集成

- `git tag v*.*.* && git push --tags` 触发 `.github/workflows/publish.yml`
- CI 流程：checkout → setup pnpm/Node → `pnpm install` (触发 prepare = typecheck + build) → 2 warn-only audit → `pnpm publish --no-git-checks` (prepublishOnly 跑 7 strict audit)
- **不加 husky/cron 主动提醒** — 0.1.0 保持简单；后续 0.1.x 若忘发版可加 husky pre-push hook

### D3 — audit gate 分层：Option A（7 strict + 2 warn-only）

基于 NPM-003 Phase 1 baseline：

| Audit | 状态 | Gate 决策 |
|---|---|---|
| audit:icon-fill-currentcolor | ✅ PASS | strict |
| audit:no-hardcoded-design-tokens | ✅ PASS | strict |
| audit:component-no-inline-svg | ✅ PASS | strict |
| audit:figma-conformance | ✅ PASS | strict |
| audit:docs-site | ✅ PASS | strict |
| audit:component-tokens | ✅ PASS | strict |
| audit:tokenized-diff | ✅ PASS | strict |
| audit:design-system | ❌ FAIL（Tab.vue 硬编码 + Icon/Logo raw SVG）| **warn-only** |
| audit:published-vs-code | ❌ FAIL（Components 36 matched / 2 figma-only 漂移）| **warn-only** |

**实现**：strict 7 个走 `prepublishOnly` 链（任一 fail 阻 CI）；warn 2 个走 workflow 独立步骤 `continue-on-error: true`。FAIL 项各派生 1 个 follow-up backlog entry，修完后升 strict。

### Version 模型 — X 路线（0.1.0 = 首次发布）

User 提出 "100+ commits 卡在 0.1.0 不符合版本管控"，plan owner 答：

- **changesets 直到 commit `7e54d50d` 才上线**，之前 100+ commits 都是 pre-publish iteration，无版本管控机制
- semver §4：`0.y.z` 阶段允许版本号粒度模糊（"public API SHOULD NOT be considered stable"）
- 0.1.0 = 首次发布是 npm 新包惯例（React/Vue v0 阶段都这样）
- **0.1.0 publish 之后**：每个 PR → `pnpm changeset` → 累积 → 发版时 `pnpm changeset:version` 聚合 + 自动 bump。从此版本号粒度变细。

→ 接受 0.1.0 = "foundation release"；0.1.1+ 起严格 changeset 管控。

### Tag 处理 — 删 stale local + 重建 at HEAD

NPM-003 Phase 1 baseline 发现 `v0.1.0` 已存在但指向 stale commit `49fb8f1e`（2026-04-22 早期 placeholder，103 commits 前）。**仅 local，未 push origin** → 可放心删除：

```bash
git tag -d v0.1.0     # 删 local stale tag (无 origin 影响)
git tag v0.1.0        # 重建在 HEAD (= NPM-003 收尾 commit 26122ad3)
git push --tags       # 推 → 触发 CI publish
```

---

## Issue / 反模式（本次现场暴露 + 修正）

### Anti-pattern 1 — AskUserQuestion 弹窗 用于 pickup 已预分析的决策点

**现场**：session 起手扫到 4 个 dirty 文件，pickup §4 已经分析过每个文件的建议处理路径（强烈建议 commit / user 自决 / 等等）。我用 `AskUserQuestion` 弹窗让 user 在"先消化 / 并行 / 搁置"3 选项里选。

**User 反馈**："没有推荐吗？不要弹窗确认"

**修正**：[`feedback_no-popup-for-clear-recommendation.md`](.claude memory)
- pickup/backlog/review 已预分析过的决策点 → 直接在文本里给推荐 + 理由，等 user 文本 go/no-go
- 真正分叉决策（pickup 没预分析、user 没明确倾向）→ 才用 AskUserQuestion
- **本质**：plan owner 角色就是要替 user 收敛到推荐方案；弹窗等于让 user 重做他已经做过的工作

### Anti-pattern 2 — Plan owner 主动消化别 session dirty 文件

**现场**：起手 onboarding 时建议"先消化 4 个 dirty 文件再写 NPM-002 prompt"，按 pickup §4 的描述。

**User 反馈**："这 4 个先不管，这是我在另一个 Session 中继续的任务，还没结束"

**修正**：[`user_parallel-sessions.md`](.claude memory)
- User 经常多 session 并行；看到 git status dirty 默认假设别 session 进行中
- onboarding 报告 dirty 时 explicit 标"如果别 session 在跑可忽略"
- 即使 pickup 已分析处理路径，也只是"知道路径"，不代表当下就该执行

### Anti-pattern 3 — Baseline → 拍板 → Phase 2 假分阶段

**现场**：写 NPM-003 prompt 时，我设计成两阶段——Phase 1 baseline audit 数据收集 + STOP → user 拍板 gate 配置 → Phase 2 写 publish workflow。Phase 1 跑完，executor 报告 7 PASS / 2 FAIL，我开始 propose gate 分层给 user 拍板。

**User 反馈**："我需要的是一步到位，不要分那么多阶段了，除非是我后续又增加了新的 Figma 组件"

**修正**：[`feedback_one-shot-prompts.md`](.claude memory)
- baseline 不确定 → propose 时带 **风险 + recommendation + fallback** 一步到位写完整 prompt
- 真正可分阶段：**外部 trigger 导致 scope 变化**（如 user 后续加 figma 组件 → 触发新 audit cycle）
- 不是 plan owner 自己制造的 "baseline 收集 → 拍板"
- 对 user 的 "OK / 推荐 / 全推荐" 视为对整路径 commit，包括所有 sub-decision

**实操影响**：把 Phase 1 prompt 改写为一步到位 NPM-003 prompt（决策 D1-D3 + Version + Tag 全 §0 baked-in；executor 直接落 3 个文件）。

### Anti-pattern 4 — Backlog ID 凭印象选号 → collision

**现场**：NPM-003 收尾时新加 backlog entry "Tab.vue 硬编码 + Icon/Logo raw SVG"，按印象选 `CANONICAL-007`。push 之后 user 让我列全局 backlog 时才发现：existing entry line 406 也叫 `CANONICAL-007: Pagination page number buttons`。我撞 ID 了。

**修正**：[`feedback_backlog-id-collision.md`](.claude memory)
- 新加 entry 前**必须**先 grep 全部已用 ID（Active + Resolved 两段）
- 挑**最大数字 +1**（不要补缺号 — 已弃用的 ID 可能在历史 retrospection / commit msg 里还有引用）
- 写完 entry 后 grep 新 ID 在仓库其它处出现的命中数：应只有 1（backlog.md 内）；如 >1 → 又撞了

**修复**：commit `1c23bf28` — backlog.md 改 CANONICAL-009 + RELEASING.md 2 处引用同步改。

---

## 工程技巧（可复用模式）

### 1. File-based prompt 范式

所有 plan owner 给 executor 的 prompt 落 `docs/internal/_prompts/<name>.prompt.md`，commit 入仓库。好处：

- 跨 session 可追溯（next session plan owner 看到 prompt 文件知道之前 fire 过什么）
- Executor 输入审计（争议时可比对 prompt vs 实际 diff）
- Prompt 本身就是合同（user 拍板的 decision 写进 §0，executor 不能"加料式发明"）
- 与 Codex 协议天然兼容（Codex context 短，每任务 fresh session，prompt 必须自包含）

### 2. Prompt 反模式 5 条自检（plan owner 强制）

写 prompt 前 / fire 前必须过 [`meta-rules.md §3`](docs/meta-rules.md)：

1. 硬编码项目级规则到工具（应在 `.md` 真源，工具读真源）
2. 打补丁方案（应抽象成机制让 X 是机制的实例）
3. to-do list 思维（应"产出契约"思维含溯源字段）
4. 没问下游怎么消费（数据/audit prompt 必须想清下游消费路径）
5. 没问扩展时改哪里（好机制扩展只改一处）

命中任一 → 重新设计，不 fire。本次 NPM-002/003 每个 prompt §6 都有自检表实证。

### 3. 协议化报告格式（executor STOP 输出 schema 化）

Prompt §4 强制定义报告 schema（fixed sections + 字段名）。executor STOP 时按 schema 填值。好处：

- Plan owner 复审有可机械比对的预期
- §3 验证命令的输出能映射到 §4 报告字段
- 多个 executor session 间的报告可累加（如 baseline + follow-up）

### 4. 验证机械化（exit code + grep + JSON 字段计数）

Prompt §3 验证段用可机械执行的命令（exit code / 行数 / 字段计数 / JSON 验证），不用 "manually inspect" 类指令。NPM-002 §3 12 条 / NPM-003 §3 17 条全部机械验证。

### 5. 审计 gate 分层（strict / warn-only）

`prepublishOnly` 跑 strict（任一 fail 阻 CI）+ workflow 独立步骤跑 warn (`continue-on-error: true`)。好处：

- baseline FAIL 不阻 publish（保留 fail 信号但不堵）
- follow-up backlog 修完后升级 = 一处改动（`prepublishOnly` chain 末尾加 `&& pnpm run audit:<name>` + 删 workflow continue-on-error step）

### 6. changesets 工作流（累积 → 聚合 → bump → tag）

- 每 PR 加 `.changeset/*.md`（`pnpm changeset` 交互式生成）
- 发版时 `pnpm changeset:version` 聚合 → 自动 bump `package.json` version + 写入 CHANGELOG 新段
- `git tag vX.Y.Z && git push --tags` → CI 自动 publish

详见 [`docs/RELEASING.md`](docs/RELEASING.md)。

### 7. 跨 session pickup pattern

`docs/internal/_plans/next-session-pickup-<date>.md` 包含：

- TL;DR（3 句话 — 阶段位置 / next task / dirty 协议）
- 时间线（已落 commit 表）
- onboarding 顺序（必读链路 + 时间预估）
- 任务队列（按临界路径）
- Dirty 文件协议（与别 session 边界）
- 生命周期（何时挪 `_plans/archived/`）

每次 session 起手读 pickup 就能进入工作模式；阶段完成后归档。

---

## 团队分享 takeaway（可直接节选）

> **AI 协作工程化 ≠ AI 自由发挥。让多 AI 工具（Claude/Codex/Cursor/Cline/Copilot）在同一项目协作不互相破坏，关键是把规则"硬"在仓库里——而不是"软"在某个 AI 的 prompt 历史里。**

### 团队 share 3 个 punch line

1. **真源单一 + 双层导入**
   - 项目级规则真源在 `.md` 文件（AGENTS.md / meta-rules.md / mockup-conventions.md）
   - 工具读真源 → 任何 AI 工具新接手该项目 24h 内就能上手
   - 实证：本仓库 Claude Code（plan owner）+ Codex（executor）+ 2-3 个并行 mockup session，0 协议冲突

2. **plan owner / executor 角色分工 + 单一决策源**
   - plan owner：propose decisions / 写 prompt / 审 diff（默认不直接改代码）
   - executor：严格按 prompt 跑 / 不"加料式发明" / STOP 等审
   - 决策固化到文档（不能只在对话里口头提）；prompt 版本化在 `_prompts/`

3. **One-shot prompt > 假分阶段**
   - "Baseline → 拍板 → Phase 2" 这种 plan owner 自己造的分阶段 = 浪费 cycle + 用户决策疲劳
   - 带 recommendation + fallback 一步到位写完整 prompt
   - 真正分阶段的合理触发是**外部 scope 变化**（新需求 / 新组件 / 新约束）

### 团队 share 3 个反例（什么时候 AI 会跑偏）

1. **AI 凭"行业惯例"自由发挥**（违反 AGENTS.md 硬规则 #2）→ 必须读 `translation/` 已登记决策；新决策必须 user 拍板
2. **AI 自创未登记的 prop / variant / 状态** → 例如 Notification 历史上自创的 `success` status（已识别为 bug，等待删除）
3. **AI 把项目级规则硬编码到脚本里**（违反 meta-rules §3 #1）→ 应在 `.md` 真源；工具读真源；规则修改 = 改一处

---

## Follow-up backlog（v0.1.0 publish 后续）

| ID | 描述 | 优先级 | 工作量 |
|---|---|---|---|
| CANONICAL-009 | Tab.vue 硬编码 + Icon/Logo raw SVG → 升 audit:design-system strict | Medium | ~2-3h |
| BRIDGE-MOCKUP-004 | 2 figma-only 组件漂移 → 升 audit:published-vs-code strict | Medium | ~1-2h baseline + 后续 fix |
| backlog hygiene | 把 NPM-001/002/003 + INFRA-F19/F22 移到 Resolved 段 | Low | ~30-60min |
| 0.1.1 演练 | 走一次完整 changeset → version → tag → publish 流程，验证工具链 | Medium | 视后续 patch 发版触发 |
| META-F28 候选 | 定期 review 节奏（每 1-2 月触发系统性 review） | Low | 待 META-F27 review 周期到点 |

---

## 元说明

- 本复盘文件落仓库前漏写了 ~30min（plan owner 疏漏 — v0.1 publish 流程完整闭环后没主动写复盘）。User 提醒 → 补写。
- AGENTS.md §共同规则要求 "阶段完成后追加复盘到 `docs/internal/retrospection/{date}.md`" 应作为 plan owner closing checklist 强制项（next-session pickup §8 元说明同步加 reminder）
- 团队分享文档（如需独立 lessons-learned 文档）可从本复盘 §团队分享 takeaway 段直接节选改写
