@alessandroraffa/tangyr 3.0.3 → 4.0.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) {
@@ -25213,8 +25220,8 @@ function toConflictPolicy2(value) {
25213
25220
  }
25214
25221
 
25215
25222
  // src/commands/install.ts
25216
- import fs44 from "fs";
25217
- import path44 from "path";
25223
+ import fs45 from "fs";
25224
+ import path45 from "path";
25218
25225
 
25219
25226
  // src/core/channel-state.ts
25220
25227
  import fs32 from "fs";
@@ -26980,8 +26987,8 @@ function isRecord3(value) {
26980
26987
  // src/adapters/codex.ts
26981
26988
  var TOML3 = __toESM(require_toml(), 1);
26982
26989
  import crypto6 from "crypto";
26983
- import fs39 from "fs";
26984
- import path38 from "path";
26990
+ import fs40 from "fs";
26991
+ import path39 from "path";
26985
26992
 
26986
26993
  // src/compiler/agents.ts
26987
26994
  var TOML = __toESM(require_toml(), 1);
@@ -27779,6 +27786,45 @@ function addHookLoss(lossReport, target, eventName, sourceLabel, severity, reaso
27779
27786
  });
27780
27787
  }
27781
27788
 
27789
+ // src/compiler/command-as-skill.ts
27790
+ var import_yaml9 = __toESM(require_dist(), 1);
27791
+ import fs38 from "fs";
27792
+ import path37 from "path";
27793
+ var CARRIED_OVER = ["argument-hint", "agent", "launch"];
27794
+ function compileCommandAsSkill(commandFile, target) {
27795
+ const name = path37.basename(commandFile, ".md");
27796
+ const { data, body } = parseMarkdownFrontmatter(commandFile);
27797
+ const relativeSource = `commands/${path37.basename(commandFile)}`;
27798
+ const description = typeof data.description === "string" && data.description.trim().length > 0 ? data.description.trim() : `The ${name} command.`;
27799
+ const frontmatter = { name, description };
27800
+ for (const key of CARRIED_OVER) {
27801
+ if (data[key] !== void 0) {
27802
+ frontmatter[key] = data[key];
27803
+ }
27804
+ }
27805
+ frontmatter["disable-model-invocation"] = true;
27806
+ frontmatter["x-tangyr"] = {
27807
+ source: relativeSource,
27808
+ hash: computeSourceHash(commandFile),
27809
+ target
27810
+ };
27811
+ const content = `---
27812
+ ${(0, import_yaml9.stringify)(frontmatter).trimEnd()}
27813
+ ---
27814
+
27815
+ ${body.trim()}
27816
+ `;
27817
+ return { name, content, relativeSource };
27818
+ }
27819
+ function compileCommandsAsSkills(commandsRoot, target) {
27820
+ if (!fs38.existsSync(commandsRoot)) {
27821
+ return [];
27822
+ }
27823
+ return fs38.readdirSync(commandsRoot).filter((entry) => entry.endsWith(".md")).sort().map(
27824
+ (entry) => compileCommandAsSkill(path37.join(commandsRoot, entry), target)
27825
+ );
27826
+ }
27827
+
27782
27828
  // src/compiler/mcp.ts
27783
27829
  var TOML2 = __toESM(require_toml(), 1);
27784
27830
  import crypto5 from "crypto";
@@ -28058,9 +28104,9 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
28058
28104
  }
28059
28105
 
28060
28106
  // src/compiler/rules.ts
28061
- import path37 from "path";
28062
- var import_yaml9 = __toESM(require_dist(), 1);
28063
- import fs38 from "fs";
28107
+ import path38 from "path";
28108
+ var import_yaml10 = __toESM(require_dist(), 1);
28109
+ import fs39 from "fs";
28064
28110
  function compileRules(sourceRulesDir, target, _mappings, lossReport) {
28065
28111
  if (target === "copilot") {
28066
28112
  addLoss(lossReport, "copilot", "rules", {
@@ -28097,13 +28143,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
28097
28143
  }
28098
28144
  const appendixParts = [];
28099
28145
  const dotRulesFiles = [];
28100
- for (const ruleFile of ts(path37.join(sourceRulesDir, "*.md")).sort()) {
28146
+ for (const ruleFile of ts(path38.join(sourceRulesDir, "*.md")).sort()) {
28101
28147
  const parsed = parseRule(ruleFile);
28102
- const name = path37.basename(ruleFile, ".md");
28148
+ const name = path38.basename(ruleFile, ".md");
28103
28149
  if (parsed.mode === "exec-policy") {
28104
28150
  dotRulesFiles.push({
28105
28151
  name: `${name}.rules`,
28106
- content: `${formatProvenanceMarker("toml", `rules/${path37.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
28152
+ content: `${formatProvenanceMarker("toml", `rules/${path38.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
28107
28153
  ${parsed.body}`
28108
28154
  });
28109
28155
  continue;
@@ -28112,7 +28158,7 @@ ${parsed.body}`
28112
28158
 
28113
28159
  ${parsed.body.trim()}`);
28114
28160
  addLoss(lossReport, "codex", "rules", {
28115
- source: `rules/${path37.basename(ruleFile)}`,
28161
+ source: `rules/${path38.basename(ruleFile)}`,
28116
28162
  fields: [
28117
28163
  {
28118
28164
  field: "mode",
@@ -28122,7 +28168,7 @@ ${parsed.body.trim()}`);
28122
28168
  "mode",
28123
28169
  "rule-as-instruction"
28124
28170
  ),
28125
- detail: `${path37.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
28171
+ detail: `${path38.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
28126
28172
  }
28127
28173
  ]
28128
28174
  });
@@ -28130,7 +28176,7 @@ ${parsed.body.trim()}`);
28130
28176
  return { agentsAppendix: appendixParts.join("\n\n"), dotRulesFiles };
28131
28177
  }
28132
28178
  function parseRule(ruleFile) {
28133
- const content = fs38.readFileSync(ruleFile, "utf8");
28179
+ const content = fs39.readFileSync(ruleFile, "utf8");
28134
28180
  if (!content.startsWith("---\n")) {
28135
28181
  return { mode: "guidance", body: content };
28136
28182
  }
@@ -28138,7 +28184,7 @@ function parseRule(ruleFile) {
28138
28184
  if (endIndex === -1) {
28139
28185
  throw new Error(`${ruleFile}: frontmatter is not closed`);
28140
28186
  }
28141
- const frontmatter = (0, import_yaml9.parse)(content.slice(4, endIndex));
28187
+ const frontmatter = (0, import_yaml10.parse)(content.slice(4, endIndex));
28142
28188
  const mode = isRuleMode(frontmatter) ? frontmatter.mode : "guidance";
28143
28189
  return {
28144
28190
  mode,
@@ -28154,14 +28200,14 @@ function isRuleMode(value) {
28154
28200
  }
28155
28201
  function compileOpenCodeRules(sourceRulesDir, lossReport) {
28156
28202
  const appendixParts = [];
28157
- for (const ruleFile of ts(path37.join(sourceRulesDir, "*.md")).sort()) {
28203
+ for (const ruleFile of ts(path38.join(sourceRulesDir, "*.md")).sort()) {
28158
28204
  const parsed = parseRule(ruleFile);
28159
- const name = path37.basename(ruleFile, ".md");
28205
+ const name = path38.basename(ruleFile, ".md");
28160
28206
  appendixParts.push(`## ${name}
28161
28207
 
28162
28208
  ${parsed.body.trim()}`);
28163
28209
  addLoss(lossReport, "opencode", "rules", {
28164
- source: `rules/${path37.basename(ruleFile)}`,
28210
+ source: `rules/${path38.basename(ruleFile)}`,
28165
28211
  fields: [
28166
28212
  {
28167
28213
  field: "rule",
@@ -28171,7 +28217,7 @@ ${parsed.body.trim()}`);
28171
28217
  "rule",
28172
28218
  "rule-path-scoping"
28173
28219
  ),
28174
- detail: `${path37.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
28220
+ detail: `${path38.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
28175
28221
  }
28176
28222
  ]
28177
28223
  });
@@ -28180,9 +28226,9 @@ ${parsed.body.trim()}`);
28180
28226
  }
28181
28227
  function compileCursorRules(sourceRulesDir, _lossReport) {
28182
28228
  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");
28229
+ for (const ruleFile of ts(path38.join(sourceRulesDir, "*.md")).sort()) {
28230
+ const content = fs39.readFileSync(ruleFile, "utf8");
28231
+ const name = path38.basename(ruleFile, ".md");
28186
28232
  let frontmatterData = {};
28187
28233
  let body = content;
28188
28234
  if (content.startsWith("---\n")) {
@@ -28190,7 +28236,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
28190
28236
  if (endIndex !== -1) {
28191
28237
  const frontmatterStr = content.slice(4, endIndex);
28192
28238
  try {
28193
- frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
28239
+ frontmatterData = (0, import_yaml10.parse)(frontmatterStr) ?? {};
28194
28240
  } catch {
28195
28241
  frontmatterData = {};
28196
28242
  }
@@ -28211,7 +28257,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
28211
28257
  }
28212
28258
  const marker = formatProvenanceMarker(
28213
28259
  "markdown",
28214
- `rules/${path37.basename(ruleFile)}`,
28260
+ `rules/${path38.basename(ruleFile)}`,
28215
28261
  computeSourceHash(ruleFile),
28216
28262
  "cursor"
28217
28263
  );
@@ -28227,9 +28273,9 @@ ${body}`;
28227
28273
  }
28228
28274
  function compileClineRules(sourceRulesDir, lossReport) {
28229
28275
  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");
28276
+ for (const ruleFile of ts(path38.join(sourceRulesDir, "*.md")).sort()) {
28277
+ const content = fs39.readFileSync(ruleFile, "utf8");
28278
+ const name = path38.basename(ruleFile, ".md");
28233
28279
  let frontmatterData = {};
28234
28280
  let body = content;
28235
28281
  if (content.startsWith("---\n")) {
@@ -28237,7 +28283,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
28237
28283
  if (endIndex !== -1) {
28238
28284
  const frontmatterStr = content.slice(4, endIndex);
28239
28285
  try {
28240
- frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
28286
+ frontmatterData = (0, import_yaml10.parse)(frontmatterStr) ?? {};
28241
28287
  } catch {
28242
28288
  frontmatterData = {};
28243
28289
  }
@@ -28246,13 +28292,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
28246
28292
  }
28247
28293
  const marker = formatProvenanceMarker(
28248
28294
  "markdown",
28249
- `rules/${path37.basename(ruleFile)}`,
28295
+ `rules/${path38.basename(ruleFile)}`,
28250
28296
  computeSourceHash(ruleFile),
28251
28297
  "cline"
28252
28298
  );
28253
28299
  if (frontmatterData.mode === "exec-policy") {
28254
28300
  addLoss(lossReport, "cline", "rules", {
28255
- source: `rules/${path37.basename(ruleFile)}`,
28301
+ source: `rules/${path38.basename(ruleFile)}`,
28256
28302
  fields: [
28257
28303
  {
28258
28304
  field: "mode",
@@ -28262,7 +28308,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
28262
28308
  "mode",
28263
28309
  "rule-mode-downgrade"
28264
28310
  ),
28265
- detail: `${path37.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
28311
+ detail: `${path38.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
28266
28312
  }
28267
28313
  ]
28268
28314
  });
@@ -28283,12 +28329,7 @@ ${frontmatterYaml}${body}`;
28283
28329
  }
28284
28330
 
28285
28331
  // src/adapters/codex.ts
28286
- var skippedComponents = [
28287
- "commands",
28288
- "settings",
28289
- "lsp",
28290
- "output-styles"
28291
- ];
28332
+ var skippedComponents = ["settings", "lsp", "output-styles"];
28292
28333
  var managedMcpStart = "# tangyr: managed mcp start";
28293
28334
  var managedMcpEnd = "# tangyr: managed mcp end";
28294
28335
  function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
@@ -28308,7 +28349,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28308
28349
  rules: profile.rules
28309
28350
  };
28310
28351
  const rules = compileRules(
28311
- path38.join(sourceRoot, config.source.rules),
28352
+ path39.join(sourceRoot, config.source.rules),
28312
28353
  "codex",
28313
28354
  mappings,
28314
28355
  lossReport
@@ -28344,7 +28385,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28344
28385
  }
28345
28386
  if (!shouldSkipComponent2(options, "skills")) {
28346
28387
  outcomes.push(
28347
- syncSkills(
28388
+ ...syncSkills(
28348
28389
  config,
28349
28390
  sourceRoot,
28350
28391
  paths,
@@ -28355,6 +28396,20 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28355
28396
  )
28356
28397
  );
28357
28398
  }
28399
+ if (!shouldSkipComponent2(options, "commands")) {
28400
+ outcomes.push(
28401
+ ...syncCommandsAsSkills(
28402
+ config,
28403
+ sourceRoot,
28404
+ paths,
28405
+ options,
28406
+ lossReport,
28407
+ logger,
28408
+ manifest,
28409
+ scopePath
28410
+ )
28411
+ );
28412
+ }
28358
28413
  if (!shouldSkipComponent2(options, "agents")) {
28359
28414
  outcomes.push(
28360
28415
  ...syncAgents(
@@ -28374,7 +28429,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28374
28429
  if (!shouldSkipComponent2(options, "hooks")) {
28375
28430
  outcomes.push(
28376
28431
  syncHookScriptsBridge({
28377
- source: path38.resolve(sourceRoot, config.source.hooks),
28432
+ source: path39.resolve(sourceRoot, config.source.hooks),
28378
28433
  destination: resolveTargetPath(paths.hook_scripts),
28379
28434
  config,
28380
28435
  sourceRoot,
@@ -28473,9 +28528,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
28473
28528
  function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
28474
28529
  const cp = mappings.modelTiers.custom_provider;
28475
28530
  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();
28531
+ const agentsDir = path39.join(sourceRoot, config.source.agents);
28532
+ if (!fs40.existsSync(agentsDir)) return "";
28533
+ const agentFiles = ts(path39.join(agentsDir, "*.md")).sort();
28479
28534
  const hasProviderAgent = agentFiles.some((agentFile) => {
28480
28535
  const { data } = parseMarkdownFrontmatter(agentFile);
28481
28536
  return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
@@ -28540,7 +28595,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
28540
28595
  }
28541
28596
  ];
28542
28597
  for (const ruleFile of rules.dotRulesFiles) {
28543
- const destination = path38.join(rulesRoot, ruleFile.name);
28598
+ const destination = path39.join(rulesRoot, ruleFile.name);
28544
28599
  if (options.dryRun) {
28545
28600
  logger.info(`[dry-run] rules: write ${destination}`);
28546
28601
  outcomes.push({
@@ -28570,16 +28625,16 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
28570
28625
  function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
28571
28626
  const source = instructionsSourcePath(sourceRoot, config);
28572
28627
  const destination = resolveTargetPath(paths.instructions);
28573
- if (!fs39.existsSync(source)) {
28628
+ if (!fs40.existsSync(source)) {
28574
28629
  return skippedMissingSource2("instructions", source);
28575
28630
  }
28576
- const composed = `${fs39.readFileSync(source, "utf8").trim()}
28631
+ const composed = `${fs40.readFileSync(source, "utf8").trim()}
28577
28632
 
28578
28633
  --- tangyr managed rules ---
28579
28634
  ${agentsAppendix}`.trim();
28580
28635
  const marker = formatProvenanceMarker(
28581
28636
  "markdown",
28582
- path38.basename(instructionsSourceLabel(sourceRoot, config)),
28637
+ path39.basename(instructionsSourceLabel(sourceRoot, config)),
28583
28638
  hashString(composed),
28584
28639
  "codex"
28585
28640
  );
@@ -28606,47 +28661,66 @@ ${composed}
28606
28661
  );
28607
28662
  }
28608
28663
  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);
28664
+ return syncSkillsSlot({
28665
+ config,
28666
+ sourceRoot,
28667
+ source: path39.resolve(sourceRoot, config.source.skills),
28668
+ destination: resolveTargetPath(paths.skills),
28669
+ dryRun: options.dryRun,
28670
+ logger,
28671
+ onUnmanagedConflict: (conflictPath) => handleConflict2(
28672
+ conflictPath,
28673
+ config,
28674
+ options,
28675
+ logger,
28676
+ manifest,
28677
+ scopePath
28678
+ )
28679
+ });
28680
+ }
28681
+ function syncCommandsAsSkills(config, sourceRoot, paths, options, _lossReport, logger, manifest, scopePath) {
28682
+ const commandsRoot = path39.resolve(sourceRoot, config.source.commands);
28683
+ if (!fs40.existsSync(commandsRoot)) {
28684
+ return [skippedMissingSource2("commands", commandsRoot)];
28633
28685
  }
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 };
28686
+ const skillsRoot = resolveTargetPath(paths.skills);
28687
+ return compileCommandsAsSkills(commandsRoot, "codex").map((skill) => {
28688
+ const destination = path39.join(skillsRoot, skill.name, "SKILL.md");
28689
+ if (options.dryRun) {
28690
+ logger.info(
28691
+ `[dry-run] commands: compile ${skill.relativeSource} -> ${destination}`
28692
+ );
28693
+ return {
28694
+ component: "commands",
28695
+ status: "dry-run",
28696
+ path: destination
28697
+ };
28698
+ }
28699
+ return writeCompiledArtifact(
28700
+ "commands",
28701
+ destination,
28702
+ skill.content,
28703
+ void 0,
28704
+ config,
28705
+ sourceRoot,
28706
+ options,
28707
+ logger,
28708
+ manifest,
28709
+ scopePath
28710
+ );
28711
+ });
28638
28712
  }
