release-skill 0.2.2 → 0.2.3

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.
@@ -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.2.2"});
12
+ const __bundlePkg = Object.freeze({"name":"release-skill","version":"0.2.3"});
13
13
 
14
14
  var __create = Object.create;
15
15
  var __defProp = Object.defineProperty;
@@ -17819,11 +17819,24 @@ var init_baseline = __esm({
17819
17819
  ".release-skill/runs",
17820
17820
  ".release-skill/transactions",
17821
17821
  ".release-skill/kimi-attestations",
17822
+ // codebuddy-attestations: same rationale as kimi-attestations above.
17823
+ // Holds CodeBuddy's closure-protocol lifecycle artifacts: manual install
17824
+ // requirements and human attestations bound to planDigest, payloadDigest,
17825
+ // version, install path, responsible person, and expiry. Neither is
17826
+ // publishable source or project configuration — they never enter the frozen
17827
+ // snapshot — so excluding them keeps reconcile's own requirement output and
17828
+ // the flow-required attestation from invalidating the baseline.
17829
+ ".release-skill/codebuddy-attestations",
17822
17830
  // T3.2 incremental hook cache: a pure local optimisation written by prepare.
17823
17831
  // Excluding it keeps cache records from destabilising workspaceDigest on
17824
17832
  // every prepare (and hook-cache.mjs also skips this prefix when fingerprinting
17825
17833
  // inputs, so records never hash themselves).
17826
- ".release-skill/cache"
17834
+ ".release-skill/cache",
17835
+ // waivers: exception records with reason, responsible person, and expiry.
17836
+ // Like attestations, they are runtime closure artifacts — not publishable
17837
+ // source or project configuration — so excluding them keeps waiver writes
17838
+ // from invalidating the workspace baseline.
17839
+ ".release-skill/waivers"
17827
17840
  ];
17828
17841
  RESERVED_CONTROL_PREFIXES = [
17829
17842
  ...CONTROL_PLANE_PREFIXES,
@@ -20810,6 +20823,9 @@ function codebuddyCliInstallRoot(cliHome, marketplace, plugin) {
20810
20823
  function codebuddyDesktopTailSegments(marketplace, plugin) {
20811
20824
  return [CODEBUDDY_DESKTOP_HOME_DIR, "plugins", "marketplaces", marketplace, "plugins", plugin];
20812
20825
  }
20826
+ function codebuddyCliTailSegments(marketplace, plugin) {
20827
+ return [CODEBUDDY_CLI_STATE_DIR, "plugins", "marketplaces", marketplace, "plugins", plugin];
20828
+ }
20813
20829
  function matchesDesktopLayout(installPath, marketplace, plugin) {
20814
20830
  const segments = installPath.split(/[\\/]+/).filter((s) => s !== "" && s !== ".");
20815
20831
  const tail = codebuddyDesktopTailSegments(marketplace, plugin);
@@ -20817,6 +20833,13 @@ function matchesDesktopLayout(installPath, marketplace, plugin) {
20817
20833
  const offset = segments.length - tail.length;
20818
20834
  return tail.every((segment, index) => segments[offset + index] === segment);
20819
20835
  }
20836
+ function matchesCliLayout(installPath, marketplace, plugin) {
20837
+ const segments = installPath.split(/[\\/]+/).filter((s) => s !== "" && s !== ".");
20838
+ const tail = codebuddyCliTailSegments(marketplace, plugin);
20839
+ if (segments.length < tail.length) return false;
20840
+ const offset = segments.length - tail.length;
20841
+ return tail.every((segment, index) => segments[offset + index] === segment);
20842
+ }
20820
20843
  function buildCodeBuddyManualInstructions({ plugin, version, ref, cliHome, attestationDir }) {
20821
20844
  const cliInstallRoot = codebuddyCliInstallRoot(cliHome, CODEBUDDY_MARKETPLACE_NAME, plugin);
20822
20845
  const desktopInstallRoot = `~/${CODEBUDDY_DESKTOP_HOME_DIR}/plugins/marketplaces/${CODEBUDDY_MARKETPLACE_NAME}/plugins/${plugin}`;
@@ -20916,6 +20939,9 @@ function validateCodeBuddyAttestation(attestation, action, isoNow, boundPlanDige
20916
20939
  if (attestation.installChannel === "desktop" && !matchesDesktopLayout(attestation.installPath, attestation.marketplace, attestation.plugin)) {
20917
20940
  return { valid: false, error: `codebuddy attestation installPath does not match the WorkBuddy desktop marketplace layout (.workbuddy/plugins/marketplaces/${attestation.marketplace}/plugins/${attestation.plugin})` };
20918
20941
  }
20942
+ if (attestation.installChannel === "cli" && !matchesCliLayout(attestation.installPath, attestation.marketplace, attestation.plugin)) {
20943
+ return { valid: false, error: `codebuddy attestation installPath does not match the CodeBuddy CLI marketplace layout (.codebuddy/plugins/marketplaces/${attestation.marketplace}/plugins/${attestation.plugin})` };
20944
+ }
20919
20945
  return { valid: true, error: null };
20920
20946
  }
20921
20947
  async function executeCodeBuddyManualRequirement(action, context) {
@@ -21096,7 +21122,9 @@ var init_codebuddy = __esm({
21096
21122
  __name(codebuddyCliHome, "codebuddyCliHome");
21097
21123
  __name(codebuddyCliInstallRoot, "codebuddyCliInstallRoot");
21098
21124
  __name(codebuddyDesktopTailSegments, "codebuddyDesktopTailSegments");
21125
+ __name(codebuddyCliTailSegments, "codebuddyCliTailSegments");
21099
21126
  __name(matchesDesktopLayout, "matchesDesktopLayout");
21127
+ __name(matchesCliLayout, "matchesCliLayout");
21100
21128
  __name(buildCodeBuddyManualInstructions, "buildCodeBuddyManualInstructions");
21101
21129
  __name(readCodeBuddyManifest, "readCodeBuddyManifest");
21102
21130
  __name(validateCodeBuddyAttestation, "validateCodeBuddyAttestation");
@@ -21229,6 +21257,21 @@ function assertRegistry(registry = PLATFORMS) {
21229
21257
  if (!Array.isArray(platform.isolationSubdirs)) {
21230
21258
  throw new Error(`platform registry: ${label} isolationSubdirs must be an array`);
21231
21259
  }
21260
+ if (!VALID_INSTALL_METHODS.has(platform.installMethod)) {
21261
+ throw new Error(`platform registry: ${label} has illegal installMethod "${platform.installMethod}"`);
21262
+ }
21263
+ if (!VALID_REF_STRENGTHS.has(platform.refStrength)) {
21264
+ throw new Error(`platform registry: ${label} has illegal refStrength "${platform.refStrength}"`);
21265
+ }
21266
+ if (!VALID_OUTPUT_PROTOCOLS.has(platform.outputProtocol)) {
21267
+ throw new Error(`platform registry: ${label} has illegal outputProtocol "${platform.outputProtocol}"`);
21268
+ }
21269
+ if (!VALID_IDENTITY_EVIDENCE.has(platform.identityEvidence)) {
21270
+ throw new Error(`platform registry: ${label} has illegal identityEvidence "${platform.identityEvidence}"`);
21271
+ }
21272
+ if (!VALID_DEGRADATION_POLICIES.has(platform.degradationPolicy)) {
21273
+ throw new Error(`platform registry: ${label} has illegal degradationPolicy "${platform.degradationPolicy}"`);
21274
+ }
21232
21275
  if (platform.automatable) {
21233
21276
  if (!platform.cli || typeof platform.cli.marketplaceAdd !== "function" || typeof platform.cli.install !== "function" || typeof platform.cli.list !== "function") {
21234
21277
  throw new Error(`platform registry: automatable platform ${label} needs cli template functions`);
@@ -21253,9 +21296,75 @@ function assertRegistry(registry = PLATFORMS) {
21253
21296
  throw new Error(`platform registry: non-automatable platform ${label} needs strategy.readManifest`);
21254
21297
  }
21255
21298
  }
21299
+ if (platform.automatable === true && platform.installMethod !== "structured-cli") {
21300
+ throw new Error(`platform registry: ${label} is automatable but installMethod is "${platform.installMethod}" (expected "structured-cli")`);
21301
+ }
21302
+ if (platform.automatable === false && platform.installMethod === "structured-cli") {
21303
+ throw new Error(`platform registry: ${label} is not automatable but installMethod is "structured-cli"`);
21304
+ }
21305
+ if (platform.installMethod === "structured-cli" && platform.refStrength === "unfixable") {
21306
+ throw new Error(`platform registry: ${label} has structured-cli install but unfixable refStrength`);
21307
+ }
21308
+ if (platform.installMethod === "human-attestation" && platform.identityEvidence !== "human-attestation") {
21309
+ throw new Error(`platform registry: ${label} has human-attestation install but identityEvidence is "${platform.identityEvidence}"`);
21310
+ }
21311
+ }
21312
+ }
21313
+ function resolvePlatformRoute(platform) {
21314
+ const { installMethod } = platform;
21315
+ if (installMethod === "structured-cli") {
21316
+ return { route: "structured-cli", reason: `installMethod is structured-cli` };
21317
+ }
21318
+ if (installMethod === "interactive-only" || installMethod === "human-attestation") {
21319
+ return { route: "human-attestation", reason: `installMethod is ${installMethod}` };
21256
21320
  }
21321
+ throw new Error(
21322
+ `platform "${platform?.id ?? "<unknown>"}" with installMethod="${installMethod}" cannot be routed`
21323
+ );
21257
21324
  }
21258
- var CLAUDE, CODEX, KIMI, CODEBUDDY, PLATFORMS, VALID_DISTRIBUTION_TYPES, VALID_ACTION_TYPES, VALID_SOURCE_FORMS, VALID_MARKETPLACE_REF_FORMS, VALID_LIST_OUTPUTS, VALID_CLI_OUTPUTS, VALID_ENTRY_VERSION_BINDING;
21325
+ function resolveCapabilityConflicts(platform) {
21326
+ const conflicts = [];
21327
+ const { id, automatable, installMethod, refStrength, identityEvidence, cli, strategy } = platform;
21328
+ if (automatable === true && installMethod !== "structured-cli") {
21329
+ conflicts.push(`automatable=true but installMethod="${installMethod}"`);
21330
+ }
21331
+ if (automatable === false && installMethod === "structured-cli") {
21332
+ conflicts.push(`automatable=false but installMethod="structured-cli"`);
21333
+ }
21334
+ if (installMethod === "structured-cli" && refStrength === "unfixable") {
21335
+ conflicts.push(`structured-cli with unfixable refStrength`);
21336
+ }
21337
+ if (installMethod === "human-attestation" && identityEvidence !== "human-attestation") {
21338
+ conflicts.push(`human-attestation install but identityEvidence="${identityEvidence}"`);
21339
+ }
21340
+ if (automatable === true) {
21341
+ if (!cli || typeof cli !== "object") {
21342
+ conflicts.push(`automatable=true but cli is missing`);
21343
+ }
21344
+ if (!strategy || typeof strategy.parseListOutput !== "function") {
21345
+ conflicts.push(`automatable=true but strategy.parseListOutput is missing`);
21346
+ }
21347
+ if (!strategy || typeof strategy.extractInstallPath !== "function") {
21348
+ conflicts.push(`automatable=true but strategy.extractInstallPath is missing`);
21349
+ }
21350
+ }
21351
+ if (automatable === false) {
21352
+ if (cli !== null) {
21353
+ conflicts.push(`automatable=false but cli is not null`);
21354
+ }
21355
+ if (!strategy || typeof strategy.buildManualRequirement !== "function") {
21356
+ conflicts.push(`automatable=false but strategy.buildManualRequirement is missing`);
21357
+ }
21358
+ if (!strategy || typeof strategy.readManifest !== "function") {
21359
+ conflicts.push(`automatable=false but strategy.readManifest is missing`);
21360
+ }
21361
+ }
21362
+ if (conflicts.length > 0) {
21363
+ throw new Error(`capability conflict in platform "${id}": ${conflicts.join("; ")}`);
21364
+ }
21365
+ return { hasConflict: false, conflicts: [] };
21366
+ }
21367
+ var CLAUDE, CODEX, KIMI, CODEBUDDY, PLATFORMS, VALID_DISTRIBUTION_TYPES, VALID_ACTION_TYPES, VALID_SOURCE_FORMS, VALID_MARKETPLACE_REF_FORMS, VALID_LIST_OUTPUTS, VALID_CLI_OUTPUTS, VALID_ENTRY_VERSION_BINDING, VALID_INSTALL_METHODS, VALID_REF_STRENGTHS, VALID_OUTPUT_PROTOCOLS, VALID_IDENTITY_EVIDENCE, VALID_DEGRADATION_POLICIES;
21259
21368
  var init_registry = __esm({
21260
21369
  async "src/platforms/registry.mjs"() {
21261
21370
  await init_kimi();
@@ -21276,6 +21385,12 @@ var init_registry = __esm({
21276
21385
  // actionType -> adapter map from it (T2.2 step 3).
21277
21386
  adapter: "plugin-marketplace",
21278
21387
  automatable: true,
21388
+ // --- capability contract (平台能力契约) ------------------------------------
21389
+ installMethod: "structured-cli",
21390
+ refStrength: "name-ref",
21391
+ outputProtocol: "text",
21392
+ identityEvidence: "list-record",
21393
+ degradationPolicy: "block",
21279
21394
  cli: Object.freeze({
21280
21395
  binary: "claude",
21281
21396
  marketplaceAdd: /* @__PURE__ */ __name((repo, ref) => ["plugin", "marketplace", "add", `${repo}@${ref}`], "marketplaceAdd"),
@@ -21328,6 +21443,12 @@ var init_registry = __esm({
21328
21443
  actionType: "codex-marketplace-install",
21329
21444
  adapter: "plugin-marketplace",
21330
21445
  automatable: true,
21446
+ // --- capability contract (平台能力契约) ------------------------------------
21447
+ installMethod: "structured-cli",
21448
+ refStrength: "commit-sha",
21449
+ outputProtocol: "structured",
21450
+ identityEvidence: "install-output",
21451
+ degradationPolicy: "block",
21331
21452
  cli: Object.freeze({
21332
21453
  binary: "codex",
21333
21454
  marketplaceAdd: /* @__PURE__ */ __name((repo, ref) => ["plugin", "marketplace", "add", repo, "--ref", ref, "--json"], "marketplaceAdd"),
@@ -21379,6 +21500,12 @@ var init_registry = __esm({
21379
21500
  actionType: "kimi-marketplace-install",
21380
21501
  adapter: "plugin-marketplace",
21381
21502
  automatable: false,
21503
+ // --- capability contract (平台能力契约) ------------------------------------
21504
+ installMethod: "interactive-only",
21505
+ refStrength: "unfixable",
21506
+ outputProtocol: "none",
21507
+ identityEvidence: "filesystem-payload",
21508
+ degradationPolicy: "human-attestation",
21382
21509
  cli: null,
21383
21510
  jsonProtocol: Object.freeze({
21384
21511
  listOutput: null,
@@ -21430,6 +21557,12 @@ var init_registry = __esm({
21430
21557
  actionType: "codebuddy-marketplace-install",
21431
21558
  adapter: "plugin-marketplace",
21432
21559
  automatable: false,
21560
+ // --- capability contract (平台能力契约) ------------------------------------
21561
+ installMethod: "human-attestation",
21562
+ refStrength: "unfixable",
21563
+ outputProtocol: "none",
21564
+ identityEvidence: "human-attestation",
21565
+ degradationPolicy: "human-attestation",
21433
21566
  cli: null,
21434
21567
  jsonProtocol: Object.freeze({
21435
21568
  listOutput: null,
@@ -21493,9 +21626,16 @@ var init_registry = __esm({
21493
21626
  VALID_LIST_OUTPUTS = /* @__PURE__ */ new Set(["array", "installed-object", null]);
21494
21627
  VALID_CLI_OUTPUTS = /* @__PURE__ */ new Set(["json", null]);
21495
21628
  VALID_ENTRY_VERSION_BINDING = /* @__PURE__ */ new Set([true, false, null]);
21629
+ VALID_INSTALL_METHODS = /* @__PURE__ */ new Set(["structured-cli", "interactive-only", "human-attestation"]);
21630
+ VALID_REF_STRENGTHS = /* @__PURE__ */ new Set(["commit-sha", "name-ref", "unfixable"]);
21631
+ VALID_OUTPUT_PROTOCOLS = /* @__PURE__ */ new Set(["structured", "text", "none"]);
21632
+ VALID_IDENTITY_EVIDENCE = /* @__PURE__ */ new Set(["list-record", "install-output", "filesystem-payload", "human-attestation"]);
21633
+ VALID_DEGRADATION_POLICIES = /* @__PURE__ */ new Set(["block", "human-attestation"]);
21496
21634
  __name(getPlatform, "getPlatform");
21497
21635
  __name(assertRegistry, "assertRegistry");
21498
21636
  assertRegistry();
21637
+ __name(resolvePlatformRoute, "resolvePlatformRoute");
21638
+ __name(resolveCapabilityConflicts, "resolveCapabilityConflicts");
21499
21639
  }
21500
21640
  });
21501
21641
 
@@ -22086,6 +22226,140 @@ function validatePlanActionCompleteness(plan, options = {}) {
22086
22226
  }
22087
22227
  }
22088
22228
  }
22229
+ if (production) {
22230
+ _checkRequired(action, "parameters.sourceCommit", action.parameters?.sourceCommit, frozen?.commit, unitId, failures);
22231
+ }
22232
+ if (requiresMarketplace) {
22233
+ const sd = action.parameters?.sourceDescriptor;
22234
+ const mf = action.parameters?.marketplaceForm;
22235
+ if (sd === void 0 || sd === null) {
22236
+ if (!options.legacyCompatibility) {
22237
+ failures.push(
22238
+ `unit "${unitId}", action "${action.id}": parameters.sourceDescriptor is missing; every marketplace install action must carry a complete source descriptor`
22239
+ );
22240
+ }
22241
+ } else if (typeof sd === "object") {
22242
+ if (mf === void 0 || mf === null) {
22243
+ failures.push(
22244
+ `unit "${unitId}", action "${action.id}": parameters.marketplaceForm is missing but sourceDescriptor is present; form must be explicitly declared`
22245
+ );
22246
+ }
22247
+ if (sd.form !== mf) {
22248
+ failures.push(
22249
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.form "${sd.form}" does not match parameters.marketplaceForm "${mf}"`
22250
+ );
22251
+ }
22252
+ const BUNDLED_REQUIRED = ["form", "repo", "marketplaceEntry", "pluginSubpath"];
22253
+ const STANDALONE_REQUIRED = ["form", "marketplaceRepo", "marketplaceEntry", "pluginRepo", "sourceType"];
22254
+ const PROD_ONLY_FIELDS = ["marketplaceCommitSha", "ref", "payloadDigest"];
22255
+ if (sd.form === "bundled-family") {
22256
+ for (const field of BUNDLED_REQUIRED) {
22257
+ if (sd[field] === void 0 || sd[field] === null) {
22258
+ failures.push(
22259
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.${field} is missing or null; bundled-family form requires all identity fields to be non-null`
22260
+ );
22261
+ }
22262
+ }
22263
+ if (production && (sd.commit === void 0 || sd.commit === null)) {
22264
+ failures.push(
22265
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.commit is missing or null; production bundled-family plans require a frozen commit`
22266
+ );
22267
+ }
22268
+ if (production && sd.commit !== void 0 && sd.commit !== null && frozen?.commit !== void 0 && sd.commit !== frozen.commit) {
22269
+ failures.push(
22270
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.commit does not match frozenSnapshot.commit`
22271
+ );
22272
+ }
22273
+ if (production && (sd.payloadDigest === void 0 || sd.payloadDigest === null)) {
22274
+ failures.push(
22275
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.payloadDigest is missing or null; production plans require a frozen payload digest`
22276
+ );
22277
+ }
22278
+ const STANDALONE_ONLY = ["marketplaceRepo", "pluginRepo", "sourceType", "marketplaceCommitSha", "ref"];
22279
+ for (const field of STANDALONE_ONLY) {
22280
+ if (sd[field] !== void 0) {
22281
+ failures.push(
22282
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.${field} is unexpected for bundled-family form; mixed fields are prohibited`
22283
+ );
22284
+ }
22285
+ }
22286
+ if (sd.repo !== void 0 && sd.repo !== null && sd.repo !== publicRepo) {
22287
+ failures.push(
22288
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.repo "${sd.repo}" does not match unit publicRepo "${publicRepo}"`
22289
+ );
22290
+ }
22291
+ if (sd.marketplaceEntry !== void 0 && sd.marketplaceEntry !== null && sd.marketplaceEntry !== plugin) {
22292
+ failures.push(
22293
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.marketplaceEntry "${sd.marketplaceEntry}" does not match action plugin "${plugin}"`
22294
+ );
22295
+ }
22296
+ if (production && sd.payloadDigest !== void 0 && sd.payloadDigest !== null && frozen?.manifestDigest !== void 0 && sd.payloadDigest !== frozen.manifestDigest) {
22297
+ failures.push(
22298
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.payloadDigest does not match frozen manifestDigest`
22299
+ );
22300
+ }
22301
+ } else if (sd.form === "standalone-index") {
22302
+ for (const field of STANDALONE_REQUIRED) {
22303
+ if (sd[field] === void 0 || sd[field] === null) {
22304
+ failures.push(
22305
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.${field} is missing or null; standalone-index form requires all identity fields to be non-null`
22306
+ );
22307
+ }
22308
+ }
22309
+ if (production) {
22310
+ for (const field of PROD_ONLY_FIELDS) {
22311
+ if (sd[field] === void 0 || sd[field] === null) {
22312
+ failures.push(
22313
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.${field} is missing or null; production standalone-index requires all fields to be non-null`
22314
+ );
22315
+ }
22316
+ }
22317
+ }
22318
+ const BUNDLED_ONLY = ["repo", "commit", "pluginSubpath"];
22319
+ for (const field of BUNDLED_ONLY) {
22320
+ if (sd[field] !== void 0) {
22321
+ failures.push(
22322
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.${field} is unexpected for standalone-index form; mixed fields are prohibited`
22323
+ );
22324
+ }
22325
+ }
22326
+ if (sd.pluginRepo !== void 0 && sd.pluginRepo !== null && sd.marketplaceRepo !== void 0 && sd.marketplaceRepo !== null && sd.pluginRepo === sd.marketplaceRepo) {
22327
+ failures.push(
22328
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.pluginRepo must not equal marketplaceRepo; the plugin repo and marketplace repo are distinct repositories`
22329
+ );
22330
+ }
22331
+ if (externalMarketplace && sd.marketplaceRepo !== void 0 && sd.marketplaceRepo !== null && sd.marketplaceRepo !== dist.marketplaceRepo) {
22332
+ failures.push(
22333
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.marketplaceRepo "${sd.marketplaceRepo}" does not match distribution marketplaceRepo "${dist.marketplaceRepo}"`
22334
+ );
22335
+ }
22336
+ if (sd.pluginRepo !== void 0 && sd.pluginRepo !== null && sd.pluginRepo !== publicRepo) {
22337
+ failures.push(
22338
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.pluginRepo "${sd.pluginRepo}" does not match unit publicRepo "${publicRepo}"`
22339
+ );
22340
+ }
22341
+ if (sd.marketplaceEntry !== void 0 && sd.marketplaceEntry !== null && sd.marketplaceEntry !== plugin) {
22342
+ failures.push(
22343
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.marketplaceEntry "${sd.marketplaceEntry}" does not match action plugin "${plugin}"`
22344
+ );
22345
+ }
22346
+ if (sd.sourceType !== void 0 && sd.sourceType !== null && sd.sourceType !== "marketplace-entry") {
22347
+ failures.push(
22348
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.sourceType "${sd.sourceType}" is unexpected; standalone-index sourceType must be "marketplace-entry"`
22349
+ );
22350
+ }
22351
+ if (production && sd.payloadDigest !== void 0 && sd.payloadDigest !== null && frozen?.manifestDigest !== void 0 && sd.payloadDigest !== frozen.manifestDigest) {
22352
+ failures.push(
22353
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.payloadDigest does not match frozen manifestDigest`
22354
+ );
22355
+ }
22356
+ } else {
22357
+ failures.push(
22358
+ `unit "${unitId}", action "${action.id}": sourceDescriptor.form "${sd.form}" is unknown; expected "bundled-family" or "standalone-index"`
22359
+ );
22360
+ }
22361
+ }
22362
+ }
22089
22363
  _checkRequired(action, "expected.installed", action.expected?.installed, true, unitId, failures);
22090
22364
  _checkRequired(action, "expected.plugin", action.expected?.plugin, plugin, unitId, failures);
22091
22365
  if (requiresMarketplace) {
@@ -75388,6 +75662,28 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
75388
75662
  const requiresMarketplace = platform.schemaRequiredFields.includes("marketplace");
75389
75663
  const timeoutMs = Number.isInteger(dist.timeoutMs) ? dist.timeoutMs : 3e5;
75390
75664
  const externalMarketplace = dist.marketplaceRepo !== void 0 && dist.marketplaceRepo !== null;
75665
+ const marketplaceForm = requiresMarketplace ? externalMarketplace ? "standalone-index" : "bundled-family" : null;
75666
+ const sourceDescriptor = marketplaceForm === "standalone-index" ? Object.freeze({
75667
+ form: "standalone-index",
75668
+ marketplaceRepo: dist.marketplaceRepo,
75669
+ marketplaceEntry: dist.plugin,
75670
+ // pluginRepo is the plugin's own public repo, NOT the external
75671
+ // marketplace repo. The marketplace repo contains the index; the
75672
+ // plugin repo contains the actual plugin code.
75673
+ pluginRepo: unit.publicRepo,
75674
+ sourceType: "marketplace-entry",
75675
+ // Production-only fields: marketplaceCommitSha and ref are frozen
75676
+ // by resolveExternalMarketplaceFreezes in the production path.
75677
+ marketplaceCommitSha: null,
75678
+ ref: null,
75679
+ payloadDigest: null
75680
+ }) : marketplaceForm === "bundled-family" ? Object.freeze({
75681
+ form: "bundled-family",
75682
+ repo: unit.publicRepo,
75683
+ marketplaceEntry: dist.plugin,
75684
+ pluginSubpath: ".",
75685
+ payloadDigest: null
75686
+ }) : null;
75391
75687
  actions.push({
75392
75688
  id: `${platform.actionType}-${unit.id}`,
75393
75689
  type: platform.actionType,
@@ -75408,7 +75704,9 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
75408
75704
  // External marketplace form uses the external-marketplace-v1
75409
75705
  // contract (whole-tree '.' containment; see plugin-marketplace).
75410
75706
  payloadContract: externalMarketplace ? "external-marketplace-v1" : "declared-manifest-v1",
75411
- ...externalMarketplace ? { marketplaceLocation: "external" } : {}
75707
+ ...externalMarketplace ? { marketplaceLocation: "external" } : {},
75708
+ ...marketplaceForm ? { marketplaceForm } : {},
75709
+ ...sourceDescriptor ? { sourceDescriptor } : {}
75412
75710
  },
75413
75711
  expected: {
75414
75712
  installed: true,
@@ -75553,6 +75851,27 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
75553
75851
  const timeoutMs = Number.isInteger(dist.timeoutMs) ? dist.timeoutMs : 3e5;
75554
75852
  const externalMarketplace = dist.marketplaceRepo !== void 0 && dist.marketplaceRepo !== null;
75555
75853
  const freeze = externalMarketplace ? externalFreezes.get(`${unit.id} ${dist.type}`) : null;
75854
+ const marketplaceForm = requiresMarketplace ? externalMarketplace ? "standalone-index" : "bundled-family" : null;
75855
+ const sourceDescriptor = marketplaceForm === "standalone-index" ? Object.freeze({
75856
+ form: "standalone-index",
75857
+ marketplaceRepo: dist.marketplaceRepo,
75858
+ marketplaceCommitSha: freeze?.marketplaceCommitSha ?? null,
75859
+ marketplaceEntry: dist.plugin,
75860
+ // pluginRepo is the plugin's own public repo, NOT the external
75861
+ // marketplace repo. The marketplace repo contains the index; the
75862
+ // plugin repo contains the actual plugin code.
75863
+ pluginRepo: unit.publicRepo,
75864
+ sourceType: "marketplace-entry",
75865
+ ref: freeze?.ref ?? null,
75866
+ payloadDigest: asset.manifestDigest
75867
+ }) : marketplaceForm === "bundled-family" ? Object.freeze({
75868
+ form: "bundled-family",
75869
+ repo: unit.publicRepo,
75870
+ commit: asset.commit,
75871
+ marketplaceEntry: dist.plugin,
75872
+ pluginSubpath: ".",
75873
+ payloadDigest: asset.manifestDigest
75874
+ }) : null;
75556
75875
  actions.push({
75557
75876
  id: `${platform.actionType}-${unit.id}`,
75558
75877
  type: platform.actionType,
@@ -75576,7 +75895,13 @@ function buildExternalActions(unitResults, resolvedVersions, productionAssets, e
75576
75895
  // External marketplace form uses the external-marketplace-v1
75577
75896
  // contract (whole-tree '.' containment; see plugin-marketplace).
75578
75897
  payloadContract: externalMarketplace ? "external-marketplace-v1" : "declared-manifest-v1",
75579
- ...externalMarketplace ? { marketplaceLocation: "external", marketplaceCommitSha: freeze.marketplaceCommitSha } : {}
75898
+ ...externalMarketplace ? { marketplaceLocation: "external", marketplaceCommitSha: freeze.marketplaceCommitSha } : {},
75899
+ ...marketplaceForm ? { marketplaceForm } : {},
75900
+ ...sourceDescriptor ? { sourceDescriptor } : {},
75901
+ // 冻结的插件来源提交,用于 sourceDescriptor.commit 交叉校验。
75902
+ // bundled-family: sourceDescriptor.commit 绑定到此值。
75903
+ // standalone-index: 通过此值绑定插件载荷来源。
75904
+ sourceCommit: asset.commit
75580
75905
  },
75581
75906
  expected: {
75582
75907
  installed: true,
@@ -78874,16 +79199,29 @@ async function resolveKimiEntrySkillFile(pluginRootReal, manifest, entrySkill) {
78874
79199
  return entryReal;
78875
79200
  }
78876
79201
  function normalizeCodeBuddySkillsRel(skillsRaw) {
78877
- if (typeof skillsRaw !== "string" || skillsRaw.length === 0) {
79202
+ let skillsPath;
79203
+ if (Array.isArray(skillsRaw)) {
79204
+ if (skillsRaw.length !== 1) {
79205
+ throw new Error(
79206
+ `codebuddy manifest skills array must have exactly one element, got ${skillsRaw.length}`
79207
+ );
79208
+ }
79209
+ skillsPath = skillsRaw[0];
79210
+ } else if (typeof skillsRaw === "string") {
79211
+ skillsPath = skillsRaw;
79212
+ } else {
79213
+ throw new Error("codebuddy manifest skills must be a string or single-element array when present");
79214
+ }
79215
+ if (typeof skillsPath !== "string" || skillsPath.length === 0) {
78878
79216
  throw new Error("codebuddy manifest skills must be a non-empty relative path when present");
78879
79217
  }
78880
- if (skillsRaw.startsWith("/") || skillsRaw.includes("..") || skillsRaw.includes("\\") || /^https?:\/\//i.test(skillsRaw)) {
78881
- throw new Error(`codebuddy manifest skills "${skillsRaw}" is not a safe relative path`);
79218
+ if (skillsPath.startsWith("/") || skillsPath.includes("..") || skillsPath.includes("\\") || /^https?:\/\//i.test(skillsPath)) {
79219
+ throw new Error(`codebuddy manifest skills "${skillsPath}" is not a safe relative path`);
78882
79220
  }
78883
- let rel = skillsRaw.replace(/^\.\//, "");
79221
+ let rel = skillsPath.replace(/^\.\//, "");
78884
79222
  rel = rel.replace(/\/+$/, "");
78885
79223
  if (rel.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
78886
- throw new Error(`codebuddy manifest skills "${skillsRaw}" is not a safe relative path`);
79224
+ throw new Error(`codebuddy manifest skills "${skillsPath}" is not a safe relative path`);
78887
79225
  }
78888
79226
  return rel;
78889
79227
  }
@@ -78984,7 +79322,9 @@ function validateMarketplaceParams(params) {
78984
79322
  if (!plugin || !SAFE_ID_RE.test(plugin)) {
78985
79323
  return { valid: false, error: `unsafe plugin identifier: "${plugin}"` };
78986
79324
  }
78987
- if (!getPlatform(consumer).automatable) {
79325
+ const consumerPlatform = getPlatform(consumer);
79326
+ const consumerRoute = resolvePlatformRoute(consumerPlatform);
79327
+ if (consumerRoute.route === "human-attestation") {
78988
79328
  if (marketplace !== void 0 && marketplace !== null && !SAFE_ID_RE.test(marketplace)) {
78989
79329
  return { valid: false, error: `unsafe marketplace identifier: "${marketplace}"` };
78990
79330
  }
@@ -79173,7 +79513,191 @@ function createPluginMarketplaceAdapter(deps = {}) {
79173
79513
  });
79174
79514
  }
79175
79515
  const consumer = action.consumer;
79516
+ const consumerPlatform = getPlatform(consumer);
79517
+ const capabilityConflicts = resolveCapabilityConflicts(consumerPlatform);
79518
+ if (capabilityConflicts.length > 0) {
79519
+ return createResult({
79520
+ actionType,
79521
+ status: ActionStatus.PREFLIGHT_FAILED,
79522
+ error: `platform capability conflict: ${capabilityConflicts.join("; ")}`
79523
+ });
79524
+ }
79525
+ const route = resolvePlatformRoute(consumerPlatform);
79526
+ if (route.route === "structured-cli") {
79527
+ const sd = action.sourceDescriptor;
79528
+ if (!sd || typeof sd !== "object") {
79529
+ return createResult({
79530
+ actionType,
79531
+ status: ActionStatus.PREFLIGHT_FAILED,
79532
+ error: "sourceDescriptor is required for marketplace install"
79533
+ });
79534
+ }
79535
+ if (sd.form !== action.marketplaceForm) {
79536
+ return createResult({
79537
+ actionType,
79538
+ status: ActionStatus.PREFLIGHT_FAILED,
79539
+ error: `sourceDescriptor.form "${sd.form}" does not match marketplaceForm "${action.marketplaceForm}"`
79540
+ });
79541
+ }
79542
+ if (typeof sd.payloadDigest !== "string" || sd.payloadDigest.length === 0) {
79543
+ return createResult({
79544
+ actionType,
79545
+ status: ActionStatus.PREFLIGHT_FAILED,
79546
+ error: "sourceDescriptor.payloadDigest is required"
79547
+ });
79548
+ }
79549
+ if (!/^[a-f0-9]{64}$/.test(sd.payloadDigest)) {
79550
+ return createResult({
79551
+ actionType,
79552
+ status: ActionStatus.PREFLIGHT_FAILED,
79553
+ error: "sourceDescriptor.payloadDigest must be a 64-char lowercase hex string"
79554
+ });
79555
+ }
79556
+ if (sd.payloadDigest === "0".repeat(64)) {
79557
+ return createResult({
79558
+ actionType,
79559
+ status: ActionStatus.PREFLIGHT_FAILED,
79560
+ error: "sourceDescriptor.payloadDigest must not be the null hash"
79561
+ });
79562
+ }
79563
+ if (typeof sd.marketplaceEntry !== "string" || sd.marketplaceEntry.length === 0) {
79564
+ return createResult({
79565
+ actionType,
79566
+ status: ActionStatus.PREFLIGHT_FAILED,
79567
+ error: "sourceDescriptor.marketplaceEntry is required"
79568
+ });
79569
+ }
79570
+ if (sd.marketplaceEntry !== action.plugin) {
79571
+ return createResult({
79572
+ actionType,
79573
+ status: ActionStatus.PREFLIGHT_FAILED,
79574
+ error: `sourceDescriptor.marketplaceEntry "${sd.marketplaceEntry}" does not match action plugin "${action.plugin}"`
79575
+ });
79576
+ }
79577
+ if (sd.form === "bundled-family") {
79578
+ if (!sd.repo || !SAFE_REPO_RE.test(sd.repo)) {
79579
+ return createResult({
79580
+ actionType,
79581
+ status: ActionStatus.PREFLIGHT_FAILED,
79582
+ error: `sourceDescriptor.repo is required and must be a safe repo pattern`
79583
+ });
79584
+ }
79585
+ if (sd.repo !== action.repo) {
79586
+ return createResult({
79587
+ actionType,
79588
+ status: ActionStatus.PREFLIGHT_FAILED,
79589
+ error: `sourceDescriptor.repo "${sd.repo}" does not match action.repo "${action.repo}"`
79590
+ });
79591
+ }
79592
+ if (sd.commit !== void 0 && (typeof sd.commit !== "string" || !/^[0-9a-f]{40}$/.test(sd.commit))) {
79593
+ return createResult({
79594
+ actionType,
79595
+ status: ActionStatus.PREFLIGHT_FAILED,
79596
+ error: "sourceDescriptor.commit must be a 40-hex commit sha for bundled-family form"
79597
+ });
79598
+ }
79599
+ if (sd.commit !== void 0 && action.sourceCommit && sd.commit !== action.sourceCommit) {
79600
+ return createResult({
79601
+ actionType,
79602
+ status: ActionStatus.PREFLIGHT_FAILED,
79603
+ error: `sourceDescriptor.commit "${sd.commit}" does not match action.sourceCommit "${action.sourceCommit}"`
79604
+ });
79605
+ }
79606
+ if (sd.payloadDigest !== void 0 && (!sd.payloadDigest || !SAFE_DIGEST_RE.test(sd.payloadDigest))) {
79607
+ return createResult({
79608
+ actionType,
79609
+ status: ActionStatus.PREFLIGHT_FAILED,
79610
+ error: "sourceDescriptor.payloadDigest is required for bundled-family form"
79611
+ });
79612
+ }
79613
+ if (sd.payloadDigest !== void 0 && action.manifestDigest && sd.payloadDigest !== action.manifestDigest) {
79614
+ return createResult({
79615
+ actionType,
79616
+ status: ActionStatus.PREFLIGHT_FAILED,
79617
+ error: `sourceDescriptor.payloadDigest does not match action.manifestDigest`
79618
+ });
79619
+ }
79620
+ if (typeof sd.pluginSubpath !== "string" || sd.pluginSubpath.length === 0) {
79621
+ return createResult({
79622
+ actionType,
79623
+ status: ActionStatus.PREFLIGHT_FAILED,
79624
+ error: "sourceDescriptor.pluginSubpath is required for bundled-family form"
79625
+ });
79626
+ }
79627
+ } else if (sd.form === "standalone-index") {
79628
+ if (!sd.pluginRepo || !SAFE_REPO_RE.test(sd.pluginRepo)) {
79629
+ return createResult({
79630
+ actionType,
79631
+ status: ActionStatus.PREFLIGHT_FAILED,
79632
+ error: `sourceDescriptor.pluginRepo is required for standalone-index form`
79633
+ });
79634
+ }
79635
+ if (!sd.marketplaceRepo || !SAFE_REPO_RE.test(sd.marketplaceRepo)) {
79636
+ return createResult({
79637
+ actionType,
79638
+ status: ActionStatus.PREFLIGHT_FAILED,
79639
+ error: "sourceDescriptor.marketplaceRepo is required for standalone-index form"
79640
+ });
79641
+ }
79642
+ if (sd.marketplaceRepo !== action.repo) {
79643
+ return createResult({
79644
+ actionType,
79645
+ status: ActionStatus.PREFLIGHT_FAILED,
79646
+ error: `sourceDescriptor.marketplaceRepo "${sd.marketplaceRepo}" does not match action.repo "${action.repo}"`
79647
+ });
79648
+ }
79649
+ if (sd.pluginRepo === sd.marketplaceRepo) {
79650
+ return createResult({
79651
+ actionType,
79652
+ status: ActionStatus.PREFLIGHT_FAILED,
79653
+ error: `sourceDescriptor.pluginRepo "${sd.pluginRepo}" must differ from marketplaceRepo "${sd.marketplaceRepo}"`
79654
+ });
79655
+ }
79656
+ if (typeof sd.marketplaceCommitSha !== "string" || !/^[0-9a-f]{40}$/.test(sd.marketplaceCommitSha)) {
79657
+ return createResult({
79658
+ actionType,
79659
+ status: ActionStatus.PREFLIGHT_FAILED,
79660
+ error: "sourceDescriptor.marketplaceCommitSha must be a 40-hex commit sha for standalone-index form"
79661
+ });
79662
+ }
79663
+ if (action.marketplaceCommitSha && sd.marketplaceCommitSha !== action.marketplaceCommitSha) {
79664
+ return createResult({
79665
+ actionType,
79666
+ status: ActionStatus.PREFLIGHT_FAILED,
79667
+ error: `sourceDescriptor.marketplaceCommitSha "${sd.marketplaceCommitSha}" does not match action.marketplaceCommitSha "${action.marketplaceCommitSha}"`
79668
+ });
79669
+ }
79670
+ if (typeof sd.ref !== "string" || sd.ref.length === 0) {
79671
+ return createResult({
79672
+ actionType,
79673
+ status: ActionStatus.PREFLIGHT_FAILED,
79674
+ error: "sourceDescriptor.ref is required for standalone-index form"
79675
+ });
79676
+ }
79677
+ if (sd.payloadDigest !== void 0 && (!sd.payloadDigest || !SAFE_DIGEST_RE.test(sd.payloadDigest))) {
79678
+ return createResult({
79679
+ actionType,
79680
+ status: ActionStatus.PREFLIGHT_FAILED,
79681
+ error: "sourceDescriptor.payloadDigest must be a 64-hex digest for standalone-index form"
79682
+ });
79683
+ }
79684
+ if (sd.payloadDigest !== void 0 && action.manifestDigest && sd.payloadDigest !== action.manifestDigest) {
79685
+ return createResult({
79686
+ actionType,
79687
+ status: ActionStatus.PREFLIGHT_FAILED,
79688
+ error: `sourceDescriptor.payloadDigest does not match action.manifestDigest`
79689
+ });
79690
+ }
79691
+ } else {
79692
+ return createResult({
79693
+ actionType,
79694
+ status: ActionStatus.PREFLIGHT_FAILED,
79695
+ error: `sourceDescriptor.form "${sd.form}" is not a recognized form (expected "bundled-family" or "standalone-index")`
79696
+ });
79697
+ }
79698
+ }
79176
79699
  const platform = getPlatform(consumer);
79700
+ const platformRoute = resolvePlatformRoute(platform);
79177
79701
  let snapshotDirReal;
79178
79702
  let kimiSnapshotManifest = null;
79179
79703
  try {
@@ -79185,7 +79709,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
79185
79709
  error: `frozen snapshot validation failed: ${frozenErr.message}`
79186
79710
  });
79187
79711
  }
79188
- if (!platform.automatable) {
79712
+ if (platformRoute.route === "human-attestation") {
79189
79713
  const manifestLabel = consumer === "codebuddy" ? "codebuddy" : "kimi";
79190
79714
  let kimiManifestResult;
79191
79715
  try {
@@ -79214,7 +79738,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
79214
79738
  }
79215
79739
  kimiSnapshotManifest = kimiManifest;
79216
79740
  }
79217
- if (platform.automatable) {
79741
+ if (platformRoute.route === "structured-cli") {
79218
79742
  if (action.marketplaceLocation === "external") {
79219
79743
  if (typeof action.marketplaceCommitSha !== "string" || !/^[0-9a-f]{40}$/.test(action.marketplaceCommitSha)) {
79220
79744
  return createResult({
@@ -79357,7 +79881,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
79357
79881
  }
79358
79882
  }
79359
79883
  }
79360
- if (!platform.automatable) {
79884
+ if (platformRoute.route === "human-attestation") {
79361
79885
  const resolveEntrySkillFile = consumer === "codebuddy" ? resolveCodeBuddyEntrySkillFile : resolveKimiEntrySkillFile;
79362
79886
  try {
79363
79887
  await resolveEntrySkillFile(snapshotDirReal, kimiSnapshotManifest, action.entrySkill);
@@ -79528,7 +80052,8 @@ function createPluginMarketplaceAdapter(deps = {}) {
79528
80052
  });
79529
80053
  }
79530
80054
  const platform = getPlatform(action.consumer);
79531
- if (!platform.automatable) {
80055
+ const executeRoute = resolvePlatformRoute(platform);
80056
+ if (executeRoute.route === "human-attestation") {
79532
80057
  return platform.strategy.buildManualRequirement(action, context);
79533
80058
  }
79534
80059
  const consumer = action.consumer;
@@ -79797,11 +80322,16 @@ function createPluginMarketplaceAdapter(deps = {}) {
79797
80322
  }
79798
80323
  const isolatedHome = resolve21(runDir, "consumers", `${consumer}-${action.plugin}`);
79799
80324
  const platform = PLATFORMS.find((p) => p.id === consumer) ?? null;
79800
- const cliCmd = platform ? platform.cli ? platform.cli.binary : null : "kimi";
80325
+ if (!platform) {
80326
+ throw new Error(
80327
+ `Unknown consumer platform "${consumer}" for action "${actionType}". Registered platforms: ${PLATFORMS.map((p) => p.id).join(", ")}`
80328
+ );
80329
+ }
80330
+ const cliCmd = platform.cli ? platform.cli.binary : null;
79801
80331
  const baseEnv = { ...process.env, ...context.env ?? {} };
79802
80332
  const env = {
79803
80333
  ...baseEnv,
79804
- ...platform ? platform.isolationEnv(isolatedHome) : { HOME: isolatedHome, KIMI_CODE_HOME: isolatedHome }
80334
+ ...platform.isolationEnv(isolatedHome)
79805
80335
  };
79806
80336
  let frozenTimeoutMs;
79807
80337
  try {
@@ -79814,7 +80344,8 @@ function createPluginMarketplaceAdapter(deps = {}) {
79814
80344
  error: timeoutErr.message
79815
80345
  });
79816
80346
  }
79817
- if (platform && !platform.automatable && actionType === ActionType.KIMI_MARKETPLACE_INSTALL) {
80347
+ const kimiRoute = platform ? resolvePlatformRoute(platform) : null;
80348
+ if (platform && kimiRoute?.route === "human-attestation" && actionType === ActionType.KIMI_MARKETPLACE_INSTALL) {
79818
80349
  const expectedRef = action.ref ?? `v${action.version}`;
79819
80350
  let boundPlanDigest;
79820
80351
  try {
@@ -80047,7 +80578,8 @@ function createPluginMarketplaceAdapter(deps = {}) {
80047
80578
  observation: observation2
80048
80579
  });
80049
80580
  }
80050
- if (platform && !platform.automatable && actionType === ActionType.CODEBUDDY_MARKETPLACE_INSTALL) {
80581
+ const codebuddyRoute = platform ? resolvePlatformRoute(platform) : null;
80582
+ if (platform && codebuddyRoute?.route === "human-attestation" && actionType === ActionType.CODEBUDDY_MARKETPLACE_INSTALL) {
80051
80583
  const expectedRef = action.ref ?? `v${action.version}`;
80052
80584
  let boundPlanDigest;
80053
80585
  try {
@@ -80571,7 +81103,7 @@ function createPluginMarketplaceAdapter(deps = {}) {
80571
81103
  }
80572
81104
  });
80573
81105
  }
80574
- var execFile9, NAME4, PAYLOAD_CONTRACT_DECLARED_MANIFEST, PAYLOAD_CONTRACT_EXTERNAL_MARKETPLACE, EXTRA_INSTALLED_PATHS_CAP, PAYLOAD_CONFLICT_REPORT_CAP, SUPPORTED_TYPES, SAFE_REPO_RE, CONSUMER_IDS, STRICT_SEMVER_RE;
81106
+ var execFile9, NAME4, PAYLOAD_CONTRACT_DECLARED_MANIFEST, PAYLOAD_CONTRACT_EXTERNAL_MARKETPLACE, EXTRA_INSTALLED_PATHS_CAP, PAYLOAD_CONFLICT_REPORT_CAP, SUPPORTED_TYPES, SAFE_REPO_RE, SAFE_DIGEST_RE, CONSUMER_IDS, STRICT_SEMVER_RE;
80575
81107
  var init_plugin_marketplace = __esm({
80576
81108
  async "src/adapters/plugin-marketplace.mjs"() {
80577
81109
  init_contract();
@@ -80603,6 +81135,7 @@ var init_plugin_marketplace = __esm({
80603
81135
  ActionType.CODEBUDDY_MARKETPLACE_INSTALL
80604
81136
  ];
80605
81137
  SAFE_REPO_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
81138
+ SAFE_DIGEST_RE = /^[0-9a-f]{64}$/;
80606
81139
  CONSUMER_IDS = new Set(PLATFORMS.map((p) => p.id));
80607
81140
  STRICT_SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
80608
81141
  __name(validateSafeRef, "validateSafeRef");
@@ -81155,7 +81688,7 @@ async function verifyRelease(options) {
81155
81688
  { actionId: action.id, observation: verifyResult.observation }
81156
81689
  );
81157
81690
  }
81158
- const distribution = action.type === "claude-marketplace-install" ? "claude-plugin" : action.type === "codex-marketplace-install" ? "codex-plugin" : "kimi-plugin";
81691
+ const distribution = action.type === "claude-marketplace-install" ? "claude-plugin" : action.type === "codex-marketplace-install" ? "codex-plugin" : action.type === "codebuddy-marketplace-install" ? "codebuddy-plugin" : "kimi-plugin";
81159
81692
  const installPath = verifyResult.observation?.installPath;
81160
81693
  consumerGateResults.push(...await runConsumerVerificationGates({
81161
81694
  plan,
@@ -81170,6 +81703,8 @@ async function verifyRelease(options) {
81170
81703
  } : action.type === "codex-marketplace-install" ? {
81171
81704
  HOME: resolve22(runDir, "consumers", `codex-${action.parameters.plugin}`),
81172
81705
  CODEX_HOME: resolve22(runDir, "consumers", `codex-${action.parameters.plugin}`)
81706
+ } : action.type === "codebuddy-marketplace-install" ? {
81707
+ HOME: resolve22(runDir, "consumers", `codebuddy-${action.parameters.plugin}`)
81173
81708
  } : {
81174
81709
  HOME: resolve22(runDir, "consumers", `kimi-${action.parameters.plugin}`),
81175
81710
  KIMI_CODE_HOME: resolve22(runDir, "consumers", `kimi-${action.parameters.plugin}`)