skillhub/docs/14-skill-lifecycle.md
千乘妍 (Xiaoyaner) c06850fde4 feat: complete versioned skill presentation flow
Signed-off-by: 千乘妍 (Xiaoyaner) <xiaoyaner0201@users.noreply.github.com>
2026-10-31 00:56:41 +08:00

16 KiB
Raw Permalink Blame History

Skill Lifecycle

Date: 2026-10-15 Status: contract reference with documented implementation exception

本文件是 Skill 生命周期的统一导航入口;业务语义结合正式需求、设计与实现测试维护。发现冲突时应明确记录并确认预期,不能自动以代码或旧文档裁定。本次对齐依据见第 8 节;原始 latest 指针的 PRIVATE 例外见第 3.1 节。本页不定义 SuiteVersion 的状态模型。

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 历史兼容状态,可提审或删除;不作为普通上传的新建状态
SCANNING 等待当前安全扫描完成
SCAN_FAILED 扫描执行失败;不等同于发现风险
UPLOADED 上传保留,等待提审或 PRIVATE 确认发布;不保证已经扫描
PENDING_REVIEW 已提交审核,等待审核决定
PUBLISHED 已发布;实际分发还需满足可见性、容器状态与可安装条件
REJECTED 审核拒绝后保留的版本
YANKED 曾发布、现已撤回分发的版本

2.3 ReviewTask 审核工作流状态

  • PENDING
  • APPROVED
  • REJECTED

ReviewTask 仅表达审核流程,不再被前端当作展示态来源。

3. 核心语义

3.1 Latest

  • 公共 latest、搜索、兼容接口和默认公开分发必须解析到已发布版本,不能把未发布内容作为公开 latest。
  • 审核通过及自动发布时,Skill.latestVersionId 指向发布版本;无已发布版本时允许为空。
  • 已知实现例外: PRIVATE 上传/重发会将原始 latestVersionId 指向新建 UPLOADED 版本;启用扫描后该版本可能处于 SCANNING。发布测试明确覆盖此指针更新,不能把这个字段单独当作已发布证明。
  • 详情和 owner summary 的 projection 检查指针目标是否 PUBLISHED,否则查找已发布版本;批量公开摘要只检查原始指针目标是否可安装,不执行该回退。不能假设各读模型都以相同方式修复指针;latest 标签和消费者也不能无条件沿用原始指针。
  • 是否将 PRIVATE 持久化指针也统一为仅指向已发布版本,需要单独设计并检查消费者、历史数据及测试。本次只记录例外,不改变该行为,也不放宽公共 published 约束。

3.2 Lifecycle Projection

详情页、我的技能、我的收藏、搜索等读模型统一基于以下 projection:

  • headlineVersion:projection 的默认主展示候选;前端可按选中版本或管理预览选择展示内容,不保证每个页面都直接显示该字段
  • publishedVersion:最新已发布版本
  • ownerPreviewVersion:有权限的管理者可见的新一轮未发布工作版本(排除 PUBLISHED / YANKED,且比已有发布版本更新)
  • resolutionMode:PUBLISHED / OWNER_PREVIEW / NONE

约束:

  • 默认公开展示、安装与搜索以最新已发布版本为候选;显式版本或自定义标签可指向其他 PUBLISHED 版本,仍须通过入口授权与就绪检查
  • owner 详情页只有在不存在 publishedVersion 时,才允许 headlineVersion = ownerPreviewVersion
  • compat latest 和默认公开下载采用最新已发布版本语义;promotion 可选择来源 skill 的任一 PUBLISHED 版本,不要求等于 publishedVersion。原始指针与各入口解析差异见第 3.1 节
  • 管理者的授权预览下载与公开分发不同:owner 或 namespace ADMIN/OWNER 可下载 UPLOADED / PENDING_REVIEW,当前 owner 另可受控下载自己的 DRAFT / REJECTED,仍须通过 Skill 可见性、文件就绪及其他安全检查;不因此放行 SCANNING / SCAN_FAILED / YANKED 或公开分发未发布版本。常规 downloadLatest 读取原始指针后也使用相同版本授权判断,因此 PRIVATE 指针例外下,默认下载不一定是已发布版本;该行为不授予公众访问权。
  • 已发布版本可安装还要求 downloadReady=true、yankedAt=null;下载要求容器为 ACTIVE,元数据可读不等于可下载

4. 代码实际链路

4.1 首次上传

