release-skill 0.9.11 → 0.9.12

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
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.11",
3
+ "version": "0.9.12",
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.11",
3
+ "version": "0.9.12",
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.11.",
22
+ "Prepare a release plan for version 0.9.12.",
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.11",
3
+ "version": "0.9.12",
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,25 @@
1
1
  # Changelog
2
2
 
3
+ <!-- release-skill:changelog:start version=0.9.12 locale=en baseline=sha256:c2511de86192c1798c17e579bed689c57c450516b10bd85d6a508b0b6e5e19b1 -->
4
+ ## [0.9.12] - 2026-09-04
5
+
6
+ 0.9.12 is a local source candidate that fixes the frozen postVerify execution closure used to publish verified releases into Skill Family Hub. It retains the 0.9.11 first-release baseline and GitHub-only distribution changes, with the three Foundation dependencies still pinned to the exact 0.17.0 release. This note is not evidence of publication, real-host acceptance, consumer installation verification, or independent acceptance.
7
+
8
+ ### Security
9
+
10
+ - The repair does not weaken the frozen execution-bundle boundary: the hook still runs from the verified tag plus the digest-bound private script. Hub branch updates remain compare-and-swap operations; a partial Hub publication is retained for recovery and is never rolled back or force-pushed.
11
+
12
+ ### Fixed
13
+
14
+ - The Hub postVerify hook now imports proposal projection from a dependency-free public module. A detached frozen-tag worktree can load the module without node_modules, while runtime proposal transports continue to use the same implementation through a compatibility re-export.
15
+ - The project-private postVerify hook continues to publish verified entries and public snapshots to Skill Family Hub through GitHub's Git Data API.
16
+
17
+ ### Upgrade Notes
18
+
19
+ Upgrade from 0.9.11 before relying on the bundled `hub-api-publish` postVerify hook. Remove any `release-skill` standalone marketplace registration, add or update `ifoohoo/skill-family-hub`, and use `release-skill@skill-family-hub`. Releases that do not use this hook are unaffected.
20
+ <!-- release-skill:changelog:end version=0.9.12 locale=en -->
21
+
22
+
3
23
  <!-- release-skill:changelog:start version=0.9.11 locale=en baseline=sha256:c8015d6a26b39a9056c121425b8758a108048d78815476e7bf3d2711cec6ee25 -->
4
24
  ## [0.9.11] - 2026-09-04
5
25
 
package/INSTALL.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [简体中文](INSTALL.zh-CN.md)
4
4
 
5
- <!-- release-skill:release-version: 0.9.11 -->
5
+ <!-- release-skill:release-version: 0.9.12 -->
6
6
  ## Prerequisites
7
7
 
8
8
  - Node.js 22.0.0 or later
@@ -110,7 +110,7 @@ tag pinned to the exact version (never the bare repository URL, which installs
110
110
  the latest release or default branch), confirm the trust prompt, then reload:
111
111
 
112
112
  ```
113
- /plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.11
113
+ /plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.12
114
114
  /plugins reload
115
115
  ```
116
116
 
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.11 -->
5
+ <!-- release-skill:release-version: 0.9.12 -->
6
6
  ## 前置条件
7
7
 
8
8
  - Node.js 22.0.0 或更高版本
@@ -101,7 +101,7 @@ release-skill 当前只采用并验证 Kimi Code 的交互式 TUI 路径,**无
101
101
  (切勿使用裸仓库地址,它会安装最新 release 或默认分支),确认信任提示后重新加载:
102
102
 
103
103
  ```
104
- /plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.11
104
+ /plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.12
105
105
  /plugins reload
106
106
  ```
107
107
 
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.11 -->
5
+ <!-- release-skill:release-version: 0.9.12 -->
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,30 +14,26 @@ Setup surfaces only the deterministic `compactSummary` review view; the full
14
14
  report stays in a temporary session directory.
15
15
 
16
16
  <!-- release-skill:managed:start id=latest-release -->
17
- **0.9.11** (2026-09-04)
17
+ **0.9.12** (2026-09-04)
18
18
 
19
- 0.9.11 is a local source candidate that makes first-release verification advance its public baseline and permits an explicit empty distribution list for GitHub-only plugin releases. It consumes the three Foundation packages at the exact 0.17.0 release. This note is not evidence of publication, real-host acceptance, consumer installation verification, or independent acceptance.
19
+ 0.9.12 is a local source candidate that fixes the frozen postVerify execution closure used to publish verified releases into Skill Family Hub. It retains the 0.9.11 first-release baseline and GitHub-only distribution changes, with the three Foundation dependencies still pinned to the exact 0.17.0 release. This note is not evidence of publication, real-host acceptance, consumer installation verification, or independent acceptance.
20
20
 
21
21
  **Security**
22
22
 
23
- - First-release baseline advancement runs only after immutable publication verification succeeds. Configuration writes are validated and atomic; restoration failures retain their phase and publication-state details in verification evidence without changing a successful publication result.
24
- - An empty distribution list does not skip the GitHub snapshot, tag, or GitHub Release actions, and it does not grant a marketplace registration.
25
- - Hub branch updates use compare-and-swap against the observed branch head. A partial Hub publication is retained for recovery and is never rolled back or force-pushed.
23
+ - The repair does not weaken the frozen execution-bundle boundary: the hook still runs from the verified tag plus the digest-bound private script. Hub branch updates remain compare-and-swap operations; a partial Hub publication is retained for recovery and is never rolled back or force-pushed.
26
24
 
27
- **Changed**
25
+ **Fixed**
28
26
 
29
- - After a release reaches VERIFIED, a unit whose previous public baseline is `mode: none` is advanced to a bound baseline with the resolved repository and ref plus the exact frozen commit, tree, and manifest digest. Mixed plans and custom in-root config paths use the same existing atomic update path, preserve an explicit GitHub host, and report only units that changed.
30
- - `releaseUnits[].distributions` remains required but may now be an explicit empty list. Such a unit still freezes and publishes its GitHub snapshot, tag, and GitHub Release, while npm and marketplace actions are omitted; postPublish and postVerify hooks remain independent.
31
- - Pinned `skill-family-contracts`, `skill-family-harness-node`, and `skill-family-engineering-kit` dependencies were upgraded from 0.16.0 to the exact published 0.17.0 versions.
32
- - Skill Family Hub remains the single marketplace source. After verification, the project-private postVerify hook applies the Hub proposal and publishes its private entry and public snapshot through GitHub's Git Data API.
27
+ - The Hub postVerify hook now imports proposal projection from a dependency-free public module. A detached frozen-tag worktree can load the module without node_modules, while runtime proposal transports continue to use the same implementation through a compatibility re-export.
28
+ - The project-private postVerify hook continues to publish verified entries and public snapshots to Skill Family Hub through GitHub's Git Data API.
33
29
 
