release-skill 0.9.28 → 0.9.30

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 (35) 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/.cursor-plugin/plugin.json +1 -1
  5. package/.kimi-plugin/plugin.json +1 -1
  6. package/.qoder-plugin/plugin.json +1 -1
  7. package/CHANGELOG.md +70 -0
  8. package/INSTALL.md +2 -2
  9. package/INSTALL.zh-CN.md +2 -2
  10. package/README.md +16 -17
  11. package/README.zh-CN.md +16 -17
  12. package/adapters/claude/.claude-plugin/plugin.json +1 -1
  13. package/adapters/claude/bin/release-skill.bundle.mjs +15 -7
  14. package/adapters/claude/skills/release-help/SKILL.md +2 -2
  15. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  16. package/adapters/codex/bin/release-skill.bundle.mjs +15 -7
  17. package/adapters/codex/skills/release-help/SKILL.md +2 -2
  18. package/adapters/cursor/.cursor-plugin/plugin.json +1 -1
  19. package/adapters/cursor/bin/release-skill.bundle.mjs +15 -7
  20. package/adapters/cursor/skills/release-help/SKILL.md +2 -2
  21. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  22. package/adapters/kimi/bin/release-skill.bundle.mjs +15 -7
  23. package/adapters/kimi/skills/release-help/SKILL.md +2 -2
  24. package/adapters/qoder/.qoder-plugin/plugin.json +1 -1
  25. package/adapters/qoder/bin/release-skill.bundle.mjs +15 -7
  26. package/adapters/qoder/skills/release-help/SKILL.md +2 -2
  27. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
  28. package/adapters/workbuddy/bin/release-skill.bundle.mjs +15 -7
  29. package/adapters/workbuddy/skills/release-help/SKILL.md +2 -2
  30. package/bin/release-skill.bundle.mjs +15 -7
  31. package/package.json +1 -1
  32. package/platform-manifest.json +4 -4
  33. package/skills/release-help/SKILL.md +2 -2
  34. package/skills-src/release-help/SKILL.md +2 -2
  35. package/src/commands/post-release-local.mjs +15 -5
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
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.9.28.",
22
+ "Prepare a release plan for version 0.9.30.",
23
23
  "Help me understand the release workflow."
24
24
  ]
25
25
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
package/CHANGELOG.md CHANGED
@@ -1,5 +1,75 @@
1
1
  # Changelog
2
2
 
3
+ <!-- release-skill:changelog:start version=0.9.30 locale=en baseline=sha256:f96989498b14d998fb38751ca6bd2610255761ebb1618018ec2ca362ebe707a5 -->
4
+ ## [0.9.30] - 2026-10-16
5
+
6
+ 0.9.30 fixes the private Hub hook's missing release-evidence argument while retaining exact Foundation 0.25.0 dependencies. This note is not evidence of publication, real-host acceptance, consumer installation verification, or independent acceptance.
7
+
8
+ ### Security
9
+
10
+ - The hook rejects missing or invalid evidence paths before remote access; the authoritative Hub gate validates the original release evidence.
11
+ - Gate failure prevents Git Data API writes. Partial Hub publication is never rolled back or force-pushed, and completed steps are not overwritten. Writes remain bound to the observed branch head through compare-and-swap.
12
+
13
+ ### Changed
14
+
15
+ - Skill Family Hub remains the unified market; entries are updated via GitHub Git Data API after post-verify validation.
16
+
17
+ ### Fixed
18
+
19
+ - The private Hub hook forwards the absolute path supplied through `RELEASE_SKILL_HUB_RELEASE_EVIDENCE` to `npm run release:check -- --release-evidence <file>`. The path must name an existing regular file; symbolic links are rejected.
20
+
21
+ ### Upgrade Notes
22
+
23
+ Before running `postverify`, maintainers set the `RELEASE_SKILL_HUB_RELEASE_EVIDENCE` environment variable to the absolute path of the original Hub evidence descriptor; the existing `envAllowlist` forwards only that key. The descriptor and referenced native records are not copied or rewritten.
24
+
25
+ A new plan freezes the corrected hook and still requires independent checkpoint approval. Historical plans, approvals and frozen hooks remain unchanged and are not replayed. `ALREADY_CURRENT` still requires the authoritative Hub gate.
26
+
27
+ Existing Hub users need no configuration migration. The old release-skill standalone marketplace is deprecated; use `ifoohoo/skill-family-hub` and `release-skill@skill-family-hub`.
28
+
29
+ This note does not authorize publication or prove real-host business or consumer installation verification. No consumer installation or update is added.
30
+ <!-- release-skill:changelog:end version=0.9.30 locale=en -->
31
+
32
+
33
+ <!-- release-skill:changelog:start version=0.9.29 locale=en baseline=sha256:b0f764fb7dc5897a2bc031a06114e766eb3bb2a39fe4778c0c23bc620921bf40 -->
34
+ ## [0.9.29] - 2026-10-16
35
+
36
+ 0.9.29 fixes Qoder local updates rejecting the valid ./skills/ layout in Foundation 0.25.0's frozen manifest. This note is not evidence of publication, real-host acceptance, consumer installation verification, or independent acceptance.
37
+
38
+ ### Security
39
+
40
+ - The skills path must be a non-empty string naming an existing directory within the plugin. The installed name/version/skills must match this release's frozen manifest. Both UPDATED and ALREADY_CURRENT branches validate the actual installed payload.
41
+ - Frozen snapshot digest, identity, Hub repository/ref and entry source.url/source.sha checks remain in effect. Missing, invalid or escaping paths and payload drift still fail; no automatic initial installation is added.
42
+ - Hub writes remain bound to the observed branch head through compare-and-swap. Partial Hub publication is never rolled back or force-pushed automatically, and completed steps are not overwritten.
43
+
44
+ ### Changed
45
+
46
+ - Skill Family Hub remains the unified marketplace. After release validation, Hub entries are updated via GitHub Git Data API. This mechanism remains unchanged and is not claimed to have been executed in this release.
47
+
48
+ ### Fixed
49
+
50
+ - Resolved incorrect path hardcoding in 0.9.28 that rejected valid ./skills/ directory from Foundation 0.25.0's frozen manifest. Qoder plugins now read skills path from verified frozen manifest, ensuring compatibility with both ./adapters/qoder/skills/ and ./skills/ layouts.
51
+
52
+ ### Upgrade Notes
53
+
54
+ - Existing installations may continue using the existing local-finish entry point,
55
+ provided they maintain authorization.
56
+
57
+ - The release note does not constitute a release authorization, nor does it confirm
58
+ real-world host business validation.
59
+
60
+ - Do not infer published status from this document; actual release status must be
61
+ referenced from approved plans, approvals, and execution records.
62
+
63
+ - The path must be a valid existing directory within the plugin and match the frozen
64
+ manifest exactly.
65
+
66
+ - No new configuration parameters or migration steps are introduced.
67
+ - Users of the existing Skill Family Hub do not need to perform configuration migration.
68
+ - The old release-skill standalone marketplace is deprecated and should be removed.
69
+ Replace it with the `ifoohoo/skill-family-hub` repository and `release-skill@skill-family-hub`.
70
+ <!-- release-skill:changelog:end version=0.9.29 locale=en -->
71
+
72
+
3
73
  <!-- release-skill:changelog:start version=0.9.28 locale=en baseline=sha256:cd1f7e8115d51b08d4d406835280d7be7716c5010255adb0afa4d3e4d4eadac6 -->
4
74
  ## [0.9.28] - 2026-10-15
5
75
 
package/INSTALL.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [简体中文](INSTALL.zh-CN.md)
4
4
 
5
- <!-- release-skill:release-version: 0.9.28 -->
5
+ <!-- release-skill:release-version: 0.9.30 -->
6
6
  ## Prerequisites
7
7
 
8
8
  - Node.js `>=22.22.2 <23` (22.22.2 or newer, and below 23)
@@ -125,7 +125,7 @@ tag pinned to the exact version (never the bare repository URL, which installs
125
125
  the latest release or default branch), confirm the trust prompt, then reload:
126
126
 
127
127
  ```
128
- /plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.28
128
+ /plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.30
129
129
  /plugins reload
130
130
  ```
131
131
 
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.9.28 -->
5
+ <!-- release-skill:release-version: 0.9.30 -->
6
6
  ## 前置条件
7
7
 
8
8
  - Node.js `>=22.22.2 <23`(22.22.2 及以上,且低于 23)
@@ -113,7 +113,7 @@ release-skill 当前只采用并验证 Kimi Code 的交互式 TUI 路径,**无
113
113
  (切勿使用裸仓库地址,它会安装最新 release 或默认分支),确认信任提示后重新加载:
114
114
 
115
115
  ```
116
- /plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.28
116
+ /plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.30
117
117
  /plugins reload
118
118
  ```
