release-skill 0.7.7 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -2
- package/.kimi-plugin/plugin.json +1 -1
- package/CHANGELOG.md +20 -0
- package/INSTALL.md +2 -2
- package/INSTALL.zh-CN.md +2 -2
- package/README.md +11 -11
- package/README.zh-CN.md +10 -10
- package/adapters/claude/.claude-plugin/marketplace.json +1 -1
- package/adapters/claude/.claude-plugin/plugin.json +1 -1
- package/adapters/claude/bin/release-skill.bundle.mjs +6 -2
- package/adapters/claude/schemas/.render-manifest.json +6 -6
- package/adapters/claude/schemas/release-run.schema.json +41 -1
- package/adapters/codex/.codex-plugin/plugin.json +2 -2
- package/adapters/codex/bin/release-skill.bundle.mjs +6 -2
- package/adapters/codex/schemas/.render-manifest.json +6 -6
- package/adapters/codex/schemas/release-run.schema.json +41 -1
- package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
- package/adapters/kimi/bin/release-skill.bundle.mjs +6 -2
- package/adapters/kimi/schemas/.render-manifest.json +6 -6
- package/adapters/kimi/schemas/release-run.schema.json +41 -1
- package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
- package/adapters/workbuddy/bin/release-skill.bundle.mjs +6 -2
- package/adapters/workbuddy/schemas/.render-manifest.json +6 -6
- package/adapters/workbuddy/schemas/release-run.schema.json +41 -1
- package/bin/release-skill.bundle.mjs +6 -2
- package/package.json +1 -1
- package/platform-manifest.json +2 -2
- package/references/.render-manifest.json +6 -6
- package/references/01-state-machine.md +2 -2
- package/references/06-adapter-contract.md +4 -3
- package/schemas/.render-manifest.json +6 -6
- package/schemas/release-run.schema.json +41 -1
- package/src/commands/publish.mjs +15 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"defaultPrompt": [
|
|
21
21
|
"Assess this project for release readiness.",
|
|
22
|
-
"Prepare a release plan for version 0.7.
|
|
22
|
+
"Prepare a release plan for version 0.7.8.",
|
|
23
23
|
"Help me understand the release workflow."
|
|
24
24
|
]
|
|
25
25
|
}
|
package/.kimi-plugin/plugin.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
<!-- release-skill:changelog:start version=0.7.8 locale=en baseline=sha256:058929eb1d0fa2abb8488f1b7f736da9046ac494c312057767d649f792bb9b81 -->
|
|
4
|
+
## [0.7.8] - 2026-08-24
|
|
5
|
+
|
|
6
|
+
v0.7.8 lets a fresh publish safely accept an npm version that already contains the exact frozen tarball, without executing npm publish again.
|
|
7
|
+
|
|
8
|
+
### Security
|
|
9
|
+
|
|
10
|
+
- **Fail-closed integrity check**: a different, missing, blank, or unparseable observed integrity stops the run before any adapter execute. The existing classifier, approval model, and forward-recovery state machine remain unchanged.
|
|
11
|
+
- **Checkpoint evidence**: a matching skipped npm checkpoint records only the observed integrity in `remoteRef.integrity`; package, version, registry, expected integrity, and tarball SHA-256 remain authoritative in the frozen plan.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **Existing npm version recovery**: when npm preflight finds the target version already published, publish compares the registry observation with the immutable plan. An exact match becomes `SKIPPED`, the npm execute count stays zero, and the remaining release actions continue.
|
|
16
|
+
|
|
17
|
+
### Upgrade Notes
|
|
18
|
+
|
|
19
|
+
No configuration or migration is required. Existing release-run files remain valid because `remoteRef.integrity` is optional.
|
|
20
|
+
<!-- release-skill:changelog:end version=0.7.8 locale=en -->
|
|
21
|
+
|
|
22
|
+
|
|
3
23
|
<!-- release-skill:changelog:start version=0.7.7 locale=en baseline=sha256:bdd8a5cd123e916f5581051c7138f56572b35b3640187551aca6faa453ea1a51 -->
|
|
4
24
|
## [0.7.7] - 2026-08-24
|
|
5
25
|
|
package/INSTALL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[简体中文](INSTALL.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
<!-- release-skill:release-version: 0.7.
|
|
5
|
+
<!-- release-skill:release-version: 0.7.8 -->
|
|
6
6
|
## Prerequisites
|
|
7
7
|
|
|
8
8
|
- Node.js 22.0.0 or later
|
|
@@ -114,7 +114,7 @@ tag pinned to the exact version (never the bare repository URL, which installs
|
|
|
114
114
|
the latest release or default branch), confirm the trust prompt, then reload:
|
|
115
115
|
|
|
116
116
|
```
|
|
117
|
-
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.7.
|
|
117
|
+
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.7.8
|
|
118
118
|
/plugins reload
|
|
119
119
|
```
|
|
120
120
|
|
package/INSTALL.zh-CN.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](INSTALL.md)
|
|
4
4
|
|
|
5
|
-
<!-- release-skill:release-version: 0.7.
|
|
5
|
+
<!-- release-skill:release-version: 0.7.8 -->
|
|
6
6
|
## 前置条件
|
|
7
7
|
|
|
8
8
|
- Node.js 22.0.0 或更高版本
|
|
@@ -104,7 +104,7 @@ Kimi Code 有交互式插件市场,但**没有可脚本化的非交互安装
|
|
|
104
104
|
(切勿使用裸仓库地址,它会安装最新 release 或默认分支),确认信任提示后重新加载:
|
|
105
105
|
|
|
106
106
|
```
|
|
107
|
-
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.7.
|
|
107
|
+
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.7.8
|
|
108
108
|
/plugins reload
|
|
109
109
|
```
|
|
110
110
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[简体中文](README.zh-CN.md) · Installation: [English](INSTALL.md) / [简体中文](INSTALL.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
<!-- release-skill:release-version: 0.7.
|
|
5
|
+
<!-- release-skill:release-version: 0.7.8 -->
|
|
6
6
|
Release preparation for Claude Code, CodeBuddy, WorkBuddy, Codex, and Kimi Code, with human-edited files kept intact.
|
|
7
7
|
|
|
8
8
|
release-skill helps a maintainer answer three questions: what will be released,
|
|
@@ -14,26 +14,26 @@ Setup surfaces only the deterministic `compactSummary` review view; the full
|
|
|
14
14
|
report stays in a temporary session directory.
|
|
15
15
|
|
|
16
16
|
<!-- release-skill:managed:start id=latest-release -->
|
|
17
|
-
**0.7.
|
|
17
|
+
**0.7.8** (2026-08-24)
|
|
18
18
|
|
|
19
|
-
v0.7.
|
|
19
|
+
v0.7.8 lets a fresh publish safely accept an npm version that already contains the exact frozen tarball, without executing npm publish again.
|
|
20
20
|
|
|
21
21
|
**Security**
|
|
22
22
|
|
|
23
|
-
- **
|
|
24
|
-
- **
|
|
23
|
+
- **Fail-closed integrity check**: a different, missing, blank, or unparseable observed integrity stops the run before any adapter execute. The existing classifier, approval model, and forward-recovery state machine remain unchanged.
|
|
24
|
+
- **Checkpoint evidence**: a matching skipped npm checkpoint records only the observed integrity in `remoteRef.integrity`; package, version, registry, expected integrity, and tarball SHA-256 remain authoritative in the frozen plan.
|
|
25
25
|
|
|
26
|
-
**
|
|
26
|
+
**Fixed**
|
|
27
27
|
|
|
28
|
-
- **
|
|
28
|
+
- **Existing npm version recovery**: when npm preflight finds the target version already published, publish compares the registry observation with the immutable plan. An exact match becomes `SKIPPED`, the npm execute count stays zero, and the remaining release actions continue.
|
|
29
29
|
|
|
30
30
|
**Upgrade Notes**
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
No configuration or migration is required. Existing release-run files remain valid because `remoteRef.integrity` is optional.
|
|
33
33
|
<!-- release-skill:managed:end id=latest-release -->
|
|
34
34
|
|
|
35
35
|
<!-- release-skill:capability:external-write-boundary -->
|
|
36
|
-
> **Current boundary:** v0.7.
|
|
36
|
+
> **Current boundary:** v0.7.8 is the current source candidate; v0.7.7 remains
|
|
37
37
|
> the latest published release. v0.4.1 was an earlier published milestone;
|
|
38
38
|
> v0.2.2 previously held published status before the platform verification
|
|
39
39
|
> convergence fix was added.
|
|
@@ -53,8 +53,8 @@ v0.7.7 can publish a small public source-authority receipt that binds an exact s
|
|
|
53
53
|
> publish global preflight.
|
|
54
54
|
|
|
55
55
|
<!-- release-skill:capability:safe-first-command -->
|
|
56
|
-
> **Production path verified since the v0.1.1 milestone; v0.7.
|
|
57
|
-
> source candidate and v0.7.
|
|
56
|
+
> **Production path verified since the v0.1.1 milestone; v0.7.8 is the current
|
|
57
|
+
> source candidate and v0.7.7 is the latest published release.** The npm-installed CLI is the supported user entry. Source checkout
|
|
58
58
|
> is the development/contributor fallback.
|
|
59
59
|
>
|
|
60
60
|
> **Start here:**
|
package/README.zh-CN.md
CHANGED
|
@@ -2,32 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) · 安装指南:[中文](INSTALL.zh-CN.md) / [English](INSTALL.md)
|
|
4
4
|
|
|
5
|
-
<!-- release-skill:release-version: 0.7.
|
|
5
|
+
<!-- release-skill:release-version: 0.7.8 -->
|
|
6
6
|
面向 Claude Code、CodeBuddy、WorkBuddy、Codex 和 Kimi Code 的发布准备工具,完整保留人工维护的文件内容。
|
|
7
7
|
|
|
8
8
|
release-skill 帮助维护者回答三个问题:准备发布什么、还有哪些检查未通过、最终发布的内容是什么。它不重新生成、也不回写项目源文件。`prepare` 把每个配置的公开文件复制到隔离快照并验证字节——先冻结并供人工审阅,再从同一份冻结产物发布。`setup` 只显示确定性的 `compactSummary` 审阅视图,完整报告保留在临时会话目录中。
|
|
9
9
|
|
|
10
10
|
<!-- release-skill:managed:start id=latest-release -->
|
|
11
|
-
**0.7.
|
|
11
|
+
**0.7.8** (2026-08-24)
|
|
12
12
|
|
|
13
|
-
v0.7.
|
|
13
|
+
v0.7.8 允许全新的发布安全接受已经包含同一份冻结 tarball 的 npm 版本,不会再次执行 npm publish。
|
|
14
14
|
|
|
15
15
|
**安全**
|
|
16
16
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
17
|
+
- **integrity 失败关闭**:观察到的 integrity 不同、缺失、空白或无法解析时,run 会在任何 Adapter execute 前停止。现有 classifier、批准模型和前向恢复状态机保持不变。
|
|
18
|
+
- **检查点证据**:npm 检查点一致并跳过时,只在 `remoteRef.integrity` 记录本次观察到的 integrity;包名、版本、registry、预期 integrity 和 tarball SHA-256 继续以冻结计划为准。
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
**修复**
|
|
21
21
|
|
|
22
|
-
-
|
|
22
|
+
- **已存在 npm 版本的恢复**:npm preflight 发现目标版本已经发布后,publish 会把 registry observation 与不可变计划逐项比较。完全一致时,npm 检查点进入 `SKIPPED`,npm execute 次数保持为零,其他发布动作继续执行。
|
|
23
23
|
|
|
24
24
|
**升级说明**
|
|
25
25
|
|
|
26
|
-
`
|
|
26
|
+
无需修改配置或迁移。`remoteRef.integrity` 是可选字段,已有 release-run 文件继续有效。
|
|
27
27
|
<!-- release-skill:managed:end id=latest-release -->
|
|
28
28
|
|
|
29
29
|
<!-- release-skill:capability:external-write-boundary -->
|
|
30
|
-
> **当前边界:** v0.7.
|
|
30
|
+
> **当前边界:** v0.7.8 是当前源码候选,v0.7.7 是最新已发布版本。v0.4.1 是更早的已发布里程碑(v0.2.2 曾处于已发布状态,后因平台验证收敛修复而更新)。
|
|
31
31
|
> v0.1.1 已完成 GitHub 与 npm 的
|
|
32
32
|
> 真实生产发布,是首次生产验证的历史里程碑,并从冻结 Git ref 完成精确 npm
|
|
33
33
|
> 安装及 Claude/Codex 消费者安装验证;"当前发布版本"与"首次生产验证里程碑"
|
|
@@ -40,7 +40,7 @@ v0.7.7 可以发布精简的公开源码权威收据,把精确的源码仓库
|
|
|
40
40
|
> 远端唯一性检查在 `publish` 全局预检执行。
|
|
41
41
|
|
|
42
42
|
<!-- release-skill:capability:safe-first-command -->
|
|
43
|
-
> **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.7.
|
|
43
|
+
> **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.7.8 是当前源码候选,v0.7.7 是最新已发布版本。**
|
|
44
44
|
> npm 安装的 CLI 是受支持的用户入口;源码 checkout 保留为开发/贡献者路径。
|
|
45
45
|
>
|
|
46
46
|
> **第一条命令:**
|
|
@@ -9,9 +9,9 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.8"});
|
|
13
13
|
// Build-time source digest for the BUNDLE_STALE freshness gate (see above).
|
|
14
|
-
const __bundleSourceDigest = "
|
|
14
|
+
const __bundleSourceDigest = "33dc18dc83ac5f6211859bd64e1b323b9166acf7307e5b8748ea1d2d99376df2";
|
|
15
15
|
|
|
16
16
|
var __create = Object.create;
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
@@ -103001,6 +103001,7 @@ async function publishRelease(options) {
|
|
|
103001
103001
|
status: checkpoint.status === "SUCCEEDED" ? "succeeded" : checkpoint.status === "FAILED" ? "failed" : checkpoint.status === "UNCERTAIN" ? "uncertain" : checkpoint.status === "SKIPPED" ? "skipped" : checkpoint.status === "DEFERRED" ? "deferred" : "pending",
|
|
103002
103002
|
...checkpoint.preObserve ? { preObserve: checkpoint.preObserve } : {},
|
|
103003
103003
|
...checkpoint.postObserve ? { postObserve: checkpoint.postObserve } : {},
|
|
103004
|
+
...checkpoint.remoteRef ? { remoteRef: checkpoint.remoteRef } : {},
|
|
103004
103005
|
...checkpoint.error ? { error: { code: "GATE_FAILED", message: checkpoint.error } } : {},
|
|
103005
103006
|
...checkpoint.reason === CONSUMER_VERIFICATION_DEFERRED ? { reason: CONSUMER_VERIFICATION_DEFERRED, phase: checkpoint.phase ?? "post-publish-verification" } : {}
|
|
103006
103007
|
})),
|
|
@@ -103080,6 +103081,9 @@ async function publishRelease(options) {
|
|
|
103080
103081
|
checkpoint.error = result.error;
|
|
103081
103082
|
if (result.preObserve) checkpoint.preObserve = result.preObserve;
|
|
103082
103083
|
if (result.postObserve) checkpoint.postObserve = result.postObserve;
|
|
103084
|
+
if (action.type === "npm-publish" && result.status === "SKIPPED" && result.preObserve === PRE_OBSERVE.CONSISTENT && typeof result.observation?.integrity === "string" && /^sha512-[A-Za-z0-9+/]+={0,2}$/.test(result.observation.integrity)) {
|
|
103085
|
+
checkpoint.remoteRef = { integrity: result.observation.integrity };
|
|
103086
|
+
}
|
|
103083
103087
|
action.status = result.status;
|
|
103084
103088
|
await evidence.append({
|
|
103085
103089
|
phase: "checkpoint",
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"bytes": 1744
|
|
27
27
|
},
|
|
28
28
|
"release-plan.schema.json": {
|
|
29
|
-
"digest": "
|
|
30
|
-
"bytes":
|
|
29
|
+
"digest": "3d24cb908cdfbfd5d89551b7c6fed5140f6f1448b9920f114264291ca4cf1c52",
|
|
30
|
+
"bytes": 55905
|
|
31
31
|
},
|
|
32
32
|
"release-project.schema.json": {
|
|
33
|
-
"digest": "
|
|
34
|
-
"bytes":
|
|
33
|
+
"digest": "b0ba3c46692622f734a80d3f4e3904180bbfd1096ca2d9b6d6fd957917e96f73",
|
|
34
|
+
"bytes": 47688
|
|
35
35
|
},
|
|
36
36
|
"release-run.schema.json": {
|
|
37
|
-
"digest": "
|
|
38
|
-
"bytes":
|
|
37
|
+
"digest": "4a041b8f6488e7d61b7eb271ebdbc2e043731df41c4437783ef63e77f664c192",
|
|
38
|
+
"bytes": 19002
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -199,6 +199,11 @@
|
|
|
199
199
|
},
|
|
200
200
|
"url": {
|
|
201
201
|
"type": "string"
|
|
202
|
+
},
|
|
203
|
+
"integrity": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"pattern": "^sha512-[A-Za-z0-9+/]{86}==$",
|
|
206
|
+
"description": "Observed npm dist.integrity when an already-consistent npm publish is skipped"
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
},
|
|
@@ -280,7 +285,42 @@
|
|
|
280
285
|
"minimum": 0,
|
|
281
286
|
"description": "写入目标的载荷文件数"
|
|
282
287
|
}
|
|
283
|
-
}
|
|
288
|
+
},
|
|
289
|
+
"allOf": [
|
|
290
|
+
{
|
|
291
|
+
"if": {
|
|
292
|
+
"properties": {
|
|
293
|
+
"remoteRef": {
|
|
294
|
+
"type": "object",
|
|
295
|
+
"required": [
|
|
296
|
+
"integrity"
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"required": [
|
|
301
|
+
"remoteRef"
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
"then": {
|
|
305
|
+
"properties": {
|
|
306
|
+
"actionType": {
|
|
307
|
+
"const": "npm-publish"
|
|
308
|
+
},
|
|
309
|
+
"status": {
|
|
310
|
+
"const": "skipped"
|
|
311
|
+
},
|
|
312
|
+
"preObserve": {
|
|
313
|
+
"const": "CONSISTENT"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
"required": [
|
|
317
|
+
"actionType",
|
|
318
|
+
"status",
|
|
319
|
+
"preObserve"
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
]
|
|
284
324
|
}
|
|
285
325
|
},
|
|
286
326
|
"sourceAuthorityReceipts": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"defaultPrompt": [
|
|
21
21
|
"Assess this project for release readiness.",
|
|
22
|
-
"Prepare a release plan for version 0.7.
|
|
22
|
+
"Prepare a release plan for version 0.7.8.",
|
|
23
23
|
"Help me understand the release workflow."
|
|
24
24
|
]
|
|
25
25
|
}
|
|
@@ -9,9 +9,9 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.8"});
|
|
13
13
|
// Build-time source digest for the BUNDLE_STALE freshness gate (see above).
|
|
14
|
-
const __bundleSourceDigest = "
|
|
14
|
+
const __bundleSourceDigest = "33dc18dc83ac5f6211859bd64e1b323b9166acf7307e5b8748ea1d2d99376df2";
|
|
15
15
|
|
|
16
16
|
var __create = Object.create;
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
@@ -103001,6 +103001,7 @@ async function publishRelease(options) {
|
|
|
103001
103001
|
status: checkpoint.status === "SUCCEEDED" ? "succeeded" : checkpoint.status === "FAILED" ? "failed" : checkpoint.status === "UNCERTAIN" ? "uncertain" : checkpoint.status === "SKIPPED" ? "skipped" : checkpoint.status === "DEFERRED" ? "deferred" : "pending",
|
|
103002
103002
|
...checkpoint.preObserve ? { preObserve: checkpoint.preObserve } : {},
|
|
103003
103003
|
...checkpoint.postObserve ? { postObserve: checkpoint.postObserve } : {},
|
|
103004
|
+
...checkpoint.remoteRef ? { remoteRef: checkpoint.remoteRef } : {},
|
|
103004
103005
|
...checkpoint.error ? { error: { code: "GATE_FAILED", message: checkpoint.error } } : {},
|
|
103005
103006
|
...checkpoint.reason === CONSUMER_VERIFICATION_DEFERRED ? { reason: CONSUMER_VERIFICATION_DEFERRED, phase: checkpoint.phase ?? "post-publish-verification" } : {}
|
|
103006
103007
|
})),
|
|
@@ -103080,6 +103081,9 @@ async function publishRelease(options) {
|
|
|
103080
103081
|
checkpoint.error = result.error;
|
|
103081
103082
|
if (result.preObserve) checkpoint.preObserve = result.preObserve;
|
|
103082
103083
|
if (result.postObserve) checkpoint.postObserve = result.postObserve;
|
|
103084
|
+
if (action.type === "npm-publish" && result.status === "SKIPPED" && result.preObserve === PRE_OBSERVE.CONSISTENT && typeof result.observation?.integrity === "string" && /^sha512-[A-Za-z0-9+/]+={0,2}$/.test(result.observation.integrity)) {
|
|
103085
|
+
checkpoint.remoteRef = { integrity: result.observation.integrity };
|
|
103086
|
+
}
|
|
103083
103087
|
action.status = result.status;
|
|
103084
103088
|
await evidence.append({
|
|
103085
103089
|
phase: "checkpoint",
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"bytes": 1744
|
|
27
27
|
},
|
|
28
28
|
"release-plan.schema.json": {
|
|
29
|
-
"digest": "
|
|
30
|
-
"bytes":
|
|
29
|
+
"digest": "3d24cb908cdfbfd5d89551b7c6fed5140f6f1448b9920f114264291ca4cf1c52",
|
|
30
|
+
"bytes": 55905
|
|
31
31
|
},
|
|
32
32
|
"release-project.schema.json": {
|
|
33
|
-
"digest": "
|
|
34
|
-
"bytes":
|
|
33
|
+
"digest": "b0ba3c46692622f734a80d3f4e3904180bbfd1096ca2d9b6d6fd957917e96f73",
|
|
34
|
+
"bytes": 47688
|
|
35
35
|
},
|
|
36
36
|
"release-run.schema.json": {
|
|
37
|
-
"digest": "
|
|
38
|
-
"bytes":
|
|
37
|
+
"digest": "4a041b8f6488e7d61b7eb271ebdbc2e043731df41c4437783ef63e77f664c192",
|
|
38
|
+
"bytes": 19002
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -199,6 +199,11 @@
|
|
|
199
199
|
},
|
|
200
200
|
"url": {
|
|
201
201
|
"type": "string"
|
|
202
|
+
},
|
|
203
|
+
"integrity": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"pattern": "^sha512-[A-Za-z0-9+/]{86}==$",
|
|
206
|
+
"description": "Observed npm dist.integrity when an already-consistent npm publish is skipped"
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
},
|
|
@@ -280,7 +285,42 @@
|
|
|
280
285
|
"minimum": 0,
|
|
281
286
|
"description": "写入目标的载荷文件数"
|
|
282
287
|
}
|
|
283
|
-
}
|
|
288
|
+
},
|
|
289
|
+
"allOf": [
|
|
290
|
+
{
|
|
291
|
+
"if": {
|
|
292
|
+
"properties": {
|
|
293
|
+
"remoteRef": {
|
|
294
|
+
"type": "object",
|
|
295
|
+
"required": [
|
|
296
|
+
"integrity"
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"required": [
|
|
301
|
+
"remoteRef"
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
"then": {
|
|
305
|
+
"properties": {
|
|
306
|
+
"actionType": {
|
|
307
|
+
"const": "npm-publish"
|
|
308
|
+
},
|
|
309
|
+
"status": {
|
|
310
|
+
"const": "skipped"
|
|
311
|
+
},
|
|
312
|
+
"preObserve": {
|
|
313
|
+
"const": "CONSISTENT"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
"required": [
|
|
317
|
+
"actionType",
|
|
318
|
+
"status",
|
|
319
|
+
"preObserve"
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
]
|
|
284
324
|
}
|
|
285
325
|
},
|
|
286
326
|
"sourceAuthorityReceipts": {
|
|
@@ -9,9 +9,9 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.8"});
|
|
13
13
|
// Build-time source digest for the BUNDLE_STALE freshness gate (see above).
|
|
14
|
-
const __bundleSourceDigest = "
|
|
14
|
+
const __bundleSourceDigest = "33dc18dc83ac5f6211859bd64e1b323b9166acf7307e5b8748ea1d2d99376df2";
|
|
15
15
|
|
|
16
16
|
var __create = Object.create;
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
@@ -103001,6 +103001,7 @@ async function publishRelease(options) {
|
|
|
103001
103001
|
status: checkpoint.status === "SUCCEEDED" ? "succeeded" : checkpoint.status === "FAILED" ? "failed" : checkpoint.status === "UNCERTAIN" ? "uncertain" : checkpoint.status === "SKIPPED" ? "skipped" : checkpoint.status === "DEFERRED" ? "deferred" : "pending",
|
|
103002
103002
|
...checkpoint.preObserve ? { preObserve: checkpoint.preObserve } : {},
|
|
103003
103003
|
...checkpoint.postObserve ? { postObserve: checkpoint.postObserve } : {},
|
|
103004
|
+
...checkpoint.remoteRef ? { remoteRef: checkpoint.remoteRef } : {},
|
|
103004
103005
|
...checkpoint.error ? { error: { code: "GATE_FAILED", message: checkpoint.error } } : {},
|
|
103005
103006
|
...checkpoint.reason === CONSUMER_VERIFICATION_DEFERRED ? { reason: CONSUMER_VERIFICATION_DEFERRED, phase: checkpoint.phase ?? "post-publish-verification" } : {}
|
|
103006
103007
|
})),
|
|
@@ -103080,6 +103081,9 @@ async function publishRelease(options) {
|
|
|
103080
103081
|
checkpoint.error = result.error;
|
|
103081
103082
|
if (result.preObserve) checkpoint.preObserve = result.preObserve;
|
|
103082
103083
|
if (result.postObserve) checkpoint.postObserve = result.postObserve;
|
|
103084
|
+
if (action.type === "npm-publish" && result.status === "SKIPPED" && result.preObserve === PRE_OBSERVE.CONSISTENT && typeof result.observation?.integrity === "string" && /^sha512-[A-Za-z0-9+/]+={0,2}$/.test(result.observation.integrity)) {
|
|
103085
|
+
checkpoint.remoteRef = { integrity: result.observation.integrity };
|
|
103086
|
+
}
|
|
103083
103087
|
action.status = result.status;
|
|
103084
103088
|
await evidence.append({
|
|
103085
103089
|
phase: "checkpoint",
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"bytes": 1744
|
|
27
27
|
},
|
|
28
28
|
"release-plan.schema.json": {
|
|
29
|
-
"digest": "
|
|
30
|
-
"bytes":
|
|
29
|
+
"digest": "3d24cb908cdfbfd5d89551b7c6fed5140f6f1448b9920f114264291ca4cf1c52",
|
|
30
|
+
"bytes": 55905
|
|
31
31
|
},
|
|
32
32
|
"release-project.schema.json": {
|
|
33
|
-
"digest": "
|
|
34
|
-
"bytes":
|
|
33
|
+
"digest": "b0ba3c46692622f734a80d3f4e3904180bbfd1096ca2d9b6d6fd957917e96f73",
|
|
34
|
+
"bytes": 47688
|
|
35
35
|
},
|
|
36
36
|
"release-run.schema.json": {
|
|
37
|
-
"digest": "
|
|
38
|
-
"bytes":
|
|
37
|
+
"digest": "4a041b8f6488e7d61b7eb271ebdbc2e043731df41c4437783ef63e77f664c192",
|
|
38
|
+
"bytes": 19002
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -199,6 +199,11 @@
|
|
|
199
199
|
},
|
|
200
200
|
"url": {
|
|
201
201
|
"type": "string"
|
|
202
|
+
},
|
|
203
|
+
"integrity": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"pattern": "^sha512-[A-Za-z0-9+/]{86}==$",
|
|
206
|
+
"description": "Observed npm dist.integrity when an already-consistent npm publish is skipped"
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
},
|
|
@@ -280,7 +285,42 @@
|
|
|
280
285
|
"minimum": 0,
|
|
281
286
|
"description": "写入目标的载荷文件数"
|
|
282
287
|
}
|
|
283
|
-
}
|
|
288
|
+
},
|
|
289
|
+
"allOf": [
|
|
290
|
+
{
|
|
291
|
+
"if": {
|
|
292
|
+
"properties": {
|
|
293
|
+
"remoteRef": {
|
|
294
|
+
"type": "object",
|
|
295
|
+
"required": [
|
|
296
|
+
"integrity"
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"required": [
|
|
301
|
+
"remoteRef"
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
"then": {
|
|
305
|
+
"properties": {
|
|
306
|
+
"actionType": {
|
|
307
|
+
"const": "npm-publish"
|
|
308
|
+
},
|
|
309
|
+
"status": {
|
|
310
|
+
"const": "skipped"
|
|
311
|
+
},
|
|
312
|
+
"preObserve": {
|
|
313
|
+
"const": "CONSISTENT"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
"required": [
|
|
317
|
+
"actionType",
|
|
318
|
+
"status",
|
|
319
|
+
"preObserve"
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
]
|
|
284
324
|
}
|
|
285
325
|
},
|
|
286
326
|
"sourceAuthorityReceipts": {
|
|
@@ -9,9 +9,9 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.8"});
|
|
13
13
|
// Build-time source digest for the BUNDLE_STALE freshness gate (see above).
|
|
14
|
-
const __bundleSourceDigest = "
|
|
14
|
+
const __bundleSourceDigest = "33dc18dc83ac5f6211859bd64e1b323b9166acf7307e5b8748ea1d2d99376df2";
|
|
15
15
|
|
|
16
16
|
var __create = Object.create;
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
@@ -103001,6 +103001,7 @@ async function publishRelease(options) {
|
|
|
103001
103001
|
status: checkpoint.status === "SUCCEEDED" ? "succeeded" : checkpoint.status === "FAILED" ? "failed" : checkpoint.status === "UNCERTAIN" ? "uncertain" : checkpoint.status === "SKIPPED" ? "skipped" : checkpoint.status === "DEFERRED" ? "deferred" : "pending",
|
|
103002
103002
|
...checkpoint.preObserve ? { preObserve: checkpoint.preObserve } : {},
|
|
103003
103003
|
...checkpoint.postObserve ? { postObserve: checkpoint.postObserve } : {},
|
|
103004
|
+
...checkpoint.remoteRef ? { remoteRef: checkpoint.remoteRef } : {},
|
|
103004
103005
|
...checkpoint.error ? { error: { code: "GATE_FAILED", message: checkpoint.error } } : {},
|
|
103005
103006
|
...checkpoint.reason === CONSUMER_VERIFICATION_DEFERRED ? { reason: CONSUMER_VERIFICATION_DEFERRED, phase: checkpoint.phase ?? "post-publish-verification" } : {}
|
|
103006
103007
|
})),
|
|
@@ -103080,6 +103081,9 @@ async function publishRelease(options) {
|
|
|
103080
103081
|
checkpoint.error = result.error;
|
|
103081
103082
|
if (result.preObserve) checkpoint.preObserve = result.preObserve;
|
|
103082
103083
|
if (result.postObserve) checkpoint.postObserve = result.postObserve;
|
|
103084
|
+
if (action.type === "npm-publish" && result.status === "SKIPPED" && result.preObserve === PRE_OBSERVE.CONSISTENT && typeof result.observation?.integrity === "string" && /^sha512-[A-Za-z0-9+/]+={0,2}$/.test(result.observation.integrity)) {
|
|
103085
|
+
checkpoint.remoteRef = { integrity: result.observation.integrity };
|
|
103086
|
+
}
|
|
103083
103087
|
action.status = result.status;
|
|
103084
103088
|
await evidence.append({
|
|
103085
103089
|
phase: "checkpoint",
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"bytes": 1744
|
|
27
27
|
},
|
|
28
28
|
"release-plan.schema.json": {
|
|
29
|
-
"digest": "
|
|
30
|
-
"bytes":
|
|
29
|
+
"digest": "3d24cb908cdfbfd5d89551b7c6fed5140f6f1448b9920f114264291ca4cf1c52",
|
|
30
|
+
"bytes": 55905
|
|
31
31
|
},
|
|
32
32
|
"release-project.schema.json": {
|
|
33
|
-
"digest": "
|
|
34
|
-
"bytes":
|
|
33
|
+
"digest": "b0ba3c46692622f734a80d3f4e3904180bbfd1096ca2d9b6d6fd957917e96f73",
|
|
34
|
+
"bytes": 47688
|
|
35
35
|
},
|
|
36
36
|
"release-run.schema.json": {
|
|
37
|
-
"digest": "
|
|
38
|
-
"bytes":
|
|
37
|
+
"digest": "4a041b8f6488e7d61b7eb271ebdbc2e043731df41c4437783ef63e77f664c192",
|
|
38
|
+
"bytes": 19002
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -199,6 +199,11 @@
|
|
|
199
199
|
},
|
|
200
200
|
"url": {
|
|
201
201
|
"type": "string"
|
|
202
|
+
},
|
|
203
|
+
"integrity": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"pattern": "^sha512-[A-Za-z0-9+/]{86}==$",
|
|
206
|
+
"description": "Observed npm dist.integrity when an already-consistent npm publish is skipped"
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
},
|
|
@@ -280,7 +285,42 @@
|
|
|
280
285
|
"minimum": 0,
|
|
281
286
|
"description": "写入目标的载荷文件数"
|
|
282
287
|
}
|
|
283
|
-
}
|
|
288
|
+
},
|
|
289
|
+
"allOf": [
|
|
290
|
+
{
|
|
291
|
+
"if": {
|
|
292
|
+
"properties": {
|
|
293
|
+
"remoteRef": {
|
|
294
|
+
"type": "object",
|
|
295
|
+
"required": [
|
|
296
|
+
"integrity"
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"required": [
|
|
301
|
+
"remoteRef"
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
"then": {
|
|
305
|
+
"properties": {
|
|
306
|
+
"actionType": {
|
|
307
|
+
"const": "npm-publish"
|
|
308
|
+
},
|
|
309
|
+
"status": {
|
|
310
|
+
"const": "skipped"
|
|
311
|
+
},
|
|
312
|
+
"preObserve": {
|
|
313
|
+
"const": "CONSISTENT"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
"required": [
|
|
317
|
+
"actionType",
|
|
318
|
+
"status",
|
|
319
|
+
"preObserve"
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
]
|
|
284
324
|
}
|
|
285
325
|
},
|
|
286
326
|
"sourceAuthorityReceipts": {
|
|
@@ -9,9 +9,9 @@ const __bundlePkgRoot = __bundleResolve(__bundleDirname(__bundleFileURLToPath(im
|
|
|
9
9
|
// Provide a real require() for CJS packages bundled into ESM (e.g. yaml, ajv).
|
|
10
10
|
const __bundleRealRequire = __bundleCreateRequire(import.meta.url);
|
|
11
11
|
// Package identity injected at build time — closure-independent --version probe.
|
|
12
|
-
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.7.8"});
|
|
13
13
|
// Build-time source digest for the BUNDLE_STALE freshness gate (see above).
|
|
14
|
-
const __bundleSourceDigest = "
|
|
14
|
+
const __bundleSourceDigest = "33dc18dc83ac5f6211859bd64e1b323b9166acf7307e5b8748ea1d2d99376df2";
|
|
15
15
|
|
|
16
16
|
var __create = Object.create;
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
@@ -103001,6 +103001,7 @@ async function publishRelease(options) {
|
|
|
103001
103001
|
status: checkpoint.status === "SUCCEEDED" ? "succeeded" : checkpoint.status === "FAILED" ? "failed" : checkpoint.status === "UNCERTAIN" ? "uncertain" : checkpoint.status === "SKIPPED" ? "skipped" : checkpoint.status === "DEFERRED" ? "deferred" : "pending",
|
|
103002
103002
|
...checkpoint.preObserve ? { preObserve: checkpoint.preObserve } : {},
|
|
103003
103003
|
...checkpoint.postObserve ? { postObserve: checkpoint.postObserve } : {},
|
|
103004
|
+
...checkpoint.remoteRef ? { remoteRef: checkpoint.remoteRef } : {},
|
|
103004
103005
|
...checkpoint.error ? { error: { code: "GATE_FAILED", message: checkpoint.error } } : {},
|
|
103005
103006
|
...checkpoint.reason === CONSUMER_VERIFICATION_DEFERRED ? { reason: CONSUMER_VERIFICATION_DEFERRED, phase: checkpoint.phase ?? "post-publish-verification" } : {}
|
|
103006
103007
|
})),
|
|
@@ -103080,6 +103081,9 @@ async function publishRelease(options) {
|
|
|
103080
103081
|
checkpoint.error = result.error;
|
|
103081
103082
|
if (result.preObserve) checkpoint.preObserve = result.preObserve;
|
|
103082
103083
|
if (result.postObserve) checkpoint.postObserve = result.postObserve;
|
|
103084
|
+
if (action.type === "npm-publish" && result.status === "SKIPPED" && result.preObserve === PRE_OBSERVE.CONSISTENT && typeof result.observation?.integrity === "string" && /^sha512-[A-Za-z0-9+/]+={0,2}$/.test(result.observation.integrity)) {
|
|
103085
|
+
checkpoint.remoteRef = { integrity: result.observation.integrity };
|
|
103086
|
+
}
|
|
103083
103087
|
action.status = result.status;
|
|
103084
103088
|
await evidence.append({
|
|
103085
103089
|
phase: "checkpoint",
|
package/package.json
CHANGED
package/platform-manifest.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
3
|
"platformId": "release-skill",
|
|
4
4
|
"platformName": "release-skill Plugin Platform",
|
|
5
|
-
"version": "0.7.
|
|
5
|
+
"version": "0.7.8",
|
|
6
6
|
"logicalRoot": "skills-src/",
|
|
7
7
|
"logicalRootDigest": "b261a4cc49e6dc52dabddb083c22e414902fb269d5879ad01ef8146ceffd7bc7",
|
|
8
8
|
"projectionDigest": "6629de035a25005fd4676b09a0526a46f992a33d974cadd542b0c964d7f906ff",
|
|
9
|
-
"projectionId": "release-skill:platform:0.7.
|
|
9
|
+
"projectionId": "release-skill:platform:0.7.8",
|
|
10
10
|
"manifestRequired": true,
|
|
11
11
|
"projectionSources": {
|
|
12
12
|
"skills-src-root": {
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"bytes": 6335
|
|
7
7
|
},
|
|
8
8
|
"01-state-machine.md": {
|
|
9
|
-
"digest": "
|
|
10
|
-
"bytes":
|
|
9
|
+
"digest": "5afc8e9c29c0d5fb0de0db8b248bbb812fc715af185ac594a172fe68d9a24fed",
|
|
10
|
+
"bytes": 12617
|
|
11
11
|
},
|
|
12
12
|
"02-project-config.md": {
|
|
13
|
-
"digest": "
|
|
14
|
-
"bytes":
|
|
13
|
+
"digest": "09e3c470dea54fe9437528620cc169596e75b5162e137683923347c9cb3702a6",
|
|
14
|
+
"bytes": 23167
|
|
15
15
|
},
|
|
16
16
|
"03-readme-quality.md": {
|
|
17
17
|
"digest": "d74e41052592443ebbd450d0ace5f9b9b19c7a94db50f952b17c1c5a4c5dc230",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"bytes": 12014
|
|
27
27
|
},
|
|
28
28
|
"06-adapter-contract.md": {
|
|
29
|
-
"digest": "
|
|
30
|
-
"bytes":
|
|
29
|
+
"digest": "fd58e8a438aaa9a7a4a939ac190dbdd5d11c3fcaca08feaced4a612a6d6dcf3f",
|
|
30
|
+
"bytes": 19206
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -148,7 +148,7 @@ postPublish hooks 分两个阶段,各自对应独立的 distribute run:
|
|
|
148
148
|
|
|
149
149
|
工作区基线(Git tree hash、workspace digest、捕获时间)与生命周期状态(计划 status、createdAt、action 运行时 status)是**记录层审计数据**:继续写入计划与审批文件以备查,但不参与 planVersion 2 的 digest、不使批准失效。publish/reconcile 检测到基线漂移时记录 warning 级证据事件并继续执行,产物完整性由发布前的冻结产物重验兜底。planVersion 1(旧版)计划维持旧规则:Git tree hash 与 workspace digest 变化同样使批准失效,基线漂移硬失败(BASELINE_CHANGED)。
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
远端冲突状态不在 approval 绑定字段中。远端对象已存在但与冻结计划完全一致时,`publish`/`reconcile` 把对应检查点标为 `SKIPPED`;存在且不一致,或无法可靠判断时,preflight 阶段阻断执行并要求人工决策。npm 版本只有在观察到有效且与冻结计划相同的 integrity 时才能进入 `SKIPPED`;integrity 缺失、空白、无法解析或不同都在任何 Adapter execute 前失败关闭。
|
|
152
152
|
|
|
153
153
|
失效后系统回退到 PREPARED 状态,要求重新批准。
|
|
154
154
|
|
|
@@ -161,7 +161,7 @@ postPublish hooks 分两个阶段,各自对应独立的 distribute run:
|
|
|
161
161
|
3. 创建并推送签名或可追溯 tag。
|
|
162
162
|
4. 发布 npm 包。
|
|
163
163
|
5. 创建 GitHub Release。
|
|
164
|
-
6. 写入远端 URL、commit、tag、包版本、integrity
|
|
164
|
+
6. 写入远端 URL、commit、tag、包版本、integrity 和执行结果。若 npm 检查点因执行前观察结果为 `CONSISTENT` 而跳过,只把本次观察到的 integrity 保存到检查点的 `remoteRef.integrity`;包名、版本、registry、预期 integrity 和 tarball 摘要继续以冻结计划为准。
|
|
165
165
|
|
|
166
166
|
任一步失败都停止后续动作,保存检查点并进入 PARTIAL。已完成的检查点通过 `observe` 验证后在 `reconcile` 中幂等跳过。
|
|
167
167
|
|
|
@@ -205,6 +205,7 @@ marketplace install action 的安装侧载荷校验以 action 参数 `payloadCon
|
|
|
205
205
|
|
|
206
206
|
### 4.1 幂等规则
|
|
207
207
|
|
|
208
|
+
- `publish` 在全局 preflight 发现远端对象已存在时,先用同一套 `observe` 分类判断它是已一致还是冲突;已一致的检查点进入 `SKIPPED`,冲突或无法可靠判断时在任何 execute 前失败关闭。
|
|
208
209
|
- `reconcile` 阶段首先通过 `observe` 查询所有计划操作的远端状态。
|
|
209
210
|
- 状态为 `CONSISTENT` 的操作幂等跳过,不重新执行。
|
|
210
211
|
- 状态为 `MISSING` 的操作安全重试。
|
|
@@ -226,7 +227,7 @@ marketplace install action 的安装侧载荷校验以 action 参数 `payloadCon
|
|
|
226
227
|
- 执行前的 `observe` 结果。
|
|
227
228
|
- 执行结果(成功/失败/跳过)。
|
|
228
229
|
- 执行后的 `observe` 验证结果。
|
|
229
|
-
- 远端资源标识(commit、tag、版本、URL)。
|
|
230
|
+
- 远端资源标识(commit、tag、版本、URL)。npm 检查点因 `preObserve=CONSISTENT` 而跳过时,可在 `remoteRef.integrity` 保存本次观察到的有效 integrity;其他 npm 身份和摘要继续由冻结计划提供。
|
|
230
231
|
|
|
231
232
|
---
|
|
232
233
|
|
|
@@ -238,9 +239,9 @@ marketplace install action 的安装侧载荷校验以 action 参数 `payloadCon
|
|
|
238
239
|
2. 重新验证发布计划摘要。
|
|
239
240
|
3. 检查批准记录是否过期。
|
|
240
241
|
4. 按 planVersion 分叉复验工作区基线:planVersion 1 计划基线变化即失败(`BASELINE_CHANGED`);planVersion 2 计划基线漂移仅记录 warning 级证据事件并继续,产物身份由外部写之前的冻结产物复验保证。
|
|
241
|
-
5.
|
|
242
|
+
5. 执行全局远程 preflight;占用类结果先用只读 pre-observe 仲裁,`CONSISTENT` 放行到幂等跳过路径,`CONFLICTING` 或不可可靠观察时失败关闭。
|
|
242
243
|
6. 按批准的操作列表顺序执行每个检查点。
|
|
243
|
-
7. 每个检查点:preflight -> execute -> observe -> 记录。
|
|
244
|
+
7. 每个检查点:pre-observe -> preflight -> execute -> post-observe -> 记录。pre-observe 为 `CONSISTENT` 时直接记录 `SKIPPED`,不调用 execute 或 post-observe。
|
|
244
245
|
8. 任一检查点失败时停止后续动作,计算 PARTIAL(若已有成功检查点)。
|
|
245
246
|
9. 所有检查点成功后进入 PUBLISHED 状态。
|
|
246
247
|
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"bytes": 1744
|
|
27
27
|
},
|
|
28
28
|
"release-plan.schema.json": {
|
|
29
|
-
"digest": "
|
|
30
|
-
"bytes":
|
|
29
|
+
"digest": "3d24cb908cdfbfd5d89551b7c6fed5140f6f1448b9920f114264291ca4cf1c52",
|
|
30
|
+
"bytes": 55905
|
|
31
31
|
},
|
|
32
32
|
"release-project.schema.json": {
|
|
33
|
-
"digest": "
|
|
34
|
-
"bytes":
|
|
33
|
+
"digest": "b0ba3c46692622f734a80d3f4e3904180bbfd1096ca2d9b6d6fd957917e96f73",
|
|
34
|
+
"bytes": 47688
|
|
35
35
|
},
|
|
36
36
|
"release-run.schema.json": {
|
|
37
|
-
"digest": "
|
|
38
|
-
"bytes":
|
|
37
|
+
"digest": "4a041b8f6488e7d61b7eb271ebdbc2e043731df41c4437783ef63e77f664c192",
|
|
38
|
+
"bytes": 19002
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -199,6 +199,11 @@
|
|
|
199
199
|
},
|
|
200
200
|
"url": {
|
|
201
201
|
"type": "string"
|
|
202
|
+
},
|
|
203
|
+
"integrity": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"pattern": "^sha512-[A-Za-z0-9+/]{86}==$",
|
|
206
|
+
"description": "Observed npm dist.integrity when an already-consistent npm publish is skipped"
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
},
|
|
@@ -280,7 +285,42 @@
|
|
|
280
285
|
"minimum": 0,
|
|
281
286
|
"description": "写入目标的载荷文件数"
|
|
282
287
|
}
|
|
283
|
-
}
|
|
288
|
+
},
|
|
289
|
+
"allOf": [
|
|
290
|
+
{
|
|
291
|
+
"if": {
|
|
292
|
+
"properties": {
|
|
293
|
+
"remoteRef": {
|
|
294
|
+
"type": "object",
|
|
295
|
+
"required": [
|
|
296
|
+
"integrity"
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"required": [
|
|
301
|
+
"remoteRef"
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
"then": {
|
|
305
|
+
"properties": {
|
|
306
|
+
"actionType": {
|
|
307
|
+
"const": "npm-publish"
|
|
308
|
+
},
|
|
309
|
+
"status": {
|
|
310
|
+
"const": "skipped"
|
|
311
|
+
},
|
|
312
|
+
"preObserve": {
|
|
313
|
+
"const": "CONSISTENT"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
"required": [
|
|
317
|
+
"actionType",
|
|
318
|
+
"status",
|
|
319
|
+
"preObserve"
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
]
|
|
284
324
|
}
|
|
285
325
|
},
|
|
286
326
|
"sourceAuthorityReceipts": {
|
package/src/commands/publish.mjs
CHANGED
|
@@ -1171,6 +1171,7 @@ export async function publishRelease(options) {
|
|
|
1171
1171
|
: 'pending',
|
|
1172
1172
|
...(checkpoint.preObserve ? { preObserve: checkpoint.preObserve } : {}),
|
|
1173
1173
|
...(checkpoint.postObserve ? { postObserve: checkpoint.postObserve } : {}),
|
|
1174
|
+
...(checkpoint.remoteRef ? { remoteRef: checkpoint.remoteRef } : {}),
|
|
1174
1175
|
...(checkpoint.error ? { error: { code: 'GATE_FAILED', message: checkpoint.error } } : {}),
|
|
1175
1176
|
...(checkpoint.reason === CONSUMER_VERIFICATION_DEFERRED
|
|
1176
1177
|
? { reason: CONSUMER_VERIFICATION_DEFERRED, phase: checkpoint.phase ?? 'post-publish-verification' }
|
|
@@ -1294,6 +1295,20 @@ export async function publishRelease(options) {
|
|
|
1294
1295
|
checkpoint.error = result.error;
|
|
1295
1296
|
if (result.preObserve) checkpoint.preObserve = result.preObserve;
|
|
1296
1297
|
if (result.postObserve) checkpoint.postObserve = result.postObserve;
|
|
1298
|
+
// When npm is already published with the exact frozen integrity, keep
|
|
1299
|
+
// that observed integrity on the existing checkpoint authority. The
|
|
1300
|
+
// immutable plan remains the source for package/version/registry and
|
|
1301
|
+
// expected artifact identity; no second receipt or duplicated fields
|
|
1302
|
+
// are introduced here.
|
|
1303
|
+
if (
|
|
1304
|
+
action.type === 'npm-publish'
|
|
1305
|
+
&& result.status === 'SKIPPED'
|
|
1306
|
+
&& result.preObserve === PRE_OBSERVE.CONSISTENT
|
|
1307
|
+
&& typeof result.observation?.integrity === 'string'
|
|
1308
|
+
&& /^sha512-[A-Za-z0-9+/]+={0,2}$/.test(result.observation.integrity)
|
|
1309
|
+
) {
|
|
1310
|
+
checkpoint.remoteRef = { integrity: result.observation.integrity };
|
|
1311
|
+
}
|
|
1297
1312
|
action.status = result.status;
|
|
1298
1313
|
await evidence.append({
|
|
1299
1314
|
phase: 'checkpoint',
|