34
30
  **Upgrade Notes**
35
31
 
36
- Remove any `release-skill` standalone marketplace registration, add or update `ifoohoo/skill-family-hub`, and use `release-skill@skill-family-hub`. Use `distributions: []` only when the release unit is intentionally GitHub-only and marketplace registration is handled by an independent verified workflow. Existing non-empty distribution lists keep their behavior. After installing or reloading the official 0.9.11 release, a historical first release may be reverified without republishing; confirm that its configured previous public baseline changed from `none` to the verified frozen coordinates.
32
+ Upgrade from 0.9.11 before relying on the bundled `hub-api-publish` postVerify hook. Remove any `release-skill` standalone marketplace registration, add or update `ifoohoo/skill-family-hub`, and use `release-skill@skill-family-hub`. Releases that do not use this hook are unaffected.
37
33
  <!-- release-skill:managed:end id=latest-release -->
38
34
 
39
35
  <!-- release-skill:capability:external-write-boundary -->
40
- > **Current boundary:** v0.9.11 is the current source candidate. This README
36
+ > **Current boundary:** v0.9.12 is the current source candidate. This README
41
37
  > records intended scope and verification boundaries; it is not evidence of
42
38
  > publication, consumer-installation verification, or independent acceptance.
43
39
  > Release availability must be established from the corresponding release records