119
119
 
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.9.28 -->
5
+ <!-- release-skill:release-version: 0.9.30 -->
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,37 +14,36 @@ 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.9.28** (2026-10-15)
17
+ **0.9.30** (2026-10-16)
18
18
 
19
- 0.9.28 adds optional host coverage diagnosis to `setup --assess-adoption`, checking whether hosts in the declared scope have the required release wiring. The three Foundation dependencies are pinned to 0.25.0. The Codex 0.154.0 static loading check consumes the original bytes of 11 generated Skills in an isolated project; this does not establish installation, session selection, or business execution. This note is not evidence of publication, real-host acceptance, consumer installation verification, or independent acceptance.
19
+ 0.9.30 fixes the private Hub hook's missing release-evidence argument while retaining exact Foundation 0.25.0 dependencies. This note is not evidence of publication, real-host acceptance, consumer installation verification, or independent acceptance.
20
20
 
21
21
  **Security**
22
22
 
23
- - Existing safety boundaries are unchanged: Hub publication remains a compare-and-swap operation bound to the observed branch head. Partial Hub publication is never rolled back or force-pushed automatically, and completed steps are not overwritten.
24
- - Approval, publication, post-publication verification, consumer installation, real-host loading, and independent acceptance still require their own actual records. This note does not prove any of those outcomes. Reading a Kimi plugin manifest does not establish authentication or real-host qualification.
25
-
26
- **Added**
27
-
28
- - `--host-coverage <file>` accepts an input file specifying declared support scope, delivery scope for this round, initial installation obligations, and installation observations, reporting per-host coverage status and factual gaps; Skill collects facts and interprets CLI output but does not implement comparison logic.
29
- - `--observe-hosts` uses commands defined by the platform registry to read plugin lists for in-scope Claude and Codex hosts when coverage input is explicitly supplied, and checks plugin and marketplace identities. Excluded targets and targets without identity do not trigger native commands.
23
+ - The hook rejects missing or invalid evidence paths before remote access; the authoritative Hub gate validates the original release evidence.
24
+ - Gate failure prevents Git Data API writes. Partial Hub publication is never rolled back or force-pushed, and completed steps are not overwritten. Writes remain bound to the observed branch head through compare-and-swap.
30
25
 
31
26
  **Changed**
32
27
 
33
- - The three Foundation dependencies are pinned to 0.25.0. The Codex 0.154.0 static loading check consumes the original bytes of 11 generated Skills in an isolated project; this does not establish installation, session selection, or business execution.
34
- - The distribution path is unchanged: Skill Family Hub remains the central marketplace, and its entry is still updated through the existing GitHub Git Data API after release verification.
28
+ - Skill Family Hub remains the unified market; entries are updated via GitHub Git Data API after post-verify validation.
35
29
 
36
30
  **Fixed**
37
31
 
38
- - Records missing identity, source, a valid observation timestamp, or installed version are not considered successful coverage; real-time unknown status cannot be overridden by old installed snapshots; multiple list entries matching the target are rejected; invalid or duplicate inputs still bind to the existing digest binding.
39
- - Kimi direct release and Hub localHostUpdate records that bind the same unit, host, plugin, version, GitHub host, repository, tag, and commit now merge into exactly one existing direct executable target. Marketplace index metadata is irrelevant only for Kimi, whose installation uses the frozen GitHub release. Different frozen identities still fail closed. Other hosts retain current marketplace identity checks.
32
+ - The private Hub hook forwards the absolute path supplied through `RELEASE_SKILL_HUB_RELEASE_EVIDENCE` to `npm run release:check -- --release-evidence <file>`. The path must name an existing regular file; symbolic links are rejected.
40
33
 
41
34
  **Upgrade Notes**
42
35
 
43
- For consumers already using Skill Family Hub, no configuration migration is required. Installations still using the old release-skill standalone marketplace should remove it and use the ifoohoo/skill-family-hub repository with the Hub-qualified plugin id release-skill@skill-family-hub; this migration path is unchanged. The existing --unit release-selection contract is unchanged. Without new options, the original four top-level states and exit codes are preserved, and no host scanning occurs; no plugin installation or updates, no host configuration or credential modifications; observed installation lists do not imply actual loading or business execution; existing configurations require no migration; explicit fact file input is mandatory for this round’s coverage check.
36
+ Before running `postverify`, maintainers set the `RELEASE_SKILL_HUB_RELEASE_EVIDENCE` environment variable to the absolute path of the original Hub evidence descriptor; the existing `envAllowlist` forwards only that key. The descriptor and referenced native records are not copied or rewritten.
37
+
38
+ A new plan freezes the corrected hook and still requires independent checkpoint approval. Historical plans, approvals and frozen hooks remain unchanged and are not replayed. `ALREADY_CURRENT` still requires the authoritative Hub gate.
39
+
40
+ Existing Hub users need no configuration migration. The old release-skill standalone marketplace is deprecated; use `ifoohoo/skill-family-hub` and `release-skill@skill-family-hub`.
41
+
42
+ This note does not authorize publication or prove real-host business or consumer installation verification. No consumer installation or update is added.
44
43
  <!-- release-skill:managed:end id=latest-release -->
45
44
 
46
45
  <!-- release-skill:capability:external-write-boundary -->
47
- > **Current boundary:** v0.9.28: this README records capabilities and verification boundaries;
46
+ > **Current boundary:** v0.9.30: this README records capabilities and verification boundaries;
48
47
  > it is not evidence of
49
48
  > publication, consumer-installation verification, or independent acceptance.
50
49
  > Release availability must be established from the corresponding release records
@@ -68,7 +67,7 @@ For consumers already using Skill Family Hub, no configuration migration is requ
68
67
  > publish global preflight.
69
68
 
70
69
  <!-- release-skill:capability:safe-first-command -->
71
- > **Production path verified since the v0.1.1 milestone; for v0.9.28,
70
+ > **Production path verified since the v0.1.1 milestone; for v0.9.30,
72
71
  > publication, consumer-installation verification, and independent acceptance
73
72
  > require version-specific release records and verification results.**
74
73
  > The npm-installed CLI is the supported user entry. Source checkout
package/README.zh-CN.md CHANGED
@@ -2,43 +2,42 @@
2
2
 
3
3
  [English](README.md) · 安装指南:[中文](INSTALL.zh-CN.md) / [English](INSTALL.md)
4
4
 
5
- <!-- release-skill:release-version: 0.9.28 -->
5
+ <!-- release-skill:release-version: 0.9.30 -->
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.9.28** (2026-10-15)
11
+ **0.9.30** (2026-10-16)
12
12
 
13
- 0.9.28 版本新增可选宿主接入覆盖诊断功能,通过 `setup --assess-adoption` 的可选参数,核对声明范围内的宿主是否具备所需接线。该版本精确依赖 Foundation 0.25.0 的公开包根 API,采用 Codex 0.154.0 静态加载规则检查,基于 11 份真实生成 Skill 的原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。本说明不代表已经发布、完成真实宿主验收、完成消费者安装验证或通过独立验收。
13
+ 0.9.30 修复项目私有 Hub 钩子漏传发布证据参数的问题,继续使用精确的 Foundation 0.25.0 依赖。本说明不代表已经发布、完成真实宿主验收、完成消费者安装验证或通过独立验收。
14
14
 
15
15
  **安全**
16
16
 
17
- - 既有安全边界保持不变:Hub 写入继续绑定已观察的分支头,按 compare-and-swap 比较后写入。部分发布时不回滚、不覆盖已成功步骤,也不自动强推。
18
- - 批准、发布、发布后验证、消费者安装、真实宿主加载和独立验收仍分别需要实际记录。本说明不能证明这些结果,读取 Kimi 插件清单也不能证明认证已成立或真实宿主资格已经通过。
19
-
20
- **新增**
21
-
22
- - `--host-coverage <file>` 接收包含项目声明支持范围、本轮交付范围、首次安装义务与安装观察的输入文件,报告每个宿主的覆盖状态及事实缺口;Skill 仅负责收集事实并解释 CLI 输出,不参与差异比较逻辑。
23
- - `--observe-hosts` 在显式提供覆盖输入时,使用平台注册表定义的命令只读获取本轮纳入的 Claude、Codex 插件列表,核对插件与市场身份;已排除或缺少身份的目标不启动原生命令。
17
+ - 钩子在访问远端前拒绝缺失或非法的证据路径,证据内容交由 Hub 正式门禁验证。
18
+ - 门禁失败不进行 Git Data API 写入;部分发布不回滚、不覆盖已完成步骤、不自动强推;写入绑定观察到的分支头并比较后写入。
24
19
 
25
20
  **变更**
26
21
 
27
- - Foundation 三个依赖锁步升级为 0.25.0,采用 Codex 0.154.0 静态加载规则检查,基于11份真实生成Skill原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。
28
- - 分发路径保持不变:Skill Family Hub 仍是统一市场;发布验证完成后,Hub 条目仍通过既有 GitHub Git Data API 更新。
22
+ - Skill Family Hub 仍是统一市场,验证后经 GitHub Git Data API 更新条目。
29
23
 
