release-skill 0.9.35 → 0.9.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -2
- package/.cursor-plugin/plugin.json +1 -1
- package/.kimi-plugin/plugin.json +1 -1
- package/.qoder-plugin/plugin.json +1 -1
- package/CHANGELOG.md +21 -0
- package/INSTALL.md +2 -2
- package/INSTALL.zh-CN.md +2 -2
- package/README.md +10 -9
- package/README.zh-CN.md +10 -9
- package/adapters/claude/.claude-plugin/plugin.json +1 -1
- package/adapters/claude/bin/release-skill.bundle.mjs +162 -47
- package/adapters/claude/schemas/.render-manifest.json +6 -2
- package/adapters/claude/skills/release-finish/SKILL.md +2 -2
- package/adapters/claude/skills/release-help/SKILL.md +1 -1
- package/adapters/codex/.codex-plugin/plugin.json +2 -2
- package/adapters/codex/bin/release-skill.bundle.mjs +162 -47
- package/adapters/codex/schemas/.render-manifest.json +6 -2
- package/adapters/codex/skills/release-finish/SKILL.md +2 -2
- package/adapters/codex/skills/release-help/SKILL.md +1 -1
- package/adapters/cursor/.cursor-plugin/plugin.json +1 -1
- package/adapters/cursor/bin/release-skill.bundle.mjs +162 -47
- package/adapters/cursor/schemas/.render-manifest.json +6 -2
- package/adapters/cursor/skills/release-finish/SKILL.md +2 -2
- package/adapters/cursor/skills/release-help/SKILL.md +1 -1
- package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
- package/adapters/kimi/bin/release-skill.bundle.mjs +162 -47
- package/adapters/kimi/schemas/.render-manifest.json +6 -2
- package/adapters/kimi/skills/release-finish/SKILL.md +2 -2
- package/adapters/kimi/skills/release-help/SKILL.md +1 -1
- package/adapters/qoder/.qoder-plugin/plugin.json +1 -1
- package/adapters/qoder/bin/release-skill.bundle.mjs +162 -47
- package/adapters/qoder/schemas/.render-manifest.json +6 -2
- package/adapters/qoder/skills/release-finish/SKILL.md +2 -2
- package/adapters/qoder/skills/release-help/SKILL.md +1 -1
- package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
- package/adapters/workbuddy/bin/release-skill.bundle.mjs +162 -47
- package/adapters/workbuddy/schemas/.render-manifest.json +6 -2
- package/adapters/workbuddy/skills/release-finish/SKILL.md +2 -2
- package/adapters/workbuddy/skills/release-help/SKILL.md +1 -1
- package/bin/release-skill.bundle.mjs +162 -47
- package/package.json +1 -1
- package/platform-manifest.json +4 -4
- package/references/.render-manifest.json +2 -2
- package/references/02-project-config.md +3 -1
- package/schemas/.render-manifest.json +6 -2
- package/skills/release-finish/SKILL.md +2 -2
- package/skills/release-help/SKILL.md +1 -1
- package/skills-src/release-finish/SKILL.md +2 -2
- package/skills-src/release-help/SKILL.md +1 -1
- package/src/adapters/plugin-marketplace.mjs +152 -43
- package/src/commands/post-release-local.mjs +41 -22
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.36",
|
|
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.
|
|
22
|
+
"Prepare a release plan for version 0.9.36.",
|
|
23
23
|
"Help me understand the release workflow."
|
|
24
24
|
]
|
|
25
25
|
}
|
package/.kimi-plugin/plugin.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
<!-- release-skill:changelog:start version=0.9.36 locale=en baseline=sha256:704d09597e835404867409d99c9b8d674751ef145a9e0855d6e2182d768bb3a2 -->
|
|
4
|
+
## [0.9.36] - 2026-10-22
|
|
5
|
+
|
|
6
|
+
0.9.36 fixes incorrect rejection of valid dual-projection plugin directories in Qoder, ensures correct validation of market sources via both URL and GitHub-based manifests, and corrects Codex entry root detection to respect manifest-declared paths instead of hardcoding `skills/`. This release note is not evidence of publication, real-host acceptance, consumer installation verification, or independent acceptance. Foundation dependencies remain pinned to 0.25.0.
|
|
7
|
+
|
|
8
|
+
### Security
|
|
9
|
+
|
|
10
|
+
- Foundation 0.25.0 remains unchanged; the source, scope, commit/digest, and full payload are preserved. The frozen snapshot is re-verified before writing, and the full payload is compared after installation. No new market, first-install, host strategy, framework, dependency, or tier has been introduced. 0.9.35 is immutable. Skill Family Hub remains the unified marketplace, using GitHub Git Data API and compare-and-swap bound to the observed branch head. Partial Hub publication is never rolled back or force-pushed; completed steps are not overwritten.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- In 0.9.35, Qoder plugins incorrectly rejected valid dual-projection directories. The `name` and `version` in `.qoder-plugin/plugin.json` and `.claude-plugin/plugin.json` must bind to the same frozen target, though individual `skills` can differ. Each present candidate must be a valid JSON object, match the target identity, have non-empty `skills`, and resolve to a real directory within the plugin root. Native takes precedence; compatibility is only used when native is missing. If any candidate is invalid, installation fails immediately without fallback. After installation, the selected path and `skills` must exactly match the frozen choice, and full payload validation is retained.
|
|
15
|
+
- Qoder now also accepts existing markets that provide `.claude-plugin/marketplace.json` instead of a root `marketplace.json`. The system supports two existing locations: a URL-based `marketplace.json` at the root, and a GitHub-based `marketplace.json` in `.claude-plugin/`. At least one must exist. Each present index must be valid and contain exactly one entry for the target plugin, bound to the same frozen identity; other plugin entries remain allowed. A bad source is not ignored just because another is valid. URL sources require exact repository and SHA verification, and any explicit `version` or `ref` must match. GitHub sources require exact verification of `repo`, `ref`, `sha`, and `entry.version`. Only confirmed missing files are considered absent. Validation occurs after market refresh and before plugin update. `ALREADY_CURRENT` remains read-only with zero update commands.
|
|
16
|
+
- The Codex entry root check previously hardcoded `skills/`, rejecting valid paths like `.agents/skills/` declared in the manifest. Installation pre-check and post-install observation now respect the `skills` directory declared in the plugin manifest. When the field is missing, the default `skills/` path is retained, and existing prefix behavior is preserved. Explicitly invalid, out-of-bounds, or non-directory paths are rejected without fallback. Post-install observation and full payload verification must bind to the same frozen installation contract.
|
|
17
|
+
|
|
18
|
+
### Upgrade Notes
|
|
19
|
+
|
|
20
|
+
The release-skill standalone marketplace is deprecated; use `ifoohoo/skill-family-hub` and the updated `release-skill@skill-family-hub`, `release-finish`, and public CLI. Unmodified plugins need not be republished. Byte changes require a new frozen plan and matching approval. Installation does not imply loading — if actual loading is not observed, the state remains `reload-pending`. Local completion failure does not alter the remote `VERIFIED` status.
|
|
21
|
+
<!-- release-skill:changelog:end version=0.9.36 locale=en -->
|
|
22
|
+
|
|
23
|
+
|
|
3
24
|
<!-- release-skill:changelog:start version=0.9.35 locale=en baseline=sha256:d6b5bc6f37e83b5ac692f09dc175c61441598caa2f12679a2ffb2a11593b8bca -->
|
|
4
25
|
## [0.9.35] - 2026-10-22
|
|
5
26
|
|
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.
|
|
5
|
+
<!-- release-skill:release-version: 0.9.36 -->
|
|
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.
|
|
128
|
+
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.36
|
|
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.
|
|
5
|
+
<!-- release-skill:release-version: 0.9.36 -->
|
|
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.
|
|
116
|
+
/plugins install https://github.com/ifoohoo/release-skill/releases/tag/release-skill-v0.9.36
|
|
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.
|
|
5
|
+
<!-- release-skill:release-version: 0.9.36 -->
|
|
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,26 +14,27 @@ 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.
|
|
17
|
+
**0.9.36** (2026-10-22)
|
|
18
18
|
|
|
19
|
-
0.9.
|
|
19
|
+
0.9.36 fixes incorrect rejection of valid dual-projection plugin directories in Qoder, ensures correct validation of market sources via both URL and GitHub-based manifests, and corrects Codex entry root detection to respect manifest-declared paths instead of hardcoding `skills/`. This release note is not evidence of publication, real-host acceptance, consumer installation verification, or independent acceptance. Foundation dependencies remain pinned to 0.25.0.
|
|
20
20
|
|
|
21
21
|
**Security**
|
|
22
22
|
|
|
23
|
-
- The frozen snapshot is
|
|
23
|
+
- Foundation 0.25.0 remains unchanged; the source, scope, commit/digest, and full payload are preserved. The frozen snapshot is re-verified before writing, and the full payload is compared after installation. No new market, first-install, host strategy, framework, dependency, or tier has been introduced. 0.9.35 is immutable. Skill Family Hub remains the unified marketplace, using GitHub Git Data API and compare-and-swap bound to the observed branch head. Partial Hub publication is never rolled back or force-pushed; completed steps are not overwritten.
|
|
24
24
|
|
|
25
25
|
**Fixed**
|
|
26
26
|
|
|
27
|
-
- The
|
|
28
|
-
- The
|
|
27
|
+
- In 0.9.35, Qoder plugins incorrectly rejected valid dual-projection directories. The `name` and `version` in `.qoder-plugin/plugin.json` and `.claude-plugin/plugin.json` must bind to the same frozen target, though individual `skills` can differ. Each present candidate must be a valid JSON object, match the target identity, have non-empty `skills`, and resolve to a real directory within the plugin root. Native takes precedence; compatibility is only used when native is missing. If any candidate is invalid, installation fails immediately without fallback. After installation, the selected path and `skills` must exactly match the frozen choice, and full payload validation is retained.
|
|
28
|
+
- Qoder now also accepts existing markets that provide `.claude-plugin/marketplace.json` instead of a root `marketplace.json`. The system supports two existing locations: a URL-based `marketplace.json` at the root, and a GitHub-based `marketplace.json` in `.claude-plugin/`. At least one must exist. Each present index must be valid and contain exactly one entry for the target plugin, bound to the same frozen identity; other plugin entries remain allowed. A bad source is not ignored just because another is valid. URL sources require exact repository and SHA verification, and any explicit `version` or `ref` must match. GitHub sources require exact verification of `repo`, `ref`, `sha`, and `entry.version`. Only confirmed missing files are considered absent. Validation occurs after market refresh and before plugin update. `ALREADY_CURRENT` remains read-only with zero update commands.
|
|
29
|
+
- The Codex entry root check previously hardcoded `skills/`, rejecting valid paths like `.agents/skills/` declared in the manifest. Installation pre-check and post-install observation now respect the `skills` directory declared in the plugin manifest. When the field is missing, the default `skills/` path is retained, and existing prefix behavior is preserved. Explicitly invalid, out-of-bounds, or non-directory paths are rejected without fallback. Post-install observation and full payload verification must bind to the same frozen installation contract.
|
|
29
30
|
|
|
30
31
|
**Upgrade Notes**
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
The release-skill standalone marketplace is deprecated; use `ifoohoo/skill-family-hub` and the updated `release-skill@skill-family-hub`, `release-finish`, and public CLI. Unmodified plugins need not be republished. Byte changes require a new frozen plan and matching approval. Installation does not imply loading — if actual loading is not observed, the state remains `reload-pending`. Local completion failure does not alter the remote `VERIFIED` status.
|
|
33
34
|
<!-- release-skill:managed:end id=latest-release -->
|
|
34
35
|
|
|
35
36
|
<!-- release-skill:capability:external-write-boundary -->
|
|
36
|
-
> **Current boundary:** v0.9.
|
|
37
|
+
> **Current boundary:** v0.9.36: this README records capabilities and verification boundaries;
|
|
37
38
|
> it is not evidence of
|
|
38
39
|
> publication, consumer-installation verification, or independent acceptance.
|
|
39
40
|
> Release availability must be established from the corresponding release records
|
|
@@ -57,7 +58,7 @@ Use the updated `release-finish` entry from the public `release-skill@skill-fami
|
|
|
57
58
|
> publish global preflight.
|
|
58
59
|
|
|
59
60
|
<!-- release-skill:capability:safe-first-command -->
|
|
60
|
-
> **Production path verified since the v0.1.1 milestone; for v0.9.
|
|
61
|
+
> **Production path verified since the v0.1.1 milestone; for v0.9.36,
|
|
61
62
|
> publication, consumer-installation verification, and independent acceptance
|
|
62
63
|
> require version-specific release records and verification results.**
|
|
63
64
|
> The npm-installed CLI is the supported user entry. Source checkout
|
package/README.zh-CN.md
CHANGED
|
@@ -2,32 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) · 安装指南:[中文](INSTALL.zh-CN.md) / [English](INSTALL.md)
|
|
4
4
|
|
|
5
|
-
<!-- release-skill:release-version: 0.9.
|
|
5
|
+
<!-- release-skill:release-version: 0.9.36 -->
|
|
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
|
+
**0.9.36** (2026-10-22)
|
|
12
12
|
|
|
13
|
-
0.9.
|
|
13
|
+
0.9.36 修复 Qoder 插件清单对合法双投影目录的误拒,确保市场来源在 URL 与 GitHub 两种路径下均正确校验,修正 Codex 入口目录检测逻辑以尊重 manifest 声明路径而非硬编码 skills/。本发布说明不代表已经发布、完成真实宿主验收、完成消费者安装验证或通过独立验收。Foundation 依赖保持精确锁定为 0.25.0。
|
|
14
14
|
|
|
15
15
|
**安全**
|
|
16
16
|
|
|
17
|
-
-
|
|
17
|
+
- Foundation 0.25.0 保持不变;Hub 来源、user-scope、冻结 commit/digest 与完整载荷校验机制保留。写入宿主前复验冻结快照摘要,安装后比较完整载荷。无新增市场、首装、新宿主策略、新框架、新依赖或 tier 变化。0.9.35 不可变。Skill Family Hub 仍为统一市场,沿用 GitHub Git Data API,以比较后写入绑定已观察的分支头;部分发布不回滚、不覆盖已完成步骤。
|
|
18
18
|
|
|
19
19
|
**修复**
|
|
20
20
|
|
|
21
|
-
-
|
|
22
|
-
-
|
|
21
|
+
- 0.9.35 版本中,Qoder 插件误拒自身合法的双投影目录。`.qoder-plugin/plugin.json` 与 `.claude-plugin/plugin.json` 中的 name/version 必须绑定同一冻结目标,各自 skills 可不同。每个已存在候选必须是合法 JSON 对象、目标身份匹配、skills 非空且解析为插件根内真实目录。原生优先,仅原生缺失时才选兼容;任一候选无效即失败,不回退。安装后路径与 skills 必须精确匹配冻结选择,完整载荷检查保留。
|
|
22
|
+
- Qoder 现可接受只提供 `.claude-plugin/marketplace.json`、未提供根 marketplace.json 的既有市场。支持两种既有位置:根 marketplace.json 的 URL 来源,以及 `.claude-plugin/marketplace.json` 的 GitHub 来源。至少一份存在,每份已存在清单均须合法,且目标插件恰有一条、绑定同一冻结身份;市场仍可包含其他插件。不因另一份有效而忽略坏清单。URL 来源保留仓库与 sha 精确校验,显式 version/ref 必须匹配;兼容 GitHub 来源校验 repo/ref/sha/entry.version。仅确定缺文件视为缺席。市场刷新后、插件更新前校验;ALREADY_CURRENT 保持只读且零更新命令。
|
|
23
|
+
- Codex 入口目录原检查写死为 skills/,误拒 `.agents/skills/` 等合法 manifest 声明路径。安装前检查与安装后观察均采用 manifest 声明的 skills 目录。字段缺省时继续使用既有 skills/ 默认路径,入口名前缀行为保留。显式无效、越界或非目录路径拒绝,不回退。已安装入口观察与完整载荷验证须绑定同一冻结安装合同。
|
|
23
24
|
|
|
24
25
|
**升级说明**
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
原独立的 `release-skill` 市场已弃用。使用更新后的 `release-skill@skill-family-hub` 入口、`release-finish` 与公共 CLI。未改插件无需重发,改字节须新冻结计划与匹配批准。安装 ≠ 加载,未观察实际加载则保留 reload-pending 状态。本机收尾失败不改变远端 VERIFIED 状态。统一使用 `ifoohoo/skill-family-hub` 和 `release-skill@skill-family-hub`。
|
|
27
28
|
<!-- release-skill:managed:end id=latest-release -->
|
|
28
29
|
|
|
29
30
|
<!-- release-skill:capability:external-write-boundary -->
|
|
30
|
-
> **当前边界:** v0.9.
|
|
31
|
+
> **当前边界:** v0.9.36 的能力范围与验证边界见本 README,
|
|
31
32
|
> 不代表已经发布、完成消费者安装验证或通过独立验收。
|
|
32
33
|
> 版本可用性以对应发布记录及发布后验证结果为准。
|
|
33
34
|
> v0.4.1 是更早的已发布里程碑(v0.2.2 曾处于已发布状态,后因平台验证收敛修复而更新)。
|
|
@@ -43,7 +44,7 @@ release-skill 帮助维护者回答三个问题:准备发布什么、还有哪
|
|
|
43
44
|
> 远端唯一性检查在 `publish` 全局预检执行。
|
|
44
45
|
|
|
45
46
|
<!-- release-skill:capability:safe-first-command -->
|
|
46
|
-
> **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.9.
|
|
47
|
+
> **生产路径自 v0.1.1 里程碑起已完成真实生产验证;v0.9.36 的发布、消费者安装验证和独立验收状态须由该版本的发布记录及验证结果确认。**
|
|
47
48
|
> npm 安装的 CLI 是受支持的用户入口;源码 checkout 保留为开发/贡献者路径。
|
|
48
49
|
>
|
|
49
50
|
> **第一条命令:**
|
|
@@ -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.
|
|
12
|
+
const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.9.36"});
|
|
13
13
|
// Build-time source digest for the BUNDLE_STALE freshness gate (see above).
|
|
14
|
-
const __bundleSourceDigest = "
|
|
14
|
+
const __bundleSourceDigest = "bc9386087a5bffe2f92c12f687ec75582a9e853164020e99618a4bdf5cd13a68";
|
|
15
15
|
|
|
16
16
|
var __create = Object.create;
|
|
17
17
|
var __defProp = Object.defineProperty;
|
|
@@ -113912,6 +113912,66 @@ function normalizeCodeBuddySkillsRel(skillsRaw) {
|
|
|
113912
113912
|
}
|
|
113913
113913
|
return rel;
|
|
113914
113914
|
}
|
|
113915
|
+
async function resolveCodexEntrySkillFile(pluginRoot, entrySkill, pluginName) {
|
|
113916
|
+
const { normalizeGenericSkillsRel: normalizeGenericSkillsRel2 } = await init_surface_host_bindings().then(() => surface_host_bindings_exports);
|
|
113917
|
+
if (!entrySkill || typeof entrySkill !== "string" || !SAFE_ID_RE.test(entrySkill)) {
|
|
113918
|
+
throw new Error(`unsafe entrySkill: "${entrySkill}"`);
|
|
113919
|
+
}
|
|
113920
|
+
const platform = getPlatform("codex");
|
|
113921
|
+
const manifestPath = await resolveContained(pluginRoot, platform.manifestPaths.plugin);
|
|
113922
|
+
let manifest;
|
|
113923
|
+
try {
|
|
113924
|
+
manifest = JSON.parse(await readFile26(manifestPath, "utf8"));
|
|
113925
|
+
} catch (err) {
|
|
113926
|
+
throw new Error(`Codex plugin manifest cannot be read: ${err.message}`);
|
|
113927
|
+
}
|
|
113928
|
+
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
|
|
113929
|
+
throw new Error("Codex plugin manifest must be an object");
|
|
113930
|
+
}
|
|
113931
|
+
const skillsRel = Object.hasOwn(manifest, "skills") ? normalizeGenericSkillsRel2(manifest.skills) : "skills";
|
|
113932
|
+
const skillsRoot = await resolveContained(pluginRoot, skillsRel);
|
|
113933
|
+
let skillsRootStat;
|
|
113934
|
+
try {
|
|
113935
|
+
skillsRootStat = await lstat37(skillsRoot);
|
|
113936
|
+
} catch {
|
|
113937
|
+
throw new Error(`Codex manifest skills root does not exist: ${manifest.skills ?? skillsRel}`);
|
|
113938
|
+
}
|
|
113939
|
+
if (skillsRootStat.isSymbolicLink() || !skillsRootStat.isDirectory()) {
|
|
113940
|
+
throw new Error(`Codex manifest skills root must be a real directory: ${manifest.skills ?? skillsRel}`);
|
|
113941
|
+
}
|
|
113942
|
+
const findCandidate = /* @__PURE__ */ __name(async (skillDirName) => {
|
|
113943
|
+
const skillDir = await resolveContained(pluginRoot, `${skillsRel}/${skillDirName}`);
|
|
113944
|
+
let skillDirStat;
|
|
113945
|
+
try {
|
|
113946
|
+
skillDirStat = await lstat37(skillDir);
|
|
113947
|
+
} catch (err) {
|
|
113948
|
+
if (err?.code === "ENOENT") return null;
|
|
113949
|
+
throw err;
|
|
113950
|
+
}
|
|
113951
|
+
if (skillDirStat.isSymbolicLink() || !skillDirStat.isDirectory()) {
|
|
113952
|
+
throw new Error(`Codex entry skill directory must be a real directory: ${skillsRel}/${skillDirName}`);
|
|
113953
|
+
}
|
|
113954
|
+
const skillFile = await resolveContained(pluginRoot, `${skillsRel}/${skillDirName}/SKILL.md`);
|
|
113955
|
+
let skillStat;
|
|
113956
|
+
try {
|
|
113957
|
+
skillStat = await lstat37(skillFile);
|
|
113958
|
+
} catch (err) {
|
|
113959
|
+
if (err?.code === "ENOENT") return null;
|
|
113960
|
+
throw err;
|
|
113961
|
+
}
|
|
113962
|
+
if (skillStat.isSymbolicLink() || !skillStat.isFile()) {
|
|
113963
|
+
throw new Error(`Codex entry skill must be a regular non-symlink file: ${skillsRel}/${skillDirName}/SKILL.md`);
|
|
113964
|
+
}
|
|
113965
|
+
return skillFile;
|
|
113966
|
+
}, "findCandidate");
|
|
113967
|
+
const shortNameEntry = await findCandidate(entrySkill);
|
|
113968
|
+
if (shortNameEntry) return shortNameEntry;
|
|
113969
|
+
if (pluginName && SAFE_ID_RE.test(pluginName)) {
|
|
113970
|
+
const prefixedEntry = await findCandidate(`${pluginName}-${entrySkill}`);
|
|
113971
|
+
if (prefixedEntry) return prefixedEntry;
|
|
113972
|
+
}
|
|
113973
|
+
throw new Error(`Codex entry skill not found: ${skillsRel}/${entrySkill}/SKILL.md`);
|
|
113974
|
+
}
|
|
113915
113975
|
async function resolveCodeBuddyEntrySkillFile(pluginRootReal, manifest, entrySkill) {
|
|
113916
113976
|
if (!entrySkill || typeof entrySkill !== "string" || !SAFE_ID_RE.test(entrySkill)) {
|
|
113917
113977
|
throw new Error(`unsafe entrySkill: "${entrySkill}"`);
|
|
@@ -115067,6 +115127,17 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
115067
115127
|
error: `entry skill not resolvable in snapshot: ${entryErr.message}`
|
|
115068
115128
|
});
|
|
115069
115129
|
}
|
|
115130
|
+
} else if (consumer === "codex") {
|
|
115131
|
+
const pluginRootForSkill = pluginRootForEntrySkill || snapshotDirReal;
|
|
115132
|
+
try {
|
|
115133
|
+
await resolveCodexEntrySkillFile(pluginRootForSkill, action.entrySkill, action.plugin);
|
|
115134
|
+
} catch (entryErr) {
|
|
115135
|
+
return createResult({
|
|
115136
|
+
actionType,
|
|
115137
|
+
status: ActionStatus.PREFLIGHT_FAILED,
|
|
115138
|
+
error: `entry skill not resolvable in snapshot: ${entryErr.message}`
|
|
115139
|
+
});
|
|
115140
|
+
}
|
|
115070
115141
|
} else {
|
|
115071
115142
|
const pluginRootForSkill = pluginRootForEntrySkill || snapshotDirReal;
|
|
115072
115143
|
let entrySkillFile = resolve22(pluginRootForSkill, "skills", action.entrySkill, "SKILL.md");
|
|
@@ -116181,42 +116252,59 @@ function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
116181
116252
|
}
|
|
116182
116253
|
});
|
|
116183
116254
|
}
|
|
116184
|
-
|
|
116185
|
-
|
|
116186
|
-
|
|
116187
|
-
|
|
116188
|
-
|
|
116189
|
-
|
|
116255
|
+
if (consumer === "codex") {
|
|
116256
|
+
try {
|
|
116257
|
+
await resolveCodexEntrySkillFile(installPath, action.entrySkill, action.plugin);
|
|
116258
|
+
} catch (entryErr) {
|
|
116259
|
+
return createResult({
|
|
116260
|
+
actionType,
|
|
116261
|
+
status: ActionStatus.OBSERVED,
|
|
116262
|
+
observation: {
|
|
116263
|
+
installed: true,
|
|
116264
|
+
installPath,
|
|
116265
|
+
entrySkillFound: false,
|
|
116266
|
+
error: `entry skill not resolvable in installed plugin: ${entryErr.message}`
|
|
116267
|
+
}
|
|
116268
|
+
});
|
|
116190
116269
|
}
|
|
116191
|
-
}
|
|
116192
|
-
|
|
116193
|
-
|
|
116194
|
-
const prefixedPath = resolve22(
|
|
116195
|
-
installPath,
|
|
116196
|
-
"skills",
|
|
116197
|
-
`${action.plugin}-${action.entrySkill}`,
|
|
116198
|
-
"SKILL.md"
|
|
116199
|
-
);
|
|
116270
|
+
} else {
|
|
116271
|
+
let entrySkillPath = resolve22(installPath, "skills", action.entrySkill, "SKILL.md");
|
|
116272
|
+
let entrySkillFound = false;
|
|
116200
116273
|
try {
|
|
116201
|
-
const skillStat = await lstat37(
|
|
116274
|
+
const skillStat = await lstat37(entrySkillPath);
|
|
116202
116275
|
if (skillStat.isFile() && !skillStat.isSymbolicLink()) {
|
|
116203
|
-
entrySkillPath = prefixedPath;
|
|
116204
116276
|
entrySkillFound = true;
|
|
116205
116277
|
}
|
|
116206
116278
|
} catch {
|
|
116207
116279
|
}
|
|
116208
|
-
|
|
116209
|
-
|
|
116210
|
-
return createResult({
|
|
116211
|
-
actionType,
|
|
116212
|
-
status: ActionStatus.OBSERVED,
|
|
116213
|
-
observation: {
|
|
116214
|
-
installed: true,
|
|
116280
|
+
if (!entrySkillFound && action.plugin) {
|
|
116281
|
+
const prefixedPath = resolve22(
|
|
116215
116282
|
installPath,
|
|
116216
|
-
|
|
116217
|
-
|
|
116283
|
+
"skills",
|
|
116284
|
+
`${action.plugin}-${action.entrySkill}`,
|
|
116285
|
+
"SKILL.md"
|
|
116286
|
+
);
|
|
116287
|
+
try {
|
|
116288
|
+
const skillStat = await lstat37(prefixedPath);
|
|
116289
|
+
if (skillStat.isFile() && !skillStat.isSymbolicLink()) {
|
|
116290
|
+
entrySkillPath = prefixedPath;
|
|
116291
|
+
entrySkillFound = true;
|
|
116292
|
+
}
|
|
116293
|
+
} catch {
|
|
116218
116294
|
}
|
|
116219
|
-
}
|
|
116295
|
+
}
|
|
116296
|
+
if (!entrySkillFound) {
|
|
116297
|
+
return createResult({
|
|
116298
|
+
actionType,
|
|
116299
|
+
status: ActionStatus.OBSERVED,
|
|
116300
|
+
observation: {
|
|
116301
|
+
installed: true,
|
|
116302
|
+
installPath,
|
|
116303
|
+
entrySkillFound: false,
|
|
116304
|
+
error: `entry skill not found: skills/${action.entrySkill}/SKILL.md`
|
|
116305
|
+
}
|
|
116306
|
+
});
|
|
116307
|
+
}
|
|
116220
116308
|
}
|
|
116221
116309
|
let manifestDigest;
|
|
116222
116310
|
let manifestError = null;
|
|
@@ -116418,6 +116506,7 @@ var init_plugin_marketplace = __esm({
|
|
|
116418
116506
|
__name(normalizeKimiSkillsRel, "normalizeKimiSkillsRel");
|
|
116419
116507
|
__name(resolveKimiEntrySkillFile, "resolveKimiEntrySkillFile");
|
|
116420
116508
|
__name(normalizeCodeBuddySkillsRel, "normalizeCodeBuddySkillsRel");
|
|
116509
|
+
__name(resolveCodexEntrySkillFile, "resolveCodexEntrySkillFile");
|
|
116421
116510
|
__name(resolveCodeBuddyEntrySkillFile, "resolveCodeBuddyEntrySkillFile");
|
|
116422
116511
|
SUPPORTED_TYPES = [
|
|
116423
116512
|
ActionType.PLUGIN_MANIFEST_VALIDATE,
|
|
@@ -116458,6 +116547,14 @@ var init_plugin_marketplace = __esm({
|
|
|
116458
116547
|
});
|
|
116459
116548
|
|
|
116460
116549
|
// src/core/surface-host-bindings.mjs
|
|
116550
|
+
var surface_host_bindings_exports = {};
|
|
116551
|
+
__export(surface_host_bindings_exports, {
|
|
116552
|
+
deriveSurfaceHostBinding: () => deriveSurfaceHostBinding,
|
|
116553
|
+
groupSurfaceHostBindings: () => groupSurfaceHostBindings,
|
|
116554
|
+
normalizeGenericSkillsRel: () => normalizeGenericSkillsRel,
|
|
116555
|
+
normalizeSurfacePath: () => normalizeSurfacePath,
|
|
116556
|
+
pluginRootFromManifestRelativePath: () => pluginRootFromManifestRelativePath
|
|
116557
|
+
});
|
|
116461
116558
|
import { dirname as dirname10, isAbsolute as isAbsolute18, join as join19, normalize as normalize3, resolve as resolve23, sep as sep9 } from "node:path";
|
|
116462
116559
|
import { lstat as lstat38 } from "node:fs/promises";
|
|
116463
116560
|
function normalizeSurfacePath(rawPath) {
|
|
@@ -139649,7 +139746,7 @@ async function observeQoderPlugin(target, command2, env, run6) {
|
|
|
139649
139746
|
found
|
|
139650
139747
|
};
|
|
139651
139748
|
}
|
|
139652
|
-
async function readQoderManifest(root, label) {
|
|
139749
|
+
async function readQoderManifest(root, label, target) {
|
|
139653
139750
|
const candidates = [];
|
|
139654
139751
|
for (const manifestPath of [".qoder-plugin/plugin.json", ".claude-plugin/plugin.json"]) {
|
|
139655
139752
|
let text;
|
|
@@ -139663,10 +139760,11 @@ async function readQoderManifest(root, label) {
|
|
|
139663
139760
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
|
|
139664
139761
|
throw new Error(`${label} (${manifestPath}) did not return an object`);
|
|
139665
139762
|
}
|
|
139763
|
+
await assertQoderPluginManifest(target, manifest, `${label} (${manifestPath})`, root);
|
|
139666
139764
|
candidates.push({ manifestPath, manifest });
|
|
139667
139765
|
}
|
|
139668
139766
|
if (candidates.length === 0) throw new Error(`${label} has no native or compatible plugin manifest`);
|
|
139669
|
-
if (candidates.length === 2 && ["name", "version"
|
|
139767
|
+
if (candidates.length === 2 && ["name", "version"].some((field) => candidates[0].manifest[field] !== candidates[1].manifest[field])) {
|
|
139670
139768
|
throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path: conflicting native and compatible manifests`);
|
|
139671
139769
|
}
|
|
139672
139770
|
return candidates[0];
|
|
@@ -139687,26 +139785,43 @@ async function assertFrozenQoderManifest(target, root) {
|
|
|
139687
139785
|
snapshotPath: target.snapshotPath,
|
|
139688
139786
|
expectedDigest: target.manifestDigest
|
|
139689
139787
|
});
|
|
139690
|
-
const { manifestPath, manifest } = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest");
|
|
139788
|
+
const { manifestPath, manifest } = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest", target);
|
|
139691
139789
|
const skills = await assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest", snapshotRoot);
|
|
139692
139790
|
return { manifestPath, skills };
|
|
139693
139791
|
}
|
|
139694
139792
|
async function assertQoderHubEntry(target, marketplaceRoot) {
|
|
139695
|
-
|
|
139696
|
-
|
|
139697
|
-
|
|
139698
|
-
|
|
139699
|
-
|
|
139700
|
-
|
|
139701
|
-
|
|
139702
|
-
|
|
139703
|
-
|
|
139704
|
-
|
|
139705
|
-
|
|
139706
|
-
|
|
139707
|
-
|
|
139708
|
-
|
|
139793
|
+
let found = false;
|
|
139794
|
+
for (const indexPath of ["marketplace.json", ".claude-plugin/marketplace.json"]) {
|
|
139795
|
+
let text;
|
|
139796
|
+
try {
|
|
139797
|
+
text = await readFileContained(marketplaceRoot, indexPath, { encoding: "utf8" });
|
|
139798
|
+
} catch (error) {
|
|
139799
|
+
if (error?.code === "SFC2004" && error?.details?.kind === "missing-resource") continue;
|
|
139800
|
+
throw error;
|
|
139801
|
+
}
|
|
139802
|
+
found = true;
|
|
139803
|
+
const marketplace = parseJson2(text, `Qoder Hub marketplace manifest (${indexPath})`);
|
|
139804
|
+
if (!marketplace || typeof marketplace !== "object" || Array.isArray(marketplace) || marketplace.name !== target.marketplace || !Array.isArray(marketplace.plugins)) {
|
|
139805
|
+
throw new Error("Qoder Hub marketplace manifest does not match the frozen marketplace");
|
|
139806
|
+
}
|
|
139807
|
+
if (indexPath === ".claude-plugin/marketplace.json") {
|
|
139808
|
+
if (target.hub.githubHost !== "github.com" || typeof target.frozenTag !== "string" || target.frozenTag.length === 0) {
|
|
139809
|
+
throw new Error("Qoder compatible Hub entry requires a frozen GitHub tag identity");
|
|
139810
|
+
}
|
|
139811
|
+
await assertHubHostEntry({ ...target, host: "claude", pluginTag: target.frozenTag, githubHost: target.hub.githubHost }, marketplaceRoot);
|
|
139812
|
+
continue;
|
|
139813
|
+
}
|
|
139814
|
+
const matches = marketplace.plugins.filter((entry2) => entry2?.name === target.plugin);
|
|
139815
|
+
if (matches.length !== 1) {
|
|
139816
|
+
throw new Error(`Qoder Hub marketplace manifest must contain exactly one ${target.plugin} entry`);
|
|
139817
|
+
}
|
|
139818
|
+
const entry = matches[0];
|
|
139819
|
+
const source = entry.source;
|
|
139820
|
+
if (source?.source !== "url" || normalizeHubGitSource(source.url, target.hub.githubHost) !== target.pluginRepo || source.sha !== target.pluginCommit || entry.version !== void 0 && entry.version !== target.version || source.ref !== void 0 && (typeof target.frozenTag !== "string" || source.ref !== target.frozenTag)) {
|
|
139821
|
+
throw new Error("Qoder Hub entry does not match the frozen public source identity");
|
|
139822
|
+
}
|
|
139709
139823
|
}
|
|
139824
|
+
if (!found) throw new Error("Qoder Hub has no native or compatible marketplace manifest");
|
|
139710
139825
|
}
|
|
139711
139826
|
async function verifyQoderInstalledPayload({
|
|
139712
139827
|
target,
|
|
@@ -139715,7 +139830,7 @@ async function verifyQoderInstalledPayload({
|
|
|
139715
139830
|
frozenManifest,
|
|
139716
139831
|
verifyInstalledPayload
|
|
139717
139832
|
}) {
|
|
139718
|
-
const { manifestPath, manifest } = await readQoderManifest(installPath, "installed Qoder plugin manifest");
|
|
139833
|
+
const { manifestPath, manifest } = await readQoderManifest(installPath, "installed Qoder plugin manifest", target);
|
|
139719
139834
|
if (manifestPath !== frozenManifest.manifestPath) {
|
|
139720
139835
|
throw new Error("installed Qoder plugin manifest path differs from the frozen manifest selection");
|
|
139721
139836
|
}
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"digest": "86c9cab024ebe9c7f8ec3358fcc12d05b8ed246ab59da2b0acc6a517f31274ea",
|
|
18
18
|
"bytes": 2488
|
|
19
19
|
},
|
|
20
|
+
"evidence-event-v2.schema.json": {
|
|
21
|
+
"digest": "693430e636afc85bf4a79e3f7bf3fb87254cbd62f2e3f35c35d6f84e5e8e0be1",
|
|
22
|
+
"bytes": 6058
|
|
23
|
+
},
|
|
20
24
|
"evidence-event.schema.json": {
|
|
21
25
|
"digest": "b7e14522a5aba818cab191545f23d2323be0e4c80566e9d3e4da576103a00490",
|
|
22
26
|
"bytes": 2390
|
|
@@ -34,8 +38,8 @@
|
|
|
34
38
|
"bytes": 57111
|
|
35
39
|
},
|
|
36
40
|
"release-run.schema.json": {
|
|
37
|
-
"digest": "
|
|
38
|
-
"bytes":
|
|
41
|
+
"digest": "26c44ddf1ed42f266a2ddee7f6132cee94c59593e37f24359c9c48f12612ec22",
|
|
42
|
+
"bytes": 21874
|
|
39
43
|
},
|
|
40
44
|
"test-intake.schema.json": {
|
|
41
45
|
"digest": "654e91ce518cb2b8aca84947d0c3bb8c4262ab047d86081e7e93dc07a9c6c739",
|
|
@@ -72,9 +72,9 @@ node "${CLAUDE_PLUGIN_ROOT}/bin/release-skill-local-finish.mjs" \
|
|
|
72
72
|
- Claude/Codex 的 Hub 目标只使用已经登记的同源市场。升级前先读取声明的 Hub 分支,并核对宿主专用索引中的插件仓库、标签、提交及存在的版本字段。刷新市场后再次核对实际目录和条目,再执行原有更新或重装命令。Claude 精确当前安装会离线核对真实载荷;Codex 列表不提供安装根时,仍须正式重装,从安装输出取得 `installedPath` 后核对载荷。旧安装动作继续使用冻结市场引用预检;远端不可达或引用不符时返回 `MANUAL_REQUIRED`。每个宿主单独保留结果,失败不会中断其他已选宿主。
|
|
73
73
|
- Kimi 的精确当前安装会在返回 `ALREADY_CURRENT` 前核对真实载荷;发生安装或迁移时,只在操作完成后核对结果。配置根依次取显式 `kimiHome`、`KIMI_CODE_HOME`、用户主目录下的 `.kimi-code`,TUI 与安装后观察使用同一根。release-finish 当前只采用并验证 Kimi Code 的受控终端交互界面(TUI)路径,并把 TUI 工作目录固定为 `--root` 指定的当前发布项目。用户已确认冻结计划、显式选择更新且 `--hosts` 包含 `kimi` 时,流程读取完整的初始 `Trust this folder?` 对话框,要求其中只有一个正向项 `Trust this folder` 和一个选中项。正向项已经选中时不发送方向键,直接确认;已知拒绝项选中时,按它与正向项的相对位置移动一次,重新读取完整对话框并确认正向项已选中,然后才提交。插件命令发出后再次出现目录信任、界面或选中项未知、正向项缺失或重复、移动后无法确认、超时或提前退出时,该宿主失败并停止后续安装步骤。若后续 Kimi 版本出现新的可复现界面差异,先记录 Kimi 版本、可见选项、选中项及选项关系;这些事实足以唯一确认当前目录、正向信任项和选择结果时,在最近测试补回归与兼容并继续,目录身份或选项语义不明时仍停止并交回主会话。插件信任仍先清理 ANSI/OSC 控制序列和软换行,再分别核对冻结仓库与标签;只有选中 `Trust and install` 才提交并重新加载。包名、版本、发布标签、已安装修订号和受管安装根必须与冻结计划一致;`.git` 只提供附加诊断,不是通过条件。旧的本地路径安装会在同一 TUI 会话中先移除,再按发布标签安装。
|
|
74
74
|
- CodeBuddy/WorkBuddy 只升级既有安装,不自动首装。CodeBuddy 仅探测全局 `codebuddy`/`cbc`,配置根固定为有效 `HOME` 下的 `.codebuddy`;WorkBuddy 仅在 macOS 探测应用内嵌 CLI,配置根固定为有效 `HOME` 下的 `.workbuddy`,两者不互作回退。Hub 目标先核对各自 `plugins/marketplaces/<hub>` 的远端和分支,再核对 `.codebuddy-plugin/marketplace.json` 条目。刷新市场后确认远端分支未漂移,才更新插件;最后核对列表中的版本、`gitCommitSha` 和 `plugins/cache/<hub>/<plugin>/<version>` 的完整载荷。旧 bundled-family 目标继续要求插件标签和市场分支均指向冻结提交。非 macOS 的 WorkBuddy 返回 `SKIPPED_UNSUPPORTED_PLATFORM`。
|
|
75
|
-
- Qoder 首先通过 `qoder plugins marketplace list --json` 验证目标 Hub 的名称、仓库地址、分支信息及本机 checkout 状态,随后使用 `qoder plugins list --json` 核对唯一插件条目的市场归属、`scope=user`、版本号与 `installPath`。若目标市场或插件未安装,返回 `MANUAL_REQUIRED`,禁止自动添加市场或执行首次安装。对于旧版已安装情况,仅执行 `qoder plugins marketplace update <name>` 与 `qoder plugins update <plugin@marketplace> --scope user
|
|
75
|
+
- Qoder 首先通过 `qoder plugins marketplace list --json` 验证目标 Hub 的名称、仓库地址、分支信息及本机 checkout 状态,随后使用 `qoder plugins list --json` 核对唯一插件条目的市场归属、`scope=user`、版本号与 `installPath`。若目标市场或插件未安装,返回 `MANUAL_REQUIRED`,禁止自动添加市场或执行首次安装。对于旧版已安装情况,仅执行 `qoder plugins marketplace update <name>` 与 `qoder plugins update <plugin@marketplace> --scope user`。在市场刷新后、插件更新前,必须完成以下来源核验。在已核对的市场安装根内,分别读取 `marketplace.json` 的 `url` 来源与 `.claude-plugin/marketplace.json` 的 `github` 来源;至少一个存在,且所有存在候选都须有效并绑定同一冻结目标。根目录来源核对 `source.url/source.sha`;兼容来源沿现有 Claude 断言核对仓库、冻结标签、提交和版本。任一损坏或冲突均拒绝,不猜测优先级。
|
|
76
76
|
|
|
77
|
-
冻结快照与真实 `installPath` 均需比对 `.qoder-plugin/plugin.json` 与 `.claude-plugin/plugin.json`
|
|
77
|
+
冻结快照与真实 `installPath` 均需比对 `.qoder-plugin/plugin.json` 与 `.claude-plugin/plugin.json` 两个候选清单。仅当原生清单缺失时,方可启用兼容清单;原生清单存在但无效时不得回退。存在的清单均须可解析为有效对象,且以原生清单为优先。每个已存在候选(包括未选候选)都须核对目标 `name/version`;其 `skills` 必须为非空字符串,经 `Foundation 0.25.0` 的 `resolveContained` 解析为根内真实目录。跨候选只比较 `name/version`,允许各自合法 `skills` 不同;原生正常不能遮蔽兼容无效。安装侧选择的相对清单路径及 `skills` 必须与冻结侧选择一致。安装侧额外出现的损坏或冲突清单不得忽略;允许宿主附加文件的 `external-marketplace-v1` 载荷完整比较,不可替代对清单的独立核验。
|
|
78
78
|
|
|
79
79
|
冻结快照摘要须在宿主写入前完成复验,安装后仍需复验完整声明载荷与冻结来源;即使版本已为目标版本,也必须完成全部复验后方可返回 `ALREADY_CURRENT`。市场在检查与更新之间可能发生变更,若事后身份校验失败,报告错误,不进行自动降级、卸载或覆盖。
|
|
80
80
|
|
|
@@ -29,7 +29,7 @@ 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.
|
|
32
|
+
## 0.9.36 能力与证据边界
|
|
33
33
|
|
|
34
34
|
四类工程材料接到现有 `release-project` 字段。公开正式材料写入 `publicFiles`(`sourceScope` / `from` / `to` / `mode`)。运行必需资源写入 `requiredPublicFiles`,必须被同一单元 `publicFiles[].to` 精确覆盖。私有正式材料与非正式运行材料不列入 `publicFiles`,需要挡住时使用 `forbiddenPaths` / `forbiddenContentPatterns`。正式不等于公开。是否进入公开快照由 `publicFiles` 是否列出决定。npm 是载荷渠道。`package.json` 的 `files` 与入口闭包和公开映射同时约束。`delivery.include` / `delivery.exclude` 只选择宿主,不是文件包含或排除。排除不得拿掉运行必需资源。互相冲突的配置必须失败关闭。
|
|
35
35
|
|