release-skill 0.3.0 → 0.4.1

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.
Files changed (81) hide show
  1. package/.claude-plugin/marketplace.json +6 -2
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/.codebuddy-plugin/plugin.json +2 -2
  4. package/.codex-plugin/plugin.json +4 -4
  5. package/.kimi-plugin/plugin.json +3 -3
  6. package/CHANGELOG.md +36 -3
  7. package/INSTALL.md +34 -110
  8. package/INSTALL.zh-CN.md +17 -83
  9. package/LICENSE +183 -18
  10. package/NOTICE +4 -2
  11. package/README.md +61 -75
  12. package/README.zh-CN.md +48 -63
  13. package/adapters/claude/.claude-plugin/marketplace.json +6 -2
  14. package/adapters/claude/.claude-plugin/plugin.json +2 -2
  15. package/adapters/claude/bin/release-skill.bundle.mjs +157 -231
  16. package/adapters/claude/schemas/release-plan.schema.json +7 -0
  17. package/adapters/claude/schemas/release-run.schema.json +43 -0
  18. package/adapters/claude/skills/release-help/SKILL.md +5 -5
  19. package/adapters/claude/skills/release-prepare/SKILL.md +6 -15
  20. package/adapters/claude/skills/release-publish/SKILL.md +5 -6
  21. package/adapters/claude/skills/release-reconcile/SKILL.md +2 -2
  22. package/adapters/claude/skills/release-setup/SKILL.md +6 -0
  23. package/adapters/claude/skills/release-verify/SKILL.md +4 -6
  24. package/adapters/codex/.codex-plugin/plugin.json +4 -4
  25. package/adapters/codex/bin/release-skill.bundle.mjs +157 -231
  26. package/adapters/codex/schemas/release-plan.schema.json +7 -0
  27. package/adapters/codex/schemas/release-run.schema.json +43 -0
  28. package/adapters/codex/skills/release-help/SKILL.md +5 -5
  29. package/adapters/codex/skills/release-prepare/SKILL.md +6 -15
  30. package/adapters/codex/skills/release-publish/SKILL.md +5 -6
  31. package/adapters/codex/skills/release-reconcile/SKILL.md +2 -2
  32. package/adapters/codex/skills/release-setup/SKILL.md +6 -0
  33. package/adapters/codex/skills/release-verify/SKILL.md +4 -6
  34. package/adapters/kimi/.kimi-plugin/plugin.json +3 -3
  35. package/adapters/kimi/bin/release-skill.bundle.mjs +157 -231
  36. package/adapters/kimi/schemas/release-plan.schema.json +7 -0
  37. package/adapters/kimi/schemas/release-run.schema.json +43 -0
  38. package/adapters/kimi/skills/release-help/SKILL.md +5 -5
  39. package/adapters/kimi/skills/release-prepare/SKILL.md +6 -15
  40. package/adapters/kimi/skills/release-publish/SKILL.md +5 -6
  41. package/adapters/kimi/skills/release-reconcile/SKILL.md +2 -2
  42. package/adapters/kimi/skills/release-setup/SKILL.md +6 -0
  43. package/adapters/kimi/skills/release-verify/SKILL.md +4 -6
  44. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +2 -2
  45. package/adapters/workbuddy/bin/release-skill.bundle.mjs +157 -231
  46. package/adapters/workbuddy/schemas/release-plan.schema.json +7 -0
  47. package/adapters/workbuddy/schemas/release-run.schema.json +43 -0
  48. package/adapters/workbuddy/skills/release-help/SKILL.md +5 -5
  49. package/adapters/workbuddy/skills/release-prepare/SKILL.md +6 -15
  50. package/adapters/workbuddy/skills/release-publish/SKILL.md +5 -6
  51. package/adapters/workbuddy/skills/release-reconcile/SKILL.md +2 -2
  52. package/adapters/workbuddy/skills/release-setup/SKILL.md +6 -0
  53. package/adapters/workbuddy/skills/release-verify/SKILL.md +4 -6
  54. package/bin/release-skill-cli.mjs +45 -48
  55. package/bin/release-skill.bundle.mjs +157 -231
  56. package/package.json +2 -2
  57. package/references/01-state-machine.md +1 -1
  58. package/references/06-adapter-contract.md +6 -5
  59. package/schemas/release-plan.schema.json +7 -0
  60. package/schemas/release-run.schema.json +43 -0
  61. package/skills/release-help/SKILL.md +5 -5
  62. package/skills/release-prepare/SKILL.md +6 -15
  63. package/skills/release-publish/SKILL.md +5 -6
  64. package/skills/release-reconcile/SKILL.md +2 -2
  65. package/skills/release-setup/SKILL.md +6 -0
  66. package/skills/release-verify/SKILL.md +4 -6
  67. package/skills-src/release-help/SKILL.md +5 -5
  68. package/skills-src/release-prepare/SKILL.md +6 -15
  69. package/skills-src/release-publish/SKILL.md +5 -6
  70. package/skills-src/release-reconcile/SKILL.md +2 -2
  71. package/skills-src/release-setup/SKILL.md +6 -0
  72. package/skills-src/release-verify/SKILL.md +4 -6
  73. package/src/adapters/npm.mjs +31 -0
  74. package/src/commands/approve.mjs +8 -6
  75. package/src/commands/hooks.mjs +4 -8
  76. package/src/commands/prepare.mjs +13 -50
  77. package/src/commands/publish.mjs +0 -8
  78. package/src/commands/reconcile.mjs +3 -37
  79. package/src/commands/ship.mjs +55 -77
  80. package/src/commands/verify.mjs +56 -19
  81. 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