30
24
  **修复**
31
25
 
32
- - 缺失身份、来源、有效时间或 installed 版本的记录不能视为覆盖成功;实时未知状态不能由旧的 installed 快照覆盖;同一目标匹配多条列表记录时将被拒绝;无效或重复输入仍绑定原有摘要路径。
33
- - Kimi 的直接发布记录与 Hub 的 localHostUpdate 记录绑定同一单元、宿主、插件、版本、GitHub 主机、仓库、标签和提交时,合并为一个原有可执行目标。Kimi 使用冻结的 GitHub Release,该场景不再比较市场索引元数据;不同冻结身份仍被拒绝。其他宿主的市场身份校验保持不变。
26
+ - 项目私有 Hub 钩子把 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE` 指定的绝对路径传给 `npm run release:check -- --release-evidence <file>`。路径必须指向已有普通文件,不接受符号链接。
34
27
 
35
28
  **升级说明**
36
29
 
37
- 已使用 Skill Family Hub 的消费者升级时无需迁移配置。若仍使用旧版独立的 `release-skill` 市场,应移除旧市场,改用 ifoohoo/skill-family-hub 仓库与 Hub 限定插件名 release-skill@skill-family-hub;这条迁移路径保持不变。既有 --unit 选择合同保持不变。 不使用新选项时,保留原有的四种顶层状态和退出码,不扫描宿主;不安装或更新插件,不修改宿主配置或凭据;安装列表的观察结果不证明插件已真实加载或完成业务执行;现有配置无需迁移;本轮覆盖检查需显式提供事实文件。
30
+ 维护者在运行 `postverify` 前,将环境变量 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE` 设为原始 Hub 证据描述符的绝对路径;现有 `envAllowlist` 只转发该键。描述符及其引用的原生记录不复制、不改写。
31
+
32
+ 新计划冻结修正的钩子,仍须取得独立检查点批准;历史计划、批准和冻结钩子保持不变,不重放。`ALREADY_CURRENT` 仍须通过 Hub 正式门禁。
33
+
34
+ 已使用 Hub 的用户无需配置迁移。旧版独立的 `release-skill` 市场已弃用,应改用 `ifoohoo/skill-family-hub` 与 `release-skill@skill-family-hub`。
35
+
36
+ 本说明不授权发布,也不证明真实宿主业务或消费者安装验证完成;不新增消费者安装或更新动作。
38
37
  <!-- release-skill:managed:end id=latest-release -->
39
38
 
40
39
  <!-- release-skill:capability:external-write-boundary -->
41
- > **当前边界:** v0.9.28 的能力范围与验证边界见本 README,
40
+ > **当前边界:** v0.9.30 的能力范围与验证边界见本 README,
42
41
  > 不代表已经发布、完成消费者安装验证或通过独立验收。
43
42
  > 版本可用性以对应发布记录及发布后验证结果为准。
44
43
  > v0.4.1 是更早的已发布里程碑(v0.2.2 曾处于已发布状态,后因平台验证收敛修复而更新)。
@@ -54,7 +53,7 @@ release-skill 帮助维护者回答三个问题:准备发布什么、还有哪
54
53
  > 远端唯一性检查在 `publish` 全局预检执行。
55
54
 
56
55
  <!-- release-skill:capability:safe-first-command -->
57
- > **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.9.28 的发布、消费者安装验证和独立验收状态须由该版本的发布记录及验证结果确认。**
56
+ > **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.9.30 的发布、消费者安装验证和独立验收状态须由该版本的发布记录及验证结果确认。**
58
57
  > npm 安装的 CLI 是受支持的用户入口;源码 checkout 保留为开发/贡献者路径。
59
58
  >
60
59
  > **第一条命令:**
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -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.9.28"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.30"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "9683591bbfad41292831f35e071273e6812b7e5b27adcb0e237dac9672605a36";
14
+ const __bundleSourceDigest = "52acbaddf4e589b42b49defb03ff5dfa59e0306f37a3ce0e8e3aaa240b9cfba4";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136643,10 +136643,15 @@ async function readQoderManifest(root, label) {
136643
136643
  }
136644
136644
  return manifest;
136645
136645
  }