@@ -61,7 +57,7 @@ Remove any `release-skill` standalone marketplace registration, add or update `i
61
57
  > publish global preflight.
62
58
 
63
59
  <!-- release-skill:capability:safe-first-command -->
64
- > **Production path verified since the v0.1.1 milestone; v0.9.11 is the current
60
+ > **Production path verified since the v0.1.1 milestone; v0.9.12 is the current
65
61
  > source candidate. Its README does not establish publication,
66
62
  > consumer-installation verification, or independent acceptance.**
67
63
  > The npm-installed CLI is the supported user entry. Source checkout
@@ -90,7 +86,7 @@ checkpoints remain intact and use matching-version recovery. Evidence v1 stays
90
86
  read-only; v2 uses a closed top level with phase extensions in `details`.
91
87
  Summaries and recovery suggestions are diagnostic, never publication authority.
92
88
 
93
- The current 0.9.11 candidate includes the narrow R-05 Hook cache v2 consumer
89
+ The current 0.9.12 candidate includes the narrow R-05 Hook cache v2 consumer
94
90
  path, the public `postverify` path, and the stable isolated install-tree record
95
91
  path (A2/A3). It also removes the repository's own marketplace indexes and
96
92
  uses Skill Family Hub as the single marketplace source. It still
package/README.zh-CN.md CHANGED
@@ -2,36 +2,32 @@
2
2
 
3
3
  [English](README.md) · 安装指南:[中文](INSTALL.zh-CN.md) / [English](INSTALL.md)
4
4
 
5
- <!-- release-skill:release-version: 0.9.11 -->
5
+ <!-- release-skill:release-version: 0.9.12 -->
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.11** (2026-09-04)
11
+ **0.9.12** (2026-09-04)
12
12
 
13
- 0.9.11 是修复首次发布验证后基线推进、并允许 GitHub-only 插件发布显式使用空分发列表的本地源码候选,三项 Foundation 依赖均精确升级到已发布的 0.17.0。本说明不代表已经发布、完成真实宿主验收、完成消费者安装验证或通过独立验收。
13
+ 0.9.12 是修复冻结 postVerify 执行闭包的本地源码候选,用于把已验证版本发布到 Skill Family Hub;它保留 0.9.11 的首次发布基线与 GitHub-only 分发能力,三项 Foundation 依赖仍精确固定在已发布的 0.17.0。本说明不代表已经发布、完成真实宿主验收、完成消费者安装验证或通过独立验收。
14
14
 
15
15
  **安全**
16
16
 
17
- - 首次发布基线只在不可变发布内容验证成功后推进。配置写入会先验证并采用原子更新;若恢复失败,验证证据会保留阶段与发布状态详情,同时不把已经成功的发布结果降级。
18
- - 空分发列表不会跳过 GitHub 快照、tag 或 GitHub Release,也不会自动获得市场登记。
19
- - Hub 分支更新以已观察的分支头做比较后写入。Hub 局部发布会保留为可恢复状态,不回滚、不覆盖,也不强推。
17
+ - 本次修复不放宽冻结执行包边界:hook 仍由已验证标签与摘要绑定的私有脚本共同执行。Hub 分支更新继续采用比较后写入;Hub 局部发布会保留为可恢复状态,不回滚、不覆盖,也不强推。
20
18
 
21
- **变更**
19
+ **修复**
22
20
 
23
- - 发布达到 VERIFIED 后,`previousPublicBaseline` 为 `mode: none` 的单元会转为 bound 基线,写入解析后的仓库与 ref,以及本次冻结的精确 commit、tree 和 manifest digest。混合计划与根目录内的自定义配置路径复用既有原子更新路径,保留显式 GitHub host,并且只报告实际发生变化的单元。
24
- - `releaseUnits[].distributions` 仍为必填字段,但现在可以显式设置为空列表。该单元仍会冻结并发布 GitHub 快照、tag 和 GitHub Release,只省略 npm 与市场动作;postPublish 和 postVerify hook 继续独立执行。
25
- - 精确固定的 `skill-family-contracts`、`skill-family-harness-node` 和 `skill-family-engineering-kit` 依赖从 0.16.0 升级到已发布的 0.17.0。
26
- - Skill Family Hub 继续作为唯一市场来源。验证完成后,项目私有的 postVerify hook 会应用 Hub 提案,并通过 GitHub Git Data API 发布 Hub 私有条目和公开快照。
21
+ - Hub postVerify hook 现在从无包依赖的公开模块导入提案投影。detached 冻结标签工作树无需 node_modules 即可加载;运行时提案传输仍通过兼容转出复用同一实现。
22
+ - 项目私有的 postVerify hook 继续通过 GitHub Git Data API,把已验证条目和公开快照发布到 Skill Family Hub。
27
23
 
28
24
  **升级说明**
29
25
 
30
- 删除各宿主中独立的 `release-skill` 市场登记,添加或更新 `ifoohoo/skill-family-hub`,并使用 `release-skill@skill-family-hub`。仅在发布单元有意采用 GitHub-only 发布、且市场登记由独立的已验证流程处理时使用 `distributions: []`。既有非空分发列表的行为不变。安装或重新加载正式发布并已验证的 0.9.11 后,可以直接重新验证历史首次发布,无需重复发布;随后应确认配置中的上一公开基线已从 `none` 更新为本次验证的精确冻结坐标。
26
+ 依赖内置 `hub-api-publish` postVerify hook 前,应从 0.9.11 升级到本版本。删除各宿主中独立的 `release-skill` 市场登记,添加或更新 `ifoohoo/skill-family-hub`,并使用 `release-skill@skill-family-hub`;未使用该 hook 的发布不受影响。
31
27
  <!-- release-skill:managed:end id=latest-release -->
32
28
 
33
29
  <!-- release-skill:capability:external-write-boundary -->
34
- > **当前边界:** v0.9.11 只是当前源码候选。本 README 记录预期范围与验证边界,
30
+ > **当前边界:** v0.9.12 只是当前源码候选。本 README 记录预期范围与验证边界,
35
31
  > 不代表已经发布、完成消费者安装验证或通过独立验收。
36
32
  > 版本可用性以对应发布记录及发布后验证结果为准。
37
33
  > v0.4.1 是更早的已发布里程碑(v0.2.2 曾处于已发布状态,后因平台验证收敛修复而更新)。
@@ -47,7 +43,7 @@ release-skill 帮助维护者回答三个问题:准备发布什么、还有哪
47
43
  > 远端唯一性检查在 `publish` 全局预检执行。
48
44
 
49
45
  <!-- release-skill:capability:safe-first-command -->
50
- > **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.9.11 是当前源码候选,本 README 不证明该候选已经发布、完成消费者安装验证或通过独立验收。**
46
+ > **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.9.12 是当前源码候选,本 README 不证明该候选已经发布、完成消费者安装验证或通过独立验收。**
51
47
  > npm 安装的 CLI 是受支持的用户入口;源码 checkout 保留为开发/贡献者路径。
52
48
  >
53
49
  > **第一条命令:**
@@ -65,7 +61,7 @@ marketplace 委托目标工作区发布的边界不变。
65
61
 
66
62
  旧 production 计划缺少 `sourceAuthority` 时,在外部写入前拒绝。未发生外部写入的计划必须重新 prepare 并批准新摘要,不能补写旧计划或迁移批准。已有 `PARTIAL` 保留检查点,走匹配版本的恢复路径。evidence v1 只读;v2 顶层封闭,阶段扩展放在 `details`。摘要和恢复建议只作诊断,不构成发布权威。
67
63
 
68
- 当前 0.9.11 候选包含窄范围的 R-05 Hook cache v2 消费路径、公开 `postverify`
64
+ 当前 0.9.12 候选包含窄范围的 R-05 Hook cache v2 消费路径、公开 `postverify`
69
65
  路径和稳定隔离安装树记录路径(A2/A3),并删除仓库自有市场索引,统一以
70
66
  Skill Family Hub 为市场来源。当前仍不包含 R-02 安全整树盘点、R-10 历史发布验证
71
67
  的产品实现、真实 Kimi/WorkBuddy 公开市场安装与调用门禁或 Audit 公开离线发布记录
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
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.11"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.12"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "42faaeb2d272e94efd6075f39b6553540afc307ce64a853a8021eb474fdb380b";
14
+ const __bundleSourceDigest = "e6659bd85e866fd7a2780e48de7c89324b9211503d1029a94ce271384f0678b7";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136313,6 +136313,49 @@ var init_notify_handoff = __esm({
136313
136313
  }
136314
136314
  });
136315
136315
 
136316
+ // src/core/proposal-document.mjs
136317
+ function proposalFileName(unitId, version) {
136318
+ if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136319
+ throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136320
+ }
136321
+ return `incoming/${unitId}-${version}.json`;
136322
+ }
136323
+ function buildProposalDocument(context) {
136324
+ const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136325
+ for (const field of required) {
136326
+ if (typeof context?.[field] !== "string" || context[field].length === 0) {
136327
+ throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136328
+ }
136329
+ }
136330
+ const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136331
+ return {
136332
+ schemaVersion: PROPOSAL_SCHEMA_VERSION,
136333
+ kind: PROPOSAL_KIND,
136334
+ unitId,
136335
+ version,
136336
+ tag,
136337
+ sha: commit,
136338
+ commit,
136339
+ ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136340
+ ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136341
+ planDigest,
136342
+ runId,
136343
+ ...publishedAt !== void 0 ? { publishedAt } : {},
136344
+ ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136345
+ changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136346
+ };
136347
+ }
136348
+ var PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND;
136349
+ var init_proposal_document = __esm({
136350
+ "src/core/proposal-document.mjs"() {
136351
+ init_errors3();
136352
+ PROPOSAL_SCHEMA_VERSION = 1;
136353
+ PROPOSAL_KIND = "release-skill/update-proposal";
136354
+ __name(proposalFileName, "proposalFileName");
136355
+ __name(buildProposalDocument, "buildProposalDocument");
136356
+ }
136357
+ });
136358
+
136316
136359
  // src/core/proposal-inbox.mjs
136317
136360
  import { execFile as execFileCb14 } from "node:child_process";
136318
136361
  import { promisify as promisify14 } from "node:util";
@@ -136389,37 +136432,6 @@ function parseLsRemote(stdout) {
136389
136432
  }
136390
136433
  return refs;
136391
136434
  }
136392
- function proposalFileName(unitId, version) {
136393
- if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136394
- throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136395
- }
136396
- return `incoming/${unitId}-${version}.json`;
136397
- }
136398
- function buildProposalDocument(context) {
136399
- const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136400
- for (const field of required) {
136401
- if (typeof context?.[field] !== "string" || context[field].length === 0) {
136402
- throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136403
- }
136404
- }
136405
- const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136406
- return {
136407
- schemaVersion: PROPOSAL_SCHEMA_VERSION,
136408
- kind: PROPOSAL_KIND,
136409
- unitId,
136410
- version,
136411
- tag,
136412
- sha: commit,
136413
- commit,
136414
- ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136415
- ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136416
- planDigest,
136417
- runId,
136418
- ...publishedAt !== void 0 ? { publishedAt } : {},
136419
- ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136420
- changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136421
- };
136422
- }
136423
136435
  function buildManualSyncPrompt({ remoteUrl, proposalPath, branch }) {
136424
136436
  const safeRemoteUrl = redactUrlCredentialsIfPresent(remoteUrl);
136425
136437
  return `manual sync required: review proposal ${proposalPath} in downstream repository ${safeRemoteUrl} (branch ${branch}); suggested action: open a pull request or apply the proposal through the downstream governance workflow`;
@@ -136729,15 +136741,15 @@ async function executeProposalInboxLocalFileHook(params) {
136729
136741
  })
136730
136742
  };
136731
136743
  }
136732
- var execFileAsync3, PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136744
+ var execFileAsync3, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136733
136745
  var init_proposal_inbox = __esm({
136734
136746
  "src/core/proposal-inbox.mjs"() {
136735
136747
  init_errors3();
136736
136748
  init_presets();
136737
136749
  init_git_url_policy();
136750
+ init_proposal_document();
136751
+ init_proposal_document();
136738
136752
  execFileAsync3 = promisify14(execFileCb14);
136739
- PROPOSAL_SCHEMA_VERSION = 1;
136740
- PROPOSAL_KIND = "release-skill/update-proposal";
136741
136753
  PROBE_TIMEOUT_MS = 3e4;
136742
136754
  GIT_TIMEOUT_MS = 12e4;
136743
136755
  TRANSFER_TIMEOUT_MS = 3e5;
@@ -136779,8 +136791,6 @@ var init_proposal_inbox = __esm({
136779
136791
  __name(stderrTail, "stderrTail");
136780
136792
  __name(classifyNetFailure, "classifyNetFailure");
136781
136793
  __name(parseLsRemote, "parseLsRemote");
136782
- __name(proposalFileName, "proposalFileName");
136783
- __name(buildProposalDocument, "buildProposalDocument");
136784
136794
  __name(buildManualSyncPrompt, "buildManualSyncPrompt");
136785
136795
  __name(crossCheckPushedCommit, "crossCheckPushedCommit");
136786
136796
  __name(observeProposalInboxGitPush, "observeProposalInboxGitPush");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
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.11.",
22
+ "Prepare a release plan for version 0.9.12.",
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.11"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.12"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "42faaeb2d272e94efd6075f39b6553540afc307ce64a853a8021eb474fdb380b";
14
+ const __bundleSourceDigest = "e6659bd85e866fd7a2780e48de7c89324b9211503d1029a94ce271384f0678b7";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136313,6 +136313,49 @@ var init_notify_handoff = __esm({
136313
136313
  }
136314
136314
  });
136315
136315
 
136316
+ // src/core/proposal-document.mjs
136317
+ function proposalFileName(unitId, version) {
136318
+ if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136319
+ throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136320
+ }
136321
+ return `incoming/${unitId}-${version}.json`;
136322
+ }
136323
+ function buildProposalDocument(context) {
136324
+ const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136325
+ for (const field of required) {
136326
+ if (typeof context?.[field] !== "string" || context[field].length === 0) {
136327
+ throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136328
+ }
136329
+ }
136330
+ const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136331
+ return {
136332
+ schemaVersion: PROPOSAL_SCHEMA_VERSION,
136333
+ kind: PROPOSAL_KIND,
136334
+ unitId,
136335
+ version,
136336
+ tag,
136337
+ sha: commit,
136338
+ commit,
136339
+ ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136340
+ ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136341
+ planDigest,
136342
+ runId,
136343
+ ...publishedAt !== void 0 ? { publishedAt } : {},
136344
+ ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136345
+ changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136346
+ };
136347
+ }
136348
+ var PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND;
136349
+ var init_proposal_document = __esm({
136350
+ "src/core/proposal-document.mjs"() {
136351
+ init_errors3();
136352
+ PROPOSAL_SCHEMA_VERSION = 1;
136353
+ PROPOSAL_KIND = "release-skill/update-proposal";
136354
+ __name(proposalFileName, "proposalFileName");
136355
+ __name(buildProposalDocument, "buildProposalDocument");
136356
+ }
136357
+ });
136358
+
136316
136359
  // src/core/proposal-inbox.mjs
136317
136360
  import { execFile as execFileCb14 } from "node:child_process";
136318
136361
  import { promisify as promisify14 } from "node:util";
@@ -136389,37 +136432,6 @@ function parseLsRemote(stdout) {
136389
136432
  }
136390
136433
  return refs;
136391
136434
  }
136392
- function proposalFileName(unitId, version) {
136393
- if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136394
- throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136395
- }
136396
- return `incoming/${unitId}-${version}.json`;
136397
- }
136398
- function buildProposalDocument(context) {
136399
- const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136400
- for (const field of required) {
136401
- if (typeof context?.[field] !== "string" || context[field].length === 0) {
136402
- throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136403
- }
136404
- }
136405
- const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136406
- return {
136407
- schemaVersion: PROPOSAL_SCHEMA_VERSION,
136408
- kind: PROPOSAL_KIND,
136409
- unitId,
136410
- version,
136411
- tag,
136412
- sha: commit,
136413
- commit,
136414
- ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136415
- ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136416
- planDigest,
136417
- runId,
136418
- ...publishedAt !== void 0 ? { publishedAt } : {},
136419
- ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136420
- changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136421
- };
136422
- }
136423
136435
  function buildManualSyncPrompt({ remoteUrl, proposalPath, branch }) {
136424
136436
  const safeRemoteUrl = redactUrlCredentialsIfPresent(remoteUrl);
136425
136437
  return `manual sync required: review proposal ${proposalPath} in downstream repository ${safeRemoteUrl} (branch ${branch}); suggested action: open a pull request or apply the proposal through the downstream governance workflow`;
@@ -136729,15 +136741,15 @@ async function executeProposalInboxLocalFileHook(params) {
136729
136741
  })
136730
136742
  };
136731
136743
  }
136732
- var execFileAsync3, PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136744
+ var execFileAsync3, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136733
136745
  var init_proposal_inbox = __esm({
136734
136746
  "src/core/proposal-inbox.mjs"() {
136735
136747
  init_errors3();
136736
136748
  init_presets();
136737
136749
  init_git_url_policy();
136750
+ init_proposal_document();
136751
+ init_proposal_document();
136738
136752
  execFileAsync3 = promisify14(execFileCb14);
136739
- PROPOSAL_SCHEMA_VERSION = 1;
136740
- PROPOSAL_KIND = "release-skill/update-proposal";
136741
136753
  PROBE_TIMEOUT_MS = 3e4;
136742
136754
  GIT_TIMEOUT_MS = 12e4;
136743
136755
  TRANSFER_TIMEOUT_MS = 3e5;
@@ -136779,8 +136791,6 @@ var init_proposal_inbox = __esm({
136779
136791
  __name(stderrTail, "stderrTail");
136780
136792
  __name(classifyNetFailure, "classifyNetFailure");
136781
136793
  __name(parseLsRemote, "parseLsRemote");
136782
- __name(proposalFileName, "proposalFileName");
136783
- __name(buildProposalDocument, "buildProposalDocument");
136784
136794
  __name(buildManualSyncPrompt, "buildManualSyncPrompt");
136785
136795
  __name(crossCheckPushedCommit, "crossCheckPushedCommit");
136786
136796
  __name(observeProposalInboxGitPush, "observeProposalInboxGitPush");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
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.11"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.12"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "42faaeb2d272e94efd6075f39b6553540afc307ce64a853a8021eb474fdb380b";
14
+ const __bundleSourceDigest = "e6659bd85e866fd7a2780e48de7c89324b9211503d1029a94ce271384f0678b7";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136313,6 +136313,49 @@ var init_notify_handoff = __esm({
136313
136313
  }
136314
136314
  });
136315
136315
 
136316
+ // src/core/proposal-document.mjs
136317
+ function proposalFileName(unitId, version) {
136318
+ if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136319
+ throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136320
+ }
136321
+ return `incoming/${unitId}-${version}.json`;
136322
+ }
136323
+ function buildProposalDocument(context) {
136324
+ const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136325
+ for (const field of required) {
136326
+ if (typeof context?.[field] !== "string" || context[field].length === 0) {
136327
+ throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136328
+ }
136329
+ }
136330
+ const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136331
+ return {
136332
+ schemaVersion: PROPOSAL_SCHEMA_VERSION,
136333
+ kind: PROPOSAL_KIND,
136334
+ unitId,
136335
+ version,
136336
+ tag,
136337
+ sha: commit,
136338
+ commit,
136339
+ ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136340
+ ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136341
+ planDigest,
136342
+ runId,
136343
+ ...publishedAt !== void 0 ? { publishedAt } : {},
136344
+ ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136345
+ changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136346
+ };
136347
+ }
136348
+ var PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND;
136349
+ var init_proposal_document = __esm({
136350
+ "src/core/proposal-document.mjs"() {
136351
+ init_errors3();
136352
+ PROPOSAL_SCHEMA_VERSION = 1;
136353
+ PROPOSAL_KIND = "release-skill/update-proposal";
136354
+ __name(proposalFileName, "proposalFileName");
136355
+ __name(buildProposalDocument, "buildProposalDocument");
136356
+ }
136357
+ });
136358
+
136316
136359
  // src/core/proposal-inbox.mjs
136317
136360
  import { execFile as execFileCb14 } from "node:child_process";
136318
136361
  import { promisify as promisify14 } from "node:util";
@@ -136389,37 +136432,6 @@ function parseLsRemote(stdout) {
136389
136432
  }
136390
136433
  return refs;
136391
136434
  }
136392
- function proposalFileName(unitId, version) {
136393
- if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136394
- throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136395
- }
136396
- return `incoming/${unitId}-${version}.json`;
136397
- }
136398
- function buildProposalDocument(context) {
136399
- const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136400
- for (const field of required) {
136401
- if (typeof context?.[field] !== "string" || context[field].length === 0) {
136402
- throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136403
- }
136404
- }
136405
- const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136406
- return {
136407
- schemaVersion: PROPOSAL_SCHEMA_VERSION,
136408
- kind: PROPOSAL_KIND,
136409
- unitId,
136410
- version,
136411
- tag,
136412
- sha: commit,
136413
- commit,
136414
- ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136415
- ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136416
- planDigest,
136417
- runId,
136418
- ...publishedAt !== void 0 ? { publishedAt } : {},
136419
- ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136420
- changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136421
- };
136422
- }
136423
136435
  function buildManualSyncPrompt({ remoteUrl, proposalPath, branch }) {
136424
136436
  const safeRemoteUrl = redactUrlCredentialsIfPresent(remoteUrl);
136425
136437
  return `manual sync required: review proposal ${proposalPath} in downstream repository ${safeRemoteUrl} (branch ${branch}); suggested action: open a pull request or apply the proposal through the downstream governance workflow`;
@@ -136729,15 +136741,15 @@ async function executeProposalInboxLocalFileHook(params) {
136729
136741
  })
136730
136742
  };
136731
136743
  }
136732
- var execFileAsync3, PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136744
+ var execFileAsync3, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136733
136745
  var init_proposal_inbox = __esm({
136734
136746
  "src/core/proposal-inbox.mjs"() {
136735
136747
  init_errors3();
136736
136748
  init_presets();
136737
136749
  init_git_url_policy();
136750
+ init_proposal_document();
136751
+ init_proposal_document();
136738
136752
  execFileAsync3 = promisify14(execFileCb14);
136739
- PROPOSAL_SCHEMA_VERSION = 1;
136740
- PROPOSAL_KIND = "release-skill/update-proposal";
136741
136753
  PROBE_TIMEOUT_MS = 3e4;
136742
136754
  GIT_TIMEOUT_MS = 12e4;
136743
136755
  TRANSFER_TIMEOUT_MS = 3e5;
@@ -136779,8 +136791,6 @@ var init_proposal_inbox = __esm({
136779
136791
  __name(stderrTail, "stderrTail");
136780
136792
  __name(classifyNetFailure, "classifyNetFailure");
136781
136793
  __name(parseLsRemote, "parseLsRemote");
136782
- __name(proposalFileName, "proposalFileName");
136783
- __name(buildProposalDocument, "buildProposalDocument");
136784
136794
  __name(buildManualSyncPrompt, "buildManualSyncPrompt");
136785
136795
  __name(crossCheckPushedCommit, "crossCheckPushedCommit");
136786
136796
  __name(observeProposalInboxGitPush, "observeProposalInboxGitPush");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
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.11"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.12"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "42faaeb2d272e94efd6075f39b6553540afc307ce64a853a8021eb474fdb380b";
14
+ const __bundleSourceDigest = "e6659bd85e866fd7a2780e48de7c89324b9211503d1029a94ce271384f0678b7";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136313,6 +136313,49 @@ var init_notify_handoff = __esm({
136313
136313
  }
136314
136314
  });
136315
136315
 
136316
+ // src/core/proposal-document.mjs
136317
+ function proposalFileName(unitId, version) {
136318
+ if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136319
+ throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136320
+ }
136321
+ return `incoming/${unitId}-${version}.json`;
136322
+ }
136323
+ function buildProposalDocument(context) {
136324
+ const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136325
+ for (const field of required) {
136326
+ if (typeof context?.[field] !== "string" || context[field].length === 0) {
136327
+ throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136328
+ }
136329
+ }
136330
+ const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136331
+ return {
136332
+ schemaVersion: PROPOSAL_SCHEMA_VERSION,
136333
+ kind: PROPOSAL_KIND,
136334
+ unitId,
136335
+ version,
136336
+ tag,
136337
+ sha: commit,
136338
+ commit,
136339
+ ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136340
+ ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136341
+ planDigest,
136342
+ runId,
136343
+ ...publishedAt !== void 0 ? { publishedAt } : {},
136344
+ ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136345
+ changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136346
+ };
136347
+ }
136348
+ var PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND;
136349
+ var init_proposal_document = __esm({
136350
+ "src/core/proposal-document.mjs"() {
136351
+ init_errors3();
136352
+ PROPOSAL_SCHEMA_VERSION = 1;
136353
+ PROPOSAL_KIND = "release-skill/update-proposal";
136354
+ __name(proposalFileName, "proposalFileName");
136355
+ __name(buildProposalDocument, "buildProposalDocument");
136356
+ }
136357
+ });
136358
+
136316
136359
  // src/core/proposal-inbox.mjs
136317
136360
  import { execFile as execFileCb14 } from "node:child_process";
136318
136361
  import { promisify as promisify14 } from "node:util";
@@ -136389,37 +136432,6 @@ function parseLsRemote(stdout) {
136389
136432
  }
136390
136433
  return refs;
136391
136434
  }
136392
- function proposalFileName(unitId, version) {
136393
- if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136394
- throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136395
- }
136396
- return `incoming/${unitId}-${version}.json`;
136397
- }
136398
- function buildProposalDocument(context) {
136399
- const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136400
- for (const field of required) {
136401
- if (typeof context?.[field] !== "string" || context[field].length === 0) {
136402
- throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136403
- }
136404
- }
136405
- const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136406
- return {
136407
- schemaVersion: PROPOSAL_SCHEMA_VERSION,
136408
- kind: PROPOSAL_KIND,
136409
- unitId,
136410
- version,
136411
- tag,
136412
- sha: commit,
136413
- commit,
136414
- ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136415
- ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136416
- planDigest,
136417
- runId,
136418
- ...publishedAt !== void 0 ? { publishedAt } : {},
136419
- ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136420
- changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136421
- };
136422
- }
136423
136435
  function buildManualSyncPrompt({ remoteUrl, proposalPath, branch }) {
136424
136436
  const safeRemoteUrl = redactUrlCredentialsIfPresent(remoteUrl);
136425
136437
  return `manual sync required: review proposal ${proposalPath} in downstream repository ${safeRemoteUrl} (branch ${branch}); suggested action: open a pull request or apply the proposal through the downstream governance workflow`;
@@ -136729,15 +136741,15 @@ async function executeProposalInboxLocalFileHook(params) {
136729
136741
  })
136730
136742
  };
136731
136743
  }
136732
- var execFileAsync3, PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136744
+ var execFileAsync3, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136733
136745
  var init_proposal_inbox = __esm({
136734
136746
  "src/core/proposal-inbox.mjs"() {
136735
136747
  init_errors3();
136736
136748
  init_presets();
136737
136749
  init_git_url_policy();
136750
+ init_proposal_document();
136751
+ init_proposal_document();
136738
136752
  execFileAsync3 = promisify14(execFileCb14);
136739
- PROPOSAL_SCHEMA_VERSION = 1;
136740
- PROPOSAL_KIND = "release-skill/update-proposal";
136741
136753
  PROBE_TIMEOUT_MS = 3e4;
136742
136754
  GIT_TIMEOUT_MS = 12e4;
136743
136755
  TRANSFER_TIMEOUT_MS = 3e5;
@@ -136779,8 +136791,6 @@ var init_proposal_inbox = __esm({
136779
136791
  __name(stderrTail, "stderrTail");
136780
136792
  __name(classifyNetFailure, "classifyNetFailure");
136781
136793
  __name(parseLsRemote, "parseLsRemote");
136782
- __name(proposalFileName, "proposalFileName");
136783
- __name(buildProposalDocument, "buildProposalDocument");
136784
136794
  __name(buildManualSyncPrompt, "buildManualSyncPrompt");
136785
136795
  __name(crossCheckPushedCommit, "crossCheckPushedCommit");
136786
136796
  __name(observeProposalInboxGitPush, "observeProposalInboxGitPush");
@@ -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.11"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.12"});
13
13
  // Build-time source digest for the BUNDLE_STALE freshness gate (see above).
14
- const __bundleSourceDigest = "42faaeb2d272e94efd6075f39b6553540afc307ce64a853a8021eb474fdb380b";
14
+ const __bundleSourceDigest = "e6659bd85e866fd7a2780e48de7c89324b9211503d1029a94ce271384f0678b7";
15
15
 
16
16
  var __create = Object.create;
17
17
  var __defProp = Object.defineProperty;
@@ -136313,6 +136313,49 @@ var init_notify_handoff = __esm({
136313
136313
  }
136314
136314
  });
136315
136315
 
136316
+ // src/core/proposal-document.mjs
136317
+ function proposalFileName(unitId, version) {
136318
+ if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136319
+ throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136320
+ }
136321
+ return `incoming/${unitId}-${version}.json`;
136322
+ }
136323
+ function buildProposalDocument(context) {
136324
+ const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136325
+ for (const field of required) {
136326
+ if (typeof context?.[field] !== "string" || context[field].length === 0) {
136327
+ throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136328
+ }
136329
+ }
136330
+ const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136331
+ return {
136332
+ schemaVersion: PROPOSAL_SCHEMA_VERSION,
136333
+ kind: PROPOSAL_KIND,
136334
+ unitId,
136335
+ version,
136336
+ tag,
136337
+ sha: commit,
136338
+ commit,
136339
+ ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136340
+ ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136341
+ planDigest,
136342
+ runId,
136343
+ ...publishedAt !== void 0 ? { publishedAt } : {},
136344
+ ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136345
+ changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136346
+ };
136347
+ }
136348
+ var PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND;
136349
+ var init_proposal_document = __esm({
136350
+ "src/core/proposal-document.mjs"() {
136351
+ init_errors3();
136352
+ PROPOSAL_SCHEMA_VERSION = 1;
136353
+ PROPOSAL_KIND = "release-skill/update-proposal";
136354
+ __name(proposalFileName, "proposalFileName");
136355
+ __name(buildProposalDocument, "buildProposalDocument");
136356
+ }
136357
+ });
136358
+
136316
136359
  // src/core/proposal-inbox.mjs
136317
136360
  import { execFile as execFileCb14 } from "node:child_process";
136318
136361
  import { promisify as promisify14 } from "node:util";
@@ -136389,37 +136432,6 @@ function parseLsRemote(stdout) {
136389
136432
  }
136390
136433
  return refs;
136391
136434
  }
136392
- function proposalFileName(unitId, version) {
136393
- if (typeof unitId !== "string" || unitId.length === 0 || typeof version !== "string" || version.length === 0) {
136394
- throw new ReleaseError(GATE_FAILED, "proposal file name requires unitId and version", { unitId, version });
136395
- }
136396
- return `incoming/${unitId}-${version}.json`;
136397
- }
136398
- function buildProposalDocument(context) {
136399
- const required = ["unitId", "version", "tag", "commit", "planDigest", "runId"];
136400
- for (const field of required) {
136401
- if (typeof context?.[field] !== "string" || context[field].length === 0) {
136402
- throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
136403
- }
136404
- }
136405
- const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
136406
- return {
136407
- schemaVersion: PROPOSAL_SCHEMA_VERSION,
136408
- kind: PROPOSAL_KIND,
136409
- unitId,
136410
- version,
136411
- tag,
136412
- sha: commit,
136413
- commit,
136414
- ...typeof tree === "string" && tree.length > 0 ? { tree } : {},
136415
- ...typeof manifestDigest === "string" && manifestDigest.length > 0 ? { manifestDigest } : {},
136416
- planDigest,
136417
- runId,
136418
- ...publishedAt !== void 0 ? { publishedAt } : {},
136419
- ...verifyEvidence !== void 0 ? { verifyEvidence } : {},
136420
- changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`
136421
- };
136422
- }
136423
136435
  function buildManualSyncPrompt({ remoteUrl, proposalPath, branch }) {
136424
136436
  const safeRemoteUrl = redactUrlCredentialsIfPresent(remoteUrl);
136425
136437
  return `manual sync required: review proposal ${proposalPath} in downstream repository ${safeRemoteUrl} (branch ${branch}); suggested action: open a pull request or apply the proposal through the downstream governance workflow`;
@@ -136729,15 +136741,15 @@ async function executeProposalInboxLocalFileHook(params) {
136729
136741
  })