28639
28713
  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)) {
28714
+ const sourceAgentsRoot = path39.join(sourceRoot, config.source.agents);
28715
+ if (!fs40.existsSync(sourceAgentsRoot)) {
28642
28716
  return [skippedMissingSource2("agents", sourceAgentsRoot)];
28643
28717
  }
28644
- const sourceAgents = ts(path38.join(sourceAgentsRoot, "*.md")).sort();
28718
+ const sourceAgents = ts(path39.join(sourceAgentsRoot, "*.md")).sort();
28645
28719
  const agentsRoot = resolveTargetPath(paths.agents);
28646
28720
  return sourceAgents.map((agentFile) => {
28647
- const destination = path38.join(
28721
+ const destination = path39.join(
28648
28722
  agentsRoot,
28649
- `${path38.basename(agentFile, ".md")}.toml`
28723
+ `${path39.basename(agentFile, ".md")}.toml`
28650
28724
  );
28651
28725
  const compiled = compileAgent(
28652
28726
  agentFile,
@@ -28724,7 +28798,7 @@ function syncHooks2(config, sourceRoot, paths, mappings, options, lossReport, lo
28724
28798
  destination,
28725
28799
  hostHooks,
28726
28800
  stringifyJson3,
28727
- !fs39.existsSync(destination),
28801
+ !fs40.existsSync(destination),
28728
28802
  logger
28729
28803
  );
28730
28804
  return {
@@ -28737,7 +28811,7 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger, provid
28737
28811
  const source = resolveMcpSourceFile(sourceRoot, config);
28738
28812
  const sourceLabel = mcpSourceLabel(config);
28739
28813
  const destination = resolveTargetPath(paths.mcp_shared_file);
28740
- if (!fs39.existsSync(source)) {
28814
+ if (!fs40.existsSync(source)) {
28741
28815
  if (providerToml && !options.dryRun) {
28742
28816
  const changed2 = writeTomlManagedSection(
28743
28817
  destination,
@@ -28752,7 +28826,7 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger, provid
28752
28826
  }
28753
28827
  return skippedMissingSource2("mcp", source);
28754
28828
  }
28755
- const sourceMcpJson = JSON.parse(fs39.readFileSync(source, "utf8"));
28829
+ const sourceMcpJson = JSON.parse(fs40.readFileSync(source, "utf8"));
28756
28830
  const compiled = compileMcp(sourceMcpJson, "codex", lossReport, sourceLabel);
28757
28831
  const managedContent = providerToml ? `${compiled.trimEnd()}${providerToml}` : compiled;
28758
28832
  if (options.dryRun) {
@@ -28767,6 +28841,9 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger, provid
28767
28841
  };
28768
28842
  }
28769
28843
  function writeCompiledArtifact(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
28844
+ if (!options.force && isCompiledCurrent(destination, content, expectedHash)) {
28845
+ return { component, status: "skipped-current", path: destination };
28846
+ }
28770
28847
  const artifactClass = classifyArtifact(destination, config, sourceRoot);
28771
28848
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent(destination, content, expectedHash)) {
28772
28849
  return { component, status: "skipped-current", path: destination };
@@ -28774,18 +28851,18 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
28774
28851
  if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
28775
28852
  return { component, status: "conflict", path: destination };
28776
28853
  }
28777
- ensureDir(path38.dirname(destination));
28854
+ ensureDir(path39.dirname(destination));
28778
28855
  const clearedLink = clearSymlinkAtDestination(destination);
28779
28856
  if (clearedLink !== null) {
28780
28857
  logger.verbose(
28781
28858
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
28782
28859
  );
28783
28860
  }
28784
- fs39.writeFileSync(destination, content);
28861
+ fs40.writeFileSync(destination, content);
28785
28862
  return { component, status: "success", path: destination };
28786
28863
  }
28787
28864
  function writeTomlManagedSection(destination, managedContent, logger) {
28788
- const current = fs39.existsSync(destination) ? fs39.readFileSync(destination, "utf8") : "";
28865
+ const current = fs40.existsSync(destination) ? fs40.readFileSync(destination, "utf8") : "";
28789
28866
  const isFirstWrite = current.length > 0 && !current.includes(managedMcpStart);
28790
28867
  if (isFirstWrite) {
28791
28868
  logger.warn(
@@ -28801,8 +28878,8 @@ ${managedMcpEnd}
28801
28878
  if (current === next.trimStart()) {
28802
28879
  return false;
28803
28880
  }
28804
- ensureDir(path38.dirname(destination));
28805
- fs39.writeFileSync(destination, next.trimStart());
28881
+ ensureDir(path39.dirname(destination));
28882
+ fs40.writeFileSync(destination, next.trimStart());
28806
28883
  return true;
28807
28884
  }
28808
28885
  function removeManagedTomlSection(content) {
@@ -28828,7 +28905,7 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
28828
28905
  if (manifest && scopePath) {
28829
28906
  backupFile(destination, manifest, scopePath);
28830
28907
  writeManifest(scopePath, manifest);
28831
- fs39.rmSync(destination, { recursive: true, force: true });
28908
+ fs40.rmSync(destination, { recursive: true, force: true });
28832
28909
  } else {
28833
28910
  const parked = parkConflictingPath(
28834
28911
  destination,
@@ -28843,14 +28920,12 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
28843
28920
  }
28844
28921
  return true;
28845
28922
  }
28846
- fs39.rmSync(destination, { recursive: true, force: true });
28923
+ fs40.rmSync(destination, { recursive: true, force: true });
28847
28924
  return true;
28848
28925
  }
28849
- function isCompiledCurrent(destination, expectedContent, expectedHash) {
28926
+ function isCompiledCurrent(destination, expectedContent, _expectedHash) {
28850
28927
  try {
28851
- const current = fs39.readFileSync(destination, "utf8");
28852
- const marker = extractProvenanceMarker(current);
28853
- return expectedHash ? marker?.hash === expectedHash && marker.target === "codex" && current === expectedContent : current === expectedContent;
28928
+ return fs40.readFileSync(destination, "utf8") === expectedContent;
28854
28929
  } catch {
28855
28930
  return false;
28856
28931
  }
@@ -28865,18 +28940,11 @@ function skippedMissingSource2(component, source) {
28865
28940
  function shouldSkipComponent2(options, component) {
28866
28941
  return Boolean(options.component && options.component !== component);
28867
28942
  }
28868
- function isSymlinkTo4(linkPath, source) {
28869
- try {
28870
- return fs39.realpathSync(linkPath) === fs39.realpathSync(source);
28871
- } catch {
28872
- return false;
28873
- }
28874
- }
28875
28943
  function readJsonObject4(filePath) {
28876
- if (!fs39.existsSync(filePath)) {
28944
+ if (!fs40.existsSync(filePath)) {
28877
28945
  return {};
28878
28946
  }
28879
- const parsed = JSON.parse(fs39.readFileSync(filePath, "utf8"));
28947
+ const parsed = JSON.parse(fs40.readFileSync(filePath, "utf8"));
28880
28948
  return isRecord5(parsed) ? parsed : {};
28881
28949
  }
28882
28950
  function stringifyJson3(value) {
@@ -28892,16 +28960,16 @@ function hashString(value) {
28892
28960
 
28893
28961
  // src/adapters/copilot.ts
28894
28962
  import crypto7 from "crypto";
28895
- import fs40 from "fs";
28896
- import path40 from "path";
28963
+ import fs41 from "fs";
28964
+ import path41 from "path";
28897
28965
 
28898
28966
  // src/compiler/commands.ts
28899
- var import_yaml10 = __toESM(require_dist(), 1);
28900
- import path39 from "path";
28967
+ var import_yaml11 = __toESM(require_dist(), 1);
28968
+ import path40 from "path";
28901
28969
  function compileCommandPrompt(sourceFile) {
28902
28970
  const { data, body } = parseMarkdownFrontmatter(sourceFile);
28903
- const relativeSource = `commands/${path39.basename(sourceFile)}`;
28904
- const fields = promptFrontmatter(data, path39.basename(sourceFile, ".md"));
28971
+ const relativeSource = `commands/${path40.basename(sourceFile)}`;
28972
+ const fields = promptFrontmatter(data, path40.basename(sourceFile, ".md"));
28905
28973
  const marker = formatProvenanceMarker(
28906
28974
  "markdown",
28907
28975
  relativeSource,
@@ -28910,7 +28978,7 @@ function compileCommandPrompt(sourceFile) {
28910
28978
  );
28911
28979
  return `${marker}
28912
28980
  ---
28913
- ${(0, import_yaml10.stringify)(fields).trim()}
28981
+ ${(0, import_yaml11.stringify)(fields).trim()}
28914
28982
  ---
28915
28983
 
28916
28984
  ${body.trimEnd()}
@@ -29016,7 +29084,7 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
29016
29084
  if (!shouldSkipComponent3(options, "hooks")) {
29017
29085
  outcomes.push(
29018
29086
  syncHookScriptsBridge({
29019
- source: path40.resolve(sourceRoot, config.source.hooks),
29087
+ source: path41.resolve(sourceRoot, config.source.hooks),
29020
29088
  destination: resolveTargetPath(paths.hook_scripts),
29021
29089
  config,
29022
29090
  sourceRoot,
@@ -29097,13 +29165,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
29097
29165
  }
29098
29166
  function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
29099
29167
  if (!mappings.modelTiers.custom_provider) return;
29100
- const agentsDir = path40.join(sourceRoot, config.source.agents);
29101
- if (!fs40.existsSync(agentsDir)) return;
29102
- for (const agentFile of ts(path40.join(agentsDir, "*.md")).sort()) {
29168
+ const agentsDir = path41.join(sourceRoot, config.source.agents);
29169
+ if (!fs41.existsSync(agentsDir)) return;
29170
+ for (const agentFile of ts(path41.join(agentsDir, "*.md")).sort()) {
29103
29171
  const { data } = parseMarkdownFrontmatter(agentFile);
29104
29172
  const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
29105
29173
  if (hasProvider) {
29106
- const basename = path40.basename(agentFile);
29174
+ const basename = path41.basename(agentFile);
29107
29175
  addLoss(lossReport, "copilot", "agents", {
29108
29176
  source: `agents/${basename}`,
29109
29177
  fields: [
@@ -29129,22 +29197,22 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
29129
29197
  return [{ component: "instructions", status: "skipped", path: message }];
29130
29198
  }
29131
29199
  const source = instructionsSourcePath(sourceRoot, config);
29132
- if (!fs40.existsSync(source)) {
29200
+ if (!fs41.existsSync(source)) {
29133
29201
  return [skippedMissingSource3("instructions", source)];
29134
29202
  }
29135
- const rawContent = fs40.readFileSync(source, "utf8");
29203
+ const rawContent = fs41.readFileSync(source, "utf8");
29136
29204
  const contentHash = hashString2(rawContent);
29137
29205
  const marker = formatProvenanceMarker(
29138
29206
  "markdown",
29139
- path40.basename(instructionsSourceLabel(sourceRoot, config)),
29207
+ path41.basename(instructionsSourceLabel(sourceRoot, config)),
29140
29208
  contentHash,
29141
29209
  "copilot"
29142
29210
  );
29143
29211
  const composedContent = `${marker}
29144
29212
  ${rawContent}`;
29145
29213
  const projectRoot = options.projectRoot ?? process.cwd();
29146
- const agentsMdDest = path40.resolve(projectRoot, "AGENTS.md");
29147
- const mirrorDest = path40.resolve(
29214
+ const agentsMdDest = path41.resolve(projectRoot, "AGENTS.md");
29215
+ const mirrorDest = path41.resolve(
29148
29216
  projectRoot,
29149
29217
  ".github",
29150
29218
  "copilot-instructions.md"
@@ -29198,14 +29266,14 @@ function writeInstructionsFile(component, destination, content, contentHash, con
29198
29266
  if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
29199
29267
  return { component, status: "conflict", path: destination };
29200
29268
  }
29201
- ensureDir(path40.dirname(destination));
29269
+ ensureDir(path41.dirname(destination));
29202
29270
  const clearedLink = clearSymlinkAtDestination(destination);
29203
29271
  if (clearedLink !== null) {
29204
29272
  logger.verbose(
29205
29273
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
29206
29274
  );
29207
29275
  }
29208
- fs40.writeFileSync(destination, content);
29276
+ fs41.writeFileSync(destination, content);
29209
29277
  return { component, status: "success", path: destination };
29210
29278
  }
29211
29279
  function hashString2(value) {
@@ -29215,7 +29283,7 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
29215
29283
  return syncSkillsSlot({
29216
29284
  config,
29217
29285
  sourceRoot,
29218
- source: path40.resolve(sourceRoot, config.source.skills),
29286
+ source: path41.resolve(sourceRoot, config.source.skills),
29219
29287
  destination: resolveTargetPath(paths.skills),
29220
29288
  dryRun: options.dryRun,
29221
29289
  logger,
@@ -29230,16 +29298,16 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
29230
29298
  });
29231
29299
  }
29232
29300
  function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
29233
- const sourceAgentsRoot = path40.join(sourceRoot, config.source.agents);
29234
- if (!fs40.existsSync(sourceAgentsRoot)) {
29301
+ const sourceAgentsRoot = path41.join(sourceRoot, config.source.agents);
29302
+ if (!fs41.existsSync(sourceAgentsRoot)) {
29235
29303
  return [skippedMissingSource3("agents", sourceAgentsRoot)];
29236
29304
  }
29237
- const sourceAgents = ts(path40.join(sourceAgentsRoot, "*.md")).sort();
29305
+ const sourceAgents = ts(path41.join(sourceAgentsRoot, "*.md")).sort();
29238
29306
  const agentsRoot = resolveTargetPath(paths.agents);
29239
29307
  return sourceAgents.map((agentFile) => {
29240
- const destination = path40.join(
29308
+ const destination = path41.join(
29241
29309
  agentsRoot,
29242
- `${path40.basename(agentFile, ".md")}.agent.md`
29310
+ `${path41.basename(agentFile, ".md")}.agent.md`
29243
29311
  );
29244
29312
  const compiled = compileAgent(
29245
29313
  agentFile,
@@ -29267,16 +29335,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
29267
29335
  });
29268
29336
  }
29269
29337
  function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
29270
- const sourceCommandsRoot = path40.join(sourceRoot, config.source.commands);
29271
- if (!fs40.existsSync(sourceCommandsRoot)) {
29338
+ const sourceCommandsRoot = path41.join(sourceRoot, config.source.commands);
29339
+ if (!fs41.existsSync(sourceCommandsRoot)) {
29272
29340
  return [skippedMissingSource3("commands", sourceCommandsRoot)];
29273
29341
  }
29274
- const sourceCommands = ts(path40.join(sourceCommandsRoot, "*.md")).sort();
29342
+ const sourceCommands = ts(path41.join(sourceCommandsRoot, "*.md")).sort();
29275
29343
  const promptsRoot = resolveTargetPath(paths.prompts);
29276
29344
  return sourceCommands.map((commandFile) => {
29277
- const destination = path40.join(
29345
+ const destination = path41.join(
29278
29346
  promptsRoot,
29279
- `${path40.basename(commandFile, ".md")}.prompt.md`
29347
+ `${path41.basename(commandFile, ".md")}.prompt.md`
29280
29348
  );
29281
29349
  const compiled = compileCommandPrompt(commandFile);
29282
29350
  if (options.dryRun) {
@@ -29300,7 +29368,7 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
29300
29368
  });
29301
29369
  }
29302
29370
  function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, logger) {
29303
- const destination = path40.join(
29371
+ const destination = path41.join(
29304
29372
  resolveTargetPath(paths.hooks),
29305
29373
  "tangyr-managed.json"
29306
29374
  );
@@ -29363,10 +29431,10 @@ function syncMcp3(config, sourceRoot, paths, options, lossReport, logger) {
29363
29431
  const source = resolveMcpSourceFile(sourceRoot, config);
29364
29432
  const sourceLabel = mcpSourceLabel(config);
29365
29433
  const destination = resolveTargetPath(paths.mcp_shared_file);
29366
- if (!fs40.existsSync(source)) {
29434
+ if (!fs41.existsSync(source)) {
29367
29435
  return skippedMissingSource3("mcp", source);
29368
29436
  }
29369
- const sourceMcpJson = JSON.parse(fs40.readFileSync(source, "utf8"));
29437
+ const sourceMcpJson = JSON.parse(fs41.readFileSync(source, "utf8"));
29370
29438
  const compiled = compileMcp(
29371
29439
  sourceMcpJson,
29372
29440
  "copilot",
@@ -29389,6 +29457,9 @@ function syncMcp3(config, sourceRoot, paths, options, lossReport, logger) {
29389
29457
  );
29390
29458
  }
29391
29459
  function writeCompiledArtifact2(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
29460
+ if (!options.force && isCompiledCurrent2(destination, content, expectedHash)) {
29461
+ return { component, status: "skipped-current", path: destination };
29462
+ }
29392
29463
  const artifactClass = classifyArtifact(destination, config, sourceRoot);
29393
29464
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent2(destination, content, expectedHash)) {
29394
29465
  return { component, status: "skipped-current", path: destination };
@@ -29396,21 +29467,19 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
29396
29467
  if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
29397
29468
  return { component, status: "conflict", path: destination };
29398
29469
  }
29399
- ensureDir(path40.dirname(destination));
29470
+ ensureDir(path41.dirname(destination));
29400
29471
  const clearedLink = clearSymlinkAtDestination(destination);
29401
29472
  if (clearedLink !== null) {
29402
29473
  logger.verbose(
29403
29474
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
29404
29475
  );
29405
29476
  }
29406
- fs40.writeFileSync(destination, content);
29477
+ fs41.writeFileSync(destination, content);
29407
29478
  return { component, status: "success", path: destination };
29408
29479
  }
29409
- function isCompiledCurrent2(destination, expectedContent, expectedHash) {
29480
+ function isCompiledCurrent2(destination, expectedContent, _expectedHash) {
29410
29481
  try {
29411
- const current = fs40.readFileSync(destination, "utf8");
29412
- const marker = extractProvenanceMarker(current);
29413
- return expectedHash ? marker?.hash === expectedHash && marker.target === "copilot" && current === expectedContent : current === expectedContent;
29482
+ return fs41.readFileSync(destination, "utf8") === expectedContent;
29414
29483
  } catch {
29415
29484
  return false;
29416
29485
  }
@@ -29430,7 +29499,7 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
29430
29499
  if (manifest && scopePath) {
29431
29500
  backupFile(destination, manifest, scopePath);
29432
29501
  writeManifest(scopePath, manifest);
29433
- fs40.rmSync(destination, { recursive: true, force: true });
29502
+ fs41.rmSync(destination, { recursive: true, force: true });
29434
29503
  } else {
29435
29504
  const parked = parkConflictingPath(
29436
29505
  destination,
@@ -29445,7 +29514,7 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
29445
29514
  }
29446
29515
  return true;
29447
29516
  }
29448
- fs40.rmSync(destination, { recursive: true, force: true });
29517
+ fs41.rmSync(destination, { recursive: true, force: true });
29449
29518
  return true;
29450
29519
  }
29451
29520
  function shouldSkipComponent3(options, component) {
@@ -29454,12 +29523,12 @@ function shouldSkipComponent3(options, component) {
29454
29523
  function cleanupLegacyAgents(paths, options, logger) {
29455
29524
  const currentAgentsRoot = resolveTargetPath(paths.agents);
29456
29525
  const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
29457
- if (path40.resolve(currentAgentsRoot) === path40.resolve(legacyAgentsRoot)) {
29526
+ if (path41.resolve(currentAgentsRoot) === path41.resolve(legacyAgentsRoot)) {
29458
29527
  return [];
29459
29528
  }
29460
29529
  const outcomes = [];
29461
29530
  for (const filePath of ts(
29462
- path40.join(legacyAgentsRoot, "*.agent.md")
29531
+ path41.join(legacyAgentsRoot, "*.agent.md")
29463
29532
  ).sort()) {
29464
29533
  if (!isCopilotManagedCompiledFile(filePath)) {
29465
29534
  continue;
@@ -29469,14 +29538,14 @@ function cleanupLegacyAgents(paths, options, logger) {
29469
29538
  outcomes.push({ component: "agents", status: "dry-run", path: filePath });
29470
29539
  continue;
29471
29540
  }
29472
- fs40.rmSync(filePath, { force: true });
29541
+ fs41.rmSync(filePath, { force: true });
29473
29542
  outcomes.push({ component: "agents", status: "success", path: filePath });
29474
29543
  }
29475
29544
  return outcomes;
29476
29545
  }
29477
29546
  function isCopilotManagedCompiledFile(filePath) {
29478
29547
  try {
29479
- return extractProvenanceMarker(fs40.readFileSync(filePath, "utf8"))?.target === "copilot";
29548
+ return extractProvenanceMarker(fs41.readFileSync(filePath, "utf8"))?.target === "copilot";
29480
29549
  } catch {
29481
29550
  return false;
29482
29551
  }
@@ -29491,8 +29560,8 @@ function skippedMissingSource3(component, source) {
29491
29560
 
29492
29561
  // src/adapters/cursor.ts
29493
29562
  import crypto8 from "crypto";
29494
- import fs41 from "fs";
29495
- import path41 from "path";
29563
+ import fs42 from "fs";
29564
+ import path42 from "path";
29496
29565
  function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
29497
29566
  const scope = options.scope ?? "global";
29498
29567
  const profile = resolveTargetPaths({
@@ -29560,7 +29629,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
29560
29629
  }
29561
29630
  if (!shouldSkipComponent4(options, "skills")) {
29562
29631
  outcomes.push(
29563
- syncSkills3(
29632
+ ...syncSkills3(
29564
29633
  config,
29565
29634
  sourceRoot,
29566
29635
  options,
@@ -29574,7 +29643,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
29574
29643
  )
29575
29644
  );
29576
29645
  outcomes.push(
29577
- syncSkills3(
29646
+ ...syncSkills3(
29578
29647
  config,
29579
29648
  sourceRoot,
29580
29649
  options,
@@ -29604,7 +29673,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
29604
29673
  if (!shouldSkipComponent4(options, "hooks")) {
29605
29674
  outcomes.push(
29606
29675
  syncHookScriptsBridge({
29607
- source: path41.resolve(sourceRoot, config.source.hooks),
29676
+ source: path42.resolve(sourceRoot, config.source.hooks),
29608
29677
  destination: resolveTargetPath(paths.hook_scripts),
29609
29678
  config,
29610
29679
  sourceRoot,
@@ -29669,7 +29738,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
29669
29738
  const composed = composeCursorInstructions(config, sourceRoot, lossReport);
29670
29739
  const marker = formatProvenanceMarker(
29671
29740
  "markdown",
29672
- path41.basename(instructionsSourceLabel(sourceRoot, config)),
29741
+ path42.basename(instructionsSourceLabel(sourceRoot, config)),
29673
29742
  hashString3(composed),
29674
29743
  "cursor"
29675
29744
  );
@@ -29695,7 +29764,7 @@ ${composed}
29695
29764
  }
29696
29765
  function composeCursorInstructions(config, sourceRoot, lossReport) {
29697
29766
  const source = instructionsSourcePath(sourceRoot, config);
29698
- const baseContent = fs41.existsSync(source) ? fs41.readFileSync(source, "utf8").trim() : "";
29767
+ const baseContent = fs42.existsSync(source) ? fs42.readFileSync(source, "utf8").trim() : "";
29699
29768
  const personaContent = extractPrimaryPersonaContent(
29700
29769
  config,
29701
29770
  sourceRoot,
@@ -29708,11 +29777,11 @@ function composeCursorInstructions(config, sourceRoot, lossReport) {
29708
29777
  ${personaContent}`.trim() : baseContent;
29709
29778
  }
29710
29779
  function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
29711
- const agentsDir = path41.join(sourceRoot, config.source.agents);
29712
- if (!fs41.existsSync(agentsDir)) {
29780
+ const agentsDir = path42.join(sourceRoot, config.source.agents);
29781
+ if (!fs42.existsSync(agentsDir)) {
29713
29782
  return null;
29714
29783
  }
29715
- const agentFiles = ts(path41.join(agentsDir, "*.md")).sort();
29784
+ const agentFiles = ts(path42.join(agentsDir, "*.md")).sort();
29716
29785
  if (agentFiles.length === 0) {
29717
29786
  return null;
29718
29787
  }
@@ -29735,7 +29804,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
29735
29804
  return null;
29736
29805
  }
29737
29806
  addLoss(lossReport, "cursor", "instructions", {
29738
- source: `agents/${path41.basename(primaryFile)}`,
29807
+ source: `agents/${path42.basename(primaryFile)}`,
29739
29808
  fields: [
29740
29809
  {
29741
29810
  field: "persona",
@@ -29745,23 +29814,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
29745
29814
  "persona",
29746
29815
  "instructions-shim"
29747
29816
  ),
29748
- detail: `Primary persona from ${path41.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
29817
+ detail: `Primary persona from ${path42.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
29749
29818
  }
29750
29819
  ]
29751
29820
  });
29752
29821
  return body.trim();
29753
29822
  }
29754
29823
  function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
29755
- const sourceAgentsRoot = path41.join(sourceRoot, config.source.agents);
29756
- if (!fs41.existsSync(sourceAgentsRoot)) {
29824
+ const sourceAgentsRoot = path42.join(sourceRoot, config.source.agents);
29825
+ if (!fs42.existsSync(sourceAgentsRoot)) {
29757
29826
  return [skippedMissingSource4("agents", sourceAgentsRoot)];
29758
29827
  }
29759
- const sourceAgents = ts(path41.join(sourceAgentsRoot, "*.md")).sort();
29828
+ const sourceAgents = ts(path42.join(sourceAgentsRoot, "*.md")).sort();
29760
29829
  const agentsRoot = resolveTargetPath(paths.agents);
29761
29830
  return sourceAgents.map((agentFile) => {
29762
- const destination = path41.join(
29831
+ const destination = path42.join(
29763
29832
  agentsRoot,
29764
- `${path41.basename(agentFile, ".md")}.md`
29833
+ `${path42.basename(agentFile, ".md")}.md`
29765
29834
  );
29766
29835
  let compiled;
29767
29836
  try {
@@ -29802,14 +29871,14 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
29802
29871
  });
29803
29872
  }
29804
29873
  function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
29805
- const sourceRulesDir = path41.join(sourceRoot, config.source.rules);
29806
- if (!fs41.existsSync(sourceRulesDir)) {
29874
+ const sourceRulesDir = path42.join(sourceRoot, config.source.rules);
29875
+ if (!fs42.existsSync(sourceRulesDir)) {
29807
29876
  return [skippedMissingSource4("rules", sourceRulesDir)];
29808
29877
  }
29809
29878
  const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
29810
29879
  const rulesDir = resolveTargetPath(paths.rules);
29811
29880
  return compiled.dotRulesFiles.map(({ name, content }) => {
29812
- const destination = path41.join(rulesDir, name);
29881
+ const destination = path42.join(rulesDir, name);
29813
29882
  if (options.dryRun) {
29814
29883
  logger.info(`[dry-run] rules: write ${destination}`);
29815
29884
  return {
@@ -29833,30 +29902,16 @@ function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, lo
29833
29902
  });
29834
29903
  }
29835
29904
  function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
29836
- const sourceCommandsRoot = path41.join(sourceRoot, config.source.commands);
29837
- if (!fs41.existsSync(sourceCommandsRoot)) {
29905
+ const sourceCommandsRoot = path42.join(sourceRoot, config.source.commands);
29906
+ if (!fs42.existsSync(sourceCommandsRoot)) {
29838
29907
  return [skippedMissingSource4("commands", sourceCommandsRoot)];
29839
29908
  }
29840
- const sourceCommands = ts(path41.join(sourceCommandsRoot, "*.md")).sort();
29909
+ const sourceCommands = ts(path42.join(sourceCommandsRoot, "*.md")).sort();
29841
29910
  const skillsRoot = resolveTargetPath(paths.skills);
29842
29911
  return sourceCommands.map((commandFile) => {
29843
- const baseName = path41.basename(commandFile, ".md");
29844
- const destination = path41.join(skillsRoot, baseName, "SKILL.md");
29845
- const commandContent = fs41.readFileSync(commandFile, "utf8");
29846
- const relativeSource = `commands/${path41.basename(commandFile)}`;
29847
- const marker = formatProvenanceMarker(
29848
- "markdown",
29849
- relativeSource,
29850
- computeSourceHash(commandFile),
29851
- "cursor"
29852
- );
29853
- const content = `${marker}
29854
- ---
29855
- disable-model-invocation: true
29856
- ---
29857
-
29858
- ${commandContent.trim()}
29859
- `;
29912
+ const baseName = path42.basename(commandFile, ".md");
29913
+ const destination = path42.join(skillsRoot, baseName, "SKILL.md");
29914
+ const { content } = compileCommandAsSkill(commandFile, "cursor");
29860
29915
  if (options.dryRun) {
29861
29916
  logger.info(
29862
29917
  `[dry-run] commands: compile ${commandFile} -> ${destination}`
@@ -29881,39 +29936,23 @@ ${commandContent.trim()}
29881
29936
  );
29882
29937
  });
29883
29938
  }
29884
- function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, component = "skills", destination = "", asSymlink = false) {
29885
- const source = path41.resolve(sourceRoot, config.source.skills);
29886
- if (!fs41.existsSync(source)) {
29887
- return skippedMissingSource4(component, source);
29888
- }
29889
- if (options.dryRun) {
29890
- const verb = asSymlink ? "symlink" : "ensuredir";
29891
- logger.info(`[dry-run] ${component}: ${verb} ${source} -> ${destination}`);
29892
- return { component, status: "dry-run", path: destination };
29893
- }
29894
- if (asSymlink) {
29895
- const artifactClass = classifyArtifact(destination, config, sourceRoot);
29896
- if (artifactClass === "managed-symlink" && isSymlinkTo5(destination, source)) {
29897
- return { component, status: "skipped-current", path: destination };
29898
- }
29899
- if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
29900
- fs41.unlinkSync(destination);
29901
- } else if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
29902
- return { component, status: "conflict", path: destination };
29903
- } else if (artifactClass === "managed-symlink") {
29904
- fs41.unlinkSync(destination);
29905
- }
29906
- ensureDir(path41.dirname(destination));
29907
- createRelativeSymlink(source, destination, "dir");
29908
- logger.verbose(`Skills: created shared skills symlink ${destination}`);
29909
- return { component, status: "success", path: destination };
29910
- }
29911
- if (fs41.existsSync(destination)) {
29912
- return { component, status: "skipped-current", path: destination };
29913
- }
29914
- ensureDir(destination);
29915
- logger.verbose(`Skills: ensured Cursor-local skills dir ${destination}`);
29916
- return { component, status: "success", path: destination };
29939
+ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, _component = "skills", destination = "", _asSymlink = false) {
29940
+ return syncSkillsSlot({
29941
+ config,
29942
+ sourceRoot,
29943
+ source: path42.resolve(sourceRoot, config.source.skills),
29944
+ destination,
29945
+ dryRun: options.dryRun,
29946
+ logger,
29947
+ onUnmanagedConflict: (conflictPath) => handleConflict4(
29948
+ conflictPath,
29949
+ config,
29950
+ options,
29951
+ logger,
29952
+ manifest,
29953
+ scopePath
29954
+ )
29955
+ });
29917
29956
  }
29918
29957
  function syncHooks4(config, sourceRoot, paths, mappings, options, lossReport, logger) {
29919
29958
  const scripts = hookScriptsDir(
@@ -29949,18 +29988,18 @@ function syncHooks4(config, sourceRoot, paths, mappings, options, lossReport, lo
29949
29988
  }
29950
29989
  const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
29951
29990
  `;
29952
- ensureDir(path41.dirname(destination));
29953
- fs41.writeFileSync(destination, hooksFileContent);
29991
+ ensureDir(path42.dirname(destination));
29992
+ fs42.writeFileSync(destination, hooksFileContent);
29954
29993
  return { component: "hooks", status: "success", path: destination };
29955
29994
  }
29956
29995
  function syncMcp4(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
29957
29996
  const source = resolveMcpSourceFile(sourceRoot, config);
29958
29997
  const sourceLabel = mcpSourceLabel(config);
29959
29998
  const destination = resolveTargetPath(paths.mcp_file);
29960
- if (!fs41.existsSync(source)) {
29999
+ if (!fs42.existsSync(source)) {
29961
30000
  return skippedMissingSource4("mcp", source);
29962
30001
  }
29963
- const sourceMcpJson = JSON.parse(fs41.readFileSync(source, "utf8"));
30002
+ const sourceMcpJson = JSON.parse(fs42.readFileSync(source, "utf8"));
29964
30003
  const mcpJson = compileMcp(sourceMcpJson, "cursor", lossReport, sourceLabel);
29965
30004
  if (options.dryRun) {
29966
30005
  logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
@@ -30013,13 +30052,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
30013
30052
  );
30014
30053
  }
30015
30054
  function syncProviderPin(config, sourceRoot, lossReport) {
30016
- const agentsDir = path41.join(sourceRoot, config.source.agents);
30017
- if (!fs41.existsSync(agentsDir)) return;
30018
- for (const agentFile of ts(path41.join(agentsDir, "*.md")).sort()) {
30055
+ const agentsDir = path42.join(sourceRoot, config.source.agents);
30056
+ if (!fs42.existsSync(agentsDir)) return;
30057
+ for (const agentFile of ts(path42.join(agentsDir, "*.md")).sort()) {
30019
30058
  const { data } = parseMarkdownFrontmatter(agentFile);
30020
30059
  const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
30021
30060
  if (hasCustomProvider) {
30022
- const relativeSource = `agents/${path41.basename(agentFile)}`;
30061
+ const relativeSource = `agents/${path42.basename(agentFile)}`;
30023
30062
  addLoss(lossReport, "cursor", "agents", {
30024
30063
  source: relativeSource,
30025
30064
  fields: [
@@ -30031,7 +30070,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
30031
30070
  "provider",
30032
30071
  "provider-not-representable"
30033
30072
  ),
30034
- detail: `${path41.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
30073
+ detail: `${path42.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
30035
30074
  }
30036
30075
  ]
30037
30076
  });
@@ -30039,6 +30078,9 @@ function syncProviderPin(config, sourceRoot, lossReport) {
30039
30078
  }
30040
30079
  }
30041
30080
  function writeCompiledArtifact3(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
30081
+ if (!options.force && isCompiledCurrent3(destination, content, expectedHash)) {
30082
+ return { component, status: "skipped-current", path: destination };
30083
+ }
30042
30084
  const artifactClass = classifyArtifact(destination, config, sourceRoot);
30043
30085
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent3(destination, content, expectedHash)) {
30044
30086
  return { component, status: "skipped-current", path: destination };
@@ -30046,14 +30088,14 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
30046
30088
  if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
30047
30089
  return { component, status: "conflict", path: destination };
30048
30090
  }
30049
- ensureDir(path41.dirname(destination));
30091
+ ensureDir(path42.dirname(destination));
30050
30092
  const clearedLink = clearSymlinkAtDestination(destination);
30051
30093
  if (clearedLink !== null) {
30052
30094
  logger.verbose(
30053
30095
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
30054
30096
  );
30055
30097
  }
30056
- fs41.writeFileSync(destination, content);
30098
+ fs42.writeFileSync(destination, content);
30057
30099
  return { component, status: "success", path: destination };
30058
30100
  }
30059
30101
  function handleConflict4(destination, config, options, logger, manifest, scopePath) {
@@ -30071,7 +30113,7 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
30071
30113
  if (manifest && scopePath) {
30072
30114
  backupFile(destination, manifest, scopePath);
30073
30115
  writeManifest(scopePath, manifest);
30074
- fs41.rmSync(destination, { recursive: true, force: true });
30116
+ fs42.rmSync(destination, { recursive: true, force: true });
30075
30117
  } else {
30076
30118
  const parked = parkConflictingPath(
30077
30119
  destination,
@@ -30086,14 +30128,12 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
30086
30128
  }
30087
30129
  return true;
30088
30130
  }
30089
- fs41.rmSync(destination, { recursive: true, force: true });
30131
+ fs42.rmSync(destination, { recursive: true, force: true });
30090
30132
  return true;
30091
30133
  }
30092
- function isCompiledCurrent3(destination, expectedContent, expectedHash) {
30134
+ function isCompiledCurrent3(destination, expectedContent, _expectedHash) {
30093
30135
  try {
30094
- const current = fs41.readFileSync(destination, "utf8");
30095
- const marker = extractProvenanceMarker(current);
30096
- return expectedHash ? marker?.hash === expectedHash && marker.target === "cursor" && current === expectedContent : current === expectedContent;
30136
+ return fs42.readFileSync(destination, "utf8") === expectedContent;
30097
30137
  } catch {
30098
30138
  return false;
30099
30139
  }
@@ -30108,21 +30148,14 @@ function skippedMissingSource4(component, source) {
30108
30148
  function shouldSkipComponent4(options, component) {
30109
30149
  return Boolean(options.component && options.component !== component);
30110
30150
  }
30111
- function isSymlinkTo5(linkPath, source) {
30112
- try {
30113
- return fs41.realpathSync(linkPath) === fs41.realpathSync(source);
30114
- } catch {
30115
- return false;
30116
- }
30117
- }
30118
30151
  function hashString3(value) {
30119
30152
  return `sha256:${crypto8.createHash("sha256").update(value).digest("hex")}`;
30120
30153
  }
30121
30154
 
30122
30155
  // src/adapters/cline.ts
30123
30156
  import crypto9 from "crypto";
30124
- import fs42 from "fs";
30125
- import path42 from "path";
30157
+ import fs43 from "fs";
30158
+ import path43 from "path";
30126
30159
  function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
30127
30160
  const scope = options.scope ?? "global";
30128
30161
  const profile = resolveTargetPaths({
@@ -30197,7 +30230,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
30197
30230
  }
30198
30231
  if (!shouldSkipComponent5(options, "skills")) {
30199
30232
  outcomes.push(
30200
- syncSkills4(
30233
+ ...syncSkills4(
30201
30234
  config,
30202
30235
  sourceRoot,
30203
30236
  paths,
@@ -30235,7 +30268,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
30235
30268
  function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
30236
30269
  if (scope === "global" || paths.instructions === null) {
30237
30270
  addLoss(lossReport, "cline", "instructions", {
30238
- source: path42.basename(instructionsSourceLabel(sourceRoot, config)),
30271
+ source: path43.basename(instructionsSourceLabel(sourceRoot, config)),
30239
30272
  fields: [
30240
30273
  {
30241
30274
  field: "instructions",
@@ -30257,10 +30290,10 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
30257
30290
  }
30258
30291
  const source = instructionsSourcePath(sourceRoot, config);
30259
30292
  const destination = resolveTargetPath(paths.instructions);
30260
- const baseContent = fs42.existsSync(source) ? fs42.readFileSync(source, "utf8").trim() : "";
30293
+ const baseContent = fs43.existsSync(source) ? fs43.readFileSync(source, "utf8").trim() : "";
30261
30294
  const marker = formatProvenanceMarker(
30262
30295
  "markdown",
30263
- path42.basename(instructionsSourceLabel(sourceRoot, config)),
30296
+ path43.basename(instructionsSourceLabel(sourceRoot, config)),
30264
30297
  hashString4(baseContent),
30265
30298
  "cline"
30266
30299
  );
@@ -30285,11 +30318,11 @@ ${baseContent}
30285
30318
  );
30286
30319
  }
30287
30320
  function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
30288
- const sourceAgentsRoot = path42.join(sourceRoot, config.source.agents);
30289
- if (!fs42.existsSync(sourceAgentsRoot)) {
30321
+ const sourceAgentsRoot = path43.join(sourceRoot, config.source.agents);
30322
+ if (!fs43.existsSync(sourceAgentsRoot)) {
30290
30323
  return [skippedMissingSource5("agents", sourceAgentsRoot)];
30291
30324
  }
30292
- const sourceAgents = ts(path42.join(sourceAgentsRoot, "*.md")).sort();
30325
+ const sourceAgents = ts(path43.join(sourceAgentsRoot, "*.md")).sort();
30293
30326
  return sourceAgents.map((agentFile) => {
30294
30327
  compileAgent(agentFile, "cline", mappings, extensions, lossReport);
30295
30328
  if (options.dryRun) {
@@ -30305,14 +30338,14 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
30305
30338
  });
30306
30339
  }
30307
30340
  function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
30308
- const sourceRulesDir = path42.join(sourceRoot, config.source.rules);
30309
- if (!fs42.existsSync(sourceRulesDir)) {
30341
+ const sourceRulesDir = path43.join(sourceRoot, config.source.rules);
30342
+ if (!fs43.existsSync(sourceRulesDir)) {
30310
30343
  return [skippedMissingSource5("rules", sourceRulesDir)];
30311
30344
  }
30312
30345
  const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
30313
30346
  const rulesDir = resolveTargetPath(paths.rules);
30314
30347
  return compiled.dotRulesFiles.map(({ name, content }) => {
30315
- const destination = path42.join(rulesDir, name);
30348
+ const destination = path43.join(rulesDir, name);
30316
30349
  if (options.dryRun) {
30317
30350
  logger.info(`[dry-run] rules: write ${destination}`);
30318
30351
  return {
@@ -30336,17 +30369,17 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
30336
30369
  });
30337
30370
  }
30338
30371
  function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
30339
- const sourceCommandsRoot = path42.join(sourceRoot, config.source.commands);
30340
- if (!fs42.existsSync(sourceCommandsRoot)) {
30372
+ const sourceCommandsRoot = path43.join(sourceRoot, config.source.commands);
30373
+ if (!fs43.existsSync(sourceCommandsRoot)) {
30341
30374
  return [skippedMissingSource5("commands", sourceCommandsRoot)];
30342
30375
  }
30343
- const sourceCommands = ts(path42.join(sourceCommandsRoot, "*.md")).sort();
30376
+ const sourceCommands = ts(path43.join(sourceCommandsRoot, "*.md")).sort();
30344
30377
  const workflowsRoot = resolveTargetPath(paths.workflows);
30345
30378
  return sourceCommands.map((commandFile) => {
30346
- const baseName = path42.basename(commandFile);
30347
- const destination = path42.join(workflowsRoot, baseName);
30348
- const commandContent = fs42.readFileSync(commandFile, "utf8");
30349
- const relativeSource = `commands/${path42.basename(commandFile)}`;
30379
+ const baseName = path43.basename(commandFile);
30380
+ const destination = path43.join(workflowsRoot, baseName);
30381
+ const commandContent = fs43.readFileSync(commandFile, "utf8");
30382
+ const relativeSource = `commands/${path43.basename(commandFile)}`;
30350
30383
  const marker = formatProvenanceMarker(
30351
30384
  "markdown",
30352
30385
  relativeSource,
@@ -30381,44 +30414,22 @@ ${commandContent.trim()}
30381
30414
  });
30382
30415
  }
30383
30416
  function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
30384
- const source = path42.resolve(sourceRoot, config.source.skills);
30385
- const destination = resolveTargetPath(paths.skills);
30386
- if (!fs42.existsSync(source)) {
30387
- return skippedMissingSource5("skills", source);
30388
- }
30389
- if (options.dryRun) {
30390
- logger.info(`[dry-run] skills: symlink ${source} -> ${destination}`);
30391
- return { component: "skills", status: "dry-run", path: destination };
30392
- }
30393
- const artifactClass = classifyArtifact(destination, config, sourceRoot);
30394
- if (artifactClass === "managed-symlink" && isSymlinkTo6(destination, source)) {
30395
- return {
30396
- component: "skills",
30397
- status: "skipped-current",
30398
- path: destination
30399
- };
30400
- }
30401
- if (
30402
- // A stale symlink from a superseded source root. Every other adapter
30403
- // unlinks it here; this one did not, so classifyArtifact's `managed-stale`
30404
- // matched no branch, fell through, and handed symlinkSync a path that
30405
- // already existed. Measured: sync died with "EEXIST: file already exists,
30406
- // symlink … -> ~/.cline/skills" and every component after skills went
30407
- // unsynced.
30408
- artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)
30409
- ) {
30410
- fs42.unlinkSync(destination);
30411
- } else if (artifactClass === "unmanaged-conflict") {
30412
- if (!handleConflict5(destination, config, options, logger, manifest, scopePath)) {
30413
- return { component: "skills", status: "conflict", path: destination };
30414
- }
30415
- } else if (artifactClass === "managed-symlink") {
30416
- fs42.unlinkSync(destination);
30417
- }
30418
- ensureDir(path42.dirname(destination));
30419
- createRelativeSymlink(source, destination, "dir");
30420
- logger.verbose(`Skills: created Cline skills symlink ${destination}`);
30421
- return { component: "skills", status: "success", path: destination };
30417
+ return syncSkillsSlot({
30418
+ config,
30419
+ sourceRoot,
30420
+ source: path43.resolve(sourceRoot, config.source.skills),
30421
+ destination: resolveTargetPath(paths.skills),
30422
+ dryRun: options.dryRun,
30423
+ logger,
30424
+ onUnmanagedConflict: (conflictPath) => handleConflict5(
30425
+ conflictPath,
30426
+ config,
30427
+ options,
30428
+ logger,
30429
+ manifest,
30430
+ scopePath
30431
+ )
30432
+ });
30422
30433
  }
30423
30434
  function syncHooks5(config, sourceRoot, mappings, options, lossReport, logger) {
30424
30435
  const hooksSource = loadKitHooksSource(sourceRoot, config);
@@ -30439,10 +30450,10 @@ function syncMcp5(config, sourceRoot, paths, options, lossReport, logger, manife
30439
30450
  const source = resolveMcpSourceFile(sourceRoot, config);
30440
30451
  const sourceLabel = mcpSourceLabel(config);
30441
30452
  const destination = resolveTargetPath(paths.mcp_file);
30442
- if (!fs42.existsSync(source)) {
30453
+ if (!fs43.existsSync(source)) {
30443
30454
  return skippedMissingSource5("mcp", source);
30444
30455
  }
30445
- const sourceMcpJson = JSON.parse(fs42.readFileSync(source, "utf8"));
30456
+ const sourceMcpJson = JSON.parse(fs43.readFileSync(source, "utf8"));
30446
30457
  const mcpJson = compileMcp(sourceMcpJson, "cline", lossReport, sourceLabel);
30447
30458
  if (options.dryRun) {
30448
30459
  logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
@@ -30485,11 +30496,11 @@ function syncSettings2(lossReport) {
30485
30496
  };
30486
30497
  }
30487
30498
  function syncProviderAndModel(config, sourceRoot, lossReport) {
30488
- const agentsDir = path42.join(sourceRoot, config.source.agents);
30489
- if (!fs42.existsSync(agentsDir)) return;
30490
- for (const agentFile of ts(path42.join(agentsDir, "*.md")).sort()) {
30499
+ const agentsDir = path43.join(sourceRoot, config.source.agents);
30500
+ if (!fs43.existsSync(agentsDir)) return;
30501
+ for (const agentFile of ts(path43.join(agentsDir, "*.md")).sort()) {
30491
30502
  const { data } = parseMarkdownFrontmatter(agentFile);
30492
- const relativeSource = `agents/${path42.basename(agentFile)}`;
30503
+ const relativeSource = `agents/${path43.basename(agentFile)}`;
30493
30504
  const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
30494
30505
  if (hasCustomProvider) {
30495
30506
  addLoss(lossReport, "cline", "agents", {
@@ -30503,7 +30514,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
30503
30514
  "provider",
30504
30515
  "provider-not-representable"
30505
30516
  ),
30506
- detail: `${path42.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
30517
+ detail: `${path43.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
30507
30518
  }
30508
30519
  ]
30509
30520
  });
@@ -30521,7 +30532,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
30521
30532
  "model",
30522
30533
  "model-not-representable"
30523
30534
  ),
30524
- detail: `${path42.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
30535
+ detail: `${path43.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
30525
30536
  }
30526
30537
  ]
30527
30538
  });
@@ -30529,6 +30540,9 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
30529
30540
  }
30530
30541
  }
30531
30542
  function writeCompiledArtifact4(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
30543
+ if (!options.force && isCompiledCurrent4(destination, content, expectedHash)) {
30544
+ return { component, status: "skipped-current", path: destination };
30545
+ }
30532
30546
  const artifactClass = classifyArtifact(destination, config, sourceRoot);
30533
30547
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent4(destination, content, expectedHash)) {
30534
30548
  return { component, status: "skipped-current", path: destination };
@@ -30536,14 +30550,14 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
30536
30550
  if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
30537
30551
  return { component, status: "conflict", path: destination };
30538
30552
  }
30539
- ensureDir(path42.dirname(destination));
30553
+ ensureDir(path43.dirname(destination));
30540
30554
  const clearedLink = clearSymlinkAtDestination(destination);
30541
30555
  if (clearedLink !== null) {
30542
30556
  logger.verbose(
30543
30557
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
30544
30558
  );
30545
30559
  }
30546
- fs42.writeFileSync(destination, content);
30560
+ fs43.writeFileSync(destination, content);
30547
30561
  return { component, status: "success", path: destination };
30548
30562
  }
30549
30563
  function handleConflict5(destination, config, options, logger, manifest, scopePath) {
@@ -30561,7 +30575,7 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
30561
30575
  if (manifest && scopePath) {
30562
30576
  backupFile(destination, manifest, scopePath);
30563
30577
  writeManifest(scopePath, manifest);
30564
- fs42.rmSync(destination, { recursive: true, force: true });
30578
+ fs43.rmSync(destination, { recursive: true, force: true });
30565
30579
  } else {
30566
30580
  const parked = parkConflictingPath(
30567
30581
  destination,
@@ -30576,14 +30590,12 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
30576
30590
  }
30577
30591
  return true;
30578
30592
  }
30579
- fs42.rmSync(destination, { recursive: true, force: true });
30593
+ fs43.rmSync(destination, { recursive: true, force: true });
30580
30594
  return true;
30581
30595
  }
30582
- function isCompiledCurrent4(destination, expectedContent, expectedHash) {
30596
+ function isCompiledCurrent4(destination, expectedContent, _expectedHash) {
30583
30597
  try {
30584
- const current = fs42.readFileSync(destination, "utf8");
30585
- const marker = extractProvenanceMarker(current);
30586
- return expectedHash ? marker?.hash === expectedHash && marker.target === "cline" && current === expectedContent : current === expectedContent;
30598
+ return fs43.readFileSync(destination, "utf8") === expectedContent;
30587
30599
  } catch {
30588
30600
  return false;
30589
30601
  }
@@ -30598,23 +30610,16 @@ function skippedMissingSource5(component, source) {
30598
30610
  function shouldSkipComponent5(options, component) {
30599
30611
  return Boolean(options.component && options.component !== component);
30600
30612
  }
30601
- function isSymlinkTo6(linkPath, source) {
30602
- try {
30603
- return fs42.realpathSync(linkPath) === fs42.realpathSync(source);
30604
- } catch {
30605
- return false;
30606
- }
30607
- }
30608
30613
  function hashString4(value) {
30609
30614
  return `sha256:${crypto9.createHash("sha256").update(value).digest("hex")}`;
30610
30615
  }
30611
30616
 
30612
30617
  // src/adapters/opencode.ts
30613
30618
  import crypto10 from "crypto";
30614
- import fs43 from "fs";
30619
+ import fs44 from "fs";
30615
30620
  import os6 from "os";
30616
- import path43 from "path";
30617
- var import_yaml11 = __toESM(require_dist(), 1);
30621
+ import path44 from "path";
30622
+ var import_yaml12 = __toESM(require_dist(), 1);
30618
30623
  function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
30619
30624
  const scope = options.scope ?? "global";
30620
30625
  const profile = resolveTargetPaths({
@@ -30631,7 +30636,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
30631
30636
  config_doc: profile.config_doc
30632
30637
  };
30633
30638
  const rules = compileRules(
30634
- path43.join(sourceRoot, config.source.rules),
30639
+ path44.join(sourceRoot, config.source.rules),
30635
30640
  "opencode",
30636
30641
  mappings,
30637
30642
  lossReport
@@ -30682,7 +30687,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
30682
30687
  }
30683
30688
  if (!shouldSkipComponent6(options, "skills")) {
30684
30689
  outcomes.push(
30685
- syncSkills5(
30690
+ ...syncSkills5(
30686
30691
  config,
30687
30692
  sourceRoot,
30688
30693
  paths,
@@ -30695,7 +30700,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
30695
30700
  )
30696
30701
  );
30697
30702
  outcomes.push(
30698
- syncSkills5(
30703
+ ...syncSkills5(
30699
30704
  config,
30700
30705
  sourceRoot,
30701
30706
  paths,
@@ -30735,14 +30740,14 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
30735
30740
  function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
30736
30741
  const source = instructionsSourcePath(sourceRoot, config);
30737
30742
  const destination = resolveTargetPath(paths.instructions);
30738
- const baseContent = fs43.existsSync(source) ? fs43.readFileSync(source, "utf8").trim() : "";
30743
+ const baseContent = fs44.existsSync(source) ? fs44.readFileSync(source, "utf8").trim() : "";
30739
30744
  const composed = agentsAppendix ? `${baseContent}
30740
30745
 
30741
30746
  --- tangyr managed rules ---
30742
30747
  ${agentsAppendix}`.trim() : baseContent;
30743
30748
  const marker = formatProvenanceMarker(
30744
30749
  "markdown",
30745
- path43.basename(instructionsSourceLabel(sourceRoot, config)),
30750
+ path44.basename(instructionsSourceLabel(sourceRoot, config)),
30746
30751
  hashString5(composed),
30747
30752
  "opencode"
30748
30753
  );
@@ -30769,16 +30774,16 @@ ${composed}
30769
30774
  );
30770
30775
  }
30771
30776
  function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
30772
- const sourceAgentsRoot = path43.join(sourceRoot, config.source.agents);
30773
- if (!fs43.existsSync(sourceAgentsRoot)) {
30777
+ const sourceAgentsRoot = path44.join(sourceRoot, config.source.agents);
30778
+ if (!fs44.existsSync(sourceAgentsRoot)) {
30774
30779
  return [skippedMissingSource6("agents", sourceAgentsRoot)];
30775
30780
  }
30776
- const sourceAgents = ts(path43.join(sourceAgentsRoot, "*.md")).sort();
30781
+ const sourceAgents = ts(path44.join(sourceAgentsRoot, "*.md")).sort();
30777
30782
  const agentsRoot = resolveTargetPath(paths.agents);
30778
30783
  return sourceAgents.map((agentFile) => {
30779
- const destination = path43.join(
30784
+ const destination = path44.join(
30780
30785
  agentsRoot,
30781
- `${path43.basename(agentFile, ".md")}.md`
30786
+ `${path44.basename(agentFile, ".md")}.md`
30782
30787
  );
30783
30788
  let compiled;
30784
30789
  try {
@@ -30834,19 +30839,19 @@ function applyProviderModelBinding(compiled, mappings) {
30834
30839
  const after = compiled.slice(fmEnd);
30835
30840
  let fields;
30836
30841
  try {
30837
- fields = (0, import_yaml11.parse)(yamlBlock) ?? {};
30842
+ fields = (0, import_yaml12.parse)(yamlBlock) ?? {};
30838
30843
  } catch {
30839
30844
  return compiled;
30840
30845
  }
30841
30846
  fields.model = modelValue;
30842
- return `${before}${(0, import_yaml11.stringify)(fields).trim()}${after}`;
30847
+ return `${before}${(0, import_yaml12.stringify)(fields).trim()}${after}`;
30843
30848
  }
30844
30849
  function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
30845
- const sourceCommandsRoot = path43.join(sourceRoot, config.source.commands);
30846
- if (!fs43.existsSync(sourceCommandsRoot)) {
30850
+ const sourceCommandsRoot = path44.join(sourceRoot, config.source.commands);
30851
+ if (!fs44.existsSync(sourceCommandsRoot)) {
30847
30852
  return [skippedMissingSource6("commands", sourceCommandsRoot)];
30848
30853
  }
30849
- const sourceCommands = ts(path43.join(sourceCommandsRoot, "*.md")).sort();
30854
+ const sourceCommands = ts(path44.join(sourceCommandsRoot, "*.md")).sort();
30850
30855
  const commandsRoot = resolveTargetPath(paths.commands);
30851
30856
  return sourceCommands.map((commandFile) => {
30852
30857
  const { data, body } = parseCommandFile(commandFile);
@@ -30860,7 +30865,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
30860
30865
  if (typeof data.model === "string") {
30861
30866
  frontmatter.model = data.model;
30862
30867
  }
30863
- const relativeSource = `commands/${path43.basename(commandFile)}`;
30868
+ const relativeSource = `commands/${path44.basename(commandFile)}`;
30864
30869
  const marker = formatProvenanceMarker(
30865
30870
  "markdown",
30866
30871
  relativeSource,
@@ -30869,16 +30874,16 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
30869
30874
  );
30870
30875
  const content = Object.keys(frontmatter).length > 0 ? `${marker}
30871
30876
  ---
30872
- ${(0, import_yaml11.stringify)(frontmatter).trim()}
30877
+ ${(0, import_yaml12.stringify)(frontmatter).trim()}
30873
30878
  ---
30874
30879
 
30875
30880
  ${body.trimEnd()}
30876
30881
  ` : `${marker}
30877
30882
  ${body.trimEnd()}
30878
30883
  `;
30879
- const destination = path43.join(
30884
+ const destination = path44.join(
30880
30885
  commandsRoot,
30881
- `${path43.basename(commandFile, ".md")}.md`
30886
+ `${path44.basename(commandFile, ".md")}.md`
30882
30887
  );
30883
30888
  if (options.dryRun) {
30884
30889
  logger.info(
@@ -30904,42 +30909,35 @@ ${body.trimEnd()}
30904
30909
  );
30905
30910
  });
30906
30911
  }
30907
- function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scopePath, component = "skills", destination = "") {
30908
- const source = path43.resolve(sourceRoot, config.source.skills);
30909
- if (!fs43.existsSync(source)) {
30910
- return skippedMissingSource6(component, source);
30911
- }
30912
- if (options.dryRun) {
30913
- logger.info(`[dry-run] ${component}: symlink ${source} -> ${destination}`);
30914
- return { component, status: "dry-run", path: destination };
30915
- }
30916
- const artifactClass = classifyArtifact(destination, config, sourceRoot);
30917
- if (artifactClass === "managed-symlink" && isSymlinkTo7(destination, source)) {
30918
- return { component, status: "skipped-current", path: destination };
30919
- }
30920
- if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
30921
- fs43.unlinkSync(destination);
30922
- } else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
30923
- return { component, status: "conflict", path: destination };
30924
- } else if (artifactClass === "managed-symlink") {
30925
- fs43.unlinkSync(destination);
30926
- }
30927
- ensureDir(path43.dirname(destination));
30928
- createRelativeSymlink(source, destination, "dir");
30929
- logger.verbose(`Skills: created skills path ${destination}`);
30930
- return { component, status: "success", path: destination };
30912
+ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scopePath, _component = "skills", destination = "") {
30913
+ return syncSkillsSlot({
30914
+ config,
30915
+ sourceRoot,
30916
+ source: path44.resolve(sourceRoot, config.source.skills),
30917
+ destination,
30918
+ dryRun: options.dryRun,
30919
+ logger,
30920
+ onUnmanagedConflict: (conflictPath) => handleConflict6(
30921
+ conflictPath,
30922
+ config,
30923
+ options,
30924
+ logger,
30925
+ manifest,
30926
+ scopePath
30927
+ )
30928
+ });
30931
30929
  }
30932
30930
  function syncMcp6(config, sourceRoot, paths, mappings, options, lossReport, logger) {
30933
30931
  const source = resolveMcpSourceFile(sourceRoot, config);
30934
30932
  const sourceLabel = mcpSourceLabel(config);
30935
30933
  const destination = resolveTargetPath(paths.config_doc);
30936
- if (!fs43.existsSync(source)) {
30934
+ if (!fs44.existsSync(source)) {
30937
30935
  if (!options.dryRun) {
30938
30936
  syncConfigDoc(paths, {}, lossReport, {}, mappings);
30939
30937
  }
30940
30938
  return skippedMissingSource6("mcp", source);
30941
30939
  }
30942
- const sourceMcpJson = JSON.parse(fs43.readFileSync(source, "utf8"));
30940
+ const sourceMcpJson = JSON.parse(fs44.readFileSync(source, "utf8"));
30943
30941
  const mcpJson = compileMcp(
30944
30942
  sourceMcpJson,
30945
30943
  "opencode",
@@ -31005,9 +31003,9 @@ function syncProviderBlock(mappings) {
31005
31003
  function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings) {
31006
31004
  const destination = resolveTargetPath(paths.config_doc);
31007
31005
  let existing = {};
31008
- if (fs43.existsSync(destination)) {
31006
+ if (fs44.existsSync(destination)) {
31009
31007
  try {
31010
- existing = JSON.parse(fs43.readFileSync(destination, "utf8"));
31008
+ existing = JSON.parse(fs44.readFileSync(destination, "utf8"));
31011
31009
  } catch {
31012
31010
  existing = {};
31013
31011
  }
@@ -31032,11 +31030,14 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
31032
31030
  };
31033
31031
  }
31034
31032
  }
31035
- ensureDir(path43.dirname(destination));
31036
- fs43.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
31033
+ ensureDir(path44.dirname(destination));
31034
+ fs44.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
31037
31035
  `);
31038
31036
  }
31039
31037
  function writeCompiledArtifact5(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
31038
+ if (!options.force && isCompiledCurrent5(destination, content, expectedHash)) {
31039
+ return { component, status: "skipped-current", path: destination };
31040
+ }
31040
31041
  const artifactClass = classifyArtifact(destination, config, sourceRoot);
31041
31042
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent5(destination, content, expectedHash)) {
31042
31043
  return { component, status: "skipped-current", path: destination };
@@ -31044,14 +31045,14 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
31044
31045
  if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
31045
31046
  return { component, status: "conflict", path: destination };
31046
31047
  }
31047
- ensureDir(path43.dirname(destination));
31048
+ ensureDir(path44.dirname(destination));
31048
31049
  const clearedLink = clearSymlinkAtDestination(destination);
31049
31050
  if (clearedLink !== null) {
31050
31051
  logger.verbose(
31051
31052
  ` ${destination}: replaced a symlink to ${clearedLink} with generated content`
31052
31053
  );
31053
31054
  }
31054
- fs43.writeFileSync(destination, content);
31055
+ fs44.writeFileSync(destination, content);
31055
31056
  return { component, status: "success", path: destination };
31056
31057
  }
31057
31058
  function handleConflict6(destination, config, options, logger, manifest, scopePath) {
@@ -31069,7 +31070,7 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
31069
31070
  if (manifest && scopePath) {
31070
31071
  backupFile(destination, manifest, scopePath);
31071
31072
  writeManifest(scopePath, manifest);
31072
- fs43.rmSync(destination, { recursive: true, force: true });
31073
+ fs44.rmSync(destination, { recursive: true, force: true });
31073
31074
  } else {
31074
31075
  const parked = parkConflictingPath(
31075
31076
  destination,
@@ -31084,14 +31085,12 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
31084
31085
  }
31085
31086
  return true;
31086
31087
  }
31087
- fs43.rmSync(destination, { recursive: true, force: true });
31088
+ fs44.rmSync(destination, { recursive: true, force: true });
31088
31089
  return true;
31089
31090
  }
31090
- function isCompiledCurrent5(destination, expectedContent, expectedHash) {
31091
+ function isCompiledCurrent5(destination, expectedContent, _expectedHash) {
31091
31092
  try {
31092
- const current = fs43.readFileSync(destination, "utf8");
31093
- const marker = extractProvenanceMarker(current);
31094
- return expectedHash ? marker?.hash === expectedHash && marker.target === "opencode" && current === expectedContent : current === expectedContent;
31093
+ return fs44.readFileSync(destination, "utf8") === expectedContent;
31095
31094
  } catch {
31096
31095
  return false;
31097
31096
  }
@@ -31106,18 +31105,11 @@ function skippedMissingSource6(component, source) {
31106
31105
  function shouldSkipComponent6(options, component) {
31107
31106
  return Boolean(options.component && options.component !== component);
31108
31107
  }
31109
- function isSymlinkTo7(linkPath, source) {
31110
- try {
31111
- return fs43.realpathSync(linkPath) === fs43.realpathSync(source);
31112
- } catch {
31113
- return false;
31114
- }
31115
- }
31116
31108
  function hashString5(value) {
31117
31109
  return `sha256:${crypto10.createHash("sha256").update(value).digest("hex")}`;
31118
31110
  }
31119
31111
  function parseCommandFile(commandFile) {
31120
- const content = fs43.readFileSync(commandFile, "utf8");
31112
+ const content = fs44.readFileSync(commandFile, "utf8");
31121
31113
  if (!content.startsWith("---\n")) {
31122
31114
  return { data: {}, body: content };
31123
31115
  }
@@ -31126,7 +31118,7 @@ function parseCommandFile(commandFile) {
31126
31118
  return { data: {}, body: content };
31127
31119
  }
31128
31120
  try {
31129
- const data = (0, import_yaml11.parse)(content.slice(4, endIndex)) ?? {};
31121
+ const data = (0, import_yaml12.parse)(content.slice(4, endIndex)) ?? {};
31130
31122
  const body = content.slice(endIndex + "\n---".length).replace(/^\n/u, "");
31131
31123
  return { data, body };
31132
31124
  } catch {
@@ -31137,7 +31129,7 @@ function parseCommandFile(commandFile) {
31137
31129
  // src/commands/install.ts
31138
31130
  function isBackupablePath(targetPath) {
31139
31131
  try {
31140
- const lstat = fs44.lstatSync(targetPath);
31132
+ const lstat = fs45.lstatSync(targetPath);
31141
31133
  return lstat.isSymbolicLink() || lstat.isFile() || lstat.isDirectory();
31142
31134
  } catch {
31143
31135
  return false;
@@ -31174,7 +31166,7 @@ async function runInstallCommand(options, logger) {
31174
31166
  );
31175
31167
  }
31176
31168
  const kitName = resolvedKitName ?? config.kit;
31177
- const kitPath = kitPathOverride ?? (options.kitPath ? path44.resolve(options.kitPath) : config.kitPath);
31169
+ const kitPath = kitPathOverride ?? (options.kitPath ? path45.resolve(options.kitPath) : config.kitPath);
31178
31170
  if (!kitName && !kitPath) {
31179
31171
  logger.error(
31180
31172
  "No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
@@ -31279,8 +31271,8 @@ async function runInstallCommand(options, logger) {
31279
31271
  config: options.config,
31280
31272
  scope
31281
31273
  });
31282
- const skillsSource = path44.resolve(kitInfo.path, config.source.skills);
31283
- const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") && path44.basename(f.path) === "skills";
31274
+ const skillsSource = path45.resolve(kitInfo.path, config.source.skills);
31275
+ const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") && path45.basename(f.path) === "skills";
31284
31276
  const foreignSkillsSlots = new Set(
31285
31277
  assessResult.findings.filter(
31286
31278
  (f) => isPerSkillSkillsSlot(f) && isForeignSkillsSlotSymlink(
@@ -31318,7 +31310,7 @@ async function runInstallCommand(options, logger) {
31318
31310
  let instructionsLabel;
31319
31311
  try {
31320
31312
  const resolved = resolveInstructionsSource(kitInfo.path, config);
31321
- instructionsLabel = resolved ? path44.relative(kitInfo.path, resolved.file) : "(none \u2014 no instructions file resolves in this kit)";
31313
+ instructionsLabel = resolved ? path45.relative(kitInfo.path, resolved.file) : "(none \u2014 no instructions file resolves in this kit)";
31322
31314
  } catch (err) {
31323
31315
  logger.error(
31324
31316
  `[dry-run] ${err instanceof Error ? err.message : String(err)}`
@@ -31346,7 +31338,7 @@ async function runInstallCommand(options, logger) {
31346
31338
  }
31347
31339
  }
31348
31340
  logger.info(
31349
- `[dry-run] Total: ${plannedTotal} destination(s); manifest at ${path44.join(scopePath, "manifest.json")}`
31341
+ `[dry-run] Total: ${plannedTotal} destination(s); manifest at ${path45.join(scopePath, "manifest.json")}`
31350
31342
  );
31351
31343
  return;
31352
31344
  }
@@ -31405,7 +31397,7 @@ ACCEPTED CONFLICTS (posture: ${posture}; ${replaceable.length} target(s)):`
31405
31397
  logger.info(` - ${finding.path}`);
31406
31398
  logger.info(` source: ${sources}`);
31407
31399
  logger.info(
31408
- ` action: backup-and-replace${fs44.lstatSync(finding.path).isDirectory() ? " (directory)" : ""}`
31400
+ ` action: backup-and-replace${fs45.lstatSync(finding.path).isDirectory() ? " (directory)" : ""}`
31409
31401
  );
31410
31402
  logger.info(` backup: ${backupLocation}`);
31411
31403
  continue;
@@ -31529,20 +31521,20 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
31529
31521
  writeManifest(scopePath, manifest);
31530
31522
  logger.info(`
31531
31523
  Installation complete: ${installedCount} files installed.`);
31532
- logger.info(`Manifest written to ${path44.join(scopePath, "manifest.json")}`);
31524
+ logger.info(`Manifest written to ${path45.join(scopePath, "manifest.json")}`);
31533
31525
  logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
31534
31526
  logger.info(`Scope: ${scope}`);
31535
31527
  logger.info(`Tools: ${tools.join(", ")}`);
31536
31528
  reportHookRejections(
31537
31529
  installLossReport,
31538
31530
  tools,
31539
- path44.resolve(kitInfo.path, "hooks"),
31531
+ path45.resolve(kitInfo.path, "hooks"),
31540
31532
  kitInfo.components.hooks.declared
31541
31533
  );
31542
31534
  const hooksConflict = reportHooksSourceConflict(
31543
31535
  installLossReport,
31544
31536
  tools,
31545
- path44.resolve(kitInfo.path, "hooks"),
31537
+ path45.resolve(kitInfo.path, "hooks"),
31546
31538
  kitInfo.components.hooks.declared
31547
31539
  );
31548
31540
  if (hooksConflict) {
@@ -31901,7 +31893,7 @@ function installClaudeCodeSkills(config, kitInfo, manifest, options, logger, sco
31901
31893
  return 0;
31902
31894
  }
31903
31895
  try {
31904
- const stat = fs44.lstatSync(destination);
31896
+ const stat = fs45.lstatSync(destination);
31905
31897
  if (stat.isFile() && !stat.isSymbolicLink()) {
31906
31898
  logger.warn(
31907
31899
  `${destination}: a regular file occupies the skills slot \u2014 skipping skills. Move or remove it, then re-run install.`
@@ -31929,17 +31921,17 @@ function installClaudeCodeSkills(config, kitInfo, manifest, options, logger, sco
31929
31921
  manifest,
31930
31922
  scopePath
31931
31923
  );
31932
- const skillsSource = path44.resolve(kitInfo.path, config.source.skills);
31924
+ const skillsSource = path45.resolve(kitInfo.path, config.source.skills);
31933
31925
  let count = 0;
31934
31926
  for (const outcome of outcomes) {
31935
31927
  if (outcome.status !== "success" && outcome.status !== "skipped-current") {
31936
31928
  continue;
31937
31929
  }
31938
- const skillName = path44.basename(outcome.path);
31930
+ const skillName = path45.basename(outcome.path);
31939
31931
  addArtifactToManifest(manifest, {
31940
31932
  relativePath: `claude-code/skills/${skillName}`,
31941
31933
  path: outcome.path,
31942
- hash: describeArtifactState(outcome.path) ?? `dir:${path44.join(skillsSource, skillName)}`,
31934
+ hash: describeArtifactState(outcome.path) ?? `dir:${path45.join(skillsSource, skillName)}`,
31943
31935
  origin: "tangyr-managed"
31944
31936
  });
31945
31937
  count++;
@@ -31953,10 +31945,10 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
31953
31945
  logger.verbose(` skipped (operator choice): ${placement.destination}`);
31954
31946
  continue;
31955
31947
  }
31956
- const destDir = path44.dirname(placement.destination);
31957
- fs44.mkdirSync(destDir, { recursive: true });
31948
+ const destDir = path45.dirname(placement.destination);
31949
+ fs45.mkdirSync(destDir, { recursive: true });
31958
31950
  if (placement.type === "symlink") {
31959
- if (fs44.existsSync(placement.destination) || isSymlink2(placement.destination)) {
31951
+ if (fs45.existsSync(placement.destination) || isSymlink2(placement.destination)) {
31960
31952
  removeManagedPath(placement.destination);
31961
31953
  }
31962
31954
  createRelativeSymlink(
@@ -31973,7 +31965,7 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
31973
31965
  ` symlink: ${placement.source} \u2192 ${placement.destination}`
31974
31966
  );
31975
31967
  } else {
31976
- fs44.copyFileSync(placement.source, placement.destination);
31968
+ fs45.copyFileSync(placement.source, placement.destination);
31977
31969
  logger.verbose(` copy: ${placement.source} \u2192 ${placement.destination}`);
31978
31970
  }
31979
31971
  addArtifactToManifest(manifest, {
@@ -32235,6 +32227,16 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32235
32227
  }
32236
32228
  throwUnrecognizedTarget(tool);
32237
32229
  }
32230
+ const skillsSlotKey = skillsSubPathKey(
32231
+ tool,
32232
+ outcome.path,
32233
+ mappings,
32234
+ scope,
32235
+ projectRoot
32236
+ );
32237
+ if (skillsSlotKey) {
32238
+ return skillsSlotKey;
32239
+ }
32238
32240
  if (tool === "cline") {
32239
32241
  const profile2 = resolveTargetPaths({
32240
32242
  scope,
@@ -32255,11 +32257,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32255
32257
  if (outcome.path === mcpFile2) {
32256
32258
  return "cline/mcp.json";
32257
32259
  }
32258
- if (outcome.path.startsWith(`${workflowsRoot}${path44.sep}`)) {
32259
- return `cline/workflows/${path44.basename(outcome.path)}`;
32260
+ if (outcome.path.startsWith(`${workflowsRoot}${path45.sep}`)) {
32261
+ return `cline/workflows/${path45.basename(outcome.path)}`;
32260
32262
  }
32261
- if (outcome.path.startsWith(`${rulesRoot2}${path44.sep}`)) {
32262
- return `cline/rules/${path44.basename(outcome.path)}`;
32263
+ if (outcome.path.startsWith(`${rulesRoot2}${path45.sep}`)) {
32264
+ return `cline/rules/${path45.basename(outcome.path)}`;
32263
32265
  }
32264
32266
  return null;
32265
32267
  }
@@ -32295,14 +32297,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32295
32297
  if (outcome.path === permissionsFile) {
32296
32298
  return "cursor/permissions.json";
32297
32299
  }
32298
- if (outcome.path.startsWith(`${agentsRoot2}${path44.sep}`)) {
32299
- return `cursor/agents/${path44.basename(outcome.path)}`;
32300
+ if (outcome.path.startsWith(`${agentsRoot2}${path45.sep}`)) {
32301
+ return `cursor/agents/${path45.basename(outcome.path)}`;
32300
32302
  }
32301
- if (outcome.path.startsWith(`${rulesRoot2}${path44.sep}`)) {
32302
- return `cursor/rules/${path44.basename(outcome.path)}`;
32303
+ if (outcome.path.startsWith(`${rulesRoot2}${path45.sep}`)) {
32304
+ return `cursor/rules/${path45.basename(outcome.path)}`;
32303
32305
  }
32304
- if (outcome.path.startsWith(`${skillsRoot2}${path44.sep}`)) {
32305
- const rel = path44.relative(skillsRoot2, outcome.path);
32306
+ if (outcome.path.startsWith(`${skillsRoot2}${path45.sep}`)) {
32307
+ const rel = path45.relative(skillsRoot2, outcome.path);
32306
32308
  return `cursor/skills/${rel}`;
32307
32309
  }
32308
32310
  return null;
@@ -32328,14 +32330,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32328
32330
  if (outcome.path === skillsSharedRoot) {
32329
32331
  return "opencode/skills_shared";
32330
32332
  }
32331
- if (outcome.path.startsWith(`${agentsRoot2}${path44.sep}`)) {
32332
- return `opencode/agents/${path44.basename(outcome.path)}`;
32333
+ if (outcome.path.startsWith(`${agentsRoot2}${path45.sep}`)) {
32334
+ return `opencode/agents/${path45.basename(outcome.path)}`;
32333
32335
  }
32334
- if (outcome.path.startsWith(`${commandsRoot}${path44.sep}`)) {
32335
- return `opencode/commands/${path44.basename(outcome.path)}`;
32336
+ if (outcome.path.startsWith(`${commandsRoot}${path45.sep}`)) {
32337
+ return `opencode/commands/${path45.basename(outcome.path)}`;
32336
32338
  }
32337
32339
  if (outcome.path === configDocFile) {
32338
- return `opencode/${path44.basename(outcome.path)}`;
32340
+ return `opencode/${path45.basename(outcome.path)}`;
32339
32341
  }
32340
32342
  return null;
32341
32343
  }
@@ -32352,26 +32354,26 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32352
32354
  const hooksRoot = resolveTargetPath(copilot.hooks);
32353
32355
  const mcpFile2 = resolveTargetPath(copilot.mcp_shared_file);
32354
32356
  const instructionsMirror = copilot.instructions !== null ? resolveTargetPath(copilot.instructions) : null;
32355
- if (outcome.path.startsWith(`${skillsRoot2}${path44.sep}`)) {
32356
- return `copilot/skills/${path44.relative(skillsRoot2, outcome.path)}`;
32357
+ if (outcome.path.startsWith(`${skillsRoot2}${path45.sep}`)) {
32358
+ return `copilot/skills/${path45.relative(skillsRoot2, outcome.path)}`;
32357
32359
  }
32358
32360
  if (outcome.path === skillsRoot2) {
32359
32361
  return "copilot/skills";
32360
32362
  }
32361
32363
  if (instructionsMirror !== null && outcome.path === instructionsMirror) {
32362
- return `copilot/${path44.basename(outcome.path)}`;
32364
+ return `copilot/${path45.basename(outcome.path)}`;
32363
32365
  }
32364
- if (outcome.path.startsWith(`${agentsRoot2}${path44.sep}`)) {
32365
- return `copilot/agents/${path44.basename(outcome.path)}`;
32366
+ if (outcome.path.startsWith(`${agentsRoot2}${path45.sep}`)) {
32367
+ return `copilot/agents/${path45.basename(outcome.path)}`;
32366
32368
  }
32367
- if (outcome.path.startsWith(`${promptsRoot}${path44.sep}`)) {
32368
- return `copilot/prompts/${path44.basename(outcome.path)}`;
32369
+ if (outcome.path.startsWith(`${promptsRoot}${path45.sep}`)) {
32370
+ return `copilot/prompts/${path45.basename(outcome.path)}`;
32369
32371
  }
32370
- if (outcome.path.startsWith(`${hooksRoot}${path44.sep}`)) {
32371
- return `copilot/hooks/${path44.basename(outcome.path)}`;
32372
+ if (outcome.path.startsWith(`${hooksRoot}${path45.sep}`)) {
32373
+ return `copilot/hooks/${path45.basename(outcome.path)}`;
32372
32374
  }
32373
32375
  if (outcome.path === mcpFile2) {
32374
- return `copilot/${path44.basename(outcome.path)}`;
32376
+ return `copilot/${path45.basename(outcome.path)}`;
32375
32377
  }
32376
32378
  return null;
32377
32379
  }
@@ -32388,17 +32390,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
32388
32390
  if (outcome.path === skillsRoot) {
32389
32391
  return "codex/skills";
32390
32392
  }
32391
- if (outcome.path.startsWith(`${agentsRoot}${path44.sep}`)) {
32392
- return `codex/agents/${path44.basename(outcome.path)}`;
32393
+ if (outcome.path.startsWith(`${agentsRoot}${path45.sep}`)) {
32394
+ return `codex/agents/${path45.basename(outcome.path)}`;
32393
32395
  }
32394
- if (outcome.path.startsWith(`${rulesRoot}${path44.sep}`)) {
32395
- return `codex/rules/${path44.basename(outcome.path)}`;
32396
+ if (outcome.path.startsWith(`${rulesRoot}${path45.sep}`)) {
32397
+ return `codex/rules/${path45.basename(outcome.path)}`;
32396
32398
  }
32397
32399
  if (outcome.path === hooksFile) {
32398
- return `codex/${path44.basename(outcome.path)}`;
32400
+ return `codex/${path45.basename(outcome.path)}`;
32399
32401
  }
32400
32402
  if (outcome.path === mcpFile) {
32401
- return `codex/${path44.basename(outcome.path)}`;
32403
+ return `codex/${path45.basename(outcome.path)}`;
32402
32404
  }
32403
32405
  return null;
32404
32406
  }
@@ -32467,8 +32469,8 @@ function getClaudeCodePlacements(kitInfo, config, scope = "global", projectRoot,
32467
32469
  rules: resolvedPaths.rules
32468
32470
  };
32469
32471
  for (const [component, targetPath] of Object.entries(componentDirMap)) {
32470
- const componentDir = path44.join(kitInfo.path, component);
32471
- if (fs44.existsSync(componentDir) && fs44.statSync(componentDir).isDirectory()) {
32472
+ const componentDir = path45.join(kitInfo.path, component);
32473
+ if (fs45.existsSync(componentDir) && fs45.statSync(componentDir).isDirectory()) {
32472
32474
  placements.push({
32473
32475
  source: componentDir,
32474
32476
  destination: targetPath,
@@ -32498,8 +32500,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile, config) {
32498
32500
  rules: profile.rules
32499
32501
  };
32500
32502
  for (const [component, targetPath] of Object.entries(componentDirMap)) {
32501
- const componentDir = path44.join(kitInfo.path, component);
32502
- if (fs44.existsSync(componentDir) && fs44.statSync(componentDir).isDirectory()) {
32503
+ const componentDir = path45.join(kitInfo.path, component);
32504
+ if (fs45.existsSync(componentDir) && fs45.statSync(componentDir).isDirectory()) {
32503
32505
  placements.push({
32504
32506
  source: componentDir,
32505
32507
  destination: targetPath,
@@ -32515,7 +32517,7 @@ function collectAllFiles(kitInfo, config) {
32515
32517
  const files = /* @__PURE__ */ new Map();
32516
32518
  const entrypoint = resolveInstructionsSource(kitInfo.path, config);
32517
32519
  if (entrypoint) {
32518
- files.set(path44.basename(entrypoint.file), entrypoint.file);
32520
+ files.set(path45.basename(entrypoint.file), entrypoint.file);
32519
32521
  }
32520
32522
  for (const [component, reconciliation] of Object.entries(
32521
32523
  kitInfo.components
@@ -32524,26 +32526,48 @@ function collectAllFiles(kitInfo, config) {
32524
32526
  const missingSet = new Set(reconciliation.missing);
32525
32527
  for (const entry of reconciliation.declared) {
32526
32528
  if (missingSet.has(entry)) continue;
32527
- const relPath = isSkills ? path44.join(component, entry) : path44.join(component, `${entry}.md`);
32528
- files.set(relPath, path44.join(kitInfo.path, relPath));
32529
+ const relPath = isSkills ? path45.join(component, entry) : path45.join(component, `${entry}.md`);
32530
+ files.set(relPath, path45.join(kitInfo.path, relPath));
32529
32531
  }
32530
32532
  }
32531
32533
  return files;
32532
32534
  }
32533
32535
  function readLinkTarget(p) {
32534
32536
  try {
32535
- return fs44.readlinkSync(p);
32537
+ return fs45.readlinkSync(p);
32536
32538
  } catch {
32537
32539
  return null;
32538
32540
  }
32539
32541
  }
32540
32542
  function isSymlink2(p) {
32541
32543
  try {
32542
- return fs44.lstatSync(p).isSymbolicLink();
32544
+ return fs45.lstatSync(p).isSymbolicLink();
32543
32545
  } catch {
32544
32546
  return false;
32545
32547
  }
32546
32548
  }
32549
+ function skillsSubPathKey(tool, outcomePath, mappings, scope, projectRoot) {
32550
+ const profile = resolveTargetPaths({
32551
+ scope,
32552
+ projectRoot,
32553
+ mappings: mappings.platformPaths
32554
+ })[tool];
32555
+ if (!profile) {
32556
+ return null;
32557
+ }
32558
+ for (const slot of [profile.skills, profile.skills_shared]) {
32559
+ if (typeof slot !== "string" || slot.length === 0) {
32560
+ continue;
32561
+ }
32562
+ const root = resolveTargetPath(slot);
32563
+ if (!outcomePath.startsWith(`${root}${path45.sep}`)) {
32564
+ continue;
32565
+ }
32566
+ const inside = path45.relative(root, outcomePath).split(path45.sep).join("/");
32567
+ return `${tool}/skills/${inside}`;
32568
+ }
32569
+ return null;
32570
+ }
32547
32571
 
32548
32572
  // src/commands/kit.ts
32549
32573
  async function runKitUpdateCommand(options, logger) {
@@ -32584,14 +32608,14 @@ async function runKitUpdateCommand(options, logger) {
32584
32608
  }
32585
32609
 
32586
32610
  // src/commands/list.ts
32587
- import path45 from "path";
32611
+ import path46 from "path";
32588
32612
  function runListCommand(options, logger) {
32589
32613
  let searchPaths = [];
32590
- let directKitPath = options.kitPath ? path45.resolve(options.kitPath) : void 0;
32614
+ let directKitPath = options.kitPath ? path46.resolve(options.kitPath) : void 0;
32591
32615
  try {
32592
32616
  const { config, configDir } = resolveConfig(options.config);
32593
32617
  searchPaths = config.kitSearchPaths ?? [
32594
- path45.join(configDir, "operating-kits")
32618
+ path46.join(configDir, "operating-kits")
32595
32619
  ];
32596
32620
  directKitPath = directKitPath ?? config.kitPath;
32597
32621
  } catch (err) {
@@ -32666,7 +32690,7 @@ function withDirectKit(kits, directKitPath) {
32666
32690
  return kits;
32667
32691
  }
32668
32692
  const directKit = loadKit(directKitPath);
32669
- if (kits.some((kit) => path45.resolve(kit.path) === directKit.path)) {
32693
+ if (kits.some((kit) => path46.resolve(kit.path) === directKit.path)) {
32670
32694
  return kits;
32671
32695
  }
32672
32696
  return [...kits, directKit];
@@ -32674,8 +32698,8 @@ function withDirectKit(kits, directKitPath) {
32674
32698
 
32675
32699
  // src/commands/probe.ts
32676
32700
  import { spawnSync as spawnSync2 } from "child_process";
32677
- import fs45 from "fs";
32678
- import path46 from "path";
32701
+ import fs46 from "fs";
32702
+ import path47 from "path";
32679
32703
  function runProbeCommand(options, logger) {
32680
32704
  const { config, configDir, configSource, sourceRoot } = resolveRuntime(
32681
32705
  options,
@@ -32703,7 +32727,7 @@ function runProbeCommand(options, logger) {
32703
32727
  toProbeRow(
32704
32728
  target,
32705
32729
  key,
32706
- scope === "project" ? path46.resolve(projectRoot ?? process.cwd(), rawPath) : rawPath
32730
+ scope === "project" ? path47.resolve(projectRoot ?? process.cwd(), rawPath) : rawPath
32707
32731
  )
32708
32732
  );
32709
32733
  }
@@ -32725,7 +32749,7 @@ function toProbeRow(target, key, rawPath) {
32725
32749
  const resolved = resolveTargetPath(rawPath);
32726
32750
  let accessible = false;
32727
32751
  try {
32728
- fs45.accessSync(resolved);
32752
+ fs46.accessSync(resolved);
32729
32753
  accessible = true;
32730
32754
  } catch {
32731
32755
  accessible = false;
@@ -32734,7 +32758,7 @@ function toProbeRow(target, key, rawPath) {
32734
32758
  target,
32735
32759
  key,
32736
32760
  path: resolved,
32737
- exists: fs45.existsSync(resolved),
32761
+ exists: fs46.existsSync(resolved),
32738
32762
  accessible
32739
32763
  };
32740
32764
  }
@@ -32752,7 +32776,7 @@ function codexRuntimeProbeRows() {
32752
32776
  ["binary_snap", "/snap/bin/codex"],
32753
32777
  ["binary_flatpak", "/var/lib/flatpak/exports/bin/codex"]
32754
32778
  ]) {
32755
- if (fs45.existsSync(candidatePath)) {
32779
+ if (fs46.existsSync(candidatePath)) {
32756
32780
  rows.push(toProbeRow("codex", key, candidatePath));
32757
32781
  }
32758
32782
  }
@@ -32768,8 +32792,8 @@ function commandProbeRows(target, key, command, args) {
32768
32792
 
32769
32793
  // src/commands/status.ts
32770
32794
  import crypto11 from "crypto";
32771
- import fs46 from "fs";
32772
- import path47 from "path";
32795
+ import fs47 from "fs";
32796
+ import path48 from "path";
32773
32797
  function runStatusCommand(options, logger) {
32774
32798
  const { config, configDir, configSource, sourceRoot } = resolveRuntime(
32775
32799
  options,
@@ -32875,11 +32899,11 @@ function classifyTargetRows(target, config, sourceRoot, configDir, scope, projec
32875
32899
  }
32876
32900
  }
32877
32901
  function sourceMarkdownFiles(sourceRoot, componentPath) {
32878
- const root = path47.join(sourceRoot, componentPath);
32879
- if (!fs46.existsSync(root)) {
32902
+ const root = path48.join(sourceRoot, componentPath);
32903
+ if (!fs47.existsSync(root)) {
32880
32904
  return [];
32881
32905
  }
32882
- return ts(path47.join(root, "*.md")).sort();
32906
+ return ts(path48.join(root, "*.md")).sort();
32883
32907
  }
32884
32908
  function notRepresentableRow(component, detail) {
32885
32909
  return {
@@ -32890,11 +32914,11 @@ function notRepresentableRow(component, detail) {
32890
32914
  };
32891
32915
  }
32892
32916
  function readTargetJson(filePath) {
32893
- if (!fs46.existsSync(filePath)) {
32917
+ if (!fs47.existsSync(filePath)) {
32894
32918
  return { kind: "missing" };
32895
32919
  }
32896
32920
  try {
32897
- const parsed = JSON.parse(fs46.readFileSync(filePath, "utf8"));
32921
+ const parsed = JSON.parse(fs47.readFileSync(filePath, "utf8"));
32898
32922
  return { kind: "object", value: isRecord(parsed) ? parsed : {} };
32899
32923
  } catch (err) {
32900
32924
  return {
@@ -32983,7 +33007,7 @@ function classifyInstructions(filePath, target, expectedHash, config, sourceRoot
32983
33007
  }
32984
33008
  function compiledMcpDocument(config, sourceRoot, target) {
32985
33009
  const source = resolveMcpSourceFile(sourceRoot, config);
32986
- if (!fs46.existsSync(source)) {
33010
+ if (!fs47.existsSync(source)) {
32987
33011
  return {};
32988
33012
  }
32989
33013
  const compiled = compileMcp(
@@ -32996,7 +33020,7 @@ function compiledMcpDocument(config, sourceRoot, target) {
32996
33020
  return isRecord(parsed) ? parsed : {};
32997
33021
  }
32998
33022
  function classifyMcpDocument(config, sourceRoot, target, filePath) {
32999
- if (!fs46.existsSync(resolveMcpSourceFile(sourceRoot, config))) {
33023
+ if (!fs47.existsSync(resolveMcpSourceFile(sourceRoot, config))) {
33000
33024
  return notConfiguredRow("mcp", filePath);
33001
33025
  }
33002
33026
  return classifyJsonDocument(
@@ -33026,12 +33050,12 @@ function classifyOpenCodeFiles(config, sourceRoot, configDir, scope, projectRoot
33026
33050
  const rows = [];
33027
33051
  const instructionsSource = instructionsSourcePath(sourceRoot, config);
33028
33052
  const rules = compileRules(
33029
- path47.join(sourceRoot, config.source.rules),
33053
+ path48.join(sourceRoot, config.source.rules),
33030
33054
  "opencode",
33031
33055
  mappings,
33032
33056
  createLossReport()
33033
33057
  );
33034
- const baseInstructions = fs46.existsSync(instructionsSource) ? fs46.readFileSync(instructionsSource, "utf8").trim() : "";
33058
+ const baseInstructions = fs47.existsSync(instructionsSource) ? fs47.readFileSync(instructionsSource, "utf8").trim() : "";
33035
33059
  const composedInstructions = rules.agentsAppendix ? `${baseInstructions}
33036
33060
 
33037
33061
  --- tangyr managed rules ---
@@ -33053,10 +33077,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
33053
33077
  )) {
33054
33078
  rows.push(
33055
33079
  classifyCompiledFile(
33056
- `agents/${path47.basename(agentFile, ".md")}`,
33057
- path47.join(
33080
+ `agents/${path48.basename(agentFile, ".md")}`,
33081
+ path48.join(
33058
33082
  resolveTargetPath(paths.agents),
33059
- `${path47.basename(agentFile, ".md")}.md`
33083
+ `${path48.basename(agentFile, ".md")}.md`
33060
33084
  ),
33061
33085
  "opencode",
33062
33086
  computeSourceHash(agentFile),
@@ -33071,10 +33095,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
33071
33095
  )) {
33072
33096
  rows.push(
33073
33097
  classifyCompiledFile(
33074
- `commands/${path47.basename(commandFile, ".md")}`,
33075
- path47.join(
33098
+ `commands/${path48.basename(commandFile, ".md")}`,
33099
+ path48.join(
33076
33100
  resolveTargetPath(paths.commands),
33077
- `${path47.basename(commandFile, ".md")}.md`
33101
+ `${path48.basename(commandFile, ".md")}.md`
33078
33102
  ),
33079
33103
  "opencode",
33080
33104
  computeSourceHash(commandFile),
@@ -33156,10 +33180,10 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
33156
33180
  )) {
33157
33181
  rows.push(
33158
33182
  classifyCompiledFile(
33159
- `agents/${path47.basename(agentFile, ".md")}`,
33160
- path47.join(
33183
+ `agents/${path48.basename(agentFile, ".md")}`,
33184
+ path48.join(
33161
33185
  resolveTargetPath(paths.agents),
33162
- `${path47.basename(agentFile, ".md")}.md`
33186
+ `${path48.basename(agentFile, ".md")}.md`
33163
33187
  ),
33164
33188
  "cursor",
33165
33189
  computeSourceHash(agentFile),
@@ -33176,7 +33200,7 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
33176
33200
  rows.push(
33177
33201
  classifyCompiledFile(
33178
33202
  `rules/${ruleFile.name}`,
33179
- path47.join(resolveTargetPath(paths.rules), ruleFile.name),
33203
+ path48.join(resolveTargetPath(paths.rules), ruleFile.name),
33180
33204
  "cursor",
33181
33205
  void 0,
33182
33206
  config,
@@ -33190,11 +33214,11 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
33190
33214
  sourceRoot,
33191
33215
  config.source.commands
33192
33216
  )) {
33193
- const baseName = path47.basename(commandFile, ".md");
33217
+ const baseName = path48.basename(commandFile, ".md");
33194
33218
  rows.push(
33195
33219
  classifyCompiledFile(
33196
33220
  `commands/${baseName}`,
33197
- path47.join(resolveTargetPath(paths.skills), baseName, "SKILL.md"),
33221
+ path48.join(resolveTargetPath(paths.skills), baseName, "SKILL.md"),
33198
33222
  "cursor",
33199
33223
  computeSourceHash(commandFile),
33200
33224
  config,
@@ -33277,7 +33301,7 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
33277
33301
  rows.push(
33278
33302
  classifyCompiledFile(
33279
33303
  `rules/${ruleFile.name}`,
33280
- path47.join(resolveTargetPath(paths.rules), ruleFile.name),
33304
+ path48.join(resolveTargetPath(paths.rules), ruleFile.name),
33281
33305
  "cline",
33282
33306
  void 0,
33283
33307
  config,
@@ -33293,10 +33317,10 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
33293
33317
  )) {
33294
33318
  rows.push(
33295
33319
  classifyCompiledFile(
33296
- `commands/${path47.basename(commandFile, ".md")}`,
33297
- path47.join(
33320
+ `commands/${path48.basename(commandFile, ".md")}`,
33321
+ path48.join(
33298
33322
  resolveTargetPath(paths.workflows),
33299
- path47.basename(commandFile)
33323
+ path48.basename(commandFile)
33300
33324
  ),
33301
33325
  "cline",
33302
33326
  computeSourceHash(commandFile),
@@ -33337,14 +33361,14 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
33337
33361
  return rows;
33338
33362
  }
33339
33363
  function compileRulesFiles(config, sourceRoot, target, mappings) {
33340
- const rulesSource = path47.join(sourceRoot, config.source.rules);
33341
- if (!fs46.existsSync(rulesSource)) {
33364
+ const rulesSource = path48.join(sourceRoot, config.source.rules);
33365
+ if (!fs47.existsSync(rulesSource)) {
33342
33366
  return [];
33343
33367
  }
33344
33368
  return compileRules(rulesSource, target, mappings, createLossReport()).dotRulesFiles;
33345
33369
  }
33346
33370
  function classifyDirectoryPresence(component, dirPath) {
33347
- const present = fs46.existsSync(dirPath) && fs46.statSync(dirPath).isDirectory();
33371
+ const present = fs47.existsSync(dirPath) && fs47.statSync(dirPath).isDirectory();
33348
33372
  return {
33349
33373
  component,
33350
33374
  className: present ? "current" : "missing",
@@ -33363,7 +33387,7 @@ function slotsForScope2(scopeMap, scope, projectRoot) {
33363
33387
  const root = projectRoot ?? process.cwd();
33364
33388
  const resolved = {};
33365
33389
  for (const [slot, value] of Object.entries(projectSlots)) {
33366
- resolved[slot] = typeof value === "string" ? path47.resolve(root, value) : value;
33390
+ resolved[slot] = typeof value === "string" ? path48.resolve(root, value) : value;
33367
33391
  }
33368
33392
  return resolved;
33369
33393
  }
@@ -33383,21 +33407,21 @@ function classifyCodexFiles(config, sourceRoot, configDir, scope, projectRoot) {
33383
33407
  rules: paths.rules
33384
33408
  };
33385
33409
  const rules = compileRules(
33386
- path47.join(sourceRoot, config.source.rules),
33410
+ path48.join(sourceRoot, config.source.rules),
33387
33411
  "codex",
33388
33412
  mappings,
33389
33413
  createLossReport()
33390
33414
  );
33391
- const instructionsSource = fs46.readFileSync(instructionsSourcePath(sourceRoot, config), "utf8").trim();
33415
+ const instructionsSource = fs47.readFileSync(instructionsSourcePath(sourceRoot, config), "utf8").trim();
33392
33416
  const composedInstructions = `${instructionsSource}
33393
33417
 
33394
33418
  --- tangyr managed rules ---
33395
33419
  ${rules.agentsAppendix}`.trim();
33396
33420
  const agentFiles = ts(
33397
- path47.join(sourceRoot, config.source.agents, "*.md")
33421
+ path48.join(sourceRoot, config.source.agents, "*.md")
33398
33422
  ).sort();
33399
33423
  const hooksPresent = hooksSourceExists(sourceRoot, config);
33400
- const mcpSource = path47.join(sourceRoot, config.source.mcp);
33424
+ const mcpSource = path48.join(sourceRoot, config.source.mcp);
33401
33425
  const ruleRows = rules.dotRulesFiles.length === 0 ? [
33402
33426
  {
33403
33427
  component: "rules",
@@ -33408,7 +33432,7 @@ ${rules.agentsAppendix}`.trim();
33408
33432
  ] : rules.dotRulesFiles.map(
33409
33433
  (ruleFile) => classifyCompiledFile(
33410
33434
  `rules/${ruleFile.name}`,
33411
- path47.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
33435
+ path48.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
33412
33436
  "codex",
33413
33437
  void 0,
33414
33438
  config,
@@ -33426,10 +33450,10 @@ ${rules.agentsAppendix}`.trim();
33426
33450
  ),
33427
33451
  ...agentFiles.map(
33428
33452
  (agentFile) => classifyCompiledFile(
33429
- `agents/${path47.basename(agentFile, ".md")}`,
33430
- path47.join(
33453
+ `agents/${path48.basename(agentFile, ".md")}`,
33454
+ path48.join(
33431
33455
  resolveTargetPath(codexPaths.agents),
33432
- `${path47.basename(agentFile, ".md")}.toml`
33456
+ `${path48.basename(agentFile, ".md")}.toml`
33433
33457
  ),
33434
33458
  "codex",
33435
33459
  computeSourceHash(agentFile),
@@ -33457,7 +33481,7 @@ ${rules.agentsAppendix}`.trim();
33457
33481
  "hooks",
33458
33482
  resolveTargetPath(codexPaths.hooksSharedFile)
33459
33483
  ),
33460
- fs46.existsSync(mcpSource) ? classifyCompiledFile(
33484
+ fs47.existsSync(mcpSource) ? classifyCompiledFile(
33461
33485
  "mcp",
33462
33486
  resolveTargetPath(codexPaths.mcpSharedFile),
33463
33487
  "codex",
@@ -33523,20 +33547,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
33523
33547
  mcpSharedFile: paths.mcp_shared_file
33524
33548
  };
33525
33549
  const agentFiles = ts(
33526
- path47.join(sourceRoot, config.source.agents, "*.md")
33550
+ path48.join(sourceRoot, config.source.agents, "*.md")
33527
33551
  ).sort();
33528
33552
  const commandFiles = ts(
33529
- path47.join(sourceRoot, config.source.commands, "*.md")
33553
+ path48.join(sourceRoot, config.source.commands, "*.md")
33530
33554
  ).sort();
33531
33555
  const hooksPresent = hooksSourceExists(sourceRoot, config);
33532
- const mcpSource = path47.join(sourceRoot, config.source.mcp);
33556
+ const mcpSource = path48.join(sourceRoot, config.source.mcp);
33533
33557
  return [
33534
33558
  ...agentFiles.map(
33535
33559
  (agentFile) => classifyCompiledFile(
33536
- `agents/${path47.basename(agentFile, ".md")}`,
33537
- path47.join(
33560
+ `agents/${path48.basename(agentFile, ".md")}`,
33561
+ path48.join(
33538
33562
  resolveTargetPath(copilotPaths.agents),
33539
- `${path47.basename(agentFile, ".md")}.agent.md`
33563
+ `${path48.basename(agentFile, ".md")}.agent.md`
33540
33564
  ),
33541
33565
  "copilot",
33542
33566
  computeSourceHash(agentFile),
@@ -33553,10 +33577,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
33553
33577
  ),
33554
33578
  ...commandFiles.map(
33555
33579
  (commandFile) => classifyCompiledFile(
33556
- `commands/${path47.basename(commandFile, ".md")}`,
33557
- path47.join(
33580
+ `commands/${path48.basename(commandFile, ".md")}`,
33581
+ path48.join(
33558
33582
  resolveTargetPath(copilotPaths.prompts),
33559
- `${path47.basename(commandFile, ".md")}.prompt.md`
33583
+ `${path48.basename(commandFile, ".md")}.prompt.md`
33560
33584
  ),
33561
33585
  "copilot",
33562
33586
  computeSourceHash(commandFile),
@@ -33575,19 +33599,19 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
33575
33599
  sourceRoot
33576
33600
  ),
33577
33601
  hooksPresent ? classifyCompiledHooksByProvenance(
33578
- path47.join(
33602
+ path48.join(
33579
33603
  resolveTargetPath(copilotPaths.hooks),
33580
33604
  "tangyr-managed.json"
33581
33605
  ),
33582
33606
  "copilot"
33583
33607
  ) : notConfiguredRow(
33584
33608
  "hooks",
33585
- path47.join(
33609
+ path48.join(
33586
33610
  resolveTargetPath(copilotPaths.hooks),
33587
33611
  "tangyr-managed.json"
33588
33612
  )
33589
33613
  ),
33590
- fs46.existsSync(mcpSource) ? classifyCompiledFile(
33614
+ fs47.existsSync(mcpSource) ? classifyCompiledFile(
33591
33615
  "mcp",
33592
33616
  resolveTargetPath(copilotPaths.mcpSharedFile),
33593
33617
  "copilot",
@@ -33607,7 +33631,7 @@ function notConfiguredRow(component, filePath) {
33607
33631
  }
33608
33632
  function classifyDirectArtifact(artifact, config, sourceRoot) {
33609
33633
  const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
33610
- const sourcePath = artifact.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : artifact.sourceKey ? path47.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
33634
+ const sourcePath = artifact.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : artifact.sourceKey ? path48.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
33611
33635
  if (artifact.sourceKey === "skills" && artifactClass === "unmanaged-conflict") {
33612
33636
  const perSkill = classifyPerSkillSlot(artifact.path, sourceRoot);
33613
33637
  if (perSkill) {
@@ -33703,20 +33727,23 @@ function classifyClaudeCodeRows(sourceRoot, config, configDir, scope, projectRoo
33703
33727
  function classifyPerSkillSlot(slotPath, sourceRoot) {
33704
33728
  let entries;
33705
33729
  try {
33706
- const stat = fs46.lstatSync(slotPath);
33730
+ const stat = fs47.lstatSync(slotPath);
33707
33731
  if (!stat.isDirectory() || stat.isSymbolicLink()) {
33708
33732
  return null;
33709
33733
  }
33710
- entries = fs46.readdirSync(slotPath, { withFileTypes: true });
33734
+ entries = fs47.readdirSync(slotPath, { withFileTypes: true });
33711
33735
  } catch {
33712
33736
  return null;
33713
33737
  }
33738
+ if (entries.length === 0) {
33739
+ return "managed-symlink";
33740
+ }
33714
33741
  const links = entries.filter((entry) => entry.isSymbolicLink());
33715
33742
  if (links.length === 0) {
33716
33743
  return null;
33717
33744
  }
33718
33745
  const ours = links.filter(
33719
- (entry) => isOurSymlink(path47.join(slotPath, entry.name), sourceRoot)
33746
+ (entry) => isOurSymlink(path48.join(slotPath, entry.name), sourceRoot)
33720
33747
  );
33721
33748
  if (ours.length === 0) {
33722
33749
  return null;
@@ -33728,9 +33755,9 @@ function classifyClaudeSharedFiles(config, sourceRoot, settingsPath, claudeJsonP
33728
33755
  classifyHooks(settingsPath),
33729
33756
  classifySettings(
33730
33757
  settingsPath,
33731
- path47.resolve(sourceRoot, config.source.settings)
33758
+ path48.resolve(sourceRoot, config.source.settings)
33732
33759
  ),
33733
- classifyMcp(claudeJsonPath, path47.resolve(sourceRoot, config.source.mcp))
33760
+ classifyMcp(claudeJsonPath, path48.resolve(sourceRoot, config.source.mcp))
33734
33761
  ];
33735
33762
  }
33736
33763
  function claudeSharedFileRows(config, sourceRoot, configDir, scope, projectRoot) {
@@ -33827,14 +33854,14 @@ function classifyMcp(filePath, sourcePath) {
33827
33854
  }
33828
33855
  function isSymlinkCurrent(linkPath, sourcePath) {
33829
33856
  try {
33830
- return fs46.realpathSync(linkPath) === fs46.realpathSync(sourcePath);
33857
+ return fs47.realpathSync(linkPath) === fs47.realpathSync(sourcePath);
33831
33858
  } catch {
33832
33859
  return false;
33833
33860
  }
33834
33861
  }
33835
33862
  function isCompiledCurrent6(filePath, sourcePath) {
33836
33863
  try {
33837
- const marker = extractProvenanceMarker(fs46.readFileSync(filePath, "utf8"));
33864
+ const marker = extractProvenanceMarker(fs47.readFileSync(filePath, "utf8"));
33838
33865
  return marker?.hash === computeSourceHash(sourcePath) && marker.target === "claude-code";
33839
33866
  } catch {
33840
33867
  return false;
@@ -33864,7 +33891,7 @@ function classifyCompiledFile(component, filePath, target, expectedHash, config,
33864
33891
  }
33865
33892
  function readCompiledContent(filePath) {
33866
33893
  try {
33867
- return fs46.readFileSync(filePath, "utf8");
33894
+ return fs47.readFileSync(filePath, "utf8");
33868
33895
  } catch {
33869
33896
  return null;
33870
33897
  }
@@ -33895,8 +33922,8 @@ function hashString6(value) {
33895
33922
  }
33896
33923
 
33897
33924
  // src/commands/sync.ts
33898
- import fs47 from "fs";
33899
- import path48 from "path";
33925
+ import fs48 from "fs";
33926
+ import path49 from "path";
33900
33927
 
33901
33928
  // node_modules/chalk/source/vendor/ansi-styles/index.js
33902
33929
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -34566,13 +34593,13 @@ async function runSyncCommand(options, logger) {
34566
34593
  reportHookRejections(
34567
34594
  lossReport,
34568
34595
  targets,
34569
- path48.resolve(kitInfo.path, "hooks"),
34596
+ path49.resolve(kitInfo.path, "hooks"),
34570
34597
  kitInfo.components.hooks.declared
34571
34598
  );
34572
34599
  const hooksConflict = reportHooksSourceConflict(
34573
34600
  lossReport,
34574
34601
  targets,
34575
- path48.resolve(kitInfo.path, "hooks"),
34602
+ path49.resolve(kitInfo.path, "hooks"),
34576
34603
  kitInfo.components.hooks.declared
34577
34604
  );
34578
34605
  if (hooksConflict) {
@@ -34775,8 +34802,8 @@ function reconcileSyncedArtifacts(manifest, results, mappings, scope, projectRoo
34775
34802
  }
34776
34803
  }
34777
34804
  function resolveKitFilePath(kitPath, relativePath) {
34778
- const fullPath = path48.join(kitPath, relativePath);
34779
- return fs47.existsSync(fullPath) ? fullPath : null;
34805
+ const fullPath = path49.join(kitPath, relativePath);
34806
+ return fs48.existsSync(fullPath) ? fullPath : null;
34780
34807
  }
34781
34808
  function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
34782
34809
  if (removedSourcePaths.length === 0 || !mappings) {
@@ -34839,9 +34866,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
34839
34866
  }
34840
34867
  if (relativePath.startsWith("agents/")) {
34841
34868
  removeManagedCompiledArtifact2(
34842
- path48.join(
34869
+ path49.join(
34843
34870
  resolveTargetPath(paths.agents ?? ""),
34844
- `${path48.parse(relativePath).name}.agent.md`
34871
+ `${path49.parse(relativePath).name}.agent.md`
34845
34872
  ),
34846
34873
  "copilot",
34847
34874
  relativePath,
@@ -34851,9 +34878,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
34851
34878
  }
34852
34879
  if (relativePath.startsWith("commands/")) {
34853
34880
  removeManagedCompiledArtifact2(
34854
- path48.join(
34881
+ path49.join(
34855
34882
  resolveTargetPath(paths.prompts ?? ""),
34856
- `${path48.parse(relativePath).name}.prompt.md`
34883
+ `${path49.parse(relativePath).name}.prompt.md`
34857
34884
  ),
34858
34885
  "copilot",
34859
34886
  relativePath,
@@ -34863,7 +34890,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
34863
34890
  }
34864
34891
  if (relativePath.endsWith("hooks.json")) {
34865
34892
  removeManagedCompiledArtifact2(
34866
- path48.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
34893
+ path49.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
34867
34894
  "copilot",
34868
34895
  relativePath,
34869
34896
  logger
@@ -34893,9 +34920,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
34893
34920
  }
34894
34921
  if (relativePath.startsWith("agents/")) {
34895
34922
  removeManagedCompiledArtifact2(
34896
- path48.join(
34923
+ path49.join(
34897
34924
  resolveTargetPath(paths.agents ?? ""),
34898
- `${path48.parse(relativePath).name}.toml`
34925
+ `${path49.parse(relativePath).name}.toml`
34899
34926
  ),
34900
34927
  "codex",
34901
34928
  relativePath,
@@ -34905,9 +34932,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
34905
34932
  }
34906
34933
  if (relativePath.startsWith("rules/")) {
34907
34934
  removeManagedCompiledArtifact2(
34908
- path48.join(
34935
+ path49.join(
34909
34936
  resolveTargetPath(paths.rules ?? ""),
34910
- `${path48.parse(relativePath).name}.rules`
34937
+ `${path49.parse(relativePath).name}.rules`
34911
34938
  ),
34912
34939
  "codex",
34913
34940
  relativePath,
@@ -34946,9 +34973,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
34946
34973
  }
34947
34974
  if (relativePath.startsWith("agents/")) {
34948
34975
  removeManagedCompiledArtifact2(
34949
- path48.join(
34976
+ path49.join(
34950
34977
  resolveTargetPath(paths.agents ?? ""),
34951
- `${path48.parse(relativePath).name}.md`
34978
+ `${path49.parse(relativePath).name}.md`
34952
34979
  ),
34953
34980
  "opencode",
34954
34981
  relativePath,
@@ -34958,9 +34985,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
34958
34985
  }
34959
34986
  if (relativePath.startsWith("commands/")) {
34960
34987
  removeManagedCompiledArtifact2(
34961
- path48.join(
34988
+ path49.join(
34962
34989
  resolveTargetPath(paths.commands ?? ""),
34963
- `${path48.parse(relativePath).name}.md`
34990
+ `${path49.parse(relativePath).name}.md`
34964
34991
  ),
34965
34992
  "opencode",
34966
34993
  relativePath,
@@ -34992,9 +35019,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
34992
35019
  }
34993
35020
  if (relativePath.startsWith("agents/")) {
34994
35021
  removeManagedCompiledArtifact2(
34995
- path48.join(
35022
+ path49.join(
34996
35023
  resolveTargetPath(paths.agents ?? ""),
34997
- `${path48.parse(relativePath).name}.md`
35024
+ `${path49.parse(relativePath).name}.md`
34998
35025
  ),
34999
35026
  "cursor",
35000
35027
  relativePath,
@@ -35004,9 +35031,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
35004
35031
  }
35005
35032
  if (relativePath.startsWith("rules/")) {
35006
35033
  removeManagedCompiledArtifact2(
35007
- path48.join(
35034
+ path49.join(
35008
35035
  resolveTargetPath(paths.rules ?? ""),
35009
- `${path48.parse(relativePath).name}.mdc`
35036
+ `${path49.parse(relativePath).name}.mdc`
35010
35037
  ),
35011
35038
  "cursor",
35012
35039
  relativePath,
@@ -35016,9 +35043,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
35016
35043
  }
35017
35044
  if (relativePath.startsWith("commands/")) {
35018
35045
  removeManagedCompiledArtifact2(
35019
- path48.join(
35046
+ path49.join(
35020
35047
  resolveTargetPath(paths.skills ?? ""),
35021
- path48.parse(relativePath).name,
35048
+ path49.parse(relativePath).name,
35022
35049
  "SKILL.md"
35023
35050
  ),
35024
35051
  "cursor",
@@ -35062,9 +35089,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
35062
35089
  }
35063
35090
  if (relativePath.startsWith("rules/")) {
35064
35091
  removeManagedCompiledArtifact2(
35065
- path48.join(
35092
+ path49.join(
35066
35093
  resolveTargetPath(paths.rules ?? ""),
35067
- `${path48.parse(relativePath).name}.md`
35094
+ `${path49.parse(relativePath).name}.md`
35068
35095
  ),
35069
35096
  "cline",
35070
35097
  relativePath,
@@ -35074,9 +35101,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
35074
35101
  }
35075
35102
  if (relativePath.startsWith("commands/")) {
35076
35103
  removeManagedCompiledArtifact2(
35077
- path48.join(
35104
+ path49.join(
35078
35105
  resolveTargetPath(paths.workflows ?? ""),
35079
- path48.basename(relativePath)
35106
+ path49.basename(relativePath)
35080
35107
  ),
35081
35108
  "cline",
35082
35109
  relativePath,
@@ -35094,17 +35121,17 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
35094
35121
  }
35095
35122
  }
35096
35123
  function removeManagedCompiledArtifact2(artifactPath, expectedTarget, expectedSource, logger) {
35097
- if (!fs47.existsSync(artifactPath)) {
35124
+ if (!fs48.existsSync(artifactPath)) {
35098
35125
  return;
35099
35126
  }
35100
- if (!fs47.statSync(artifactPath).isFile()) {
35127
+ if (!fs48.statSync(artifactPath).isFile()) {
35101
35128
  return;
35102
35129
  }
35103
- const marker = extractProvenanceMarker(fs47.readFileSync(artifactPath, "utf8"));
35130
+ const marker = extractProvenanceMarker(fs48.readFileSync(artifactPath, "utf8"));
35104
35131
  if (marker?.source !== expectedSource || marker.target !== expectedTarget) {
35105
35132
  return;
35106
35133
  }
35107
- fs47.rmSync(artifactPath, { force: true });
35134
+ fs48.rmSync(artifactPath, { force: true });
35108
35135
  logger.verbose(` removed stale target artifact: ${artifactPath}`);
35109
35136
  }
35110
35137
  function removeManagedCopilotMcpArtifact2(artifactPath, expectedSource, logger) {
@@ -35135,10 +35162,10 @@ function removeManagedCodexHooksArtifact2(artifactPath, expectedSource, logger)
35135
35162
  logger.verbose(` removed stale target artifact: ${artifactPath}`);
35136
35163
  }
35137
35164
  function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
35138
- if (!fs47.existsSync(artifactPath)) {
35165
+ if (!fs48.existsSync(artifactPath)) {
35139
35166
  return;
35140
35167
  }
35141
- const content = fs47.readFileSync(artifactPath, "utf8");
35168
+ const content = fs48.readFileSync(artifactPath, "utf8");
35142
35169
  const startMarker = "# tangyr: managed mcp start";
35143
35170
  const endMarker = "# tangyr: managed mcp end";
35144
35171
  const startIndex = content.indexOf(startMarker);
@@ -35155,19 +35182,19 @@ function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
35155
35182
  const after = content.slice(endIndex + endMarker.length).trimStart();
35156
35183
  const cleaned = [before, after].filter((entry) => entry.length > 0).join("\n\n");
35157
35184
  if (cleaned.length === 0) {
35158
- fs47.rmSync(artifactPath, { force: true });
35185
+ fs48.rmSync(artifactPath, { force: true });
35159
35186
  } else {
35160
- fs47.writeFileSync(artifactPath, `${cleaned}
35187
+ fs48.writeFileSync(artifactPath, `${cleaned}
35161
35188
  `);
35162
35189
  }
35163
35190
  logger.verbose(` removed stale target artifact: ${artifactPath}`);
35164
35191
  }
35165
35192
  function readJsonObject5(filePath) {
35166
- if (!fs47.existsSync(filePath)) {
35193
+ if (!fs48.existsSync(filePath)) {
35167
35194
  return null;
35168
35195
  }
35169
35196
  try {
35170
- const parsed = JSON.parse(fs47.readFileSync(filePath, "utf8"));
35197
+ const parsed = JSON.parse(fs48.readFileSync(filePath, "utf8"));
35171
35198
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
35172
35199
  } catch {
35173
35200
  return null;
@@ -35181,10 +35208,10 @@ function readJsonMetadata(value) {
35181
35208
  }
35182
35209
  function writeJsonOrRemove2(filePath, parsed) {
35183
35210
  if (isEmptyJsonValue2(parsed)) {
35184
- fs47.rmSync(filePath, { force: true });
35211
+ fs48.rmSync(filePath, { force: true });
35185
35212
  return;
35186
35213
  }
35187
- fs47.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
35214
+ fs48.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
35188
35215
  `);
35189
35216
  }
35190
35217
  function isEmptyJsonValue2(value) {
@@ -35244,8 +35271,8 @@ function removeManagedHookEntries(value, expectedSource) {
35244
35271
  }
35245
35272
 
35246
35273
  // src/commands/validate.ts
35247
- import fs48 from "fs";
35248
- import path49 from "path";
35274
+ import fs49 from "fs";
35275
+ import path50 from "path";
35249
35276
  var SUPPORTED_KIT_FORMATS2 = [1];
35250
35277
  var SUPPORTED_DISCIPLINE_VERSIONS = [
35251
35278
  "0.14.0",
@@ -35360,12 +35387,12 @@ function checkArchetype(kit) {
35360
35387
  }
35361
35388
  function checkHookScriptsExist(kit) {
35362
35389
  const violations = [];
35363
- const hooksDir = path49.join(kit.path, "hooks");
35390
+ const hooksDir = path50.join(kit.path, "hooks");
35364
35391
  const missingSet = new Set(kit.components.hooks.missing);
35365
35392
  for (const name of kit.components.hooks.declared) {
35366
35393
  if (missingSet.has(name)) continue;
35367
- const declarationPath = path49.join(hooksDir, `${name}.md`);
35368
- if (!fs48.existsSync(declarationPath)) continue;
35394
+ const declarationPath = path50.join(hooksDir, `${name}.md`);
35395
+ if (!fs49.existsSync(declarationPath)) continue;
35369
35396
  let data;
35370
35397
  try {
35371
35398
  ({ data } = parseMarkdownFrontmatter(declarationPath));
@@ -35375,8 +35402,8 @@ function checkHookScriptsExist(kit) {
35375
35402
  if (typeof data.command === "string" && data.command.trim().length > 0) {
35376
35403
  continue;
35377
35404
  }
35378
- const scriptPath = path49.join(hooksDir, "scripts", `${name}.ts`);
35379
- if (!fs48.existsSync(scriptPath)) {
35405
+ const scriptPath = path50.join(hooksDir, "scripts", `${name}.ts`);
35406
+ if (!fs49.existsSync(scriptPath)) {
35380
35407
  violations.push({
35381
35408
  code: "hook-script-missing",
35382
35409
  location: `hooks/scripts/${name}.ts`,
@@ -35389,10 +35416,10 @@ function checkHookScriptsExist(kit) {
35389
35416
  function checkOptionalSourceDocuments(kit) {
35390
35417
  const violations = [];
35391
35418
  for (const name of [".mcp.json", "settings.json", ".lsp.json"]) {
35392
- const filePath = path49.join(kit.path, name);
35393
- if (!fs48.existsSync(filePath)) continue;
35419
+ const filePath = path50.join(kit.path, name);
35420
+ if (!fs49.existsSync(filePath)) continue;
35394
35421
  try {
35395
- const parsed = JSON.parse(fs48.readFileSync(filePath, "utf8"));
35422
+ const parsed = JSON.parse(fs49.readFileSync(filePath, "utf8"));
35396
35423
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
35397
35424
  violations.push({
35398
35425
  code: "optional-source-malformed",
@@ -35414,10 +35441,10 @@ function checkSkillSubfolderNames(kit) {
35414
35441
  const notices = [];
35415
35442
  const canonical = new Set(CANONICAL_SKILL_SUBFOLDERS);
35416
35443
  for (const name of kit.components.skills.declared) {
35417
- const skillDir = path49.join(kit.path, "skills", name);
35444
+ const skillDir = path50.join(kit.path, "skills", name);
35418
35445
  let entries;
35419
35446
  try {
35420
- entries = fs48.readdirSync(skillDir, { withFileTypes: true });
35447
+ entries = fs49.readdirSync(skillDir, { withFileTypes: true });
35421
35448
  } catch {
35422
35449
  continue;
35423
35450
  }
@@ -35435,7 +35462,7 @@ function checkSkillSubfolderNames(kit) {
35435
35462
  return notices;
35436
35463
  }
35437
35464
  function checkHooksSourceForm(kit) {
35438
- const hooksDir = path49.join(kit.path, "hooks");
35465
+ const hooksDir = path50.join(kit.path, "hooks");
35439
35466
  const message = describeHooksSourceConflict(
35440
35467
  hooksDir,
35441
35468
  kit.components.hooks.declared
@@ -35447,12 +35474,12 @@ function checkHooksSourceForm(kit) {
35447
35474
  } : null;
35448
35475
  }
35449
35476
  function checkHookDeclarations(kit) {
35450
- const hooksDir = path49.join(kit.path, "hooks");
35477
+ const hooksDir = path50.join(kit.path, "hooks");
35451
35478
  return collectHookRejections(hooksDir, kit.components.hooks.declared).map(
35452
35479
  (r) => ({
35453
35480
  code: "hook-declaration-invalid",
35454
- location: `hooks/${path49.basename(r.file)}`,
35455
- 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.`
35481
+ location: `hooks/${path50.basename(r.file)}`,
35482
+ 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.`
35456
35483
  })
35457
35484
  );
35458
35485
  }
@@ -35472,11 +35499,11 @@ function checkKitFormatSupported(kit) {
35472
35499
  function checkEntrypointExists(kit) {
35473
35500
  const declared = kit.entrypoint;
35474
35501
  const entrypoint = declared ?? DEFAULT_ENTRYPOINT;
35475
- const entrypointPath = path49.join(kit.path, entrypoint);
35476
- if (fs48.existsSync(entrypointPath)) {
35502
+ const entrypointPath = path50.join(kit.path, entrypoint);
35503
+ if (fs49.existsSync(entrypointPath)) {
35477
35504
  return null;
35478
35505
  }
35479
- const legacyPresent = declared === void 0 && fs48.existsSync(path49.join(kit.path, LEGACY_ENTRYPOINT));
35506
+ const legacyPresent = declared === void 0 && fs49.existsSync(path50.join(kit.path, LEGACY_ENTRYPOINT));
35480
35507
  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.`;
35481
35508
  return {
35482
35509
  code: "entrypoint-missing",
@@ -35535,9 +35562,9 @@ function checkComponentFrontmatter(kit) {
35535
35562
  const missingSet = new Set(kit.components[cat].missing);
35536
35563
  for (const name of kit.components[cat].declared) {
35537
35564
  if (missingSet.has(name)) continue;
35538
- const filePath = cat === "skills" ? path49.join(kit.path, cat, name, "SKILL.md") : path49.join(kit.path, cat, `${name}.md`);
35539
- if (!fs48.existsSync(filePath)) continue;
35540
- const relPath = path49.relative(kit.path, filePath);
35565
+ const filePath = cat === "skills" ? path50.join(kit.path, cat, name, "SKILL.md") : path50.join(kit.path, cat, `${name}.md`);
35566
+ if (!fs49.existsSync(filePath)) continue;
35567
+ const relPath = path50.relative(kit.path, filePath);
35541
35568
  try {
35542
35569
  const { data } = parseMarkdownFrontmatter(filePath);
35543
35570
  for (const field of requiredFields) {
@@ -35562,10 +35589,10 @@ function checkComponentFrontmatter(kit) {
35562
35589
  }
35563
35590
  function checkReservedRootNames(kit) {
35564
35591
  const violations = [];
35565
- if (!fs48.existsSync(kit.path) || !fs48.statSync(kit.path).isDirectory()) {
35592
+ if (!fs49.existsSync(kit.path) || !fs49.statSync(kit.path).isDirectory()) {
35566
35593
  return violations;
35567
35594
  }
35568
- const entries = fs48.readdirSync(kit.path, { withFileTypes: true });
35595
+ const entries = fs49.readdirSync(kit.path, { withFileTypes: true });
35569
35596
  for (const entry of entries) {
35570
35597
  if (RESERVED_ROOT_NAMES.includes(entry.name)) {
35571
35598
  violations.push({
@@ -35582,8 +35609,8 @@ function checkHumanOnlyCommandInvocation(kit) {
35582
35609
  const missingSet = new Set(kit.components.commands.missing);
35583
35610
  for (const name of kit.components.commands.declared) {
35584
35611
  if (missingSet.has(name)) continue;
35585
- const filePath = path49.join(kit.path, "commands", `${name}.md`);
35586
- if (!fs48.existsSync(filePath)) continue;
35612
+ const filePath = path50.join(kit.path, "commands", `${name}.md`);
35613
+ if (!fs49.existsSync(filePath)) continue;
35587
35614
  let data;
35588
35615
  try {
35589
35616
  ({ data } = parseMarkdownFrontmatter(filePath));
@@ -35596,7 +35623,7 @@ function checkHumanOnlyCommandInvocation(kit) {
35596
35623
  if (!barred) {
35597
35624
  violations.push({
35598
35625
  code: "command-human-only-model-invocable",
35599
- location: path49.relative(kit.path, filePath),
35626
+ location: path50.relative(kit.path, filePath),
35600
35627
  message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
35601
35628
  });
35602
35629
  }
@@ -35605,8 +35632,8 @@ function checkHumanOnlyCommandInvocation(kit) {
35605
35632
  }
35606
35633
 
35607
35634
  // src/commands/verify.ts
35608
- import fs49 from "fs";
35609
- import path50 from "path";
35635
+ import fs50 from "fs";
35636
+ import path51 from "path";
35610
35637
  function runVerifyCommand(options, logger) {
35611
35638
  if (options.target && !isKnownTarget(options.target)) {
35612
35639
  throwUnrecognizedTarget(options.target);
@@ -35787,8 +35814,8 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
35787
35814
  if (!slotPath) {
35788
35815
  continue;
35789
35816
  }
35790
- const fullPath = subPath ? path50.join(slotPath, subPath) : slotPath;
35791
- if (!fs49.existsSync(fullPath)) {
35817
+ const fullPath = subPath ? path51.join(slotPath, subPath) : slotPath;
35818
+ if (!fs50.existsSync(fullPath)) {
35792
35819
  failures.push(
35793
35820
  `claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`
35794
35821
  );