@alessandroraffa/tangyr 3.0.4 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1372,8 +1372,8 @@ var require_command = __commonJS({
1372
1372
  "use strict";
1373
1373
  var EventEmitter = __require("events").EventEmitter;
1374
1374
  var childProcess = __require("child_process");
1375
- var path51 = __require("path");
1376
- var fs50 = __require("fs");
1375
+ var path52 = __require("path");
1376
+ var fs51 = __require("fs");
1377
1377
  var process5 = __require("process");
1378
1378
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1379
1379
  var { CommanderError: CommanderError2 } = require_error();
@@ -2367,7 +2367,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2367
2367
  * @param {string} subcommandName
2368
2368
  */
2369
2369
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
2370
- if (fs50.existsSync(executableFile)) return;
2370
+ if (fs51.existsSync(executableFile)) return;
2371
2371
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
2372
2372
  const executableMissing = `'${executableFile}' does not exist
2373
2373
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -2385,11 +2385,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
2385
2385
  let launchWithNode = false;
2386
2386
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
2387
2387
  function findFile(baseDir, baseName) {
2388
- const localBin = path51.resolve(baseDir, baseName);
2389
- if (fs50.existsSync(localBin)) return localBin;
2390
- if (sourceExt.includes(path51.extname(baseName))) return void 0;
2388
+ const localBin = path52.resolve(baseDir, baseName);
2389
+ if (fs51.existsSync(localBin)) return localBin;
2390
+ if (sourceExt.includes(path52.extname(baseName))) return void 0;
2391
2391
  const foundExt = sourceExt.find(
2392
- (ext) => fs50.existsSync(`${localBin}${ext}`)
2392
+ (ext) => fs51.existsSync(`${localBin}${ext}`)
2393
2393
  );
2394
2394
  if (foundExt) return `${localBin}${foundExt}`;
2395
2395
  return void 0;
@@ -2401,21 +2401,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
2401
2401
  if (this._scriptPath) {
2402
2402
  let resolvedScriptPath;
2403
2403
  try {
2404
- resolvedScriptPath = fs50.realpathSync(this._scriptPath);
2404
+ resolvedScriptPath = fs51.realpathSync(this._scriptPath);
2405
2405
  } catch {
2406
2406
  resolvedScriptPath = this._scriptPath;
2407
2407
  }
2408
- executableDir = path51.resolve(
2409
- path51.dirname(resolvedScriptPath),
2408
+ executableDir = path52.resolve(
2409
+ path52.dirname(resolvedScriptPath),
2410
2410
  executableDir
2411
2411
  );
2412
2412
  }
2413
2413
  if (executableDir) {
2414
2414
  let localFile = findFile(executableDir, executableFile);
2415
2415
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
2416
- const legacyName = path51.basename(
2416
+ const legacyName = path52.basename(
2417
2417
  this._scriptPath,
2418
- path51.extname(this._scriptPath)
2418
+ path52.extname(this._scriptPath)
2419
2419
  );
2420
2420
  if (legacyName !== this._name) {
2421
2421
  localFile = findFile(
@@ -2426,7 +2426,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2426
2426
  }
2427
2427
  executableFile = localFile || executableFile;
2428
2428
  }
2429
- launchWithNode = sourceExt.includes(path51.extname(executableFile));
2429
+ launchWithNode = sourceExt.includes(path52.extname(executableFile));
2430
2430
  let proc;
2431
2431
  if (process5.platform !== "win32") {
2432
2432
  if (launchWithNode) {
@@ -3341,7 +3341,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3341
3341
  * @return {Command}
3342
3342
  */
3343
3343
  nameFromFilename(filename) {
3344
- this._name = path51.basename(filename, path51.extname(filename));
3344
+ this._name = path52.basename(filename, path52.extname(filename));
3345
3345
  return this;
3346
3346
  }
3347
3347
  /**
@@ -3355,9 +3355,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3355
3355
  * @param {string} [path]
3356
3356
  * @return {(string|null|Command)}
3357
3357
  */
3358
- executableDir(path52) {
3359
- if (path52 === void 0) return this._executableDir;
3360
- this._executableDir = path52;
3358
+ executableDir(path53) {
3359
+ if (path53 === void 0) return this._executableDir;
3360
+ this._executableDir = path53;
3361
3361
  return this;
3362
3362
  }
3363
3363
  /**
@@ -3713,17 +3713,17 @@ var require_visit = __commonJS({
3713
3713
  visit.BREAK = BREAK;
3714
3714
  visit.SKIP = SKIP;
3715
3715
  visit.REMOVE = REMOVE;
3716
- function visit_(key, node, visitor, path51) {
3717
- const ctrl = callVisitor(key, node, visitor, path51);
3716
+ function visit_(key, node, visitor, path52) {
3717
+ const ctrl = callVisitor(key, node, visitor, path52);
3718
3718
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
3719
- replaceNode(key, path51, ctrl);
3720
- return visit_(key, ctrl, visitor, path51);
3719
+ replaceNode(key, path52, ctrl);
3720
+ return visit_(key, ctrl, visitor, path52);
3721
3721
  }
3722
3722
  if (typeof ctrl !== "symbol") {
3723
3723
  if (identity.isCollection(node)) {
3724
- path51 = Object.freeze(path51.concat(node));
3724
+ path52 = Object.freeze(path52.concat(node));
3725
3725
  for (let i = 0; i < node.items.length; ++i) {
3726
- const ci2 = visit_(i, node.items[i], visitor, path51);
3726
+ const ci2 = visit_(i, node.items[i], visitor, path52);
3727
3727
  if (typeof ci2 === "number")
3728
3728
  i = ci2 - 1;
3729
3729
  else if (ci2 === BREAK)
@@ -3734,13 +3734,13 @@ var require_visit = __commonJS({
3734
3734
  }
3735
3735
  }
3736
3736
  } else if (identity.isPair(node)) {
3737
- path51 = Object.freeze(path51.concat(node));
3738
- const ck = visit_("key", node.key, visitor, path51);
3737
+ path52 = Object.freeze(path52.concat(node));
3738
+ const ck = visit_("key", node.key, visitor, path52);
3739
3739
  if (ck === BREAK)
3740
3740
  return BREAK;
3741
3741
  else if (ck === REMOVE)
3742
3742
  node.key = null;
3743
- const cv = visit_("value", node.value, visitor, path51);
3743
+ const cv = visit_("value", node.value, visitor, path52);
3744
3744
  if (cv === BREAK)
3745
3745
  return BREAK;
3746
3746
  else if (cv === REMOVE)
@@ -3761,17 +3761,17 @@ var require_visit = __commonJS({
3761
3761
  visitAsync.BREAK = BREAK;
3762
3762
  visitAsync.SKIP = SKIP;
3763
3763
  visitAsync.REMOVE = REMOVE;
3764
- async function visitAsync_(key, node, visitor, path51) {
3765
- const ctrl = await callVisitor(key, node, visitor, path51);
3764
+ async function visitAsync_(key, node, visitor, path52) {
3765
+ const ctrl = await callVisitor(key, node, visitor, path52);
3766
3766
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
3767
- replaceNode(key, path51, ctrl);
3768
- return visitAsync_(key, ctrl, visitor, path51);
3767
+ replaceNode(key, path52, ctrl);
3768
+ return visitAsync_(key, ctrl, visitor, path52);
3769
3769
  }
3770
3770
  if (typeof ctrl !== "symbol") {
3771
3771
  if (identity.isCollection(node)) {
3772
- path51 = Object.freeze(path51.concat(node));
3772
+ path52 = Object.freeze(path52.concat(node));
3773
3773
  for (let i = 0; i < node.items.length; ++i) {
3774
- const ci2 = await visitAsync_(i, node.items[i], visitor, path51);
3774
+ const ci2 = await visitAsync_(i, node.items[i], visitor, path52);
3775
3775
  if (typeof ci2 === "number")
3776
3776
  i = ci2 - 1;
3777
3777
  else if (ci2 === BREAK)
@@ -3782,13 +3782,13 @@ var require_visit = __commonJS({
3782
3782
  }
3783
3783
  }
3784
3784
  } else if (identity.isPair(node)) {
3785
- path51 = Object.freeze(path51.concat(node));
3786
- const ck = await visitAsync_("key", node.key, visitor, path51);
3785
+ path52 = Object.freeze(path52.concat(node));
3786
+ const ck = await visitAsync_("key", node.key, visitor, path52);
3787
3787
  if (ck === BREAK)
3788
3788
  return BREAK;
3789
3789
  else if (ck === REMOVE)
3790
3790
  node.key = null;
3791
- const cv = await visitAsync_("value", node.value, visitor, path51);
3791
+ const cv = await visitAsync_("value", node.value, visitor, path52);
3792
3792
  if (cv === BREAK)
3793
3793
  return BREAK;
3794
3794
  else if (cv === REMOVE)
@@ -3815,23 +3815,23 @@ var require_visit = __commonJS({
3815
3815
  }
3816
3816
  return visitor;
3817
3817
  }
3818
- function callVisitor(key, node, visitor, path51) {
3818
+ function callVisitor(key, node, visitor, path52) {
3819
3819
  if (typeof visitor === "function")
3820
- return visitor(key, node, path51);
3820
+ return visitor(key, node, path52);
3821
3821
  if (identity.isMap(node))
3822
- return visitor.Map?.(key, node, path51);
3822
+ return visitor.Map?.(key, node, path52);
3823
3823
  if (identity.isSeq(node))
3824
- return visitor.Seq?.(key, node, path51);
3824
+ return visitor.Seq?.(key, node, path52);
3825
3825
  if (identity.isPair(node))
3826
- return visitor.Pair?.(key, node, path51);
3826
+ return visitor.Pair?.(key, node, path52);
3827
3827
  if (identity.isScalar(node))
3828
- return visitor.Scalar?.(key, node, path51);
3828
+ return visitor.Scalar?.(key, node, path52);
3829
3829
  if (identity.isAlias(node))
3830
- return visitor.Alias?.(key, node, path51);
3830
+ return visitor.Alias?.(key, node, path52);
3831
3831
  return void 0;
3832
3832
  }
3833
- function replaceNode(key, path51, node) {
3834
- const parent = path51[path51.length - 1];
3833
+ function replaceNode(key, path52, node) {
3834
+ const parent = path52[path52.length - 1];
3835
3835
  if (identity.isCollection(parent)) {
3836
3836
  parent.items[key] = node;
3837
3837
  } else if (identity.isPair(parent)) {
@@ -4439,10 +4439,10 @@ var require_Collection = __commonJS({
4439
4439
  var createNode = require_createNode();
4440
4440
  var identity = require_identity();
4441
4441
  var Node = require_Node();
4442
- function collectionFromPath(schema, path51, value) {
4442
+ function collectionFromPath(schema, path52, value) {
4443
4443
  let v2 = value;
4444
- for (let i = path51.length - 1; i >= 0; --i) {
4445
- const k2 = path51[i];
4444
+ for (let i = path52.length - 1; i >= 0; --i) {
4445
+ const k2 = path52[i];
4446
4446
  if (typeof k2 === "number" && Number.isInteger(k2) && k2 >= 0) {
4447
4447
  const a = [];
4448
4448
  a[k2] = v2;
@@ -4461,7 +4461,7 @@ var require_Collection = __commonJS({
4461
4461
  sourceObjects: /* @__PURE__ */ new Map()
4462
4462
  });
4463
4463
  }
4464
- var isEmptyPath = (path51) => path51 == null || typeof path51 === "object" && !!path51[Symbol.iterator]().next().done;
4464
+ var isEmptyPath = (path52) => path52 == null || typeof path52 === "object" && !!path52[Symbol.iterator]().next().done;
4465
4465
  var Collection = class extends Node.NodeBase {
4466
4466
  constructor(type, schema) {
4467
4467
  super(type);
@@ -4491,11 +4491,11 @@ var require_Collection = __commonJS({
4491
4491
  * be a Pair instance or a `{ key, value }` object, which may not have a key
4492
4492
  * that already exists in the map.
4493
4493
  */
4494
- addIn(path51, value) {
4495
- if (isEmptyPath(path51))
4494
+ addIn(path52, value) {
4495
+ if (isEmptyPath(path52))
4496
4496
  this.add(value);
4497
4497
  else {
4498
- const [key, ...rest] = path51;
4498
+ const [key, ...rest] = path52;
4499
4499
  const node = this.get(key, true);
4500
4500
  if (identity.isCollection(node))
4501
4501
  node.addIn(rest, value);
@@ -4509,8 +4509,8 @@ var require_Collection = __commonJS({
4509
4509
  * Removes a value from the collection.
4510
4510
  * @returns `true` if the item was found and removed.
4511
4511
  */
4512
- deleteIn(path51) {
4513
- const [key, ...rest] = path51;
4512
+ deleteIn(path52) {
4513
+ const [key, ...rest] = path52;
4514
4514
  if (rest.length === 0)
4515
4515
  return this.delete(key);
4516
4516
  const node = this.get(key, true);
@@ -4524,8 +4524,8 @@ var require_Collection = __commonJS({
4524
4524
  * scalar values from their surrounding node; to disable set `keepScalar` to
4525
4525
  * `true` (collections are always returned intact).
4526
4526
  */
4527
- getIn(path51, keepScalar) {
4528
- const [key, ...rest] = path51;
4527
+ getIn(path52, keepScalar) {
4528
+ const [key, ...rest] = path52;
4529
4529
  const node = this.get(key, true);
4530
4530
  if (rest.length === 0)
4531
4531
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -4543,8 +4543,8 @@ var require_Collection = __commonJS({
4543
4543
  /**
4544
4544
  * Checks if the collection includes a value with the key `key`.
4545
4545
  */
4546
- hasIn(path51) {
4547
- const [key, ...rest] = path51;
4546
+ hasIn(path52) {
4547
+ const [key, ...rest] = path52;
4548
4548
  if (rest.length === 0)
4549
4549
  return this.has(key);
4550
4550
  const node = this.get(key, true);
@@ -4554,8 +4554,8 @@ var require_Collection = __commonJS({
4554
4554
  * Sets a value in this collection. For `!!set`, `value` needs to be a
4555
4555
  * boolean to add/remove the item from the set.
4556
4556
  */
4557
- setIn(path51, value) {
4558
- const [key, ...rest] = path51;
4557
+ setIn(path52, value) {
4558
+ const [key, ...rest] = path52;
4559
4559
  if (rest.length === 0) {
4560
4560
  this.set(key, value);
4561
4561
  } else {
@@ -7067,9 +7067,9 @@ var require_Document = __commonJS({
7067
7067
  this.contents.add(value);
7068
7068
  }
7069
7069
  /** Adds a value to the document. */
7070
- addIn(path51, value) {
7070
+ addIn(path52, value) {
7071
7071
  if (assertCollection(this.contents))
7072
- this.contents.addIn(path51, value);
7072
+ this.contents.addIn(path52, value);
7073
7073
  }
7074
7074
  /**
7075
7075
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -7144,14 +7144,14 @@ var require_Document = __commonJS({
7144
7144
  * Removes a value from the document.
7145
7145
  * @returns `true` if the item was found and removed.
7146
7146
  */
7147
- deleteIn(path51) {
7148
- if (Collection.isEmptyPath(path51)) {
7147
+ deleteIn(path52) {
7148
+ if (Collection.isEmptyPath(path52)) {
7149
7149
  if (this.contents == null)
7150
7150
  return false;
7151
7151
  this.contents = null;
7152
7152
  return true;
7153
7153
  }
7154
- return assertCollection(this.contents) ? this.contents.deleteIn(path51) : false;
7154
+ return assertCollection(this.contents) ? this.contents.deleteIn(path52) : false;
7155
7155
  }
7156
7156
  /**
7157
7157
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -7166,10 +7166,10 @@ var require_Document = __commonJS({
7166
7166
  * scalar values from their surrounding node; to disable set `keepScalar` to
7167
7167
  * `true` (collections are always returned intact).
7168
7168
  */
7169
- getIn(path51, keepScalar) {
7170
- if (Collection.isEmptyPath(path51))
7169
+ getIn(path52, keepScalar) {
7170
+ if (Collection.isEmptyPath(path52))
7171
7171
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
7172
- return identity.isCollection(this.contents) ? this.contents.getIn(path51, keepScalar) : void 0;
7172
+ return identity.isCollection(this.contents) ? this.contents.getIn(path52, keepScalar) : void 0;
7173
7173
  }
7174
7174
  /**
7175
7175
  * Checks if the document includes a value with the key `key`.
@@ -7180,10 +7180,10 @@ var require_Document = __commonJS({
7180
7180
  /**
7181
7181
  * Checks if the document includes a value at `path`.
7182
7182
  */
7183
- hasIn(path51) {
7184
- if (Collection.isEmptyPath(path51))
7183
+ hasIn(path52) {
7184
+ if (Collection.isEmptyPath(path52))
7185
7185
  return this.contents !== void 0;
7186
- return identity.isCollection(this.contents) ? this.contents.hasIn(path51) : false;
7186
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path52) : false;
7187
7187
  }
7188
7188
  /**
7189
7189
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -7200,13 +7200,13 @@ var require_Document = __commonJS({
7200
7200
  * Sets a value in this document. For `!!set`, `value` needs to be a
7201
7201
  * boolean to add/remove the item from the set.
7202
7202
  */
7203
- setIn(path51, value) {
7204
- if (Collection.isEmptyPath(path51)) {
7203
+ setIn(path52, value) {
7204
+ if (Collection.isEmptyPath(path52)) {
7205
7205
  this.contents = value;
7206
7206
  } else if (this.contents == null) {
7207
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path51), value);
7207
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path52), value);
7208
7208
  } else if (assertCollection(this.contents)) {
7209
- this.contents.setIn(path51, value);
7209
+ this.contents.setIn(path52, value);
7210
7210
  }
7211
7211
  }
7212
7212
  /**
@@ -9163,9 +9163,9 @@ var require_cst_visit = __commonJS({
9163
9163
  visit.BREAK = BREAK;
9164
9164
  visit.SKIP = SKIP;
9165
9165
  visit.REMOVE = REMOVE;
9166
- visit.itemAtPath = (cst, path51) => {
9166
+ visit.itemAtPath = (cst, path52) => {
9167
9167
  let item = cst;
9168
- for (const [field, index] of path51) {
9168
+ for (const [field, index] of path52) {
9169
9169
  const tok = item?.[field];
9170
9170
  if (tok && "items" in tok) {
9171
9171
  item = tok.items[index];
@@ -9174,23 +9174,23 @@ var require_cst_visit = __commonJS({
9174
9174
  }
9175
9175
  return item;
9176
9176
  };
9177
- visit.parentCollection = (cst, path51) => {
9178
- const parent = visit.itemAtPath(cst, path51.slice(0, -1));
9179
- const field = path51[path51.length - 1][0];
9177
+ visit.parentCollection = (cst, path52) => {
9178
+ const parent = visit.itemAtPath(cst, path52.slice(0, -1));
9179
+ const field = path52[path52.length - 1][0];
9180
9180
  const coll = parent?.[field];
9181
9181
  if (coll && "items" in coll)
9182
9182
  return coll;
9183
9183
  throw new Error("Parent collection not found");
9184
9184
  };
9185
- function _visit(path51, item, visitor) {
9186
- let ctrl = visitor(item, path51);
9185
+ function _visit(path52, item, visitor) {
9186
+ let ctrl = visitor(item, path52);
9187
9187
  if (typeof ctrl === "symbol")
9188
9188
  return ctrl;
9189
9189
  for (const field of ["key", "value"]) {
9190
9190
  const token = item[field];
9191
9191
  if (token && "items" in token) {
9192
9192
  for (let i = 0; i < token.items.length; ++i) {
9193
- const ci2 = _visit(Object.freeze(path51.concat([[field, i]])), token.items[i], visitor);
9193
+ const ci2 = _visit(Object.freeze(path52.concat([[field, i]])), token.items[i], visitor);
9194
9194
  if (typeof ci2 === "number")
9195
9195
  i = ci2 - 1;
9196
9196
  else if (ci2 === BREAK)
@@ -9201,10 +9201,10 @@ var require_cst_visit = __commonJS({
9201
9201
  }
9202
9202
  }
9203
9203
  if (typeof ctrl === "function" && field === "key")
9204
- ctrl = ctrl(item, path51);
9204
+ ctrl = ctrl(item, path52);
9205
9205
  }
9206
9206
  }
9207
- return typeof ctrl === "function" ? ctrl(item, path51) : ctrl;
9207
+ return typeof ctrl === "function" ? ctrl(item, path52) : ctrl;
9208
9208
  }
9209
9209
  exports2.visit = visit;
9210
9210
  }
@@ -10489,14 +10489,14 @@ var require_parser = __commonJS({
10489
10489
  case "scalar":
10490
10490
  case "single-quoted-scalar":
10491
10491
  case "double-quoted-scalar": {
10492
- const fs50 = this.flowScalar(this.type);
10492
+ const fs51 = this.flowScalar(this.type);
10493
10493
  if (atNextItem || it2.value) {
10494
- map.items.push({ start, key: fs50, sep: [] });
10494
+ map.items.push({ start, key: fs51, sep: [] });
10495
10495
  this.onKeyLine = true;
10496
10496
  } else if (it2.sep) {
10497
- this.stack.push(fs50);
10497
+ this.stack.push(fs51);
10498
10498
  } else {
10499
- Object.assign(it2, { key: fs50, sep: [] });
10499
+ Object.assign(it2, { key: fs51, sep: [] });
10500
10500
  this.onKeyLine = true;
10501
10501
  }
10502
10502
  return;
@@ -10624,13 +10624,13 @@ var require_parser = __commonJS({
10624
10624
  case "scalar":
10625
10625
  case "single-quoted-scalar":
10626
10626
  case "double-quoted-scalar": {
10627
- const fs50 = this.flowScalar(this.type);
10627
+ const fs51 = this.flowScalar(this.type);
10628
10628
  if (!it2 || it2.value)
10629
- fc.items.push({ start: [], key: fs50, sep: [] });
10629
+ fc.items.push({ start: [], key: fs51, sep: [] });
10630
10630
  else if (it2.sep)
10631
- this.stack.push(fs50);
10631
+ this.stack.push(fs51);
10632
10632
  else
10633
- Object.assign(it2, { key: fs50, sep: [] });
10633
+ Object.assign(it2, { key: fs51, sep: [] });
10634
10634
  return;
10635
10635
  }
10636
10636
  case "flow-map-end":
@@ -15320,6 +15320,13 @@ function extractProvenanceMarker(content) {
15320
15320
  if (jsonProvenance) {
15321
15321
  return jsonProvenance;
15322
15322
  }
15323
+ const yamlMarker = /(?:^|\n)x-(?:tangyr|proteus):\s*\n\s+source:\s*(\S+)\s*\n\s+hash:\s*(sha256:[a-f0-9]+)\s*\n\s+target:\s*(\S+)/u.exec(
15324
+ content
15325
+ );
15326
+ const yamlProvenance = markerFromMatch(yamlMarker);
15327
+ if (yamlProvenance) {
15328
+ return yamlProvenance;
15329
+ }
15323
15330
  return null;
15324
15331
  }
15325
15332
  function markerFromMatch(match) {
@@ -16490,7 +16497,10 @@ function resolveCopilotProfile(scope, projectRoot, mappings) {
16490
16497
  hooks: r(slotMap, "hooks"),
16491
16498
  hook_scripts: r(slotMap, "hook_scripts"),
16492
16499
  mcp_shared_file: r(slotMap, "mcp_shared_file"),
16493
- instructions
16500
+ instructions,
16501
+ // Project-only, like instructions: `.github/instructions` is a repository
16502
+ // surface and has no user-level equivalent Copilot documents.
16503
+ rules: r(slotMap, "rules")
16494
16504
  };
16495
16505
  }
16496
16506
  function resolveCodexProfile(scope, projectRoot, mappings) {
@@ -25213,8 +25223,8 @@ function toConflictPolicy2(value) {
25213
25223
  }
25214
25224
 
25215
25225
  // src/commands/install.ts
25216
- import fs44 from "fs";
25217
- import path44 from "path";
25226
+ import fs45 from "fs";
25227
+ import path45 from "path";
25218
25228
 
25219
25229
  // src/core/channel-state.ts
25220
25230
  import fs32 from "fs";
@@ -26980,8 +26990,8 @@ function isRecord3(value) {
26980
26990
  // src/adapters/codex.ts
26981
26991
  var TOML3 = __toESM(require_toml(), 1);
26982
26992
  import crypto6 from "crypto";
26983
- import fs39 from "fs";
26984
- import path38 from "path";
26993
+ import fs40 from "fs";
26994
+ import path39 from "path";
26985
26995
 
26986
26996
  // src/compiler/agents.ts
26987
26997
  var TOML = __toESM(require_toml(), 1);
@@ -27779,6 +27789,45 @@ function addHookLoss(lossReport, target, eventName, sourceLabel, severity, reaso
27779
27789
  });
27780
27790
  }
27781
27791
 
27792
+ // src/compiler/command-as-skill.ts
27793
+ var import_yaml9 = __toESM(require_dist(), 1);
27794
+ import fs38 from "fs";
27795
+ import path37 from "path";
27796
+ var CARRIED_OVER = ["argument-hint", "agent", "launch"];
27797
+ function compileCommandAsSkill(commandFile, target) {
27798
+ const name = path37.basename(commandFile, ".md");
27799
+ const { data, body } = parseMarkdownFrontmatter(commandFile);
27800
+ const relativeSource = `commands/${path37.basename(commandFile)}`;
27801
+ const description = typeof data.description === "string" && data.description.trim().length > 0 ? data.description.trim() : `The ${name} command.`;
27802
+ const frontmatter = { name, description };
27803
+ for (const key of CARRIED_OVER) {
27804
+ if (data[key] !== void 0) {
27805
+ frontmatter[key] = data[key];
27806
+ }
27807
+ }
27808
+ frontmatter["disable-model-invocation"] = true;
27809
+ frontmatter["x-tangyr"] = {
27810
+ source: relativeSource,
27811
+ hash: computeSourceHash(commandFile),
27812
+ target
27813
+ };
27814
+ const content = `---
27815
+ ${(0, import_yaml9.stringify)(frontmatter).trimEnd()}
27816
+ ---
27817
+
27818
+ ${body.trim()}
27819
+ `;
27820
+ return { name, content, relativeSource };
27821
+ }
27822
+ function compileCommandsAsSkills(commandsRoot, target) {
27823
+ if (!fs38.existsSync(commandsRoot)) {
27824
+ return [];
27825
+ }
27826
+ return fs38.readdirSync(commandsRoot).filter((entry) => entry.endsWith(".md")).sort().map(
27827
+ (entry) => compileCommandAsSkill(path37.join(commandsRoot, entry), target)
27828
+ );
27829
+ }
27830
+
27782
27831
  // src/compiler/mcp.ts
27783
27832
  var TOML2 = __toESM(require_toml(), 1);
27784
27833
  import crypto5 from "crypto";
@@ -28058,9 +28107,9 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
28058
28107
  }
28059
28108
 
28060
28109
  // src/compiler/rules.ts
28061
- import path37 from "path";
28062
- var import_yaml9 = __toESM(require_dist(), 1);
28063
- import fs38 from "fs";
28110
+ import path38 from "path";
28111
+ var import_yaml10 = __toESM(require_dist(), 1);
28112
+ import fs39 from "fs";
28064
28113
  function compileRules(sourceRulesDir, target, _mappings, lossReport) {
28065
28114
  if (target === "copilot") {
28066
28115
  addLoss(lossReport, "copilot", "rules", {
@@ -28097,13 +28146,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
28097
28146
  }
28098
28147
  const appendixParts = [];
28099
28148
  const dotRulesFiles = [];
28100
- for (const ruleFile of ts(path37.join(sourceRulesDir, "*.md")).sort()) {
28149
+ for (const ruleFile of ts(path38.join(sourceRulesDir, "*.md")).sort()) {
28101
28150
  const parsed = parseRule(ruleFile);
28102
- const name = path37.basename(ruleFile, ".md");
28151
+ const name = path38.basename(ruleFile, ".md");
28103
28152
  if (parsed.mode === "exec-policy") {
28104
28153
  dotRulesFiles.push({
28105
28154
  name: `${name}.rules`,
28106
- content: `${formatProvenanceMarker("toml", `rules/${path37.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
28155
+ content: `${formatProvenanceMarker("toml", `rules/${path38.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
28107
28156
  ${parsed.body}`
28108
28157
  });
28109
28158
  continue;
@@ -28112,7 +28161,7 @@ ${parsed.body}`
28112
28161
 
28113
28162
  ${parsed.body.trim()}`);
28114
28163
  addLoss(lossReport, "codex", "rules", {
28115
- source: `rules/${path37.basename(ruleFile)}`,
28164
+ source: `rules/${path38.basename(ruleFile)}`,
28116
28165
  fields: [
28117
28166
  {
28118
28167
  field: "mode",
@@ -28122,7 +28171,7 @@ ${parsed.body.trim()}`);
28122
28171
  "mode",
28123
28172
  "rule-as-instruction"
28124
28173
  ),
28125
- detail: `${path37.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
28174
+ detail: `${path38.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
28126
28175
  }
28127
28176
  ]
28128
28177
  });
@@ -28130,7 +28179,7 @@ ${parsed.body.trim()}`);
28130
28179
  return { agentsAppendix: appendixParts.join("\n\n"), dotRulesFiles };
28131
28180
  }
28132
28181
  function parseRule(ruleFile) {
28133
- const content = fs38.readFileSync(ruleFile, "utf8");
28182
+ const content = fs39.readFileSync(ruleFile, "utf8");
28134
28183
  if (!content.startsWith("---\n")) {
28135
28184
  return { mode: "guidance", body: content };
28136
28185
  }
@@ -28138,7 +28187,7 @@ function parseRule(ruleFile) {
28138
28187
  if (endIndex === -1) {
28139
28188
  throw new Error(`${ruleFile}: frontmatter is not closed`);
28140
28189
  }
28141
- const frontmatter = (0, import_yaml9.parse)(content.slice(4, endIndex));
28190
+ const frontmatter = (0, import_yaml10.parse)(content.slice(4, endIndex));
28142
28191
  const mode = isRuleMode(frontmatter) ? frontmatter.mode : "guidance";
28143
28192
  return {
28144
28193
  mode,
@@ -28154,14 +28203,14 @@ function isRuleMode(value) {
28154
28203
  }
28155
28204
  function compileOpenCodeRules(sourceRulesDir, lossReport) {
28156
28205
  const appendixParts = [];
28157
- for (const ruleFile of ts(path37.join(sourceRulesDir, "*.md")).sort()) {
28206
+ for (const ruleFile of ts(path38.join(sourceRulesDir, "*.md")).sort()) {
28158
28207
  const parsed = parseRule(ruleFile);
28159
- const name = path37.basename(ruleFile, ".md");
28208
+ const name = path38.basename(ruleFile, ".md");
28160
28209
  appendixParts.push(`## ${name}
28161
28210
 
28162
28211
  ${parsed.body.trim()}`);
28163
28212
  addLoss(lossReport, "opencode", "rules", {
28164
- source: `rules/${path37.basename(ruleFile)}`,
28213
+ source: `rules/${path38.basename(ruleFile)}`,
28165
28214
  fields: [
28166
28215
  {
28167
28216
  field: "rule",
@@ -28171,7 +28220,7 @@ ${parsed.body.trim()}`);
28171
28220
  "rule",
28172
28221
  "rule-path-scoping"
28173
28222
  ),
28174
- detail: `${path37.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
28223
+ detail: `${path38.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
28175
28224
  }
28176
28225
  ]
28177
28226
  });
@@ -28180,9 +28229,9 @@ ${parsed.body.trim()}`);
28180
28229
  }
28181
28230
  function compileCursorRules(sourceRulesDir, _lossReport) {
28182
28231
  const dotRulesFiles = [];
28183
- for (const ruleFile of ts(path37.join(sourceRulesDir, "*.md")).sort()) {
28184
- const content = fs38.readFileSync(ruleFile, "utf8");
28185
- const name = path37.basename(ruleFile, ".md");
28232
+ for (const ruleFile of ts(path38.join(sourceRulesDir, "*.md")).sort()) {
28233
+ const content = fs39.readFileSync(ruleFile, "utf8");
28234
+ const name = path38.basename(ruleFile, ".md");
28186
28235
  let frontmatterData = {};
28187
28236
  let body = content;
28188
28237
  if (content.startsWith("---\n")) {
@@ -28190,7 +28239,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
28190
28239
  if (endIndex !== -1) {
28191
28240
  const frontmatterStr = content.slice(4, endIndex);
28192
28241
  try {
28193
- frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
28242
+ frontmatterData = (0, import_yaml10.parse)(frontmatterStr) ?? {};
28194
28243
  } catch {
28195
28244
  frontmatterData = {};
28196
28245
  }
@@ -28211,7 +28260,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
28211
28260
  }
28212
28261
  const marker = formatProvenanceMarker(
28213
28262
  "markdown",
28214
- `rules/${path37.basename(ruleFile)}`,
28263
+ `rules/${path38.basename(ruleFile)}`,
28215
28264
  computeSourceHash(ruleFile),
28216
28265
  "cursor"
28217
28266
  );
@@ -28227,9 +28276,9 @@ ${body}`;
28227
28276
  }
28228
28277
  function compileClineRules(sourceRulesDir, lossReport) {
28229
28278
  const dotRulesFiles = [];
28230
- for (const ruleFile of ts(path37.join(sourceRulesDir, "*.md")).sort()) {
28231
- const content = fs38.readFileSync(ruleFile, "utf8");
28232
- const name = path37.basename(ruleFile, ".md");
28279
+ for (const ruleFile of ts(path38.join(sourceRulesDir, "*.md")).sort()) {
28280
+ const content = fs39.readFileSync(ruleFile, "utf8");
28281
+ const name = path38.basename(ruleFile, ".md");
28233
28282
  let frontmatterData = {};
28234
28283
  let body = content;
28235
28284
  if (content.startsWith("---\n")) {
@@ -28237,7 +28286,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
28237
28286
  if (endIndex !== -1) {
28238
28287
  const frontmatterStr = content.slice(4, endIndex);
28239
28288
  try {
28240
- frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
28289
+ frontmatterData = (0, import_yaml10.parse)(frontmatterStr) ?? {};
28241
28290
  } catch {
28242
28291
  frontmatterData = {};
28243
28292
  }
@@ -28246,13 +28295,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
28246
28295
  }
28247
28296
  const marker = formatProvenanceMarker(
28248
28297
  "markdown",
28249
- `rules/${path37.basename(ruleFile)}`,
28298
+ `rules/${path38.basename(ruleFile)}`,
28250
28299
  computeSourceHash(ruleFile),
28251
28300
  "cline"
28252
28301
  );
28253
28302
  if (frontmatterData.mode === "exec-policy") {
28254
28303
  addLoss(lossReport, "cline", "rules", {
28255
- source: `rules/${path37.basename(ruleFile)}`,
28304
+ source: `rules/${path38.basename(ruleFile)}`,
28256
28305
  fields: [
28257
28306
  {
28258
28307
  field: "mode",
@@ -28262,7 +28311,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
28262
28311
  "mode",
28263
28312
  "rule-mode-downgrade"
28264
28313
  ),
28265
- detail: `${path37.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
28314
+ detail: `${path38.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
28266
28315
  }
28267
28316
  ]
28268
28317
  });
@@ -28281,14 +28330,39 @@ ${frontmatterYaml}${body}`;
28281
28330
  }
28282
28331
  return { agentsAppendix: "", dotRulesFiles };
28283
28332
  }
28333
+ function compileCopilotRules(sourceRulesDir) {
28334
+ if (!fs39.existsSync(sourceRulesDir)) {
28335
+ return [];
28336
+ }
28337
+ const files = [];
28338
+ for (const ruleFile of ts(path38.join(sourceRulesDir, "*.md")).sort()) {
28339
+ const name = path38.basename(ruleFile, ".md");
28340
+ const { data } = parseMarkdownFrontmatter(ruleFile);
28341
+ const { body } = parseRule(ruleFile);
28342
+ const declared = data.paths;
28343
+ const applyTo = Array.isArray(declared) ? declared.filter((p) => typeof p === "string").join(", ") : typeof declared === "string" && declared.trim() !== "" ? declared.trim() : "**";
28344
+ const frontmatter = [
28345
+ "---",
28346
+ `applyTo: ${JSON.stringify(applyTo)}`,
28347
+ "x-tangyr:",
28348
+ ` source: rules/${path38.basename(ruleFile)}`,
28349
+ ` hash: ${computeSourceHash(ruleFile)}`,
28350
+ " target: copilot",
28351
+ "---"
28352
+ ].join("\n");
28353
+ files.push({
28354
+ name: `${name}.instructions.md`,
28355
+ content: `${frontmatter}
28356
+
28357
+ ${body.trim()}
28358
+ `
28359
+ });
28360
+ }
28361
+ return files;
28362
+ }
28284
28363
 
28285
28364
  // src/adapters/codex.ts
28286
- var skippedComponents = [
28287
- "commands",
28288
- "settings",
28289
- "lsp",
28290
- "output-styles"
28291
- ];
28365
+ var skippedComponents = ["settings", "lsp", "output-styles"];
28292
28366
  var managedMcpStart = "# tangyr: managed mcp start";
28293
28367
  var managedMcpEnd = "# tangyr: managed mcp end";
28294
28368
  function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
@@ -28308,7 +28382,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28308
28382
  rules: profile.rules
28309
28383
  };
28310
28384
  const rules = compileRules(
28311
- path38.join(sourceRoot, config.source.rules),
28385
+ path39.join(sourceRoot, config.source.rules),
28312
28386
  "codex",
28313
28387
  mappings,
28314
28388
  lossReport
@@ -28344,7 +28418,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28344
28418
  }
28345
28419
  if (!shouldSkipComponent2(options, "skills")) {
28346
28420
  outcomes.push(
28347
- syncSkills(
28421
+ ...syncSkills(
28348
28422
  config,
28349
28423
  sourceRoot,
28350
28424
  paths,
@@ -28355,6 +28429,20 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28355
28429
  )
28356
28430
  );
28357
28431
  }
28432
+ if (!shouldSkipComponent2(options, "commands")) {
28433
+ outcomes.push(
28434
+ ...syncCommandsAsSkills(
28435
+ config,
28436
+ sourceRoot,
28437
+ paths,
28438
+ options,
28439
+ lossReport,
28440
+ logger,
28441
+ manifest,
28442
+ scopePath
28443
+ )
28444
+ );
28445
+ }
28358
28446
  if (!shouldSkipComponent2(options, "agents")) {
28359
28447
  outcomes.push(
28360
28448
  ...syncAgents(
@@ -28374,7 +28462,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28374
28462
  if (!shouldSkipComponent2(options, "hooks")) {
28375
28463
  outcomes.push(
28376
28464
  syncHookScriptsBridge({
28377
- source: path38.resolve(sourceRoot, config.source.hooks),
28465
+ source: path39.resolve(sourceRoot, config.source.hooks),
28378
28466
  destination: resolveTargetPath(paths.hook_scripts),
28379
28467
  config,
28380
28468
  sourceRoot,
@@ -28473,9 +28561,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28473
28561
  function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
28474
28562
  const cp = mappings.modelTiers.custom_provider;
28475
28563
  if (!cp) return "";
28476
- const agentsDir = path38.join(sourceRoot, config.source.agents);
28477
- if (!fs39.existsSync(agentsDir)) return "";
28478
- const agentFiles = ts(path38.join(agentsDir, "*.md")).sort();
28564
+ const agentsDir = path39.join(sourceRoot, config.source.agents);
28565
+ if (!fs40.existsSync(agentsDir)) return "";
28566
+ const agentFiles = ts(path39.join(agentsDir, "*.md")).sort();
28479
28567
  const hasProviderAgent = agentFiles.some((agentFile) => {
28480
28568
  const { data } = parseMarkdownFrontmatter(agentFile);
28481
28569
  return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
@@ -28540,7 +28628,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
28540
28628
  }
28541
28629
  ];
28542
28630
  for (const ruleFile of rules.dotRulesFiles) {
28543
- const destination = path38.join(rulesRoot, ruleFile.name);
28631
+ const destination = path39.join(rulesRoot, ruleFile.name);
28544
28632
  if (options.dryRun) {
28545
28633
  logger.info(`[dry-run] rules: write ${destination}`);
28546
28634
  outcomes.push({
@@ -28570,16 +28658,16 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
28570
28658
  function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
28571
28659
  const source = instructionsSourcePath(sourceRoot, config);
28572
28660
  const destination = resolveTargetPath(paths.instructions);
28573
- if (!fs39.existsSync(source)) {
28661
+ if (!fs40.existsSync(source)) {
28574
28662
  return skippedMissingSource2("instructions", source);
28575
28663
  }
28576
- const composed = `${fs39.readFileSync(source, "utf8").trim()}
28664
+ const composed = `${fs40.readFileSync(source, "utf8").trim()}
28577
28665
 
28578
28666
  --- tangyr managed rules ---
28579
28667
  ${agentsAppendix}`.trim();
28580
28668
  const marker = formatProvenanceMarker(
28581
28669
  "markdown",
28582
- path38.basename(instructionsSourceLabel(sourceRoot, config)),
28670
+ path39.basename(instructionsSourceLabel(sourceRoot, config)),
28583
28671
  hashString(composed),
28584
28672
  "codex"
28585
28673
  );
@@ -28606,47 +28694,66 @@ ${composed}
28606
28694
  );
28607
28695
  }
28608
28696
  function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopePath) {
28609
- const source = path38.resolve(sourceRoot, config.source.skills);
28610
- const destination = resolveTargetPath(paths.skills);
28611
- if (!fs39.existsSync(source)) {
28612
- return skippedMissingSource2("skills", source);
28613
- }
28614
- if (options.dryRun) {
28615
- logger.info(`[dry-run] skills: symlink ${source} -> ${destination}`);
28616
- return { component: "skills", status: "dry-run", path: destination };
28617
- }
28618
- const artifactClass = classifyArtifact(destination, config, sourceRoot);
28619
- if (artifactClass === "managed-symlink" && isSymlinkTo4(destination, source)) {
28620
- return {
28621
- component: "skills",
28622
- status: "skipped-current",
28623
- path: destination
28624
- };
28625
- }
28626
- if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
28627
- fs39.unlinkSync(destination);
28628
- logger.verbose(`Skills: created skills path ${destination}`);
28629
- } else if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
28630
- return { component: "skills", status: "conflict", path: destination };
28631
- } else if (artifactClass === "managed-symlink") {
28632
- fs39.unlinkSync(destination);
28697
+ return syncSkillsSlot({
28698
+ config,
28699
+ sourceRoot,
28700
+ source: path39.resolve(sourceRoot, config.source.skills),
28701
+ destination: resolveTargetPath(paths.skills),
28702
+ dryRun: options.dryRun,
28703
+ logger,
28704
+ onUnmanagedConflict: (conflictPath) => handleConflict2(
28705
+ conflictPath,
28706
+ config,
28707
+ options,
28708
+ logger,
28709
+ manifest,
28710
+ scopePath
28711
+ )
28712
+ });
28713
+ }
28714
+ function syncCommandsAsSkills(config, sourceRoot, paths, options, _lossReport, logger, manifest, scopePath) {
28715
+ const commandsRoot = path39.resolve(sourceRoot, config.source.commands);
28716
+ if (!fs40.existsSync(commandsRoot)) {
28717
+ return [skippedMissingSource2("commands", commandsRoot)];
28633
28718
  }
28634
- ensureDir(path38.dirname(destination));
28635
- createRelativeSymlink(source, destination, "dir");
28636
- logger.verbose(`Skills: created skills path ${destination}`);
28637
- return { component: "skills", status: "success", path: destination };
28719
+ const skillsRoot = resolveTargetPath(paths.skills);
28720
+ return compileCommandsAsSkills(commandsRoot, "codex").map((skill) => {
28721
+ const destination = path39.join(skillsRoot, skill.name, "SKILL.md");
28722
+ if (options.dryRun) {
28723
+ logger.info(
28724
+ `[dry-run] commands: compile ${skill.relativeSource} -> ${destination}`
28725
+ );
28726
+ return {
28727
+ component: "commands",
28728
+ status: "dry-run",
28729
+ path: destination
28730
+ };
28731
+ }
28732
+ return writeCompiledArtifact(
28733
+ "commands",
28734
+ destination,
28735
+ skill.content,
28736
+ void 0,
28737
+ config,
28738
+ sourceRoot,
28739
+ options,
28740
+ logger,
28741
+ manifest,
28742
+ scopePath
28743
+ );
28744
+ });
28638
28745
  }
28639
28746
  function syncAgents(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
28640
- const sourceAgentsRoot = path38.join(sourceRoot, config.source.agents);
28641
- if (!fs39.existsSync(sourceAgentsRoot)) {
28747
+ const sourceAgentsRoot = path39.join(sourceRoot, config.source.agents);
28748
+ if (!fs40.existsSync(sourceAgentsRoot)) {
28642
28749
  return [skippedMissingSource2("agents", sourceAgentsRoot)];
28643
28750
  }
28644
- const sourceAgents = ts(path38.join(sourceAgentsRoot, "*.md")).sort();
28751
+ const sourceAgents = ts(path39.join(sourceAgentsRoot, "*.md")).sort();
28645
28752
  const agentsRoot = resolveTargetPath(paths.agents);
28646
28753
  return sourceAgents.map((agentFile) => {
28647
- const destination = path38.join(
28754
+ const destination = path39.join(
28648
28755
  agentsRoot,
28649
- `${path38.basename(agentFile, ".md")}.toml`
28756
+ `${path39.basename(agentFile, ".md")}.toml`
28650
28757
  );
28651
28758
  const compiled = compileAgent(
28652
28759
  agentFile,
@@ -28724,7 +28831,7 @@ function syncHooks2(config, sourceRoot, paths, mappings, options, lossReport, lo
28724
28831
  destination,
28725
28832
  hostHooks,
28726
28833
  stringifyJson3,
28727
- !fs39.existsSync(destination),
28834
+ !fs40.existsSync(destination),
28728
28835
  logger
28729
28836
  );
28730
28837
  return {
@@ -28737,7 +28844,7 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger, provid
28737
28844
  const source = resolveMcpSourceFile(sourceRoot, config);
28738
28845
  const sourceLabel = mcpSourceLabel(config);
28739
28846
  const destination = resolveTargetPath(paths.mcp_shared_file);
28740
- if (!fs39.existsSync(source)) {
28847
+ if (!fs40.existsSync(source)) {
28741
28848
  if (providerToml && !options.dryRun) {
28742
28849
  const changed2 = writeTomlManagedSection(
28743
28850
  destination,
@@ -28752,7 +28859,7 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger, provid
28752
28859
  }
28753
28860
  return skippedMissingSource2("mcp", source);
28754
28861
  }
28755
- const sourceMcpJson = JSON.parse(fs39.readFileSync(source, "utf8"));
28862
+ const sourceMcpJson = JSON.parse(fs40.readFileSync(source, "utf8"));
28756
28863
  const compiled = compileMcp(sourceMcpJson, "codex", lossReport, sourceLabel);
28757
28864
  const managedContent = providerToml ? `${compiled.trimEnd()}${providerToml}` : compiled;
28758
28865
  if (options.dryRun) {
@@ -28777,18 +28884,18 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
28777
28884
  if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
28778
28885
  return { component, status: "conflict", path: destination };
28779
28886
  }
28780
- ensureDir(path38.dirname(destination));
28887
+ ensureDir(path39.dirname(destination));
28781
28888
  const clearedLink = clearSymlinkAtDestination(destination);
28782
28889
  if (clearedLink !== null) {
28783
28890
  logger.verbose(
28784
28891
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
28785
28892
  );
28786
28893
  }
28787
- fs39.writeFileSync(destination, content);
28894
+ fs40.writeFileSync(destination, content);
28788
28895
  return { component, status: "success", path: destination };
28789
28896
  }
28790
28897
  function writeTomlManagedSection(destination, managedContent, logger) {
28791
- const current = fs39.existsSync(destination) ? fs39.readFileSync(destination, "utf8") : "";
28898
+ const current = fs40.existsSync(destination) ? fs40.readFileSync(destination, "utf8") : "";
28792
28899
  const isFirstWrite = current.length > 0 && !current.includes(managedMcpStart);
28793
28900
  if (isFirstWrite) {
28794
28901
  logger.warn(
@@ -28804,8 +28911,8 @@ ${managedMcpEnd}
28804
28911
  if (current === next.trimStart()) {
28805
28912
  return false;
28806
28913
  }
28807
- ensureDir(path38.dirname(destination));
28808
- fs39.writeFileSync(destination, next.trimStart());
28914
+ ensureDir(path39.dirname(destination));
28915
+ fs40.writeFileSync(destination, next.trimStart());
28809
28916
  return true;
28810
28917
  }
28811
28918
  function removeManagedTomlSection(content) {
@@ -28831,7 +28938,7 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
28831
28938
  if (manifest && scopePath) {
28832
28939
  backupFile(destination, manifest, scopePath);
28833
28940
  writeManifest(scopePath, manifest);
28834
- fs39.rmSync(destination, { recursive: true, force: true });
28941
+ fs40.rmSync(destination, { recursive: true, force: true });
28835
28942
  } else {
28836
28943
  const parked = parkConflictingPath(
28837
28944
  destination,
@@ -28846,12 +28953,12 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
28846
28953
  }
28847
28954
  return true;
28848
28955
  }
28849
- fs39.rmSync(destination, { recursive: true, force: true });
28956
+ fs40.rmSync(destination, { recursive: true, force: true });
28850
28957
  return true;
28851
28958
  }
28852
28959
  function isCompiledCurrent(destination, expectedContent, _expectedHash) {
28853
28960
  try {
28854
- return fs39.readFileSync(destination, "utf8") === expectedContent;
28961
+ return fs40.readFileSync(destination, "utf8") === expectedContent;
28855
28962
  } catch {
28856
28963
  return false;
28857
28964
  }
@@ -28866,18 +28973,11 @@ function skippedMissingSource2(component, source) {
28866
28973
  function shouldSkipComponent2(options, component) {
28867
28974
  return Boolean(options.component && options.component !== component);
28868
28975
  }
28869
- function isSymlinkTo4(linkPath, source) {
28870
- try {
28871
- return fs39.realpathSync(linkPath) === fs39.realpathSync(source);
28872
- } catch {
28873
- return false;
28874
- }
28875
- }
28876
28976
  function readJsonObject4(filePath) {
28877
- if (!fs39.existsSync(filePath)) {
28977
+ if (!fs40.existsSync(filePath)) {
28878
28978
  return {};
28879
28979
  }
28880
- const parsed = JSON.parse(fs39.readFileSync(filePath, "utf8"));
28980
+ const parsed = JSON.parse(fs40.readFileSync(filePath, "utf8"));
28881
28981
  return isRecord5(parsed) ? parsed : {};
28882
28982
  }
28883
28983
  function stringifyJson3(value) {
@@ -28893,16 +28993,16 @@ function hashString(value) {
28893
28993
 
28894
28994
  // src/adapters/copilot.ts
28895
28995
  import crypto7 from "crypto";
28896
- import fs40 from "fs";
28897
- import path40 from "path";
28996
+ import fs41 from "fs";
28997
+ import path41 from "path";
28898
28998
 
28899
28999
  // src/compiler/commands.ts
28900
- var import_yaml10 = __toESM(require_dist(), 1);
28901
- import path39 from "path";
29000
+ var import_yaml11 = __toESM(require_dist(), 1);
29001
+ import path40 from "path";
28902
29002
  function compileCommandPrompt(sourceFile) {
28903
29003
  const { data, body } = parseMarkdownFrontmatter(sourceFile);
28904
- const relativeSource = `commands/${path39.basename(sourceFile)}`;
28905
- const fields = promptFrontmatter(data, path39.basename(sourceFile, ".md"));
29004
+ const relativeSource = `commands/${path40.basename(sourceFile)}`;
29005
+ const fields = promptFrontmatter(data, path40.basename(sourceFile, ".md"));
28906
29006
  const marker = formatProvenanceMarker(
28907
29007
  "markdown",
28908
29008
  relativeSource,
@@ -28911,7 +29011,7 @@ function compileCommandPrompt(sourceFile) {
28911
29011
  );
28912
29012
  return `${marker}
28913
29013
  ---
28914
- ${(0, import_yaml10.stringify)(fields).trim()}
29014
+ ${(0, import_yaml11.stringify)(fields).trim()}
28915
29015
  ---
28916
29016
 
28917
29017
  ${body.trimEnd()}
@@ -28935,12 +29035,7 @@ function promptFrontmatter(data, defaultName) {
28935
29035
  }
28936
29036
 
28937
29037
  // src/adapters/copilot.ts
28938
- var skippedComponents2 = [
28939
- "rules",
28940
- "settings",
28941
- "lsp",
28942
- "output-styles"
28943
- ];
29038
+ var skippedComponents2 = ["settings", "lsp", "output-styles"];
28944
29039
  var legacyCopilotAgentsPath = "~/.copilot/agents";
28945
29040
  function syncCopilot(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
28946
29041
  const scope = options.scope ?? "global";
@@ -28951,6 +29046,7 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
28951
29046
  }).copilot;
28952
29047
  const paths = {
28953
29048
  agents: profile.agents,
29049
+ rules: profile.rules,
28954
29050
  skills: profile.skills,
28955
29051
  prompts: profile.prompts,
28956
29052
  hooks: profile.hooks,
@@ -28984,6 +29080,36 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
28984
29080
  )
28985
29081
  );
28986
29082
  }
29083
+ if (!shouldSkipComponent3(options, "rules") && !paths.rules) {
29084
+ addLoss(lossReport, "copilot", "rules", {
29085
+ source: "rules",
29086
+ fields: [
29087
+ {
29088
+ field: "rules",
29089
+ action: "rule-path-scoping",
29090
+ severity: resolveLossSeverity(
29091
+ "agent-field",
29092
+ "rules",
29093
+ "rule-path-scoping"
29094
+ ),
29095
+ detail: "Rules: no user-level rules surface for Copilot; `.github/instructions` is a repository path and has no global equivalent"
29096
+ }
29097
+ ]
29098
+ });
29099
+ }
29100
+ if (!shouldSkipComponent3(options, "rules") && paths.rules) {
29101
+ outcomes.push(
29102
+ ...syncRules2(
29103
+ config,
29104
+ sourceRoot,
29105
+ paths.rules,
29106
+ options,
29107
+ logger,
29108
+ manifest,
29109
+ scopePath
29110
+ )
29111
+ );
29112
+ }
28987
29113
  if (!shouldSkipComponent3(options, "agents")) {
28988
29114
  outcomes.push(...cleanupLegacyAgents(paths, options, logger));
28989
29115
  outcomes.push(
@@ -29017,7 +29143,7 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
29017
29143
  if (!shouldSkipComponent3(options, "hooks")) {
29018
29144
  outcomes.push(
29019
29145
  syncHookScriptsBridge({
29020
- source: path40.resolve(sourceRoot, config.source.hooks),
29146
+ source: path41.resolve(sourceRoot, config.source.hooks),
29021
29147
  destination: resolveTargetPath(paths.hook_scripts),
29022
29148
  config,
29023
29149
  sourceRoot,
@@ -29098,13 +29224,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
29098
29224
  }
29099
29225
  function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
29100
29226
  if (!mappings.modelTiers.custom_provider) return;
29101
- const agentsDir = path40.join(sourceRoot, config.source.agents);
29102
- if (!fs40.existsSync(agentsDir)) return;
29103
- for (const agentFile of ts(path40.join(agentsDir, "*.md")).sort()) {
29227
+ const agentsDir = path41.join(sourceRoot, config.source.agents);
29228
+ if (!fs41.existsSync(agentsDir)) return;
29229
+ for (const agentFile of ts(path41.join(agentsDir, "*.md")).sort()) {
29104
29230
  const { data } = parseMarkdownFrontmatter(agentFile);
29105
29231
  const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
29106
29232
  if (hasProvider) {
29107
- const basename = path40.basename(agentFile);
29233
+ const basename = path41.basename(agentFile);
29108
29234
  addLoss(lossReport, "copilot", "agents", {
29109
29235
  source: `agents/${basename}`,
29110
29236
  fields: [
@@ -29130,22 +29256,22 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
29130
29256
  return [{ component: "instructions", status: "skipped", path: message }];
29131
29257
  }
29132
29258
  const source = instructionsSourcePath(sourceRoot, config);
29133
- if (!fs40.existsSync(source)) {
29259
+ if (!fs41.existsSync(source)) {
29134
29260
  return [skippedMissingSource3("instructions", source)];
29135
29261
  }
29136
- const rawContent = fs40.readFileSync(source, "utf8");
29262
+ const rawContent = fs41.readFileSync(source, "utf8");
29137
29263
  const contentHash = hashString2(rawContent);
29138
29264
  const marker = formatProvenanceMarker(
29139
29265
  "markdown",
29140
- path40.basename(instructionsSourceLabel(sourceRoot, config)),
29266
+ path41.basename(instructionsSourceLabel(sourceRoot, config)),
29141
29267
  contentHash,
29142
29268
  "copilot"
29143
29269
  );
29144
29270
  const composedContent = `${marker}
29145
29271
  ${rawContent}`;
29146
29272
  const projectRoot = options.projectRoot ?? process.cwd();
29147
- const agentsMdDest = path40.resolve(projectRoot, "AGENTS.md");
29148
- const mirrorDest = path40.resolve(
29273
+ const agentsMdDest = path41.resolve(projectRoot, "AGENTS.md");
29274
+ const mirrorDest = path41.resolve(
29149
29275
  projectRoot,
29150
29276
  ".github",
29151
29277
  "copilot-instructions.md"
@@ -29199,14 +29325,14 @@ function writeInstructionsFile(component, destination, content, contentHash, con
29199
29325
  if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
29200
29326
  return { component, status: "conflict", path: destination };
29201
29327
  }
29202
- ensureDir(path40.dirname(destination));
29328
+ ensureDir(path41.dirname(destination));
29203
29329
  const clearedLink = clearSymlinkAtDestination(destination);
29204
29330
  if (clearedLink !== null) {
29205
29331
  logger.verbose(
29206
29332
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
29207
29333
  );
29208
29334
  }
29209
- fs40.writeFileSync(destination, content);
29335
+ fs41.writeFileSync(destination, content);
29210
29336
  return { component, status: "success", path: destination };
29211
29337
  }
29212
29338
  function hashString2(value) {
@@ -29216,7 +29342,7 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
29216
29342
  return syncSkillsSlot({
29217
29343
  config,
29218
29344
  sourceRoot,
29219
- source: path40.resolve(sourceRoot, config.source.skills),
29345
+ source: path41.resolve(sourceRoot, config.source.skills),
29220
29346
  destination: resolveTargetPath(paths.skills),
29221
29347
  dryRun: options.dryRun,
29222
29348
  logger,
@@ -29231,16 +29357,16 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
29231
29357
  });
29232
29358
  }
29233
29359
  function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
29234
- const sourceAgentsRoot = path40.join(sourceRoot, config.source.agents);
29235
- if (!fs40.existsSync(sourceAgentsRoot)) {
29360
+ const sourceAgentsRoot = path41.join(sourceRoot, config.source.agents);
29361
+ if (!fs41.existsSync(sourceAgentsRoot)) {
29236
29362
  return [skippedMissingSource3("agents", sourceAgentsRoot)];
29237
29363
  }
29238
- const sourceAgents = ts(path40.join(sourceAgentsRoot, "*.md")).sort();
29364
+ const sourceAgents = ts(path41.join(sourceAgentsRoot, "*.md")).sort();
29239
29365
  const agentsRoot = resolveTargetPath(paths.agents);
29240
29366
  return sourceAgents.map((agentFile) => {
29241
- const destination = path40.join(
29367
+ const destination = path41.join(
29242
29368
  agentsRoot,
29243
- `${path40.basename(agentFile, ".md")}.agent.md`
29369
+ `${path41.basename(agentFile, ".md")}.agent.md`
29244
29370
  );
29245
29371
  const compiled = compileAgent(
29246
29372
  agentFile,
@@ -29268,16 +29394,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
29268
29394
  });
29269
29395
  }
29270
29396
  function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
29271
- const sourceCommandsRoot = path40.join(sourceRoot, config.source.commands);
29272
- if (!fs40.existsSync(sourceCommandsRoot)) {
29397
+ const sourceCommandsRoot = path41.join(sourceRoot, config.source.commands);
29398
+ if (!fs41.existsSync(sourceCommandsRoot)) {
29273
29399
  return [skippedMissingSource3("commands", sourceCommandsRoot)];
29274
29400
  }
29275
- const sourceCommands = ts(path40.join(sourceCommandsRoot, "*.md")).sort();
29401
+ const sourceCommands = ts(path41.join(sourceCommandsRoot, "*.md")).sort();
29276
29402
  const promptsRoot = resolveTargetPath(paths.prompts);
29277
29403
  return sourceCommands.map((commandFile) => {
29278
- const destination = path40.join(
29404
+ const destination = path41.join(
29279
29405
  promptsRoot,
29280
- `${path40.basename(commandFile, ".md")}.prompt.md`
29406
+ `${path41.basename(commandFile, ".md")}.prompt.md`
29281
29407
  );
29282
29408
  const compiled = compileCommandPrompt(commandFile);
29283
29409
  if (options.dryRun) {
@@ -29301,7 +29427,7 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
29301
29427
  });
29302
29428
  }
29303
29429
  function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, logger) {
29304
- const destination = path40.join(
29430
+ const destination = path41.join(
29305
29431
  resolveTargetPath(paths.hooks),
29306
29432
  "tangyr-managed.json"
29307
29433
  );
@@ -29364,10 +29490,10 @@ function syncMcp3(config, sourceRoot, paths, options, lossReport, logger) {
29364
29490
  const source = resolveMcpSourceFile(sourceRoot, config);
29365
29491
  const sourceLabel = mcpSourceLabel(config);
29366
29492
  const destination = resolveTargetPath(paths.mcp_shared_file);
29367
- if (!fs40.existsSync(source)) {
29493
+ if (!fs41.existsSync(source)) {
29368
29494
  return skippedMissingSource3("mcp", source);
29369
29495
  }
29370
- const sourceMcpJson = JSON.parse(fs40.readFileSync(source, "utf8"));
29496
+ const sourceMcpJson = JSON.parse(fs41.readFileSync(source, "utf8"));
29371
29497
  const compiled = compileMcp(
29372
29498
  sourceMcpJson,
29373
29499
  "copilot",
@@ -29389,6 +29515,36 @@ function syncMcp3(config, sourceRoot, paths, options, lossReport, logger) {
29389
29515
  logger
29390
29516
  );
29391
29517
  }
29518
+ function syncRules2(config, sourceRoot, rulesSlot, options, logger, manifest, scopePath) {
29519
+ const sourceRulesDir = path41.resolve(sourceRoot, config.source.rules);
29520
+ if (!fs41.existsSync(sourceRulesDir)) {
29521
+ return [skippedMissingSource3("rules", sourceRulesDir)];
29522
+ }
29523
+ const destinationRoot = resolveTargetPath(rulesSlot);
29524
+ return compileCopilotRules(sourceRulesDir).map((file) => {
29525
+ const destination = path41.join(destinationRoot, file.name);
29526
+ if (options.dryRun) {
29527
+ logger.info(`[dry-run] rules: compile -> ${destination}`);
29528
+ return {
29529
+ component: "rules",
29530
+ status: "dry-run",
29531
+ path: destination
29532
+ };
29533
+ }
29534
+ return writeCompiledArtifact2(
29535
+ "rules",
29536
+ destination,
29537
+ file.content,
29538
+ void 0,
29539
+ config,
29540
+ sourceRoot,
29541
+ options,
29542
+ logger,
29543
+ manifest,
29544
+ scopePath
29545
+ );
29546
+ });
29547
+ }
29392
29548
  function writeCompiledArtifact2(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
29393
29549
  if (!options.force && isCompiledCurrent2(destination, content, expectedHash)) {
29394
29550
  return { component, status: "skipped-current", path: destination };
@@ -29400,19 +29556,19 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
29400
29556
  if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
29401
29557
  return { component, status: "conflict", path: destination };
29402
29558
  }
29403
- ensureDir(path40.dirname(destination));
29559
+ ensureDir(path41.dirname(destination));
29404
29560
  const clearedLink = clearSymlinkAtDestination(destination);
29405
29561
  if (clearedLink !== null) {
29406
29562
  logger.verbose(
29407
29563
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
29408
29564
  );
29409
29565
  }
29410
- fs40.writeFileSync(destination, content);
29566
+ fs41.writeFileSync(destination, content);
29411
29567
  return { component, status: "success", path: destination };
29412
29568
  }
29413
29569
  function isCompiledCurrent2(destination, expectedContent, _expectedHash) {
29414
29570
  try {
29415
- return fs40.readFileSync(destination, "utf8") === expectedContent;
29571
+ return fs41.readFileSync(destination, "utf8") === expectedContent;
29416
29572
  } catch {
29417
29573
  return false;
29418
29574
  }
@@ -29432,7 +29588,7 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
29432
29588
  if (manifest && scopePath) {
29433
29589
  backupFile(destination, manifest, scopePath);
29434
29590
  writeManifest(scopePath, manifest);
29435
- fs40.rmSync(destination, { recursive: true, force: true });
29591
+ fs41.rmSync(destination, { recursive: true, force: true });
29436
29592
  } else {
29437
29593
  const parked = parkConflictingPath(
29438
29594
  destination,
@@ -29447,7 +29603,7 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
29447
29603
  }
29448
29604
  return true;
29449
29605
  }
29450
- fs40.rmSync(destination, { recursive: true, force: true });
29606
+ fs41.rmSync(destination, { recursive: true, force: true });
29451
29607
  return true;
29452
29608
  }
29453
29609
  function shouldSkipComponent3(options, component) {
@@ -29456,12 +29612,12 @@ function shouldSkipComponent3(options, component) {
29456
29612
  function cleanupLegacyAgents(paths, options, logger) {
29457
29613
  const currentAgentsRoot = resolveTargetPath(paths.agents);
29458
29614
  const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
29459
- if (path40.resolve(currentAgentsRoot) === path40.resolve(legacyAgentsRoot)) {
29615
+ if (path41.resolve(currentAgentsRoot) === path41.resolve(legacyAgentsRoot)) {
29460
29616
  return [];
29461
29617
  }
29462
29618
  const outcomes = [];
29463
29619
  for (const filePath of ts(
29464
- path40.join(legacyAgentsRoot, "*.agent.md")
29620
+ path41.join(legacyAgentsRoot, "*.agent.md")
29465
29621
  ).sort()) {
29466
29622
  if (!isCopilotManagedCompiledFile(filePath)) {
29467
29623
  continue;
@@ -29471,14 +29627,14 @@ function cleanupLegacyAgents(paths, options, logger) {
29471
29627
  outcomes.push({ component: "agents", status: "dry-run", path: filePath });
29472
29628
  continue;
29473
29629
  }
29474
- fs40.rmSync(filePath, { force: true });
29630
+ fs41.rmSync(filePath, { force: true });
29475
29631
  outcomes.push({ component: "agents", status: "success", path: filePath });
29476
29632
  }
29477
29633
  return outcomes;
29478
29634
  }
29479
29635
  function isCopilotManagedCompiledFile(filePath) {
29480
29636
  try {
29481
- return extractProvenanceMarker(fs40.readFileSync(filePath, "utf8"))?.target === "copilot";
29637
+ return extractProvenanceMarker(fs41.readFileSync(filePath, "utf8"))?.target === "copilot";
29482
29638
  } catch {
29483
29639
  return false;
29484
29640
  }
@@ -29493,8 +29649,8 @@ function skippedMissingSource3(component, source) {
29493
29649
 
29494
29650
  // src/adapters/cursor.ts
29495
29651
  import crypto8 from "crypto";
29496
- import fs41 from "fs";
29497
- import path41 from "path";
29652
+ import fs42 from "fs";
29653
+ import path42 from "path";
29498
29654
  function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
29499
29655
  const scope = options.scope ?? "global";
29500
29656
  const profile = resolveTargetPaths({
@@ -29547,7 +29703,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
29547
29703
  }
29548
29704
  if (!shouldSkipComponent4(options, "rules")) {
29549
29705
  outcomes.push(
29550
- ...syncRules2(
29706
+ ...syncRules3(
29551
29707
  config,
29552
29708
  sourceRoot,
29553
29709
  paths,
@@ -29562,7 +29718,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
29562
29718
  }
29563
29719
  if (!shouldSkipComponent4(options, "skills")) {
29564
29720
  outcomes.push(
29565
- syncSkills3(
29721
+ ...syncSkills3(
29566
29722
  config,
29567
29723
  sourceRoot,
29568
29724
  options,
@@ -29576,7 +29732,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
29576
29732
  )
29577
29733
  );
29578
29734
  outcomes.push(
29579
- syncSkills3(
29735
+ ...syncSkills3(
29580
29736
  config,
29581
29737
  sourceRoot,
29582
29738
  options,
@@ -29606,7 +29762,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
29606
29762
  if (!shouldSkipComponent4(options, "hooks")) {
29607
29763
  outcomes.push(
29608
29764
  syncHookScriptsBridge({
29609
- source: path41.resolve(sourceRoot, config.source.hooks),
29765
+ source: path42.resolve(sourceRoot, config.source.hooks),
29610
29766
  destination: resolveTargetPath(paths.hook_scripts),
29611
29767
  config,
29612
29768
  sourceRoot,
@@ -29671,7 +29827,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
29671
29827
  const composed = composeCursorInstructions(config, sourceRoot, lossReport);
29672
29828
  const marker = formatProvenanceMarker(
29673
29829
  "markdown",
29674
- path41.basename(instructionsSourceLabel(sourceRoot, config)),
29830
+ path42.basename(instructionsSourceLabel(sourceRoot, config)),
29675
29831
  hashString3(composed),
29676
29832
  "cursor"
29677
29833
  );
@@ -29697,7 +29853,7 @@ ${composed}
29697
29853
  }
29698
29854
  function composeCursorInstructions(config, sourceRoot, lossReport) {
29699
29855
  const source = instructionsSourcePath(sourceRoot, config);
29700
- const baseContent = fs41.existsSync(source) ? fs41.readFileSync(source, "utf8").trim() : "";
29856
+ const baseContent = fs42.existsSync(source) ? fs42.readFileSync(source, "utf8").trim() : "";
29701
29857
  const personaContent = extractPrimaryPersonaContent(
29702
29858
  config,
29703
29859
  sourceRoot,
@@ -29710,11 +29866,11 @@ function composeCursorInstructions(config, sourceRoot, lossReport) {
29710
29866
  ${personaContent}`.trim() : baseContent;
29711
29867
  }
29712
29868
  function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
29713
- const agentsDir = path41.join(sourceRoot, config.source.agents);
29714
- if (!fs41.existsSync(agentsDir)) {
29869
+ const agentsDir = path42.join(sourceRoot, config.source.agents);
29870
+ if (!fs42.existsSync(agentsDir)) {
29715
29871
  return null;
29716
29872
  }
29717
- const agentFiles = ts(path41.join(agentsDir, "*.md")).sort();
29873
+ const agentFiles = ts(path42.join(agentsDir, "*.md")).sort();
29718
29874
  if (agentFiles.length === 0) {
29719
29875
  return null;
29720
29876
  }
@@ -29737,7 +29893,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
29737
29893
  return null;
29738
29894
  }
29739
29895
  addLoss(lossReport, "cursor", "instructions", {
29740
- source: `agents/${path41.basename(primaryFile)}`,
29896
+ source: `agents/${path42.basename(primaryFile)}`,
29741
29897
  fields: [
29742
29898
  {
29743
29899
  field: "persona",
@@ -29747,23 +29903,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
29747
29903
  "persona",
29748
29904
  "instructions-shim"
29749
29905
  ),
29750
- detail: `Primary persona from ${path41.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
29906
+ detail: `Primary persona from ${path42.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
29751
29907
  }
29752
29908
  ]
29753
29909
  });
29754
29910
  return body.trim();
29755
29911
  }
29756
29912
  function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
29757
- const sourceAgentsRoot = path41.join(sourceRoot, config.source.agents);
29758
- if (!fs41.existsSync(sourceAgentsRoot)) {
29913
+ const sourceAgentsRoot = path42.join(sourceRoot, config.source.agents);
29914
+ if (!fs42.existsSync(sourceAgentsRoot)) {
29759
29915
  return [skippedMissingSource4("agents", sourceAgentsRoot)];
29760
29916
  }
29761
- const sourceAgents = ts(path41.join(sourceAgentsRoot, "*.md")).sort();
29917
+ const sourceAgents = ts(path42.join(sourceAgentsRoot, "*.md")).sort();
29762
29918
  const agentsRoot = resolveTargetPath(paths.agents);
29763
29919
  return sourceAgents.map((agentFile) => {
29764
- const destination = path41.join(
29920
+ const destination = path42.join(
29765
29921
  agentsRoot,
29766
- `${path41.basename(agentFile, ".md")}.md`
29922
+ `${path42.basename(agentFile, ".md")}.md`
29767
29923
  );
29768
29924
  let compiled;
29769
29925
  try {
@@ -29803,15 +29959,15 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
29803
29959
  );
29804
29960
  });
29805
29961
  }
29806
- function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
29807
- const sourceRulesDir = path41.join(sourceRoot, config.source.rules);
29808
- if (!fs41.existsSync(sourceRulesDir)) {
29962
+ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
29963
+ const sourceRulesDir = path42.join(sourceRoot, config.source.rules);
29964
+ if (!fs42.existsSync(sourceRulesDir)) {
29809
29965
  return [skippedMissingSource4("rules", sourceRulesDir)];
29810
29966
  }
29811
29967
  const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
29812
29968
  const rulesDir = resolveTargetPath(paths.rules);
29813
29969
  return compiled.dotRulesFiles.map(({ name, content }) => {
29814
- const destination = path41.join(rulesDir, name);
29970
+ const destination = path42.join(rulesDir, name);
29815
29971
  if (options.dryRun) {
29816
29972
  logger.info(`[dry-run] rules: write ${destination}`);
29817
29973
  return {
@@ -29835,30 +29991,16 @@ function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, lo
29835
29991
  });
29836
29992
  }
29837
29993
  function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
29838
- const sourceCommandsRoot = path41.join(sourceRoot, config.source.commands);
29839
- if (!fs41.existsSync(sourceCommandsRoot)) {
29994
+ const sourceCommandsRoot = path42.join(sourceRoot, config.source.commands);
29995
+ if (!fs42.existsSync(sourceCommandsRoot)) {
29840
29996
  return [skippedMissingSource4("commands", sourceCommandsRoot)];
29841
29997
  }
29842
- const sourceCommands = ts(path41.join(sourceCommandsRoot, "*.md")).sort();
29998
+ const sourceCommands = ts(path42.join(sourceCommandsRoot, "*.md")).sort();
29843
29999
  const skillsRoot = resolveTargetPath(paths.skills);
29844
30000
  return sourceCommands.map((commandFile) => {
29845
- const baseName = path41.basename(commandFile, ".md");
29846
- const destination = path41.join(skillsRoot, baseName, "SKILL.md");
29847
- const commandContent = fs41.readFileSync(commandFile, "utf8");
29848
- const relativeSource = `commands/${path41.basename(commandFile)}`;
29849
- const marker = formatProvenanceMarker(
29850
- "markdown",
29851
- relativeSource,
29852
- computeSourceHash(commandFile),
29853
- "cursor"
29854
- );
29855
- const content = `${marker}
29856
- ---
29857
- disable-model-invocation: true
29858
- ---
29859
-
29860
- ${commandContent.trim()}
29861
- `;
30001
+ const baseName = path42.basename(commandFile, ".md");
30002
+ const destination = path42.join(skillsRoot, baseName, "SKILL.md");
30003
+ const { content } = compileCommandAsSkill(commandFile, "cursor");
29862
30004
  if (options.dryRun) {
29863
30005
  logger.info(
29864
30006
  `[dry-run] commands: compile ${commandFile} -> ${destination}`
@@ -29883,39 +30025,23 @@ ${commandContent.trim()}
29883
30025
  );
29884
30026
  });
29885
30027
  }
29886
- function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, component = "skills", destination = "", asSymlink = false) {
29887
- const source = path41.resolve(sourceRoot, config.source.skills);
29888
- if (!fs41.existsSync(source)) {
29889
- return skippedMissingSource4(component, source);
29890
- }
29891
- if (options.dryRun) {
29892
- const verb = asSymlink ? "symlink" : "ensuredir";
29893
- logger.info(`[dry-run] ${component}: ${verb} ${source} -> ${destination}`);
29894
- return { component, status: "dry-run", path: destination };
29895
- }
29896
- if (asSymlink) {
29897
- const artifactClass = classifyArtifact(destination, config, sourceRoot);
29898
- if (artifactClass === "managed-symlink" && isSymlinkTo5(destination, source)) {
29899
- return { component, status: "skipped-current", path: destination };
29900
- }
29901
- if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
29902
- fs41.unlinkSync(destination);
29903
- } else if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
29904
- return { component, status: "conflict", path: destination };
29905
- } else if (artifactClass === "managed-symlink") {
29906
- fs41.unlinkSync(destination);
29907
- }
29908
- ensureDir(path41.dirname(destination));
29909
- createRelativeSymlink(source, destination, "dir");
29910
- logger.verbose(`Skills: created shared skills symlink ${destination}`);
29911
- return { component, status: "success", path: destination };
29912
- }
29913
- if (fs41.existsSync(destination)) {
29914
- return { component, status: "skipped-current", path: destination };
29915
- }
29916
- ensureDir(destination);
29917
- logger.verbose(`Skills: ensured Cursor-local skills dir ${destination}`);
29918
- return { component, status: "success", path: destination };
30028
+ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, _component = "skills", destination = "", _asSymlink = false) {
30029
+ return syncSkillsSlot({
30030
+ config,
30031
+ sourceRoot,
30032
+ source: path42.resolve(sourceRoot, config.source.skills),
30033
+ destination,
30034
+ dryRun: options.dryRun,
30035
+ logger,
30036
+ onUnmanagedConflict: (conflictPath) => handleConflict4(
30037
+ conflictPath,
30038
+ config,
30039
+ options,
30040
+ logger,
30041
+ manifest,
30042
+ scopePath
30043
+ )
30044
+ });
29919
30045
  }
29920
30046
  function syncHooks4(config, sourceRoot, paths, mappings, options, lossReport, logger) {
29921
30047
  const scripts = hookScriptsDir(
@@ -29951,18 +30077,18 @@ function syncHooks4(config, sourceRoot, paths, mappings, options, lossReport, lo
29951
30077
  }
29952
30078
  const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
29953
30079
  `;
29954
- ensureDir(path41.dirname(destination));
29955
- fs41.writeFileSync(destination, hooksFileContent);
30080
+ ensureDir(path42.dirname(destination));
30081
+ fs42.writeFileSync(destination, hooksFileContent);
29956
30082
  return { component: "hooks", status: "success", path: destination };
29957
30083
  }
29958
30084
  function syncMcp4(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
29959
30085
  const source = resolveMcpSourceFile(sourceRoot, config);
29960
30086
  const sourceLabel = mcpSourceLabel(config);
29961
30087
  const destination = resolveTargetPath(paths.mcp_file);
29962
- if (!fs41.existsSync(source)) {
30088
+ if (!fs42.existsSync(source)) {
29963
30089
  return skippedMissingSource4("mcp", source);
29964
30090
  }
29965
- const sourceMcpJson = JSON.parse(fs41.readFileSync(source, "utf8"));
30091
+ const sourceMcpJson = JSON.parse(fs42.readFileSync(source, "utf8"));
29966
30092
  const mcpJson = compileMcp(sourceMcpJson, "cursor", lossReport, sourceLabel);
29967
30093
  if (options.dryRun) {
29968
30094
  logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
@@ -30015,13 +30141,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
30015
30141
  );
30016
30142
  }
30017
30143
  function syncProviderPin(config, sourceRoot, lossReport) {
30018
- const agentsDir = path41.join(sourceRoot, config.source.agents);
30019
- if (!fs41.existsSync(agentsDir)) return;
30020
- for (const agentFile of ts(path41.join(agentsDir, "*.md")).sort()) {
30144
+ const agentsDir = path42.join(sourceRoot, config.source.agents);
30145
+ if (!fs42.existsSync(agentsDir)) return;
30146
+ for (const agentFile of ts(path42.join(agentsDir, "*.md")).sort()) {
30021
30147
  const { data } = parseMarkdownFrontmatter(agentFile);
30022
30148
  const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
30023
30149
  if (hasCustomProvider) {
30024
- const relativeSource = `agents/${path41.basename(agentFile)}`;
30150
+ const relativeSource = `agents/${path42.basename(agentFile)}`;
30025
30151
  addLoss(lossReport, "cursor", "agents", {
30026
30152
  source: relativeSource,
30027
30153
  fields: [
@@ -30033,7 +30159,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
30033
30159
  "provider",
30034
30160
  "provider-not-representable"
30035
30161
  ),
30036
- detail: `${path41.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
30162
+ detail: `${path42.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
30037
30163
  }
30038
30164
  ]
30039
30165
  });
@@ -30051,14 +30177,14 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
30051
30177
  if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
30052
30178
  return { component, status: "conflict", path: destination };
30053
30179
  }
30054
- ensureDir(path41.dirname(destination));
30180
+ ensureDir(path42.dirname(destination));
30055
30181
  const clearedLink = clearSymlinkAtDestination(destination);
30056
30182
  if (clearedLink !== null) {
30057
30183
  logger.verbose(
30058
30184
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
30059
30185
  );
30060
30186
  }
30061
- fs41.writeFileSync(destination, content);
30187
+ fs42.writeFileSync(destination, content);
30062
30188
  return { component, status: "success", path: destination };
30063
30189
  }
30064
30190
  function handleConflict4(destination, config, options, logger, manifest, scopePath) {
@@ -30076,7 +30202,7 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
30076
30202
  if (manifest && scopePath) {
30077
30203
  backupFile(destination, manifest, scopePath);
30078
30204
  writeManifest(scopePath, manifest);
30079
- fs41.rmSync(destination, { recursive: true, force: true });
30205
+ fs42.rmSync(destination, { recursive: true, force: true });
30080
30206
  } else {
30081
30207
  const parked = parkConflictingPath(
30082
30208
  destination,
@@ -30091,12 +30217,12 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
30091
30217
  }
30092
30218
  return true;
30093
30219
  }
30094
- fs41.rmSync(destination, { recursive: true, force: true });
30220
+ fs42.rmSync(destination, { recursive: true, force: true });
30095
30221
  return true;
30096
30222
  }
30097
30223
  function isCompiledCurrent3(destination, expectedContent, _expectedHash) {
30098
30224
  try {
30099
- return fs41.readFileSync(destination, "utf8") === expectedContent;
30225
+ return fs42.readFileSync(destination, "utf8") === expectedContent;
30100
30226
  } catch {
30101
30227
  return false;
30102
30228
  }
@@ -30111,21 +30237,14 @@ function skippedMissingSource4(component, source) {
30111
30237
  function shouldSkipComponent4(options, component) {
30112
30238
  return Boolean(options.component && options.component !== component);
30113
30239
  }
30114
- function isSymlinkTo5(linkPath, source) {
30115
- try {
30116
- return fs41.realpathSync(linkPath) === fs41.realpathSync(source);
30117
- } catch {
30118
- return false;
30119
- }
30120
- }
30121
30240
  function hashString3(value) {
30122
30241
  return `sha256:${crypto8.createHash("sha256").update(value).digest("hex")}`;
30123
30242
  }
30124
30243
 
30125
30244
  // src/adapters/cline.ts
30126
30245
  import crypto9 from "crypto";
30127
- import fs42 from "fs";
30128
- import path42 from "path";
30246
+ import fs43 from "fs";
30247
+ import path43 from "path";
30129
30248
  function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
30130
30249
  const scope = options.scope ?? "global";
30131
30250
  const profile = resolveTargetPaths({
@@ -30172,7 +30291,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
30172
30291
  }
30173
30292
  if (!shouldSkipComponent5(options, "rules")) {
30174
30293
  outcomes.push(
30175
- ...syncRules3(
30294
+ ...syncRules4(
30176
30295
  config,
30177
30296
  sourceRoot,
30178
30297
  paths,
@@ -30200,7 +30319,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
30200
30319
  }
30201
30320
  if (!shouldSkipComponent5(options, "skills")) {
30202
30321
  outcomes.push(
30203
- syncSkills4(
30322
+ ...syncSkills4(
30204
30323
  config,
30205
30324
  sourceRoot,
30206
30325
  paths,
@@ -30238,7 +30357,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
30238
30357
  function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
30239
30358
  if (scope === "global" || paths.instructions === null) {
30240
30359
  addLoss(lossReport, "cline", "instructions", {
30241
- source: path42.basename(instructionsSourceLabel(sourceRoot, config)),
30360
+ source: path43.basename(instructionsSourceLabel(sourceRoot, config)),
30242
30361
  fields: [
30243
30362
  {
30244
30363
  field: "instructions",
@@ -30260,10 +30379,10 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
30260
30379
  }
30261
30380
  const source = instructionsSourcePath(sourceRoot, config);
30262
30381
  const destination = resolveTargetPath(paths.instructions);
30263
- const baseContent = fs42.existsSync(source) ? fs42.readFileSync(source, "utf8").trim() : "";
30382
+ const baseContent = fs43.existsSync(source) ? fs43.readFileSync(source, "utf8").trim() : "";
30264
30383
  const marker = formatProvenanceMarker(
30265
30384
  "markdown",
30266
- path42.basename(instructionsSourceLabel(sourceRoot, config)),
30385
+ path43.basename(instructionsSourceLabel(sourceRoot, config)),
30267
30386
  hashString4(baseContent),
30268
30387
  "cline"
30269
30388
  );
@@ -30288,11 +30407,11 @@ ${baseContent}
30288
30407
  );
30289
30408
  }
30290
30409
  function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
30291
- const sourceAgentsRoot = path42.join(sourceRoot, config.source.agents);
30292
- if (!fs42.existsSync(sourceAgentsRoot)) {
30410
+ const sourceAgentsRoot = path43.join(sourceRoot, config.source.agents);
30411
+ if (!fs43.existsSync(sourceAgentsRoot)) {
30293
30412
  return [skippedMissingSource5("agents", sourceAgentsRoot)];
30294
30413
  }
30295
- const sourceAgents = ts(path42.join(sourceAgentsRoot, "*.md")).sort();
30414
+ const sourceAgents = ts(path43.join(sourceAgentsRoot, "*.md")).sort();
30296
30415
  return sourceAgents.map((agentFile) => {
30297
30416
  compileAgent(agentFile, "cline", mappings, extensions, lossReport);
30298
30417
  if (options.dryRun) {
@@ -30307,15 +30426,15 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
30307
30426
  };
30308
30427
  });
30309
30428
  }
30310
- function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
30311
- const sourceRulesDir = path42.join(sourceRoot, config.source.rules);
30312
- if (!fs42.existsSync(sourceRulesDir)) {
30429
+ function syncRules4(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
30430
+ const sourceRulesDir = path43.join(sourceRoot, config.source.rules);
30431
+ if (!fs43.existsSync(sourceRulesDir)) {
30313
30432
  return [skippedMissingSource5("rules", sourceRulesDir)];
30314
30433
  }
30315
30434
  const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
30316
30435
  const rulesDir = resolveTargetPath(paths.rules);
30317
30436
  return compiled.dotRulesFiles.map(({ name, content }) => {
30318
- const destination = path42.join(rulesDir, name);
30437
+ const destination = path43.join(rulesDir, name);
30319
30438
  if (options.dryRun) {
30320
30439
  logger.info(`[dry-run] rules: write ${destination}`);
30321
30440
  return {
@@ -30339,17 +30458,17 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
30339
30458
  });
30340
30459
  }
30341
30460
  function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
30342
- const sourceCommandsRoot = path42.join(sourceRoot, config.source.commands);
30343
- if (!fs42.existsSync(sourceCommandsRoot)) {
30461
+ const sourceCommandsRoot = path43.join(sourceRoot, config.source.commands);
30462
+ if (!fs43.existsSync(sourceCommandsRoot)) {
30344
30463
  return [skippedMissingSource5("commands", sourceCommandsRoot)];
30345
30464
  }
30346
- const sourceCommands = ts(path42.join(sourceCommandsRoot, "*.md")).sort();
30465
+ const sourceCommands = ts(path43.join(sourceCommandsRoot, "*.md")).sort();
30347
30466
  const workflowsRoot = resolveTargetPath(paths.workflows);
30348
30467
  return sourceCommands.map((commandFile) => {
30349
- const baseName = path42.basename(commandFile);
30350
- const destination = path42.join(workflowsRoot, baseName);
30351
- const commandContent = fs42.readFileSync(commandFile, "utf8");
30352
- const relativeSource = `commands/${path42.basename(commandFile)}`;
30468
+ const baseName = path43.basename(commandFile);
30469
+ const destination = path43.join(workflowsRoot, baseName);
30470
+ const commandContent = fs43.readFileSync(commandFile, "utf8");
30471
+ const relativeSource = `commands/${path43.basename(commandFile)}`;
30353
30472
  const marker = formatProvenanceMarker(
30354
30473
  "markdown",
30355
30474
  relativeSource,
@@ -30384,44 +30503,22 @@ ${commandContent.trim()}
30384
30503
  });
30385
30504
  }
30386
30505
  function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
30387
- const source = path42.resolve(sourceRoot, config.source.skills);
30388
- const destination = resolveTargetPath(paths.skills);
30389
- if (!fs42.existsSync(source)) {
30390
- return skippedMissingSource5("skills", source);
30391
- }
30392
- if (options.dryRun) {
30393
- logger.info(`[dry-run] skills: symlink ${source} -> ${destination}`);
30394
- return { component: "skills", status: "dry-run", path: destination };
30395
- }
30396
- const artifactClass = classifyArtifact(destination, config, sourceRoot);
30397
- if (artifactClass === "managed-symlink" && isSymlinkTo6(destination, source)) {
30398
- return {
30399
- component: "skills",
30400
- status: "skipped-current",
30401
- path: destination
30402
- };
30403
- }
30404
- if (
30405
- // A stale symlink from a superseded source root. Every other adapter
30406
- // unlinks it here; this one did not, so classifyArtifact's `managed-stale`
30407
- // matched no branch, fell through, and handed symlinkSync a path that
30408
- // already existed. Measured: sync died with "EEXIST: file already exists,
30409
- // symlink … -> ~/.cline/skills" and every component after skills went
30410
- // unsynced.
30411
- artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)
30412
- ) {
30413
- fs42.unlinkSync(destination);
30414
- } else if (artifactClass === "unmanaged-conflict") {
30415
- if (!handleConflict5(destination, config, options, logger, manifest, scopePath)) {
30416
- return { component: "skills", status: "conflict", path: destination };
30417
- }
30418
- } else if (artifactClass === "managed-symlink") {
30419
- fs42.unlinkSync(destination);
30420
- }
30421
- ensureDir(path42.dirname(destination));
30422
- createRelativeSymlink(source, destination, "dir");
30423
- logger.verbose(`Skills: created Cline skills symlink ${destination}`);
30424
- return { component: "skills", status: "success", path: destination };
30506
+ return syncSkillsSlot({
30507
+ config,
30508
+ sourceRoot,
30509
+ source: path43.resolve(sourceRoot, config.source.skills),
30510
+ destination: resolveTargetPath(paths.skills),
30511
+ dryRun: options.dryRun,
30512
+ logger,
30513
+ onUnmanagedConflict: (conflictPath) => handleConflict5(
30514
+ conflictPath,
30515
+ config,
30516
+ options,
30517
+ logger,
30518
+ manifest,
30519
+ scopePath
30520
+ )
30521
+ });
30425
30522
  }
30426
30523
  function syncHooks5(config, sourceRoot, mappings, options, lossReport, logger) {
30427
30524
  const hooksSource = loadKitHooksSource(sourceRoot, config);
@@ -30442,10 +30539,10 @@ function syncMcp5(config, sourceRoot, paths, options, lossReport, logger, manife
30442
30539
  const source = resolveMcpSourceFile(sourceRoot, config);
30443
30540
  const sourceLabel = mcpSourceLabel(config);
30444
30541
  const destination = resolveTargetPath(paths.mcp_file);
30445
- if (!fs42.existsSync(source)) {
30542
+ if (!fs43.existsSync(source)) {
30446
30543
  return skippedMissingSource5("mcp", source);
30447
30544
  }
30448
- const sourceMcpJson = JSON.parse(fs42.readFileSync(source, "utf8"));
30545
+ const sourceMcpJson = JSON.parse(fs43.readFileSync(source, "utf8"));
30449
30546
  const mcpJson = compileMcp(sourceMcpJson, "cline", lossReport, sourceLabel);
30450
30547
  if (options.dryRun) {
30451
30548
  logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
@@ -30488,11 +30585,11 @@ function syncSettings2(lossReport) {
30488
30585
  };
30489
30586
  }
30490
30587
  function syncProviderAndModel(config, sourceRoot, lossReport) {
30491
- const agentsDir = path42.join(sourceRoot, config.source.agents);
30492
- if (!fs42.existsSync(agentsDir)) return;
30493
- for (const agentFile of ts(path42.join(agentsDir, "*.md")).sort()) {
30588
+ const agentsDir = path43.join(sourceRoot, config.source.agents);
30589
+ if (!fs43.existsSync(agentsDir)) return;
30590
+ for (const agentFile of ts(path43.join(agentsDir, "*.md")).sort()) {
30494
30591
  const { data } = parseMarkdownFrontmatter(agentFile);
30495
- const relativeSource = `agents/${path42.basename(agentFile)}`;
30592
+ const relativeSource = `agents/${path43.basename(agentFile)}`;
30496
30593
  const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
30497
30594
  if (hasCustomProvider) {
30498
30595
  addLoss(lossReport, "cline", "agents", {
@@ -30506,7 +30603,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
30506
30603
  "provider",
30507
30604
  "provider-not-representable"
30508
30605
  ),
30509
- detail: `${path42.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
30606
+ detail: `${path43.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
30510
30607
  }
30511
30608
  ]
30512
30609
  });
@@ -30524,7 +30621,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
30524
30621
  "model",
30525
30622
  "model-not-representable"
30526
30623
  ),
30527
- detail: `${path42.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
30624
+ detail: `${path43.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
30528
30625
  }
30529
30626
  ]
30530
30627
  });
@@ -30542,14 +30639,14 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
30542
30639
  if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
30543
30640
  return { component, status: "conflict", path: destination };
30544
30641
  }
30545
- ensureDir(path42.dirname(destination));
30642
+ ensureDir(path43.dirname(destination));
30546
30643
  const clearedLink = clearSymlinkAtDestination(destination);
30547
30644
  if (clearedLink !== null) {
30548
30645
  logger.verbose(
30549
30646
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
30550
30647
  );
30551
30648
  }
30552
- fs42.writeFileSync(destination, content);
30649
+ fs43.writeFileSync(destination, content);
30553
30650
  return { component, status: "success", path: destination };
30554
30651
  }
30555
30652
  function handleConflict5(destination, config, options, logger, manifest, scopePath) {
@@ -30567,7 +30664,7 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
30567
30664
  if (manifest && scopePath) {
30568
30665
  backupFile(destination, manifest, scopePath);
30569
30666
  writeManifest(scopePath, manifest);
30570
- fs42.rmSync(destination, { recursive: true, force: true });
30667
+ fs43.rmSync(destination, { recursive: true, force: true });
30571
30668
  } else {
30572
30669
  const parked = parkConflictingPath(
30573
30670
  destination,
@@ -30582,12 +30679,12 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
30582
30679
  }
30583
30680
  return true;
30584
30681
  }
30585
- fs42.rmSync(destination, { recursive: true, force: true });
30682
+ fs43.rmSync(destination, { recursive: true, force: true });
30586
30683
  return true;
30587
30684
  }
30588
30685
  function isCompiledCurrent4(destination, expectedContent, _expectedHash) {
30589
30686
  try {
30590
- return fs42.readFileSync(destination, "utf8") === expectedContent;
30687
+ return fs43.readFileSync(destination, "utf8") === expectedContent;
30591
30688
  } catch {
30592
30689
  return false;
30593
30690
  }
@@ -30602,23 +30699,16 @@ function skippedMissingSource5(component, source) {
30602
30699
  function shouldSkipComponent5(options, component) {
30603
30700
  return Boolean(options.component && options.component !== component);
30604
30701
  }
30605
- function isSymlinkTo6(linkPath, source) {
30606
- try {
30607
- return fs42.realpathSync(linkPath) === fs42.realpathSync(source);
30608
- } catch {
30609
- return false;
30610
- }
30611
- }
30612
30702
  function hashString4(value) {
30613
30703
  return `sha256:${crypto9.createHash("sha256").update(value).digest("hex")}`;
30614
30704
  }
30615
30705
 
30616
30706
  // src/adapters/opencode.ts
30617
30707
  import crypto10 from "crypto";
30618
- import fs43 from "fs";
30708
+ import fs44 from "fs";
30619
30709
  import os6 from "os";
30620
- import path43 from "path";
30621
- var import_yaml11 = __toESM(require_dist(), 1);
30710
+ import path44 from "path";
30711
+ var import_yaml12 = __toESM(require_dist(), 1);
30622
30712
  function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
30623
30713
  const scope = options.scope ?? "global";
30624
30714
  const profile = resolveTargetPaths({
@@ -30635,7 +30725,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
30635
30725
  config_doc: profile.config_doc
30636
30726
  };
30637
30727
  const rules = compileRules(
30638
- path43.join(sourceRoot, config.source.rules),
30728
+ path44.join(sourceRoot, config.source.rules),
30639
30729
  "opencode",
30640
30730
  mappings,
30641
30731
  lossReport
@@ -30686,7 +30776,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
30686
30776
  }
30687
30777
  if (!shouldSkipComponent6(options, "skills")) {
30688
30778
  outcomes.push(
30689
- syncSkills5(
30779
+ ...syncSkills5(
30690
30780
  config,
30691
30781
  sourceRoot,
30692
30782
  paths,
@@ -30699,7 +30789,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
30699
30789
  )
30700
30790
  );
30701
30791
  outcomes.push(
30702
- syncSkills5(
30792
+ ...syncSkills5(
30703
30793
  config,
30704
30794
  sourceRoot,
30705
30795
  paths,
@@ -30739,14 +30829,14 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
30739
30829
  function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
30740
30830
  const source = instructionsSourcePath(sourceRoot, config);
30741
30831
  const destination = resolveTargetPath(paths.instructions);
30742
- const baseContent = fs43.existsSync(source) ? fs43.readFileSync(source, "utf8").trim() : "";
30832
+ const baseContent = fs44.existsSync(source) ? fs44.readFileSync(source, "utf8").trim() : "";
30743
30833
  const composed = agentsAppendix ? `${baseContent}
30744
30834
 
30745
30835
  --- tangyr managed rules ---
30746
30836
  ${agentsAppendix}`.trim() : baseContent;
30747
30837
  const marker = formatProvenanceMarker(
30748
30838
  "markdown",
30749
- path43.basename(instructionsSourceLabel(sourceRoot, config)),
30839
+ path44.basename(instructionsSourceLabel(sourceRoot, config)),
30750
30840
  hashString5(composed),
30751
30841
  "opencode"
30752
30842
  );
@@ -30773,16 +30863,16 @@ ${composed}
30773
30863
  );
30774
30864
  }
30775
30865
  function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
30776
- const sourceAgentsRoot = path43.join(sourceRoot, config.source.agents);
30777
- if (!fs43.existsSync(sourceAgentsRoot)) {
30866
+ const sourceAgentsRoot = path44.join(sourceRoot, config.source.agents);
30867
+ if (!fs44.existsSync(sourceAgentsRoot)) {
30778
30868
  return [skippedMissingSource6("agents", sourceAgentsRoot)];
30779
30869
  }
30780
- const sourceAgents = ts(path43.join(sourceAgentsRoot, "*.md")).sort();
30870
+ const sourceAgents = ts(path44.join(sourceAgentsRoot, "*.md")).sort();
30781
30871
  const agentsRoot = resolveTargetPath(paths.agents);
30782
30872
  return sourceAgents.map((agentFile) => {
30783
- const destination = path43.join(
30873
+ const destination = path44.join(
30784
30874
  agentsRoot,
30785
- `${path43.basename(agentFile, ".md")}.md`
30875
+ `${path44.basename(agentFile, ".md")}.md`
30786
30876
  );
30787
30877
  let compiled;
30788
30878
  try {
@@ -30838,19 +30928,19 @@ function applyProviderModelBinding(compiled, mappings) {
30838
30928
  const after = compiled.slice(fmEnd);
30839
30929
  let fields;
30840
30930
  try {
30841
- fields = (0, import_yaml11.parse)(yamlBlock) ?? {};
30931
+ fields = (0, import_yaml12.parse)(yamlBlock) ?? {};
30842
30932
  } catch {
30843
30933
  return compiled;
30844
30934
  }
30845
30935
  fields.model = modelValue;
30846
- return `${before}${(0, import_yaml11.stringify)(fields).trim()}${after}`;
30936
+ return `${before}${(0, import_yaml12.stringify)(fields).trim()}${after}`;
30847
30937
  }
30848
30938
  function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
30849
- const sourceCommandsRoot = path43.join(sourceRoot, config.source.commands);
30850
- if (!fs43.existsSync(sourceCommandsRoot)) {
30939
+ const sourceCommandsRoot = path44.join(sourceRoot, config.source.commands);
30940
+ if (!fs44.existsSync(sourceCommandsRoot)) {
30851
30941
  return [skippedMissingSource6("commands", sourceCommandsRoot)];
30852
30942
  }
30853
- const sourceCommands = ts(path43.join(sourceCommandsRoot, "*.md")).sort();
30943
+ const sourceCommands = ts(path44.join(sourceCommandsRoot, "*.md")).sort();
30854
30944
  const commandsRoot = resolveTargetPath(paths.commands);
30855
30945
  return sourceCommands.map((commandFile) => {
30856
30946
  const { data, body } = parseCommandFile(commandFile);
@@ -30864,7 +30954,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
30864
30954
  if (typeof data.model === "string") {
30865
30955
  frontmatter.model = data.model;
30866
30956
  }
30867
- const relativeSource = `commands/${path43.basename(commandFile)}`;
30957
+ const relativeSource = `commands/${path44.basename(commandFile)}`;
30868
30958
  const marker = formatProvenanceMarker(
30869
30959
  "markdown",
30870
30960
  relativeSource,
@@ -30873,16 +30963,16 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
30873
30963
  );
30874
30964
  const content = Object.keys(frontmatter).length > 0 ? `${marker}
30875
30965
  ---
30876
- ${(0, import_yaml11.stringify)(frontmatter).trim()}
30966
+ ${(0, import_yaml12.stringify)(frontmatter).trim()}
30877
30967
  ---
30878
30968
 
30879
30969
  ${body.trimEnd()}
30880
30970
  ` : `${marker}
30881
30971
  ${body.trimEnd()}
30882
30972
  `;
30883
- const destination = path43.join(
30973
+ const destination = path44.join(
30884
30974
  commandsRoot,
30885
- `${path43.basename(commandFile, ".md")}.md`
30975
+ `${path44.basename(commandFile, ".md")}.md`
30886
30976
  );
30887
30977
  if (options.dryRun) {
30888
30978
  logger.info(
@@ -30908,42 +30998,35 @@ ${body.trimEnd()}
30908
30998
  );
30909
30999
  });
30910
31000
  }
30911
- function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scopePath, component = "skills", destination = "") {
30912
- const source = path43.resolve(sourceRoot, config.source.skills);
30913
- if (!fs43.existsSync(source)) {
30914
- return skippedMissingSource6(component, source);
30915
- }
30916
- if (options.dryRun) {
30917
- logger.info(`[dry-run] ${component}: symlink ${source} -> ${destination}`);
30918
- return { component, status: "dry-run", path: destination };
30919
- }
30920
- const artifactClass = classifyArtifact(destination, config, sourceRoot);
30921
- if (artifactClass === "managed-symlink" && isSymlinkTo7(destination, source)) {
30922
- return { component, status: "skipped-current", path: destination };
30923
- }
30924
- if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
30925
- fs43.unlinkSync(destination);
30926
- } else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
30927
- return { component, status: "conflict", path: destination };
30928
- } else if (artifactClass === "managed-symlink") {
30929
- fs43.unlinkSync(destination);
30930
- }
30931
- ensureDir(path43.dirname(destination));
30932
- createRelativeSymlink(source, destination, "dir");
30933
- logger.verbose(`Skills: created skills path ${destination}`);
30934
- return { component, status: "success", path: destination };
31001
+ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scopePath, _component = "skills", destination = "") {
31002
+ return syncSkillsSlot({
31003
+ config,
31004
+ sourceRoot,
31005
+ source: path44.resolve(sourceRoot, config.source.skills),
31006
+ destination,
31007
+ dryRun: options.dryRun,
31008
+ logger,
31009
+ onUnmanagedConflict: (conflictPath) => handleConflict6(
31010
+ conflictPath,
31011
+ config,
31012
+ options,
31013
+ logger,
31014
+ manifest,
31015
+ scopePath
31016
+ )
31017
+ });
30935
31018
  }
30936
31019
  function syncMcp6(config, sourceRoot, paths, mappings, options, lossReport, logger) {
30937
31020
  const source = resolveMcpSourceFile(sourceRoot, config);
30938
31021
  const sourceLabel = mcpSourceLabel(config);
30939
31022
  const destination = resolveTargetPath(paths.config_doc);
30940
- if (!fs43.existsSync(source)) {
31023
+ if (!fs44.existsSync(source)) {
30941
31024
  if (!options.dryRun) {
30942
31025
  syncConfigDoc(paths, {}, lossReport, {}, mappings);
30943
31026
  }
30944
31027
  return skippedMissingSource6("mcp", source);
30945
31028
  }
30946
- const sourceMcpJson = JSON.parse(fs43.readFileSync(source, "utf8"));
31029
+ const sourceMcpJson = JSON.parse(fs44.readFileSync(source, "utf8"));
30947
31030
  const mcpJson = compileMcp(
30948
31031
  sourceMcpJson,
30949
31032
  "opencode",
@@ -31009,9 +31092,9 @@ function syncProviderBlock(mappings) {
31009
31092
  function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings) {
31010
31093
  const destination = resolveTargetPath(paths.config_doc);
31011
31094
  let existing = {};
31012
- if (fs43.existsSync(destination)) {
31095
+ if (fs44.existsSync(destination)) {
31013
31096
  try {
31014
- existing = JSON.parse(fs43.readFileSync(destination, "utf8"));
31097
+ existing = JSON.parse(fs44.readFileSync(destination, "utf8"));
31015
31098
  } catch {
31016
31099
  existing = {};
31017
31100
  }
@@ -31036,8 +31119,8 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
31036
31119
  };
31037
31120
  }
31038
31121
  }
31039
- ensureDir(path43.dirname(destination));
31040
- fs43.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
31122
+ ensureDir(path44.dirname(destination));
31123
+ fs44.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
31041
31124
  `);
31042
31125
  }
31043
31126
  function writeCompiledArtifact5(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
@@ -31051,14 +31134,14 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
31051
31134
  if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
31052
31135
  return { component, status: "conflict", path: destination };
31053
31136
  }
31054
- ensureDir(path43.dirname(destination));
31137
+ ensureDir(path44.dirname(destination));
31055
31138
  const clearedLink = clearSymlinkAtDestination(destination);
31056
31139
  if (clearedLink !== null) {
31057
31140
  logger.verbose(
31058
31141
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
31059
31142
  );
31060
31143
  }
31061
- fs43.writeFileSync(destination, content);
31144
+ fs44.writeFileSync(destination, content);
31062
31145
  return { component, status: "success", path: destination };
31063
31146
  }
31064
31147
  function handleConflict6(destination, config, options, logger, manifest, scopePath) {
@@ -31076,7 +31159,7 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
31076
31159
  if (manifest && scopePath) {
31077
31160
  backupFile(destination, manifest, scopePath);
31078
31161
  writeManifest(scopePath, manifest);
31079
- fs43.rmSync(destination, { recursive: true, force: true });
31162
+ fs44.rmSync(destination, { recursive: true, force: true });
31080
31163
  } else {
31081
31164
  const parked = parkConflictingPath(
31082
31165
  destination,
@@ -31091,12 +31174,12 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
31091
31174
  }
31092
31175
  return true;
31093
31176
  }
31094
- fs43.rmSync(destination, { recursive: true, force: true });
31177
+ fs44.rmSync(destination, { recursive: true, force: true });
31095
31178
  return true;
31096
31179
  }
31097
31180
  function isCompiledCurrent5(destination, expectedContent, _expectedHash) {
31098
31181
  try {
31099
- return fs43.readFileSync(destination, "utf8") === expectedContent;
31182
+ return fs44.readFileSync(destination, "utf8") === expectedContent;
31100
31183
  } catch {
31101
31184
  return false;
31102
31185
  }
@@ -31111,18 +31194,11 @@ function skippedMissingSource6(component, source) {
31111
31194
  function shouldSkipComponent6(options, component) {
31112
31195
  return Boolean(options.component && options.component !== component);
31113
31196
  }
31114
- function isSymlinkTo7(linkPath, source) {
31115
- try {
31116
- return fs43.realpathSync(linkPath) === fs43.realpathSync(source);
31117
- } catch {
31118
- return false;
31119
- }
31120
- }
31121
31197
  function hashString5(value) {
31122
31198
  return `sha256:${crypto10.createHash("sha256").update(value).digest("hex")}`;
31123
31199
  }
31124
31200
  function parseCommandFile(commandFile) {
31125
- const content = fs43.readFileSync(commandFile, "utf8");
31201
+ const content = fs44.readFileSync(commandFile, "utf8");
31126
31202
  if (!content.startsWith("---\n")) {
31127
31203
  return { data: {}, body: content };
31128
31204
  }
@@ -31131,7 +31207,7 @@ function parseCommandFile(commandFile) {
31131
31207
  return { data: {}, body: content };
31132
31208
  }
31133
31209
  try {
31134
- const data = (0, import_yaml11.parse)(content.slice(4, endIndex)) ?? {};
31210
+ const data = (0, import_yaml12.parse)(content.slice(4, endIndex)) ?? {};
31135
31211
  const body = content.slice(endIndex + "\n---".length).replace(/^\n/u, "");
31136
31212
  return { data, body };
31137
31213
  } catch {
@@ -31142,7 +31218,7 @@ function parseCommandFile(commandFile) {
31142
31218
  // src/commands/install.ts
31143
31219
  function isBackupablePath(targetPath) {
31144
31220
  try {
31145
- const lstat = fs44.lstatSync(targetPath);
31221
+ const lstat = fs45.lstatSync(targetPath);
31146
31222
  return lstat.isSymbolicLink() || lstat.isFile() || lstat.isDirectory();
31147
31223
  } catch {
31148
31224
  return false;
@@ -31179,7 +31255,7 @@ async function runInstallCommand(options, logger) {
31179
31255
  );
31180
31256
  }
31181
31257
  const kitName = resolvedKitName ?? config.kit;
31182
- const kitPath = kitPathOverride ?? (options.kitPath ? path44.resolve(options.kitPath) : config.kitPath);
31258
+ const kitPath = kitPathOverride ?? (options.kitPath ? path45.resolve(options.kitPath) : config.kitPath);
31183
31259
  if (!kitName && !kitPath) {
31184
31260
  logger.error(
31185
31261
  "No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
@@ -31284,8 +31360,8 @@ async function runInstallCommand(options, logger) {
31284
31360
  config: options.config,
31285
31361
  scope
31286
31362
  });
31287
- const skillsSource = path44.resolve(kitInfo.path, config.source.skills);
31288
- const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") && path44.basename(f.path) === "skills";
31363
+ const skillsSource = path45.resolve(kitInfo.path, config.source.skills);
31364
+ const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") && path45.basename(f.path) === "skills";
31289
31365
  const foreignSkillsSlots = new Set(
31290
31366
  assessResult.findings.filter(
31291
31367
  (f) => isPerSkillSkillsSlot(f) && isForeignSkillsSlotSymlink(
@@ -31323,7 +31399,7 @@ async function runInstallCommand(options, logger) {
31323
31399
  let instructionsLabel;
31324
31400
  try {
31325
31401
  const resolved = resolveInstructionsSource(kitInfo.path, config);
31326
- instructionsLabel = resolved ? path44.relative(kitInfo.path, resolved.file) : "(none \u2014 no instructions file resolves in this kit)";
31402
+ instructionsLabel = resolved ? path45.relative(kitInfo.path, resolved.file) : "(none \u2014 no instructions file resolves in this kit)";
31327
31403
  } catch (err) {
31328
31404
  logger.error(
31329
31405
  `[dry-run] ${err instanceof Error ? err.message : String(err)}`
@@ -31351,7 +31427,7 @@ async function runInstallCommand(options, logger) {
31351
31427
  }
31352
31428
  }
31353
31429
  logger.info(
31354
- `[dry-run] Total: ${plannedTotal} destination(s); manifest at ${path44.join(scopePath, "manifest.json")}`
31430
+ `[dry-run] Total: ${plannedTotal} destination(s); manifest at ${path45.join(scopePath, "manifest.json")}`
31355
31431
  );
31356
31432
  return;
31357
31433
  }
@@ -31410,7 +31486,7 @@ ACCEPTED CONFLICTS (posture: ${posture}; ${replaceable.length} target(s)):`
31410
31486
  logger.info(` - ${finding.path}`);
31411
31487
  logger.info(` source: ${sources}`);
31412
31488
  logger.info(
31413
- ` action: backup-and-replace${fs44.lstatSync(finding.path).isDirectory() ? " (directory)" : ""}`
31489
+ ` action: backup-and-replace${fs45.lstatSync(finding.path).isDirectory() ? " (directory)" : ""}`
31414
31490
  );
31415
31491
  logger.info(` backup: ${backupLocation}`);
31416
31492
  continue;
@@ -31534,20 +31610,20 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
31534
31610
  writeManifest(scopePath, manifest);
31535
31611
  logger.info(`
31536
31612
  Installation complete: ${installedCount} files installed.`);
31537
- logger.info(`Manifest written to ${path44.join(scopePath, "manifest.json")}`);
31613
+ logger.info(`Manifest written to ${path45.join(scopePath, "manifest.json")}`);
31538
31614
  logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
31539
31615
  logger.info(`Scope: ${scope}`);
31540
31616
  logger.info(`Tools: ${tools.join(", ")}`);
31541
31617
  reportHookRejections(
31542
31618
  installLossReport,
31543
31619
  tools,
31544
- path44.resolve(kitInfo.path, "hooks"),
31620
+ path45.resolve(kitInfo.path, "hooks"),
31545
31621
  kitInfo.components.hooks.declared
31546
31622
  );
31547
31623
  const hooksConflict = reportHooksSourceConflict(
31548
31624
  installLossReport,
31549
31625
  tools,
31550
- path44.resolve(kitInfo.path, "hooks"),
31626
+ path45.resolve(kitInfo.path, "hooks"),
31551
31627
  kitInfo.components.hooks.declared
31552
31628
  );
31553
31629
  if (hooksConflict) {
@@ -31906,7 +31982,7 @@ function installClaudeCodeSkills(config, kitInfo, manifest, options, logger, sco
31906
31982
  return 0;
31907
31983
  }
31908
31984
  try {
31909
- const stat = fs44.lstatSync(destination);
31985
+ const stat = fs45.lstatSync(destination);
31910
31986
  if (stat.isFile() && !stat.isSymbolicLink()) {
31911
31987
  logger.warn(
31912
31988
  `${destination}: a regular file occupies the skills slot \u2014 skipping skills. Move or remove it, then re-run install.`
@@ -31934,17 +32010,17 @@ function installClaudeCodeSkills(config, kitInfo, manifest, options, logger, sco
31934
32010
  manifest,
31935
32011
  scopePath
31936
32012
  );
31937
- const skillsSource = path44.resolve(kitInfo.path, config.source.skills);
32013
+ const skillsSource = path45.resolve(kitInfo.path, config.source.skills);
31938
32014
  let count = 0;
31939
32015
  for (const outcome of outcomes) {
31940
32016
  if (outcome.status !== "success" && outcome.status !== "skipped-current") {
31941
32017
  continue;
31942
32018
  }
31943
- const skillName = path44.basename(outcome.path);
32019
+ const skillName = path45.basename(outcome.path);
31944
32020
  addArtifactToManifest(manifest, {
31945
32021
  relativePath: `claude-code/skills/${skillName}`,
31946
32022
  path: outcome.path,
31947
- hash: describeArtifactState(outcome.path) ?? `dir:${path44.join(skillsSource, skillName)}`,
32023
+ hash: describeArtifactState(outcome.path) ?? `dir:${path45.join(skillsSource, skillName)}`,
31948
32024
  origin: "tangyr-managed"
31949
32025
  });
31950
32026
  count++;
@@ -31958,10 +32034,10 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
31958
32034
  logger.verbose(` skipped (operator choice): ${placement.destination}`);
31959
32035
  continue;
31960
32036
  }
31961
- const destDir = path44.dirname(placement.destination);
31962
- fs44.mkdirSync(destDir, { recursive: true });
32037
+ const destDir = path45.dirname(placement.destination);
32038
+ fs45.mkdirSync(destDir, { recursive: true });
31963
32039
  if (placement.type === "symlink") {
31964
- if (fs44.existsSync(placement.destination) || isSymlink2(placement.destination)) {
32040
+ if (fs45.existsSync(placement.destination) || isSymlink2(placement.destination)) {
31965
32041
  removeManagedPath(placement.destination);
31966
32042
  }
31967
32043
  createRelativeSymlink(
@@ -31978,7 +32054,7 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
31978
32054
  ` symlink: ${placement.source} \u2192 ${placement.destination}`
31979
32055
  );
31980
32056
  } else {
31981
- fs44.copyFileSync(placement.source, placement.destination);
32057
+ fs45.copyFileSync(placement.source, placement.destination);
31982
32058
  logger.verbose(` copy: ${placement.source} \u2192 ${placement.destination}`);
31983
32059
  }
31984
32060
  addArtifactToManifest(manifest, {
@@ -32240,6 +32316,16 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32240
32316
  }
32241
32317
  throwUnrecognizedTarget(tool);
32242
32318
  }
32319
+ const skillsSlotKey = skillsSubPathKey(
32320
+ tool,
32321
+ outcome.path,
32322
+ mappings,
32323
+ scope,
32324
+ projectRoot
32325
+ );
32326
+ if (skillsSlotKey) {
32327
+ return skillsSlotKey;
32328
+ }
32243
32329
  if (tool === "cline") {
32244
32330
  const profile2 = resolveTargetPaths({
32245
32331
  scope,
@@ -32260,11 +32346,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32260
32346
  if (outcome.path === mcpFile2) {
32261
32347
  return "cline/mcp.json";
32262
32348
  }
32263
- if (outcome.path.startsWith(`${workflowsRoot}${path44.sep}`)) {
32264
- return `cline/workflows/${path44.basename(outcome.path)}`;
32349
+ if (outcome.path.startsWith(`${workflowsRoot}${path45.sep}`)) {
32350
+ return `cline/workflows/${path45.basename(outcome.path)}`;
32265
32351
  }
32266
- if (outcome.path.startsWith(`${rulesRoot2}${path44.sep}`)) {
32267
- return `cline/rules/${path44.basename(outcome.path)}`;
32352
+ if (outcome.path.startsWith(`${rulesRoot2}${path45.sep}`)) {
32353
+ return `cline/rules/${path45.basename(outcome.path)}`;
32268
32354
  }
32269
32355
  return null;
32270
32356
  }
@@ -32300,14 +32386,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32300
32386
  if (outcome.path === permissionsFile) {
32301
32387
  return "cursor/permissions.json";
32302
32388
  }
32303
- if (outcome.path.startsWith(`${agentsRoot2}${path44.sep}`)) {
32304
- return `cursor/agents/${path44.basename(outcome.path)}`;
32389
+ if (outcome.path.startsWith(`${agentsRoot2}${path45.sep}`)) {
32390
+ return `cursor/agents/${path45.basename(outcome.path)}`;
32305
32391
  }
32306
- if (outcome.path.startsWith(`${rulesRoot2}${path44.sep}`)) {
32307
- return `cursor/rules/${path44.basename(outcome.path)}`;
32392
+ if (outcome.path.startsWith(`${rulesRoot2}${path45.sep}`)) {
32393
+ return `cursor/rules/${path45.basename(outcome.path)}`;
32308
32394
  }
32309
- if (outcome.path.startsWith(`${skillsRoot2}${path44.sep}`)) {
32310
- const rel = path44.relative(skillsRoot2, outcome.path);
32395
+ if (outcome.path.startsWith(`${skillsRoot2}${path45.sep}`)) {
32396
+ const rel = path45.relative(skillsRoot2, outcome.path);
32311
32397
  return `cursor/skills/${rel}`;
32312
32398
  }
32313
32399
  return null;
@@ -32333,14 +32419,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32333
32419
  if (outcome.path === skillsSharedRoot) {
32334
32420
  return "opencode/skills_shared";
32335
32421
  }
32336
- if (outcome.path.startsWith(`${agentsRoot2}${path44.sep}`)) {
32337
- return `opencode/agents/${path44.basename(outcome.path)}`;
32422
+ if (outcome.path.startsWith(`${agentsRoot2}${path45.sep}`)) {
32423
+ return `opencode/agents/${path45.basename(outcome.path)}`;
32338
32424
  }
32339
- if (outcome.path.startsWith(`${commandsRoot}${path44.sep}`)) {
32340
- return `opencode/commands/${path44.basename(outcome.path)}`;
32425
+ if (outcome.path.startsWith(`${commandsRoot}${path45.sep}`)) {
32426
+ return `opencode/commands/${path45.basename(outcome.path)}`;
32341
32427
  }
32342
32428
  if (outcome.path === configDocFile) {
32343
- return `opencode/${path44.basename(outcome.path)}`;
32429
+ return `opencode/${path45.basename(outcome.path)}`;
32344
32430
  }
32345
32431
  return null;
32346
32432
  }
@@ -32357,26 +32443,29 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32357
32443
  const hooksRoot = resolveTargetPath(copilot.hooks);
32358
32444
  const mcpFile2 = resolveTargetPath(copilot.mcp_shared_file);
32359
32445
  const instructionsMirror = copilot.instructions !== null ? resolveTargetPath(copilot.instructions) : null;
32360
- if (outcome.path.startsWith(`${skillsRoot2}${path44.sep}`)) {
32361
- return `copilot/skills/${path44.relative(skillsRoot2, outcome.path)}`;
32446
+ if (copilot.rules !== null && outcome.path.startsWith(`${resolveTargetPath(copilot.rules)}${path45.sep}`)) {
32447
+ return `copilot/rules/${path45.relative(resolveTargetPath(copilot.rules), outcome.path)}`;
32448
+ }
32449
+ if (outcome.path.startsWith(`${skillsRoot2}${path45.sep}`)) {
32450
+ return `copilot/skills/${path45.relative(skillsRoot2, outcome.path)}`;
32362
32451
  }
32363
32452
  if (outcome.path === skillsRoot2) {
32364
32453
  return "copilot/skills";
32365
32454
  }
32366
32455
  if (instructionsMirror !== null && outcome.path === instructionsMirror) {
32367
- return `copilot/${path44.basename(outcome.path)}`;
32456
+ return `copilot/${path45.basename(outcome.path)}`;
32368
32457
  }
32369
- if (outcome.path.startsWith(`${agentsRoot2}${path44.sep}`)) {
32370
- return `copilot/agents/${path44.basename(outcome.path)}`;
32458
+ if (outcome.path.startsWith(`${agentsRoot2}${path45.sep}`)) {
32459
+ return `copilot/agents/${path45.basename(outcome.path)}`;
32371
32460
  }
32372
- if (outcome.path.startsWith(`${promptsRoot}${path44.sep}`)) {
32373
- return `copilot/prompts/${path44.basename(outcome.path)}`;
32461
+ if (outcome.path.startsWith(`${promptsRoot}${path45.sep}`)) {
32462
+ return `copilot/prompts/${path45.basename(outcome.path)}`;
32374
32463
  }
32375
- if (outcome.path.startsWith(`${hooksRoot}${path44.sep}`)) {
32376
- return `copilot/hooks/${path44.basename(outcome.path)}`;
32464
+ if (outcome.path.startsWith(`${hooksRoot}${path45.sep}`)) {
32465
+ return `copilot/hooks/${path45.basename(outcome.path)}`;
32377
32466
  }
32378
32467
  if (outcome.path === mcpFile2) {
32379
- return `copilot/${path44.basename(outcome.path)}`;
32468
+ return `copilot/${path45.basename(outcome.path)}`;
32380
32469
  }
32381
32470
  return null;
32382
32471
  }
@@ -32393,17 +32482,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32393
32482
  if (outcome.path === skillsRoot) {
32394
32483
  return "codex/skills";
32395
32484
  }
32396
- if (outcome.path.startsWith(`${agentsRoot}${path44.sep}`)) {
32397
- return `codex/agents/${path44.basename(outcome.path)}`;
32485
+ if (outcome.path.startsWith(`${agentsRoot}${path45.sep}`)) {
32486
+ return `codex/agents/${path45.basename(outcome.path)}`;
32398
32487
  }
32399
- if (outcome.path.startsWith(`${rulesRoot}${path44.sep}`)) {
32400
- return `codex/rules/${path44.basename(outcome.path)}`;
32488
+ if (outcome.path.startsWith(`${rulesRoot}${path45.sep}`)) {
32489
+ return `codex/rules/${path45.basename(outcome.path)}`;
32401
32490
  }
32402
32491
  if (outcome.path === hooksFile) {
32403
- return `codex/${path44.basename(outcome.path)}`;
32492
+ return `codex/${path45.basename(outcome.path)}`;
32404
32493
  }
32405
32494
  if (outcome.path === mcpFile) {
32406
- return `codex/${path44.basename(outcome.path)}`;
32495
+ return `codex/${path45.basename(outcome.path)}`;
32407
32496
  }
32408
32497
  return null;
32409
32498
  }
@@ -32472,8 +32561,8 @@ function getClaudeCodePlacements(kitInfo, config, scope = "global", projectRoot,
32472
32561
  rules: resolvedPaths.rules
32473
32562
  };
32474
32563
  for (const [component, targetPath] of Object.entries(componentDirMap)) {
32475
- const componentDir = path44.join(kitInfo.path, component);
32476
- if (fs44.existsSync(componentDir) && fs44.statSync(componentDir).isDirectory()) {
32564
+ const componentDir = path45.join(kitInfo.path, component);
32565
+ if (fs45.existsSync(componentDir) && fs45.statSync(componentDir).isDirectory()) {
32477
32566
  placements.push({
32478
32567
  source: componentDir,
32479
32568
  destination: targetPath,
@@ -32503,8 +32592,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile, config) {
32503
32592
  rules: profile.rules
32504
32593
  };
32505
32594
  for (const [component, targetPath] of Object.entries(componentDirMap)) {
32506
- const componentDir = path44.join(kitInfo.path, component);
32507
- if (fs44.existsSync(componentDir) && fs44.statSync(componentDir).isDirectory()) {
32595
+ const componentDir = path45.join(kitInfo.path, component);
32596
+ if (fs45.existsSync(componentDir) && fs45.statSync(componentDir).isDirectory()) {
32508
32597
  placements.push({
32509
32598
  source: componentDir,
32510
32599
  destination: targetPath,
@@ -32520,7 +32609,7 @@ function collectAllFiles(kitInfo, config) {
32520
32609
  const files = /* @__PURE__ */ new Map();
32521
32610
  const entrypoint = resolveInstructionsSource(kitInfo.path, config);
32522
32611
  if (entrypoint) {
32523
- files.set(path44.basename(entrypoint.file), entrypoint.file);
32612
+ files.set(path45.basename(entrypoint.file), entrypoint.file);
32524
32613
  }
32525
32614
  for (const [component, reconciliation] of Object.entries(
32526
32615
  kitInfo.components
@@ -32529,26 +32618,48 @@ function collectAllFiles(kitInfo, config) {
32529
32618
  const missingSet = new Set(reconciliation.missing);
32530
32619
  for (const entry of reconciliation.declared) {
32531
32620
  if (missingSet.has(entry)) continue;
32532
- const relPath = isSkills ? path44.join(component, entry) : path44.join(component, `${entry}.md`);
32533
- files.set(relPath, path44.join(kitInfo.path, relPath));
32621
+ const relPath = isSkills ? path45.join(component, entry) : path45.join(component, `${entry}.md`);
32622
+ files.set(relPath, path45.join(kitInfo.path, relPath));
32534
32623
  }
32535
32624
  }
32536
32625
  return files;
32537
32626
  }
32538
32627
  function readLinkTarget(p) {
32539
32628
  try {
32540
- return fs44.readlinkSync(p);
32629
+ return fs45.readlinkSync(p);
32541
32630
  } catch {
32542
32631
  return null;
32543
32632
  }
32544
32633
  }
32545
32634
  function isSymlink2(p) {
32546
32635
  try {
32547
- return fs44.lstatSync(p).isSymbolicLink();
32636
+ return fs45.lstatSync(p).isSymbolicLink();
32548
32637
  } catch {
32549
32638
  return false;
32550
32639
  }
32551
32640
  }
32641
+ function skillsSubPathKey(tool, outcomePath, mappings, scope, projectRoot) {
32642
+ const profile = resolveTargetPaths({
32643
+ scope,
32644
+ projectRoot,
32645
+ mappings: mappings.platformPaths
32646
+ })[tool];
32647
+ if (!profile) {
32648
+ return null;
32649
+ }
32650
+ for (const slot of [profile.skills, profile.skills_shared]) {
32651
+ if (typeof slot !== "string" || slot.length === 0) {
32652
+ continue;
32653
+ }
32654
+ const root = resolveTargetPath(slot);
32655
+ if (!outcomePath.startsWith(`${root}${path45.sep}`)) {
32656
+ continue;
32657
+ }
32658
+ const inside = path45.relative(root, outcomePath).split(path45.sep).join("/");
32659
+ return `${tool}/skills/${inside}`;
32660
+ }
32661
+ return null;
32662
+ }
32552
32663
 
32553
32664
  // src/commands/kit.ts
32554
32665
  async function runKitUpdateCommand(options, logger) {
@@ -32589,14 +32700,14 @@ async function runKitUpdateCommand(options, logger) {
32589
32700
  }
32590
32701
 
32591
32702
  // src/commands/list.ts
32592
- import path45 from "path";
32703
+ import path46 from "path";
32593
32704
  function runListCommand(options, logger) {
32594
32705
  let searchPaths = [];
32595
- let directKitPath = options.kitPath ? path45.resolve(options.kitPath) : void 0;
32706
+ let directKitPath = options.kitPath ? path46.resolve(options.kitPath) : void 0;
32596
32707
  try {
32597
32708
  const { config, configDir } = resolveConfig(options.config);
32598
32709
  searchPaths = config.kitSearchPaths ?? [
32599
- path45.join(configDir, "operating-kits")
32710
+ path46.join(configDir, "operating-kits")
32600
32711
  ];
32601
32712
  directKitPath = directKitPath ?? config.kitPath;
32602
32713
  } catch (err) {
@@ -32671,7 +32782,7 @@ function withDirectKit(kits, directKitPath) {
32671
32782
  return kits;
32672
32783
  }
32673
32784
  const directKit = loadKit(directKitPath);
32674
- if (kits.some((kit) => path45.resolve(kit.path) === directKit.path)) {
32785
+ if (kits.some((kit) => path46.resolve(kit.path) === directKit.path)) {
32675
32786
  return kits;
32676
32787
  }
32677
32788
  return [...kits, directKit];
@@ -32679,8 +32790,8 @@ function withDirectKit(kits, directKitPath) {
32679
32790
 
32680
32791
  // src/commands/probe.ts
32681
32792
  import { spawnSync as spawnSync2 } from "child_process";
32682
- import fs45 from "fs";
32683
- import path46 from "path";
32793
+ import fs46 from "fs";
32794
+ import path47 from "path";
32684
32795
  function runProbeCommand(options, logger) {
32685
32796
  const { config, configDir, configSource, sourceRoot } = resolveRuntime(
32686
32797
  options,
@@ -32708,7 +32819,7 @@ function runProbeCommand(options, logger) {
32708
32819
  toProbeRow(
32709
32820
  target,
32710
32821
  key,
32711
- scope === "project" ? path46.resolve(projectRoot ?? process.cwd(), rawPath) : rawPath
32822
+ scope === "project" ? path47.resolve(projectRoot ?? process.cwd(), rawPath) : rawPath
32712
32823
  )
32713
32824
  );
32714
32825
  }
@@ -32730,7 +32841,7 @@ function toProbeRow(target, key, rawPath) {
32730
32841
  const resolved = resolveTargetPath(rawPath);
32731
32842
  let accessible = false;
32732
32843
  try {
32733
- fs45.accessSync(resolved);
32844
+ fs46.accessSync(resolved);
32734
32845
  accessible = true;
32735
32846
  } catch {
32736
32847
  accessible = false;
@@ -32739,7 +32850,7 @@ function toProbeRow(target, key, rawPath) {
32739
32850
  target,
32740
32851
  key,
32741
32852
  path: resolved,
32742
- exists: fs45.existsSync(resolved),
32853
+ exists: fs46.existsSync(resolved),
32743
32854
  accessible
32744
32855
  };
32745
32856
  }
@@ -32757,7 +32868,7 @@ function codexRuntimeProbeRows() {
32757
32868
  ["binary_snap", "/snap/bin/codex"],
32758
32869
  ["binary_flatpak", "/var/lib/flatpak/exports/bin/codex"]
32759
32870
  ]) {
32760
- if (fs45.existsSync(candidatePath)) {
32871
+ if (fs46.existsSync(candidatePath)) {
32761
32872
  rows.push(toProbeRow("codex", key, candidatePath));
32762
32873
  }
32763
32874
  }
@@ -32773,8 +32884,8 @@ function commandProbeRows(target, key, command, args) {
32773
32884
 
32774
32885
  // src/commands/status.ts
32775
32886
  import crypto11 from "crypto";
32776
- import fs46 from "fs";
32777
- import path47 from "path";
32887
+ import fs47 from "fs";
32888
+ import path48 from "path";
32778
32889
  function runStatusCommand(options, logger) {
32779
32890
  const { config, configDir, configSource, sourceRoot } = resolveRuntime(
32780
32891
  options,
@@ -32880,11 +32991,11 @@ function classifyTargetRows(target, config, sourceRoot, configDir, scope, projec
32880
32991
  }
32881
32992
  }
32882
32993
  function sourceMarkdownFiles(sourceRoot, componentPath) {
32883
- const root = path47.join(sourceRoot, componentPath);
32884
- if (!fs46.existsSync(root)) {
32994
+ const root = path48.join(sourceRoot, componentPath);
32995
+ if (!fs47.existsSync(root)) {
32885
32996
  return [];
32886
32997
  }
32887
- return ts(path47.join(root, "*.md")).sort();
32998
+ return ts(path48.join(root, "*.md")).sort();
32888
32999
  }
32889
33000
  function notRepresentableRow(component, detail) {
32890
33001
  return {
@@ -32895,11 +33006,11 @@ function notRepresentableRow(component, detail) {
32895
33006
  };
32896
33007
  }
32897
33008
  function readTargetJson(filePath) {
32898
- if (!fs46.existsSync(filePath)) {
33009
+ if (!fs47.existsSync(filePath)) {
32899
33010
  return { kind: "missing" };
32900
33011
  }
32901
33012
  try {
32902
- const parsed = JSON.parse(fs46.readFileSync(filePath, "utf8"));
33013
+ const parsed = JSON.parse(fs47.readFileSync(filePath, "utf8"));
32903
33014
  return { kind: "object", value: isRecord(parsed) ? parsed : {} };
32904
33015
  } catch (err) {
32905
33016
  return {
@@ -32988,7 +33099,7 @@ function classifyInstructions(filePath, target, expectedHash, config, sourceRoot
32988
33099
  }
32989
33100
  function compiledMcpDocument(config, sourceRoot, target) {
32990
33101
  const source = resolveMcpSourceFile(sourceRoot, config);
32991
- if (!fs46.existsSync(source)) {
33102
+ if (!fs47.existsSync(source)) {
32992
33103
  return {};
32993
33104
  }
32994
33105
  const compiled = compileMcp(
@@ -33001,7 +33112,7 @@ function compiledMcpDocument(config, sourceRoot, target) {
33001
33112
  return isRecord(parsed) ? parsed : {};
33002
33113
  }
33003
33114
  function classifyMcpDocument(config, sourceRoot, target, filePath) {
33004
- if (!fs46.existsSync(resolveMcpSourceFile(sourceRoot, config))) {
33115
+ if (!fs47.existsSync(resolveMcpSourceFile(sourceRoot, config))) {
33005
33116
  return notConfiguredRow("mcp", filePath);
33006
33117
  }
33007
33118
  return classifyJsonDocument(
@@ -33031,12 +33142,12 @@ function classifyOpenCodeFiles(config, sourceRoot, configDir, scope, projectRoot
33031
33142
  const rows = [];
33032
33143
  const instructionsSource = instructionsSourcePath(sourceRoot, config);
33033
33144
  const rules = compileRules(
33034
- path47.join(sourceRoot, config.source.rules),
33145
+ path48.join(sourceRoot, config.source.rules),
33035
33146
  "opencode",
33036
33147
  mappings,
33037
33148
  createLossReport()
33038
33149
  );
33039
- const baseInstructions = fs46.existsSync(instructionsSource) ? fs46.readFileSync(instructionsSource, "utf8").trim() : "";
33150
+ const baseInstructions = fs47.existsSync(instructionsSource) ? fs47.readFileSync(instructionsSource, "utf8").trim() : "";
33040
33151
  const composedInstructions = rules.agentsAppendix ? `${baseInstructions}
33041
33152
 
33042
33153
  --- tangyr managed rules ---
@@ -33058,10 +33169,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
33058
33169
  )) {
33059
33170
  rows.push(
33060
33171
  classifyCompiledFile(
33061
- `agents/${path47.basename(agentFile, ".md")}`,
33062
- path47.join(
33172
+ `agents/${path48.basename(agentFile, ".md")}`,
33173
+ path48.join(
33063
33174
  resolveTargetPath(paths.agents),
33064
- `${path47.basename(agentFile, ".md")}.md`
33175
+ `${path48.basename(agentFile, ".md")}.md`
33065
33176
  ),
33066
33177
  "opencode",
33067
33178
  computeSourceHash(agentFile),
@@ -33076,10 +33187,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
33076
33187
  )) {
33077
33188
  rows.push(
33078
33189
  classifyCompiledFile(
33079
- `commands/${path47.basename(commandFile, ".md")}`,
33080
- path47.join(
33190
+ `commands/${path48.basename(commandFile, ".md")}`,
33191
+ path48.join(
33081
33192
  resolveTargetPath(paths.commands),
33082
- `${path47.basename(commandFile, ".md")}.md`
33193
+ `${path48.basename(commandFile, ".md")}.md`
33083
33194
  ),
33084
33195
  "opencode",
33085
33196
  computeSourceHash(commandFile),
@@ -33161,10 +33272,10 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
33161
33272
  )) {
33162
33273
  rows.push(
33163
33274
  classifyCompiledFile(
33164
- `agents/${path47.basename(agentFile, ".md")}`,
33165
- path47.join(
33275
+ `agents/${path48.basename(agentFile, ".md")}`,
33276
+ path48.join(
33166
33277
  resolveTargetPath(paths.agents),
33167
- `${path47.basename(agentFile, ".md")}.md`
33278
+ `${path48.basename(agentFile, ".md")}.md`
33168
33279
  ),
33169
33280
  "cursor",
33170
33281
  computeSourceHash(agentFile),
@@ -33181,7 +33292,7 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
33181
33292
  rows.push(
33182
33293
  classifyCompiledFile(
33183
33294
  `rules/${ruleFile.name}`,
33184
- path47.join(resolveTargetPath(paths.rules), ruleFile.name),
33295
+ path48.join(resolveTargetPath(paths.rules), ruleFile.name),
33185
33296
  "cursor",
33186
33297
  void 0,
33187
33298
  config,
@@ -33195,11 +33306,11 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
33195
33306
  sourceRoot,
33196
33307
  config.source.commands
33197
33308
  )) {
33198
- const baseName = path47.basename(commandFile, ".md");
33309
+ const baseName = path48.basename(commandFile, ".md");
33199
33310
  rows.push(
33200
33311
  classifyCompiledFile(
33201
33312
  `commands/${baseName}`,
33202
- path47.join(resolveTargetPath(paths.skills), baseName, "SKILL.md"),
33313
+ path48.join(resolveTargetPath(paths.skills), baseName, "SKILL.md"),
33203
33314
  "cursor",
33204
33315
  computeSourceHash(commandFile),
33205
33316
  config,
@@ -33282,7 +33393,7 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
33282
33393
  rows.push(
33283
33394
  classifyCompiledFile(
33284
33395
  `rules/${ruleFile.name}`,
33285
- path47.join(resolveTargetPath(paths.rules), ruleFile.name),
33396
+ path48.join(resolveTargetPath(paths.rules), ruleFile.name),
33286
33397
  "cline",
33287
33398
  void 0,
33288
33399
  config,
@@ -33298,10 +33409,10 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
33298
33409
  )) {
33299
33410
  rows.push(
33300
33411
  classifyCompiledFile(
33301
- `commands/${path47.basename(commandFile, ".md")}`,
33302
- path47.join(
33412
+ `commands/${path48.basename(commandFile, ".md")}`,
33413
+ path48.join(
33303
33414
  resolveTargetPath(paths.workflows),
33304
- path47.basename(commandFile)
33415
+ path48.basename(commandFile)
33305
33416
  ),
33306
33417
  "cline",
33307
33418
  computeSourceHash(commandFile),
@@ -33342,14 +33453,14 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
33342
33453
  return rows;
33343
33454
  }
33344
33455
  function compileRulesFiles(config, sourceRoot, target, mappings) {
33345
- const rulesSource = path47.join(sourceRoot, config.source.rules);
33346
- if (!fs46.existsSync(rulesSource)) {
33456
+ const rulesSource = path48.join(sourceRoot, config.source.rules);
33457
+ if (!fs47.existsSync(rulesSource)) {
33347
33458
  return [];
33348
33459
  }
33349
33460
  return compileRules(rulesSource, target, mappings, createLossReport()).dotRulesFiles;
33350
33461
  }
33351
33462
  function classifyDirectoryPresence(component, dirPath) {
33352
- const present = fs46.existsSync(dirPath) && fs46.statSync(dirPath).isDirectory();
33463
+ const present = fs47.existsSync(dirPath) && fs47.statSync(dirPath).isDirectory();
33353
33464
  return {
33354
33465
  component,
33355
33466
  className: present ? "current" : "missing",
@@ -33368,7 +33479,7 @@ function slotsForScope2(scopeMap, scope, projectRoot) {
33368
33479
  const root = projectRoot ?? process.cwd();
33369
33480
  const resolved = {};
33370
33481
  for (const [slot, value] of Object.entries(projectSlots)) {
33371
- resolved[slot] = typeof value === "string" ? path47.resolve(root, value) : value;
33482
+ resolved[slot] = typeof value === "string" ? path48.resolve(root, value) : value;
33372
33483
  }
33373
33484
  return resolved;
33374
33485
  }
@@ -33388,21 +33499,21 @@ function classifyCodexFiles(config, sourceRoot, configDir, scope, projectRoot) {
33388
33499
  rules: paths.rules
33389
33500
  };
33390
33501
  const rules = compileRules(
33391
- path47.join(sourceRoot, config.source.rules),
33502
+ path48.join(sourceRoot, config.source.rules),
33392
33503
  "codex",
33393
33504
  mappings,
33394
33505
  createLossReport()
33395
33506
  );
33396
- const instructionsSource = fs46.readFileSync(instructionsSourcePath(sourceRoot, config), "utf8").trim();
33507
+ const instructionsSource = fs47.readFileSync(instructionsSourcePath(sourceRoot, config), "utf8").trim();
33397
33508
  const composedInstructions = `${instructionsSource}
33398
33509
 
33399
33510
  --- tangyr managed rules ---
33400
33511
  ${rules.agentsAppendix}`.trim();
33401
33512
  const agentFiles = ts(
33402
- path47.join(sourceRoot, config.source.agents, "*.md")
33513
+ path48.join(sourceRoot, config.source.agents, "*.md")
33403
33514
  ).sort();
33404
33515
  const hooksPresent = hooksSourceExists(sourceRoot, config);
33405
- const mcpSource = path47.join(sourceRoot, config.source.mcp);
33516
+ const mcpSource = path48.join(sourceRoot, config.source.mcp);
33406
33517
  const ruleRows = rules.dotRulesFiles.length === 0 ? [
33407
33518
  {
33408
33519
  component: "rules",
@@ -33413,7 +33524,7 @@ ${rules.agentsAppendix}`.trim();
33413
33524
  ] : rules.dotRulesFiles.map(
33414
33525
  (ruleFile) => classifyCompiledFile(
33415
33526
  `rules/${ruleFile.name}`,
33416
- path47.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
33527
+ path48.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
33417
33528
  "codex",
33418
33529
  void 0,
33419
33530
  config,
@@ -33431,10 +33542,10 @@ ${rules.agentsAppendix}`.trim();
33431
33542
  ),
33432
33543
  ...agentFiles.map(
33433
33544
  (agentFile) => classifyCompiledFile(
33434
- `agents/${path47.basename(agentFile, ".md")}`,
33435
- path47.join(
33545
+ `agents/${path48.basename(agentFile, ".md")}`,
33546
+ path48.join(
33436
33547
  resolveTargetPath(codexPaths.agents),
33437
- `${path47.basename(agentFile, ".md")}.toml`
33548
+ `${path48.basename(agentFile, ".md")}.toml`
33438
33549
  ),
33439
33550
  "codex",
33440
33551
  computeSourceHash(agentFile),
@@ -33462,7 +33573,7 @@ ${rules.agentsAppendix}`.trim();
33462
33573
  "hooks",
33463
33574
  resolveTargetPath(codexPaths.hooksSharedFile)
33464
33575
  ),
33465
- fs46.existsSync(mcpSource) ? classifyCompiledFile(
33576
+ fs47.existsSync(mcpSource) ? classifyCompiledFile(
33466
33577
  "mcp",
33467
33578
  resolveTargetPath(codexPaths.mcpSharedFile),
33468
33579
  "codex",
@@ -33528,20 +33639,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
33528
33639
  mcpSharedFile: paths.mcp_shared_file
33529
33640
  };
33530
33641
  const agentFiles = ts(
33531
- path47.join(sourceRoot, config.source.agents, "*.md")
33642
+ path48.join(sourceRoot, config.source.agents, "*.md")
33532
33643
  ).sort();
33533
33644
  const commandFiles = ts(
33534
- path47.join(sourceRoot, config.source.commands, "*.md")
33645
+ path48.join(sourceRoot, config.source.commands, "*.md")
33535
33646
  ).sort();
33536
33647
  const hooksPresent = hooksSourceExists(sourceRoot, config);
33537
- const mcpSource = path47.join(sourceRoot, config.source.mcp);
33648
+ const mcpSource = path48.join(sourceRoot, config.source.mcp);
33538
33649
  return [
33539
33650
  ...agentFiles.map(
33540
33651
  (agentFile) => classifyCompiledFile(
33541
- `agents/${path47.basename(agentFile, ".md")}`,
33542
- path47.join(
33652
+ `agents/${path48.basename(agentFile, ".md")}`,
33653
+ path48.join(
33543
33654
  resolveTargetPath(copilotPaths.agents),
33544
- `${path47.basename(agentFile, ".md")}.agent.md`
33655
+ `${path48.basename(agentFile, ".md")}.agent.md`
33545
33656
  ),
33546
33657
  "copilot",
33547
33658
  computeSourceHash(agentFile),
@@ -33558,10 +33669,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
33558
33669
  ),
33559
33670
  ...commandFiles.map(
33560
33671
  (commandFile) => classifyCompiledFile(
33561
- `commands/${path47.basename(commandFile, ".md")}`,
33562
- path47.join(
33672
+ `commands/${path48.basename(commandFile, ".md")}`,
33673
+ path48.join(
33563
33674
  resolveTargetPath(copilotPaths.prompts),
33564
- `${path47.basename(commandFile, ".md")}.prompt.md`
33675
+ `${path48.basename(commandFile, ".md")}.prompt.md`
33565
33676
  ),
33566
33677
  "copilot",
33567
33678
  computeSourceHash(commandFile),
@@ -33580,19 +33691,19 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
33580
33691
  sourceRoot
33581
33692
  ),
33582
33693
  hooksPresent ? classifyCompiledHooksByProvenance(
33583
- path47.join(
33694
+ path48.join(
33584
33695
  resolveTargetPath(copilotPaths.hooks),
33585
33696
  "tangyr-managed.json"
33586
33697
  ),
33587
33698
  "copilot"
33588
33699
  ) : notConfiguredRow(
33589
33700
  "hooks",
33590
- path47.join(
33701
+ path48.join(
33591
33702
  resolveTargetPath(copilotPaths.hooks),
33592
33703
  "tangyr-managed.json"
33593
33704
  )
33594
33705
  ),
33595
- fs46.existsSync(mcpSource) ? classifyCompiledFile(
33706
+ fs47.existsSync(mcpSource) ? classifyCompiledFile(
33596
33707
  "mcp",
33597
33708
  resolveTargetPath(copilotPaths.mcpSharedFile),
33598
33709
  "copilot",
@@ -33612,7 +33723,7 @@ function notConfiguredRow(component, filePath) {
33612
33723
  }
33613
33724
  function classifyDirectArtifact(artifact, config, sourceRoot) {
33614
33725
  const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
33615
- const sourcePath = artifact.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : artifact.sourceKey ? path47.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
33726
+ const sourcePath = artifact.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : artifact.sourceKey ? path48.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
33616
33727
  if (artifact.sourceKey === "skills" && artifactClass === "unmanaged-conflict") {
33617
33728
  const perSkill = classifyPerSkillSlot(artifact.path, sourceRoot);
33618
33729
  if (perSkill) {
@@ -33708,20 +33819,23 @@ function classifyClaudeCodeRows(sourceRoot, config, configDir, scope, projectRoo
33708
33819
  function classifyPerSkillSlot(slotPath, sourceRoot) {
33709
33820
  let entries;
33710
33821
  try {
33711
- const stat = fs46.lstatSync(slotPath);
33822
+ const stat = fs47.lstatSync(slotPath);
33712
33823
  if (!stat.isDirectory() || stat.isSymbolicLink()) {
33713
33824
  return null;
33714
33825
  }
33715
- entries = fs46.readdirSync(slotPath, { withFileTypes: true });
33826
+ entries = fs47.readdirSync(slotPath, { withFileTypes: true });
33716
33827
  } catch {
33717
33828
  return null;
33718
33829
  }
33830
+ if (entries.length === 0) {
33831
+ return "managed-symlink";
33832
+ }
33719
33833
  const links = entries.filter((entry) => entry.isSymbolicLink());
33720
33834
  if (links.length === 0) {
33721
33835
  return null;
33722
33836
  }
33723
33837
  const ours = links.filter(
33724
- (entry) => isOurSymlink(path47.join(slotPath, entry.name), sourceRoot)
33838
+ (entry) => isOurSymlink(path48.join(slotPath, entry.name), sourceRoot)
33725
33839
  );
33726
33840
  if (ours.length === 0) {
33727
33841
  return null;
@@ -33733,9 +33847,9 @@ function classifyClaudeSharedFiles(config, sourceRoot, settingsPath, claudeJsonP
33733
33847
  classifyHooks(settingsPath),
33734
33848
  classifySettings(
33735
33849
  settingsPath,
33736
- path47.resolve(sourceRoot, config.source.settings)
33850
+ path48.resolve(sourceRoot, config.source.settings)
33737
33851
  ),
33738
- classifyMcp(claudeJsonPath, path47.resolve(sourceRoot, config.source.mcp))
33852
+ classifyMcp(claudeJsonPath, path48.resolve(sourceRoot, config.source.mcp))
33739
33853
  ];
33740
33854
  }
33741
33855
  function claudeSharedFileRows(config, sourceRoot, configDir, scope, projectRoot) {
@@ -33832,14 +33946,14 @@ function classifyMcp(filePath, sourcePath) {
33832
33946
  }
33833
33947
  function isSymlinkCurrent(linkPath, sourcePath) {
33834
33948
  try {
33835
- return fs46.realpathSync(linkPath) === fs46.realpathSync(sourcePath);
33949
+ return fs47.realpathSync(linkPath) === fs47.realpathSync(sourcePath);
33836
33950
  } catch {
33837
33951
  return false;
33838
33952
  }
33839
33953
  }
33840
33954
  function isCompiledCurrent6(filePath, sourcePath) {
33841
33955
  try {
33842
- const marker = extractProvenanceMarker(fs46.readFileSync(filePath, "utf8"));
33956
+ const marker = extractProvenanceMarker(fs47.readFileSync(filePath, "utf8"));
33843
33957
  return marker?.hash === computeSourceHash(sourcePath) && marker.target === "claude-code";
33844
33958
  } catch {
33845
33959
  return false;
@@ -33869,7 +33983,7 @@ function classifyCompiledFile(component, filePath, target, expectedHash, config,
33869
33983
  }
33870
33984
  function readCompiledContent(filePath) {
33871
33985
  try {
33872
- return fs46.readFileSync(filePath, "utf8");
33986
+ return fs47.readFileSync(filePath, "utf8");
33873
33987
  } catch {
33874
33988
  return null;
33875
33989
  }
@@ -33900,8 +34014,8 @@ function hashString6(value) {
33900
34014
  }
33901
34015
 
33902
34016
  // src/commands/sync.ts
33903
- import fs47 from "fs";
33904
- import path48 from "path";
34017
+ import fs48 from "fs";
34018
+ import path49 from "path";
33905
34019
 
33906
34020
  // node_modules/chalk/source/vendor/ansi-styles/index.js
33907
34021
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -34571,13 +34685,13 @@ async function runSyncCommand(options, logger) {
34571
34685
  reportHookRejections(
34572
34686
  lossReport,
34573
34687
  targets,
34574
- path48.resolve(kitInfo.path, "hooks"),
34688
+ path49.resolve(kitInfo.path, "hooks"),
34575
34689
  kitInfo.components.hooks.declared
34576
34690
  );
34577
34691
  const hooksConflict = reportHooksSourceConflict(
34578
34692
  lossReport,
34579
34693
  targets,
34580
- path48.resolve(kitInfo.path, "hooks"),
34694
+ path49.resolve(kitInfo.path, "hooks"),
34581
34695
  kitInfo.components.hooks.declared
34582
34696
  );
34583
34697
  if (hooksConflict) {
@@ -34780,8 +34894,8 @@ function reconcileSyncedArtifacts(manifest, results, mappings, scope, projectRoo
34780
34894
  }
34781
34895
  }
34782
34896
  function resolveKitFilePath(kitPath, relativePath) {
34783
- const fullPath = path48.join(kitPath, relativePath);
34784
- return fs47.existsSync(fullPath) ? fullPath : null;
34897
+ const fullPath = path49.join(kitPath, relativePath);
34898
+ return fs48.existsSync(fullPath) ? fullPath : null;
34785
34899
  }
34786
34900
  function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
34787
34901
  if (removedSourcePaths.length === 0 || !mappings) {
@@ -34844,9 +34958,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
34844
34958
  }
34845
34959
  if (relativePath.startsWith("agents/")) {
34846
34960
  removeManagedCompiledArtifact2(
34847
- path48.join(
34961
+ path49.join(
34848
34962
  resolveTargetPath(paths.agents ?? ""),
34849
- `${path48.parse(relativePath).name}.agent.md`
34963
+ `${path49.parse(relativePath).name}.agent.md`
34850
34964
  ),
34851
34965
  "copilot",
34852
34966
  relativePath,
@@ -34856,9 +34970,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
34856
34970
  }
34857
34971
  if (relativePath.startsWith("commands/")) {
34858
34972
  removeManagedCompiledArtifact2(
34859
- path48.join(
34973
+ path49.join(
34860
34974
  resolveTargetPath(paths.prompts ?? ""),
34861
- `${path48.parse(relativePath).name}.prompt.md`
34975
+ `${path49.parse(relativePath).name}.prompt.md`
34862
34976
  ),
34863
34977
  "copilot",
34864
34978
  relativePath,
@@ -34868,7 +34982,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
34868
34982
  }
34869
34983
  if (relativePath.endsWith("hooks.json")) {
34870
34984
  removeManagedCompiledArtifact2(
34871
- path48.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
34985
+ path49.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
34872
34986
  "copilot",
34873
34987
  relativePath,
34874
34988
  logger
@@ -34898,9 +35012,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
34898
35012
  }
34899
35013
  if (relativePath.startsWith("agents/")) {
34900
35014
  removeManagedCompiledArtifact2(
34901
- path48.join(
35015
+ path49.join(
34902
35016
  resolveTargetPath(paths.agents ?? ""),
34903
- `${path48.parse(relativePath).name}.toml`
35017
+ `${path49.parse(relativePath).name}.toml`
34904
35018
  ),
34905
35019
  "codex",
34906
35020
  relativePath,
@@ -34910,9 +35024,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
34910
35024
  }
34911
35025
  if (relativePath.startsWith("rules/")) {
34912
35026
  removeManagedCompiledArtifact2(
34913
- path48.join(
35027
+ path49.join(
34914
35028
  resolveTargetPath(paths.rules ?? ""),
34915
- `${path48.parse(relativePath).name}.rules`
35029
+ `${path49.parse(relativePath).name}.rules`
34916
35030
  ),
34917
35031
  "codex",
34918
35032
  relativePath,
@@ -34951,9 +35065,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
34951
35065
  }
34952
35066
  if (relativePath.startsWith("agents/")) {
34953
35067
  removeManagedCompiledArtifact2(
34954
- path48.join(
35068
+ path49.join(
34955
35069
  resolveTargetPath(paths.agents ?? ""),
34956
- `${path48.parse(relativePath).name}.md`
35070
+ `${path49.parse(relativePath).name}.md`
34957
35071
  ),
34958
35072
  "opencode",
34959
35073
  relativePath,
@@ -34963,9 +35077,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
34963
35077
  }
34964
35078
  if (relativePath.startsWith("commands/")) {
34965
35079
  removeManagedCompiledArtifact2(
34966
- path48.join(
35080
+ path49.join(
34967
35081
  resolveTargetPath(paths.commands ?? ""),
34968
- `${path48.parse(relativePath).name}.md`
35082
+ `${path49.parse(relativePath).name}.md`
34969
35083
  ),
34970
35084
  "opencode",
34971
35085
  relativePath,
@@ -34997,9 +35111,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
34997
35111
  }
34998
35112
  if (relativePath.startsWith("agents/")) {
34999
35113
  removeManagedCompiledArtifact2(
35000
- path48.join(
35114
+ path49.join(
35001
35115
  resolveTargetPath(paths.agents ?? ""),
35002
- `${path48.parse(relativePath).name}.md`
35116
+ `${path49.parse(relativePath).name}.md`
35003
35117
  ),
35004
35118
  "cursor",
35005
35119
  relativePath,
@@ -35009,9 +35123,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
35009
35123
  }
35010
35124
  if (relativePath.startsWith("rules/")) {
35011
35125
  removeManagedCompiledArtifact2(
35012
- path48.join(
35126
+ path49.join(
35013
35127
  resolveTargetPath(paths.rules ?? ""),
35014
- `${path48.parse(relativePath).name}.mdc`
35128
+ `${path49.parse(relativePath).name}.mdc`
35015
35129
  ),
35016
35130
  "cursor",
35017
35131
  relativePath,
@@ -35021,9 +35135,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
35021
35135
  }
35022
35136
  if (relativePath.startsWith("commands/")) {
35023
35137
  removeManagedCompiledArtifact2(
35024
- path48.join(
35138
+ path49.join(
35025
35139
  resolveTargetPath(paths.skills ?? ""),
35026
- path48.parse(relativePath).name,
35140
+ path49.parse(relativePath).name,
35027
35141
  "SKILL.md"
35028
35142
  ),
35029
35143
  "cursor",
@@ -35067,9 +35181,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
35067
35181
  }
35068
35182
  if (relativePath.startsWith("rules/")) {
35069
35183
  removeManagedCompiledArtifact2(
35070
- path48.join(
35184
+ path49.join(
35071
35185
  resolveTargetPath(paths.rules ?? ""),
35072
- `${path48.parse(relativePath).name}.md`
35186
+ `${path49.parse(relativePath).name}.md`
35073
35187
  ),
35074
35188
  "cline",
35075
35189
  relativePath,
@@ -35079,9 +35193,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
35079
35193
  }
35080
35194
  if (relativePath.startsWith("commands/")) {
35081
35195
  removeManagedCompiledArtifact2(
35082
- path48.join(
35196
+ path49.join(
35083
35197
  resolveTargetPath(paths.workflows ?? ""),
35084
- path48.basename(relativePath)
35198
+ path49.basename(relativePath)
35085
35199
  ),
35086
35200
  "cline",
35087
35201
  relativePath,
@@ -35099,17 +35213,17 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
35099
35213
  }
35100
35214
  }
35101
35215
  function removeManagedCompiledArtifact2(artifactPath, expectedTarget, expectedSource, logger) {
35102
- if (!fs47.existsSync(artifactPath)) {
35216
+ if (!fs48.existsSync(artifactPath)) {
35103
35217
  return;
35104
35218
  }
35105
- if (!fs47.statSync(artifactPath).isFile()) {
35219
+ if (!fs48.statSync(artifactPath).isFile()) {
35106
35220
  return;
35107
35221
  }
35108
- const marker = extractProvenanceMarker(fs47.readFileSync(artifactPath, "utf8"));
35222
+ const marker = extractProvenanceMarker(fs48.readFileSync(artifactPath, "utf8"));
35109
35223
  if (marker?.source !== expectedSource || marker.target !== expectedTarget) {
35110
35224
  return;
35111
35225
  }
35112
- fs47.rmSync(artifactPath, { force: true });
35226
+ fs48.rmSync(artifactPath, { force: true });
35113
35227
  logger.verbose(` removed stale target artifact: ${artifactPath}`);
35114
35228
  }
35115
35229
  function removeManagedCopilotMcpArtifact2(artifactPath, expectedSource, logger) {
@@ -35140,10 +35254,10 @@ function removeManagedCodexHooksArtifact2(artifactPath, expectedSource, logger)
35140
35254
  logger.verbose(` removed stale target artifact: ${artifactPath}`);
35141
35255
  }
35142
35256
  function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
35143
- if (!fs47.existsSync(artifactPath)) {
35257
+ if (!fs48.existsSync(artifactPath)) {
35144
35258
  return;
35145
35259
  }
35146
- const content = fs47.readFileSync(artifactPath, "utf8");
35260
+ const content = fs48.readFileSync(artifactPath, "utf8");
35147
35261
  const startMarker = "# tangyr: managed mcp start";
35148
35262
  const endMarker = "# tangyr: managed mcp end";
35149
35263
  const startIndex = content.indexOf(startMarker);
@@ -35160,19 +35274,19 @@ function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
35160
35274
  const after = content.slice(endIndex + endMarker.length).trimStart();
35161
35275
  const cleaned = [before, after].filter((entry) => entry.length > 0).join("\n\n");
35162
35276
  if (cleaned.length === 0) {
35163
- fs47.rmSync(artifactPath, { force: true });
35277
+ fs48.rmSync(artifactPath, { force: true });
35164
35278
  } else {
35165
- fs47.writeFileSync(artifactPath, `${cleaned}
35279
+ fs48.writeFileSync(artifactPath, `${cleaned}
35166
35280
  `);
35167
35281
  }
35168
35282
  logger.verbose(` removed stale target artifact: ${artifactPath}`);
35169
35283
  }
35170
35284
  function readJsonObject5(filePath) {
35171
- if (!fs47.existsSync(filePath)) {
35285
+ if (!fs48.existsSync(filePath)) {
35172
35286
  return null;
35173
35287
  }
35174
35288
  try {
35175
- const parsed = JSON.parse(fs47.readFileSync(filePath, "utf8"));
35289
+ const parsed = JSON.parse(fs48.readFileSync(filePath, "utf8"));
35176
35290
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
35177
35291
  } catch {
35178
35292
  return null;
@@ -35186,10 +35300,10 @@ function readJsonMetadata(value) {
35186
35300
  }
35187
35301
  function writeJsonOrRemove2(filePath, parsed) {
35188
35302
  if (isEmptyJsonValue2(parsed)) {
35189
- fs47.rmSync(filePath, { force: true });
35303
+ fs48.rmSync(filePath, { force: true });
35190
35304
  return;
35191
35305
  }
35192
- fs47.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
35306
+ fs48.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
35193
35307
  `);
35194
35308
  }
35195
35309
  function isEmptyJsonValue2(value) {
@@ -35249,8 +35363,8 @@ function removeManagedHookEntries(value, expectedSource) {
35249
35363
  }
35250
35364
 
35251
35365
  // src/commands/validate.ts
35252
- import fs48 from "fs";
35253
- import path49 from "path";
35366
+ import fs49 from "fs";
35367
+ import path50 from "path";
35254
35368
  var SUPPORTED_KIT_FORMATS2 = [1];
35255
35369
  var SUPPORTED_DISCIPLINE_VERSIONS = [
35256
35370
  "0.14.0",
@@ -35365,12 +35479,12 @@ function checkArchetype(kit) {
35365
35479
  }
35366
35480
  function checkHookScriptsExist(kit) {
35367
35481
  const violations = [];
35368
- const hooksDir = path49.join(kit.path, "hooks");
35482
+ const hooksDir = path50.join(kit.path, "hooks");
35369
35483
  const missingSet = new Set(kit.components.hooks.missing);
35370
35484
  for (const name of kit.components.hooks.declared) {
35371
35485
  if (missingSet.has(name)) continue;
35372
- const declarationPath = path49.join(hooksDir, `${name}.md`);
35373
- if (!fs48.existsSync(declarationPath)) continue;
35486
+ const declarationPath = path50.join(hooksDir, `${name}.md`);
35487
+ if (!fs49.existsSync(declarationPath)) continue;
35374
35488
  let data;
35375
35489
  try {
35376
35490
  ({ data } = parseMarkdownFrontmatter(declarationPath));
@@ -35380,8 +35494,8 @@ function checkHookScriptsExist(kit) {
35380
35494
  if (typeof data.command === "string" && data.command.trim().length > 0) {
35381
35495
  continue;
35382
35496
  }
35383
- const scriptPath = path49.join(hooksDir, "scripts", `${name}.ts`);
35384
- if (!fs48.existsSync(scriptPath)) {
35497
+ const scriptPath = path50.join(hooksDir, "scripts", `${name}.ts`);
35498
+ if (!fs49.existsSync(scriptPath)) {
35385
35499
  violations.push({
35386
35500
  code: "hook-script-missing",
35387
35501
  location: `hooks/scripts/${name}.ts`,
@@ -35394,10 +35508,10 @@ function checkHookScriptsExist(kit) {
35394
35508
  function checkOptionalSourceDocuments(kit) {
35395
35509
  const violations = [];
35396
35510
  for (const name of [".mcp.json", "settings.json", ".lsp.json"]) {
35397
- const filePath = path49.join(kit.path, name);
35398
- if (!fs48.existsSync(filePath)) continue;
35511
+ const filePath = path50.join(kit.path, name);
35512
+ if (!fs49.existsSync(filePath)) continue;
35399
35513
  try {
35400
- const parsed = JSON.parse(fs48.readFileSync(filePath, "utf8"));
35514
+ const parsed = JSON.parse(fs49.readFileSync(filePath, "utf8"));
35401
35515
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
35402
35516
  violations.push({
35403
35517
  code: "optional-source-malformed",
@@ -35419,10 +35533,10 @@ function checkSkillSubfolderNames(kit) {
35419
35533
  const notices = [];
35420
35534
  const canonical = new Set(CANONICAL_SKILL_SUBFOLDERS);
35421
35535
  for (const name of kit.components.skills.declared) {
35422
- const skillDir = path49.join(kit.path, "skills", name);
35536
+ const skillDir = path50.join(kit.path, "skills", name);
35423
35537
  let entries;
35424
35538
  try {
35425
- entries = fs48.readdirSync(skillDir, { withFileTypes: true });
35539
+ entries = fs49.readdirSync(skillDir, { withFileTypes: true });
35426
35540
  } catch {
35427
35541
  continue;
35428
35542
  }
@@ -35440,7 +35554,7 @@ function checkSkillSubfolderNames(kit) {
35440
35554
  return notices;
35441
35555
  }
35442
35556
  function checkHooksSourceForm(kit) {
35443
- const hooksDir = path49.join(kit.path, "hooks");
35557
+ const hooksDir = path50.join(kit.path, "hooks");
35444
35558
  const message = describeHooksSourceConflict(
35445
35559
  hooksDir,
35446
35560
  kit.components.hooks.declared
@@ -35452,12 +35566,12 @@ function checkHooksSourceForm(kit) {
35452
35566
  } : null;
35453
35567
  }
35454
35568
  function checkHookDeclarations(kit) {
35455
- const hooksDir = path49.join(kit.path, "hooks");
35569
+ const hooksDir = path50.join(kit.path, "hooks");
35456
35570
  return collectHookRejections(hooksDir, kit.components.hooks.declared).map(
35457
35571
  (r) => ({
35458
35572
  code: "hook-declaration-invalid",
35459
- location: `hooks/${path49.basename(r.file)}`,
35460
- message: `hooks: '${path49.basename(r.file, ".md")}' was rejected at '${r.field}' \u2014 ${r.reason}. Until this is fixed the hook is not installed on any target; install and sync report it as an error-severity loss and exit 3. To fix: correct the field named above in this file.`
35573
+ location: `hooks/${path50.basename(r.file)}`,
35574
+ message: `hooks: '${path50.basename(r.file, ".md")}' was rejected at '${r.field}' \u2014 ${r.reason}. Until this is fixed the hook is not installed on any target; install and sync report it as an error-severity loss and exit 3. To fix: correct the field named above in this file.`
35461
35575
  })
35462
35576
  );
35463
35577
  }
@@ -35477,11 +35591,11 @@ function checkKitFormatSupported(kit) {
35477
35591
  function checkEntrypointExists(kit) {
35478
35592
  const declared = kit.entrypoint;
35479
35593
  const entrypoint = declared ?? DEFAULT_ENTRYPOINT;
35480
- const entrypointPath = path49.join(kit.path, entrypoint);
35481
- if (fs48.existsSync(entrypointPath)) {
35594
+ const entrypointPath = path50.join(kit.path, entrypoint);
35595
+ if (fs49.existsSync(entrypointPath)) {
35482
35596
  return null;
35483
35597
  }
35484
- const legacyPresent = declared === void 0 && fs48.existsSync(path49.join(kit.path, LEGACY_ENTRYPOINT));
35598
+ const legacyPresent = declared === void 0 && fs49.existsSync(path50.join(kit.path, LEGACY_ENTRYPOINT));
35485
35599
  const remedy = legacyPresent ? `This kit has '${LEGACY_ENTRYPOINT}' but not '${DEFAULT_ENTRYPOINT}'. Until now validate looked for '${LEGACY_ENTRYPOINT}' unconditionally; it now reads the manifest's 'entrypoint', defaulting to '${DEFAULT_ENTRYPOINT}' \u2014 the contract's canonical orientation document, of which '${LEGACY_ENTRYPOINT}' is a target translation. To fix: either add "entrypoint: ${LEGACY_ENTRYPOINT}" to tangyr-kit.yaml to keep the current filename, or rename '${LEGACY_ENTRYPOINT}' to '${DEFAULT_ENTRYPOINT}'.` : declared === void 0 ? `No 'entrypoint' is declared in tangyr-kit.yaml, so '${DEFAULT_ENTRYPOINT}' is expected at the kit root. To fix: create it, or declare the file you use with "entrypoint: <filename>".` : `tangyr-kit.yaml declares "entrypoint: ${declared}", and no such file exists at the kit root. To fix: create it, or correct the declaration.`;
35486
35600
  return {
35487
35601
  code: "entrypoint-missing",
@@ -35540,9 +35654,9 @@ function checkComponentFrontmatter(kit) {
35540
35654
  const missingSet = new Set(kit.components[cat].missing);
35541
35655
  for (const name of kit.components[cat].declared) {
35542
35656
  if (missingSet.has(name)) continue;
35543
- const filePath = cat === "skills" ? path49.join(kit.path, cat, name, "SKILL.md") : path49.join(kit.path, cat, `${name}.md`);
35544
- if (!fs48.existsSync(filePath)) continue;
35545
- const relPath = path49.relative(kit.path, filePath);
35657
+ const filePath = cat === "skills" ? path50.join(kit.path, cat, name, "SKILL.md") : path50.join(kit.path, cat, `${name}.md`);
35658
+ if (!fs49.existsSync(filePath)) continue;
35659
+ const relPath = path50.relative(kit.path, filePath);
35546
35660
  try {
35547
35661
  const { data } = parseMarkdownFrontmatter(filePath);
35548
35662
  for (const field of requiredFields) {
@@ -35567,10 +35681,10 @@ function checkComponentFrontmatter(kit) {
35567
35681
  }
35568
35682
  function checkReservedRootNames(kit) {
35569
35683
  const violations = [];
35570
- if (!fs48.existsSync(kit.path) || !fs48.statSync(kit.path).isDirectory()) {
35684
+ if (!fs49.existsSync(kit.path) || !fs49.statSync(kit.path).isDirectory()) {
35571
35685
  return violations;
35572
35686
  }
35573
- const entries = fs48.readdirSync(kit.path, { withFileTypes: true });
35687
+ const entries = fs49.readdirSync(kit.path, { withFileTypes: true });
35574
35688
  for (const entry of entries) {
35575
35689
  if (RESERVED_ROOT_NAMES.includes(entry.name)) {
35576
35690
  violations.push({
@@ -35587,8 +35701,8 @@ function checkHumanOnlyCommandInvocation(kit) {
35587
35701
  const missingSet = new Set(kit.components.commands.missing);
35588
35702
  for (const name of kit.components.commands.declared) {
35589
35703
  if (missingSet.has(name)) continue;
35590
- const filePath = path49.join(kit.path, "commands", `${name}.md`);
35591
- if (!fs48.existsSync(filePath)) continue;
35704
+ const filePath = path50.join(kit.path, "commands", `${name}.md`);
35705
+ if (!fs49.existsSync(filePath)) continue;
35592
35706
  let data;
35593
35707
  try {
35594
35708
  ({ data } = parseMarkdownFrontmatter(filePath));
@@ -35601,7 +35715,7 @@ function checkHumanOnlyCommandInvocation(kit) {
35601
35715
  if (!barred) {
35602
35716
  violations.push({
35603
35717
  code: "command-human-only-model-invocable",
35604
- location: path49.relative(kit.path, filePath),
35718
+ location: path50.relative(kit.path, filePath),
35605
35719
  message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
35606
35720
  });
35607
35721
  }
@@ -35610,8 +35724,8 @@ function checkHumanOnlyCommandInvocation(kit) {
35610
35724
  }
35611
35725
 
35612
35726
  // src/commands/verify.ts
35613
- import fs49 from "fs";
35614
- import path50 from "path";
35727
+ import fs50 from "fs";
35728
+ import path51 from "path";
35615
35729
  function runVerifyCommand(options, logger) {
35616
35730
  if (options.target && !isKnownTarget(options.target)) {
35617
35731
  throwUnrecognizedTarget(options.target);
@@ -35792,8 +35906,8 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
35792
35906
  if (!slotPath) {
35793
35907
  continue;
35794
35908
  }
35795
- const fullPath = subPath ? path50.join(slotPath, subPath) : slotPath;
35796
- if (!fs49.existsSync(fullPath)) {
35909
+ const fullPath = subPath ? path51.join(slotPath, subPath) : slotPath;
35910
+ if (!fs50.existsSync(fullPath)) {
35797
35911
  failures.push(
35798
35912
  `claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`
35799
35913
  );