136730
136742
  };
136731
136743
  }
136732
- var execFileAsync3, PROPOSAL_SCHEMA_VERSION, PROPOSAL_KIND, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136744
+ var execFileAsync3, PROBE_TIMEOUT_MS, GIT_TIMEOUT_MS, TRANSFER_TIMEOUT_MS, TMP_PREFIX, SAFE_BRANCH_RE, SHA_RE2, NEVER_PROMPT_ENV, AUTH_FAILURE_PATTERNS, TRANSPORT_FAILURE_PATTERNS;
136733
136745
  var init_proposal_inbox = __esm({
136734
136746
  "src/core/proposal-inbox.mjs"() {
136735
136747
  init_errors3();
136736
136748
  init_presets();
136737
136749
  init_git_url_policy();
136750
+ init_proposal_document();
136751
+ init_proposal_document();
136738
136752
  execFileAsync3 = promisify14(execFileCb14);
136739
- PROPOSAL_SCHEMA_VERSION = 1;
136740
- PROPOSAL_KIND = "release-skill/update-proposal";
136741
136753
  PROBE_TIMEOUT_MS = 3e4;
136742
136754
  GIT_TIMEOUT_MS = 12e4;
136743
136755
  TRANSFER_TIMEOUT_MS = 3e5;
@@ -136779,8 +136791,6 @@ var init_proposal_inbox = __esm({
136779
136791
  __name(stderrTail, "stderrTail");
136780
136792
  __name(classifyNetFailure, "classifyNetFailure");
136781
136793
  __name(parseLsRemote, "parseLsRemote");
136782
- __name(proposalFileName, "proposalFileName");
136783
- __name(buildProposalDocument, "buildProposalDocument");
136784
136794
  __name(buildManualSyncPrompt, "buildManualSyncPrompt");
136785
136795
  __name(crossCheckPushedCommit, "crossCheckPushedCommit");
136786
136796
  __name(observeProposalInboxGitPush, "observeProposalInboxGitPush");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
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.11",
5
+ "version": "0.9.12",
6
6
  "logicalRoot": "skills-src/",
7
7
  "logicalRootDigest": "aec96745b30289ed48d576fbfc98ecd3aacb834f83394be76d4734d7d0fc0ad4",
8
8
  "projectionDigest": "e5117d89c9f965e15a1464cc84f542cb1e75a685f842183d0cfc7a105ace5ceb",
9
- "projectionId": "release-skill:platform:0.9.11",
9
+ "projectionId": "release-skill:platform:0.9.12",
10
10
  "manifestRequired": true,
11
11
  "projectionSources": {
12
12
  "skills-src-root": {
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Pure proposal-document projection shared by runtime transports and frozen
3
+ * postVerify execution hooks. Keep this module free of package dependencies
4
+ * so a detached public-tag worktree can load it without node_modules.
5
+ *
6
+ * @module core/proposal-document
7
+ */
8
+
9
+ import { ReleaseError, GATE_FAILED } from './errors.mjs';
10
+
11
+ /** Proposal document identity. */
12
+ export const PROPOSAL_SCHEMA_VERSION = 1;
13
+ export const PROPOSAL_KIND = 'release-skill/update-proposal';
14
+
15
+ /** Proposal file location inside the downstream repository. */
16
+ export function proposalFileName(unitId, version) {
17
+ if (typeof unitId !== 'string' || unitId.length === 0
18
+ || typeof version !== 'string' || version.length === 0) {
19
+ throw new ReleaseError(GATE_FAILED, 'proposal file name requires unitId and version', { unitId, version });
20
+ }
21
+ return `incoming/${unitId}-${version}.json`;
22
+ }
23
+
24
+ /**
25
+ * Build the deterministic downstream proposal from a post-publish context.
26
+ * Local materialization paths are intentionally excluded.
27
+ */
28
+ export function buildProposalDocument(context) {
29
+ const required = ['unitId', 'version', 'tag', 'commit', 'planDigest', 'runId'];
30
+ for (const field of required) {
31
+ if (typeof context?.[field] !== 'string' || context[field].length === 0) {
32
+ throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
33
+ }
34
+ }
35
+ const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
36
+ return {
37
+ schemaVersion: PROPOSAL_SCHEMA_VERSION,
38
+ kind: PROPOSAL_KIND,
39
+ unitId,
40
+ version,
41
+ tag,
42
+ sha: commit,
43
+ commit,
44
+ ...(typeof tree === 'string' && tree.length > 0 ? { tree } : {}),
45
+ ...(typeof manifestDigest === 'string' && manifestDigest.length > 0 ? { manifestDigest } : {}),
46
+ planDigest,
47
+ runId,
48
+ ...(publishedAt !== undefined ? { publishedAt } : {}),
49
+ ...(verifyEvidence !== undefined ? { verifyEvidence } : {}),
50
+ changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`,
51
+ };
52
+ }
@@ -53,12 +53,16 @@ import {
53
53
  describeGitRemoteUrlFailure,
54
54
  redactUrlCredentialsIfPresent,
55
55
  } from './git-url-policy.mjs';
56
+ import { buildProposalDocument, proposalFileName } from './proposal-document.mjs';
56
57
 
57
- const execFileAsync = promisify(execFileCb);
58
+ export {
59
+ PROPOSAL_SCHEMA_VERSION,
60
+ PROPOSAL_KIND,
61
+ buildProposalDocument,
62
+ proposalFileName,
63
+ } from './proposal-document.mjs';
58
64
 
59
- /** Proposal document identity. */
60
- export const PROPOSAL_SCHEMA_VERSION = 1;
61
- export const PROPOSAL_KIND = 'release-skill/update-proposal';
65
+ const execFileAsync = promisify(execFileCb);
62
66
 
63
67
  const PROBE_TIMEOUT_MS = 30_000;
64
68
  const GIT_TIMEOUT_MS = 120_000;
@@ -187,54 +191,6 @@ function parseLsRemote(stdout) {
187
191
  // Proposal document (deterministic projection of the §2.3 context)
188
192
  // ---------------------------------------------------------------------------
189
193
 
190
- /** Proposal file location inside the downstream repository. */
191
- export function proposalFileName(unitId, version) {
192
- if (typeof unitId !== 'string' || unitId.length === 0
193
- || typeof version !== 'string' || version.length === 0) {
194
- throw new ReleaseError(GATE_FAILED, 'proposal file name requires unitId and version', { unitId, version });
195
- }
196
- return `incoming/${unitId}-${version}.json`;
197
- }
198
-
199
- /**
200
- * Build the proposal document from the §2.3 context projection. Pure and
201
- * deterministic. Deliberately EXCLUDES payloadDir (a local materialization
202
- * path has no place in a downstream-facing document), and optional frozen
203
- * fields are ABSENT rather than null when the plan did not freeze them.
204
- *
205
- * Field set suffices to backfill a missing downstream hub entry:
206
- * unitId/version/tag/sha/commit/tree/manifestDigest/planDigest/runId/
207
- * publishedAt/verifyEvidence/changeSummary.
208
- *
209
- * @param {object} context - The §2.3 context projection.
210
- * @returns {object} The proposal document.
211
- */
212
- export function buildProposalDocument(context) {
213
- const required = ['unitId', 'version', 'tag', 'commit', 'planDigest', 'runId'];
214
- for (const field of required) {
215
- if (typeof context?.[field] !== 'string' || context[field].length === 0) {
216
- throw new ReleaseError(GATE_FAILED, `proposal document requires context field "${field}"`, { field });
217
- }
218
- }
219
- const { unitId, version, tag, commit, tree, manifestDigest, planDigest, runId, publishedAt, verifyEvidence } = context;
220
- return {
221
- schemaVersion: PROPOSAL_SCHEMA_VERSION,
222
- kind: PROPOSAL_KIND,
223
- unitId,
224
- version,
225
- tag,
226
- sha: commit,
227
- commit,
228
- ...(typeof tree === 'string' && tree.length > 0 ? { tree } : {}),
229
- ...(typeof manifestDigest === 'string' && manifestDigest.length > 0 ? { manifestDigest } : {}),
230
- planDigest,
231
- runId,
232
- ...(publishedAt !== undefined ? { publishedAt } : {}),
233
- ...(verifyEvidence !== undefined ? { verifyEvidence } : {}),
234
- changeSummary: `release ${unitId} ${version} (tag ${tag}, commit ${commit})`,
235
- };
236
- }
237
-
238
194
  /**
239
195
  * Deterministic manual-sync prompt (closure semantics): delivery success plus
240
196
  * this prompt in evidence IS the closed loop — downstream consumption is the