universal-plugin 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-plugin",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Research and design toolkit for building universal AI coding agent plugins that work across Claude Code, Cursor, Codex, and GitHub Copilot CLI.",
5
5
  "author": {
6
6
  "name": "unional"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-plugin",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Research and design toolkit for building universal AI coding agent plugins that work across Claude Code, Cursor, Codex, and GitHub Copilot CLI.",
5
5
  "author": {
6
6
  "name": "unional"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-plugin",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Research and design toolkit for building universal AI coding agent plugins that work across Claude Code, Cursor, Codex, and GitHub Copilot CLI.",
5
5
  "author": {
6
6
  "name": "unional"
package/dist/cli.mjs CHANGED
@@ -26,11 +26,11 @@ var __copyProps = (to, from, except, desc) => {
26
26
  }
27
27
  return to;
28
28
  };
29
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
29
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
30
30
  value: mod,
31
31
  enumerable: true
32
32
  }) : target, mod));
33
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
33
+ var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
34
34
  //#endregion
35
35
  //#region ../../node_modules/.pnpm/commander@14.0.3/node_modules/commander/lib/error.js
36
36
  var require_error = /* @__PURE__ */ __commonJSMin(((exports) => {
@@ -102,7 +102,6 @@ var require_argument = /* @__PURE__ */ __commonJSMin(((exports) => {
102
102
  default:
103
103
  this.required = true;
104
104
  this._name = name;
105
- break;
106
105
  }
107
106
  if (this._name.endsWith("...")) {
108
107
  this.variadic = true;
@@ -1597,16 +1596,20 @@ Expecting one of '${allowedValues.join("', '")}'`);
1597
1596
  const oldValue = this.getOptionValue(name);
1598
1597
  if (val !== null && option.parseArg) val = this._callParseArg(option, val, oldValue, invalidValueMessage);
1599
1598
  else if (val !== null && option.variadic) val = option._collectValue(val, oldValue);
1600
- if (val == null) if (option.negate) val = false;
1601
- else if (option.isBoolean() || option.optional) val = true;
1602
- else val = "";
1599
+ if (val == null) {
1600
+ if (option.negate) val = false;
1601
+ else if (option.isBoolean() || option.optional) val = true;
1602
+ else val = "";
1603
+ }
1603
1604
  this.setOptionValueWithSource(name, val, valueSource);
1604
1605
  };
1605
1606
  this.on("option:" + oname, (val) => {
1606
- handleOptionValue(val, `error: option '${option.flags}' argument '${val}' is invalid.`, "cli");
1607
+ const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;
1608
+ handleOptionValue(val, invalidValueMessage, "cli");
1607
1609
  });
1608
1610
  if (option.envVar) this.on("optionEnv:" + oname, (val) => {
1609
- handleOptionValue(val, `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`, "env");
1611
+ const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;
1612
+ handleOptionValue(val, invalidValueMessage, "env");
1610
1613
  });
1611
1614
  return this;
1612
1615
  }
@@ -1997,12 +2000,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
1997
2000
  }
1998
2001
  launchWithNode = sourceExt.includes(path$1.extname(executableFile));
1999
2002
  let proc;
2000
- if (process$1.platform !== "win32") if (launchWithNode) {
2001
- args.unshift(executableFile);
2002
- args = incrementNodeInspectorPort(process$1.execArgv).concat(args);
2003
- proc = childProcess$1.spawn(process$1.argv[0], args, { stdio: "inherit" });
2004
- } else proc = childProcess$1.spawn(executableFile, args, { stdio: "inherit" });
2005
- else {
2003
+ if (process$1.platform !== "win32") {
2004
+ if (launchWithNode) {
2005
+ args.unshift(executableFile);
2006
+ args = incrementNodeInspectorPort(process$1.execArgv).concat(args);
2007
+ proc = childProcess$1.spawn(process$1.argv[0], args, { stdio: "inherit" });
2008
+ } else proc = childProcess$1.spawn(executableFile, args, { stdio: "inherit" });
2009
+ } else {
2006
2010
  this._checkForMissingExecutable(executableFile, executableDir, subcommand._name);
2007
2011
  args.unshift(executableFile);
2008
2012
  args = incrementNodeInspectorPort(process$1.execArgv).concat(args);
@@ -2446,8 +2450,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
2446
2450
  "default",
2447
2451
  "config",
2448
2452
  "env"
2449
- ].includes(this.getOptionValueSource(optionKey))) if (option.required || option.optional) this.emit(`optionEnv:${option.name()}`, process$1.env[option.envVar]);
2450
- else this.emit(`optionEnv:${option.name()}`);
2453
+ ].includes(this.getOptionValueSource(optionKey))) {
2454
+ if (option.required || option.optional) this.emit(`optionEnv:${option.name()}`, process$1.env[option.envVar]);
2455
+ else this.emit(`optionEnv:${option.name()}`);
2456
+ }
2451
2457
  }
2452
2458
  });
2453
2459
  }
@@ -3071,7 +3077,7 @@ function resolveOwnVersion(packageJsonPath, deps = {}) {
3071
3077
  }
3072
3078
  //#endregion
3073
3079
  //#region src/state/state.ts
3074
- const KNOWN_ACTION_TYPES = new Set([
3080
+ const KNOWN_ACTION_TYPES = /* @__PURE__ */ new Set([
3075
3081
  "install",
3076
3082
  "upgrade",
3077
3083
  "remove"
@@ -3784,14 +3790,12 @@ function output(data, view) {
3784
3790
  //#endregion
3785
3791
  //#region ../../node_modules/.pnpm/semver@7.8.1/node_modules/semver/internal/constants.js
3786
3792
  var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
3787
- const SEMVER_SPEC_VERSION = "2.0.0";
3788
- const MAX_LENGTH = 256;
3789
- const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;
3790
3793
  module.exports = {
3791
- MAX_LENGTH,
3794
+ MAX_LENGTH: 256,
3792
3795
  MAX_SAFE_COMPONENT_LENGTH: 16,
3793
- MAX_SAFE_BUILD_LENGTH: MAX_LENGTH - 6,
3794
- MAX_SAFE_INTEGER,
3796
+ MAX_SAFE_BUILD_LENGTH: 250,
3797
+ MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER ||
3798
+ /* istanbul ignore next */ 9007199254740991,
3795
3799
  RELEASE_TYPES: [
3796
3800
  "major",
3797
3801
  "premajor",
@@ -3801,7 +3805,7 @@ var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
3801
3805
  "prepatch",
3802
3806
  "prerelease"
3803
3807
  ],
3804
- SEMVER_SPEC_VERSION,
3808
+ SEMVER_SPEC_VERSION: "2.0.0",
3805
3809
  FLAG_INCLUDE_PRERELEASE: 1,
3806
3810
  FLAG_LOOSE: 2
3807
3811
  };
@@ -3933,9 +3937,10 @@ var require_semver$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
3933
3937
  module.exports = class SemVer {
3934
3938
  constructor(version, options) {
3935
3939
  options = parseOptions(options);
3936
- if (version instanceof SemVer) if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) return version;
3937
- else version = version.version;
3938
- else if (typeof version !== "string") throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`);
3940
+ if (version instanceof SemVer) {
3941
+ if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) return version;
3942
+ else version = version.version;
3943
+ } else if (typeof version !== "string") throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`);
3939
3944
  if (version.length > MAX_LENGTH) throw new TypeError(`version is longer than ${MAX_LENGTH} characters`);
3940
3945
  debug("SemVer", version, options);
3941
3946
  this.options = options;
@@ -4356,7 +4361,11 @@ var require_coerce = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4356
4361
  }
4357
4362
  if (match === null) return null;
4358
4363
  const major = match[2];
4359
- return parse(`${major}.${match[3] || "0"}.${match[4] || "0"}${options.includePrerelease && match[5] ? `-${match[5]}` : ""}${options.includePrerelease && match[6] ? `+${match[6]}` : ""}`, options);
4364
+ const minor = match[3] || "0";
4365
+ const patch = match[4] || "0";
4366
+ const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : "";
4367
+ const build = options.includePrerelease && match[6] ? `+${match[6]}` : "";
4368
+ return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options);
4360
4369
  };
4361
4370
  module.exports = coerce;
4362
4371
  }));
@@ -4372,7 +4381,8 @@ var require_truncate = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4372
4381
  return clonedVersion && doTruncation(clonedVersion, truncation);
4373
4382
  };
4374
4383
  const cloneInputVersion = (version, options) => {
4375
- return parse(version instanceof SemVer ? version.version : version, options);
4384
+ const versionStringToParse = version instanceof SemVer ? version.version : version;
4385
+ return parse(versionStringToParse, options);
4376
4386
  };
4377
4387
  const doTruncation = (version, truncation) => {
4378
4388
  if (isPrerelease(truncation)) return version.version;
@@ -4382,9 +4392,7 @@ var require_truncate = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4382
4392
  version.minor = 0;
4383
4393
  version.patch = 0;
4384
4394
  break;
4385
- case "minor":
4386
- version.patch = 0;
4387
- break;
4395
+ case "minor": version.patch = 0;
4388
4396
  }
4389
4397
  return version.format();
4390
4398
  };
@@ -4433,8 +4441,10 @@ var require_range = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4433
4441
  module.exports = class Range {
4434
4442
  constructor(range, options) {
4435
4443
  options = parseOptions(options);
4436
- if (range instanceof Range) if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) return range;
4437
- else return new Range(range.raw, options);
4444
+ if (range instanceof Range) {
4445
+ if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) return range;
4446
+ else return new Range(range.raw, options);
4447
+ }
4438
4448
  if (range instanceof Comparator) {
4439
4449
  this.raw = range.value;
4440
4450
  this.set = [[range]];
@@ -4602,18 +4612,21 @@ var require_range = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4602
4612
  let ret;
4603
4613
  if (isX(M)) ret = "";
4604
4614
  else if (isX(m)) ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`;
4605
- else if (isX(p)) if (M === "0") ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`;
4606
- else ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`;
4607
- else if (pr) {
4615
+ else if (isX(p)) {
4616
+ if (M === "0") ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`;
4617
+ else ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`;
4618
+ } else if (pr) {
4608
4619
  debug("replaceCaret pr", pr);
4609
- if (M === "0") if (m === "0") ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`;
4610
- else ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`;
4611
- else ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`;
4620
+ if (M === "0") {
4621
+ if (m === "0") ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`;
4622
+ else ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`;
4623
+ } else ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`;
4612
4624
  } else {
4613
4625
  debug("no pr");
4614
- if (M === "0") if (m === "0") ret = `>=${M}.${m}.${p}${z} <${M}.${m}.${+p + 1}-0`;
4615
- else ret = `>=${M}.${m}.${p}${z} <${M}.${+m + 1}.0-0`;
4616
- else ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`;
4626
+ if (M === "0") {
4627
+ if (m === "0") ret = `>=${M}.${m}.${p}${z} <${M}.${m}.${+p + 1}-0`;
4628
+ else ret = `>=${M}.${m}.${p}${z} <${M}.${+m + 1}.0-0`;
4629
+ } else ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`;
4617
4630
  }
4618
4631
  debug("caret return", ret);
4619
4632
  return ret;
@@ -4634,9 +4647,10 @@ var require_range = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4634
4647
  const anyX = xp;
4635
4648
  if (gtlt === "=" && anyX) gtlt = "";
4636
4649
  pr = options.includePrerelease ? "-0" : "";
4637
- if (xM) if (gtlt === ">" || gtlt === "<") ret = "<0.0.0-0";
4638
- else ret = "*";
4639
- else if (gtlt && anyX) {
4650
+ if (xM) {
4651
+ if (gtlt === ">" || gtlt === "<") ret = "<0.0.0-0";
4652
+ else ret = "*";
4653
+ } else if (gtlt && anyX) {
4640
4654
  if (xm) m = 0;
4641
4655
  p = 0;
4642
4656
  if (gtlt === ">") {
@@ -4710,8 +4724,10 @@ var require_comparator = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4710
4724
  }
4711
4725
  constructor(comp, options) {
4712
4726
  options = parseOptions(options);
4713
- if (comp instanceof Comparator) if (comp.loose === !!options.loose) return comp;
4714
- else comp = comp.value;
4727
+ if (comp instanceof Comparator) {
4728
+ if (comp.loose === !!options.loose) return comp;
4729
+ else comp = comp.value;
4730
+ }
4715
4731
  comp = comp.trim().split(/\s+/).join(" ");
4716
4732
  debug("comparator", comp, options);
4717
4733
  this.options = options;
@@ -5031,11 +5047,15 @@ var require_subset = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5031
5047
  const minimumVersion = [new Comparator(">=0.0.0")];
5032
5048
  const simpleSubset = (sub, dom, options) => {
5033
5049
  if (sub === dom) return true;
5034
- if (sub.length === 1 && sub[0].semver === ANY) if (dom.length === 1 && dom[0].semver === ANY) return true;
5035
- else if (options.includePrerelease) sub = minimumVersionWithPreRelease;
5036
- else sub = minimumVersion;
5037
- if (dom.length === 1 && dom[0].semver === ANY) if (options.includePrerelease) return true;
5038
- else dom = minimumVersion;
5050
+ if (sub.length === 1 && sub[0].semver === ANY) {
5051
+ if (dom.length === 1 && dom[0].semver === ANY) return true;
5052
+ else if (options.includePrerelease) sub = minimumVersionWithPreRelease;
5053
+ else sub = minimumVersion;
5054
+ }
5055
+ if (dom.length === 1 && dom[0].semver === ANY) {
5056
+ if (options.includePrerelease) return true;
5057
+ else dom = minimumVersion;
5058
+ }
5039
5059
  const eqSet = /* @__PURE__ */ new Set();
5040
5060
  let gt, lt;
5041
5061
  for (const c of sub) if (c.operator === ">" || c.operator === ">=") gt = higherGT(gt, c, options);
@@ -5169,7 +5189,7 @@ const VENDOR_READS_DEPENDENCIES = {
5169
5189
  };
5170
5190
  /** Vendors the canonical root manifest serves as-is: nothing is derived for them, so a declaration
5171
5191
  * they cannot read is ignored at runtime rather than dropped from a file. */
5172
- const CANONICAL_SERVED$1 = new Set(["copilot-cli"]);
5192
+ const CANONICAL_SERVED$1 = /* @__PURE__ */ new Set(["copilot-cli"]);
5173
5193
  /** What Claude Code accepts as a dependency string: a plugin name, an optional `@marketplace`, and an
5174
5194
  * optional `@^…` range tail that the runtime strips before resolving. */
5175
5195
  const DEPENDENCY_STRING = /^[A-Za-z0-9][-A-Za-z0-9._]*(@[A-Za-z0-9][-A-Za-z0-9._]*)?(@\^[^@]*)?$/;
@@ -6232,12 +6252,12 @@ const STRING_FIELDS = [
6232
6252
  "repository",
6233
6253
  "license"
6234
6254
  ];
6235
- const AUTHOR_FIELDS = new Set([
6255
+ const AUTHOR_FIELDS = /* @__PURE__ */ new Set([
6236
6256
  "name",
6237
6257
  "email",
6238
6258
  "url"
6239
6259
  ]);
6240
- const TOP_LEVEL_FIELDS = new Set([
6260
+ const TOP_LEVEL_FIELDS = /* @__PURE__ */ new Set([
6241
6261
  "$schema",
6242
6262
  "name",
6243
6263
  ...STRING_FIELDS,
@@ -6258,7 +6278,7 @@ function validateCanonicalManifest(manifest, opts) {
6258
6278
  const uext = isObject(manifest.extensions) ? manifest.extensions[UP_NAMESPACE$2] : void 0;
6259
6279
  const extension = isObject(uext) ? uext : {};
6260
6280
  const harnesses = isObject(extension.harnesses) ? extension.harnesses : {};
6261
- const declared = [...new Set([...Array.isArray(extension.vendors) ? extension.vendors.filter((v) => typeof v === "string") : [], ...Object.keys(harnesses)])];
6281
+ const declared = [.../* @__PURE__ */ new Set([...Array.isArray(extension.vendors) ? extension.vendors.filter((v) => typeof v === "string") : [], ...Object.keys(harnesses)])];
6262
6282
  for (const vendor of declared.filter((v) => !opts.knownVendors.has(v))) {
6263
6283
  const message = `Unknown vendor "${vendor}" in harnesses`;
6264
6284
  warnings.push(message);
@@ -6315,18 +6335,22 @@ function schemaRuleViolations(manifest, warnings) {
6315
6335
  else for (const [key, value] of Object.entries(manifest.author)) if (!AUTHOR_FIELDS.has(key)) push(`author.${key}`, "additionalProperties", "unknown author field");
6316
6336
  else if (typeof value !== "string") push(`author.${key}`, "type", "must be a string");
6317
6337
  }
6318
- if (manifest.keywords !== void 0) if (!Array.isArray(manifest.keywords)) push("keywords", "type", "must be an array of strings");
6319
- else manifest.keywords.forEach((keyword, index) => {
6320
- if (typeof keyword !== "string") push(`keywords[${index}]`, "type", "must be a string");
6321
- });
6322
- if (manifest.extensions !== void 0) if (!isObject(manifest.extensions)) push("extensions", "type", "must be an object keyed by namespace");
6323
- else {
6324
- for (const [namespace, value] of Object.entries(manifest.extensions)) if (!isObject(value)) push(`extensions.${namespace}`, "type", "must be an object");
6325
- const uext = manifest.extensions[UP_NAMESPACE$2];
6326
- if (isObject(uext)) {
6327
- const dependencies = validateDependencies(uext.dependencies);
6328
- for (const error of dependencies.errors) push(`extensions.${UP_NAMESPACE$2}.dependencies`, "dependencies", error);
6329
- warnings.push(...dependencies.warnings);
6338
+ if (manifest.keywords !== void 0) {
6339
+ if (!Array.isArray(manifest.keywords)) push("keywords", "type", "must be an array of strings");
6340
+ else manifest.keywords.forEach((keyword, index) => {
6341
+ if (typeof keyword !== "string") push(`keywords[${index}]`, "type", "must be a string");
6342
+ });
6343
+ }
6344
+ if (manifest.extensions !== void 0) {
6345
+ if (!isObject(manifest.extensions)) push("extensions", "type", "must be an object keyed by namespace");
6346
+ else {
6347
+ for (const [namespace, value] of Object.entries(manifest.extensions)) if (!isObject(value)) push(`extensions.${namespace}`, "type", "must be an object");
6348
+ const uext = manifest.extensions[UP_NAMESPACE$2];
6349
+ if (isObject(uext)) {
6350
+ const dependencies = validateDependencies(uext.dependencies);
6351
+ for (const error of dependencies.errors) push(`extensions.${UP_NAMESPACE$2}.dependencies`, "dependencies", error);
6352
+ warnings.push(...dependencies.warnings);
6353
+ }
6330
6354
  }
6331
6355
  }
6332
6356
  for (const key of Object.keys(manifest)) if (!TOP_LEVEL_FIELDS.has(key)) push(key, "additionalProperties", "not an Agent Plugins 1.0.0 field; move tool-specific data under extensions");
@@ -6346,7 +6370,7 @@ const KNOWN_VENDORS$1 = new Set(Object.keys(VENDOR_OUTPUT));
6346
6370
  /** Vendors the canonical root manifest serves as-is. The build derives no *manifest* for these —
6347
6371
  * writing one would either be shadowed by root (a lower-precedence path) or clobber root itself.
6348
6372
  * Their components are a separate question: see COPILOT_NAMESPACE. */
6349
- const CANONICAL_SERVED = new Set(["copilot-cli"]);
6373
+ const CANONICAL_SERVED = /* @__PURE__ */ new Set(["copilot-cli"]);
6350
6374
  /** The reverse-domain directory Copilot CLI reads its native components from once a plugin declares
6351
6375
  * the canonical `$schema` (ADR-0015). It REPLACES the plugin root for these kinds — a spec-mode
6352
6376
  * runtime does not read `agents/` at all — so the build derives the tree rather than relying on the
@@ -6506,11 +6530,15 @@ function buildPlugin(root, opts = {}) {
6506
6530
  }
6507
6531
  for (const drop of dedupeDrops(hooks?.drops ?? [])) warnings.push(`${vendor} cannot run the "${drop.type}" hook handler on ${drop.event} — dropped from the derived hooks file`);
6508
6532
  const derivedHooksPath = path.join(outputDir, "hooks.json");
6509
- if (hooks?.changed) if (hooks.hooks) vendorManifest["hooks"] = `./${path.dirname(relPath).split(path.sep).join("/")}/hooks.json`;
6510
- else delete vendorManifest["hooks"];
6533
+ if (hooks?.changed) {
6534
+ if (hooks.hooks) vendorManifest["hooks"] = `./${path.dirname(relPath).split(path.sep).join("/")}/hooks.json`;
6535
+ else delete vendorManifest["hooks"];
6536
+ }
6511
6537
  const derivedMcpPath = path.join(outputDir, "mcp.json");
6512
- if (mcp?.changed && declaredMcp) if (declaredMcp.inline) vendorManifest["mcpServers"] = mcp.servers;
6513
- else vendorManifest["mcpServers"] = `./${path.dirname(relPath).split(path.sep).join("/")}/mcp.json`;
6538
+ if (mcp?.changed && declaredMcp) {
6539
+ if (declaredMcp.inline) vendorManifest["mcpServers"] = mcp.servers;
6540
+ else vendorManifest["mcpServers"] = `./${path.dirname(relPath).split(path.sep).join("/")}/mcp.json`;
6541
+ }
6514
6542
  if (opts.verbose) {
6515
6543
  console.log(`[${vendor}] → ${outputPath}`);
6516
6544
  for (const key of Object.keys(vendorFields)) console.log(` + ${key} (from harnesses.${vendor})`);
@@ -6948,7 +6976,7 @@ function buildCommand() {
6948
6976
  }
6949
6977
  //#endregion
6950
6978
  //#region src/pin/fs.ts
6951
- const TEXT_EXTENSIONS = new Set([
6979
+ const TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
6952
6980
  ".md",
6953
6981
  ".mdx",
6954
6982
  ".markdown",
@@ -7964,7 +7992,7 @@ function readPluginName(manifestPath) {
7964
7992
  }
7965
7993
  /** Entries a copy never carries: the working copy's history and its installed dependencies. Neither
7966
7994
  * is part of the plugin, and both dwarf it. */
7967
- const COPY_EXCLUDED = new Set([".git", "node_modules"]);
7995
+ const COPY_EXCLUDED = /* @__PURE__ */ new Set([".git", "node_modules"]);
7968
7996
  /** Applies one planned write. A replace removes the destination first, so a copy never merges into
7969
7997
  * what was there before. A copy dereferences symlinks — a skill linked into the tree has to travel
7970
7998
  * as its content, since the destination is read on its own. */
@@ -9302,8 +9330,10 @@ function runPrepare(opts) {
9302
9330
  version
9303
9331
  });
9304
9332
  }
9305
- if (!dryRun) if (scope === "global") prepareFs.writeGlobalState(updatedState);
9306
- else prepareFs.writeProjectState(updatedState);
9333
+ if (!dryRun) {
9334
+ if (scope === "global") prepareFs.writeGlobalState(updatedState);
9335
+ else prepareFs.writeProjectState(updatedState);
9336
+ }
9307
9337
  return { newActionCount: actions.length };
9308
9338
  }
9309
9339
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-plugin",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Universal AI agent plugin build tool",
5
5
  "keywords": [
6
6
  "agent-plugin",
@@ -50,7 +50,7 @@
50
50
  "@types/semver": "^7.7.1",
51
51
  "ajv": "^8.20.0",
52
52
  "knip": "^6.14.1",
53
- "tsdown": "^0.22.0",
53
+ "tsdown": "^0.23.0",
54
54
  "tsx": "^4.22.3",
55
55
  "typescript": "^6.0.0",
56
56
  "vitest": "^4.1.7"
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
3
  "name": "universal-plugin",
4
- "version": "0.11.0",
4
+ "version": "0.11.1",
5
5
  "description": "Research and design toolkit for building universal AI coding agent plugins that work across Claude Code, Cursor, Codex, and GitHub Copilot CLI.",
6
6
  "author": {
7
7
  "name": "unional"
package/readme.md CHANGED
@@ -110,7 +110,7 @@ TOON by default; pass `--format json` for JSON.
110
110
 
111
111
  This package ships its own documents (`plugin-design`, `slash-invocation`, `universal-plugin`) under
112
112
  `references/`. Read one with `buddy-agent-harness reference show <name>` in any project that depends
113
- on `universal-plugin`, or, from a skill, with the `load-reference` skill in the `buddy-agent-harness`
113
+ on `universal-plugin`, or, from a skill, with the `reference` skill in the `buddy-agent-harness`
114
114
  plugin.
115
115
 
116
116
  ### Housekeeping
@@ -330,6 +330,6 @@ Portability rules for skill bodies: keep each `SKILL.md` body under 6,000 chars;
330
330
 
331
331
  ## References
332
332
 
333
- Load `skill-design`, `skill-repo-structure`, and `agent-tool-output` with the `load-reference` skill in the `buddy-agent-harness` plugin.
333
+ Load `skill-design`, `skill-repo-structure`, and `agent-tool-output` with the `reference` skill in the `buddy-agent-harness` plugin.
334
334
 
335
335
  Spec: https://github.com/cyberuni/universal-plugin/blob/main/packages/universal-plugin/.agents/spec/spec.md
@@ -1,4 +1,4 @@
1
1
  # Universal Plugin Format
2
2
 
3
3
  The rules for the universal plugin format live in `plugin-design`, which this package also ships.
4
- Load `plugin-design` with the `load-reference` skill in the `buddy-agent-harness` plugin.
4
+ Load `plugin-design` with the `reference` skill in the `buddy-agent-harness` plugin.
@@ -117,7 +117,7 @@ Validation runs before the first write, so a failed build leaves the tree untouc
117
117
  - **Expect a build to pin skill `npx` references.** That is the release-time `plugin bundle`, not
118
118
  this step.
119
119
  - **Expect a build to copy governances into skills.** A skill loads a reference through the
120
- `load-reference` skill in the `buddy-agent-harness` plugin; the build no longer copies them, and
120
+ `reference` skill in the `buddy-agent-harness` plugin; the build no longer copies them, and
121
121
  `--check` is gone.
122
122
 
123
123
  ## Related skills
@@ -38,7 +38,7 @@ This skill owns the **authoring** side: the plugin a project ships. Setting a re
38
38
 
39
39
  ## Prerequisites
40
40
 
41
- Before any work that adds or removes components, load `plugin-design` with the `load-reference`
41
+ Before any work that adds or removes components, load `plugin-design` with the `reference`
42
42
  skill in the `buddy-agent-harness` plugin.
43
43
 
44
44
  It is the authoritative source for which component to reach for and which anti-patterns to avoid.
@@ -233,7 +233,7 @@ This skill is not a formatter. If the project has one, run it over the written f
233
233
 
234
234
  ## References
235
235
 
236
- - Reference: `plugin-design`, loaded with the `load-reference` skill in the `buddy-agent-harness` plugin
236
+ - Reference: `plugin-design`, loaded with the `reference` skill in the `buddy-agent-harness` plugin
237
237
  - Spec: https://github.com/cyberuni/universal-plugin/blob/main/packages/universal-plugin/.agents/spec/spec.md
238
238
  - Manifest schema (Agent Plugins Specification v1.0.0): https://agent-plugins.org/schemas/1.0.0/plugin.schema.json
239
239
  - Extension schema (the body of `extensions["org.cyberuni.universal-plugin"]`), shipped in the package at