release-skill 0.3.0 → 0.4.0
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 +23 -3
- package/INSTALL.md +34 -110
- package/INSTALL.zh-CN.md +17 -83
- package/README.md +42 -65
- package/README.zh-CN.md +37 -57
- 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 +138 -231
- package/adapters/claude/schemas/release-plan.schema.json +7 -0
- package/adapters/claude/schemas/release-run.schema.json +43 -0
- package/adapters/claude/skills/release-help/SKILL.md +5 -5
- package/adapters/claude/skills/release-prepare/SKILL.md +6 -15
- package/adapters/claude/skills/release-publish/SKILL.md +5 -6
- package/adapters/claude/skills/release-reconcile/SKILL.md +2 -2
- package/adapters/claude/skills/release-verify/SKILL.md +4 -6
- package/adapters/codex/.codex-plugin/plugin.json +2 -2
- package/adapters/codex/bin/release-skill.bundle.mjs +138 -231
- package/adapters/codex/schemas/release-plan.schema.json +7 -0
- package/adapters/codex/schemas/release-run.schema.json +43 -0
- package/adapters/codex/skills/release-help/SKILL.md +5 -5
- package/adapters/codex/skills/release-prepare/SKILL.md +6 -15
- package/adapters/codex/skills/release-publish/SKILL.md +5 -6
- package/adapters/codex/skills/release-reconcile/SKILL.md +2 -2
- package/adapters/codex/skills/release-verify/SKILL.md +4 -6
- package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
- package/adapters/kimi/bin/release-skill.bundle.mjs +138 -231
- package/adapters/kimi/schemas/release-plan.schema.json +7 -0
- package/adapters/kimi/schemas/release-run.schema.json +43 -0
- package/adapters/kimi/skills/release-help/SKILL.md +5 -5
- package/adapters/kimi/skills/release-prepare/SKILL.md +6 -15
- package/adapters/kimi/skills/release-publish/SKILL.md +5 -6
- package/adapters/kimi/skills/release-reconcile/SKILL.md +2 -2
- package/adapters/kimi/skills/release-verify/SKILL.md +4 -6
- package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
- package/adapters/workbuddy/bin/release-skill.bundle.mjs +138 -231
- package/adapters/workbuddy/schemas/release-plan.schema.json +7 -0
- package/adapters/workbuddy/schemas/release-run.schema.json +43 -0
- package/adapters/workbuddy/skills/release-help/SKILL.md +5 -5
- package/adapters/workbuddy/skills/release-prepare/SKILL.md +6 -15
- package/adapters/workbuddy/skills/release-publish/SKILL.md +5 -6
- package/adapters/workbuddy/skills/release-reconcile/SKILL.md +2 -2
- package/adapters/workbuddy/skills/release-verify/SKILL.md +4 -6
- package/bin/release-skill-cli.mjs +45 -48
- package/bin/release-skill.bundle.mjs +138 -231
- package/package.json +1 -1
- package/references/01-state-machine.md +1 -1
- package/references/06-adapter-contract.md +6 -5
- package/schemas/release-plan.schema.json +7 -0
- package/schemas/release-run.schema.json +43 -0
- package/skills/release-help/SKILL.md +5 -5
- package/skills/release-prepare/SKILL.md +6 -15
- package/skills/release-publish/SKILL.md +5 -6
- package/skills/release-reconcile/SKILL.md +2 -2
- package/skills/release-verify/SKILL.md +4 -6
- package/skills-src/release-help/SKILL.md +5 -5
- package/skills-src/release-prepare/SKILL.md +6 -15
- package/skills-src/release-publish/SKILL.md +5 -6
- package/skills-src/release-reconcile/SKILL.md +2 -2
- package/skills-src/release-verify/SKILL.md +4 -6
- package/src/commands/approve.mjs +8 -6
- package/src/commands/hooks.mjs +4 -8
- package/src/commands/prepare.mjs +13 -50
- package/src/commands/publish.mjs +0 -8
- package/src/commands/reconcile.mjs +3 -37
- package/src/commands/ship.mjs +55 -77
- package/src/commands/verify.mjs +56 -19
- package/src/core/skill-resource-closure.mjs +7 -1
|
@@ -988,6 +988,13 @@
|
|
|
988
988
|
"type": "string",
|
|
989
989
|
"description": "Overall snapshot digest across all units"
|
|
990
990
|
},
|
|
991
|
+
"humanConsumersStrategy": {
|
|
992
|
+
"type": "string",
|
|
993
|
+
"enum": [
|
|
994
|
+
"manualFollowUps"
|
|
995
|
+
],
|
|
996
|
+
"description": "Human consumer strategy marker. 'manualFollowUps': Kimi/CodeBuddy installations are non-blocking post-release manual tasks; verify returns VERIFIED with manualFollowUps list and does not block on attestation. Absent: legacy attestation closed loop (backward compatibility)."
|
|
997
|
+
},
|
|
991
998
|
"digest": {
|
|
992
999
|
"type": "string",
|
|
993
1000
|
"minLength": 1
|
|
@@ -432,6 +432,49 @@
|
|
|
432
432
|
}
|
|
433
433
|
}
|
|
434
434
|
},
|
|
435
|
+
"manualFollowUps": {
|
|
436
|
+
"type": "array",
|
|
437
|
+
"description": "Non-blocking manual follow-up tasks for human consumer platforms (Kimi/CodeBuddy) when plan declares humanConsumersStrategy: 'manualFollowUps'",
|
|
438
|
+
"items": {
|
|
439
|
+
"type": "object",
|
|
440
|
+
"required": [
|
|
441
|
+
"actionId",
|
|
442
|
+
"platform",
|
|
443
|
+
"plugin",
|
|
444
|
+
"verifiedBySystem"
|
|
445
|
+
],
|
|
446
|
+
"additionalProperties": false,
|
|
447
|
+
"properties": {
|
|
448
|
+
"actionId": {
|
|
449
|
+
"type": "string",
|
|
450
|
+
"minLength": 1
|
|
451
|
+
},
|
|
452
|
+
"platform": {
|
|
453
|
+
"type": "string",
|
|
454
|
+
"enum": [
|
|
455
|
+
"kimi",
|
|
456
|
+
"codebuddy"
|
|
457
|
+
]
|
|
458
|
+
},
|
|
459
|
+
"plugin": {
|
|
460
|
+
"type": "string"
|
|
461
|
+
},
|
|
462
|
+
"version": {
|
|
463
|
+
"type": "string"
|
|
464
|
+
},
|
|
465
|
+
"unitId": {
|
|
466
|
+
"type": "string"
|
|
467
|
+
},
|
|
468
|
+
"verifiedBySystem": {
|
|
469
|
+
"const": false,
|
|
470
|
+
"description": "Always false — these tasks are not verified by the system"
|
|
471
|
+
},
|
|
472
|
+
"reason": {
|
|
473
|
+
"type": "string"
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
},
|
|
435
478
|
"skillResourceClosureReceipts": {
|
|
436
479
|
"type": "array",
|
|
437
480
|
"description": "Per-surface skill resource closure verification receipts from verify phase",
|
|
@@ -35,12 +35,12 @@ description: "Discoverable entry point for release-skill: dependency and environ
|
|
|
35
35
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" help --json
|
|
36
36
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" setup --root <path> --json
|
|
37
37
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" assess --root <path> --offline --json
|
|
38
|
-
#
|
|
38
|
+
# 日常发布快速路径:仅在发布前确认一次可读计划摘要,状态文件可恢复
|
|
39
39
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" ship --root <path> --target-version <version> --json
|
|
40
40
|
# 开发阶段执行声明 hooks 并生成 prepare 可复用的内容绑定收据
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# Kimi/CodeBuddy
|
|
41
|
+
# 命令调用本身即授权执行配置中的 hooks
|
|
42
|
+
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" hooks validate --root <path> --json
|
|
43
|
+
# 仅旧冻结计划兼容:记录历史 Kimi/CodeBuddy 人工证明
|
|
44
44
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" attest --root <path> \
|
|
45
45
|
--platform <kimi|codebuddy> --plugin <id> --result <passed|failed> --actor <person> --json
|
|
46
46
|
# 发布文档刷新:默认只读演练
|
|
@@ -59,7 +59,7 @@ node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" docs refresh --unit <id> \
|
|
|
59
59
|
- **只读演练**:`docs refresh --unit <id> --json` 输出逐文件相对路径、locale、新旧摘要、`version`、`locales`、`inputDigest`、`refreshDigest` 和 `nextCommand.argv`;候选无变化时 `status: "clean"`。
|
|
60
60
|
- **确认写入**:必须同时提供 `--write`、精确 `--confirm-refresh <refreshDigest>` 和 `--ack-local-document-write`,全部目标作为一个事务提交;成功后立即复演必须为 `clean`。
|
|
61
61
|
|
|
62
|
-
**授权边界**:本地发布文档写入授权只覆盖声明的本地文档目标,不是
|
|
62
|
+
**授权边界**:本地发布文档写入授权只覆盖声明的本地文档目标,不是 Git 提交、push、publish 或安装的授权。hook/gate 由对应命令调用直接授权。写入后必须审阅、提交,再重新 prepare。
|
|
63
63
|
|
|
64
64
|
## 故障路由
|
|
65
65
|
|
|
@@ -13,9 +13,7 @@ description: Freeze an immutable release plan with local configuration, document
|
|
|
13
13
|
|
|
14
14
|
运行项目构建/测试 hook,生成公开快照并扫描泄漏,冻结不可变发布计划。prepare 自身不调用发布 adapter,但会执行用户配置的 hook。hook 是任意本地进程,不受文件系统/网络隔离,可能产生项目目录外的副作用或远端写入。
|
|
15
15
|
|
|
16
|
-
**Hook
|
|
17
|
-
|
|
18
|
-
**Gate 授权门**: 当项目含 `snapshot-verify` gate 时,prepare 同样默认失败关闭。逐项审阅后才可传入 `--acknowledge-gate-side-effects`(CLI)或 `verificationGatesAuthorized: true`(API);gate 也没有操作系统或网络沙箱。
|
|
16
|
+
**Hook 与 Gate 执行**: 命令调用本身即授权执行已配置的 hook 和 gate,不再设置额外人工授权环节。
|
|
19
17
|
|
|
20
18
|
**阶段通过规则**: 本阶段的通过只能由 CLI exit code 0 和结构化状态码 `PREPARED` 确认。Agent 无权自行宣布计划冻结成功。
|
|
21
19
|
|
|
@@ -30,9 +28,8 @@ description: Freeze an immutable release plan with local configuration, document
|
|
|
30
28
|
1. 使用插件根相对路径运行 CLI:`CLI="node ${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs"`
|
|
31
29
|
2. 配置含 `releaseDocuments` 时,先运行只读演练 `${CLI} docs refresh --unit <id> --json`;`status: "changes"` 时展示逐文件路径/语种/版本/`refreshDigest`,取得"本地发布文档写入"明确授权后才执行 `nextCommand.argv` 写入,审阅并提交刷新结果后再继续;`status: "clean"` 时直接进入 prepare
|
|
32
30
|
3. 运行 `${CLI} prepare --root <path> --offline --json`
|
|
33
|
-
4.
|
|
34
|
-
5.
|
|
35
|
-
6. 向用户展示 targetVersion、externalActions、planDigest 和 planPath;后续 approve/publish 只能使用该 immutable planPath,等待确认后再 approve
|
|
31
|
+
4. 检查 exit code 0,读取 JSON 返回的 immutable `planPath=plans/<planDigest>.json`,再从该文件读取 `status`、`units`、`externalActions`
|
|
32
|
+
5. 向用户展示可读的 `approvalSummary`(版本、仓库/包、branch/tag、外部动作和例外);`planDigest` 仅作为内部绑定字段,不要求用户复制或确认。后续 approve/publish 只能使用该 immutable planPath,等待确认后再 approve
|
|
36
33
|
|
|
37
34
|
若用户明确要求 GitHub+npm 生产发布,加入 `--production`。该模式还会封存独立
|
|
38
35
|
Git commit/tree 和 npm tarball,并把路径、SHA/integrity、branch/tag 写入计划。
|
|
@@ -63,24 +60,18 @@ node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" docs refresh --unit <id> \
|
|
|
63
60
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" prepare --root <path> --offline --json
|
|
64
61
|
# 生产 happy end:bound 基线必须 online;远端目标唯一性仍由 publish 全局预检
|
|
65
62
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" prepare --root <path> --online --production --json
|
|
66
|
-
# 项目含 hook 时需显式授权:
|
|
67
|
-
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" prepare --root <path> --offline --acknowledge-hook-side-effects --json
|
|
68
|
-
# 项目含 snapshot gate 时另行显式授权:
|
|
69
|
-
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" prepare --root <path> --offline --acknowledge-gate-side-effects --json
|
|
70
63
|
```
|
|
71
64
|
|
|
72
65
|
## 执行顺序
|
|
73
66
|
|
|
74
67
|
1. 校验配置 schema → 2. 版本解析与发布文档新鲜度门(只读,RELEASE_DOCS_STALE)→
|
|
75
|
-
3.
|
|
76
|
-
|
|
68
|
+
3. 运行 hooks 并复检文档新鲜度 → 4. 捕获 Git baseline →
|
|
69
|
+
5. 逐 unit 观察前序公开基线 → 6. 生成快照/扫描/README → 7. 原子写入 plan
|
|
77
70
|
|
|
78
71
|
## 故障路由
|
|
79
72
|
|
|
80
73
|
| 错误码 | 处理 |
|
|
81
74
|
|---|---|
|
|
82
|
-
| GATE_FAILED (hook 授权) | 向用户展示 hook 命令和风险,获得授权后加 `--acknowledge-hook-side-effects` 重试 |
|
|
83
|
-
| GATE_FAILED (gate 授权) | 向用户展示 snapshot gate 命令和风险,获得授权后加 `--acknowledge-gate-side-effects` 重试 |
|
|
84
75
|
| GATE_FAILED (bound + offline) | 改用 `--online --production`,不得把 unobserved-offline plan 交给 publish |
|
|
85
76
|
| GATE_FAILED (前序基线漂移) | 先取得并比较实际远端内容;人工选择 merge/adopt/reject。merge/adopt 都必须把接受内容落回 human-owned 权威源,并把 `previousPublicBaseline` 更新为接受状态的精确 repo/ref/commit 后重新 online production prepare;reject 停止调查,禁止改 `mode: none` 绕过 |
|
|
86
77
|
| GATE_FAILED (`npm-entry-closure`) | 修复打包内容或入口声明后重新 prepare;不得用 `requiredPublicFiles`/`smokeBin` 缺省绕过 |
|
|
@@ -94,4 +85,4 @@ node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" prepare --root <path> --of
|
|
|
94
85
|
|
|
95
86
|
## 后续引导
|
|
96
87
|
|
|
97
|
-
计划冻结后,读取命令返回的 immutable `planPath` 展示给用户,等待确认后再 approve。`release-plan.json` 等 latest alias 只用于浏览,不得作为生产 authority 传递。
|
|
88
|
+
计划冻结后,读取命令返回的 immutable `planPath` 和 `approvalSummary` 展示给用户,等待确认后再 approve。`planDigest` 由系统自动计算和绑定,不作为人工交互口令。`release-plan.json` 等 latest alias 只用于浏览,不得作为生产 authority 传递。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: release-publish
|
|
3
|
-
description:
|
|
3
|
+
description: 从已批准的生产计划发布冻结 Git branch/tag、npm tarball 与 GitHub Release,并执行已配置的 Claude/Codex marketplace 隔离消费者安装检查以达到 PUBLISHED;随后必须路由 release-verify 才可能达到 VERIFIED;遇到冲突或不确定远端状态时失败关闭并要求人工介入
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# release-publish
|
|
@@ -25,16 +25,15 @@ description: 从已批准且摘要确认的生产计划发布冻结 Git branch/t
|
|
|
25
25
|
|
|
26
26
|
## 授权门
|
|
27
27
|
|
|
28
|
-
1.
|
|
29
|
-
2.
|
|
30
|
-
3.
|
|
31
|
-
4. 只有 CLI exit code 0 且结构化状态为 `PUBLISHED` 才算外写阶段通过;随后必须运行 verify,只有 `VERIFIED` 才是完整终态。
|
|
28
|
+
1. 展示可读的 `approvalSummary`:版本、仓库/包名、branch/tag、全部 actions 和例外。
|
|
29
|
+
2. 必须存在未过期且由系统绑定同一内部 digest 的 approval record;批准后不再要求用户复制摘要做二次确认。
|
|
30
|
+
3. 只有 CLI exit code 0 且结构化状态为 `PUBLISHED` 才算外写阶段通过;随后必须运行 verify,只有 `VERIFIED` 才是完整终态。
|
|
32
31
|
|
|
33
32
|
## 确定性执行
|
|
34
33
|
|
|
35
34
|
```bash
|
|
36
35
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" publish --root <path> --plan <plan-path> \
|
|
37
|
-
--approval <approval-path> --
|
|
36
|
+
--approval <approval-path> --json
|
|
38
37
|
```
|
|
39
38
|
|
|
40
39
|
执行顺序:全局只读预检 → 配置的公开分支(按三种 `branchStrategy` 执行)→ 必要时
|
|
@@ -32,7 +32,7 @@ marketplace 隔离消费者 checkpoint,但只恢复到 `PUBLISHED`;最终 np
|
|
|
32
32
|
1. 使用插件根相对路径运行 CLI,确认有 `--run` 路径(必需),且源 run 状态为 `PARTIAL`
|
|
33
33
|
2. 运行 `node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" reconcile --root <path> --plan <plan-path> --run <run-path> --json`
|
|
34
34
|
3. 检查 exit code 和结构化状态:`PUBLISHED`(恢复完成,待 verify)/ `PARTIAL`(需重试)/ `BLOCKED`(需人工决策)
|
|
35
|
-
4. 若 PARTIAL 且需重试,加 `--approval
|
|
35
|
+
4. 若 PARTIAL 且需重试,加 `--approval`;批准记录由系统核验与冻结计划的内部摘要绑定,不再要求二次摘要确认
|
|
36
36
|
|
|
37
37
|
## 确定性脚本调用
|
|
38
38
|
|
|
@@ -42,7 +42,7 @@ node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" reconcile --root <path> --
|
|
|
42
42
|
# verify
|
|
43
43
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" verify --root <path> --plan <plan-path> --run <reconcile-run-path> --json
|
|
44
44
|
# 重试(需 --approval)
|
|
45
|
-
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" reconcile --root <path> --plan <plan-path> --run <run-path> --approval <approval-path> --
|
|
45
|
+
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" reconcile --root <path> --plan <plan-path> --run <run-path> --approval <approval-path> --json
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
## 幂等跳过逻辑
|
|
@@ -17,7 +17,7 @@ verify 只接受 `PUBLISHED` 状态的源 run;`VERIFIED` 是终态,不会再
|
|
|
17
17
|
|
|
18
18
|
## 职责与边界
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
验证远端所有自动化 action 的实际状态与冻结计划一致。执行精确 `<package>@<version>` npm 安装到隔离目录,验证包名、版本、静态入口闭包,并在配置时验证 bin 路径安全和 CLI 烟雾输出。对 Claude/Codex marketplace distribution 执行全新隔离消费者安装验证。新计划中的 Kimi/CodeBuddy 安装只返回 `manualFollowUps`,明确标记 `verifiedBySystem: false`,不阻塞 `VERIFIED`;缺少该策略字段的旧冻结计划继续走历史 attestation 兼容路径。
|
|
21
21
|
|
|
22
22
|
**阶段通过规则**: 只有 CLI exit code 0 和结构化状态码 `VERIFIED` 才是完整终态。
|
|
23
23
|
|
|
@@ -28,7 +28,7 @@ verify 只接受 `PUBLISHED` 状态的源 run;`VERIFIED` 是终态,不会再
|
|
|
28
28
|
## 正向执行路径
|
|
29
29
|
|
|
30
30
|
1. 确认有 `--run` 路径(必需),且源 run 状态为 PUBLISHED
|
|
31
|
-
2. 使用插件根相对路径运行 CLI
|
|
31
|
+
2. 使用插件根相对路径运行 CLI;命令调用本身即授权执行已配置的 verification gate 和 smoke process
|
|
32
32
|
3. 检查 exit code 和结构化状态:`VERIFIED`(全部通过)/ 失败(具体错误)
|
|
33
33
|
4. 只有 `VERIFIED` 才是 happy end
|
|
34
34
|
|
|
@@ -37,8 +37,6 @@ verify 只接受 `PUBLISHED` 状态的源 run;`VERIFIED` 是终态,不会再
|
|
|
37
37
|
```bash
|
|
38
38
|
# 从插件根运行
|
|
39
39
|
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" verify --root <path> --plan <plan-path> --run <run-path> --json
|
|
40
|
-
# 计划含 consumer gate 或 smokeBin 时:
|
|
41
|
-
node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" verify --root <path> --plan <plan-path> --run <run-path> --acknowledge-gate-side-effects --json
|
|
42
40
|
```
|
|
43
41
|
|
|
44
42
|
## 验证步骤
|
|
@@ -47,7 +45,7 @@ node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" verify --root <path> --pla
|
|
|
47
45
|
2. 加载源 run,验证 planDigest 匹配和 checkpoint 完整性
|
|
48
46
|
3. 对每个 plan action 执行 adapter.verify()(远端状态重检)
|
|
49
47
|
4. 对每个 npm distribution 执行隔离安装烟雾测试
|
|
50
|
-
5.
|
|
48
|
+
5. 对 Claude/Codex marketplace distribution 执行全新隔离消费者安装验证;收集 Kimi/CodeBuddy 的非阻塞 `manualFollowUps`
|
|
51
49
|
6. 全部通过 → `VERIFIED`
|
|
52
50
|
|
|
53
51
|
## 烟雾测试
|
|
@@ -69,4 +67,4 @@ node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" verify --root <path> --pla
|
|
|
69
67
|
| 远端状态不匹配 | POST_PUBLISH_VERIFY_FAILED | 停止 |
|
|
70
68
|
| npm 安装失败 | POST_PUBLISH_VERIFY_FAILED | 停止 |
|
|
71
69
|
| CLI 烟雾输出不匹配 | POST_PUBLISH_VERIFY_FAILED | 停止 |
|
|
72
|
-
| consumer gate / smokeBin
|
|
70
|
+
| consumer gate / smokeBin 执行失败 | GATE_FAILED | 检查失败原因,修复后重试 |
|
|
@@ -149,14 +149,14 @@ async function performEnvironmentChecks() {
|
|
|
149
149
|
checks.kimi = {
|
|
150
150
|
...kimiCheck,
|
|
151
151
|
required: false,
|
|
152
|
-
usage: '
|
|
152
|
+
usage: '仅供发布后的人工安装使用;release-skill 不核验 Kimi 安装',
|
|
153
153
|
};
|
|
154
154
|
|
|
155
155
|
const codebuddyCheck = await checkCodeBuddyDependency();
|
|
156
156
|
checks.codebuddy = {
|
|
157
157
|
...codebuddyCheck,
|
|
158
158
|
required: false,
|
|
159
|
-
usage: '
|
|
159
|
+
usage: '仅供发布后的人工安装使用;release-skill 不核验 CodeBuddy/WorkBuddy 安装',
|
|
160
160
|
};
|
|
161
161
|
|
|
162
162
|
return checks;
|
|
@@ -182,7 +182,7 @@ function getCapabilityMaturity() {
|
|
|
182
182
|
prepare: {
|
|
183
183
|
available: true,
|
|
184
184
|
mode: 'offline local writes',
|
|
185
|
-
description: 'Freeze a release plan with snapshots and gates',
|
|
185
|
+
description: 'Freeze a release plan with snapshots and gates; the command invocation authorizes hook and gate execution',
|
|
186
186
|
},
|
|
187
187
|
docs: {
|
|
188
188
|
available: true,
|
|
@@ -192,7 +192,7 @@ function getCapabilityMaturity() {
|
|
|
192
192
|
publish: {
|
|
193
193
|
available: true,
|
|
194
194
|
mode: 'controlled production (protocol-tested; no OS/network sandbox)',
|
|
195
|
-
description: 'Publishes frozen GitHub/npm artifacts
|
|
195
|
+
description: 'Publishes frozen GitHub/npm artifacts after one readable-plan approval, runs automated Claude/Codex checkpoints, and emits non-blocking Kimi/CodeBuddy manual follow-ups',
|
|
196
196
|
},
|
|
197
197
|
reconcile: {
|
|
198
198
|
available: true,
|
|
@@ -202,7 +202,7 @@ function getCapabilityMaturity() {
|
|
|
202
202
|
verify: {
|
|
203
203
|
available: true,
|
|
204
204
|
mode: 'fresh consumer verification (protocol-tested; no OS/network sandbox)',
|
|
205
|
-
description: 'Recheck remote state, exact npm installation, CLI help, and
|
|
205
|
+
description: 'Recheck remote state, exact npm installation, CLI help, and automated Claude/Codex installs before VERIFIED; Kimi/CodeBuddy remain unverified manual follow-ups',
|
|
206
206
|
},
|
|
207
207
|
};
|
|
208
208
|
}
|
|
@@ -219,11 +219,11 @@ Commands:
|
|
|
219
219
|
assess Read-only assessment of project release readiness
|
|
220
220
|
prepare Freeze a release plan (release-skill output to .release-skill/; hooks may do remote ops)
|
|
221
221
|
approve Record local approval for a frozen release plan
|
|
222
|
-
publish Publish frozen GitHub/npm artifacts after approval
|
|
222
|
+
publish Publish frozen GitHub/npm artifacts after approval
|
|
223
223
|
reconcile Resume PARTIAL state from evidence; conflicts require a human
|
|
224
224
|
verify Fresh remote and consumer verification; only this reaches VERIFIED
|
|
225
225
|
ship Resume one durable prepare -> approve -> publish -> verify flow
|
|
226
|
-
attest
|
|
226
|
+
attest Legacy only: record a Kimi/CodeBuddy result for an old frozen plan
|
|
227
227
|
hooks Run declared development hooks and populate reusable receipts
|
|
228
228
|
artifacts Artifact status, inspect, update/apply, resolution, and diagnostics
|
|
229
229
|
docs Refresh declared release documents (read-only dry-run by default)
|
|
@@ -234,7 +234,6 @@ Options:
|
|
|
234
234
|
--run <path> Path to the release run file (required for reconcile/verify)
|
|
235
235
|
--approval <path> Path to the approval record
|
|
236
236
|
--production Prepare immutable Git/npm production artifacts
|
|
237
|
-
--confirm-production <digest> Confirm the exact production plan digest
|
|
238
237
|
--output <path> Override prepare/approve output path (non-production only)
|
|
239
238
|
--run-dir <path> Override prepare run directory; production requires one direct child of .release-skill/runs
|
|
240
239
|
--answers <path> Human-reviewed setup answers JSON
|
|
@@ -243,16 +242,13 @@ Options:
|
|
|
243
242
|
--unit <id> Release unit whose declared release documents are refreshed (docs refresh)
|
|
244
243
|
--confirm-refresh <sha256:...> Confirm the exact dry-run refreshDigest before any document write
|
|
245
244
|
--ack-local-document-write Acknowledge the explicit local release-document write (docs refresh --write)
|
|
246
|
-
--
|
|
247
|
-
--acknowledge-gate-side-effects Acknowledge unsandboxed local verification gate execution
|
|
248
|
-
--platform <id> Manual attestation platform: kimi or codebuddy
|
|
245
|
+
--platform <id> Legacy attestation platform: kimi or codebuddy
|
|
249
246
|
--plugin <id> Plugin id for a generated manual requirement
|
|
250
247
|
--actor <name> Person confirming an approval or manual result
|
|
251
248
|
--result <value> Manual result: passed or failed
|
|
252
249
|
--install-path <path> Actual managed plugin path when closure verification requires it
|
|
253
250
|
--install-channel <desktop|cli> CodeBuddy installation channel when required
|
|
254
|
-
--
|
|
255
|
-
--approve-plan <digest> Approve the exact ship plan and its verification gates
|
|
251
|
+
--approve Approve the ship plan (boolean; plan digest is auto-resolved)
|
|
256
252
|
--state <path> Override the durable ship state file
|
|
257
253
|
--no-hook-cache Force every prepare hook to run in full; neither read nor write the hook cache
|
|
258
254
|
--json Output results as JSON
|
|
@@ -261,14 +257,16 @@ Options:
|
|
|
261
257
|
|
|
262
258
|
Safety:
|
|
263
259
|
Safe default: help -> setup (when config is absent) -> assess -> prepare --offline -> human review.
|
|
264
|
-
Production happy end:
|
|
260
|
+
Production happy end: ship --target-version <ver> -> ship --approve --actor <name>.
|
|
261
|
+
The ship command runs configured hooks and gates automatically; the only human gate is plan approval.
|
|
262
|
+
Kimi/CodeBuddy installations are non-blocking manual follow-up tasks (not verified by system).
|
|
265
263
|
prepare copies current public files into a local snapshot; it does not rewrite source files.
|
|
266
264
|
- Default mode is offline (release-skill pipeline does no remote writes)
|
|
267
265
|
- prepare output goes to .release-skill/ directory only
|
|
268
266
|
- User-configured hooks may write anywhere and perform remote operations
|
|
269
267
|
- To ensure zero remote writes, disable hooks or audit them separately
|
|
270
268
|
- docs refresh --write rewrites only declared README managed regions and the current CHANGELOG entry after exact refreshDigest confirmation; it never commits, pushes, tags, publishes, or installs.
|
|
271
|
-
- publish requires explicit approval
|
|
269
|
+
- publish requires explicit approval; plan digest is auto-read from the plan file
|
|
272
270
|
- publish consumes frozen Git/npm artifacts, never the live workspace
|
|
273
271
|
- existing remote objects and uncertain checks stop for human intervention
|
|
274
272
|
- production-equivalent protocol sandbox is verified; a real remote canary is not
|
|
@@ -355,8 +353,8 @@ if (!command || command === 'help') {
|
|
|
355
353
|
conditionalConsumers: {
|
|
356
354
|
claude: '声明 claude-plugin distribution 时必须可用',
|
|
357
355
|
codex: '声明 codex-plugin distribution 时必须可用',
|
|
358
|
-
kimi: '
|
|
359
|
-
codebuddy: '
|
|
356
|
+
kimi: '发布后人工安装待办;不影响生产发布就绪度,系统不核验',
|
|
357
|
+
codebuddy: '发布后人工安装待办;不影响生产发布就绪度,系统不核验',
|
|
360
358
|
},
|
|
361
359
|
},
|
|
362
360
|
},
|
|
@@ -365,12 +363,12 @@ if (!command || command === 'help') {
|
|
|
365
363
|
maturity: {
|
|
366
364
|
setup: 'read-only by default; create-once requires answers plus exact setupDigest confirmation',
|
|
367
365
|
assess: 'read-only (default); --output writes local report',
|
|
368
|
-
prepare: 'offline local writes;
|
|
366
|
+
prepare: 'offline local writes; the command invocation authorizes configured hook and gate execution',
|
|
369
367
|
docs: 'read-only dry-run by default; write requires --write, exact --confirm-refresh, and --ack-local-document-write; never commits, pushes, or publishes',
|
|
370
368
|
onlinePrepare: 'previous-public-baseline observation available; production mode freezes publish artifacts and fails closed on drift or unknown state',
|
|
371
|
-
publish: 'GitHub/npm plus
|
|
369
|
+
publish: 'GitHub/npm plus automated Claude/Codex consumer checkpoints are protocol-tested without an OS/network sandbox; one approval is required and the internal plan digest is checked automatically',
|
|
372
370
|
reconcile: 'PARTIAL recovery is protocol-tested without an OS/network sandbox; remote conflicts require human intervention',
|
|
373
|
-
verify: 'fresh exact npm and Claude/Codex
|
|
371
|
+
verify: 'fresh exact npm and Claude/Codex consumer installation checks are protocol-tested without an OS/network sandbox; Kimi/CodeBuddy are unverified manual follow-ups; command invocation authorizes configured gates',
|
|
374
372
|
},
|
|
375
373
|
recommendations: [],
|
|
376
374
|
};
|
|
@@ -406,13 +404,8 @@ if (!command || command === 'help') {
|
|
|
406
404
|
output.recommendations.push('Install Codex CLI before releasing a configured codex-plugin distribution');
|
|
407
405
|
}
|
|
408
406
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
if (!checks.codebuddy.available) {
|
|
414
|
-
output.recommendations.push('Install WorkBuddy (bundled codebuddy CLI) before releasing a configured codebuddy-plugin distribution; the install is a manual attestation closed loop because the CLI cannot pin a frozen ref');
|
|
415
|
-
}
|
|
407
|
+
// Kimi/CodeBuddy are post-release manual follow-ups. Their local CLI
|
|
408
|
+
// availability is informational and never blocks release readiness.
|
|
416
409
|
|
|
417
410
|
console.log(JSON.stringify(output, null, 2));
|
|
418
411
|
process.exit(readiness.status === 'READY' ? 0 : 1);
|
|
@@ -527,6 +520,7 @@ if (command === 'hooks') {
|
|
|
527
520
|
const { validateDeclaredHooks } = await import('../src/commands/hooks.mjs');
|
|
528
521
|
const result = await validateDeclaredHooks({
|
|
529
522
|
root,
|
|
523
|
+
// --acknowledge-hook-side-effects is accepted as a no-effect compatibility input
|
|
530
524
|
hooksAuthorized: args.includes('--acknowledge-hook-side-effects'),
|
|
531
525
|
hookCache: !args.includes('--no-hook-cache'),
|
|
532
526
|
});
|
|
@@ -582,7 +576,7 @@ if (command === 'ship') {
|
|
|
582
576
|
root,
|
|
583
577
|
statePath: value('--state'),
|
|
584
578
|
targetVersion: value('--target-version') ?? value('--version'),
|
|
585
|
-
|
|
579
|
+
approve: args.includes('--approve'),
|
|
586
580
|
planApprovalDigest: value('--approve-plan'),
|
|
587
581
|
actor: value('--actor'),
|
|
588
582
|
adapterRegistry,
|
|
@@ -592,11 +586,11 @@ if (command === 'ship') {
|
|
|
592
586
|
} else {
|
|
593
587
|
console.log(`Ship status: ${result.status}`);
|
|
594
588
|
console.log(`State: ${result.statePath}`);
|
|
595
|
-
if (result.hookAuthorizationDigest && result.status === 'NEEDS_HOOK_AUTHORIZATION') {
|
|
596
|
-
console.log(`Authorize hooks: --authorize-hooks ${result.hookAuthorizationDigest}`);
|
|
597
|
-
}
|
|
598
589
|
if (result.planDigest && result.status === 'NEEDS_PLAN_APPROVAL') {
|
|
599
|
-
console.log(`Approve plan
|
|
590
|
+
console.log(`Approve plan: ship --approve --actor <person>`);
|
|
591
|
+
}
|
|
592
|
+
for (const followUp of result.manualFollowUps ?? []) {
|
|
593
|
+
console.log(`Manual follow-up [${followUp.platform}] ${followUp.plugin}: not verified by system`);
|
|
600
594
|
}
|
|
601
595
|
for (const requirement of result.requirements ?? []) {
|
|
602
596
|
console.log(`Manual requirement [${requirement.platform}]: ${requirement.requirementPath}`);
|
|
@@ -763,8 +757,8 @@ if (command === 'approve') {
|
|
|
763
757
|
const outputIdx = args.indexOf('--output');
|
|
764
758
|
const outputPath = outputIdx !== -1 && args[outputIdx + 1] ? resolve(args[outputIdx + 1]) : undefined;
|
|
765
759
|
|
|
766
|
-
if (!planPath || !
|
|
767
|
-
const msg = 'approve requires --plan <path
|
|
760
|
+
if (!planPath || !actor) {
|
|
761
|
+
const msg = 'approve requires --plan <path> and --actor <name>';
|
|
768
762
|
if (hasJson) {
|
|
769
763
|
console.log(JSON.stringify({ error: 'MISSING_PARAMETERS', message: msg, exitCode: 1 }));
|
|
770
764
|
} else {
|
|
@@ -775,13 +769,24 @@ if (command === 'approve') {
|
|
|
775
769
|
|
|
776
770
|
try {
|
|
777
771
|
const { approvePlan } = await import('../src/commands/approve.mjs');
|
|
772
|
+
const { computePlanDigest } = await import('../src/core/plan.mjs');
|
|
773
|
+
const { readFile: readFileFs } = await import('node:fs/promises');
|
|
774
|
+
|
|
775
|
+
// Auto-read digest from plan when --digest is omitted
|
|
776
|
+
let resolvedDigest = expectedDigest;
|
|
777
|
+
if (!resolvedDigest) {
|
|
778
|
+
const planRaw = await readFileFs(resolve(planPath), 'utf8');
|
|
779
|
+
const planObj = JSON.parse(planRaw);
|
|
780
|
+
resolvedDigest = computePlanDigest(planObj);
|
|
781
|
+
}
|
|
782
|
+
|
|
778
783
|
const resolvedPlanPath = resolve(planPath);
|
|
779
784
|
const planDir = dirname(resolvedPlanPath);
|
|
780
|
-
const releaseDir = basename(planDir) === 'plans' && basename(resolvedPlanPath) === `${
|
|
785
|
+
const releaseDir = basename(planDir) === 'plans' && basename(resolvedPlanPath) === `${resolvedDigest}.json`
|
|
781
786
|
? dirname(planDir)
|
|
782
787
|
: planDir;
|
|
783
788
|
const approvalPath = outputPath ?? join(releaseDir, 'approval-record.json');
|
|
784
|
-
const record = await approvePlan({ planPath, expectedDigest, actor, outputPath: approvalPath });
|
|
789
|
+
const record = await approvePlan({ planPath, expectedDigest: resolvedDigest, actor, outputPath: approvalPath });
|
|
785
790
|
|
|
786
791
|
if (hasJson) {
|
|
787
792
|
console.log(JSON.stringify(record, null, 2));
|
|
@@ -819,10 +824,6 @@ if (command === 'reconcile') {
|
|
|
819
824
|
const runPath = runIdx !== -1 && args[runIdx + 1] ? resolve(args[runIdx + 1]) : undefined;
|
|
820
825
|
const approvalIdx = args.indexOf('--approval');
|
|
821
826
|
const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve(args[approvalIdx + 1]) : undefined;
|
|
822
|
-
const confirmationIdx = args.indexOf('--confirm-production');
|
|
823
|
-
const productionConfirmation = confirmationIdx !== -1 && args[confirmationIdx + 1]
|
|
824
|
-
? args[confirmationIdx + 1]
|
|
825
|
-
: undefined;
|
|
826
827
|
|
|
827
828
|
if (!planPath || !runPath) {
|
|
828
829
|
const msg = 'reconcile requires --plan <path> and --run <path>';
|
|
@@ -841,6 +842,7 @@ if (command === 'reconcile') {
|
|
|
841
842
|
const { createPluginMarketplaceAdapter } = await import('../src/adapters/plugin-marketplace.mjs');
|
|
842
843
|
const { createPushSnapshotAdapter } = await import('../src/adapters/push-snapshot.mjs');
|
|
843
844
|
const { createAdapterRegistry } = await import('../src/adapters/contract.mjs');
|
|
845
|
+
|
|
844
846
|
const registry = createAdapterRegistry([
|
|
845
847
|
createGitGithubAdapter(),
|
|
846
848
|
createNpmAdapter(),
|
|
@@ -854,7 +856,6 @@ if (command === 'reconcile') {
|
|
|
854
856
|
approvalPath,
|
|
855
857
|
adapterRegistry: registry,
|
|
856
858
|
root,
|
|
857
|
-
productionConfirmation,
|
|
858
859
|
});
|
|
859
860
|
|
|
860
861
|
if (hasJson) {
|
|
@@ -960,13 +961,9 @@ if (command === 'publish') {
|
|
|
960
961
|
const planPath = planIdx !== -1 && args[planIdx + 1] ? resolve(args[planIdx + 1]) : undefined;
|
|
961
962
|
const approvalIdx = args.indexOf('--approval');
|
|
962
963
|
const approvalPath = approvalIdx !== -1 && args[approvalIdx + 1] ? resolve(args[approvalIdx + 1]) : undefined;
|
|
963
|
-
const confirmationIdx = args.indexOf('--confirm-production');
|
|
964
|
-
const productionConfirmation = confirmationIdx !== -1 && args[confirmationIdx + 1]
|
|
965
|
-
? args[confirmationIdx + 1]
|
|
966
|
-
: undefined;
|
|
967
964
|
|
|
968
|
-
if (!planPath || !approvalPath
|
|
969
|
-
const msg = 'publish requires --plan <path
|
|
965
|
+
if (!planPath || !approvalPath) {
|
|
966
|
+
const msg = 'publish requires --plan <path> and --approval <path>';
|
|
970
967
|
if (hasJson) {
|
|
971
968
|
console.log(JSON.stringify({ error: 'MISSING_PARAMETERS', message: msg, exitCode: 1 }));
|
|
972
969
|
} else {
|
|
@@ -982,6 +979,7 @@ if (command === 'publish') {
|
|
|
982
979
|
const { createPluginMarketplaceAdapter } = await import('../src/adapters/plugin-marketplace.mjs');
|
|
983
980
|
const { createPushSnapshotAdapter } = await import('../src/adapters/push-snapshot.mjs');
|
|
984
981
|
const { createAdapterRegistry } = await import('../src/adapters/contract.mjs');
|
|
982
|
+
|
|
985
983
|
const registry = createAdapterRegistry([
|
|
986
984
|
createGitGithubAdapter(),
|
|
987
985
|
createNpmAdapter(),
|
|
@@ -995,7 +993,6 @@ if (command === 'publish') {
|
|
|
995
993
|
adapterRegistry: registry,
|
|
996
994
|
root,
|
|
997
995
|
productionMode: true,
|
|
998
|
-
productionConfirmation,
|
|
999
996
|
});
|
|
1000
997
|
|
|
1001
998
|
if (hasJson) {
|