- node "${CODEBUDDY_PLUGIN_ROOT}/bin/release-skill.mjs" hooks validate --root <path> \
42
- --acknowledge-hook-side-effects --json
43
- # Kimi/CodeBuddy 安装完成后记录人工事实,不手改 JSON
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
- **授权边界**:本地发布文档写入授权只覆盖声明的本地文档目标,不是 hook、Git 提交、push、publish 或安装的授权。写入后必须审阅、提交,再重新 prepare。
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 授权门**: 当项目配置含任何 hook 时,prepare 默认失败关闭并展示将执行的 executable/args/cwd。只有显式传入 `--acknowledge-hook-side-effects`(CLI)或 `hooksAuthorized: true`(API)才能执行。授权表示用户接受 hook 风险,不表示 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. 若遇到 hook/gate 授权门失败,分别展示命令和风险,获取授权后只增加实际需要的 `--acknowledge-hook-side-effects` / `--acknowledge-gate-side-effects`
34
- 5. 检查 exit code 0,读取 JSON 返回的 immutable `planPath=plans/<planDigest>.json`,再从该文件读取 `status`、`units`、`externalActions`
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. Hook 授权门 → 4. 运行 hooks 并复检文档新鲜度 → 5. 捕获 Git baseline →
76
- 6. 逐 unit 观察前序公开基线 → 7. 生成快照/扫描/README → 8. 原子写入 plan
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: 从已批准且摘要确认的生产计划发布冻结 Git branch/tag、npm tarball 与 GitHub Release,并执行已配置的 Claude/Codex marketplace 隔离消费者安装检查以达到 PUBLISHED;随后必须路由 release-verify 才可能达到 VERIFIED;遇到冲突或不确定远端状态时失败关闭并要求人工介入
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. 展示 `planDigest`、版本、仓库/包名、branch/tag 和全部 actions。
29
- 2. 必须存在未过期且绑定同一 digest 的 approval record
30
- 3. 用户必须明确提供 `--confirm-production <planDigest>`;Agent 不得代替用户猜测确认值。
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> --confirm-production <planDigest> --json
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`;生产计划还必须加 `--confirm-production <planDigest>`
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> --confirm-production <planDigest> --json
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
  ## 幂等跳过逻辑
@@ -91,6 +91,12 @@ node -e 'const fs=require("node:fs");const [c,p,a]=process.argv.slice(1).map(x=>
91
91
  node -e 'require("node:fs").rmSync(process.argv[1],{recursive:true,force:false})' "$SETUP_SESSION"
92
92
  ```
93
93
 