上传路径 扫描与后续状态 审核任务 / latest
普通 PUBLIC / NAMESPACE_ONLY 要求扫描启用;创建待审版本,触发扫描进入 SCANNING,当前扫描完成后回到 PENDING_REVIEW 创建 PENDING review task;不移动 published 指针
普通 PRIVATE 启用扫描时 SCANNING -> UPLOADED;未启用时直接 UPLOADED 不自动创建审核任务;原始指针例外见 3.1
特权自动发布 直接 PUBLISHED;启用扫描时仍扫描,但不降为 SCANNING 不创建审核任务;更新发布指针
  • 扫描执行失败可进入 SCAN_FAILED。扫描完成不代表无风险,风险发现、警告确认和审核门槛是独立检查;过期扫描结果不能完成新一轮扫描。
  • submit-review 接受 UPLOADED(兼容历史 DRAFT),设为 PENDING_REVIEW 并创建审核任务,保存请求的目标可见性。
  • confirm-publish 仅用于 PRIVATE Skill 的 UPLOADED(兼容 DRAFT):转为 PUBLISHED,更新发布时间与 latest,发出发布事件,不触发新扫描。

4.2 审核通过

  • PENDING_REVIEW -> PUBLISHED
  • review task 标记为 APPROVED
  • Skill.latestVersionId 指向该版本
  • skill 展示元数据从发布版本刷新,摘要采用该版本有效 short-description(自定义覆盖优先,其次包内值,再退回 description);overview 仅在选中版本详情展示。提交时的自定义继承冻结在版本快照,审核期间不随其他版本发布而变化。

4.3 审核拒绝

  • PENDING_REVIEW -> REJECTED
  • review task 标记为 REJECTED
  • 版本保留,可后续删除

4.4 撤回审核

  • withdraw-review 的统一语义是 PENDING_REVIEW -> UPLOADED
  • 同时删除关联的 PENDING review_task
  • 该操作是可逆、非破坏性的
  • 当前代码只允许提交人本人撤回

4.5 重传新版本

  • 若发现旧的 PENDING_REVIEW 版本,会先把旧版本自动撤回到 UPLOADED
  • 然后按可见性及自动发布条件创建新版本,走 4.1 的对应路径
  • 普通交互上传的自动撤回与手动撤回保持同一目标状态;Bundle 发布禁止自动撤回,已有待审版本时应阻塞,由用户先处理

4.6 已发布版本重发

  • rerelease 当前本质上是从已发布版本复制并重新走发布流程
  • 入口先检查生命周期管理权限,要求来源版本为 PUBLISHED、目标版本号未占用;内部传空平台角色集且 forceAutoPublish=false,不沿用平台特权直发
  • 新版本按原 skill 的可见性及扫描配置进入 4.1 对应的上传、扫描或待审路径;内部绕过重复成员校验不等于绕过审核
  • 该能力是复制内容重新发布,不是生命周期展示态

4.7 隐藏 / 恢复 / 归档 / 撤回已发布版本

  • 隐藏:设置 hidden=true 并记录治理信息,不改变版本状态;不抹除 owner / namespace 管理者的访问权限
  • 恢复:设置 hidden=false 并更新治理信息
  • 归档:Skill.status = ARCHIVED,保留记录并禁止下载;公开元数据仍可能可读
  • 取消归档:Skill.status = ACTIVE
  • yank:PUBLISHED -> YANKED,记录撤回人、时间和原因,设置 downloadReady=false;没有对应的恢复发布操作

4.8 Yank 后指针修正

  • yank 已发布版本时,若命中当前 latestVersionId,必须重算 latest published pointer,并从回退版本的 metadata 恢复展示名和摘要
  • 若仍有其他 PUBLISHED 版本,则指向最新一个
  • 若已无任何 PUBLISHED 版本,则 latestVersionId = null

4.9 独立调整已发布技能的可见范围

可见范围属于 Skill 容器,不需要新建 SkillVersion。缩小立即生效;扩大创建 SKILL_METADATA 范围申请,与内容待审互斥。原范围、目标范围和发布版本快照保存在 ReviewTask,审核通过才更新范围;旧审批不能覆盖新版本。未扫描的已发布包复用存量 bundle 扫描,保持 PUBLISHED,申请绑定扫描 taskId;未通过不得批准。头像按目标受众复用同一审核申请。范围事件仅刷新搜索,不发送“新内容版本发布”通知。操作和接口详见使用指南。

5. 对外协议约束

5.1 Public / Search / Compat

  • 对外协议可以继续暴露 latestVersion、latest、默认下载等概念
  • 但它们都必须严格表示“最新已发布版本”
  • compat 层内部实现必须从统一 lifecycle projection 的 publishedVersion 映射,不允许自行推导“当前版本”

5.2 Frontend

  • 页面状态展示统一消费 projection
  • 不再新增旧兼容字段依赖
  • hidden 仅作为治理标记展示,不参与版本状态拼装

