release-skill 0.9.13 → 0.9.15

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 (50) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codebuddy-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +2 -2
  4. package/.kimi-plugin/plugin.json +1 -1
  5. package/CHANGELOG.md +51 -0
  6. package/INSTALL.md +2 -2
  7. package/INSTALL.zh-CN.md +2 -2
  8. package/README.md +42 -14
  9. package/README.zh-CN.md +35 -14
  10. package/adapters/claude/.claude-plugin/plugin.json +1 -1
  11. package/adapters/claude/bin/release-skill.bundle.mjs +1195 -694
  12. package/adapters/claude/schemas/release-plan.schema.json +41 -1
  13. package/adapters/claude/schemas/release-project.schema.json +40 -0
  14. package/adapters/claude/skills/release-finish/SKILL.md +1 -1
  15. package/adapters/claude/skills/release-prepare/SKILL.md +34 -8
  16. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  17. package/adapters/codex/bin/release-skill.bundle.mjs +1195 -694
  18. package/adapters/codex/schemas/release-plan.schema.json +41 -1
  19. package/adapters/codex/schemas/release-project.schema.json +40 -0
  20. package/adapters/codex/skills/release-finish/SKILL.md +1 -1
  21. package/adapters/codex/skills/release-prepare/SKILL.md +34 -8
  22. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  23. package/adapters/kimi/bin/release-skill.bundle.mjs +1195 -694
  24. package/adapters/kimi/schemas/release-plan.schema.json +41 -1
  25. package/adapters/kimi/schemas/release-project.schema.json +40 -0
  26. package/adapters/kimi/skills/release-finish/SKILL.md +1 -1
  27. package/adapters/kimi/skills/release-prepare/SKILL.md +34 -8
  28. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
  29. package/adapters/workbuddy/bin/release-skill.bundle.mjs +1195 -694
  30. package/adapters/workbuddy/schemas/release-plan.schema.json +41 -1
  31. package/adapters/workbuddy/schemas/release-project.schema.json +40 -0
  32. package/adapters/workbuddy/skills/release-finish/SKILL.md +1 -1
  33. package/adapters/workbuddy/skills/release-prepare/SKILL.md +34 -8
  34. package/bin/release-skill-cli.mjs +85 -10
  35. package/bin/release-skill.bundle.mjs +1195 -694
  36. package/package.json +1 -1
  37. package/platform-manifest.json +4 -4
  38. package/references/02-project-config.md +10 -0
  39. package/references/05-evidence-and-errors.md +2 -1
  40. package/schemas/release-plan.schema.json +41 -1
  41. package/schemas/release-project.schema.json +40 -0
  42. package/skills/release-finish/SKILL.md +1 -1
  43. package/skills/release-prepare/SKILL.md +34 -8
  44. package/skills-src/release-finish/SKILL.md +1 -1
  45. package/skills-src/release-prepare/SKILL.md +34 -8
  46. package/src/commands/post-release-local.mjs +73 -3
  47. package/src/commands/prepare.mjs +56 -0
  48. package/src/core/postpublish.mjs +51 -0
  49. package/src/core/run-retention.mjs +227 -0
  50. package/src/core/run.mjs +10 -1
@@ -1465,6 +1465,9 @@
1465
1465
  "const": "tag-worktree",
1466
1466
  "description": "时序契约:载荷只能来自 tagCommit 处的 detached worktree,绝不读取工作区状态"
1467
1467
  },
1468
+ "localHostUpdate": {
1469
+ "$ref": "#/definitions/planLocalHostUpdate"
1470
+ },
1468
1471
  "executionBundle": {
1469
1472
  "type": "object",
1470
1473
  "description": "冻结的私有执行包(F-01/T1):closure 直接采用 Foundation computeResourceClosure() 的返回(排序、去重、受收容读取与摘要均由 Foundation 完成),publicFiles 是从发布单元投影的公开映射。计划是该执行包的唯一事实源:随整个 plan digest 绑定,不维护平行 manifest,也不另造 bundle digest。字节写入计划权威 .release-skill 的 postpublish-bundles/<closure.digest>/<resource.path>;distribute/postVerify 在任何 hook/外部写之前经 Foundation 严格复验并重算闭包,任何不一致即失败。",
@@ -1598,7 +1601,44 @@
1598
1601
  }
