| name | release-verification |
| description | 发布验证规范 — 覆盖版本、changelog、测试、pack、install smoke、commit/tag/push/publish 前确认与发布后 registry/tag 验收 |
Release Verification Skill
职责
当用户明确要求 release / tag / publish / 版本发布时,执行发布前后验证链。它只做验证和确认边界,不自动执行真实发布动作。
触发条件
| 场景 | 是否触发 |
|---|
用户明确要求 release / publish / tag | 🔴 必须 |
| 修改 package/plugin/version/changelog 口径 | 🟡 条件 |
| 普通未发布实现批次 | N/A,默认写 changelogs/unreleased.md |
R0~R7 验证链
| 阶段 | 检查 |
|---|
| R0 | 确认目标版本、SemVer、tag 和 registry 唯一性;执行 ReleaseAuthorityBeforeCompatibilityGate,冻结 publishedState、consumerEvidence、authoritySources 与兼容决策 |
| R1 | 将 changelogs/unreleased.md 归档到 changelogs/releases/vX.Y.Z.md,并更新根 CHANGELOG.md |
| R2 | 同步 package.json、package-lock.json、plugin.json、Profile/README/website 版本口径;发布型 Profile 必须补齐 CI workflow/job 矩阵、tag/publish 触发链、失败恢复路径、外部消费者验证矩阵、dist 产物边界、registry/tag 验收与常见故障诊断;用户可交互发布面追加 InteractiveSemanticProbe |
| R2a | 执行 CandidateFreezeGate:冻结 candidate identity/generation、授权 scope、允许进入当前 release 的 mutation class 与 evidence dependency graph;冻结后新发现的非 P0/P1、非发布阻断治理项进入下一版本 |
| R3 | 执行 npm test(默认全链) |
| R3a | 执行 CandidateDiffCompletenessGate:先清点 tracked/untracked/ignored 边界,再使用临时 GIT_INDEX_FILE 物化本次授权范围,禁止改写用户真实 index;对隔离 snapshot 执行 git diff --cached --check、git diff --cached --name-status、项目策略要求的 secret-shape scan 和 intended scope 对账;最后验证用户 index digest 与 staged set 前后不变。普通 git diff --check 不能替代本门禁 |
| R3b | 执行 npm run test:audit,并完成 package completeness gate(description、keywords、repository、homepage、bugs、license、files/exports/bin、publishConfig、engines、plugin.json 元数据);包边界检查必须在构建/benchmark/codegen 完成后单独串行执行;公开打包脚本必须执行 PackagedScriptDependencyClosureGate,递归核对本地 require()、path.join(ROOT,'scripts',...) 或等价运行时脚本依赖都进入 tarball |
| R3c | 执行 RemoteCIParityPushGate:push / tag / release / publish 前先执行与远端 CI 同构的本地门禁;若项目存在远端 CI(如 GitHub Actions),确认目标 commit 对应 CI run 已完成且 conclusion 为 success;若存在独立消费者仓,再执行 ConsumerValidationEngineeringGate,证明 source event→consumer run、目标 SHA、身份新鲜度和全部适用分母 accepted;无远端 CI/消费者或无权限查询时必须写 N/A + skipReason,不得把普通测试通过替代 coverage、audit、examples、website、pack 或矩阵脚本 |
| R3e | Skill portfolio / V92:generate-skill-portfolio --check 必须在与 CI 同语义下通过——consumer 扫描仅用 git-tracked 文件;禁止在含 untracked 杂项的脏树按「全盘 walk」生成并提交 skills/portfolio.json;push 前建议 git worktree add --detach 于目标 SHA 复跑 --check |
| R3d | 执行 ReleaseCriticalPathBudgetGate、ValidationEvidenceReuseGate 与条件 ReleaseReworkIncidentGate;预算或复用不得削弱 immutable candidate、version、pack、registry 与 R7 证据 |
| R4 | 执行 npm pack --dry-run 与 npm publish --dry-run(遵循当前 publishConfig),并执行 NativeCommandExitCodeGate |
| R5 | 条件执行 pack install smoke,并执行 IsolatedConsumerCwdGate:显式 consumer manifest、真实 consumer cwd、source candidate identity 前后对账与真实命令退出码缺一不可 |
| R6 | commit/tag/push/publish 前输出确认,真实发布动作必须等待用户当前消息明确确认(SharedStateMutationGate / PI-119);一次历史发版授权不覆盖后续补丁 push;本会话自引入 CI 回归须先 OwnIntroducedRegressionSelfFixGate 本地修绿再进入 R6。负向:无用户确认却宣称「已 push」→ 违规;CI 自引入失败却「暂停不修」→ 违规(classifyPushAuthorizationSample / classifyOwnIntroducedRegressionSample) |
| R7 | 发布后验证 git tag、registry 版本、安装包边界和 node scripts/validate.js |
PublisherCredentialTopologyGate
首次 publish、repository/owner/package name/registry/publisher/auth mode 变化、迁移发布 workflow,或用户要求“参考成功项目发布”时,必须在 R0~R3c 之间冻结发布凭据拓扑;普通 patch 且拓扑明确未变时可记录 unchanged + evidence,不得静默跳过。
| 字段 | 要求 |
|---|
publisherIdentity | 实际发布主体/组织;不得包含 token 或 secret value |
repositoryIdentity | owner/repository、workflow 所在仓库与可访问边界 |
packageIdentity | package name、registry、package owner/access 与现存版本 |
authMode | trusted-publishing / workflow-secret / local-token / other |
secretTopology | 只记录 org/repo/environment/local scope、access policy 和传递/继承方式;禁止读取或复制 value |
workflowPermissions | OIDC/trusted publishing 所需最小权限;无 workflow 时 N/A + skipReason |
referenceEvidence | 参考成功仓库或最近成功 publish run 的身份、拓扑和结论;复制 YAML 不等于凭据等价 |
topologyParity | aligned / mismatch / unverifiable、阻断原因与恢复动作 |
GitHub Actions secrets 的 org/repo/environment scope、access policy 与 precedence 必须作为拓扑事实;reusable workflow 的显式 secret 传递或 secrets: inherit 只在平台允许的边界内成立。npm registry 采用 trusted publishing 时,按官方条件验证 OIDC、runner、Node/npm 与 id-token: write;其他 registry 不得机械套用 npm trusted publisher 结论。
ScopedRegistryResolutionGate
同一 scoped package 发布到多个 registry,或仓库/用户 .npmrc 已声明 @scope:registry 时,--registry=<target> 不能单独作为目标 registry 证据。每个 view/whoami/dry-run/publish/post-check 必须冻结 package scope、全局 registry、scope registry、userconfig 来源与命令级优先级,并以隔离 userconfig 或显式 --@scope:registry=<target> 绑定目标;双 registry 查询若返回完全相同版本集,先判定为可能被 scope 路由污染,禁止直接认定两个 registry 均已验证。
验证至少包含:默认配置下的污染复现、显式 scope override 后的目标 registry 结果、命令参数单测、真实退出码,以及不读取 token value 的 whoami / package existence / ownership 证据。npmjs primary 未通过身份与 scope 解析时,不得先发布 mirror 或创建 tag,避免半发布状态。
ReleaseAuthorityBeforeCompatibilityGate
| 字段 | 要求 |
|---|
publishedState | released / unreleased / unknown;用 tag、registry、release note、public docs 和目标 commit 交叉证明 |
consumerEvidence | 稳定外部消费者、已公开示例/类型/配置、安装或升级路径;本地 fixture 不等于稳定消费者 |
authoritySources | 每条发布或未发布结论的权威来源、时间/版本与冲突处理 |
decision | released → 兼容/迁移评估;unreleased 且无稳定消费者 → 直接收敛 canonical contract;unreleased 但有产品取舍 → 用户决策;unknown → 阻断兼容结论 |
不得因为字段或行为曾在未发布分支、草稿文档、内部 fixture 或本地历史包中出现,就自动引入 alias、fallback 或迁移层。需要保留未发布兼容行为时,必须记录真实消费者证据或用户明确产品决策。
ReleaseEfficiencyControlGate
CandidateFreezeGate
在首次完整 qualification 前形成 CandidateFreezeRecord:
| 字段 | 要求 |
|---|
candidateIdentity | commit/tree 或临时 staged snapshot digest、package version、pack-relevant inputs |
candidateGeneration | 每次冻结后 mutation 单调递增;旧 generation 证据不得冒充当前候选 |
authorizedScope | intended files、public surfaces、registry、target version 与明确排除项 |
allowedMutationClasses | release-blocker / P0-P1 / approved-scope / deferred;冻结后 deferred 不进入当前版本 |
evidenceDependencyGraph | mutation class → targeted/related/full/pack/CI/registry evidence 失效关系 |
freezeAt | 时间、owner 与基线来源 |
冻结后发生 mutation,必须先更新 generation、分类变更并使依赖证据 stale,再选择重跑路线。禁止一边 qualification 一边继续吸纳非阻断治理项。
发布收口若含多个 defect,冻结前还必须执行 ConvergenceFirstValidationV1:先冻结完整 issue set,批量实施所有修复,再统一 affected V2;禁止每修一项就跑 qualification。只有 affected 与 ECR 全绿后才能形成最终 CandidateFreezeRecord,并只执行一次 V3/full。
ReleaseCriticalPathBudgetGate
预算必须来自 Profile、最近可比较成功 release 或明确项目约束;字段为 baselineWindow / qualificationBudget / remoteCiBudget / publishPostcheckBudget / totalBudget / budgetAuthority / budgetMode。无可比较基线时只能 measure-only/advisory,不得把任意统一分钟数伪造成 blocking SLA。报告同时记录真实 elapsed、等待/执行拆分、streak reset 和超预算原因。
ValidationEvidenceReuseGate
每个复用决策记录 evidenceId / candidateIdentity / commandFingerprint / environmentIdentity / artifactDigest / freshness / dependencyCoverage / reuseDecision / invalidationReason。只有 immutable identity、命令/环境等价、制品一致、未过期且 dependency graph 未命中失效边时可复用。远端 CI attestation 可减少同一 SHA 的重复 qualification,但不能替代版本唯一性、staged candidate、pack metadata、registry identity、publish exitCode 或 R7。
ReleaseReworkIncidentGate
预算超限、candidate generation 连续重置达到项目阈值、同一 release blocker 重复逃逸或复用误判时,创建 ReleaseReworkIncident,记录 WorkUnit、双根因、失效证据、关键路径放大、冻结/降级动作和下一版本 prevention。当前修复后通过只关闭本 incident,不证明长期返工率已下降。
mismatch 或首次发布的 unverifiable 阻断 R6;不得通过读取 secret value 来证明等价。本地 token 路线只核对 auth/config 来源、发布身份与真实 dry-run/publish exitCode,不回显认证值。
安全边界
- 不主动索取 npm token、GitHub token 或私钥;若用户、registry、CI 或发布平台明确要求提供、写入或输出,按该显式策略处理并记录来源。
PublisherCredentialTopologyGate 只检查身份、scope、access、inheritance、permission 与成功证据;禁止读取或复制 secret value,也禁止把“workflow 相同”当作凭据等价。
- 不把
publish、push、tag 设计为无确认自动动作。
- CandidateDiff 默认使用临时
GIT_INDEX_FILE:先对临时 index 执行 git read-tree HEAD,再仅加入授权路径;命令结束后比较真实 .git/index digest 和 git diff --cached --name-status before/after。只有用户明确授权把候选写入真实 staged set 时才允许使用真实 index,且仍须先保存快照并在报告记录差异。
- tag 或 registry 已存在时必须阻断发布动作。
- 有远端 CI 的项目,tag / release / publish 前必须确认目标 commit 远端 CI 绿色;若无法查询,应阻断正式发布或由用户基于风险另行确认,报告中不得标为 ✅。
- 发布失败时写报告和恢复路径,不静默重试凭据相关动作。
- 若
publishConfig 指向 GitHub Packages / restricted access,README 与安装文档必须显式保留认证步骤,禁止再宣称“匿名直接安装”。
- 若
publishConfig 指向 GitHub Packages,test:audit 必须显式使用 https://registry.npmjs.org 作为 audit registry,避免 publish dry-run / prepublishOnly 继承 GitHub Packages 的非审计端点;这不等于跳过审计。
- 完整 release gate 必须由绑定
ValidationRunIdentityV1 的 VerificationExecutionLeaseV2 授权 ManagedValidationRunnerV2,在冻结候选上执行一次并持久化 ValidationExecutionTerminalProjectionV3;prepublishOnly 只校验该稳定终态与当前 candidate/HEAD/dirty scope、plan/budget、release-pipeline 角色、V3/release/full 范围及 hard deadline 完全一致,禁止在 npm lifecycle 中无授权地重复启动全量验证。V1 仅可读,终态缺失、失败、过期或候选漂移一律阻断 publish。
- V3/full 通过后必须执行
ExactReleaseArtifactV1:原生 npm pack 只运行一次生成精确 tarball,包外 ExactReleaseArtifactReceiptV1 绑定 source candidate、HEAD、release terminal receipt、npm name/version、tarball path、bytes、entry count、SHA-256 与 SHA-512/integrity。publish 前必须重新校验 receipt 与当前 tarball字节,再执行 npm publish <exact-tarball> --ignore-scripts --provenance --access public;禁止 bare directory publish、第二次 pack 或 publish lifecycle 重跑。registry 回读的 integrity/gitHead/provenance 必须与该 receipt 对账。
npm publish 与发布收尾是两个事务边界。publish 命令成功后必须立即形成并持久化 PublishedArtifactReceiptV1;registry 可见性等待、provenance 回读和 GitHub Release 创建只允许在 finalize 中幂等重试。registry 未返回可选 gitHead 时记录 WARN;返回且与候选不一致时 BLOCK;integrity、shasum 或 provenance 不一致时始终 BLOCK。finalize 超时不得再次 publish,只能携带既有发布回执走 finalize-only;启动新 publish 前若精确版本已存在,只有制品身份一致时才可跳过 publish 并转入 reconcile/finalize。
输出格式
## ReleaseVerification
| 阶段 | 状态 | 证据 |
|------|------|------|
| R0 | ✅/⚠️/N/A | |
| ReleaseAuthorityBeforeCompatibilityGate | ✅/⚠️/N/A | publishedState/consumerEvidence/authoritySources/decision |
| InteractiveSemanticProbe | ✅/⚠️/N/A | role/name/focusability/Enter-Space-Escape/focus recovery;截图不作为替代证据 |
| R1 | ✅/⚠️/N/A | |
| R2 | ✅/⚠️/N/A | |
| CandidateFreezeGate | ✅/⚠️/N/A | candidate identity/generation、authorized scope、allowed mutations、evidence dependency graph |
| R3 | ✅/⚠️/N/A | |
| CandidateDiffCompletenessGate | ✅/⚠️/N/A | inventory、staged snapshot、cached diff check、name-status review、secret-shape scan、intended scope match |
| R3b | ✅/⚠️/N/A | package completeness gate |
| R3c | ✅/⚠️/N/A | remote CI green |
| ReleaseCriticalPathBudgetGate | ✅/⚠️/N/A | baseline/budget/mode、elapsed、reset、decision |
| ValidationEvidenceReuseGate | ✅/⚠️/N/A | identity/command/environment/artifact/freshness/dependency/reuse |
| ReleaseReworkIncidentGate | ✅/⚠️/N/A | incident 或 N/A + threshold evidence |
| PublisherCredentialTopologyGate | ✅/⚠️/N/A | publisher/repository/package/auth/secret scope/workflow permission/reference run;不含 secret value |
| ScopedRegistryResolutionGate | ✅/⚠️/N/A | packageScope/globalRegistry/scopeRegistry/userconfig/commandOverride/resolvedTarget/independentChannelEvidence |
| ConsumerValidationEngineeringGate | ✅/⚠️/N/A | repository binding / source-consumer identity / denominators / packed artifact / cross-repo CI / freshness;无独立仓写 skipReason |
| R4 | ✅/⚠️/N/A | command/shell/cwd/exitCode |
| R5 | ✅/⚠️/N/A | command/shell/cwd/exitCode |
| IsolatedConsumerCwdGate | ✅/⚠️/N/A | explicit consumer manifest、consumer cwd、禁止 npm init --prefix、source identity/dirty/staged before-after |
| R6 | ✅/⚠️/N/A | |
| R7 | ✅/⚠️/N/A | |
报告要求
正式发布报告必须包含 ReleaseVerification R0~R7 状态、CandidateDiffCompletenessGate staged candidate 证据、R3b package completeness gate 证据、NativeCommandExitCodeGate 退出码证据、失败恢复路径、发布后 registry/tag 验收证据和关联 commit/tag。