5.3 提升更新与撤销

  • 提升要求所选版本属于团队来源 Skill 且为 PUBLISHED,可选历史版本,再单独进入平台提升审核;后续更新同一全局 Skill 时为它新增不可变的已发布版本。
  • 首次和后续提升均优先从所选来源版本的 parsedMetadataJson 读取展示名和摘要;字段为空才回退到审核时来源 Skill 的展示信息,非空但解析失败则抛错。
  • 全局 Skill 也可独立上传并审核。提升更新与独立上传使用相同版本号时不能互相覆盖;不同号版本分别发布,latest 指向最后通过审核的版本,不按版本字符串大小排序。
  • 撤销提升不同于归档或隐藏:平台审核通过后移除全局派生 Skill 的公众入口及记录,保留来源团队 Skill、提升和撤销审计,并保护共用对象存储文件。重新提升形成新的全局 Skill ID。

5.4 已提升技能如何删除

团队技能与提升生成的全局技能是两条关联记录。只撤回待审核版本、取消更新或撤回尚未批准的申请,不会删除已经发布的全局技能,也不会解除首次提升的关联。

若删除时提示须先撤销全局发布(旧版本提示“已提升的技能须通过审核撤销流程删除”),按以下顺序操作:

  1. 打开来源团队技能详情页,在提升区域选择“申请撤销全局发布”,填写原因并提交。
  2. 平台管理员在提升管理的撤销申请中审核;申请处于待审或被拒绝时,全局技能仍然存在,两条技能都不能绕过该流程直接删除。具有相应平台治理权限的管理员也可在来源详情页直接撤销。
  3. 撤销批准后,全局技能及其地址自动删除,来源团队技能和版本仍保留。此时如需连来源一起删除,由技能所有者或超级管理员执行来源技能的永久删除。

撤销时已有的全局更新申请会失效,不能在全局记录删除后重新发布到该记录。提升撤销保留提升、撤销与删除审计;来源技能后续永久删除仍按既有物理删除流程清理其业务记录,操作审计继续保留。不要通过手工清除来源关联字段来绕过撤销审核。

6. 权限边界

TEAM 成员移除后的当前所有者

账号正常但已不是 TEAM 成员的当前技能所有者,保留自己的技能、私有内容、草稿及历史版本的查看和受控下载权限,不能凭所有者身份执行以下写操作。成员移除不删除技能、不迁移地址、不改 owner、不自动撤回待审核申请;既有审核人继续按原安全与审核规则处理。重新加入且账号正常、所有权未变时恢复原有维护权限。

本条只收紧普通 owner 的成员边界,空间/平台管理员的原有独立权限不变;其他空间和 GLOBAL 原有规则不变。账号停用仍由原认证机制拒绝,不能通过 owner 匹配绕过。以下各行中的 owner 写权限均以这条成员边界为前提,不影响管理员独立路径。

操作边界

  • withdraw-review:仅提交人本人
  • 删除版本:owner 或 namespace ADMIN/OWNER,仅限 DRAFT / REJECTED / SCAN_FAILED / UPLOADED,禁止删除最后一个版本。数据库删除提交后清理对象存储,失败调用补偿入口;不是跨存储原子删除,补偿持久化的验证限制见对象存储写入策略
  • 归档 / 取消归档:owner 或 namespace ADMIN/OWNER
  • 隐藏 / 恢复技能:平台技能治理权限
  • yank:owner 或 namespace ADMIN/OWNER 可走普通治理入口;平台治理入口另校验平台权限
  • 提交审核:owner 或 namespace ADMIN/OWNER;PRIVATE 确认发布还支持传入平台角色的 SUPER_ADMIN 路径
  • 读取:可见性检查区分 PUBLIC、NAMESPACE_ONLY、PRIVATE 和 hidden;没有 latest 指针且未隐藏时,普通 namespace 管理角色不自动获得读取权限,owner 可读。接受平台角色的检查入口另支持 SUPER_ADMIN,不等于每个服务调用均传递该角色
  • 写操作授权与读取授权分别校验,不能从管理身份推导所有未发布技能均可读取

7. 当前最终约束

  • 一个 skill 生命周期的唯一规范入口就是本文件
  • 其它文档如 02-domain-model、05-business-flows、06-api-design、08-frontend-architecture 必须与本文件保持一致
  • 生命周期行为变化先确认正式需求与验收,再同步修改实现、测试及本文;不能以文档对齐名义静默裁定新业务规则

8. 依据与验证锚点

以上锚点用于核对具体行为,不代表覆盖了所有状态组合,也不等于真实部署或对象存储验收。