1599
1602
  }
1600
1603
  }
1601
- ]
1604
+ ],
1605
+ "allOf": [{
1606
+ "if": { "required": ["localHostUpdate"] },
1607
+ "then": {
1608
+ "required": ["hooks"],
1609
+ "properties": {
1610
+ "hooks": {
1611
+ "contains": { "type": "object", "required": ["phase"], "properties": { "phase": { "const": "postVerify" } } }
1612
+ }
1613
+ }
1614
+ }
1615
+ }]
1616
+ },
1617
+ "planLocalHostUpdate": {
1618
+ "type": "object",
1619
+ "additionalProperties": false,
1620
+ "required": ["plugin", "hosts", "hub"],
1621
+ "properties": {
1622
+ "plugin": { "type": "string", "minLength": 1, "pattern": ".*\\S.*" },
1623
+ "hosts": {
1624
+ "type": "array",
1625
+ "minItems": 1,
1626
+ "uniqueItems": true,
1627
+ "items": { "type": "string", "enum": ["claude", "codex", "kimi", "codebuddy", "workbuddy"] }
1628
+ },
1629
+ "hub": { "$ref": "#/definitions/planLocalHostHub" }
1630
+ }
1631
+ },
1632
+ "planLocalHostHub": {
1633
+ "type": "object",
1634
+ "additionalProperties": false,
1635
+ "required": ["name", "repo", "ref"],
1636
+ "properties": {
1637
+ "name": { "type": "string", "minLength": 1, "pattern": ".*\\S.*" },
1638
+ "githubHost": { "type": "string", "pattern": "^[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?$" },
1639
+ "repo": { "type": "string", "pattern": "^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$" },
1640
+ "ref": { "type": "string", "pattern": "^refs\\/heads\\/[A-Za-z0-9][A-Za-z0-9._-]*(?:\\/[A-Za-z0-9][A-Za-z0-9._-]*)*$" }
1641
+ }
1602
1642
  },
1603
1643
  "planPostPublishHook": {
1604
1644
  "type": "object",
@@ -1008,7 +1008,47 @@
1008
1008
  "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\).+$"
1009
1009
  },
1010
1010
  "uniqueItems": true
1011
+ },
1012
+ "localHostUpdate": {
1013
+ "$ref": "#/definitions/localHostUpdate"
1014
+ }
1015
+ },
1016
+ "allOf": [{
1017
+ "if": { "required": ["localHostUpdate"] },
1018
+ "then": {
1019
+ "required": ["hooks"],
1020
+ "properties": {
1021
+ "hooks": {
1022
+ "contains": { "type": "object", "required": ["phase"], "properties": { "phase": { "const": "postVerify" } } }
1023
+ }
1024
+ }
1011
1025
  }
1026
+ }]
1027
+ },
1028
+ "localHostUpdate": {
1029
+ "type": "object",
1030
+ "additionalProperties": false,
1031
+ "required": ["plugin", "hosts", "hub"],
1032
+ "properties": {
1033
+ "plugin": { "type": "string", "minLength": 1, "pattern": ".*\\S.*" },
1034
+ "hosts": {
1035
+ "type": "array",
1036
+ "minItems": 1,
1037
+ "uniqueItems": true,
1038
+ "items": { "type": "string", "enum": ["claude", "codex", "kimi", "codebuddy", "workbuddy"] }
1039
+ },
1040
+ "hub": { "$ref": "#/definitions/localHostHub" }
1041
+ }
1042
+ },
1043
+ "localHostHub": {
1044
+ "type": "object",
1045
+ "additionalProperties": false,
1046
+ "required": ["name", "repo", "ref"],
1047
+ "properties": {
1048
+ "name": { "type": "string", "minLength": 1, "pattern": ".*\\S.*" },
1049
+ "githubHost": { "type": "string", "pattern": "^[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?$" },
1050
+ "repo": { "type": "string", "pattern": "^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$" },
1051
+ "ref": { "type": "string", "pattern": "^refs\\/heads\\/[A-Za-z0-9][A-Za-z0-9._-]*(?:\\/[A-Za-z0-9][A-Za-z0-9._-]*)*$" }
1012
1052
  }
1013
1053
  },