136646
- function assertQoderPluginManifest(target, manifest, label) {
136647
- if (manifest.name !== target.plugin || manifest.version !== target.version || manifest.skills !== "./adapters/qoder/skills/") {
136646
+ async function assertQoderPluginManifest(target, manifest, label, pluginRoot, frozenSkills) {
136647
+ if (manifest.name !== target.plugin || manifest.version !== target.version || typeof manifest.skills !== "string" || manifest.skills.length === 0 || frozenSkills !== void 0 && manifest.skills !== frozenSkills) {
136648
136648
  throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path`);
136649
136649
  }
136650
+ const skillsRoot = await resolveContained(pluginRoot, manifest.skills);
136651
+ if (!(await lstat45(skillsRoot)).isDirectory()) {
136652
+ throw new Error(`${label} skills path must name a contained directory`);
136653
+ }
136654
+ return manifest.skills;
136650
136655
  }
136651
136656
  async function assertFrozenQoderManifest(target, root) {
136652
136657
  const { snapshotDir: snapshotRoot } = await verifyFrozenSnapshot({
@@ -136655,7 +136660,7 @@ async function assertFrozenQoderManifest(target, root) {
136655
136660
  expectedDigest: target.manifestDigest
136656
136661
  });
136657
136662
  const manifest = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest");
136658
- assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest");
136663
+ return assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest", snapshotRoot);
136659
136664
  }
136660
136665
  async function assertQoderHubEntry(target, marketplaceRoot) {
136661
136666
  const marketplace = parseJson2(
@@ -136678,10 +136683,11 @@ async function verifyQoderInstalledPayload({
136678
136683
  target,
136679
136684
  root,
136680
136685
  installPath,
136686
+ frozenSkills,
136681
136687
  verifyInstalledPayload
136682
136688
  }) {
136683
136689
  const manifest = await readQoderManifest(installPath, "installed Qoder plugin manifest");
136684
- assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest");
136690
+ await assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest", installPath, frozenSkills);
136685
136691
  await verifyInstalledPayload({
136686
136692
  snapshotPath: target.snapshotPath,
136687
136693
  manifestDigest: target.manifestDigest,
@@ -136694,7 +136700,7 @@ async function runQoderUpdate(target, detected, run6, {
136694
136700
  verifyInstalledPayload
136695
136701
  }) {
136696
136702
  const env = hostEnvironment("qoder");
136697
- await assertFrozenQoderManifest(target, root);
136703
+ const frozenSkills = await assertFrozenQoderManifest(target, root);
136698
136704
  const marketplace = await observeQoderMarketplace(target, detected.command, env, run6);
136699
136705
  if (!marketplace.installed) {
136700
136706
  return {
@@ -136715,6 +136721,7 @@ async function runQoderUpdate(target, detected, run6, {
136715
136721
  target,
136716
136722
  root,
136717
136723
  installPath: before.installPath,
136724
+ frozenSkills,
136718
136725
  verifyInstalledPayload
136719
136726
  });
136720
136727
  return { status: "ALREADY_CURRENT", version: target.version };
@@ -136741,6 +136748,7 @@ async function runQoderUpdate(target, detected, run6, {
136741
136748
  target,
136742
136749
  root,
136743
136750
  installPath: after.installPath,
136751
+ frozenSkills,
136744
136752
  verifyInstalledPayload
136745
136753
  });
136746
136754
  return {
@@ -29,9 +29,9 @@ description: "Discoverable entry point for release-skill: dependency and environ
29
29
 
30
30
  治理诊断只运行 release-skill 自己的只读检查程序,不运行目标 Skill、业务脚本、构建、hook 或发布动作,也不把 `prepare`、`verify`、`release-finish` 当作静态治理入口。用户要求实际接入或发布时,把已有授权带到对应原业务入口;各入口继续执行原有确认、副作用和状态机合同。
31
31
 
32
- ## 0.9.28 能力与证据边界
32
+ ## 0.9.30 能力与证据边界
33
33
 
34
- release-skill 0.9.28 精确依赖 Foundation 0.25.0 的公开包根 API。本版本新增可选宿主覆盖诊断能力,支持通过 `--host-coverage <file>` 提供输入文件,报告每个宿主在声明范围内的覆盖状态与事实缺口;同时采用 Codex 0.154.0 静态加载规则检查,基于 11 份真实生成 Skill 的原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。批准、发布和验证状态以对应计划、批准及执行记录为准,不能由本说明推断。
34
+ release-skill 0.9.30 保留 Foundation 0.25.0 精确依赖、可选宿主覆盖诊断输入 `--host-coverage <file>` 与 `--observe-hosts`、Codex 0.154.0 静态加载规则检查 11 份真实生成 Skill 的原字节等既有事实;本版修复私有 Hub 的 postVerify 钩子:通过既有 `envAllowlist` 传递 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE`,其值为原始描述符所指向的已有普通文件绝对路径(拒绝符号链接),交由 Hub `npm run release:check -- --release-evidence <file>` 验证。Qoder 本机更新路径处理维持既有能力,支持 `./adapters/qoder/skills/` 与 `./skills/` 两种布局,仍核对安装 name/version/skills、路径包含性与实际载荷。静态检查不证明安装、会话选择或业务执行通过,批准、发布和验证状态以对应计划、批准及执行记录为准。
35
35
 
36
36
  在冻结前,`prepare` 或新建 `ship` 状态时可重复传入 `--unit <id>`;未传入则默认选择全部单元。延期单元不进入发布计划,亦不获得发布状态。完整配置、生成物新鲜度检查及顶层 Hook 仍作用于全项目范围。`publicSourceAuthorityReceipt` 的 coordinator 与全部 subjects 必须共同选择。
37
37
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
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.9.28.",
22
+ "Prepare a release plan for version 0.9.30.",
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.9.28"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.30"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "9683591bbfad41292831f35e071273e6812b7e5b27adcb0e237dac9672605a36";
14
+ const __bundleSourceDigest = "52acbaddf4e589b42b49defb03ff5dfa59e0306f37a3ce0e8e3aaa240b9cfba4";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136643,10 +136643,15 @@ async function readQoderManifest(root, label) {
136643
136643
  }
136644
136644
  return manifest;
136645
136645
  }
136646
- function assertQoderPluginManifest(target, manifest, label) {
136647
- if (manifest.name !== target.plugin || manifest.version !== target.version || manifest.skills !== "./adapters/qoder/skills/") {
136646
+ async function assertQoderPluginManifest(target, manifest, label, pluginRoot, frozenSkills) {
136647
+ if (manifest.name !== target.plugin || manifest.version !== target.version || typeof manifest.skills !== "string" || manifest.skills.length === 0 || frozenSkills !== void 0 && manifest.skills !== frozenSkills) {
136648
136648
  throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path`);
136649
136649
  }
136650
+ const skillsRoot = await resolveContained(pluginRoot, manifest.skills);
136651
+ if (!(await lstat45(skillsRoot)).isDirectory()) {
136652
+ throw new Error(`${label} skills path must name a contained directory`);
136653
+ }
136654
+ return manifest.skills;
136650
136655
  }
136651
136656
  async function assertFrozenQoderManifest(target, root) {
136652
136657
  const { snapshotDir: snapshotRoot } = await verifyFrozenSnapshot({
@@ -136655,7 +136660,7 @@ async function assertFrozenQoderManifest(target, root) {
136655
136660
  expectedDigest: target.manifestDigest
136656
136661
  });
136657
136662
  const manifest = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest");
136658
- assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest");
136663
+ return assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest", snapshotRoot);
136659
136664
  }
136660
136665
  async function assertQoderHubEntry(target, marketplaceRoot) {
136661
136666
  const marketplace = parseJson2(
@@ -136678,10 +136683,11 @@ async function verifyQoderInstalledPayload({
136678
136683
  target,
136679
136684
  root,
136680
136685
  installPath,
136686
+ frozenSkills,
136681
136687
  verifyInstalledPayload
136682
136688
  }) {
136683
136689
  const manifest = await readQoderManifest(installPath, "installed Qoder plugin manifest");
136684
- assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest");
136690
+ await assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest", installPath, frozenSkills);
136685
136691
  await verifyInstalledPayload({
136686
136692
  snapshotPath: target.snapshotPath,
136687
136693
  manifestDigest: target.manifestDigest,
@@ -136694,7 +136700,7 @@ async function runQoderUpdate(target, detected, run6, {
136694
136700
  verifyInstalledPayload
136695
136701
  }) {
136696
136702
  const env = hostEnvironment("qoder");
136697
- await assertFrozenQoderManifest(target, root);
136703
+ const frozenSkills = await assertFrozenQoderManifest(target, root);
136698
136704
  const marketplace = await observeQoderMarketplace(target, detected.command, env, run6);
136699
136705
  if (!marketplace.installed) {
136700
136706
  return {
@@ -136715,6 +136721,7 @@ async function runQoderUpdate(target, detected, run6, {
136715
136721
  target,
136716
136722
  root,
136717
136723
  installPath: before.installPath,
136724
+ frozenSkills,
136718
136725
  verifyInstalledPayload
136719
136726
  });
136720
136727
  return { status: "ALREADY_CURRENT", version: target.version };
@@ -136741,6 +136748,7 @@ async function runQoderUpdate(target, detected, run6, {
136741
136748
  target,
136742
136749
  root,
136743
136750
  installPath: after.installPath,
136751
+ frozenSkills,
136744
136752
  verifyInstalledPayload
136745
136753
  });
136746
136754
  return {
@@ -37,9 +37,9 @@ description: "Discoverable entry point for release-skill: dependency and environ
37
37
 
38
38
  治理诊断只运行 release-skill 自己的只读检查程序,不运行目标 Skill、业务脚本、构建、hook 或发布动作,也不把 `prepare`、`verify`、`release-finish` 当作静态治理入口。用户要求实际接入或发布时,把已有授权带到对应原业务入口;各入口继续执行原有确认、副作用和状态机合同。
39
39
 
40
- ## 0.9.28 能力与证据边界
40
+ ## 0.9.30 能力与证据边界
41
41
 
42
- release-skill 0.9.28 精确依赖 Foundation 0.25.0 的公开包根 API。本版本新增可选宿主覆盖诊断能力,支持通过 `--host-coverage <file>` 提供输入文件,报告每个宿主在声明范围内的覆盖状态与事实缺口;同时采用 Codex 0.154.0 静态加载规则检查,基于 11 份真实生成 Skill 的原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。批准、发布和验证状态以对应计划、批准及执行记录为准,不能由本说明推断。
42
+ release-skill 0.9.30 保留 Foundation 0.25.0 精确依赖、可选宿主覆盖诊断输入 `--host-coverage <file>` 与 `--observe-hosts`、Codex 0.154.0 静态加载规则检查 11 份真实生成 Skill 的原字节等既有事实;本版修复私有 Hub 的 postVerify 钩子:通过既有 `envAllowlist` 传递 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE`,其值为原始描述符所指向的已有普通文件绝对路径(拒绝符号链接),交由 Hub `npm run release:check -- --release-evidence <file>` 验证。Qoder 本机更新路径处理维持既有能力,支持 `./adapters/qoder/skills/` 与 `./skills/` 两种布局,仍核对安装 name/version/skills、路径包含性与实际载荷。静态检查不证明安装、会话选择或业务执行通过,批准、发布和验证状态以对应计划、批准及执行记录为准。
43
43
 
44
44
  在冻结前,`prepare` 或新建 `ship` 状态时可重复传入 `--unit <id>`;未传入则默认选择全部单元。延期单元不进入发布计划,亦不获得发布状态。完整配置、生成物新鲜度检查及顶层 Hook 仍作用于全项目范围。`publicSourceAuthorityReceipt` 的 coordinator 与全部 subjects 必须共同选择。
45
45
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -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.9.28"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.30"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "9683591bbfad41292831f35e071273e6812b7e5b27adcb0e237dac9672605a36";
14
+ const __bundleSourceDigest = "52acbaddf4e589b42b49defb03ff5dfa59e0306f37a3ce0e8e3aaa240b9cfba4";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136643,10 +136643,15 @@ async function readQoderManifest(root, label) {
136643
136643
  }
136644
136644
  return manifest;
136645
136645
  }
136646
- function assertQoderPluginManifest(target, manifest, label) {
136647
- if (manifest.name !== target.plugin || manifest.version !== target.version || manifest.skills !== "./adapters/qoder/skills/") {
136646
+ async function assertQoderPluginManifest(target, manifest, label, pluginRoot, frozenSkills) {
136647
+ if (manifest.name !== target.plugin || manifest.version !== target.version || typeof manifest.skills !== "string" || manifest.skills.length === 0 || frozenSkills !== void 0 && manifest.skills !== frozenSkills) {
136648
136648
  throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path`);
136649
136649
  }
136650
+ const skillsRoot = await resolveContained(pluginRoot, manifest.skills);
136651
+ if (!(await lstat45(skillsRoot)).isDirectory()) {
136652
+ throw new Error(`${label} skills path must name a contained directory`);
136653
+ }
136654
+ return manifest.skills;
136650
136655
  }
136651
136656
  async function assertFrozenQoderManifest(target, root) {
136652
136657
  const { snapshotDir: snapshotRoot } = await verifyFrozenSnapshot({
@@ -136655,7 +136660,7 @@ async function assertFrozenQoderManifest(target, root) {
136655
136660
  expectedDigest: target.manifestDigest
136656
136661
  });
136657
136662
  const manifest = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest");
136658
- assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest");
136663
+ return assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest", snapshotRoot);
136659
136664
  }
136660
136665
  async function assertQoderHubEntry(target, marketplaceRoot) {
136661
136666
  const marketplace = parseJson2(
@@ -136678,10 +136683,11 @@ async function verifyQoderInstalledPayload({
136678
136683
  target,
136679
136684
  root,
136680
136685
  installPath,
136686
+ frozenSkills,
136681
136687
  verifyInstalledPayload
136682
136688
  }) {
136683
136689
  const manifest = await readQoderManifest(installPath, "installed Qoder plugin manifest");
136684
- assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest");
136690
+ await assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest", installPath, frozenSkills);
136685
136691
  await verifyInstalledPayload({
136686
136692
  snapshotPath: target.snapshotPath,
136687
136693
  manifestDigest: target.manifestDigest,
@@ -136694,7 +136700,7 @@ async function runQoderUpdate(target, detected, run6, {
136694
136700
  verifyInstalledPayload
136695
136701
  }) {
136696
136702
  const env = hostEnvironment("qoder");
136697
- await assertFrozenQoderManifest(target, root);
136703
+ const frozenSkills = await assertFrozenQoderManifest(target, root);
136698
136704
  const marketplace = await observeQoderMarketplace(target, detected.command, env, run6);
136699
136705
  if (!marketplace.installed) {
136700
136706
  return {
@@ -136715,6 +136721,7 @@ async function runQoderUpdate(target, detected, run6, {
136715
136721
  target,
136716
136722
  root,
136717
136723
  installPath: before.installPath,
136724
+ frozenSkills,
136718
136725
  verifyInstalledPayload
136719
136726
  });
136720
136727
  return { status: "ALREADY_CURRENT", version: target.version };
@@ -136741,6 +136748,7 @@ async function runQoderUpdate(target, detected, run6, {
136741
136748
  target,
136742
136749
  root,
136743
136750
  installPath: after.installPath,
136751
+ frozenSkills,
136744
136752
  verifyInstalledPayload
136745
136753
  });
136746
136754
  return {
@@ -38,9 +38,9 @@ description: "Discoverable entry point for release-skill: dependency and environ
38
38
 
39
39
  治理诊断只运行 release-skill 自己的只读检查程序,不运行目标 Skill、业务脚本、构建、hook 或发布动作,也不把 `prepare`、`verify`、`release-finish` 当作静态治理入口。用户要求实际接入或发布时,把已有授权带到对应原业务入口;各入口继续执行原有确认、副作用和状态机合同。
40
40
 
41
- ## 0.9.28 能力与证据边界
41
+ ## 0.9.30 能力与证据边界
42
42
 
43
- release-skill 0.9.28 精确依赖 Foundation 0.25.0 的公开包根 API。本版本新增可选宿主覆盖诊断能力,支持通过 `--host-coverage <file>` 提供输入文件,报告每个宿主在声明范围内的覆盖状态与事实缺口;同时采用 Codex 0.154.0 静态加载规则检查,基于 11 份真实生成 Skill 的原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。批准、发布和验证状态以对应计划、批准及执行记录为准,不能由本说明推断。
43
+ release-skill 0.9.30 保留 Foundation 0.25.0 精确依赖、可选宿主覆盖诊断输入 `--host-coverage <file>` 与 `--observe-hosts`、Codex 0.154.0 静态加载规则检查 11 份真实生成 Skill 的原字节等既有事实;本版修复私有 Hub 的 postVerify 钩子:通过既有 `envAllowlist` 传递 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE`,其值为原始描述符所指向的已有普通文件绝对路径(拒绝符号链接),交由 Hub `npm run release:check -- --release-evidence <file>` 验证。Qoder 本机更新路径处理维持既有能力,支持 `./adapters/qoder/skills/` 与 `./skills/` 两种布局,仍核对安装 name/version/skills、路径包含性与实际载荷。静态检查不证明安装、会话选择或业务执行通过,批准、发布和验证状态以对应计划、批准及执行记录为准。
44
44
 
45
45
  在冻结前,`prepare` 或新建 `ship` 状态时可重复传入 `--unit <id>`;未传入则默认选择全部单元。延期单元不进入发布计划,亦不获得发布状态。完整配置、生成物新鲜度检查及顶层 Hook 仍作用于全项目范围。`publicSourceAuthorityReceipt` 的 coordinator 与全部 subjects 必须共同选择。
46
46
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -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.9.28"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.30"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "9683591bbfad41292831f35e071273e6812b7e5b27adcb0e237dac9672605a36";
14
+ const __bundleSourceDigest = "52acbaddf4e589b42b49defb03ff5dfa59e0306f37a3ce0e8e3aaa240b9cfba4";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136643,10 +136643,15 @@ async function readQoderManifest(root, label) {
136643
136643
  }
136644
136644
  return manifest;
136645
136645
  }
136646
- function assertQoderPluginManifest(target, manifest, label) {
136647
- if (manifest.name !== target.plugin || manifest.version !== target.version || manifest.skills !== "./adapters/qoder/skills/") {
136646
+ async function assertQoderPluginManifest(target, manifest, label, pluginRoot, frozenSkills) {
136647
+ if (manifest.name !== target.plugin || manifest.version !== target.version || typeof manifest.skills !== "string" || manifest.skills.length === 0 || frozenSkills !== void 0 && manifest.skills !== frozenSkills) {
136648
136648
  throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path`);
136649
136649
  }
136650
+ const skillsRoot = await resolveContained(pluginRoot, manifest.skills);
136651
+ if (!(await lstat45(skillsRoot)).isDirectory()) {
136652
+ throw new Error(`${label} skills path must name a contained directory`);
136653
+ }
136654
+ return manifest.skills;
136650
136655
  }
136651
136656
  async function assertFrozenQoderManifest(target, root) {
136652
136657
  const { snapshotDir: snapshotRoot } = await verifyFrozenSnapshot({
@@ -136655,7 +136660,7 @@ async function assertFrozenQoderManifest(target, root) {
136655
136660
  expectedDigest: target.manifestDigest
136656
136661
  });
136657
136662
  const manifest = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest");
136658
- assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest");
136663
+ return assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest", snapshotRoot);
136659
136664
  }
136660
136665
  async function assertQoderHubEntry(target, marketplaceRoot) {
136661
136666
  const marketplace = parseJson2(
@@ -136678,10 +136683,11 @@ async function verifyQoderInstalledPayload({
136678
136683
  target,
136679
136684
  root,
136680
136685
  installPath,
136686
+ frozenSkills,
136681
136687
  verifyInstalledPayload
136682
136688
  }) {
136683
136689
  const manifest = await readQoderManifest(installPath, "installed Qoder plugin manifest");
136684
- assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest");
136690
+ await assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest", installPath, frozenSkills);
136685
136691
  await verifyInstalledPayload({
136686
136692
  snapshotPath: target.snapshotPath,
136687
136693
  manifestDigest: target.manifestDigest,
@@ -136694,7 +136700,7 @@ async function runQoderUpdate(target, detected, run6, {
136694
136700
  verifyInstalledPayload
136695
136701
  }) {
136696
136702
  const env = hostEnvironment("qoder");
136697
- await assertFrozenQoderManifest(target, root);
136703
+ const frozenSkills = await assertFrozenQoderManifest(target, root);
136698
136704
  const marketplace = await observeQoderMarketplace(target, detected.command, env, run6);
136699
136705
  if (!marketplace.installed) {
136700
136706
  return {
@@ -136715,6 +136721,7 @@ async function runQoderUpdate(target, detected, run6, {
136715
136721
  target,
136716
136722
  root,
136717
136723
  installPath: before.installPath,
136724
+ frozenSkills,
136718
136725
  verifyInstalledPayload
136719
136726
  });
136720
136727
  return { status: "ALREADY_CURRENT", version: target.version };
@@ -136741,6 +136748,7 @@ async function runQoderUpdate(target, detected, run6, {
136741
136748
  target,
136742
136749
  root,
136743
136750
  installPath: after.installPath,
136751
+ frozenSkills,
136744
136752
  verifyInstalledPayload
136745
136753
  });
136746
136754
  return {
@@ -37,9 +37,9 @@ description: "Discoverable entry point for release-skill: dependency and environ
37
37
 
38
38
  治理诊断只运行 release-skill 自己的只读检查程序,不运行目标 Skill、业务脚本、构建、hook 或发布动作,也不把 `prepare`、`verify`、`release-finish` 当作静态治理入口。用户要求实际接入或发布时,把已有授权带到对应原业务入口;各入口继续执行原有确认、副作用和状态机合同。
39
39
 
40
- ## 0.9.28 能力与证据边界
40
+ ## 0.9.30 能力与证据边界
41
41
 
42
- release-skill 0.9.28 精确依赖 Foundation 0.25.0 的公开包根 API。本版本新增可选宿主覆盖诊断能力,支持通过 `--host-coverage <file>` 提供输入文件,报告每个宿主在声明范围内的覆盖状态与事实缺口;同时采用 Codex 0.154.0 静态加载规则检查,基于 11 份真实生成 Skill 的原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。批准、发布和验证状态以对应计划、批准及执行记录为准,不能由本说明推断。
42
+ release-skill 0.9.30 保留 Foundation 0.25.0 精确依赖、可选宿主覆盖诊断输入 `--host-coverage <file>` 与 `--observe-hosts`、Codex 0.154.0 静态加载规则检查 11 份真实生成 Skill 的原字节等既有事实;本版修复私有 Hub 的 postVerify 钩子:通过既有 `envAllowlist` 传递 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE`,其值为原始描述符所指向的已有普通文件绝对路径(拒绝符号链接),交由 Hub `npm run release:check -- --release-evidence <file>` 验证。Qoder 本机更新路径处理维持既有能力,支持 `./adapters/qoder/skills/` 与 `./skills/` 两种布局,仍核对安装 name/version/skills、路径包含性与实际载荷。静态检查不证明安装、会话选择或业务执行通过,批准、发布和验证状态以对应计划、批准及执行记录为准。
43
43
 
44
44
  在冻结前,`prepare` 或新建 `ship` 状态时可重复传入 `--unit <id>`;未传入则默认选择全部单元。延期单元不进入发布计划,亦不获得发布状态。完整配置、生成物新鲜度检查及顶层 Hook 仍作用于全项目范围。`publicSourceAuthorityReceipt` 的 coordinator 与全部 subjects 必须共同选择。
45
45
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -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.9.28"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.30"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "9683591bbfad41292831f35e071273e6812b7e5b27adcb0e237dac9672605a36";
14
+ const __bundleSourceDigest = "52acbaddf4e589b42b49defb03ff5dfa59e0306f37a3ce0e8e3aaa240b9cfba4";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136643,10 +136643,15 @@ async function readQoderManifest(root, label) {
136643
136643
  }
136644
136644
  return manifest;
136645
136645
  }
136646
- function assertQoderPluginManifest(target, manifest, label) {
136647
- if (manifest.name !== target.plugin || manifest.version !== target.version || manifest.skills !== "./adapters/qoder/skills/") {
136646
+ async function assertQoderPluginManifest(target, manifest, label, pluginRoot, frozenSkills) {
136647
+ if (manifest.name !== target.plugin || manifest.version !== target.version || typeof manifest.skills !== "string" || manifest.skills.length === 0 || frozenSkills !== void 0 && manifest.skills !== frozenSkills) {
136648
136648
  throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path`);
136649
136649
  }
136650
+ const skillsRoot = await resolveContained(pluginRoot, manifest.skills);
136651
+ if (!(await lstat45(skillsRoot)).isDirectory()) {
136652
+ throw new Error(`${label} skills path must name a contained directory`);
136653
+ }
136654
+ return manifest.skills;
136650
136655
  }
136651
136656
  async function assertFrozenQoderManifest(target, root) {
136652
136657
  const { snapshotDir: snapshotRoot } = await verifyFrozenSnapshot({
@@ -136655,7 +136660,7 @@ async function assertFrozenQoderManifest(target, root) {
136655
136660
  expectedDigest: target.manifestDigest
136656
136661
  });
136657
136662
  const manifest = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest");
136658
- assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest");
136663
+ return assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest", snapshotRoot);
136659
136664
  }
136660
136665
  async function assertQoderHubEntry(target, marketplaceRoot) {
136661
136666
  const marketplace = parseJson2(
@@ -136678,10 +136683,11 @@ async function verifyQoderInstalledPayload({
136678
136683
  target,
136679
136684
  root,
136680
136685
  installPath,
136686
+ frozenSkills,
136681
136687
  verifyInstalledPayload
136682
136688
  }) {
136683
136689
  const manifest = await readQoderManifest(installPath, "installed Qoder plugin manifest");
136684
- assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest");
136690
+ await assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest", installPath, frozenSkills);
136685
136691
  await verifyInstalledPayload({
136686
136692
  snapshotPath: target.snapshotPath,
136687
136693
  manifestDigest: target.manifestDigest,
@@ -136694,7 +136700,7 @@ async function runQoderUpdate(target, detected, run6, {
136694
136700
  verifyInstalledPayload
136695
136701
  }) {
136696
136702
  const env = hostEnvironment("qoder");
136697
- await assertFrozenQoderManifest(target, root);
136703
+ const frozenSkills = await assertFrozenQoderManifest(target, root);
136698
136704
  const marketplace = await observeQoderMarketplace(target, detected.command, env, run6);
136699
136705
  if (!marketplace.installed) {
136700
136706
  return {
@@ -136715,6 +136721,7 @@ async function runQoderUpdate(target, detected, run6, {
136715
136721
  target,
136716
136722
  root,
136717
136723
  installPath: before.installPath,
136724
+ frozenSkills,
136718
136725
  verifyInstalledPayload
136719
136726
  });
136720
136727
  return { status: "ALREADY_CURRENT", version: target.version };
@@ -136741,6 +136748,7 @@ async function runQoderUpdate(target, detected, run6, {
136741
136748
  target,
136742
136749
  root,
136743
136750
  installPath: after.installPath,
136751
+ frozenSkills,
136744
136752
  verifyInstalledPayload
136745
136753
  });
136746
136754
  return {
@@ -37,9 +37,9 @@ description: "Discoverable entry point for release-skill: dependency and environ
37
37
 
38
38
  治理诊断只运行 release-skill 自己的只读检查程序,不运行目标 Skill、业务脚本、构建、hook 或发布动作,也不把 `prepare`、`verify`、`release-finish` 当作静态治理入口。用户要求实际接入或发布时,把已有授权带到对应原业务入口;各入口继续执行原有确认、副作用和状态机合同。
39
39
 
40
- ## 0.9.28 能力与证据边界
40
+ ## 0.9.30 能力与证据边界
41
41
 
42
- release-skill 0.9.28 精确依赖 Foundation 0.25.0 的公开包根 API。本版本新增可选宿主覆盖诊断能力,支持通过 `--host-coverage <file>` 提供输入文件,报告每个宿主在声明范围内的覆盖状态与事实缺口;同时采用 Codex 0.154.0 静态加载规则检查,基于 11 份真实生成 Skill 的原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。批准、发布和验证状态以对应计划、批准及执行记录为准,不能由本说明推断。
42
+ release-skill 0.9.30 保留 Foundation 0.25.0 精确依赖、可选宿主覆盖诊断输入 `--host-coverage <file>` 与 `--observe-hosts`、Codex 0.154.0 静态加载规则检查 11 份真实生成 Skill 的原字节等既有事实;本版修复私有 Hub 的 postVerify 钩子:通过既有 `envAllowlist` 传递 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE`,其值为原始描述符所指向的已有普通文件绝对路径(拒绝符号链接),交由 Hub `npm run release:check -- --release-evidence <file>` 验证。Qoder 本机更新路径处理维持既有能力,支持 `./adapters/qoder/skills/` 与 `./skills/` 两种布局,仍核对安装 name/version/skills、路径包含性与实际载荷。静态检查不证明安装、会话选择或业务执行通过,批准、发布和验证状态以对应计划、批准及执行记录为准。
43
43
 
44
44
  在冻结前,`prepare` 或新建 `ship` 状态时可重复传入 `--unit <id>`;未传入则默认选择全部单元。延期单元不进入发布计划,亦不获得发布状态。完整配置、生成物新鲜度检查及顶层 Hook 仍作用于全项目范围。`publicSourceAuthorityReceipt` 的 coordinator 与全部 subjects 必须共同选择。
45
45
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -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.9.28"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.30"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "9683591bbfad41292831f35e071273e6812b7e5b27adcb0e237dac9672605a36";
14
+ const __bundleSourceDigest = "52acbaddf4e589b42b49defb03ff5dfa59e0306f37a3ce0e8e3aaa240b9cfba4";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136643,10 +136643,15 @@ async function readQoderManifest(root, label) {
136643
136643
  }
136644
136644
  return manifest;
136645
136645
  }
136646
- function assertQoderPluginManifest(target, manifest, label) {
136647
- if (manifest.name !== target.plugin || manifest.version !== target.version || manifest.skills !== "./adapters/qoder/skills/") {
136646
+ async function assertQoderPluginManifest(target, manifest, label, pluginRoot, frozenSkills) {
136647
+ if (manifest.name !== target.plugin || manifest.version !== target.version || typeof manifest.skills !== "string" || manifest.skills.length === 0 || frozenSkills !== void 0 && manifest.skills !== frozenSkills) {
136648
136648
  throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path`);
136649
136649
  }
136650
+ const skillsRoot = await resolveContained(pluginRoot, manifest.skills);
136651
+ if (!(await lstat45(skillsRoot)).isDirectory()) {
136652
+ throw new Error(`${label} skills path must name a contained directory`);
136653
+ }
136654
+ return manifest.skills;
136650
136655
  }
136651
136656
  async function assertFrozenQoderManifest(target, root) {
136652
136657
  const { snapshotDir: snapshotRoot } = await verifyFrozenSnapshot({
@@ -136655,7 +136660,7 @@ async function assertFrozenQoderManifest(target, root) {
136655
136660
  expectedDigest: target.manifestDigest
136656
136661
  });
136657
136662
  const manifest = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest");
136658
- assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest");
136663
+ return assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest", snapshotRoot);
136659
136664
  }
136660
136665
  async function assertQoderHubEntry(target, marketplaceRoot) {
136661
136666
  const marketplace = parseJson2(
@@ -136678,10 +136683,11 @@ async function verifyQoderInstalledPayload({
136678
136683
  target,
136679
136684
  root,
136680
136685
  installPath,
136686
+ frozenSkills,
136681
136687
  verifyInstalledPayload
136682
136688
  }) {
136683
136689
  const manifest = await readQoderManifest(installPath, "installed Qoder plugin manifest");
136684
- assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest");
136690
+ await assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest", installPath, frozenSkills);
136685
136691
  await verifyInstalledPayload({
136686
136692
  snapshotPath: target.snapshotPath,
136687
136693
  manifestDigest: target.manifestDigest,
@@ -136694,7 +136700,7 @@ async function runQoderUpdate(target, detected, run6, {
136694
136700
  verifyInstalledPayload
136695
136701
  }) {
136696
136702
  const env = hostEnvironment("qoder");
136697
- await assertFrozenQoderManifest(target, root);
136703
+ const frozenSkills = await assertFrozenQoderManifest(target, root);
136698
136704
  const marketplace = await observeQoderMarketplace(target, detected.command, env, run6);
136699
136705
  if (!marketplace.installed) {
136700
136706
  return {
@@ -136715,6 +136721,7 @@ async function runQoderUpdate(target, detected, run6, {
136715
136721
  target,
136716
136722
  root,
136717
136723
  installPath: before.installPath,
136724
+ frozenSkills,
136718
136725
  verifyInstalledPayload
136719
136726
  });
136720
136727
  return { status: "ALREADY_CURRENT", version: target.version };
@@ -136741,6 +136748,7 @@ async function runQoderUpdate(target, detected, run6, {
136741
136748
  target,
136742
136749
  root,
136743
136750
  installPath: after.installPath,
136751
+ frozenSkills,
136744
136752
  verifyInstalledPayload
136745
136753
  });
136746
136754
  return {
@@ -29,9 +29,9 @@ description: "Discoverable entry point for release-skill: dependency and environ
29
29
 
30
30
  治理诊断只运行 release-skill 自己的只读检查程序,不运行目标 Skill、业务脚本、构建、hook 或发布动作,也不把 `prepare`、`verify`、`release-finish` 当作静态治理入口。用户要求实际接入或发布时,把已有授权带到对应原业务入口;各入口继续执行原有确认、副作用和状态机合同。
31
31
 
32
- ## 0.9.28 能力与证据边界
32
+ ## 0.9.30 能力与证据边界
33
33
 
34
- release-skill 0.9.28 精确依赖 Foundation 0.25.0 的公开包根 API。本版本新增可选宿主覆盖诊断能力,支持通过 `--host-coverage <file>` 提供输入文件,报告每个宿主在声明范围内的覆盖状态与事实缺口;同时采用 Codex 0.154.0 静态加载规则检查,基于 11 份真实生成 Skill 的原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。批准、发布和验证状态以对应计划、批准及执行记录为准,不能由本说明推断。
34
+ release-skill 0.9.30 保留 Foundation 0.25.0 精确依赖、可选宿主覆盖诊断输入 `--host-coverage <file>` 与 `--observe-hosts`、Codex 0.154.0 静态加载规则检查 11 份真实生成 Skill 的原字节等既有事实;本版修复私有 Hub 的 postVerify 钩子:通过既有 `envAllowlist` 传递 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE`,其值为原始描述符所指向的已有普通文件绝对路径(拒绝符号链接),交由 Hub `npm run release:check -- --release-evidence <file>` 验证。Qoder 本机更新路径处理维持既有能力,支持 `./adapters/qoder/skills/` 与 `./skills/` 两种布局,仍核对安装 name/version/skills、路径包含性与实际载荷。静态检查不证明安装、会话选择或业务执行通过,批准、发布和验证状态以对应计划、批准及执行记录为准。
35
35
 
36
36
  在冻结前,`prepare` 或新建 `ship` 状态时可重复传入 `--unit <id>`;未传入则默认选择全部单元。延期单元不进入发布计划,亦不获得发布状态。完整配置、生成物新鲜度检查及顶层 Hook 仍作用于全项目范围。`publicSourceAuthorityReceipt` 的 coordinator 与全部 subjects 必须共同选择。
37
37
 
@@ -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.9.28"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.30"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "9683591bbfad41292831f35e071273e6812b7e5b27adcb0e237dac9672605a36";
14
+ const __bundleSourceDigest = "52acbaddf4e589b42b49defb03ff5dfa59e0306f37a3ce0e8e3aaa240b9cfba4";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136643,10 +136643,15 @@ async function readQoderManifest(root, label) {
136643
136643
  }
136644
136644
  return manifest;
136645
136645
  }
136646
- function assertQoderPluginManifest(target, manifest, label) {
136647
- if (manifest.name !== target.plugin || manifest.version !== target.version || manifest.skills !== "./adapters/qoder/skills/") {
136646
+ async function assertQoderPluginManifest(target, manifest, label, pluginRoot, frozenSkills) {
136647
+ if (manifest.name !== target.plugin || manifest.version !== target.version || typeof manifest.skills !== "string" || manifest.skills.length === 0 || frozenSkills !== void 0 && manifest.skills !== frozenSkills) {
136648
136648
  throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path`);
136649
136649
  }
136650
+ const skillsRoot = await resolveContained(pluginRoot, manifest.skills);
136651
+ if (!(await lstat45(skillsRoot)).isDirectory()) {
136652
+ throw new Error(`${label} skills path must name a contained directory`);
136653
+ }
136654
+ return manifest.skills;
136650
136655
  }
136651
136656
  async function assertFrozenQoderManifest(target, root) {
136652
136657
  const { snapshotDir: snapshotRoot } = await verifyFrozenSnapshot({
@@ -136655,7 +136660,7 @@ async function assertFrozenQoderManifest(target, root) {
136655
136660
  expectedDigest: target.manifestDigest
136656
136661
  });
136657
136662
  const manifest = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest");
136658
- assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest");
136663
+ return assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest", snapshotRoot);
136659
136664
  }
136660
136665
  async function assertQoderHubEntry(target, marketplaceRoot) {
136661
136666
  const marketplace = parseJson2(
@@ -136678,10 +136683,11 @@ async function verifyQoderInstalledPayload({
136678
136683
  target,
136679
136684
  root,
136680
136685
  installPath,
136686
+ frozenSkills,
136681
136687
  verifyInstalledPayload
136682
136688
  }) {
136683
136689
  const manifest = await readQoderManifest(installPath, "installed Qoder plugin manifest");
136684
- assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest");
136690
+ await assertQoderPluginManifest(target, manifest, "installed Qoder plugin manifest", installPath, frozenSkills);
136685
136691
  await verifyInstalledPayload({
136686
136692
  snapshotPath: target.snapshotPath,
136687
136693
  manifestDigest: target.manifestDigest,
@@ -136694,7 +136700,7 @@ async function runQoderUpdate(target, detected, run6, {
136694
136700
  verifyInstalledPayload
136695
136701
  }) {
136696
136702
  const env = hostEnvironment("qoder");
136697
- await assertFrozenQoderManifest(target, root);
136703
+ const frozenSkills = await assertFrozenQoderManifest(target, root);
136698
136704
  const marketplace = await observeQoderMarketplace(target, detected.command, env, run6);
136699
136705
  if (!marketplace.installed) {
136700
136706
  return {
@@ -136715,6 +136721,7 @@ async function runQoderUpdate(target, detected, run6, {
136715
136721
  target,
136716
136722
  root,
136717
136723
  installPath: before.installPath,
136724
+ frozenSkills,
136718
136725
  verifyInstalledPayload
136719
136726
  });
136720
136727
  return { status: "ALREADY_CURRENT", version: target.version };
@@ -136741,6 +136748,7 @@ async function runQoderUpdate(target, detected, run6, {
136741
136748
  target,
136742
136749
  root,
136743
136750
  installPath: after.installPath,
136751
+ frozenSkills,
136744
136752
  verifyInstalledPayload
136745
136753
  });
136746
136754
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -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.9.28",
5
+ "version": "0.9.30",
6
6
  "logicalRoot": "skills-src/",
7
- "logicalRootDigest": "043a4f6c014adeddf4565a9d04839fd4a4f45b24a904fed105945e29197b02a7",
8
- "projectionDigest": "6031c13a38f988088cdfd35f58e61906a348248cc543f0830f27e2432c6c5311",
9
- "projectionId": "release-skill:platform:0.9.28",
7
+ "logicalRootDigest": "1ea3c60db0fbc3c3943d2103f76730500886d0994d5e406e4438d6479df86b62",
8
+ "projectionDigest": "77fdc2b733c05475ee6784e049ff4ce6b09dcd01f3d4391b3d264603827f1cfa",
9
+ "projectionId": "release-skill:platform:0.9.30",
10
10
  "manifestRequired": true,
11
11
  "projectionSources": {
12
12
  "skills-src-root": {
@@ -29,9 +29,9 @@ description: "Discoverable entry point for release-skill: dependency and environ
29
29
 
30
30
  治理诊断只运行 release-skill 自己的只读检查程序,不运行目标 Skill、业务脚本、构建、hook 或发布动作,也不把 `prepare`、`verify`、`release-finish` 当作静态治理入口。用户要求实际接入或发布时,把已有授权带到对应原业务入口;各入口继续执行原有确认、副作用和状态机合同。
31
31
 
32
- ## 0.9.28 能力与证据边界
32
+ ## 0.9.30 能力与证据边界
33
33
 
34
- release-skill 0.9.28 精确依赖 Foundation 0.25.0 的公开包根 API。本版本新增可选宿主覆盖诊断能力,支持通过 `--host-coverage <file>` 提供输入文件,报告每个宿主在声明范围内的覆盖状态与事实缺口;同时采用 Codex 0.154.0 静态加载规则检查,基于 11 份真实生成 Skill 的原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。批准、发布和验证状态以对应计划、批准及执行记录为准,不能由本说明推断。
34
+ release-skill 0.9.30 保留 Foundation 0.25.0 精确依赖、可选宿主覆盖诊断输入 `--host-coverage <file>` 与 `--observe-hosts`、Codex 0.154.0 静态加载规则检查 11 份真实生成 Skill 的原字节等既有事实;本版修复私有 Hub 的 postVerify 钩子:通过既有 `envAllowlist` 传递 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE`,其值为原始描述符所指向的已有普通文件绝对路径(拒绝符号链接),交由 Hub `npm run release:check -- --release-evidence <file>` 验证。Qoder 本机更新路径处理维持既有能力,支持 `./adapters/qoder/skills/` 与 `./skills/` 两种布局,仍核对安装 name/version/skills、路径包含性与实际载荷。静态检查不证明安装、会话选择或业务执行通过,批准、发布和验证状态以对应计划、批准及执行记录为准。
35
35
 
36
36
  在冻结前,`prepare` 或新建 `ship` 状态时可重复传入 `--unit <id>`;未传入则默认选择全部单元。延期单元不进入发布计划,亦不获得发布状态。完整配置、生成物新鲜度检查及顶层 Hook 仍作用于全项目范围。`publicSourceAuthorityReceipt` 的 coordinator 与全部 subjects 必须共同选择。
37
37
 
@@ -29,9 +29,9 @@ description: "Discoverable entry point for release-skill: dependency and environ
29
29
 
30
30
  治理诊断只运行 release-skill 自己的只读检查程序,不运行目标 Skill、业务脚本、构建、hook 或发布动作,也不把 `prepare`、`verify`、`release-finish` 当作静态治理入口。用户要求实际接入或发布时,把已有授权带到对应原业务入口;各入口继续执行原有确认、副作用和状态机合同。
31
31
 
32
- ## 0.9.28 能力与证据边界
32
+ ## 0.9.30 能力与证据边界
33
33
 
34
- release-skill 0.9.28 精确依赖 Foundation 0.25.0 的公开包根 API。本版本新增可选宿主覆盖诊断能力,支持通过 `--host-coverage <file>` 提供输入文件,报告每个宿主在声明范围内的覆盖状态与事实缺口;同时采用 Codex 0.154.0 静态加载规则检查,基于 11 份真实生成 Skill 的原字节在隔离环境中完成诊断,不证明安装、会话选择或业务执行通过。批准、发布和验证状态以对应计划、批准及执行记录为准,不能由本说明推断。
34
+ release-skill 0.9.30 保留 Foundation 0.25.0 精确依赖、可选宿主覆盖诊断输入 `--host-coverage <file>` 与 `--observe-hosts`、Codex 0.154.0 静态加载规则检查 11 份真实生成 Skill 的原字节等既有事实;本版修复私有 Hub 的 postVerify 钩子:通过既有 `envAllowlist` 传递 `RELEASE_SKILL_HUB_RELEASE_EVIDENCE`,其值为原始描述符所指向的已有普通文件绝对路径(拒绝符号链接),交由 Hub `npm run release:check -- --release-evidence <file>` 验证。Qoder 本机更新路径处理维持既有能力,支持 `./adapters/qoder/skills/` 与 `./skills/` 两种布局,仍核对安装 name/version/skills、路径包含性与实际载荷。静态检查不证明安装、会话选择或业务执行通过,批准、发布和验证状态以对应计划、批准及执行记录为准。
35
35
 
36
36
  在冻结前,`prepare` 或新建 `ship` 状态时可重复传入 `--unit <id>`;未传入则默认选择全部单元。延期单元不进入发布计划,亦不获得发布状态。完整配置、生成物新鲜度检查及顶层 Hook 仍作用于全项目范围。`publicSourceAuthorityReceipt` 的 coordinator 与全部 subjects 必须共同选择。
37
37
 
@@ -857,14 +857,21 @@ async function readQoderManifest(root, label) {
857
857
  return manifest;
858
858
  }
859
859
 
860
- function assertQoderPluginManifest(target, manifest, label) {
860
+ async function assertQoderPluginManifest(target, manifest, label, pluginRoot, frozenSkills) {
861
861
  if (
862
862
  manifest.name !== target.plugin
863
863
  || manifest.version !== target.version
864
- || manifest.skills !== './adapters/qoder/skills/'
864
+ || typeof manifest.skills !== 'string'
865
+ || manifest.skills.length === 0
866
+ || (frozenSkills !== undefined && manifest.skills !== frozenSkills)
865
867
  ) {
866
868
  throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path`);
867
869
  }
870
+ const skillsRoot = await resolveContained(pluginRoot, manifest.skills);
871
+ if (!(await lstat(skillsRoot)).isDirectory()) {
872
+ throw new Error(`${label} skills path must name a contained directory`);
873
+ }
874
+ return manifest.skills;
868
875
  }
869
876
 
870
877
  async function assertFrozenQoderManifest(target, root) {
@@ -874,7 +881,7 @@ async function assertFrozenQoderManifest(target, root) {
874
881
  expectedDigest: target.manifestDigest,
875
882
  });
876
883
  const manifest = await readQoderManifest(snapshotRoot, 'frozen Qoder plugin manifest');
877
- assertQoderPluginManifest(target, manifest, 'frozen Qoder plugin manifest');
884
+ return assertQoderPluginManifest(target, manifest, 'frozen Qoder plugin manifest', snapshotRoot);
878
885
  }
879
886
 
880
887
  async function assertQoderHubEntry(target, marketplaceRoot) {
@@ -903,10 +910,11 @@ async function verifyQoderInstalledPayload({
903
910
  target,
904
911
  root,
905
912
  installPath,
913
+ frozenSkills,
906
914
  verifyInstalledPayload,
907
915
  }) {
908
916
  const manifest = await readQoderManifest(installPath, 'installed Qoder plugin manifest');
909
- assertQoderPluginManifest(target, manifest, 'installed Qoder plugin manifest');
917
+ await assertQoderPluginManifest(target, manifest, 'installed Qoder plugin manifest', installPath, frozenSkills);
910
918
  await verifyInstalledPayload({
911
919
  snapshotPath: target.snapshotPath,
912
920
  manifestDigest: target.manifestDigest,
@@ -920,7 +928,7 @@ async function runQoderUpdate(target, detected, run, {
920
928
  verifyInstalledPayload,
921
929
  }) {
922
930
  const env = hostEnvironment('qoder');
923
- await assertFrozenQoderManifest(target, root);
931
+ const frozenSkills = await assertFrozenQoderManifest(target, root);
924
932
  const marketplace = await observeQoderMarketplace(target, detected.command, env, run);
925
933
  if (!marketplace.installed) {
926
934
  return {
@@ -941,6 +949,7 @@ async function runQoderUpdate(target, detected, run, {
941
949
  target,
942
950
  root,
943
951
  installPath: before.installPath,
952
+ frozenSkills,
944
953
  verifyInstalledPayload,
945
954
  });
946
955
  return { status: 'ALREADY_CURRENT', version: target.version };
@@ -964,6 +973,7 @@ async function runQoderUpdate(target, detected, run, {
964
973
  target,
965
974
  root,
966
975
  installPath: after.installPath,
976
+ frozenSkills,
967
977
  verifyInstalledPayload,
968
978
  });
969
979
  return {