release-skill 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codebuddy-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +2 -2
  5. package/.kimi-plugin/plugin.json +1 -1
  6. package/CHANGELOG.md +15 -0
  7. package/INSTALL.md +2 -2
  8. package/INSTALL.zh-CN.md +2 -2
  9. package/README.md +16 -9
  10. package/README.zh-CN.md +12 -8
  11. package/adapters/claude/.claude-plugin/marketplace.json +1 -1
  12. package/adapters/claude/.claude-plugin/plugin.json +1 -1
  13. package/adapters/claude/bin/release-skill.bundle.mjs +81 -18
  14. package/adapters/claude/schemas/release-plan.schema.json +5 -0
  15. package/adapters/claude/schemas/release-project.schema.json +5 -0
  16. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  17. package/adapters/codex/bin/release-skill.bundle.mjs +81 -18
  18. package/adapters/codex/schemas/release-plan.schema.json +5 -0
  19. package/adapters/codex/schemas/release-project.schema.json +5 -0
  20. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  21. package/adapters/kimi/bin/release-skill.bundle.mjs +81 -18
  22. package/adapters/kimi/schemas/release-plan.schema.json +5 -0
  23. package/adapters/kimi/schemas/release-project.schema.json +5 -0
  24. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
  25. package/adapters/workbuddy/bin/release-skill.bundle.mjs +81 -18
  26. package/adapters/workbuddy/schemas/release-plan.schema.json +5 -0
  27. package/adapters/workbuddy/schemas/release-project.schema.json +5 -0
  28. package/bin/release-skill.bundle.mjs +81 -18
  29. package/package.json +1 -1
  30. package/schemas/release-plan.schema.json +5 -0
  31. package/schemas/release-project.schema.json +5 -0
  32. package/src/adapters/plugin-marketplace.mjs +21 -5
  33. package/src/commands/prepare.mjs +19 -13
  34. package/src/core/plan.mjs +4 -3
  35. package/src/platforms/codebuddy.mjs +92 -10
  36. package/src/platforms/registry.mjs +4 -3
@@ -9,7 +9,7 @@ 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.4.1"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.2"});
13
13
 
14
14
  var __create = Object.create;
15
15
  var __defProp = Object.defineProperty;
@@ -17400,6 +17400,19 @@ function normalizePlanForDigest2(plan) {
17400
17400
  }
17401
17401
  return normalized;
17402
17402
  }
