# Semantic Release 版本迁移追踪

## 2026-04-26

### 当前恢复点（SEMREL-RP-004）

- 当前链路：
  - `workflow_dispatch` 手动启动
  - `preview` 对 dispatch SHA 执行 dry-run
  - `release-approval` environment 审批
  - `release` 在同一次 run、同一 SHA 上执行真实打 tag
- 当前规则：
  - `conventionalcommits` preset 负责解析 `feat!:` / `feat(scope)!:` 与 `BREAKING CHANGE`
  - `feat -> minor`
  - `fix/perf/refactor -> patch`
  - `docs/test/chore/build/ci/style -> no release`
  - `breaking -> major`
- 当前 workflow 加固：
  - `release` 额外要求 `needs.preview.result == 'success'`
  - `PAT_TOKEN` 通过复用的 composite action 统一校验
  - GitHub API 校验额外断言 `.permissions.push == true`，避免 read-only PAT 混过 preview
  - preview / release summary 会展示 snapshot 语义与生成的 release notes
  - `preview` 改为先校验并使用 `PAT_TOKEN`，避免 `github-actions[bot]` 在 dry-run 的远端 push 权限探测中触发 403

### 本轮关键决策

- 保留 `@semantic-release/release-notes-generator`，但不再让它白跑：
  - 继续生成 notes
  - 将 notes 写入 GitHub Actions summary
- preview 与 release 共用 `PAT_TOKEN`：
  - `semantic-release` dry-run 仍会执行 `git push --dry-run`
  - preview 如果继续使用 `${{ github.token }}`，会先被 `github-actions[bot]` 的仓库写权限拦住，日志不再具有可读性
- API 探活必须覆盖 push 权限：
  - 单纯 `GET /repos/{owner}/{repo}` 的 `200` 只能证明 read access
  - 本轮直接读取响应体里的 `permissions.push`，让 preview 在更接近真实失败原因的位置终止
- 不保留已废弃的 `release_mode=preview|release` 中间方案：
  - active trace 只保留当前有效链路
  - 历史演进以 tracking 归档文件为准，active tracking 仅保留当前恢复入口

### 验证结论

1. `npx --yes -p semantic-release -p conventional-changelog-conventionalcommits@9.1.0 semantic-release --dry-run --no-ci`
   - 已确认新 preset 包可加载，`commit-analyzer` 与 `release-notes-generator` 正常初始化
   - 本次 dry-run 未继续出版本，因为干净克隆的 `main` 已落后远端
2. `dotnet build GFramework.sln -c Release`
   - 通过，`639 warning / 0 error`
   - warning 为仓库既有基线，本轮 workflow / ai-plan 调整未新增关联 warning

### 下一步

1. 重跑 `auto-tag.yml` 的 preview，确认 read-only PAT 会在校验步骤提前失败、可写 PAT 不再落到 `EGITNOPERMISSION`
2. 复查当前 PR 的 open review threads 是否已与本地修复对齐
3. 创建提交并推送当前分支
