skillhub/docs/14-skill-lifecycle.md
Xudong Sun 4aa3d29599 refactor: skill lifecycle projection and docs (#78)
* Refactor skill lifecycle projection and docs

* Improve owner lifecycle visibility on skill detail

* Track download counts per skill version
2026-03-18 13:39:22 +08:00

155 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Skill Lifecycle
Date: 2026-03-18
Status: current code-aligned reference
本文件是 skill 生命周期的单一规范入口。结论以当前代码实现为准并已经同步到领域模型、业务流程、API、前端、搜索和兼容层文档。
## 1. 设计原则
- skill 生命周期不再被建模为一个混杂状态机,而是拆分为容器状态、版本状态、审核工作流状态和可见性覆盖层
- 前端不再从 `status + hidden + latestVersionStatus + viewingVersionStatus` 拼装状态,而统一消费后端 lifecycle projection
- destructive action 和 reversible action 必须分离;`withdraw-review` 只表示撤回提审,不表示删除版本
- 对外仍可保留 `latest` 协议词汇,但内部语义必须严格等价于 latest published
## 2. 状态模型
### 2.1 Skill 容器状态
- `ACTIVE`
- `ARCHIVED`
说明:
- `hidden` 是独立治理覆盖层,不属于 `Skill.status`
- `SkillStatus.HIDDEN` 不再视为有效生命周期语义
### 2.2 SkillVersion 版本状态
- `DRAFT`
- `PENDING_REVIEW`
- `PUBLISHED`
- `REJECTED`
- `YANKED`
状态含义:
- `DRAFT`:可再次提交审核或删除的非公开版本
- `PENDING_REVIEW`:冻结待审版本
- `PUBLISHED`:当前可分发版本
- `REJECTED`:审核拒绝后保留的版本
- `YANKED`:曾发布、现已撤回分发的版本
### 2.3 ReviewTask 审核工作流状态
- `PENDING`
- `APPROVED`
- `REJECTED`
`ReviewTask` 仅表达审核流程,不再被前端当作展示态来源。
## 3. 核心语义
### 3.1 Latest
- `Skill.latestVersionId` 的唯一语义是 latest published pointer
- 它只能指向 `PUBLISHED` 版本
- 若 skill 没有任何已发布版本,则允许为 `null`
- `latest` 系统保留标签自动跟随该指针
### 3.2 Lifecycle Projection
详情页、我的技能、我的收藏、搜索等读模型统一基于以下 projection
- `headlineVersion`:当前页面主展示版本
- `publishedVersion`:最新已发布版本
- `ownerPreviewVersion`owner / namespace 管理者可见的待审核预览版本
- `resolutionMode``PUBLISHED` / `OWNER_PREVIEW` / `NONE`
约束:
- 公开浏览、安装、下载、搜索只认 `publishedVersion`
- owner 详情页只有在不存在 `publishedVersion` 时,才允许 `headlineVersion = ownerPreviewVersion`
- promotion、compat latest、默认下载等公开分发行为都只能绑定 `publishedVersion`
## 4. 代码实际链路
### 4.1 首次上传
- 普通用户上传后直接创建 `PENDING_REVIEW` 版本
- 同时创建 `PENDING` review task
- 不会创建初始 `DRAFT`
- 不会更新 `latestVersionId`
### 4.2 审核通过
- `PENDING_REVIEW -> PUBLISHED`
- review task 标记为 `APPROVED`
- `Skill.latestVersionId` 指向该版本
- skill 展示元数据从发布版本刷新
### 4.3 审核拒绝
- `PENDING_REVIEW -> REJECTED`
- review task 标记为 `REJECTED`
- 版本保留,可后续删除
### 4.4 撤回审核
- `withdraw-review` 的统一语义是 `PENDING_REVIEW -> DRAFT`
- 同时删除关联的 `PENDING review_task`
- 该操作是可逆、非破坏性的
- 当前代码只允许提交人本人撤回
### 4.5 重传新版本
- 若发现旧的 `PENDING_REVIEW` 版本,会先把旧版本自动降回 `DRAFT`
- 然后创建新的待审版本
- 自动撤回与手动撤回必须保持同一语义
### 4.6 已发布版本重发
- rerelease 当前本质上是从已发布版本复制并重新走发布流程
- 当前实现允许特权路径直接产出新 `PUBLISHED` 版本
- 该能力应被理解为发布路径特例,不是生命周期展示态
### 4.7 隐藏 / 恢复 / 归档 / 撤回已发布版本
- 隐藏:只改 `hidden=true`
- 恢复:只改 `hidden=false`
- 归档:`Skill.status = ARCHIVED`
- 取消归档:`Skill.status = ACTIVE`
- yank`PUBLISHED -> YANKED`
### 4.8 Yank 后指针修正
- yank 已发布版本时,若命中当前 `latestVersionId`,必须重算 latest published pointer
- 若仍有其他 `PUBLISHED` 版本,则指向最新一个
- 若已无任何 `PUBLISHED` 版本,则 `latestVersionId = null`
## 5. 对外协议约束
### 5.1 Public / Search / Compat
- 对外协议可以继续暴露 `latestVersion``latest`、默认下载等概念
- 但它们都必须严格表示“最新已发布版本”
- compat 层内部实现必须从统一 lifecycle projection 的 `publishedVersion` 映射,不允许自行推导“当前版本”
### 5.2 Frontend
- 页面状态展示统一消费 projection
- 不再新增旧兼容字段依赖
- `hidden` 仅作为治理标记展示,不参与版本状态拼装
## 6. 权限边界
- `withdraw-review`:仅提交人本人
- 删除版本owner 或 namespace 管理者,且仅限 `DRAFT` / `REJECTED`
- 归档 / 取消归档owner 或 namespace 管理者
- 隐藏 / 恢复技能、撤回已发布版本:平台技能治理权限
## 7. 当前最终约束
- 一个 skill 生命周期的唯一规范入口就是本文件
- 其它文档如 `02-domain-model``05-business-flows``06-api-design``08-frontend-architecture` 必须与本文件保持一致
- 若后续代码再次改变生命周期语义,应先修改代码,再同步更新本文件和相关子文档