17403
+ function resolveCodeBuddyMarketplace(action) {
17404
+ const marketplace = action?.marketplace ?? CODEBUDDY_MARKETPLACE_NAME;
17405
+ if (typeof marketplace !== "string" || marketplace.length === 0) {
17406
+ throw new Error(`codebuddy marketplace must be a non-empty string when declared, got ${JSON.stringify(action?.marketplace)}`);
17407
+ }
17408
+ return marketplace;
17409
+ }
17410
+ function resolveCodeBuddyMarketplaceSource(action) {
17411
+ if (action?.marketplace === void 0 || action?.marketplace === null) {
17412
+ return CODEBUDDY_MARKETPLACE_SOURCE;
17413
+ }
17414
+ return typeof action.marketplaceSource === "string" && action.marketplaceSource.length > 0 ? action.marketplaceSource : null;
17415
+ }
17403
17416
  async function resolveCodeBuddyBoundPlanDigest(context) {
17404
17417
  const plan = context?.plan;
17405
17418
  if (!plan || typeof plan !== "object" || Array.isArray(plan)) {
@@ -17440,12 +17453,14 @@ function buildCodeBuddyManualInstructions({
17440
17453
  version,
17441
17454
  ref,
17442
17455
  attestationDir,
17443
- requiresInstalledClosure
17456
+ requiresInstalledClosure,
17457
+ marketplace,
17458
+ marketplaceSource
17444
17459
  }) {
17445
17460
  return [
17446
17461
  `CodeBuddy/WorkBuddy \u63D2\u4EF6\u5B89\u88C5\u65E0\u6CD5\u9501\u5B9A\u51BB\u7ED3 ref\uFF08codebuddy CLI marketplace add/install \u6CA1\u6709 ref \u9009\u9879\uFF0C\u8DDF\u8E2A\u9ED8\u8BA4\u5206\u652F\uFF09\uFF0C\u56E0\u6B64\u5B89\u88C5\u662F\u9700\u8981\u4EBA\u5DE5\u7ED3\u679C\u8BC1\u660E\u7684\u624B\u52A8\u6B65\u9AA4\u3002`,
17447
17462
  `1) publish \u5B8C\u6210\u6240\u6709\u8FDC\u7AEF\u5199\u5165\u540E\u8FDB\u5165 PUBLISHED \u72B6\u6001\uFF08\u81EA\u52A8\u5316 Git \u5206\u652F/\u6807\u7B7E\u3001npm \u548C GitHub Release \u5199\u5165\u5DF2\u5B8C\u6210\uFF09\u3002\u6B64 codebuddy \u68C0\u67E5\u70B9\u6807\u8BB0\u4E3A\u9700\u8981\u4EBA\u5DE5\u5B89\u88C5\u3002`,
17448
- `2) \u4ECE\u7EDF\u4E00\u5E02\u573A "${CODEBUDDY_MARKETPLACE_NAME}" (${CODEBUDDY_MARKETPLACE_SOURCE}) \u5B89\u88C5 release-skill\u3002\u786E\u8BA4\u5B89\u88C5\u7684\u63D2\u4EF6\u7248\u672C\u7B49\u4E8E\u51BB\u7ED3\u7248\u672C ${version}\u3002`,
17463
+ `2) \u4ECE\u7EDF\u4E00\u5E02\u573A "${marketplace}"${marketplaceSource ? ` (${marketplaceSource})` : ""} \u5B89\u88C5 ${plugin}\u3002\u786E\u8BA4\u5B89\u88C5\u7684\u63D2\u4EF6\u7248\u672C\u7B49\u4E8E\u51BB\u7ED3\u7248\u672C ${version}\u3002`,
17449
17464
  `3) \u5C06\u4EBA\u5DE5\u7ED3\u679C JSON \u5199\u5165: ${attestationDir}/${CODEBUDDY_ATTESTATION_FILE}`,
17450
17465
  ` \u5FC5\u586B\u5B57\u6BB5: platform="codebuddy", version, planDigest\uFF08\u51BB\u7ED3\u8BA1\u5212\u6458\u8981\uFF09, result("passed" \u6216 "failed"), actor\uFF08\u786E\u8BA4\u4EBA\uFF09, confirmedAt\uFF08ISO 8601 \u65F6\u95F4\u6233\uFF09${requiresInstalledClosure ? '\uFF0CinstallChannel("desktop" \u6216 "cli")\uFF0CinstallPath\uFF08\u5B9E\u9645\u5B89\u88C5\u540E\u7684\u63D2\u4EF6\u76EE\u5F55\uFF09' : ""}`,
17451
17466
  ` \u53EF\u9009\u5B57\u6BB5: note\uFF08\u5907\u6CE8\uFF09`,
@@ -17509,12 +17524,29 @@ function validateCodeBuddyAttestation(attestation, action, isoNow, boundPlanDige
17509
17524
  return { valid: false, error: 'codebuddy attestation installPath must not contain path traversal ("..")', normalized: null };
17510
17525
  }
17511
17526
  if (normalized.installChannel === "cli") {
17512
- const expectedSuffix = `.workbuddy/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin}`;
17527
+ let resolvedMarketplace;
17528
+ try {
17529
+ resolvedMarketplace = resolveCodeBuddyMarketplace(action);
17530
+ } catch (resolveErr) {
17531
+ return { valid: false, error: resolveErr.message, normalized: null };
17532
+ }
17533
+ const expectedSuffix = `.workbuddy/plugins/marketplaces/${resolvedMarketplace}/plugins/${action.plugin}`;
17513
17534
  if (!normalized.installPath.endsWith(expectedSuffix)) {
17514
17535
  return { valid: false, error: `codebuddy CLI attestation installPath must end with "${expectedSuffix}", got "${normalized.installPath}"`, normalized: null };
17515
17536
  }
17516
17537
  }
17517
17538
  }
17539
+ if (normalized.marketplace !== void 0) {
17540
+ let resolvedMarketplace;
17541
+ try {
17542
+ resolvedMarketplace = resolveCodeBuddyMarketplace(action);
17543
+ } catch (resolveErr) {
17544
+ return { valid: false, error: resolveErr.message, normalized: null };
17545
+ }
17546
+ if (normalized.marketplace !== resolvedMarketplace) {
17547
+ return { valid: false, error: `codebuddy attestation marketplace "${normalized.marketplace}" does not match the resolved marketplace "${resolvedMarketplace}"`, normalized: null };
17548
+ }
17549
+ }
17518
17550
  if (normalized.result !== "passed" && normalized.result !== "failed") {
17519
17551
  return { valid: false, error: `codebuddy attestation result "${normalized.result}" must be "passed" or "failed"`, normalized: null };
17520
17552
  }
@@ -17607,6 +17639,17 @@ async function executeCodeBuddyManualRequirement(action, context) {
17607
17639
  });
17608
17640
  }
17609
17641
  const ref = action.ref ?? `v${action.version}`;
17642
+ let marketplace;
17643
+ try {
17644
+ marketplace = resolveCodeBuddyMarketplace(action);
17645
+ } catch (marketplaceErr) {
17646
+ return createResult({
17647
+ actionType,
17648
+ status: ActionStatus.EXECUTE_FAILED,
17649
+ error: marketplaceErr.message
17650
+ });
17651
+ }
17652
+ const marketplaceSource = resolveCodeBuddyMarketplaceSource(action);
17610
17653
  let attestationDir;
17611
17654
  try {
17612
17655
  attestationDir = codebuddyAuthorityDir(context, planDigest, action.plugin);
@@ -17622,7 +17665,9 @@ async function executeCodeBuddyManualRequirement(action, context) {
17622
17665
  version: action.version,
17623
17666
  ref,
17624
17667
  attestationDir,
17625
- requiresInstalledClosure: Boolean(context.plan?.skillResourceClosure)
17668
+ requiresInstalledClosure: Boolean(context.plan?.skillResourceClosure),
17669
+ marketplace,
17670
+ marketplaceSource
17626
17671
  });
17627
17672
  const requirement = {
17628
17673
  kind: "codebuddy-manual-install-requirement",
@@ -17632,6 +17677,8 @@ async function executeCodeBuddyManualRequirement(action, context) {
17632
17677
  repo: action.repo,
17633
17678
  ref,
17634
17679
  entrySkill: action.entrySkill,
17680
+ marketplace,
17681
+ ...marketplaceSource ? { marketplaceSource } : {},
17635
17682
  planDigest,
17636
17683
  attestationDir,
17637
17684
  attestationFile: CODEBUDDY_ATTESTATION_FILE,
@@ -17644,7 +17691,7 @@ async function executeCodeBuddyManualRequirement(action, context) {
17644
17691
  confirmedAt: "<ISO 8601 timestamp>",
17645
17692
  ...context.plan?.skillResourceClosure ? {
17646
17693
  installChannel: '<"desktop" or "cli">',
17647
- installPath: `<actual .workbuddy/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin} directory>`
17694
+ installPath: `<actual .workbuddy/plugins/marketplaces/${marketplace}/plugins/${action.plugin} directory>`
17648
17695
  } : {},
17649
17696
  note: "<optional note>"
17650
17697
  },
@@ -17736,6 +17783,8 @@ var init_codebuddy = __esm({
17736
17783
  CODEBUDDY_ATTESTATION_FILE = "release-skill-codebuddy-attestation.json";
17737
17784
  CODEBUDDY_MARKETPLACE_NAME = "artifact-skill-set";
17738
17785
  CODEBUDDY_MARKETPLACE_SOURCE = "https://github.com/ifoohoo/artifact-skill-set";
17786
+ __name(resolveCodeBuddyMarketplace, "resolveCodeBuddyMarketplace");
17787
+ __name(resolveCodeBuddyMarketplaceSource, "resolveCodeBuddyMarketplaceSource");
17739
17788
  CODEBUDDY_PLUGIN_MANIFEST_RELATIVE = join4(".codebuddy-plugin", "plugin.json");
17740
17789
  CODEBUDDY_MAX_ATTESTATION_VALIDITY_MS = 24 * 60 * 60 * 1e3;
17741
17790
  __name(resolveCodeBuddyBoundPlanDigest, "resolveCodeBuddyBoundPlanDigest");
@@ -18465,9 +18514,10 @@ var init_registry = __esm({
18465
18514
  marketplace: ".claude-plugin/marketplace.json"
18466
18515
  }),
18467
18516
  marketplaceSourceForm: null,
18468
- // codebuddy installs from a unified marketplace but carries no marketplace
18469
- // identity in the action (the marketplace is a fixed constant in
18470
- // ./codebuddy.mjs); the entry-version binding does not apply (null = N/A).
18517
+ // codebuddy installs from a unified marketplace whose identity is optional
18518
+ // on the action: a distribution may declare `marketplace` to override the
18519
+ // default constant in ./codebuddy.mjs (resolveCodeBuddyMarketplace); the
18520
+ // entry-version binding does not apply either way (null = N/A).
18471
18521
  marketplaceEntryCarriesVersion: null,
18472
18522
  // codebuddy has no marketplace add that can pin a frozen ref (attestation
18473
18523
  // loop instead), so the marketplace ref form does not apply (null = N/A).
@@ -74267,15 +74317,16 @@ function createPluginMarketplaceAdapter(deps = {}) {
74267
74317
  try {
74268
74318
  attestation = JSON.parse(await readFile18(resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE), "utf8"));
74269
74319
  } catch {
74320
+ const marketplaceSource = resolveCodeBuddyMarketplaceSource(action);
74270
74321
  return createResult({
74271
74322
  actionType,
74272
74323
  status: ActionStatus.OBSERVED,
74273
74324
  observation: {
74274
74325
  installed: false,
74275
74326
  manualInstallRequired: true,
74276
- marketplaceSource: CODEBUDDY_MARKETPLACE_SOURCE,
74327
+ ...marketplaceSource ? { marketplaceSource } : {},
74277
74328
  attestationDir,
74278
- error: `codebuddy attestation is missing; write ${resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE)} after the manual install (marketplace ${CODEBUDDY_MARKETPLACE_SOURCE})`
74329
+ error: `codebuddy attestation is missing; write ${resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE)} after the manual install${marketplaceSource ? ` (marketplace ${marketplaceSource})` : ""}`
74279
74330
  }
74280
74331
  });
74281
74332
  }
@@ -74328,7 +74379,17 @@ function createPluginMarketplaceAdapter(deps = {}) {
74328
74379
  });
74329
74380
  }
74330
74381
  const normalizedPath = normalizedAttestation.installPath.replaceAll("\\", "/");
74331
- const expectedSuffix = `.workbuddy/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin}`;
74382
+ let resolvedMarketplace;
74383
+ try {
74384
+ resolvedMarketplace = resolveCodeBuddyMarketplace(action);
74385
+ } catch (resolveErr) {
74386
+ return createResult({
74387
+ actionType,
74388
+ status: ActionStatus.OBSERVED,
74389
+ observation: { installed: false, error: resolveErr.message }
74390
+ });
74391
+ }
74392
+ const expectedSuffix = `.workbuddy/plugins/marketplaces/${resolvedMarketplace}/plugins/${action.plugin}`;
74332
74393
  if (!normalizedPath.endsWith(expectedSuffix)) {
74333
74394
  return createResult({
74334
74395
  actionType,
@@ -80887,7 +80948,6 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
80887
80948
  for (const platform of PLATFORMS) {
80888
80949
  const dist = frozenUnitDists ? frozenUnitDists.find((d) => d.type === platform.distributionType) : (unit.distributions ?? []).find((d) => d.type === platform.distributionType);
80889
80950
  if (!dist) continue;
80890
- const requiresMarketplace = platform.schemaRequiredFields.includes("marketplace");
80891
80951
  const timeoutMs = Number.isInteger(dist.timeoutMs) ? dist.timeoutMs : 3e5;
80892
80952
  const externalMarketplace = dist.marketplaceRepo !== void 0 && dist.marketplaceRepo !== null;
80893
80953
  const marketplaceSourceType = dist.marketplaceSourceType ?? (externalMarketplace ? "standalone-index" : "bundled-family");
@@ -80921,7 +80981,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
80921
80981
  parameters: {
80922
80982
  consumer: platform.id,
80923
80983
  plugin: dist.plugin,
80924
- ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
80984
+ ...dist.marketplace !== void 0 ? { marketplace: dist.marketplace } : {},
80985
+ ...dist.marketplaceSource !== void 0 ? { marketplaceSource: dist.marketplaceSource } : {},
80925
80986
  repo: externalMarketplace ? dist.marketplaceRepo : unit.publicRepo,
80926
80987
  version,
80927
80988
  entrySkill: dist.entrySkill,
@@ -80948,7 +81009,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
80948
81009
  expected: {
80949
81010
  installed: true,
80950
81011
  plugin: dist.plugin,
80951
- ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
81012
+ ...dist.marketplace !== void 0 ? { marketplace: dist.marketplace } : {},
81013
+ ...dist.marketplaceSource !== void 0 ? { marketplaceSource: dist.marketplaceSource } : {},
80952
81014
  version,
80953
81015
  entrySkill: dist.entrySkill,
80954
81016
  ...externalMarketplace ? { marketplaceLocation: "external", repo: dist.marketplaceRepo } : {}
@@ -81085,7 +81147,6 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
81085
81147
  for (const platform of PLATFORMS) {
81086
81148
  const dist = frozenUnitDists ? frozenUnitDists.find((d) => d.type === platform.distributionType) : (unit.distributions ?? []).find((d) => d.type === platform.distributionType);
81087
81149
  if (!dist) continue;
81088
- const requiresMarketplace = platform.schemaRequiredFields.includes("marketplace");
81089
81150
  const timeoutMs = Number.isInteger(dist.timeoutMs) ? dist.timeoutMs : 3e5;
81090
81151
  const externalMarketplace = dist.marketplaceRepo !== void 0 && dist.marketplaceRepo !== null;
81091
81152
  const freeze = externalMarketplace ? externalFreezes.get(`${unit.id} ${dist.type}`) : null;
@@ -81119,7 +81180,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
81119
81180
  parameters: {
81120
81181
  consumer: platform.id,
81121
81182
  plugin: dist.plugin,
81122
- ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
81183
+ ...dist.marketplace !== void 0 ? { marketplace: dist.marketplace } : {},
81184
+ ...dist.marketplaceSource !== void 0 ? { marketplaceSource: dist.marketplaceSource } : {},
81123
81185
  repo: externalMarketplace ? dist.marketplaceRepo : unit.publicRepo,
81124
81186
  ref: externalMarketplace ? freeze.ref : resolvedTag,
81125
81187
  version: unitVersion,
@@ -81158,7 +81220,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
81158
81220
  installed: true,
81159
81221
  consumer: platform.id,
81160
81222
  plugin: dist.plugin,
81161
- ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
81223
+ ...dist.marketplace !== void 0 ? { marketplace: dist.marketplace } : {},
81224
+ ...dist.marketplaceSource !== void 0 ? { marketplaceSource: dist.marketplaceSource } : {},
81162
81225
  repo: externalMarketplace ? dist.marketplaceRepo : unit.publicRepo,
81163
81226
  version: unitVersion,
81164
81227
  ref: externalMarketplace ? freeze.ref : resolvedTag,
@@ -398,6 +398,11 @@
398
398
  "minLength": 1,
399
399
  "pattern": "^[a-z0-9][a-z0-9._-]*$"
400
400
  },
401
+ "marketplaceSource": {
402
+ "type": "string",
403
+ "minLength": 1,
404
+ "description": "消费者添加统一市场所用的来源 URL(如 codebuddy plugin marketplace add);可选,仅在可知时声明"
405
+ },
401
406
  "marketplaceRepo": {
402
407
  "type": "string",
403
408
  "pattern": "^[a-z0-9][a-z0-9._-]*/[a-z0-9][a-z0-9._-]*$",
@@ -191,6 +191,11 @@
191
191
  "minLength": 1,
192
192
  "pattern": "^[a-z0-9][a-z0-9._-]*$"
193
193
  },
194
+ "marketplaceSource": {
195
+ "type": "string",
196
+ "minLength": 1,
197
+ "description": "消费者添加统一市场所用的来源 URL(如 codebuddy plugin marketplace add);可选,仅在可知时声明"
198
+ },
194
199
  "marketplaceRepo": {
195
200
  "type": "string",
196
201
  "pattern": "^[a-z0-9][a-z0-9._-]*/[a-z0-9][a-z0-9._-]*$",
@@ -9,7 +9,7 @@ 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.4.1"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.4.2"});
13
13
 
14
14
  var __create = Object.create;
15
15
  var __defProp = Object.defineProperty;
@@ -17400,6 +17400,19 @@ function normalizePlanForDigest2(plan) {
17400
17400
  }
17401
17401
  return normalized;
17402
17402
  }
17403
+ function resolveCodeBuddyMarketplace(action) {
17404
+ const marketplace = action?.marketplace ?? CODEBUDDY_MARKETPLACE_NAME;
17405
+ if (typeof marketplace !== "string" || marketplace.length === 0) {
17406
+ throw new Error(`codebuddy marketplace must be a non-empty string when declared, got ${JSON.stringify(action?.marketplace)}`);
17407
+ }
17408
+ return marketplace;
17409
+ }
17410
+ function resolveCodeBuddyMarketplaceSource(action) {
17411
+ if (action?.marketplace === void 0 || action?.marketplace === null) {
17412
+ return CODEBUDDY_MARKETPLACE_SOURCE;
17413
+ }
17414
+ return typeof action.marketplaceSource === "string" && action.marketplaceSource.length > 0 ? action.marketplaceSource : null;
17415
+ }
17403
17416
  async function resolveCodeBuddyBoundPlanDigest(context) {
17404
17417
  const plan = context?.plan;
17405
17418
  if (!plan || typeof plan !== "object" || Array.isArray(plan)) {
@@ -17440,12 +17453,14 @@ function buildCodeBuddyManualInstructions({
17440
17453
  version,
17441
17454
  ref,
17442
17455
  attestationDir,
17443
- requiresInstalledClosure
17456
+ requiresInstalledClosure,
17457
+ marketplace,
17458
+ marketplaceSource
17444
17459
  }) {
17445
17460
  return [
17446
17461
  `CodeBuddy/WorkBuddy \u63D2\u4EF6\u5B89\u88C5\u65E0\u6CD5\u9501\u5B9A\u51BB\u7ED3 ref\uFF08codebuddy CLI marketplace add/install \u6CA1\u6709 ref \u9009\u9879\uFF0C\u8DDF\u8E2A\u9ED8\u8BA4\u5206\u652F\uFF09\uFF0C\u56E0\u6B64\u5B89\u88C5\u662F\u9700\u8981\u4EBA\u5DE5\u7ED3\u679C\u8BC1\u660E\u7684\u624B\u52A8\u6B65\u9AA4\u3002`,
17447
17462
  `1) publish \u5B8C\u6210\u6240\u6709\u8FDC\u7AEF\u5199\u5165\u540E\u8FDB\u5165 PUBLISHED \u72B6\u6001\uFF08\u81EA\u52A8\u5316 Git \u5206\u652F/\u6807\u7B7E\u3001npm \u548C GitHub Release \u5199\u5165\u5DF2\u5B8C\u6210\uFF09\u3002\u6B64 codebuddy \u68C0\u67E5\u70B9\u6807\u8BB0\u4E3A\u9700\u8981\u4EBA\u5DE5\u5B89\u88C5\u3002`,
17448
- `2) \u4ECE\u7EDF\u4E00\u5E02\u573A "${CODEBUDDY_MARKETPLACE_NAME}" (${CODEBUDDY_MARKETPLACE_SOURCE}) \u5B89\u88C5 release-skill\u3002\u786E\u8BA4\u5B89\u88C5\u7684\u63D2\u4EF6\u7248\u672C\u7B49\u4E8E\u51BB\u7ED3\u7248\u672C ${version}\u3002`,
17463
+ `2) \u4ECE\u7EDF\u4E00\u5E02\u573A "${marketplace}"${marketplaceSource ? ` (${marketplaceSource})` : ""} \u5B89\u88C5 ${plugin}\u3002\u786E\u8BA4\u5B89\u88C5\u7684\u63D2\u4EF6\u7248\u672C\u7B49\u4E8E\u51BB\u7ED3\u7248\u672C ${version}\u3002`,
17449
17464
  `3) \u5C06\u4EBA\u5DE5\u7ED3\u679C JSON \u5199\u5165: ${attestationDir}/${CODEBUDDY_ATTESTATION_FILE}`,
17450
17465
  ` \u5FC5\u586B\u5B57\u6BB5: platform="codebuddy", version, planDigest\uFF08\u51BB\u7ED3\u8BA1\u5212\u6458\u8981\uFF09, result("passed" \u6216 "failed"), actor\uFF08\u786E\u8BA4\u4EBA\uFF09, confirmedAt\uFF08ISO 8601 \u65F6\u95F4\u6233\uFF09${requiresInstalledClosure ? '\uFF0CinstallChannel("desktop" \u6216 "cli")\uFF0CinstallPath\uFF08\u5B9E\u9645\u5B89\u88C5\u540E\u7684\u63D2\u4EF6\u76EE\u5F55\uFF09' : ""}`,
17451
17466
  ` \u53EF\u9009\u5B57\u6BB5: note\uFF08\u5907\u6CE8\uFF09`,
@@ -17509,12 +17524,29 @@ function validateCodeBuddyAttestation(attestation, action, isoNow, boundPlanDige
17509
17524
  return { valid: false, error: 'codebuddy attestation installPath must not contain path traversal ("..")', normalized: null };
17510
17525
  }
17511
17526
  if (normalized.installChannel === "cli") {
17512
- const expectedSuffix = `.workbuddy/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin}`;
17527
+ let resolvedMarketplace;
17528
+ try {
17529
+ resolvedMarketplace = resolveCodeBuddyMarketplace(action);
17530
+ } catch (resolveErr) {
17531
+ return { valid: false, error: resolveErr.message, normalized: null };
17532
+ }
17533
+ const expectedSuffix = `.workbuddy/plugins/marketplaces/${resolvedMarketplace}/plugins/${action.plugin}`;
17513
17534
  if (!normalized.installPath.endsWith(expectedSuffix)) {
17514
17535
  return { valid: false, error: `codebuddy CLI attestation installPath must end with "${expectedSuffix}", got "${normalized.installPath}"`, normalized: null };
17515
17536
  }
17516
17537
  }
17517
17538
  }
17539
+ if (normalized.marketplace !== void 0) {
17540
+ let resolvedMarketplace;
17541
+ try {
17542
+ resolvedMarketplace = resolveCodeBuddyMarketplace(action);
17543
+ } catch (resolveErr) {
17544
+ return { valid: false, error: resolveErr.message, normalized: null };
17545
+ }
17546
+ if (normalized.marketplace !== resolvedMarketplace) {
17547
+ return { valid: false, error: `codebuddy attestation marketplace "${normalized.marketplace}" does not match the resolved marketplace "${resolvedMarketplace}"`, normalized: null };
17548
+ }
17549
+ }
17518
17550
  if (normalized.result !== "passed" && normalized.result !== "failed") {
17519
17551
  return { valid: false, error: `codebuddy attestation result "${normalized.result}" must be "passed" or "failed"`, normalized: null };
17520
17552
  }
@@ -17607,6 +17639,17 @@ async function executeCodeBuddyManualRequirement(action, context) {
17607
17639
  });
17608
17640
  }
17609
17641
  const ref = action.ref ?? `v${action.version}`;
17642
+ let marketplace;
17643
+ try {
17644
+ marketplace = resolveCodeBuddyMarketplace(action);
17645
+ } catch (marketplaceErr) {
17646
+ return createResult({
17647
+ actionType,
17648
+ status: ActionStatus.EXECUTE_FAILED,
17649
+ error: marketplaceErr.message
17650
+ });
17651
+ }
17652
+ const marketplaceSource = resolveCodeBuddyMarketplaceSource(action);
17610
17653
  let attestationDir;
17611
17654
  try {
17612
17655
  attestationDir = codebuddyAuthorityDir(context, planDigest, action.plugin);
@@ -17622,7 +17665,9 @@ async function executeCodeBuddyManualRequirement(action, context) {
17622
17665
  version: action.version,
17623
17666
  ref,
17624
17667
  attestationDir,
17625
- requiresInstalledClosure: Boolean(context.plan?.skillResourceClosure)
17668
+ requiresInstalledClosure: Boolean(context.plan?.skillResourceClosure),
17669
+ marketplace,
17670
+ marketplaceSource
17626
17671
  });
17627
17672
  const requirement = {
17628
17673
  kind: "codebuddy-manual-install-requirement",
@@ -17632,6 +17677,8 @@ async function executeCodeBuddyManualRequirement(action, context) {
17632
17677
  repo: action.repo,
17633
17678
  ref,
17634
17679
  entrySkill: action.entrySkill,
17680
+ marketplace,
17681
+ ...marketplaceSource ? { marketplaceSource } : {},
17635
17682
  planDigest,
17636
17683
  attestationDir,
17637
17684
  attestationFile: CODEBUDDY_ATTESTATION_FILE,
@@ -17644,7 +17691,7 @@ async function executeCodeBuddyManualRequirement(action, context) {
17644
17691
  confirmedAt: "<ISO 8601 timestamp>",
17645
17692
  ...context.plan?.skillResourceClosure ? {
17646
17693
  installChannel: '<"desktop" or "cli">',
17647
- installPath: `<actual .workbuddy/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin} directory>`
17694
+ installPath: `<actual .workbuddy/plugins/marketplaces/${marketplace}/plugins/${action.plugin} directory>`
17648
17695
  } : {},
17649
17696
  note: "<optional note>"
17650
17697
  },
@@ -17736,6 +17783,8 @@ var init_codebuddy = __esm({
17736
17783
  CODEBUDDY_ATTESTATION_FILE = "release-skill-codebuddy-attestation.json";
17737
17784
  CODEBUDDY_MARKETPLACE_NAME = "artifact-skill-set";
17738
17785
  CODEBUDDY_MARKETPLACE_SOURCE = "https://github.com/ifoohoo/artifact-skill-set";
17786
+ __name(resolveCodeBuddyMarketplace, "resolveCodeBuddyMarketplace");
17787
+ __name(resolveCodeBuddyMarketplaceSource, "resolveCodeBuddyMarketplaceSource");
17739
17788
  CODEBUDDY_PLUGIN_MANIFEST_RELATIVE = join4(".codebuddy-plugin", "plugin.json");
17740
17789
  CODEBUDDY_MAX_ATTESTATION_VALIDITY_MS = 24 * 60 * 60 * 1e3;
17741
17790
  __name(resolveCodeBuddyBoundPlanDigest, "resolveCodeBuddyBoundPlanDigest");
@@ -18465,9 +18514,10 @@ var init_registry = __esm({
18465
18514
  marketplace: ".claude-plugin/marketplace.json"
18466
18515
  }),
18467
18516
  marketplaceSourceForm: null,
18468
- // codebuddy installs from a unified marketplace but carries no marketplace
18469
- // identity in the action (the marketplace is a fixed constant in
18470
- // ./codebuddy.mjs); the entry-version binding does not apply (null = N/A).
18517
+ // codebuddy installs from a unified marketplace whose identity is optional
18518
+ // on the action: a distribution may declare `marketplace` to override the
18519
+ // default constant in ./codebuddy.mjs (resolveCodeBuddyMarketplace); the
18520
+ // entry-version binding does not apply either way (null = N/A).
18471
18521
  marketplaceEntryCarriesVersion: null,
18472
18522
  // codebuddy has no marketplace add that can pin a frozen ref (attestation
18473
18523
  // loop instead), so the marketplace ref form does not apply (null = N/A).
@@ -74267,15 +74317,16 @@ function createPluginMarketplaceAdapter(deps = {}) {
74267
74317
  try {
74268
74318
  attestation = JSON.parse(await readFile18(resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE), "utf8"));
74269
74319
  } catch {
74320
+ const marketplaceSource = resolveCodeBuddyMarketplaceSource(action);
74270
74321
  return createResult({
74271
74322
  actionType,
74272
74323
  status: ActionStatus.OBSERVED,
74273
74324
  observation: {
74274
74325
  installed: false,
74275
74326
  manualInstallRequired: true,
74276
- marketplaceSource: CODEBUDDY_MARKETPLACE_SOURCE,
74327
+ ...marketplaceSource ? { marketplaceSource } : {},
74277
74328
  attestationDir,
74278
- error: `codebuddy attestation is missing; write ${resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE)} after the manual install (marketplace ${CODEBUDDY_MARKETPLACE_SOURCE})`
74329
+ error: `codebuddy attestation is missing; write ${resolve21(attestationDir, CODEBUDDY_ATTESTATION_FILE)} after the manual install${marketplaceSource ? ` (marketplace ${marketplaceSource})` : ""}`
74279
74330
  }
74280
74331
  });
74281
74332
  }
@@ -74328,7 +74379,17 @@ function createPluginMarketplaceAdapter(deps = {}) {
74328
74379
  });
74329
74380
  }
74330
74381
  const normalizedPath = normalizedAttestation.installPath.replaceAll("\\", "/");
74331
- const expectedSuffix = `.workbuddy/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin}`;
74382
+ let resolvedMarketplace;
74383
+ try {
74384
+ resolvedMarketplace = resolveCodeBuddyMarketplace(action);
74385
+ } catch (resolveErr) {
74386
+ return createResult({
74387
+ actionType,
74388
+ status: ActionStatus.OBSERVED,
74389
+ observation: { installed: false, error: resolveErr.message }
74390
+ });
74391
+ }
74392
+ const expectedSuffix = `.workbuddy/plugins/marketplaces/${resolvedMarketplace}/plugins/${action.plugin}`;
74332
74393
  if (!normalizedPath.endsWith(expectedSuffix)) {
74333
74394
  return createResult({
74334
74395
  actionType,
@@ -80887,7 +80948,6 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
80887
80948
  for (const platform of PLATFORMS) {
80888
80949
  const dist = frozenUnitDists ? frozenUnitDists.find((d) => d.type === platform.distributionType) : (unit.distributions ?? []).find((d) => d.type === platform.distributionType);
80889
80950
  if (!dist) continue;
80890
- const requiresMarketplace = platform.schemaRequiredFields.includes("marketplace");
80891
80951
  const timeoutMs = Number.isInteger(dist.timeoutMs) ? dist.timeoutMs : 3e5;
80892
80952
  const externalMarketplace = dist.marketplaceRepo !== void 0 && dist.marketplaceRepo !== null;
80893
80953
  const marketplaceSourceType = dist.marketplaceSourceType ?? (externalMarketplace ? "standalone-index" : "bundled-family");
@@ -80921,7 +80981,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
80921
80981
  parameters: {
80922
80982
  consumer: platform.id,
80923
80983
  plugin: dist.plugin,
80924
- ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
80984
+ ...dist.marketplace !== void 0 ? { marketplace: dist.marketplace } : {},
80985
+ ...dist.marketplaceSource !== void 0 ? { marketplaceSource: dist.marketplaceSource } : {},
80925
80986
  repo: externalMarketplace ? dist.marketplaceRepo : unit.publicRepo,
80926
80987
  version,
80927
80988
  entrySkill: dist.entrySkill,
@@ -80948,7 +81009,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
80948
81009
  expected: {
80949
81010
  installed: true,
80950
81011
  plugin: dist.plugin,
80951
- ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
81012
+ ...dist.marketplace !== void 0 ? { marketplace: dist.marketplace } : {},
81013
+ ...dist.marketplaceSource !== void 0 ? { marketplaceSource: dist.marketplaceSource } : {},
80952
81014
  version,
80953
81015
  entrySkill: dist.entrySkill,
80954
81016
  ...externalMarketplace ? { marketplaceLocation: "external", repo: dist.marketplaceRepo } : {}
@@ -81085,7 +81147,6 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
81085
81147
  for (const platform of PLATFORMS) {
81086
81148
  const dist = frozenUnitDists ? frozenUnitDists.find((d) => d.type === platform.distributionType) : (unit.distributions ?? []).find((d) => d.type === platform.distributionType);
81087
81149
  if (!dist) continue;
81088
- const requiresMarketplace = platform.schemaRequiredFields.includes("marketplace");
81089
81150
  const timeoutMs = Number.isInteger(dist.timeoutMs) ? dist.timeoutMs : 3e5;
81090
81151
  const externalMarketplace = dist.marketplaceRepo !== void 0 && dist.marketplaceRepo !== null;
81091
81152
  const freeze = externalMarketplace ? externalFreezes.get(`${unit.id} ${dist.type}`) : null;
@@ -81119,7 +81180,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
81119
81180
  parameters: {
81120
81181
  consumer: platform.id,
81121
81182
  plugin: dist.plugin,
81122
- ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
81183
+ ...dist.marketplace !== void 0 ? { marketplace: dist.marketplace } : {},
81184
+ ...dist.marketplaceSource !== void 0 ? { marketplaceSource: dist.marketplaceSource } : {},
81123
81185
  repo: externalMarketplace ? dist.marketplaceRepo : unit.publicRepo,
81124
81186
  ref: externalMarketplace ? freeze.ref : resolvedTag,
81125
81187
  version: unitVersion,
@@ -81158,7 +81220,8 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
81158
81220
  installed: true,
81159
81221
  consumer: platform.id,
81160
81222
  plugin: dist.plugin,
81161
- ...requiresMarketplace ? { marketplace: dist.marketplace } : {},
81223
+ ...dist.marketplace !== void 0 ? { marketplace: dist.marketplace } : {},
81224
+ ...dist.marketplaceSource !== void 0 ? { marketplaceSource: dist.marketplaceSource } : {},
81162
81225
  repo: externalMarketplace ? dist.marketplaceRepo : unit.publicRepo,
81163
81226
  version: unitVersion,
81164
81227
  ref: externalMarketplace ? freeze.ref : resolvedTag,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-skill",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
5
5
  "author": {
6
6
  "name": "广州市风荷科技有限公司"
@@ -398,6 +398,11 @@
398
398
  "minLength": 1,
399
399
  "pattern": "^[a-z0-9][a-z0-9._-]*$"
400
400
  },
401
+ "marketplaceSource": {
402
+ "type": "string",
403
+ "minLength": 1,
404
+ "description": "消费者添加统一市场所用的来源 URL(如 codebuddy plugin marketplace add);可选,仅在可知时声明"
405
+ },
401
406
  "marketplaceRepo": {
402
407
  "type": "string",
403
408
  "pattern": "^[a-z0-9][a-z0-9._-]*/[a-z0-9][a-z0-9._-]*$",
@@ -191,6 +191,11 @@
191
191
  "minLength": 1,
192
192
  "pattern": "^[a-z0-9][a-z0-9._-]*$"
193
193
  },
194
+ "marketplaceSource": {
195
+ "type": "string",
196
+ "minLength": 1,
197
+ "description": "消费者添加统一市场所用的来源 URL(如 codebuddy plugin marketplace add);可选,仅在可知时声明"
198
+ },
194
199
  "marketplaceRepo": {
195
200
  "type": "string",
196
201
  "pattern": "^[a-z0-9][a-z0-9._-]*/[a-z0-9][a-z0-9._-]*$",
@@ -48,8 +48,8 @@ import {
48
48
  import {
49
49
  CODEBUDDY_REQUIREMENT_FILE,
50
50
  CODEBUDDY_ATTESTATION_FILE,
51
- CODEBUDDY_MARKETPLACE_NAME,
52
- CODEBUDDY_MARKETPLACE_SOURCE,
51
+ resolveCodeBuddyMarketplace,
52
+ resolveCodeBuddyMarketplaceSource,
53
53
  resolveCodeBuddyBoundPlanDigest,
54
54
  codebuddyAuthorityDir,
55
55
  validateCodeBuddyAttestation,
@@ -3095,15 +3095,19 @@ export function createPluginMarketplaceAdapter(deps = {}) {
3095
3095
  try {
3096
3096
  attestation = JSON.parse(await readFile(resolve(attestationDir, CODEBUDDY_ATTESTATION_FILE), 'utf8'));
3097
3097
  } catch {
3098
+ // The marketplace source hint follows the frozen action's
3099
+ // resolved marketplace; unknown configured marketplaces cite no
3100
+ // fabricated URL.
3101
+ const marketplaceSource = resolveCodeBuddyMarketplaceSource(action);
3098
3102
  return createResult({
3099
3103
  actionType,
3100
3104
  status: ActionStatus.OBSERVED,
3101
3105
  observation: {
3102
3106
  installed: false,
3103
3107
  manualInstallRequired: true,
3104
- marketplaceSource: CODEBUDDY_MARKETPLACE_SOURCE,
3108
+ ...(marketplaceSource ? { marketplaceSource } : {}),
3105
3109
  attestationDir,
3106
- error: `codebuddy attestation is missing; write ${resolve(attestationDir, CODEBUDDY_ATTESTATION_FILE)} after the manual install (marketplace ${CODEBUDDY_MARKETPLACE_SOURCE})`,
3110
+ error: `codebuddy attestation is missing; write ${resolve(attestationDir, CODEBUDDY_ATTESTATION_FILE)} after the manual install${marketplaceSource ? ` (marketplace ${marketplaceSource})` : ''}`,
3107
3111
  },
3108
3112
  });
3109
3113
  }
@@ -3162,7 +3166,19 @@ export function createPluginMarketplaceAdapter(deps = {}) {
3162
3166
  });
3163
3167
  }
3164
3168
  const normalizedPath = normalizedAttestation.installPath.replaceAll('\\', '/');
3165
- const expectedSuffix = `.workbuddy/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${action.plugin}`;
3169
+ // The expected suffix follows the frozen action's resolved
3170
+ // marketplace (default constant for legacy plans).
3171
+ let resolvedMarketplace;
3172
+ try {
3173
+ resolvedMarketplace = resolveCodeBuddyMarketplace(action);
3174
+ } catch (resolveErr) {
3175
+ return createResult({
3176
+ actionType,
3177
+ status: ActionStatus.OBSERVED,
3178
+ observation: { installed: false, error: resolveErr.message },
3179
+ });
3180
+ }
3181
+ const expectedSuffix = `.workbuddy/plugins/marketplaces/${resolvedMarketplace}/plugins/${action.plugin}`;
3166
3182
  if (!normalizedPath.endsWith(expectedSuffix)) {
3167
3183
  return createResult({
3168
3184
  actionType,