release-skill 0.9.35 → 0.9.37
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 +45 -0
- package/INSTALL.md +2 -2
- package/INSTALL.zh-CN.md +2 -2
- package/README.md +24 -9
- package/README.zh-CN.md +15 -9
- package/adapters/claude/.claude-plugin/plugin.json +1 -1
- package/adapters/claude/bin/release-skill.bundle.mjs +270 -58
- package/adapters/claude/schemas/.render-manifest.json +6 -2
- package/adapters/claude/skills/release-config/SKILL.md +36 -41
- package/adapters/claude/skills/release-docs/SKILL.md +38 -35
- package/adapters/claude/skills/release-finish/SKILL.md +2 -2
- package/adapters/claude/skills/release-help/SKILL.md +51 -41
- package/adapters/claude/skills/release-marketplace/SKILL.md +38 -46
- package/adapters/claude/skills/release-prepare/SKILL.md +19 -28
- package/adapters/claude/skills/release-publish/SKILL.md +29 -45
- package/adapters/codex/.codex-plugin/plugin.json +2 -2
- package/adapters/codex/bin/release-skill.bundle.mjs +270 -58
- package/adapters/codex/schemas/.render-manifest.json +6 -2
- package/adapters/codex/skills/release-config/SKILL.md +36 -41
- package/adapters/codex/skills/release-docs/SKILL.md +38 -35
- package/adapters/codex/skills/release-finish/SKILL.md +2 -2
- package/adapters/codex/skills/release-help/SKILL.md +51 -41
- package/adapters/codex/skills/release-marketplace/SKILL.md +38 -46
- package/adapters/codex/skills/release-prepare/SKILL.md +19 -28
- package/adapters/codex/skills/release-publish/SKILL.md +29 -45
- package/adapters/cursor/.cursor-plugin/plugin.json +1 -1
- package/adapters/cursor/bin/release-skill.bundle.mjs +270 -58
- package/adapters/cursor/schemas/.render-manifest.json +6 -2
- package/adapters/cursor/skills/release-config/SKILL.md +36 -41
- package/adapters/cursor/skills/release-docs/SKILL.md +38 -35
- package/adapters/cursor/skills/release-finish/SKILL.md +2 -2
- package/adapters/cursor/skills/release-help/SKILL.md +51 -41
- package/adapters/cursor/skills/release-marketplace/SKILL.md +38 -46
- package/adapters/cursor/skills/release-prepare/SKILL.md +19 -28
- package/adapters/cursor/skills/release-publish/SKILL.md +29 -45
- package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
- package/adapters/kimi/bin/release-skill.bundle.mjs +270 -58
- package/adapters/kimi/schemas/.render-manifest.json +6 -2
- package/adapters/kimi/skills/release-config/SKILL.md +36 -41
- package/adapters/kimi/skills/release-docs/SKILL.md +38 -35
- package/adapters/kimi/skills/release-finish/SKILL.md +2 -2
- package/adapters/kimi/skills/release-help/SKILL.md +51 -41
- package/adapters/kimi/skills/release-marketplace/SKILL.md +38 -46
- package/adapters/kimi/skills/release-prepare/SKILL.md +19 -28
- package/adapters/kimi/skills/release-publish/SKILL.md +29 -45
- package/adapters/qoder/.qoder-plugin/plugin.json +1 -1
- package/adapters/qoder/bin/release-skill.bundle.mjs +270 -58
- package/adapters/qoder/schemas/.render-manifest.json +6 -2
- package/adapters/qoder/skills/release-config/SKILL.md +36 -41
- package/adapters/qoder/skills/release-docs/SKILL.md +38 -35
- package/adapters/qoder/skills/release-finish/SKILL.md +2 -2
- package/adapters/qoder/skills/release-help/SKILL.md +51 -41
- package/adapters/qoder/skills/release-marketplace/SKILL.md +38 -46
- package/adapters/qoder/skills/release-prepare/SKILL.md +19 -28
- package/adapters/qoder/skills/release-publish/SKILL.md +29 -45
- package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
- package/adapters/workbuddy/bin/release-skill.bundle.mjs +270 -58
- package/adapters/workbuddy/schemas/.render-manifest.json +6 -2
- package/adapters/workbuddy/skills/release-config/SKILL.md +36 -41
- package/adapters/workbuddy/skills/release-docs/SKILL.md +38 -35
- package/adapters/workbuddy/skills/release-finish/SKILL.md +2 -2
- package/adapters/workbuddy/skills/release-help/SKILL.md +51 -41
- package/adapters/workbuddy/skills/release-marketplace/SKILL.md +38 -46
- package/adapters/workbuddy/skills/release-prepare/SKILL.md +19 -28
- package/adapters/workbuddy/skills/release-publish/SKILL.md +29 -45
- package/bin/release-skill.bundle.mjs +270 -58
- package/package.json +1 -1
- package/platform-manifest.json +4 -4
- package/references/.render-manifest.json +2 -2
- package/references/02-project-config.md +91 -8
- package/schemas/.render-manifest.json +6 -2
- package/skills/release-config/SKILL.md +36 -41
- package/skills/release-docs/SKILL.md +38 -35
- package/skills/release-finish/SKILL.md +2 -2
- package/skills/release-help/SKILL.md +51 -41
- package/skills/release-marketplace/SKILL.md +38 -46
- package/skills/release-prepare/SKILL.md +19 -28
- package/skills/release-publish/SKILL.md +29 -45
- package/skills-src/release-config/SKILL.md +36 -41
- package/skills-src/release-docs/SKILL.md +38 -35
- package/skills-src/release-finish/SKILL.md +2 -2
- package/skills-src/release-help/SKILL.md +51 -41
- package/skills-src/release-marketplace/SKILL.md +38 -46
- package/skills-src/release-prepare/SKILL.md +19 -28
- package/skills-src/release-publish/SKILL.md +29 -45
- package/src/adapters/plugin-marketplace.mjs +152 -43
- package/src/commands/post-release-local.mjs +41 -22
- package/src/commands/verify.mjs +123 -17
- package/src/core/skill-resource-closure.mjs +1 -1
|
@@ -15,55 +15,44 @@ description: "从已批准的生产计划发布冻结 Git branch/tag、npm tarba
|
|
|
15
15
|
|
|
16
16
|
## 生产边界
|
|
17
17
|
|
|
18
|
-
冻结 Git branch/tag、GitHub Release、npm tarball 路径已通过本地生产等价沙箱(协议级 fake
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
不得把沙箱通过描述成真实发布成功。
|
|
22
|
-
|
|
23
|
-
只发布 `prepare --production` 封存的 Git object 和 npm tarball,不从活动工作区重新
|
|
24
|
-
打包,不生成或覆盖 README,也永不隐式刷新工作树中的发布文档;
|
|
25
|
-
遇到 `RELEASE_DOCS_STALE` 或文档陈旧只能回到 `docs refresh` → 人工审阅 → 提交 →
|
|
26
|
-
重新 prepare。远端 branch/tag/Release/npm version 已存在、查询不确定、
|
|
27
|
-
认证失败或摘要漂移时,在全局预检阶段停止并交给人工。禁止覆盖、删除和自动回滚;
|
|
28
|
-
新建 ref 的 create-only CAS(`--force-with-lease=<ref>:`)只断言目标不存在,不授权覆盖。
|
|
18
|
+
冻结 Git branch/tag、GitHub Release、npm tarball 路径已通过本地生产等价沙箱(协议级 fake)验证,测试未提供 OS 级网络隔离。插件市场消费者安装验证通过本地协议沙箱完成;真实生产 canary 仅在用户明确授权目标后执行。不得将沙箱结果描述为真实发布成功。
|
|
19
|
+
|
|
20
|
+
仅发布 `prepare --production` 封存的 Git object 和 npm tarball,不从活动工作区重新打包,不生成或覆盖 README,也永不隐式刷新工作树中的发布文档。遇到 `RELEASE_DOCS_STALE` 或文档陈旧时,必须返回 `docs refresh` → 人工审阅 → 提交 → 重新 `prepare`。远端 branch/tag/Release/npm version 已存在、查询不确定、认证失败或摘要漂移时,在全局预检阶段停止并交由人工介入。禁止覆盖、删除和自动回滚;新建 ref 的 `create-only CAS`(`--force-with-lease=<ref>:`)仅断言目标不存在,不授权覆盖。
|
|
29
21
|
|
|
30
22
|
## 前置条件:工作流选择
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
`release-publish` 直接执行自身的计划、批准、冻结制品身份和远端预检。`route` 只提供
|
|
34
|
-
工作流建议,不是已批准 production plan 的授权门。
|
|
24
|
+
当调用方持有合法、未过期且绑定当前 production plan 的 approval record 时,`release-publish` 直接执行自身的计划、批准、冻结制品身份和远端预检。`route` 仅提供工作流建议,非已批准 production plan 的授权门。
|
|
35
25
|
|
|
36
|
-
|
|
37
|
-
已知目标版本时一并传入 `--target-version <version>`,使恢复建议只读取与该目标绑定的
|
|
38
|
-
完整运行血缘。未传目标时,route 仍按 diff/baseline 选择工作流;历史 diagnostics 只作
|
|
39
|
-
报告,不得覆盖当前建议。
|
|
26
|
+
尚未形成计划时,可先使用 `release-skill route --root <path> --json` 确定变更类型。已知目标版本时一并传入 `--target-version <version>`,使恢复建议仅读取与该目标绑定的完整运行血缘。未传目标时,`route` 仍按 diff/baseline 选择工作流;历史 diagnostics 仅作报告,不得覆盖当前建议。
|
|
40
27
|
|
|
41
28
|
根据推荐的 `workflowKind` 选择对应路径:
|
|
42
29
|
|
|
43
|
-
- `docs-only` → 先执行 `release-docs` 完整流程
|
|
44
|
-
- `config-only` → 先执行 `release-config`,仅在 public surface 变化时进入 publish
|
|
45
|
-
- `marketplace-only` → 先执行 `release-marketplace`,然后由 workspace exclusive skill 接管
|
|
46
|
-
- `full-happy-end` → 直接进入标准完整流程:`prepare → approve → publish → verify`
|
|
47
|
-
- `reconcile` → 先执行 `release-reconcile` 恢复 PARTIAL 状态
|
|
48
|
-
- `help` → 无变更,无需 publish
|
|
30
|
+
- `docs-only` → 先执行 `release-docs` 完整流程
|
|
31
|
+
- `config-only` → 先执行 `release-config`,仅在 public surface 变化时进入 publish
|
|
32
|
+
- `marketplace-only` → 先执行 `release-marketplace`,然后由 workspace exclusive skill 接管
|
|
33
|
+
- `full-happy-end` → 直接进入标准完整流程:`prepare → approve → publish → verify`
|
|
34
|
+
- `reconcile` → 先执行 `release-reconcile` 恢复 PARTIAL 状态
|
|
35
|
+
- `help` → 无变更,无需 publish
|
|
36
|
+
|
|
37
|
+
> **注意**:`release-publish` 是标准工作流中的第⑦步,必须在以下步骤之后执行:
|
|
38
|
+
> - 步骤⑤:`release-prepare`(或轻量级 prepare)
|
|
39
|
+
> - 步骤⑥:`release-approve`(非过期 approval record)
|
|
49
40
|
|
|
50
|
-
|
|
51
|
-
- 步骤⑤: `release-prepare` (或轻量级 prepare)
|
|
52
|
-
- 步骤⑥: `release-approve` (非过期 approval record)
|
|
41
|
+
接收已有冻结计划时沿原合同执行,不回头追加接入义务。仅当本入口转入新一轮生产准备时,才按 `release-prepare` 同一完整流程核对 `testIntake`:若缺失,则说明缺项并默认推动 `skill-family-test:skill-family-test-plan`,再在授权范围内调用 `skill-family-test:skill-family-test-run`,由 TEST 组织检查并交回结果。跳过须先明确征询,再依据本轮适用且范围匹配的明确同意决定。沉默、拒绝、仅普通发布预授权、旧轮次、其他项目、版本或范围不匹配均不可跳过。本轮匹配答复可复用。不得把跳过写成测试已达标,也不得用跳过清除已声明的适用要求。只读、非生产准备不新增接入义务。直接非交互 CLI 仍接受可选 `testIntake`,不新增选择参数。答复与适用范围记入既有任务或执行计划。未完成接入且无有效跳过时,不进入新一轮正式 prepare。
|
|
53
42
|
|
|
54
43
|
决策表链接:参见 [`release-help`](../release-help/SKILL.md) 的 Routing Suggestions 章节。
|
|
55
44
|
|
|
56
45
|
## 触发
|
|
57
46
|
|
|
58
|
-
|
|
47
|
+
用户明确要求执行已人工审阅的 GitHub + npm 生产计划。
|
|
59
48
|
|
|
60
49
|
## 授权门
|
|
61
50
|
|
|
62
|
-
1. 读取本次批准所绑定的不可变计划,按其中实际存在的 `units`、`externalActions`、`waivers` 和 `postPublish` 整理并展示人可读批准摘要。版本、公开仓库、分支策略、branch/tag、npm 与 GitHub Release 目标、全部 actions、例外,以及需要独立 checkpoint 批准的 postPublish hook
|
|
63
|
-
2. 必须存在未过期且由系统绑定同一内部 digest 的 approval record;批准后不再要求用户复制摘要做二次确认。
|
|
64
|
-
3. 只有 CLI exit code 0 且结构化状态为 `PUBLISHED` 才算外写阶段通过;随后必须运行 verify
|
|
51
|
+
1. 读取本次批准所绑定的不可变计划,按其中实际存在的 `units`、`externalActions`、`waivers` 和 `postPublish` 整理并展示人可读批准摘要。版本、公开仓库、分支策略、branch/tag、npm 与 GitHub Release 目标、全部 actions、例外,以及需要独立 checkpoint 批准的 postPublish hook,仅展示计划中已写入的值;未出现字段保持缺失,不猜测。
|
|
52
|
+
2. 必须存在未过期且由系统绑定同一内部 digest 的 approval record;批准后不再要求用户复制摘要做二次确认。
|
|
53
|
+
3. 只有 CLI exit code 0 且结构化状态为 `PUBLISHED` 才算外写阶段通过;随后必须运行 `release-verify`,只有 `VERIFIED` 才是完整终态。
|
|
65
54
|
|
|
66
|
-
冻结计划批准是正常发布级流程的唯一批准门。它包含计划内的外部动作和验证门禁,不包含有效 `requiresApproval: true` 的 postPublish checkpoint
|
|
55
|
+
冻结计划批准是正常发布级流程的唯一批准门。它包含计划内的外部动作和验证门禁,不包含有效 `requiresApproval: true` 的 postPublish checkpoint。此类 hook 仍须使用绑定 `(planDigest, hookId)` 且最长有效 24 小时的独立批准记录。
|
|
67
56
|
|
|
68
57
|
## 确定性执行
|
|
69
58
|
|
|
@@ -72,27 +61,22 @@ node "$RELEASE_SKILL_ENTRY" publish --root <path> --plan <plan-path> \
|
|
|
72
61
|
--approval <approval-path> --json
|
|
73
62
|
```
|
|
74
63
|
|
|
75
|
-
执行顺序:全局只读预检 → 配置的公开分支(按三种 `branchStrategy` 执行)→
|
|
76
|
-
单独切换默认分支 → tag → npm tarball →
|
|
77
|
-
GitHub Release → Claude/Codex marketplace 隔离安装。每步 execute 后立即 observe;
|
|
78
|
-
默认分支 action 同时绑定名称和目标精确 commit;末尾再次核对分支/默认分支一致性。
|
|
79
|
-
失败停止后续动作并记录 PARTIAL。PUBLISHED 后运行 verify 复核全新消费者安装。
|
|
64
|
+
执行顺序:全局只读预检 → 配置的公开分支(按三种 `branchStrategy` 执行)→ 必要时单独切换默认分支 → tag → npm tarball → GitHub Release → Claude/Codex marketplace 隔离安装。每步 execute 后立即 observe;默认分支 action 同时绑定名称和目标精确 commit;末尾再次核对分支/默认分支一致性。失败停止后续动作并记录 `PARTIAL`。`PUBLISHED` 后运行 `verify` 复核全新消费者安装。
|
|
80
65
|
|
|
81
66
|
## 故障路由
|
|
82
67
|
|
|
83
68
|
| 结果 | 处理 |
|
|
84
|
-
|
|
85
|
-
| `BASELINE_CHANGED` | 保留人工修改,重新 prepare
|
|
86
|
-
| 摘要/制品不匹配 | 停止;重新 prepare
|
|
87
|
-
| 远端对象已存在 |
|
|
88
|
-
| 认证/网络/未知查询错误 | 失败关闭,修复环境后基于同一证据判断是否 reconcile
|
|
69
|
+
|------|------|
|
|
70
|
+
| `BASELINE_CHANGED` | 保留人工修改,重新 `prepare`、审阅和 `approve`;不得覆盖修改。 |
|
|
71
|
+
| 摘要/制品不匹配 | 停止;重新 `prepare`,不修补冻结目录。 |
|
|
72
|
+
| 远端对象已存在 | 人工判断版本或远端状态;不得覆盖。`create-only CAS` 也必须失败关闭。 |
|
|
73
|
+
| 认证/网络/未知查询错误 | 失败关闭,修复环境后基于同一证据判断是否 `reconcile`。 |
|
|
89
74
|
| `PARTIAL` | 检查 `release-run.json`,不重跑整套发布、不删除成功对象。 |
|
|
90
75
|
|
|
91
|
-
发布成功后必须运行 `release-verify
|
|
92
|
-
`release-reconcile`。
|
|
76
|
+
发布成功后必须运行 `release-verify`;`PARTIAL` 仅在人工确认远端状态后进入 `release-reconcile`。
|
|
93
77
|
|
|
94
78
|
## 人类最终回复
|
|
95
79
|
|
|
96
80
|
纯问询或转交时短答:写明实际回答、适用范围或理由、必要限制和下一步。建议保持为建议。
|
|
97
81
|
|
|
98
|
-
执行路径说明本轮实际阶段、范围、退出码和结构化结果,引用已批准计划、approval 与 run 产物位置。保留预检阻断、`PARTIAL` 和人工后续。仅当退出码为 0 且状态为 `PUBLISHED` 时,把外写阶段写为已发布;随后仍须 `release-verify`。`PUBLISHED`、本机更新与 `VERIFIED` 按各自既有通过条件分别报告。已有 run 文件按原合同呈现。栏目只收录当前命令已经返回的事实。
|
|
82
|
+
执行路径说明本轮实际阶段、范围、退出码和结构化结果,引用已批准计划、approval 与 run 产物位置。保留预检阻断、`PARTIAL` 和人工后续。仅当退出码为 0 且状态为 `PUBLISHED` 时,把外写阶段写为已发布;随后仍须 `release-verify`。`PUBLISHED`、本机更新与 `VERIFIED` 按各自既有通过条件分别报告。已有 run 文件按原合同呈现。栏目只收录当前命令已经返回的事实。
|
|
@@ -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.37"});
|
|
13
13
|
// Build-time source digest for the BUNDLE_STALE freshness gate (see above).
|
|
14
|
-
const __bundleSourceDigest = "
|
|
14
|
+
const __bundleSourceDigest = "6eb7b6560da84252426dc5cfc81297a3d5d6d6101aecb1a8fbf3f35402892715";
|
|
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) {
|
|
@@ -116586,6 +116683,49 @@ import { dirname as dirname11, join as join20, relative as relative18, isAbsolut
|
|
|
116586
116683
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
116587
116684
|
import { execFile as execFileCb7 } from "node:child_process";
|
|
116588
116685
|
import { promisify as promisify7 } from "node:util";
|
|
116686
|
+
function transportIdentityEntries(entries) {
|
|
116687
|
+
return entries.map(({ path: path43, type, mode, size, contentDigest }) => ({
|
|
116688
|
+
path: path43,
|
|
116689
|
+
type,
|
|
116690
|
+
mode: mode & ~WRITE_BITS,
|
|
116691
|
+
size,
|
|
116692
|
+
contentDigest
|
|
116693
|
+
}));
|
|
116694
|
+
}
|
|
116695
|
+
function compareInstallToFrozenTransport(frozenEntries, installedEntries) {
|
|
116696
|
+
const frozen = transportIdentityEntries(frozenEntries);
|
|
116697
|
+
const installed = transportIdentityEntries(installedEntries);
|
|
116698
|
+
const installedByPath = new Map(installed.map((entry) => [entry.path, entry]));
|
|
116699
|
+
const conflicts = [];
|
|
116700
|
+
for (const frozenEntry of frozen) {
|
|
116701
|
+
const installedEntry = installedByPath.get(frozenEntry.path);
|
|
116702
|
+
if (!installedEntry) {
|
|
116703
|
+
conflicts.push(`missing: ${frozenEntry.path}`);
|
|
116704
|
+
continue;
|
|
116705
|
+
}
|
|
116706
|
+
if (installedEntry.type !== frozenEntry.type) {
|
|
116707
|
+
conflicts.push(`type mismatch: ${frozenEntry.path}`);
|
|
116708
|
+
} else if (installedEntry.size !== frozenEntry.size || installedEntry.contentDigest !== frozenEntry.contentDigest) {
|
|
116709
|
+
conflicts.push(`content mismatch: ${frozenEntry.path}`);
|
|
116710
|
+
} else if (installedEntry.mode !== frozenEntry.mode) {
|
|
116711
|
+
conflicts.push(`mode mismatch: ${frozenEntry.path}`);
|
|
116712
|
+
}
|
|
116713
|
+
}
|
|
116714
|
+
const frozenPaths = new Set(frozen.map((entry) => entry.path));
|
|
116715
|
+
for (const installedEntry of installed) {
|
|
116716
|
+
if (!frozenPaths.has(installedEntry.path)) {
|
|
116717
|
+
conflicts.push(`extra: ${installedEntry.path}`);
|
|
116718
|
+
}
|
|
116719
|
+
}
|
|
116720
|
+
return conflicts;
|
|
116721
|
+
}
|
|
116722
|
+
function frozenSnapshotRelativePath(unit, actions, unitId) {
|
|
116723
|
+
if (typeof unit?.frozenSnapshot?.path === "string" && unit.frozenSnapshot.path.length > 0) {
|
|
116724
|
+
return unit.frozenSnapshot.path;
|
|
116725
|
+
}
|
|
116726
|
+
const action = (actions ?? []).find((item) => item.unitId === unitId && typeof item.parameters?.snapshotPath === "string" && item.parameters.snapshotPath.length > 0);
|
|
116727
|
+
return action?.parameters?.snapshotPath ?? null;
|
|
116728
|
+
}
|
|
116589
116729
|
async function verifyCursorHostDistributions({
|
|
116590
116730
|
plan,
|
|
116591
116731
|
root,
|
|
@@ -118161,16 +118301,65 @@ async function verifyRelease(options) {
|
|
|
118161
118301
|
}
|
|
118162
118302
|
const pluginDistCount = (surface.unit?.distributions ?? []).filter((d) => d.type !== "npm").length;
|
|
118163
118303
|
if (pluginDistCount === 1 && surface.frozenPluginRoot === ".") {
|
|
118164
|
-
const
|
|
118165
|
-
|
|
118166
|
-
|
|
118167
|
-
|
|
118168
|
-
|
|
118169
|
-
|
|
118170
|
-
|
|
118171
|
-
|
|
118172
|
-
|
|
118173
|
-
|
|
118304
|
+
const frozenRel = frozenSnapshotRelativePath(surface.unit, actions, surface.unitId);
|
|
118305
|
+
if (frozenRel) {
|
|
118306
|
+
const frozenDir = await resolveFrozenPath(root, frozenRel, "frozen snapshot path");
|
|
118307
|
+
const frozenClosure = await checkSkillResourceClosure({
|
|
118308
|
+
snapshotDir: frozenDir,
|
|
118309
|
+
host: surface.host,
|
|
118310
|
+
surfaceHostBindings: [{ surfaceId: surface.surfaceId, host: surface.host }]
|
|
118311
|
+
});
|
|
118312
|
+
const frozenReceipt = createSkillResourceClosureReceipt(frozenClosure, {
|
|
118313
|
+
unitId: surface.unitId,
|
|
118314
|
+
preparedAt: expectedUnitReceipt.preparedAt ?? null,
|
|
118315
|
+
exitCode: expectedUnitReceipt.exitCode ?? 0
|
|
118316
|
+
});
|
|
118317
|
+
assertSkillResourceClosureReceipt(
|
|
118318
|
+
expectedUnitReceipt,
|
|
118319
|
+
frozenReceipt,
|
|
118320
|
+
`unit "${surface.unitId}"`
|
|
118321
|
+
);
|
|
118322
|
+
const frozenSnap = await computeFrozenSnapshot(frozenDir, {
|
|
118323
|
+
excludeRootEntries: TRANSPORT_EXCLUSIONS
|
|
118324
|
+
});
|
|
118325
|
+
const installedSnap = await computeFrozenSnapshot(surface.installPath, {
|
|
118326
|
+
excludeRootEntries: TRANSPORT_EXCLUSIONS
|
|
118327
|
+
});
|
|
118328
|
+
const conflicts = compareInstallToFrozenTransport(
|
|
118329
|
+
frozenSnap.entries,
|
|
118330
|
+
installedSnap.entries
|
|
118331
|
+
);
|
|
118332
|
+
await evidence.append({
|
|
118333
|
+
phase: "verify",
|
|
118334
|
+
step: "skill-resource-closure",
|
|
118335
|
+
status: "install-comparison",
|
|
118336
|
+
unitId: surface.unitId,
|
|
118337
|
+
frozenInputDigest: frozenSnap.digest,
|
|
118338
|
+
installedInputDigest: installedSnap.digest,
|
|
118339
|
+
frozenModes: frozenSnap.entries.map((entry) => ({ path: entry.path, mode: entry.mode })),
|
|
118340
|
+
installedModes: installedSnap.entries.map((entry) => ({ path: entry.path, mode: entry.mode }))
|
|
118341
|
+
});
|
|
118342
|
+
if (conflicts.length > 0) {
|
|
118343
|
+
const listed = conflicts.slice(0, PAYLOAD_CONFLICT_REPORT_CAP2).join("; ");
|
|
118344
|
+
const overflow = conflicts.length > PAYLOAD_CONFLICT_REPORT_CAP2 ? `; and ${conflicts.length - PAYLOAD_CONFLICT_REPORT_CAP2} more conflicting path(s)` : "";
|
|
118345
|
+
throw new ReleaseError(
|
|
118346
|
+
POST_PUBLISH_VERIFY_FAILED,
|
|
118347
|
+
`installed plugin root differs in path, bytes, size, or non-write mode bits for unit "${surface.unitId}": ${listed}${overflow}`,
|
|
118348
|
+
{ unitId: surface.unitId, conflicts }
|
|
118349
|
+
);
|
|
118350
|
+
}
|
|
118351
|
+
} else {
|
|
118352
|
+
const observedReceipt = createSkillResourceClosureReceipt(closureResult, {
|
|
118353
|
+
unitId: surface.unitId,
|
|
118354
|
+
preparedAt: expectedUnitReceipt.preparedAt ?? null,
|
|
118355
|
+
exitCode: expectedUnitReceipt.exitCode ?? 0
|
|
118356
|
+
});
|
|
118357
|
+
assertSkillResourceClosureReceipt(
|
|
118358
|
+
expectedUnitReceipt,
|
|
118359
|
+
observedReceipt,
|
|
118360
|
+
`unit "${surface.unitId}"`
|
|
118361
|
+
);
|
|
118362
|
+
}
|
|
118174
118363
|
}
|
|
118175
118364
|
}
|
|
118176
118365
|
skillResourceClosureReceipts.push(createSkillResourceClosureReceipt(
|
|
@@ -118381,7 +118570,7 @@ async function verifyRelease(options) {
|
|
|
118381
118570
|
throw err;
|
|
118382
118571
|
}
|
|
118383
118572
|
}
|
|
118384
|
-
var execFile6, VERIFICATION_RESOLVED_TYPES, ADAPTER_ACTION_TYPE_MAP2, FIRST_RELEASE_BOOTSTRAP_MODE, EXTERNAL_MARKETPLACE_SHA_RE2, defaultNpmExecutor;
|
|
118573
|
+
var execFile6, VERIFICATION_RESOLVED_TYPES, WRITE_BITS, PAYLOAD_CONFLICT_REPORT_CAP2, ADAPTER_ACTION_TYPE_MAP2, FIRST_RELEASE_BOOTSTRAP_MODE, EXTERNAL_MARKETPLACE_SHA_RE2, defaultNpmExecutor;
|
|
118385
118574
|
var init_verify = __esm({
|
|
118386
118575
|
async "src/commands/verify.mjs"() {
|
|
118387
118576
|
init_src2();
|
|
@@ -118419,6 +118608,11 @@ var init_verify = __esm({
|
|
|
118419
118608
|
PASSED_MANUAL: "PASSED_MANUAL",
|
|
118420
118609
|
NOT_REQUIRED_UNCHANGED: "NOT_REQUIRED_UNCHANGED"
|
|
118421
118610
|
});
|
|
118611
|
+
WRITE_BITS = 146;
|
|
118612
|
+
PAYLOAD_CONFLICT_REPORT_CAP2 = 10;
|
|
118613
|
+
__name(transportIdentityEntries, "transportIdentityEntries");
|
|
118614
|
+
__name(compareInstallToFrozenTransport, "compareInstallToFrozenTransport");
|
|
118615
|
+
__name(frozenSnapshotRelativePath, "frozenSnapshotRelativePath");
|
|
118422
118616
|
__name(verifyCursorHostDistributions, "verifyCursorHostDistributions");
|
|
118423
118617
|
__name(verifyPublicSourceAuthorityReceiptOffline, "verifyPublicSourceAuthorityReceiptOffline");
|
|
118424
118618
|
ADAPTER_ACTION_TYPE_MAP2 = {
|
|
@@ -139649,7 +139843,7 @@ async function observeQoderPlugin(target, command2, env, run6) {
|
|
|
139649
139843
|
found
|
|
139650
139844
|
};
|
|
139651
139845
|
}
|
|
139652
|
-
async function readQoderManifest(root, label) {
|
|
139846
|
+
async function readQoderManifest(root, label, target) {
|
|
139653
139847
|
const candidates = [];
|
|
139654
139848
|
for (const manifestPath of [".qoder-plugin/plugin.json", ".claude-plugin/plugin.json"]) {
|
|
139655
139849
|
let text;
|
|
@@ -139663,10 +139857,11 @@ async function readQoderManifest(root, label) {
|
|
|
139663
139857
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
|
|
139664
139858
|
throw new Error(`${label} (${manifestPath}) did not return an object`);
|
|
139665
139859
|
}
|
|
139860
|
+
await assertQoderPluginManifest(target, manifest, `${label} (${manifestPath})`, root);
|
|
139666
139861
|
candidates.push({ manifestPath, manifest });
|
|
139667
139862
|
}
|
|
139668
139863
|
if (candidates.length === 0) throw new Error(`${label} has no native or compatible plugin manifest`);
|
|
139669
|
-
if (candidates.length === 2 && ["name", "version"
|
|
139864
|
+
if (candidates.length === 2 && ["name", "version"].some((field) => candidates[0].manifest[field] !== candidates[1].manifest[field])) {
|
|
139670
139865
|
throw new Error(`${label} does not match the frozen Qoder plugin identity and projection path: conflicting native and compatible manifests`);
|
|
139671
139866
|
}
|
|
139672
139867
|
return candidates[0];
|
|
@@ -139687,26 +139882,43 @@ async function assertFrozenQoderManifest(target, root) {
|
|
|
139687
139882
|
snapshotPath: target.snapshotPath,
|
|
139688
139883
|
expectedDigest: target.manifestDigest
|
|
139689
139884
|
});
|
|
139690
|
-
const { manifestPath, manifest } = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest");
|
|
139885
|
+
const { manifestPath, manifest } = await readQoderManifest(snapshotRoot, "frozen Qoder plugin manifest", target);
|
|
139691
139886
|
const skills = await assertQoderPluginManifest(target, manifest, "frozen Qoder plugin manifest", snapshotRoot);
|
|
139692
139887
|
return { manifestPath, skills };
|
|
139693
139888
|
}
|
|
139694
139889
|
async function assertQoderHubEntry(target, marketplaceRoot) {
|
|
139695
|
-
|
|
139696
|
-
|
|
139697
|
-
|
|
139698
|
-
|
|
139699
|
-
|
|
139700
|
-
|
|
139701
|
-
|
|
139702
|
-
|
|
139703
|
-
|
|
139704
|
-
|
|
139705
|
-
|
|
139706
|
-
|
|
139707
|
-
|
|
139708
|
-
|
|
139890
|
+
let found = false;
|
|
139891
|
+
for (const indexPath of ["marketplace.json", ".claude-plugin/marketplace.json"]) {
|
|
139892
|
+
let text;
|
|
139893
|
+
try {
|
|
139894
|
+
text = await readFileContained(marketplaceRoot, indexPath, { encoding: "utf8" });
|
|
139895
|
+
} catch (error) {
|
|
139896
|
+
if (error?.code === "SFC2004" && error?.details?.kind === "missing-resource") continue;
|
|
139897
|
+
throw error;
|
|
139898
|
+
}
|
|
139899
|
+
found = true;
|
|
139900
|
+
const marketplace = parseJson2(text, `Qoder Hub marketplace manifest (${indexPath})`);
|
|
139901
|
+
if (!marketplace || typeof marketplace !== "object" || Array.isArray(marketplace) || marketplace.name !== target.marketplace || !Array.isArray(marketplace.plugins)) {
|
|
139902
|
+
throw new Error("Qoder Hub marketplace manifest does not match the frozen marketplace");
|
|
139903
|
+
}
|
|
139904
|
+
if (indexPath === ".claude-plugin/marketplace.json") {
|
|
139905
|
+
if (target.hub.githubHost !== "github.com" || typeof target.frozenTag !== "string" || target.frozenTag.length === 0) {
|
|
139906
|
+
throw new Error("Qoder compatible Hub entry requires a frozen GitHub tag identity");
|
|
139907
|
+
}
|
|
139908
|
+
await assertHubHostEntry({ ...target, host: "claude", pluginTag: target.frozenTag, githubHost: target.hub.githubHost }, marketplaceRoot);
|
|
139909
|
+
continue;
|
|
139910
|
+
}
|
|
139911
|
+
const matches = marketplace.plugins.filter((entry2) => entry2?.name === target.plugin);
|
|
139912
|
+
if (matches.length !== 1) {
|
|
139913
|
+
throw new Error(`Qoder Hub marketplace manifest must contain exactly one ${target.plugin} entry`);
|
|
139914
|
+
}
|
|
139915
|
+
const entry = matches[0];
|
|
139916
|
+
const source = entry.source;
|
|
139917
|
+
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)) {
|
|
139918
|
+
throw new Error("Qoder Hub entry does not match the frozen public source identity");
|
|
139919
|
+
}
|
|
139709
139920
|
}
|
|
139921
|
+
if (!found) throw new Error("Qoder Hub has no native or compatible marketplace manifest");
|
|
139710
139922
|
}
|
|
139711
139923
|
async function verifyQoderInstalledPayload({
|
|
139712
139924
|
target,
|
|
@@ -139715,7 +139927,7 @@ async function verifyQoderInstalledPayload({
|
|
|
139715
139927
|
frozenManifest,
|
|
139716
139928
|
verifyInstalledPayload
|
|
139717
139929
|
}) {
|
|
139718
|
-
const { manifestPath, manifest } = await readQoderManifest(installPath, "installed Qoder plugin manifest");
|
|
139930
|
+
const { manifestPath, manifest } = await readQoderManifest(installPath, "installed Qoder plugin manifest", target);
|
|
139719
139931
|
if (manifestPath !== frozenManifest.manifestPath) {
|
|
139720
139932
|
throw new Error("installed Qoder plugin manifest path differs from the frozen manifest selection");
|
|
139721
139933
|
}
|
|
@@ -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",
|