94
+ ## publisher 字段与个人片段泄漏策略
95
+
96
+ setup 生成的 `.release-skill/project.yaml` 中 `publisher` 是**已批准的公开发布身份**:它是人工确认的对外发布署名,属于公开面的一部分,而非需要隐藏的私有信息。
97
+
98
+ 若目标仓库用“个人片段”类泄漏策略扫描仓树,而该策略按片段匹配恰好覆盖到 `publisher` 字段,正确做法不是删除或改写策略,而是由贡献者在**本地、gitignore 的个人片段 overlay** 中为该规则声明位置豁免(如 `approvedPlacements`:限定 `publisher` 所在的确切文件路径与行键前缀)。豁免只放行已批准的放置位置,其余出现照常命中;overlay 不入库,个人片段本身不进 committed 策略。
99
+
94
100
  ## 故障路由
95
101
 
96
102
  - `NEEDS_INPUT`:审阅紧凑摘要;有冲突先修正权威事实并重跑。
@@ -17,7 +17,7 @@ verify 只接受 `PUBLISHED` 状态的源 run;`VERIFIED` 是终态,不会再
17
17
 
18
18
  ## 职责与边界
19
19
 
20
- 验证远端所有 action 的实际状态与冻结计划一致。执行精确 `<package>@<version>` npm 安装到隔离目录,验证包名、版本、静态入口闭包,并在配置时验证 bin 路径安全和 CLI 烟雾输出。对每个声明的 marketplace distribution 执行全新隔离消费者安装验证。
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;若存在 consumer gate npm `smokeBin`,先逐项审阅并增加 `--acknowledge-gate-side-effects`
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. 对每个 marketplace distribution 执行全新隔离消费者安装验证
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 未授权 | GATE_FAILED | 展示命令和副作用,人工确认后加 `--acknowledge-gate-side-effects` |
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: '仅当计划声明 kimi-plugin distribution 时用于消费者安装验证',
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: '仅当计划声明 codebuddy-plugin distribution 时用于消费者安装验证(人工 attestation 闭环;CLI 无法钉死冻结 ref,安装由人工完成并出具 attestation)',
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 and runs configured Claude/Codex/Kimi/CodeBuddy consumer checkpoints (CodeBuddy via human attestation closed loop) with approval and exact digest confirmation',
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 configured Claude/Codex/Kimi/CodeBuddy installs (CodeBuddy via human attestation) before VERIFIED',
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 and digest confirmation
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 Record a generated Kimi/CodeBuddy manual result without editing JSON
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
- --acknowledge-hook-side-effects Acknowledge unsandboxed legacy hook execution
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
- --authorize-hooks <digest> Authorize the exact ship hook/config digest
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: prepare --production -> approve -> publish -> verify.
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 and an exact plan-digest confirmation
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: '声明 kimi-plugin distribution 时必须可用',
359
- codebuddy: '声明 codebuddy-plugin distribution 时用于人工 attestation 闭环(CLI 无法钉死冻结 ref,安装由人工完成并出具 attestation)',
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; configured hooks/gates require their explicit side-effect acknowledgements',
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 configured Claude/Codex/Kimi/CodeBuddy consumer checkpoints are protocol-tested without an OS/network sandbox (CodeBuddy via human attestation closed loop); approval and exact digest confirmation required',
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/Kimi/CodeBuddy consumer installation checks are protocol-tested without an OS/network sandbox (CodeBuddy via human attestation); configured consumer processes require explicit acknowledgement; success reaches VERIFIED',
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
- if (!checks.kimi.available) {
410
- output.recommendations.push('Install Kimi Code CLI before releasing a configured kimi-plugin distribution');
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
- hookAuthorizationDigest: value('--authorize-hooks'),
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 and verification gates: --approve-plan ${result.planDigest} --actor <person>`);
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 || !expectedDigest || !actor) {
767
- const msg = 'approve requires --plan <path>, --digest <sha256>, and --actor <name>';
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) === `${expectedDigest}.json`
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 || !productionConfirmation) {
969
- const msg = 'publish requires --plan <path>, --approval <path>, and --confirm-production <plan-digest>';
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) {