1014
1054
  "postPublishHook": {
@@ -42,7 +42,7 @@ node "$RELEASE_SKILL_LOCAL_FINISH_ENTRY" \
42
42
 
43
43
  1. `merge.promptRequired=false` 时,发布工作流已经推进或初始化目标分支,不再询问合并。
44
44
  2. `merge.promptRequired=true` 时,向用户说明尚未覆盖的发布分支,并询问是否需要合并。用户同意后,先只读核对源分支、目标分支、工作区状态和项目既有合并方式,再用明确的分支名执行;本脚本不猜分支,也不自动推送。
45
- 3. `localHostUpdate.promptRequired=true` 时,列出计划覆盖的宿主,询问是否更新本机插件。两个问题可以一次问完。
45
+ 3. `localHostUpdate.promptRequired=true` 时,列出计划覆盖的宿主,询问是否更新本机插件。Hub-backed 目标必须显示其声明的 Hub、插件和宿主,并明确这是人工安装/升级入口,不运行本机命令;Claude/Codex 使用现有 marketplace 管理入口,Kimi 使用冻结 GitHub Release 和现有人工确认路径,CodeBuddy/WorkBuddy 明确人工处理且不能固定 Hub ref。后续“用户同意更新”段仅适用于 `available=true` 的 executable externalActions 目标;Hub-backed 始终人工入口。两个问题可以一次问完。
46
46
 
47
47
  ## postVerify 提案送达边界
48
48
 
@@ -32,17 +32,45 @@ description: Freeze an immutable release plan with local configuration, document
32
32
 
33
33
  **不确定性停止**: 遇到无法确定的配置项或版本冲突时,Agent 必须停止并上报用户。
34
34
 
35
+ **候选与授权边界**: 先确认本轮操作的是未冻结工作树,还是已经冻结并取得验收的候选。候选已经冻结时,未经授权不得运行会改写候选的生成命令或 Hook。保留原候选时,原有验收继续绑定原候选。若要生成新候选,先说明哪些计划、批准和验收需要重新绑定;禁止把旧候选的验收用于新候选。
36
+
37
+ **项目事实来源**: 依赖关系、生成入口、聚焦检查和环境前提只能来自用户请求、项目权威指引、配置及现有脚本。Skill 必须在授权范围内实际执行已确认的入口,不能只建议主会话“统一刷新”。现有事实不足以证明顺序或副作用时,报告缺少的具体事实并停止,不创建通用依赖图、前提检查脚本或配置迁移。
38
+
35
39
  **发布文档新鲜度门**: 配置了 `releaseDocuments` 的单元在 hook 授权门前先执行同一只读规划器:`clean` 继续;`changes` 抛 `RELEASE_DOCS_STALE`,详情列出相对路径、语种、`refreshDigest` 和精确演练/写入参数数组。prepare 只检查、不写工作树。正式 prepare 前先运行只读演练;有变化时向用户展示文件/语种/版本/`refreshDigest`,只有在用户明确授权"本地发布文档写入"后,才执行带 `--write --confirm-refresh <refreshDigest> --ack-local-document-write` 三项绑定的写入,随后运行聚焦校验,要求维护者审阅并提交刷新结果,再重新 prepare。该授权不扩展为 hook、提交、push 或 publish 授权。
36
40
 
37
41
  **显式发布范围**: 只有用户已经指出本轮要发布哪些单元时,才把这些 ID 逐个传给 `--unit`。release-skill 不根据失败自动排除单元。选择命中 `publicSourceAuthorityReceipt` 的 coordinator 或 subject 时,必须包含收据声明的完整单元闭包;缺少单元时按命令返回的精确 argv 重新选择,不自动扩选。成功后展示 `releaseScope.selectedUnitIds`、`releaseScope.deferredUnitIds` 和批准摘要。延期仅表示没有进入本轮计划,不表示通过或失败。
38
42
 
39
43
  ## 正向执行路径
40
44
 
41
- 1. 使用插件根相对路径运行 CLI:`CLI="node $RELEASE_SKILL_ENTRY"`
42
- 2. 配置含 `releaseDocuments` 时,先运行只读演练 `${CLI} docs refresh --unit <id> --json`;`status: "changes"` 时展示逐文件路径/语种/版本/`refreshDigest`,取得"本地发布文档写入"明确授权后才执行 `nextCommand.argv` 写入,审阅并提交刷新结果后再继续;`status: "clean"` 时直接进入 prepare
43
- 3. 运行 `${CLI} prepare --root <path> --offline --json`;用户已明确选择范围时,为每个单元追加一个 `--unit <id>`
44
- 4. 检查 exit code 0,读取 JSON 返回的 immutable `planPath=plans/<planDigest>.json`,再从该文件读取 `status`、`units`、`externalActions`
45
- 5. 向用户展示可读的 `approvalSummary`:版本、公开仓库、分支策略、branch/tag、npm 与 GitHub Release 目标、全部外部动作、例外,以及需要独立 checkpoint 批准的 postPublish hook。`planDigest` 仅作为内部绑定字段,不要求用户复制或确认。后续 approve/publish 只能使用该 immutable planPath,等待确认后再 approve。计划批准不包含受限 postPublish hook 的 checkpoint 批准
45
+ 1. 使用插件根相对路径运行 CLI:`CLI="node $RELEASE_SKILL_ENTRY"`。读取用户请求、项目权威指引和 `.release-skill/project.yaml`,固定目标版本、单元范围、候选状态和本轮写入授权。
46
+ 2. 配置首次接入或本轮发生变化时,运行只读评估 `${CLI} assess --root <path> --offline --json`;配置未变且已有对应检查证据时不重复评估。读取 `status` 和 `gaps[]` 并逐项分类,不能把整体 `ASSESSED` 当作生成前置,也不能只凭退出码宣布发布条件齐备:
47
+ - `CONFIG_INVALID` 必须先按结构化错误定位字段。只有已知合法值和本轮授权同时具备时才修复,随后复跑 assess;在此之前不得生成或运行完整测试,也不得放宽 schema 或猜值。
48
+ - 明确发布范围内的 missing/stale gap,如果能由项目已有且获授权的生成入口或发布文档协议解决,保留原 gap 并进入后续刷新链。配置本身未变时,使用刷新和聚焦检查的新证据继续,不为形式完整重复 assess。
49
+ - gap 需要用户输入,或缺少写入授权、权威入口或必要项目事实时,停在 `NEEDS_INPUT`,报告缺少的具体条件。
50
+ - 按发布单元保留 gap 归属。延期单元的问题不能证明已选单元通过,也不能据此自动增删范围。assess 的整体状态也不能单独阻断已选范围;最终结果由正式 prepare 的完整配置、新鲜度和 Hook 门禁裁决。
51
+ 3. 配置含 `releaseDocuments` 时,运行只读演练 `${CLI} docs refresh --unit <id> --json`。`status: "changes"` 时展示逐文件路径、语种、版本和 `refreshDigest`;取得“本地发布文档写入”明确授权后才执行 `nextCommand.argv`。审阅并提交刷新结果后再继续;`status: "clean"` 时进入下一步。
52
+ 4. 根据项目权威指引列出从配置到最终派生物的完整依赖链,并确认唯一生成责任。此时只选择现有入口,不开始生成:
53
+ - 项目已有外部完整生成入口时,记录该入口及对应聚焦检查。后续 build Hook 不得重复生成同一批输出。
54
+ - 可达的 `hooks.build` 已承担完整生成流程时,不在 prepare 外重复生成。必须从现有 Hook 命令确认它会刷新完整依赖链并执行所需聚焦检查;前置新鲜度门会先阻断时,不能期待 build Hook 修复输入。
55
+ - `releaseDocuments` 仍按上一步的专用刷新协议处理,不能改由 build Hook 绕过。
56
+ 5. 在首次生成、写候选或完整验证之前,核对项目合同中已知的环境前提。`envAllowlist` 只转发调用环境中已经存在的同名变量,不会生成值或证明值正确:
57
+ - 项目已有廉价前提检查时,先在当前环境原样运行同一入口。检查失败后保留原始错误,且不得开始生成、Hook 或昂贵测试。
58
+ - 只有项目合同给出合法值且本轮已经授权修正时,才修正后续命令环境;随后复跑同一廉价检查。没有值或授权时停在 `NEEDS_INPUT`。
59
+ - 项目没有廉价入口时,说明尚未验证的前提,再由正式 Hook 的实际结果裁决。不得临时编写检查脚本或把 assess 当成环境值检查。
60
+ 6. 外部生成入口承担责任时,在授权写集内运行一次该入口,再运行一次项目指定的聚焦检查。build Hook 承担责任时跳过本步,留给 prepare 执行;不得先手工调用同一生成流程。
61
+ 7. 普通路径不额外运行手动完整测试或 `hooks validate`。直接运行 `${CLI} prepare --root <path> --offline --json`,由 prepare 执行已声明 Hook 和完整验证;用户已明确选择范围时,为每个单元追加一个 `--unit <id>`。用户明确要求独立完整验收时保留该要求,即使正式 prepare 会再次运行完整 Hook。
62
+ 8. 检查 CLI exit code 0 和结构化状态 `PREPARED`。读取返回的不可变 `planPath=plans/<planDigest>.json`,再从该文件读取 `status`、`units` 和 `externalActions`。build Hook 承担生成时,还要从 Hook 输出及 evidence 确认完整依赖链和聚焦检查各执行一次。聚焦检查通过、Hook 通过和 `PREPARED` 是不同结果,不得互相代替。
63
+ 9. 向用户展示可读的 `approvalSummary`:版本、公开仓库、分支策略、branch/tag、npm 与 GitHub Release 目标、全部外部动作、例外,以及需要独立 checkpoint 批准的 postPublish hook。`planDigest` 仅作为内部绑定字段,不要求用户复制或确认。后续 approve/publish 只能使用该 immutable planPath,等待确认后再 approve。计划批准不包含受限 postPublish hook 的 checkpoint 批准。
64
+
65
+ 报告调用次数时,以本轮请求开始到取得结果或停止为计数窗口。分别列出生成命令、聚焦检查、正式 Hook 前提检查和昂贵测试。`prepare` 不是生成命令;一次 Hook 启动也不能证明昂贵测试已经进入测试体。优先使用工具转录、项目夹具输出和 CLI evidence,不能用模型自报替代实际记录。
66
+
67
+ ## 修复与重试
68
+
69
+ 一次失败后,集中核对该失败及其直接依赖。统一完成已授权修复,再运行现有聚焦检查;修复收敛后才重新尝试 prepare,不用完整门禁逐项寻找下一项问题。
70
+
71
+ 命令、目录、参数或环境错误由当前职责修正。环境改变后重新验证受影响的廉价入口和正式入口,过去的手动成功不能证明新环境。需要单独诊断 Hook 时可以使用 `hooks validate`,但须说明它会执行全部已声明 Hook,并可能写文件或访问网络。它不是每次 prepare 的固定前置步骤;缺少有效 cache 时,随后 prepare 会再次执行 Hook。
72
+
73
+ 同类产品失败连续两次时停止原样重试,检查依赖和入口是否选错。保留原始错误和输出;新诊断替换旧猜测,但不得覆盖已有日志或另建整改状态。
46
74
 
47
75
  若用户明确要求 GitHub+npm 生产发布,加入 `--production`。该模式还会封存独立
48
76
  Git commit/tree 和 npm tarball,并把路径、SHA/integrity、branch/tag 写入计划。
@@ -100,9 +128,7 @@ node "$RELEASE_SKILL_ENTRY" prepare --root <path> --online --production --json
100
128
  | RELEASE_DOCS_STALE | 文档相对说明源已陈旧;按详情运行只读演练,展示文件/语种/版本/摘要,经用户授权“本地发布文档写入”后执行写入,审阅提交再重新 prepare |
101
129
  | RELEASE_DOCS_INVALID / TRANSLATION_MISSING / CONFLICT / REFRESH_STALE | 修复配置/说明源/目标或重新演练取得新 `refreshDigest`;不得扩大写入范围绕过 |
102
130
  | SECRET_DETECTED | 移除密钥并更新 allowlist |
103
- | CONFIG_INVALID | 检查 version.source、package.json,以及 `--unit` 是否为空、重复或不在 `releaseUnits[]` 中 |
104
-
105
- 重试时只保留最新结构化错误码和失败门,不沿用早期猜测;重跑确定性命令获得新证据。
131
+ | CONFIG_INVALID | 先用 assess 定位结构化配置错误;检查 version.source、package.json、环境白名单是否为合法大写名称,以及 `--unit` 是否为空、重复或不在 `releaseUnits[]` 中。修复须使用已知合法值和明确写入授权 |
106
132
 
107
133
  ## 后续引导
108
134
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.13",
3
+ "version": "0.9.15",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"