@alessandroraffa/tangyr 8.0.0 → 9.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.
Files changed (3) hide show
  1. package/README.md +24 -24
  2. package/dist/index.js +738 -648
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1372,7 +1372,7 @@ var require_command = __commonJS({
1372
1372
  "use strict";
1373
1373
  var EventEmitter = __require("events").EventEmitter;
1374
1374
  var childProcess = __require("child_process");
1375
- var path56 = __require("path");
1375
+ var path57 = __require("path");
1376
1376
  var fs53 = __require("fs");
1377
1377
  var process5 = __require("process");
1378
1378
  var { Argument: Argument2, humanReadableArgName } = require_argument();
@@ -2385,9 +2385,9 @@ 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 = path56.resolve(baseDir, baseName);
2388
+ const localBin = path57.resolve(baseDir, baseName);
2389
2389
  if (fs53.existsSync(localBin)) return localBin;
2390
- if (sourceExt.includes(path56.extname(baseName))) return void 0;
2390
+ if (sourceExt.includes(path57.extname(baseName))) return void 0;
2391
2391
  const foundExt = sourceExt.find(
2392
2392
  (ext) => fs53.existsSync(`${localBin}${ext}`)
2393
2393
  );
@@ -2405,17 +2405,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
2405
2405
  } catch {
2406
2406
  resolvedScriptPath = this._scriptPath;
2407
2407
  }
2408
- executableDir = path56.resolve(
2409
- path56.dirname(resolvedScriptPath),
2408
+ executableDir = path57.resolve(
2409
+ path57.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 = path56.basename(
2416
+ const legacyName = path57.basename(
2417
2417
  this._scriptPath,
2418
- path56.extname(this._scriptPath)
2418
+ path57.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(path56.extname(executableFile));
2429
+ launchWithNode = sourceExt.includes(path57.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 = path56.basename(filename, path56.extname(filename));
3344
+ this._name = path57.basename(filename, path57.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(path57) {
3359
- if (path57 === void 0) return this._executableDir;
3360
- this._executableDir = path57;
3358
+ executableDir(path58) {
3359
+ if (path58 === void 0) return this._executableDir;
3360
+ this._executableDir = path58;
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, path56) {
3717
- const ctrl = callVisitor(key, node, visitor, path56);
3716
+ function visit_(key, node, visitor, path57) {
3717
+ const ctrl = callVisitor(key, node, visitor, path57);
3718
3718
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
3719
- replaceNode(key, path56, ctrl);
3720
- return visit_(key, ctrl, visitor, path56);
3719
+ replaceNode(key, path57, ctrl);
3720
+ return visit_(key, ctrl, visitor, path57);
3721
3721
  }
3722
3722
  if (typeof ctrl !== "symbol") {
3723
3723
  if (identity.isCollection(node)) {
3724
- path56 = Object.freeze(path56.concat(node));
3724
+ path57 = Object.freeze(path57.concat(node));
3725
3725
  for (let i = 0; i < node.items.length; ++i) {
3726
- const ci2 = visit_(i, node.items[i], visitor, path56);
3726
+ const ci2 = visit_(i, node.items[i], visitor, path57);
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
- path56 = Object.freeze(path56.concat(node));
3738
- const ck = visit_("key", node.key, visitor, path56);
3737
+ path57 = Object.freeze(path57.concat(node));
3738
+ const ck = visit_("key", node.key, visitor, path57);
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, path56);
3743
+ const cv = visit_("value", node.value, visitor, path57);
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, path56) {
3765
- const ctrl = await callVisitor(key, node, visitor, path56);
3764
+ async function visitAsync_(key, node, visitor, path57) {
3765
+ const ctrl = await callVisitor(key, node, visitor, path57);
3766
3766
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
3767
- replaceNode(key, path56, ctrl);
3768
- return visitAsync_(key, ctrl, visitor, path56);
3767
+ replaceNode(key, path57, ctrl);
3768
+ return visitAsync_(key, ctrl, visitor, path57);
3769
3769
  }
3770
3770
  if (typeof ctrl !== "symbol") {
3771
3771
  if (identity.isCollection(node)) {
3772
- path56 = Object.freeze(path56.concat(node));
3772
+ path57 = Object.freeze(path57.concat(node));
3773
3773
  for (let i = 0; i < node.items.length; ++i) {
3774
- const ci2 = await visitAsync_(i, node.items[i], visitor, path56);
3774
+ const ci2 = await visitAsync_(i, node.items[i], visitor, path57);
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
- path56 = Object.freeze(path56.concat(node));
3786
- const ck = await visitAsync_("key", node.key, visitor, path56);
3785
+ path57 = Object.freeze(path57.concat(node));
3786
+ const ck = await visitAsync_("key", node.key, visitor, path57);
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, path56);
3791
+ const cv = await visitAsync_("value", node.value, visitor, path57);
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, path56) {
3818
+ function callVisitor(key, node, visitor, path57) {
3819
3819
  if (typeof visitor === "function")
3820
- return visitor(key, node, path56);
3820
+ return visitor(key, node, path57);
3821
3821
  if (identity.isMap(node))
3822
- return visitor.Map?.(key, node, path56);
3822
+ return visitor.Map?.(key, node, path57);
3823
3823
  if (identity.isSeq(node))
3824
- return visitor.Seq?.(key, node, path56);
3824
+ return visitor.Seq?.(key, node, path57);
3825
3825
  if (identity.isPair(node))
3826
- return visitor.Pair?.(key, node, path56);
3826
+ return visitor.Pair?.(key, node, path57);
3827
3827
  if (identity.isScalar(node))
3828
- return visitor.Scalar?.(key, node, path56);
3828
+ return visitor.Scalar?.(key, node, path57);
3829
3829
  if (identity.isAlias(node))
3830
- return visitor.Alias?.(key, node, path56);
3830
+ return visitor.Alias?.(key, node, path57);
3831
3831
  return void 0;
3832
3832
  }
3833
- function replaceNode(key, path56, node) {
3834
- const parent = path56[path56.length - 1];
3833
+ function replaceNode(key, path57, node) {
3834
+ const parent = path57[path57.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, path56, value) {
4442
+ function collectionFromPath(schema, path57, value) {
4443
4443
  let v2 = value;
4444
- for (let i = path56.length - 1; i >= 0; --i) {
4445
- const k2 = path56[i];
4444
+ for (let i = path57.length - 1; i >= 0; --i) {
4445
+ const k2 = path57[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 = (path56) => path56 == null || typeof path56 === "object" && !!path56[Symbol.iterator]().next().done;
4464
+ var isEmptyPath = (path57) => path57 == null || typeof path57 === "object" && !!path57[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(path56, value) {
4495
- if (isEmptyPath(path56))
4494
+ addIn(path57, value) {
4495
+ if (isEmptyPath(path57))
4496
4496
  this.add(value);
4497
4497
  else {
4498
- const [key, ...rest] = path56;
4498
+ const [key, ...rest] = path57;
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(path56) {
4513
- const [key, ...rest] = path56;
4512
+ deleteIn(path57) {
4513
+ const [key, ...rest] = path57;
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(path56, keepScalar) {
4528
- const [key, ...rest] = path56;
4527
+ getIn(path57, keepScalar) {
4528
+ const [key, ...rest] = path57;
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(path56) {
4547
- const [key, ...rest] = path56;
4546
+ hasIn(path57) {
4547
+ const [key, ...rest] = path57;
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(path56, value) {
4558
- const [key, ...rest] = path56;
4557
+ setIn(path57, value) {
4558
+ const [key, ...rest] = path57;
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(path56, value) {
7070
+ addIn(path57, value) {
7071
7071
  if (assertCollection(this.contents))
7072
- this.contents.addIn(path56, value);
7072
+ this.contents.addIn(path57, 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(path56) {
7148
- if (Collection.isEmptyPath(path56)) {
7147
+ deleteIn(path57) {
7148
+ if (Collection.isEmptyPath(path57)) {
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(path56) : false;
7154
+ return assertCollection(this.contents) ? this.contents.deleteIn(path57) : 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(path56, keepScalar) {
7170
- if (Collection.isEmptyPath(path56))
7169
+ getIn(path57, keepScalar) {
7170
+ if (Collection.isEmptyPath(path57))
7171
7171
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
7172
- return identity.isCollection(this.contents) ? this.contents.getIn(path56, keepScalar) : void 0;
7172
+ return identity.isCollection(this.contents) ? this.contents.getIn(path57, 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(path56) {
7184
- if (Collection.isEmptyPath(path56))
7183
+ hasIn(path57) {
7184
+ if (Collection.isEmptyPath(path57))
7185
7185
  return this.contents !== void 0;
7186
- return identity.isCollection(this.contents) ? this.contents.hasIn(path56) : false;
7186
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path57) : 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(path56, value) {
7204
- if (Collection.isEmptyPath(path56)) {
7203
+ setIn(path57, value) {
7204
+ if (Collection.isEmptyPath(path57)) {
7205
7205
  this.contents = value;
7206
7206
  } else if (this.contents == null) {
7207
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path56), value);
7207
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path57), value);
7208
7208
  } else if (assertCollection(this.contents)) {
7209
- this.contents.setIn(path56, value);
7209
+ this.contents.setIn(path57, 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, path56) => {
9166
+ visit.itemAtPath = (cst, path57) => {
9167
9167
  let item = cst;
9168
- for (const [field, index] of path56) {
9168
+ for (const [field, index] of path57) {
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, path56) => {
9178
- const parent = visit.itemAtPath(cst, path56.slice(0, -1));
9179
- const field = path56[path56.length - 1][0];
9177
+ visit.parentCollection = (cst, path57) => {
9178
+ const parent = visit.itemAtPath(cst, path57.slice(0, -1));
9179
+ const field = path57[path57.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(path56, item, visitor) {
9186
- let ctrl = visitor(item, path56);
9185
+ function _visit(path57, item, visitor) {
9186
+ let ctrl = visitor(item, path57);
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(path56.concat([[field, i]])), token.items[i], visitor);
9193
+ const ci2 = _visit(Object.freeze(path57.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, path56);
9204
+ ctrl = ctrl(item, path57);
9205
9205
  }
9206
9206
  }
9207
- return typeof ctrl === "function" ? ctrl(item, path56) : ctrl;
9207
+ return typeof ctrl === "function" ? ctrl(item, path57) : ctrl;
9208
9208
  }
9209
9209
  exports2.visit = visit;
9210
9210
  }
@@ -15336,6 +15336,14 @@ function markerFromMatch(match) {
15336
15336
  }
15337
15337
  return { source, hash, target };
15338
15338
  }
15339
+ function carriesProvenanceMarker(filePath) {
15340
+ try {
15341
+ const firstNonEmpty = fs2.readFileSync(filePath, "utf8").split("\n").find((line) => line.trim().length > 0) ?? "";
15342
+ return extractProvenanceMarker(firstNonEmpty) !== null;
15343
+ } catch {
15344
+ return false;
15345
+ }
15346
+ }
15339
15347
 
15340
15348
  // src/core/kit.ts
15341
15349
  import fs4 from "fs";
@@ -15644,6 +15652,10 @@ function findKit(registry, name) {
15644
15652
  function defaultKitSearchPaths(configDir) {
15645
15653
  return [path4.join(configDir, "operating-kits")];
15646
15654
  }
15655
+ function conventionalKitPath(configDir) {
15656
+ const candidate = path4.join(configDir, "tangyr-kit");
15657
+ return fs4.existsSync(path4.join(candidate, "tangyr-kit.yaml")) ? candidate : void 0;
15658
+ }
15647
15659
  function resolveKitSelection(selection) {
15648
15660
  const registry = discoverKits(selection.searchPaths);
15649
15661
  if (selection.kitPath) {
@@ -15659,6 +15671,10 @@ function resolveKitSelection(selection) {
15659
15671
  };
15660
15672
  }
15661
15673
  if (!selection.kit) {
15674
+ if (selection.conventionalPath) {
15675
+ const kit2 = loadKit(selection.conventionalPath);
15676
+ return { kit: kit2, registry: mergeRegistryKit(registry, kit2) };
15677
+ }
15662
15678
  return void 0;
15663
15679
  }
15664
15680
  const kit = findKit(registry, selection.kit);
@@ -16814,7 +16830,8 @@ function resolveRuntime(options, importMetaUrl) {
16814
16830
  const kitResolution = resolveKitSelection({
16815
16831
  kit: config.kit,
16816
16832
  kitPath: config.kitPath,
16817
- searchPaths
16833
+ searchPaths,
16834
+ conventionalPath: conventionalKitPath(configDir)
16818
16835
  });
16819
16836
  if ((config.kit || config.kitPath) && !kitResolution) {
16820
16837
  throw new Error(
@@ -17338,9 +17355,6 @@ function instructionsByActiveTarget(tools, scope, projectRoot, mappings) {
17338
17355
  }
17339
17356
 
17340
17357
  // src/core/foreign-instructions.ts
17341
- function postureLeavesConflicts(onConflict) {
17342
- return onConflict === "ask" || onConflict === "skip";
17343
- }
17344
17358
  function instructionsEntrypoints(tools, scope, projectRoot, mappings) {
17345
17359
  const byPath = /* @__PURE__ */ new Map();
17346
17360
  const add = (destination, tool) => {
@@ -17383,7 +17397,7 @@ function findForeignInstructions(conflicting, entrypoints) {
17383
17397
  }
17384
17398
  return [...found2.values()].sort((a, b) => a.path.localeCompare(b.path));
17385
17399
  }
17386
- function describeForeignInstructions(foreign, posture, projectRoot) {
17400
+ function describeForeignInstructions(foreign, projectRoot) {
17387
17401
  const display2 = (target) => {
17388
17402
  if (!projectRoot) {
17389
17403
  return target;
@@ -17392,6 +17406,7 @@ function describeForeignInstructions(foreign, posture, projectRoot) {
17392
17406
  return relative.startsWith("..") ? target : relative;
17393
17407
  };
17394
17408
  const width = Math.max(...foreign.map((one) => display2(one.path).length));
17409
+ const first = display2(foreign[0].path);
17395
17410
  return [
17396
17411
  "",
17397
17412
  "This project already has an instructions file that Tangyr did not write:",
@@ -17400,14 +17415,15 @@ function describeForeignInstructions(foreign, posture, projectRoot) {
17400
17415
  (one) => ` ${display2(one.path).padEnd(width)} read by ${one.targets.join(", ")}`
17401
17416
  ),
17402
17417
  "",
17403
- "That file carries the working method the rest of the kit is used by. With",
17404
- posture === "ask" ? "onConflict: ask and no one to ask, it would be left where it is while every" : "onConflict: skip, it would be left where it is while every",
17405
- "other component was installed \u2014 the tools without the rules, and a closing",
17406
- "line saying the installation completed.",
17418
+ "That file carries the working method the rest of the kit is used by, so a",
17419
+ "kit installed beside it does nothing it was adopted for. No conflict",
17420
+ "posture changes this: replacing a document a repository wrote on purpose",
17421
+ "is not a decision Tangyr makes because a configuration key allows it.",
17407
17422
  "",
17408
- "Either move it aside and install again, or tell Tangyr to replace it:",
17409
- " onConflict: backup replaces it and keeps a copy under .tangyr/backups/",
17410
- " onConflict: overwrite replaces it and keeps no copy"
17423
+ "Do one of these, then install again:",
17424
+ ` move it aside mv ${first} ${first}.before-tangyr`,
17425
+ " delete it if the kit's entrypoint already carries its content",
17426
+ " fold it in move what it says into the kit, and let the kit deliver it"
17411
17427
  ];
17412
17428
  }
17413
17429
 
@@ -17632,25 +17648,19 @@ function runAssessCommand(options, logger) {
17632
17648
  function reportWhatInstallWillDo(conflicts, scope, projectRoot, options, logger) {
17633
17649
  const posture = configuredPosture(options);
17634
17650
  const count = `${String(conflicts.length)} conflicting configuration(s) found.`;
17635
- if (postureLeavesConflicts(posture)) {
17636
- const foreign = foreignInstructionsAmong(
17637
- conflicts,
17638
- scope,
17639
- projectRoot,
17640
- options
17641
- );
17642
- if (foreign.length > 0) {
17643
- logger.warn(`
17644
- ${count} Installation will be refused.`);
17645
- for (const line of describeForeignInstructions(
17646
- foreign,
17647
- posture === "ask" ? "ask" : "skip",
17648
- projectRoot
17649
- )) {
17650
- logger.warn(line);
17651
- }
17652
- return;
17651
+ const foreign = foreignInstructionsAmong(
17652
+ conflicts,
17653
+ scope,
17654
+ projectRoot,
17655
+ options
17656
+ );
17657
+ if (foreign.length > 0) {
17658
+ logger.warn(`
17659
+ ${count} Installation will be refused (exit 2).`);
17660
+ for (const line of describeForeignInstructions(foreign, projectRoot)) {
17661
+ logger.warn(line);
17653
17662
  }
17663
+ return;
17654
17664
  }
17655
17665
  const outcome = {
17656
17666
  ask: "With onConflict: ask, installation will ask you about each one; run non-interactively, where there is no one to ask, it leaves them as they are.",
@@ -17728,7 +17738,7 @@ function collectProjectScopeFindings(projectRoot, tools, options) {
17728
17738
  continue;
17729
17739
  }
17730
17740
  const type = stat.isSymbolicLink() ? "symlink" : stat.isDirectory() ? "directory" : "file";
17731
- const ours = type === "file" && carriesTangyrMarker(resolvedPath);
17741
+ const ours = type === "file" && carriesProvenanceMarker(resolvedPath);
17732
17742
  findings.push({
17733
17743
  path: resolvedPath,
17734
17744
  tool,
@@ -17740,14 +17750,6 @@ function collectProjectScopeFindings(projectRoot, tools, options) {
17740
17750
  }
17741
17751
  return findings;
17742
17752
  }
17743
- function carriesTangyrMarker(filePath) {
17744
- try {
17745
- const firstNonEmpty = fs12.readFileSync(filePath, "utf8").split("\n").find((line) => line.trim().length > 0) ?? "";
17746
- return extractProvenanceMarker(firstNonEmpty) !== null;
17747
- } catch {
17748
- return false;
17749
- }
17750
- }
17751
17753
  function requestedAssessTools(toolFilter) {
17752
17754
  return toolFilter ?? [...DEFAULT_ASSESS_TARGETS];
17753
17755
  }
@@ -17826,7 +17828,8 @@ function resolveKitPath(config, configDir) {
17826
17828
  const resolution = resolveKitSelection({
17827
17829
  kit: config.kit,
17828
17830
  kitPath: config.kitPath,
17829
- searchPaths
17831
+ searchPaths,
17832
+ conventionalPath: conventionalKitPath(configDir)
17830
17833
  });
17831
17834
  return resolution?.kit.path ?? null;
17832
17835
  }
@@ -18627,7 +18630,7 @@ async function runCacheClearCommand(options, logger) {
18627
18630
 
18628
18631
  // src/commands/cleanup.ts
18629
18632
  import fs30 from "fs";
18630
- import path29 from "path";
18633
+ import path30 from "path";
18631
18634
 
18632
18635
  // node_modules/glob/dist/esm/index.min.js
18633
18636
  import { fileURLToPath as Wi } from "url";
@@ -21782,7 +21785,7 @@ function removeManagedEntries(filePath, parser, serializer, removeManaged, logge
21782
21785
 
21783
21786
  // src/commands/uninstall.ts
21784
21787
  import fs29 from "fs";
21785
- import path28 from "path";
21788
+ import path29 from "path";
21786
21789
 
21787
21790
  // src/core/managed-sources.ts
21788
21791
  var import_yaml5 = __toESM(require_dist(), 1);
@@ -22306,7 +22309,7 @@ function reportHooksSourceConflict(report, targets, hooksDir, hookNames) {
22306
22309
 
22307
22310
  // src/adapters/hook-scripts-bridge.ts
22308
22311
  import fs26 from "fs";
22309
- import path26 from "path";
22312
+ import path27 from "path";
22310
22313
 
22311
22314
  // src/utils/fs.ts
22312
22315
  import fs24 from "fs";
@@ -22388,6 +22391,7 @@ function clearSymlinkAtDestination(destination) {
22388
22391
 
22389
22392
  // src/core/artifact-state.ts
22390
22393
  import fs25 from "fs";
22394
+ import path25 from "path";
22391
22395
  function isLegacyArtifactState(recorded) {
22392
22396
  return recorded.startsWith("target:") || recorded.startsWith("dir:");
22393
22397
  }
@@ -22414,11 +22418,14 @@ function describeArtifactState(artifactPath) {
22414
22418
  return null;
22415
22419
  }
22416
22420
  }
22417
- function refreshArtifactStates(artifacts) {
22421
+ function refreshArtifactStates(artifacts, written) {
22418
22422
  for (const artifact of artifacts) {
22419
22423
  if (!artifact.path) {
22420
22424
  continue;
22421
22425
  }
22426
+ if (written && !written.has(path25.resolve(artifact.path))) {
22427
+ continue;
22428
+ }
22422
22429
  const state = describeArtifactState(artifact.path);
22423
22430
  if (state !== null) {
22424
22431
  artifact.hash = state;
@@ -22435,9 +22442,22 @@ function compareArtifactState(recorded, artifactPath) {
22435
22442
  }
22436
22443
  return current === recorded ? "current" : "modified";
22437
22444
  }
22445
+ function hasDriftedSinceInstall(artifactPath, manifest) {
22446
+ if (!manifest) {
22447
+ return false;
22448
+ }
22449
+ const resolved = path25.resolve(artifactPath);
22450
+ const recorded = manifest.artifacts.find(
22451
+ (artifact) => artifact.path && path25.resolve(artifact.path) === resolved
22452
+ );
22453
+ if (!recorded) {
22454
+ return false;
22455
+ }
22456
+ return compareArtifactState(recorded.hash, artifactPath) === "modified";
22457
+ }
22438
22458
 
22439
22459
  // src/core/shared-artifacts.ts
22440
- import path25 from "path";
22460
+ import path26 from "path";
22441
22461
  var SHARED_NAMESPACE = "shared";
22442
22462
  var SHARED_INSTRUCTIONS_KEY = `${SHARED_NAMESPACE}/AGENTS.md`;
22443
22463
  var SHARED_INSTRUCTIONS_FILE = "AGENTS.md";
@@ -22447,14 +22467,14 @@ function sharedArtifactKey(destination, scope, projectRoot) {
22447
22467
  return null;
22448
22468
  }
22449
22469
  const root = projectRoot ?? process.cwd();
22450
- const shared = path25.resolve(root, SHARED_INSTRUCTIONS_FILE);
22451
- return path25.resolve(destination) === shared ? SHARED_INSTRUCTIONS_KEY : null;
22470
+ const shared = path26.resolve(root, SHARED_INSTRUCTIONS_FILE);
22471
+ return path26.resolve(destination) === shared ? SHARED_INSTRUCTIONS_KEY : null;
22452
22472
  }
22453
22473
  function resolveSharedArtifactKey(key, scope, projectRoot) {
22454
22474
  if (key !== SHARED_INSTRUCTIONS_KEY || scope !== "project") {
22455
22475
  return null;
22456
22476
  }
22457
- return path25.join(projectRoot ?? process.cwd(), SHARED_INSTRUCTIONS_FILE);
22477
+ return path26.join(projectRoot ?? process.cwd(), SHARED_INSTRUCTIONS_FILE);
22458
22478
  }
22459
22479
  var SHARED_SKILLS_PREFIX = `${SHARED_NAMESPACE}/skills`;
22460
22480
  function sharedKeyForDestination(destination, scope, projectRoot, platformPaths) {
@@ -22462,7 +22482,7 @@ function sharedKeyForDestination(destination, scope, projectRoot, platformPaths)
22462
22482
  if (instructions) {
22463
22483
  return instructions;
22464
22484
  }
22465
- const resolved = path25.resolve(destination);
22485
+ const resolved = path26.resolve(destination);
22466
22486
  let profiles;
22467
22487
  try {
22468
22488
  profiles = resolveTargetPaths({
@@ -22473,12 +22493,12 @@ function sharedKeyForDestination(destination, scope, projectRoot, platformPaths)
22473
22493
  } catch {
22474
22494
  return null;
22475
22495
  }
22476
- if (resolved === path25.resolve(profiles.codex.hook_scripts)) {
22496
+ if (resolved === path26.resolve(profiles.codex.hook_scripts)) {
22477
22497
  return SHARED_HOOK_SCRIPTS_KEY;
22478
22498
  }
22479
- const skillsRoot = path25.resolve(profiles.opencode.skills_shared);
22480
- if (resolved.startsWith(`${skillsRoot}${path25.sep}`)) {
22481
- const inside = path25.relative(skillsRoot, resolved).split(path25.sep).join("/");
22499
+ const skillsRoot = path26.resolve(profiles.opencode.skills_shared);
22500
+ if (resolved.startsWith(`${skillsRoot}${path26.sep}`)) {
22501
+ const inside = path26.relative(skillsRoot, resolved).split(path26.sep).join("/");
22482
22502
  return `${SHARED_SKILLS_PREFIX}/${inside}`;
22483
22503
  }
22484
22504
  return null;
@@ -22488,7 +22508,7 @@ function resolveSharedSkillsKey(key, sharedSkillsRoot) {
22488
22508
  return null;
22489
22509
  }
22490
22510
  const inside = key.slice(SHARED_SKILLS_PREFIX.length + 1);
22491
- return path25.join(sharedSkillsRoot, ...inside.split("/"));
22511
+ return path26.join(sharedSkillsRoot, ...inside.split("/"));
22492
22512
  }
22493
22513
 
22494
22514
  // src/adapters/hook-scripts-bridge.ts
@@ -22516,7 +22536,7 @@ function syncHookScriptsBridge(args) {
22516
22536
  } else if (artifactClass === "managed-symlink") {
22517
22537
  fs26.unlinkSync(destination);
22518
22538
  }
22519
- ensureDir(path26.dirname(destination));
22539
+ ensureDir(path27.dirname(destination));
22520
22540
  createRelativeSymlink(source, destination, "dir");
22521
22541
  if (args.manifest) {
22522
22542
  const state = describeArtifactState(destination);
@@ -22547,7 +22567,7 @@ function isSymlinkTo(linkPath, source) {
22547
22567
 
22548
22568
  // src/core/shared-surface.ts
22549
22569
  import fs27 from "fs";
22550
- import path27 from "path";
22570
+ import path28 from "path";
22551
22571
  function isPlainObject2(value) {
22552
22572
  return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) !== null;
22553
22573
  }
@@ -22887,7 +22907,7 @@ async function runUninstallCommand(options, logger) {
22887
22907
  if (recorded) {
22888
22908
  const outcome = revertSharedSurface(recorded, logger);
22889
22909
  if (outcome === "reverted" || outcome === "removed") {
22890
- removedParentDirs.add(path28.dirname(recorded.path));
22910
+ removedParentDirs.add(path29.dirname(recorded.path));
22891
22911
  removedCount++;
22892
22912
  }
22893
22913
  if (outcome === "reverted") {
@@ -22903,7 +22923,7 @@ async function runUninstallCommand(options, logger) {
22903
22923
  uninstallProjectRoot
22904
22924
  );
22905
22925
  if (surfacePath && stripTangyrFromMergeSurface(surfacePath, logger)) {
22906
- removedParentDirs.add(path28.dirname(surfacePath));
22926
+ removedParentDirs.add(path29.dirname(surfacePath));
22907
22927
  removedCount++;
22908
22928
  if (fs29.existsSync(surfacePath)) {
22909
22929
  keptSurfaces.push(surfacePath);
@@ -22925,7 +22945,7 @@ async function runUninstallCommand(options, logger) {
22925
22945
  for (const actualPath of paths) {
22926
22946
  if (actualPath && (fs29.existsSync(actualPath) || isSymlink(actualPath))) {
22927
22947
  removeManagedPath(actualPath);
22928
- removedParentDirs.add(path28.dirname(actualPath));
22948
+ removedParentDirs.add(path29.dirname(actualPath));
22929
22949
  logger.verbose(` removed: ${actualPath}`);
22930
22950
  removedCount++;
22931
22951
  } else {
@@ -22947,7 +22967,7 @@ async function runUninstallCommand(options, logger) {
22947
22967
  continue;
22948
22968
  }
22949
22969
  removeManagedPath(actualPath);
22950
- removedParentDirs.add(path28.dirname(actualPath));
22970
+ removedParentDirs.add(path29.dirname(actualPath));
22951
22971
  logger.verbose(` removed: ${actualPath}`);
22952
22972
  removedCount++;
22953
22973
  } else {
@@ -23004,17 +23024,17 @@ ${String(kept.length)} later backup(s) were NOT restored: the earliest copy of e
23004
23024
  " The manifest is removed below, so nothing will reference these copies afterwards. Move what you need out of the backups directory now."
23005
23025
  );
23006
23026
  }
23007
- const manifestPath = path28.join(scopePath, "manifest.json");
23027
+ const manifestPath = path29.join(scopePath, "manifest.json");
23008
23028
  if (fs29.existsSync(manifestPath)) {
23009
23029
  fs29.unlinkSync(manifestPath);
23010
23030
  logger.verbose(` removed manifest: ${manifestPath}`);
23011
23031
  }
23012
- const lossReportPath = path28.join(scopePath, DEFAULT_LOSS_REPORT_FILE);
23032
+ const lossReportPath = path29.join(scopePath, DEFAULT_LOSS_REPORT_FILE);
23013
23033
  if (fs29.existsSync(lossReportPath)) {
23014
23034
  fs29.unlinkSync(lossReportPath);
23015
23035
  logger.verbose(` removed loss report: ${lossReportPath}`);
23016
23036
  }
23017
- pruneEmptyDirs(path28.join(scopePath, "backups"), logger);
23037
+ pruneEmptyDirs(path29.join(scopePath, "backups"), logger);
23018
23038
  try {
23019
23039
  const remaining = fs29.readdirSync(scopePath);
23020
23040
  if (remaining.length === 0) {
@@ -23037,7 +23057,7 @@ ${String(kept.length)} later backup(s) were NOT restored: the earliest copy of e
23037
23057
  } else {
23038
23058
  logger.verbose(" no manifest to update after partial residue cleanup");
23039
23059
  }
23040
- const pruneBoundary = path28.dirname(scopePath);
23060
+ const pruneBoundary = path29.dirname(scopePath);
23041
23061
  for (const dir of removedParentDirs) {
23042
23062
  pruneEmptyAncestors2(dir, pruneBoundary, logger);
23043
23063
  }
@@ -23088,32 +23108,32 @@ function resolveManifestKeyToPath(key, scope, runtime, projectRootOverride) {
23088
23108
  if (!slotPath) {
23089
23109
  return null;
23090
23110
  }
23091
- return subPath ? path28.join(slotPath, subPath) : slotPath;
23111
+ return subPath ? path29.join(slotPath, subPath) : slotPath;
23092
23112
  }
23093
23113
  if (tool === "copilot") {
23094
23114
  const copilotPaths = resolveCopilotPaths(runtime, scope, projectRoot);
23095
23115
  if (component.startsWith("skills/")) {
23096
- return path28.join(copilotPaths.skills, component.slice("skills/".length));
23116
+ return path29.join(copilotPaths.skills, component.slice("skills/".length));
23097
23117
  }
23098
23118
  if (component === "skills") {
23099
23119
  return copilotPaths.skills;
23100
23120
  }
23101
23121
  if (component.startsWith("agents/")) {
23102
- return path28.join(copilotPaths.agents, component.slice("agents/".length));
23122
+ return path29.join(copilotPaths.agents, component.slice("agents/".length));
23103
23123
  }
23104
23124
  if (component.startsWith("prompts/")) {
23105
- return path28.join(
23125
+ return path29.join(
23106
23126
  copilotPaths.prompts,
23107
23127
  component.slice("prompts/".length)
23108
23128
  );
23109
23129
  }
23110
23130
  if (component.startsWith("hooks/")) {
23111
- return path28.join(copilotPaths.hooks, component.slice("hooks/".length));
23131
+ return path29.join(copilotPaths.hooks, component.slice("hooks/".length));
23112
23132
  }
23113
- if (component === path28.basename(copilotPaths.mcpSharedFile)) {
23133
+ if (component === path29.basename(copilotPaths.mcpSharedFile)) {
23114
23134
  return copilotPaths.mcpSharedFile;
23115
23135
  }
23116
- if (copilotPaths.instructions !== null && component === path28.basename(copilotPaths.instructions)) {
23136
+ if (copilotPaths.instructions !== null && component === path29.basename(copilotPaths.instructions)) {
23117
23137
  return copilotPaths.instructions;
23118
23138
  }
23119
23139
  return null;
@@ -23127,15 +23147,15 @@ function resolveManifestKeyToPath(key, scope, runtime, projectRootOverride) {
23127
23147
  return codexPaths.skills;
23128
23148
  }
23129
23149
  if (component.startsWith("agents/")) {
23130
- return path28.join(codexPaths.agents, component.slice("agents/".length));
23150
+ return path29.join(codexPaths.agents, component.slice("agents/".length));
23131
23151
  }
23132
23152
  if (component.startsWith("rules/")) {
23133
- return path28.join(codexPaths.rules, component.slice("rules/".length));
23153
+ return path29.join(codexPaths.rules, component.slice("rules/".length));
23134
23154
  }
23135
- if (component === path28.basename(codexPaths.hooksSharedFile)) {
23155
+ if (component === path29.basename(codexPaths.hooksSharedFile)) {
23136
23156
  return codexPaths.hooksSharedFile;
23137
23157
  }
23138
- if (component === path28.basename(codexPaths.mcpSharedFile)) {
23158
+ if (component === path29.basename(codexPaths.mcpSharedFile)) {
23139
23159
  return codexPaths.mcpSharedFile;
23140
23160
  }
23141
23161
  return null;
@@ -23152,15 +23172,15 @@ function resolveManifestKeyToPath(key, scope, runtime, projectRootOverride) {
23152
23172
  return opencodePaths.skillsShared;
23153
23173
  }
23154
23174
  if (component.startsWith("agents/")) {
23155
- return path28.join(opencodePaths.agents, component.slice("agents/".length));
23175
+ return path29.join(opencodePaths.agents, component.slice("agents/".length));
23156
23176
  }
23157
23177
  if (component.startsWith("commands/")) {
23158
- return path28.join(
23178
+ return path29.join(
23159
23179
  opencodePaths.commands,
23160
23180
  component.slice("commands/".length)
23161
23181
  );
23162
23182
  }
23163
- if (component === path28.basename(opencodePaths.configDoc)) {
23183
+ if (component === path29.basename(opencodePaths.configDoc)) {
23164
23184
  return opencodePaths.configDoc;
23165
23185
  }
23166
23186
  return null;
@@ -23186,13 +23206,13 @@ function resolveManifestKeyToPath(key, scope, runtime, projectRootOverride) {
23186
23206
  return cursorPaths.permissionsFile;
23187
23207
  }
23188
23208
  if (component.startsWith("agents/")) {
23189
- return path28.join(cursorPaths.agents, component.slice("agents/".length));
23209
+ return path29.join(cursorPaths.agents, component.slice("agents/".length));
23190
23210
  }
23191
23211
  if (component.startsWith("rules/")) {
23192
- return path28.join(cursorPaths.rules, component.slice("rules/".length));
23212
+ return path29.join(cursorPaths.rules, component.slice("rules/".length));
23193
23213
  }
23194
23214
  if (component.startsWith("skills/")) {
23195
- return path28.join(cursorPaths.skills, component.slice("skills/".length));
23215
+ return path29.join(cursorPaths.skills, component.slice("skills/".length));
23196
23216
  }
23197
23217
  return null;
23198
23218
  }
@@ -23208,10 +23228,10 @@ function resolveManifestKeyToPath(key, scope, runtime, projectRootOverride) {
23208
23228
  return clinePaths.mcpFile;
23209
23229
  }
23210
23230
  if (component.startsWith("rules/")) {
23211
- return path28.join(clinePaths.rules, component.slice("rules/".length));
23231
+ return path29.join(clinePaths.rules, component.slice("rules/".length));
23212
23232
  }
23213
23233
  if (component.startsWith("workflows/")) {
23214
- return path28.join(
23234
+ return path29.join(
23215
23235
  clinePaths.workflows,
23216
23236
  component.slice("workflows/".length)
23217
23237
  );
@@ -23245,22 +23265,22 @@ function resolveClaudeCodePaths(runtime, scope, projectRoot) {
23245
23265
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
23246
23266
  if (scope === "global") {
23247
23267
  return {
23248
- instructions: path28.join(home, ".claude", "CLAUDE.md"),
23249
- agents: path28.join(home, ".claude", "agents"),
23250
- skills: path28.join(home, ".claude", "skills"),
23251
- commands: path28.join(home, ".claude", "commands"),
23252
- rules: path28.join(home, ".claude", "rules"),
23253
- output_styles: path28.join(home, ".claude", "output-styles")
23268
+ instructions: path29.join(home, ".claude", "CLAUDE.md"),
23269
+ agents: path29.join(home, ".claude", "agents"),
23270
+ skills: path29.join(home, ".claude", "skills"),
23271
+ commands: path29.join(home, ".claude", "commands"),
23272
+ rules: path29.join(home, ".claude", "rules"),
23273
+ output_styles: path29.join(home, ".claude", "output-styles")
23254
23274
  };
23255
23275
  }
23256
23276
  const root = projectRoot ?? process.cwd();
23257
23277
  return {
23258
- instructions: path28.join(root, "CLAUDE.md"),
23259
- agents: path28.join(root, ".claude", "agents"),
23260
- skills: path28.join(root, ".claude", "skills"),
23261
- commands: path28.join(root, ".claude", "commands"),
23262
- rules: path28.join(root, ".claude", "rules"),
23263
- output_styles: path28.join(root, ".claude", "output-styles")
23278
+ instructions: path29.join(root, "CLAUDE.md"),
23279
+ agents: path29.join(root, ".claude", "agents"),
23280
+ skills: path29.join(root, ".claude", "skills"),
23281
+ commands: path29.join(root, ".claude", "commands"),
23282
+ rules: path29.join(root, ".claude", "rules"),
23283
+ output_styles: path29.join(root, ".claude", "output-styles")
23264
23284
  };
23265
23285
  }
23266
23286
  function resolveClaudeRootsForUninstall(manifest, runtime) {
@@ -23279,12 +23299,12 @@ function resolveClaudeRootsForUninstall(manifest, runtime) {
23279
23299
  projectRoot: void 0,
23280
23300
  mappings: mappings.platformPaths
23281
23301
  })["claude-code"];
23282
- return [path28.dirname(profile.agents)];
23302
+ return [path29.dirname(profile.agents)];
23283
23303
  } catch {
23284
23304
  }
23285
23305
  }
23286
23306
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
23287
- return [path28.resolve(expandHome(`${home}/.claude`))];
23307
+ return [path29.resolve(expandHome(`${home}/.claude`))];
23288
23308
  }
23289
23309
  function resolveAllClaudeRoots(manifest, runtime, claudeConfigDirs) {
23290
23310
  const home = process.env.HOME ?? process.env.USERPROFILE;
@@ -23296,13 +23316,13 @@ function resolveAllClaudeRoots(manifest, runtime, claudeConfigDirs) {
23296
23316
  env: process.env.TANGYR_CLAUDE_CONFIG_DIRS,
23297
23317
  config: runtime.config.claudeCodeGlobalPaths
23298
23318
  })
23299
- ].map((root) => path28.resolve(root))
23319
+ ].map((root) => path29.resolve(root))
23300
23320
  );
23301
23321
  if (home && fs29.existsSync(home)) {
23302
23322
  try {
23303
23323
  for (const entry of fs29.readdirSync(home, { withFileTypes: true })) {
23304
23324
  if (entry.isDirectory() && entry.name.startsWith(".claude-")) {
23305
- roots.add(path28.resolve(home, entry.name));
23325
+ roots.add(path29.resolve(home, entry.name));
23306
23326
  }
23307
23327
  }
23308
23328
  } catch {
@@ -23321,13 +23341,13 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
23321
23341
  const rootsToResolve = isShared ? [claudeRoots[0]] : claudeRoots;
23322
23342
  if (!runtime) {
23323
23343
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
23324
- const defaultRoot = path28.resolve(expandHome(`${home}/.claude`));
23344
+ const defaultRoot = path29.resolve(expandHome(`${home}/.claude`));
23325
23345
  return rootsToResolve.flatMap((root) => {
23326
23346
  const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
23327
23347
  if (!hardcoded) {
23328
23348
  return [];
23329
23349
  }
23330
- return [subPath ? path28.join(hardcoded, subPath) : hardcoded];
23350
+ return [subPath ? path29.join(hardcoded, subPath) : hardcoded];
23331
23351
  });
23332
23352
  }
23333
23353
  try {
@@ -23345,17 +23365,17 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
23345
23365
  if (!slotPath) {
23346
23366
  return [];
23347
23367
  }
23348
- return [subPath ? path28.join(slotPath, subPath) : slotPath];
23368
+ return [subPath ? path29.join(slotPath, subPath) : slotPath];
23349
23369
  });
23350
23370
  } catch {
23351
23371
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
23352
- const defaultRoot = path28.resolve(expandHome(`${home}/.claude`));
23372
+ const defaultRoot = path29.resolve(expandHome(`${home}/.claude`));
23353
23373
  return rootsToResolve.flatMap((root) => {
23354
23374
  const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
23355
23375
  if (!hardcoded) {
23356
23376
  return [];
23357
23377
  }
23358
- return [subPath ? path28.join(hardcoded, subPath) : hardcoded];
23378
+ return [subPath ? path29.join(hardcoded, subPath) : hardcoded];
23359
23379
  });
23360
23380
  }
23361
23381
  }
@@ -23380,9 +23400,9 @@ function resolveHardcodedClaudeSlot(root, defaultRoot, slotName) {
23380
23400
  return null;
23381
23401
  }
23382
23402
  if (root === defaultRoot) {
23383
- return path28.join(root, relative);
23403
+ return path29.join(root, relative);
23384
23404
  }
23385
- return path28.join(root, relative);
23405
+ return path29.join(root, relative);
23386
23406
  }
23387
23407
  function resolveRuntimeIfAvailable(options, logger) {
23388
23408
  try {
@@ -23454,9 +23474,9 @@ function stripTangyrFromMergeSurface(filePath, logger) {
23454
23474
  return true;
23455
23475
  }
23456
23476
  function pruneEmptyAncestors2(startDir, stopAt, logger) {
23457
- const boundary = path28.resolve(stopAt);
23458
- let current = path28.resolve(startDir);
23459
- while (current !== boundary && current.startsWith(`${boundary}${path28.sep}`)) {
23477
+ const boundary = path29.resolve(stopAt);
23478
+ let current = path29.resolve(startDir);
23479
+ while (current !== boundary && current.startsWith(`${boundary}${path29.sep}`)) {
23460
23480
  try {
23461
23481
  if (fs29.readdirSync(current).length > 0) {
23462
23482
  return;
@@ -23466,7 +23486,7 @@ function pruneEmptyAncestors2(startDir, stopAt, logger) {
23466
23486
  } catch {
23467
23487
  return;
23468
23488
  }
23469
- current = path28.dirname(current);
23489
+ current = path29.dirname(current);
23470
23490
  }
23471
23491
  }
23472
23492
  function pruneEmptyDirs(dir, logger) {
@@ -23481,7 +23501,7 @@ function pruneEmptyDirs(dir, logger) {
23481
23501
  }
23482
23502
  for (const entry of fs29.readdirSync(dir, { withFileTypes: true })) {
23483
23503
  if (entry.isDirectory() && !entry.isSymbolicLink()) {
23484
- pruneEmptyDirs(path28.join(dir, entry.name), logger);
23504
+ pruneEmptyDirs(path29.join(dir, entry.name), logger);
23485
23505
  }
23486
23506
  }
23487
23507
  try {
@@ -23506,9 +23526,9 @@ function sharedSurfaceFor(manifest, file, selectedTools, scope, runtime, project
23506
23526
  if (!artifactPath) {
23507
23527
  return null;
23508
23528
  }
23509
- const resolved = path28.resolve(artifactPath);
23529
+ const resolved = path29.resolve(artifactPath);
23510
23530
  return records.find(
23511
- (record) => path28.resolve(record.path) === resolved && selectedTools.has(record.tool)
23531
+ (record) => path29.resolve(record.path) === resolved && selectedTools.has(record.tool)
23512
23532
  ) ?? null;
23513
23533
  }
23514
23534
  function revertSharedSurface(record, logger) {
@@ -23589,7 +23609,7 @@ function addManagedSymlinkChildren(artifacts, directory, runtime, component) {
23589
23609
  return;
23590
23610
  }
23591
23611
  for (const entry of entries) {
23592
- const artifactPath = path28.join(directory, entry.name);
23612
+ const artifactPath = path29.join(directory, entry.name);
23593
23613
  const artifactClass = classifyArtifact(
23594
23614
  artifactPath,
23595
23615
  runtime.config,
@@ -23628,8 +23648,8 @@ function collectStringValuesByKey(value, keyName, values) {
23628
23648
  }
23629
23649
  function addLegacyOperatingGuideCopies(artifacts, claudeRoot) {
23630
23650
  for (const artifactPath of [
23631
- ...ts(path28.join(claudeRoot, "CLAUDE.md.bak.*")),
23632
- ...ts(path28.join(claudeRoot, "AGENTS.md.bak.*"))
23651
+ ...ts(path29.join(claudeRoot, "CLAUDE.md.bak.*")),
23652
+ ...ts(path29.join(claudeRoot, "AGENTS.md.bak.*"))
23633
23653
  ].sort()) {
23634
23654
  artifacts.push({
23635
23655
  component: "claude-code legacy operating guide backup",
@@ -23683,7 +23703,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23683
23703
  for (const skill of runtime.kitInfo.components.skills.declared) {
23684
23704
  artifacts.push({
23685
23705
  component: "claude-code skill",
23686
- path: path28.join(profile.skills, skill),
23706
+ path: path29.join(profile.skills, skill),
23687
23707
  kind: "direct"
23688
23708
  });
23689
23709
  }
@@ -23702,7 +23722,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23702
23722
  if (isFullToolUninstall(manifest, selectedTools)) {
23703
23723
  addLegacyOperatingGuideCopies(
23704
23724
  artifacts,
23705
- path28.dirname(profile.instructions)
23725
+ path29.dirname(profile.instructions)
23706
23726
  );
23707
23727
  }
23708
23728
  }
@@ -23725,20 +23745,20 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23725
23745
  if (selectedTools.has("copilot")) {
23726
23746
  addCompiledGlobPlans(
23727
23747
  artifacts,
23728
- path28.join(copilotPaths.agents, "*.agent.md"),
23748
+ path29.join(copilotPaths.agents, "*.agent.md"),
23729
23749
  "copilot",
23730
23750
  "copilot agent residue"
23731
23751
  );
23732
23752
  addCompiledGlobPlans(
23733
23753
  artifacts,
23734
- path28.join(copilotPaths.prompts, "*.prompt.md"),
23754
+ path29.join(copilotPaths.prompts, "*.prompt.md"),
23735
23755
  "copilot",
23736
23756
  "copilot prompt residue"
23737
23757
  );
23738
23758
  for (const agentEntry of runtime.kitInfo.components.agents.declared) {
23739
23759
  artifacts.push({
23740
23760
  component: "copilot agent",
23741
- path: path28.join(copilotPaths.agents, `${agentEntry}.agent.md`),
23761
+ path: path29.join(copilotPaths.agents, `${agentEntry}.agent.md`),
23742
23762
  kind: "compiled",
23743
23763
  expectedTarget: "copilot",
23744
23764
  expectedSource: `agents/${agentEntry}.md`
@@ -23747,7 +23767,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23747
23767
  for (const commandEntry of runtime.kitInfo.components.commands.declared) {
23748
23768
  artifacts.push({
23749
23769
  component: "copilot prompt",
23750
- path: path28.join(copilotPaths.prompts, `${commandEntry}.prompt.md`),
23770
+ path: path29.join(copilotPaths.prompts, `${commandEntry}.prompt.md`),
23751
23771
  kind: "compiled",
23752
23772
  expectedTarget: "copilot",
23753
23773
  expectedSource: `commands/${commandEntry}.md`
@@ -23762,7 +23782,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23762
23782
  for (const skill of runtime.kitInfo.components.skills.declared) {
23763
23783
  artifacts.push({
23764
23784
  component: "copilot skill",
23765
- path: path28.join(copilotPaths.skills, skill),
23785
+ path: path29.join(copilotPaths.skills, skill),
23766
23786
  kind: "direct"
23767
23787
  });
23768
23788
  }
@@ -23776,13 +23796,13 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23776
23796
  artifacts.push(
23777
23797
  {
23778
23798
  component: "copilot hooks",
23779
- path: path28.join(copilotPaths.hooks, "tangyr-managed.json"),
23799
+ path: path29.join(copilotPaths.hooks, "tangyr-managed.json"),
23780
23800
  kind: "managed-json",
23781
23801
  expectedTarget: "copilot"
23782
23802
  },
23783
23803
  {
23784
23804
  component: "copilot legacy hooks",
23785
- path: path28.join(copilotPaths.hooks, "proteus-managed.json"),
23805
+ path: path29.join(copilotPaths.hooks, "proteus-managed.json"),
23786
23806
  kind: "managed-json",
23787
23807
  expectedTarget: "copilot"
23788
23808
  }
@@ -23791,7 +23811,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23791
23811
  if (hooksSourceExists(runtime.sourceRoot, runtime.config)) {
23792
23812
  artifacts.push({
23793
23813
  component: "copilot hooks",
23794
- path: path28.join(copilotPaths.hooks, "tangyr-managed.json"),
23814
+ path: path29.join(copilotPaths.hooks, "tangyr-managed.json"),
23795
23815
  kind: "compiled",
23796
23816
  expectedTarget: "copilot",
23797
23817
  expectedSource: hooksSource
@@ -23821,13 +23841,13 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23821
23841
  );
23822
23842
  addCompiledGlobPlans(
23823
23843
  artifacts,
23824
- path28.join(codexPaths.agents, "*.toml"),
23844
+ path29.join(codexPaths.agents, "*.toml"),
23825
23845
  "codex",
23826
23846
  "codex agent residue"
23827
23847
  );
23828
23848
  addCompiledGlobPlans(
23829
23849
  artifacts,
23830
- path28.join(codexPaths.rules, "*.rules"),
23850
+ path29.join(codexPaths.rules, "*.rules"),
23831
23851
  "codex",
23832
23852
  "codex rule residue"
23833
23853
  );
@@ -23841,7 +23861,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23841
23861
  for (const agentEntry of runtime.kitInfo.components.agents.declared) {
23842
23862
  artifacts.push({
23843
23863
  component: "codex agent",
23844
- path: path28.join(codexPaths.agents, `${agentEntry}.toml`),
23864
+ path: path29.join(codexPaths.agents, `${agentEntry}.toml`),
23845
23865
  kind: "compiled",
23846
23866
  expectedTarget: "codex",
23847
23867
  expectedSource: `agents/${agentEntry}.md`
@@ -23850,7 +23870,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23850
23870
  for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
23851
23871
  artifacts.push({
23852
23872
  component: "codex rule",
23853
- path: path28.join(codexPaths.rules, `${ruleEntry}.rules`),
23873
+ path: path29.join(codexPaths.rules, `${ruleEntry}.rules`),
23854
23874
  kind: "compiled",
23855
23875
  expectedTarget: "codex",
23856
23876
  expectedSource: `rules/${ruleEntry}.md`
@@ -23902,13 +23922,13 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23902
23922
  );
23903
23923
  addCompiledGlobPlans(
23904
23924
  artifacts,
23905
- path28.join(opencodePaths.agents, "*.md"),
23925
+ path29.join(opencodePaths.agents, "*.md"),
23906
23926
  "opencode",
23907
23927
  "opencode agent residue"
23908
23928
  );
23909
23929
  addCompiledGlobPlans(
23910
23930
  artifacts,
23911
- path28.join(opencodePaths.commands, "*.md"),
23931
+ path29.join(opencodePaths.commands, "*.md"),
23912
23932
  "opencode",
23913
23933
  "opencode command residue"
23914
23934
  );
@@ -23927,7 +23947,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23927
23947
  for (const agentEntry of runtime.kitInfo.components.agents.declared) {
23928
23948
  artifacts.push({
23929
23949
  component: "opencode agent",
23930
- path: path28.join(opencodePaths.agents, `${agentEntry}.md`),
23950
+ path: path29.join(opencodePaths.agents, `${agentEntry}.md`),
23931
23951
  kind: "compiled",
23932
23952
  expectedTarget: "opencode",
23933
23953
  expectedSource: `agents/${agentEntry}.md`
@@ -23936,7 +23956,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23936
23956
  for (const commandEntry of runtime.kitInfo.components.commands.declared) {
23937
23957
  artifacts.push({
23938
23958
  component: "opencode command",
23939
- path: path28.join(opencodePaths.commands, `${commandEntry}.md`),
23959
+ path: path29.join(opencodePaths.commands, `${commandEntry}.md`),
23940
23960
  kind: "compiled",
23941
23961
  expectedTarget: "opencode",
23942
23962
  expectedSource: `commands/${commandEntry}.md`
@@ -23991,19 +24011,19 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
23991
24011
  );
23992
24012
  addCompiledGlobPlans(
23993
24013
  artifacts,
23994
- path28.join(cursorPaths.agents, "*.md"),
24014
+ path29.join(cursorPaths.agents, "*.md"),
23995
24015
  "cursor",
23996
24016
  "cursor agent residue"
23997
24017
  );
23998
24018
  addCompiledGlobPlans(
23999
24019
  artifacts,
24000
- path28.join(cursorPaths.rules, "*.mdc"),
24020
+ path29.join(cursorPaths.rules, "*.mdc"),
24001
24021
  "cursor",
24002
24022
  "cursor rule residue"
24003
24023
  );
24004
24024
  addCompiledGlobPlans(
24005
24025
  artifacts,
24006
- path28.join(cursorPaths.skills, "*", "SKILL.md"),
24026
+ path29.join(cursorPaths.skills, "*", "SKILL.md"),
24007
24027
  "cursor",
24008
24028
  "cursor command residue"
24009
24029
  );
@@ -24017,7 +24037,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
24017
24037
  for (const agentEntry of runtime.kitInfo.components.agents.declared) {
24018
24038
  artifacts.push({
24019
24039
  component: "cursor agent",
24020
- path: path28.join(cursorPaths.agents, `${agentEntry}.md`),
24040
+ path: path29.join(cursorPaths.agents, `${agentEntry}.md`),
24021
24041
  kind: "compiled",
24022
24042
  expectedTarget: "cursor",
24023
24043
  expectedSource: `agents/${agentEntry}.md`
@@ -24054,13 +24074,13 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
24054
24074
  );
24055
24075
  addCompiledGlobPlans(
24056
24076
  artifacts,
24057
- path28.join(clinePaths.rules, "*.md"),
24077
+ path29.join(clinePaths.rules, "*.md"),
24058
24078
  "cline",
24059
24079
  "cline rule residue"
24060
24080
  );
24061
24081
  addCompiledGlobPlans(
24062
24082
  artifacts,
24063
- path28.join(clinePaths.workflows, "*.md"),
24083
+ path29.join(clinePaths.workflows, "*.md"),
24064
24084
  "cline",
24065
24085
  "cline workflow residue"
24066
24086
  );
@@ -24088,7 +24108,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
24088
24108
  for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
24089
24109
  artifacts.push({
24090
24110
  component: "cline rule",
24091
- path: path28.join(clinePaths.rules, `${ruleEntry}.md`),
24111
+ path: path29.join(clinePaths.rules, `${ruleEntry}.md`),
24092
24112
  kind: "compiled",
24093
24113
  expectedTarget: "cline",
24094
24114
  expectedSource: `rules/${ruleEntry}.md`
@@ -24097,7 +24117,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, cla
24097
24117
  for (const commandEntry of runtime.kitInfo.components.commands.declared) {
24098
24118
  artifacts.push({
24099
24119
  component: "cline workflow",
24100
- path: path28.join(clinePaths.workflows, `${commandEntry}.md`),
24120
+ path: path29.join(clinePaths.workflows, `${commandEntry}.md`),
24101
24121
  kind: "compiled",
24102
24122
  expectedTarget: "cline",
24103
24123
  expectedSource: `commands/${commandEntry}.md`
@@ -24432,12 +24452,12 @@ function resolveCopilotPaths(runtime, scope = "global", projectRoot) {
24432
24452
  if (scope === "project") {
24433
24453
  const root = projectRoot ?? process.cwd();
24434
24454
  return {
24435
- instructions: path28.join(root, ".github", "copilot-instructions.md"),
24436
- agents: path28.join(root, ".github", "agents"),
24437
- prompts: path28.join(root, ".github", "prompts"),
24438
- skills: path28.join(root, ".github", "skills"),
24439
- hooks: path28.join(root, ".github", "hooks"),
24440
- mcpSharedFile: path28.join(root, ".vscode", "mcp.json")
24455
+ instructions: path29.join(root, ".github", "copilot-instructions.md"),
24456
+ agents: path29.join(root, ".github", "agents"),
24457
+ prompts: path29.join(root, ".github", "prompts"),
24458
+ skills: path29.join(root, ".github", "skills"),
24459
+ hooks: path29.join(root, ".github", "hooks"),
24460
+ mcpSharedFile: path29.join(root, ".vscode", "mcp.json")
24441
24461
  };
24442
24462
  }
24443
24463
  return {
@@ -24477,12 +24497,12 @@ function resolveCodexPaths(runtime, scope = "global", projectRoot) {
24477
24497
  if (scope === "project") {
24478
24498
  const root = projectRoot ?? process.cwd();
24479
24499
  return {
24480
- instructions: path28.join(root, "AGENTS.md"),
24481
- agents: path28.join(root, ".codex", "agents"),
24482
- rules: path28.join(root, ".codex", "rules"),
24483
- skills: path28.join(root, ".codex", "skills"),
24484
- hooksSharedFile: path28.join(root, ".codex", "hooks.json"),
24485
- mcpSharedFile: path28.join(root, ".codex", "config.toml")
24500
+ instructions: path29.join(root, "AGENTS.md"),
24501
+ agents: path29.join(root, ".codex", "agents"),
24502
+ rules: path29.join(root, ".codex", "rules"),
24503
+ skills: path29.join(root, ".codex", "skills"),
24504
+ hooksSharedFile: path29.join(root, ".codex", "hooks.json"),
24505
+ mcpSharedFile: path29.join(root, ".codex", "config.toml")
24486
24506
  };
24487
24507
  }
24488
24508
  return {
@@ -24511,7 +24531,7 @@ function resolveSharedHookScriptsPath(runtime, scope, projectRoot) {
24511
24531
  }
24512
24532
  }
24513
24533
  if (scope === "project") {
24514
- return path28.join(projectRoot ?? process.cwd(), ".agents", "hooks");
24534
+ return path29.join(projectRoot ?? process.cwd(), ".agents", "hooks");
24515
24535
  }
24516
24536
  return resolveTargetPath("~/.agents/hooks");
24517
24537
  }
@@ -24532,7 +24552,7 @@ function resolveSharedSkillsPath(runtime, scope, projectRoot) {
24532
24552
  }
24533
24553
  }
24534
24554
  if (scope === "project") {
24535
- return path28.join(projectRoot ?? process.cwd(), ".agents", "skills");
24555
+ return path29.join(projectRoot ?? process.cwd(), ".agents", "skills");
24536
24556
  }
24537
24557
  return resolveTargetPath("~/.agents/skills");
24538
24558
  }
@@ -24717,7 +24737,7 @@ function isKitPointer(artifact) {
24717
24737
  }
24718
24738
  try {
24719
24739
  const recordedPath = fs29.readFileSync(artifact.path, "utf8").trim();
24720
- return recordedPath.length > 0 && path28.resolve(recordedPath) === path28.resolve(artifact.expectedPath);
24740
+ return recordedPath.length > 0 && path29.resolve(recordedPath) === path29.resolve(artifact.expectedPath);
24721
24741
  } catch {
24722
24742
  return false;
24723
24743
  }
@@ -24882,7 +24902,7 @@ function restoreBackup(backup, logger) {
24882
24902
  logger.warn(` backup not found: ${backup.backupLocation}`);
24883
24903
  return;
24884
24904
  }
24885
- const destDir = path28.dirname(backup.originalPath);
24905
+ const destDir = path29.dirname(backup.originalPath);
24886
24906
  fs29.mkdirSync(destDir, { recursive: true });
24887
24907
  if (fs29.lstatSync(backup.backupLocation).isDirectory()) {
24888
24908
  fs29.cpSync(backup.backupLocation, backup.originalPath, {
@@ -25044,7 +25064,7 @@ function cleanupCopilot(config, sourceRoot, configDir, logger) {
25044
25064
  logger
25045
25065
  );
25046
25066
  removeManagedJsonFile(
25047
- path29.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
25067
+ path30.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
25048
25068
  "_tangyr",
25049
25069
  logger
25050
25070
  );
@@ -25206,7 +25226,7 @@ function removeManagedDirectPath(artifactPath, config, sourceRoot, component, lo
25206
25226
  }
25207
25227
  }
25208
25228
  function removeManagedCompiledFiles(dir, pattern, expectedTarget, logger) {
25209
- for (const filePath of ts(path29.join(dir, pattern)).sort()) {
25229
+ for (const filePath of ts(path30.join(dir, pattern)).sort()) {
25210
25230
  removeManagedCompiledFile(filePath, expectedTarget, logger);
25211
25231
  }
25212
25232
  }
@@ -25317,7 +25337,7 @@ function toVerbosity(value) {
25317
25337
  // src/commands/detect.ts
25318
25338
  import fs31 from "fs";
25319
25339
  import os5 from "os";
25320
- import path30 from "path";
25340
+ import path31 from "path";
25321
25341
  import { spawnSync } from "child_process";
25322
25342
  var copilotEditorCommands = [
25323
25343
  "code",
@@ -25449,7 +25469,7 @@ function detectEditorExtension(label, matchesExtension, logger, dependencies = {
25449
25469
  }
25450
25470
  }
25451
25471
  for (const relativeDirectory of copilotExtensionDirectories) {
25452
- const extensionDirectory = path30.join(homeDirectory, relativeDirectory);
25472
+ const extensionDirectory = path31.join(homeDirectory, relativeDirectory);
25453
25473
  if (!pathExists(extensionDirectory)) {
25454
25474
  continue;
25455
25475
  }
@@ -25472,7 +25492,7 @@ function cursorExecutablePaths(platform, homeDirectory) {
25472
25492
  }
25473
25493
  return [
25474
25494
  ...systemPaths,
25475
- path30.join(
25495
+ path31.join(
25476
25496
  homeDirectory,
25477
25497
  "Applications/Cursor.app/Contents/Resources/app/bin/cursor"
25478
25498
  )
@@ -25533,7 +25553,7 @@ function logDetectionError(attemptedCommand, error, logger) {
25533
25553
 
25534
25554
  // src/commands/doctor.ts
25535
25555
  import fs32 from "fs";
25536
- import path31 from "path";
25556
+ import path32 from "path";
25537
25557
  function runDoctorCommand(options, logger) {
25538
25558
  const { config, configDir, configPath, sourceRoot } = resolveRuntime(
25539
25559
  options,
@@ -25543,7 +25563,7 @@ function runDoctorCommand(options, logger) {
25543
25563
  if (!fs32.existsSync(configPath)) {
25544
25564
  findings.push(`${configPath}: missing`);
25545
25565
  }
25546
- const hooksJsonPath = path31.join(
25566
+ const hooksJsonPath = path32.join(
25547
25567
  sourceRoot,
25548
25568
  config.source.hooks,
25549
25569
  "hooks.json"
@@ -25619,18 +25639,18 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
25619
25639
  projectRoot
25620
25640
  )) {
25621
25641
  const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
25622
- const sourcePath = artifact.sourceKey ? path31.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
25642
+ const sourcePath = artifact.sourceKey ? path32.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
25623
25643
  if (artifactClass === "managed-stale") {
25624
25644
  findings.push(
25625
25645
  `${artifact.component}: managed stale artifact at ${artifact.path}`
25626
25646
  );
25627
25647
  if (options.fix && sourcePath && isOurStaleSymlink(
25628
25648
  artifact.path,
25629
- /* @__PURE__ */ new Set([path31.resolve(artifact.path)]),
25649
+ /* @__PURE__ */ new Set([path32.resolve(artifact.path)]),
25630
25650
  config
25631
25651
  )) {
25632
25652
  fs32.unlinkSync(artifact.path);
25633
- ensureDir(path31.dirname(artifact.path));
25653
+ ensureDir(path32.dirname(artifact.path));
25634
25654
  const symlinkType = fs32.statSync(sourcePath).isDirectory() ? "dir" : "file";
25635
25655
  createRelativeSymlink(sourcePath, artifact.path, symlinkType, {
25636
25656
  logger,
@@ -25644,8 +25664,8 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
25644
25664
  logger.info(`${artifact.component}: recreated managed symlink`);
25645
25665
  }
25646
25666
  }
25647
- if (options.fix && !fs32.existsSync(path31.dirname(artifact.path))) {
25648
- ensureDir(path31.dirname(artifact.path));
25667
+ if (options.fix && !fs32.existsSync(path32.dirname(artifact.path))) {
25668
+ ensureDir(path32.dirname(artifact.path));
25649
25669
  }
25650
25670
  checkParentWritablePath(artifact.path, artifact.component, findings);
25651
25671
  }
@@ -25667,7 +25687,7 @@ function slotsForScope2(config, sourceRoot, configDir, target, options) {
25667
25687
  });
25668
25688
  const resolved = {};
25669
25689
  for (const [slot, value] of Object.entries(projectSlots)) {
25670
- resolved[slot] = typeof value === "string" ? path31.resolve(root, value) : value;
25690
+ resolved[slot] = typeof value === "string" ? path32.resolve(root, value) : value;
25671
25691
  }
25672
25692
  return resolved;
25673
25693
  }
@@ -25687,7 +25707,7 @@ function checkCopilot(config, sourceRoot, configDir, findings, options) {
25687
25707
  continue;
25688
25708
  }
25689
25709
  const label = `copilot: ${rawPath}`;
25690
- if (key.endsWith("_shared_file") || path31.extname(rawPath).length > 0) {
25710
+ if (key.endsWith("_shared_file") || path32.extname(rawPath).length > 0) {
25691
25711
  checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
25692
25712
  continue;
25693
25713
  }
@@ -25713,7 +25733,7 @@ function checkCodex(config, sourceRoot, configDir, findings, logger, options) {
25713
25733
  continue;
25714
25734
  }
25715
25735
  const label = `codex: ${rawPath}`;
25716
- if (key.endsWith("_shared_file") || path31.extname(rawPath).length > 0) {
25736
+ if (key.endsWith("_shared_file") || path32.extname(rawPath).length > 0) {
25717
25737
  checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
25718
25738
  continue;
25719
25739
  }
@@ -25730,13 +25750,13 @@ function resolveHooksScriptPath(config, sourceRoot, configDir) {
25730
25750
  scope: "global",
25731
25751
  mappings: mappings.platformPaths
25732
25752
  });
25733
- return path31.join(profile["claude-code"].hooks, "scripts");
25753
+ return path32.join(profile["claude-code"].hooks, "scripts");
25734
25754
  } catch {
25735
25755
  return resolveTargetPath("~/.agents/hooks/scripts");
25736
25756
  }
25737
25757
  }
25738
25758
  function checkParentWritablePath(targetPath, label, findings) {
25739
- checkWritablePath(path31.dirname(targetPath), `${label} parent`, findings);
25759
+ checkWritablePath(path32.dirname(targetPath), `${label} parent`, findings);
25740
25760
  }
25741
25761
  function checkWritablePath(checkPath, label, findings) {
25742
25762
  if (!fs32.existsSync(checkPath)) {
@@ -25753,7 +25773,7 @@ function walkHookScripts(dir) {
25753
25773
  if (!fs32.existsSync(dir)) {
25754
25774
  return [];
25755
25775
  }
25756
- return fs32.readdirSync(dir).map((entry) => path31.join(dir, entry)).filter((entryPath) => fs32.statSync(entryPath).isFile());
25776
+ return fs32.readdirSync(dir).map((entry) => path32.join(dir, entry)).filter((entryPath) => fs32.statSync(entryPath).isFile());
25757
25777
  }
25758
25778
  function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
25759
25779
  if (!fs32.existsSync(scriptRoot)) {
@@ -25770,16 +25790,16 @@ function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
25770
25790
  }
25771
25791
  }
25772
25792
  function hasSymlinkAncestor(targetPath, stopAt) {
25773
- const relative = path31.relative(
25774
- path31.resolve(stopAt),
25775
- path31.resolve(targetPath)
25793
+ const relative = path32.relative(
25794
+ path32.resolve(stopAt),
25795
+ path32.resolve(targetPath)
25776
25796
  );
25777
- if (relative.startsWith("..") || path31.isAbsolute(relative)) {
25797
+ if (relative.startsWith("..") || path32.isAbsolute(relative)) {
25778
25798
  return false;
25779
25799
  }
25780
- return relative.split(path31.sep).some((_segment, index, segments) => {
25781
- const candidate = path31.join(
25782
- path31.resolve(stopAt),
25800
+ return relative.split(path32.sep).some((_segment, index, segments) => {
25801
+ const candidate = path32.join(
25802
+ path32.resolve(stopAt),
25783
25803
  ...segments.slice(0, index + 1)
25784
25804
  );
25785
25805
  try {
@@ -25790,8 +25810,8 @@ function hasSymlinkAncestor(targetPath, stopAt) {
25790
25810
  });
25791
25811
  }
25792
25812
  function isInside(childPath, parentPath) {
25793
- const relative = path31.relative(parentPath, childPath);
25794
- return relative.length === 0 || !relative.startsWith("..") && !path31.isAbsolute(relative);
25813
+ const relative = path32.relative(parentPath, childPath);
25814
+ return relative.length === 0 || !relative.startsWith("..") && !path32.isAbsolute(relative);
25795
25815
  }
25796
25816
  function realPathOrInput2(filePath) {
25797
25817
  try {
@@ -25803,12 +25823,12 @@ function realPathOrInput2(filePath) {
25803
25823
 
25804
25824
  // src/commands/init.ts
25805
25825
  import fs33 from "fs";
25806
- import path32 from "path";
25826
+ import path33 from "path";
25807
25827
  var import_yaml7 = __toESM(require_dist(), 1);
25808
25828
  async function runInitCommand(_options, logger) {
25809
25829
  const sourceRoot = await dist_default6({
25810
25830
  message: "Canonical Tangyr kit root",
25811
- default: path32.resolve("projects/tangyr/agent-coding")
25831
+ default: path33.resolve("projects/tangyr/agent-coding")
25812
25832
  });
25813
25833
  const componentCount = [
25814
25834
  "CLAUDE.md",
@@ -25818,7 +25838,7 @@ async function runInitCommand(_options, logger) {
25818
25838
  "rules",
25819
25839
  "hooks"
25820
25840
  ].filter(
25821
- (relativePath) => fs33.existsSync(path32.join(sourceRoot, relativePath))
25841
+ (relativePath) => fs33.existsSync(path33.join(sourceRoot, relativePath))
25822
25842
  ).length;
25823
25843
  const detectedTargets = detectTargets(logger);
25824
25844
  const enabledTargets = await dist_default4({
@@ -25838,7 +25858,7 @@ async function runInitCommand(_options, logger) {
25838
25858
  value
25839
25859
  }))
25840
25860
  });
25841
- const configPath = path32.join(sourceRoot, "tangyr.config.yaml");
25861
+ const configPath = path33.join(sourceRoot, "tangyr.config.yaml");
25842
25862
  if (fs33.existsSync(configPath)) {
25843
25863
  const overwrite = await dist_default5({
25844
25864
  message: `${configPath} exists. Overwrite?`,
@@ -25893,14 +25913,14 @@ function toConflictPolicy2(value) {
25893
25913
 
25894
25914
  // src/commands/install.ts
25895
25915
  import fs47 from "fs";
25896
- import path49 from "path";
25916
+ import path50 from "path";
25897
25917
 
25898
25918
  // src/core/channel-state.ts
25899
25919
  import fs34 from "fs";
25900
- import path33 from "path";
25920
+ import path34 from "path";
25901
25921
  var CHANNEL_STATE_FILENAME = ".tangyr-channels.json";
25902
25922
  function stateFilePath(cacheRoot) {
25903
- return path33.join(cacheRoot, CHANNEL_STATE_FILENAME);
25923
+ return path34.join(cacheRoot, CHANNEL_STATE_FILENAME);
25904
25924
  }
25905
25925
  function channelKey(kit, channel) {
25906
25926
  return `${kit}/${channel}`;
@@ -25956,7 +25976,7 @@ function writeChannelSequence(params) {
25956
25976
  [key]: { sequence, version, seenAt: now.toISOString() }
25957
25977
  };
25958
25978
  const filePath = stateFilePath(cacheRoot);
25959
- fs34.mkdirSync(path33.dirname(filePath), { recursive: true, mode: 448 });
25979
+ fs34.mkdirSync(path34.dirname(filePath), { recursive: true, mode: 448 });
25960
25980
  const tempPath = `${filePath}.${process.pid}.tmp`;
25961
25981
  fs34.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
25962
25982
  `, {
@@ -25979,7 +25999,7 @@ var DEFAULT_CHANNEL = "stable";
25979
25999
 
25980
26000
  // src/core/materialize.ts
25981
26001
  import fs35 from "fs";
25982
- import path34 from "path";
26002
+ import path35 from "path";
25983
26003
 
25984
26004
  // src/core/integrity.ts
25985
26005
  import crypto3 from "crypto";
@@ -26315,7 +26335,7 @@ function assertFileWithinCeiling(entryPath, byteLength) {
26315
26335
  }
26316
26336
  var WINDOWS_DRIVE_ABSOLUTE = /^[a-zA-Z]:[\\/]/u;
26317
26337
  function sanitizeBundleFilePath(entryPath, stagingDir) {
26318
- if (path34.isAbsolute(entryPath) || WINDOWS_DRIVE_ABSOLUTE.test(entryPath)) {
26338
+ if (path35.isAbsolute(entryPath) || WINDOWS_DRIVE_ABSOLUTE.test(entryPath)) {
26319
26339
  throw new IntegrityError(
26320
26340
  `Bundle file path "${entryPath}" is absolute \u2014 every file inside a bundle must use a relative path (REQ-INT-004).`
26321
26341
  );
@@ -26331,13 +26351,13 @@ function sanitizeBundleFilePath(entryPath, stagingDir) {
26331
26351
  `Bundle file path "${entryPath}" contains a ".." segment \u2014 directory traversal is rejected (REQ-INT-004).`
26332
26352
  );
26333
26353
  }
26334
- const resolved = path34.resolve(stagingDir, entryPath);
26354
+ const resolved = path35.resolve(stagingDir, entryPath);
26335
26355
  if (resolved === stagingDir) {
26336
26356
  throw new IntegrityError(
26337
26357
  `Bundle file path "${entryPath}" resolves to the staging directory itself \u2014 every entry must be a file inside it (REQ-INT-004).`
26338
26358
  );
26339
26359
  }
26340
- if (!resolved.startsWith(stagingDir + path34.sep)) {
26360
+ if (!resolved.startsWith(stagingDir + path35.sep)) {
26341
26361
  throw new IntegrityError(
26342
26362
  `Bundle file path "${entryPath}" escapes the staging directory \u2014 refusing to write (REQ-INT-004).`
26343
26363
  );
@@ -26389,7 +26409,7 @@ function verifyBundleFileHashes(bundle) {
26389
26409
  function writeStagedFiles(stagingDir, decoded) {
26390
26410
  for (const [rawPath, bytes] of decoded) {
26391
26411
  const target = sanitizeBundleFilePath(rawPath, stagingDir);
26392
- fs35.mkdirSync(path34.dirname(target), { recursive: true, mode: 448 });
26412
+ fs35.mkdirSync(path35.dirname(target), { recursive: true, mode: 448 });
26393
26413
  let existingStat;
26394
26414
  try {
26395
26415
  existingStat = fs35.lstatSync(target);
@@ -26801,7 +26821,7 @@ function sleep(ms2) {
26801
26821
 
26802
26822
  // src/core/kit-coverage.ts
26803
26823
  import fs36 from "fs";
26804
- import path35 from "path";
26824
+ import path36 from "path";
26805
26825
  var COVERED_CATEGORIES = [
26806
26826
  "agents",
26807
26827
  "commands",
@@ -26859,35 +26879,35 @@ function deliveredPaths(manifest, outcomes = []) {
26859
26879
  const delivered = /* @__PURE__ */ new Set();
26860
26880
  for (const artifact of manifest?.artifacts ?? []) {
26861
26881
  if (artifact.path) {
26862
- delivered.add(path35.resolve(artifact.path));
26882
+ delivered.add(path36.resolve(artifact.path));
26863
26883
  }
26864
26884
  }
26865
26885
  for (const link of manifest?.managedLinks ?? []) {
26866
26886
  if (link.path) {
26867
- delivered.add(path35.resolve(link.path));
26887
+ delivered.add(path36.resolve(link.path));
26868
26888
  }
26869
26889
  }
26870
26890
  for (const outcome of outcomes) {
26871
26891
  if (outcome.status === "success" || outcome.status === "skipped-current") {
26872
- delivered.add(path35.resolve(outcome.path));
26892
+ delivered.add(path36.resolve(outcome.path));
26873
26893
  }
26874
26894
  }
26875
26895
  return delivered;
26876
26896
  }
26877
26897
  function wasDelivered(candidate, delivered) {
26878
- const resolved = path35.resolve(candidate);
26898
+ const resolved = path36.resolve(candidate);
26879
26899
  let current = resolved;
26880
26900
  for (; ; ) {
26881
26901
  if (delivered.has(current)) {
26882
26902
  return true;
26883
26903
  }
26884
- const parent = path35.dirname(current);
26904
+ const parent = path36.dirname(current);
26885
26905
  if (parent === current) {
26886
26906
  break;
26887
26907
  }
26888
26908
  current = parent;
26889
26909
  }
26890
- const prefix = `${resolved}${path35.sep}`;
26910
+ const prefix = `${resolved}${path36.sep}`;
26891
26911
  for (const one of delivered) {
26892
26912
  if (one.startsWith(prefix)) {
26893
26913
  return true;
@@ -26923,12 +26943,12 @@ function inSlot(slotPath, name, delivered) {
26923
26943
  );
26924
26944
  if (named.length > 0) {
26925
26945
  return named.some(
26926
- (entry) => wasDelivered(path35.join(slotPath, entry), delivered)
26946
+ (entry) => wasDelivered(path36.join(slotPath, entry), delivered)
26927
26947
  ) ? true : null;
26928
26948
  }
26929
26949
  let found2 = false;
26930
26950
  for (const entry of entries) {
26931
- const full = path35.join(slotPath, entry);
26951
+ const full = path36.join(slotPath, entry);
26932
26952
  try {
26933
26953
  if (!fs36.statSync(full).isFile()) {
26934
26954
  continue;
@@ -27038,7 +27058,7 @@ function explain(target, category, surfaces, hasSurface, contestedByPath, lossRe
27038
27058
  return `${displacedByName.join(", ")}: a file of that name is in ${where}, and this installation did not write it \u2014 the kit's version is not there`;
27039
27059
  }
27040
27060
  if (FOLDS_INTO_INSTRUCTIONS.has(category) && surfaces.instructions) {
27041
- const contested = contestedByPath.get(path35.resolve(surfaces.instructions));
27061
+ const contested = contestedByPath.get(path36.resolve(surfaces.instructions));
27042
27062
  if (contested && contested.survivor !== null && contested.survivor !== target) {
27043
27063
  return `folded into ${display(surfaces.instructions, projectRoot)}, which ${contested.survivor} wrote last`;
27044
27064
  }
@@ -27054,7 +27074,7 @@ function display(target, projectRoot) {
27054
27074
  if (!projectRoot) {
27055
27075
  return target;
27056
27076
  }
27057
- const relative = path35.relative(projectRoot, target);
27077
+ const relative = path36.relative(projectRoot, target);
27058
27078
  return relative.startsWith("..") ? target : relative;
27059
27079
  }
27060
27080
  function reportKitCoverage(coverage, logger) {
@@ -27132,7 +27152,7 @@ function declaredComponents(kit) {
27132
27152
 
27133
27153
  // src/adapters/claude-code.ts
27134
27154
  import fs39 from "fs";
27135
- import path39 from "path";
27155
+ import path40 from "path";
27136
27156
 
27137
27157
  // src/core/shim.ts
27138
27158
  import crypto4 from "crypto";
@@ -27155,7 +27175,7 @@ ${SHIM_BODY}`;
27155
27175
 
27156
27176
  // src/core/skills-slot.ts
27157
27177
  import fs37 from "fs";
27158
- import path36 from "path";
27178
+ import path37 from "path";
27159
27179
  function isForeignSkillsSlotSymlink(destination, config, sourceRoot, source) {
27160
27180
  if (!isSymlinkPath(destination)) {
27161
27181
  return false;
@@ -27196,7 +27216,7 @@ function syncSkillsSlot(sync) {
27196
27216
  if (isLegacyWholesaleSymlink) {
27197
27217
  for (const name of foreignSkillNames(source, declaredNames)) {
27198
27218
  logger.info(
27199
- `[dry-run] skills: migrate foreign skill ${path36.join(source, name)} -> ${path36.join(destination, name)}`
27219
+ `[dry-run] skills: migrate foreign skill ${path37.join(source, name)} -> ${path37.join(destination, name)}`
27200
27220
  );
27201
27221
  }
27202
27222
  logger.info(
@@ -27204,9 +27224,9 @@ function syncSkillsSlot(sync) {
27204
27224
  );
27205
27225
  }
27206
27226
  for (const name of declaredNames ?? listSkillDirNames(source)) {
27207
- const skillDestination = path36.join(destination, name);
27227
+ const skillDestination = path37.join(destination, name);
27208
27228
  logger.info(
27209
- `[dry-run] skills: symlink ${path36.join(source, name)} -> ${skillDestination}`
27229
+ `[dry-run] skills: symlink ${path37.join(source, name)} -> ${skillDestination}`
27210
27230
  );
27211
27231
  outcomes2.push({
27212
27232
  component: "skills",
@@ -27233,8 +27253,8 @@ function syncSkillsSlot(sync) {
27233
27253
  }
27234
27254
  function syncSingleSkill(sync, name) {
27235
27255
  const { config, sourceRoot, source, destination } = sync;
27236
- const skillSource = path36.join(source, name);
27237
- const skillDestination = path36.join(destination, name);
27256
+ const skillSource = path37.join(source, name);
27257
+ const skillDestination = path37.join(destination, name);
27238
27258
  if (!fs37.existsSync(skillSource)) {
27239
27259
  return {
27240
27260
  component: "skills",
@@ -27265,8 +27285,8 @@ function migrateWholesaleSkillsSymlink(source, destination, declaredNames, logge
27265
27285
  fs37.unlinkSync(destination);
27266
27286
  ensureDir(destination);
27267
27287
  for (const name of foreignNames) {
27268
- const from = path36.join(source, name);
27269
- const to = path36.join(destination, name);
27288
+ const from = path37.join(source, name);
27289
+ const to = path37.join(destination, name);
27270
27290
  if (fs37.existsSync(to)) {
27271
27291
  logger.warn(
27272
27292
  `skills migration: ${to} already exists \u2014 skipping ${from} to avoid overwrite. Nothing in the kit was changed.`
@@ -27308,23 +27328,23 @@ function isSymlinkTo2(linkPath, source) {
27308
27328
  }
27309
27329
 
27310
27330
  // src/core/hook-scripts.ts
27311
- import path37 from "path";
27331
+ import path38 from "path";
27312
27332
  function hookScriptsDir(bridge, target, projectRoot) {
27313
27333
  const globalBridge = resolveTargetPath("~/.agents/hooks");
27314
- if (path37.resolve(bridge) === path37.resolve(globalBridge)) {
27334
+ if (path38.resolve(bridge) === path38.resolve(globalBridge)) {
27315
27335
  return { prefix: GLOBAL_HOOK_SCRIPTS_DIR, machineLocal: false };
27316
27336
  }
27317
- const relative = path37.relative(projectRoot ?? process.cwd(), bridge);
27318
- const insideProject = !relative.startsWith("..") && !path37.isAbsolute(relative) && relative !== "";
27337
+ const relative = path38.relative(projectRoot ?? process.cwd(), bridge);
27338
+ const insideProject = !relative.startsWith("..") && !path38.isAbsolute(relative) && relative !== "";
27319
27339
  const variable = PROJECT_DIR_VARIABLE[target];
27320
27340
  if (insideProject && variable) {
27321
- const posix = path37.posix.join(
27322
- relative.split(path37.sep).join("/"),
27341
+ const posix = path38.posix.join(
27342
+ relative.split(path38.sep).join("/"),
27323
27343
  "scripts"
27324
27344
  );
27325
27345
  return { prefix: `$${variable.slice(1)}/${posix}`, machineLocal: false };
27326
27346
  }
27327
- return { prefix: path37.join(bridge, "scripts"), machineLocal: true };
27347
+ return { prefix: path38.join(bridge, "scripts"), machineLocal: true };
27328
27348
  }
27329
27349
  var PROJECT_DIR_VARIABLE = {
27330
27350
  "claude-code": "$CLAUDE_PROJECT_DIR"
@@ -27335,18 +27355,18 @@ function machineLocalScriptPathNotice(target, prefix) {
27335
27355
 
27336
27356
  // src/core/instructions-source.ts
27337
27357
  import fs38 from "fs";
27338
- import path38 from "path";
27358
+ import path39 from "path";
27339
27359
  var PORTABLE_INSTRUCTIONS_NAME = "AGENTS.md";
27340
27360
  var InstructionsSourceMissingError = class extends Error {
27341
27361
  constructor(kitRoot, expected, declaredBy) {
27342
27362
  super(
27343
- `${path38.join(kitRoot, expected)}: instructions source not found (declared by ${declaredBy}). To fix: create that file, or point '${declaredBy}' at the file this kit actually carries. With neither declaration, the kit's ${DEFAULT_ENTRYPOINT} or ${PORTABLE_INSTRUCTIONS_NAME} is used.`
27363
+ `${path39.join(kitRoot, expected)}: instructions source not found (declared by ${declaredBy}). To fix: create that file, or point '${declaredBy}' at the file this kit actually carries. With neither declaration, the kit's ${DEFAULT_ENTRYPOINT} or ${PORTABLE_INSTRUCTIONS_NAME} is used.`
27344
27364
  );
27345
27365
  this.name = "InstructionsSourceMissingError";
27346
27366
  }
27347
27367
  };
27348
27368
  function normalizeLabel(kitRoot, file) {
27349
- return path38.relative(kitRoot, file).split(path38.sep).join("/");
27369
+ return path39.relative(kitRoot, file).split(path39.sep).join("/");
27350
27370
  }
27351
27371
  function isExplicitOverride(configured) {
27352
27372
  const normalize = (value) => value.replace(/\\/gu, "/").replace(/^\.\//u, "");
@@ -27355,7 +27375,7 @@ function isExplicitOverride(configured) {
27355
27375
  function resolveInstructionsSource(kitRoot, config) {
27356
27376
  const configured = config.source.instructions;
27357
27377
  if (isExplicitOverride(configured)) {
27358
- const file = path38.resolve(kitRoot, configured);
27378
+ const file = path39.resolve(kitRoot, configured);
27359
27379
  if (!fs38.existsSync(file)) {
27360
27380
  throw new InstructionsSourceMissingError(
27361
27381
  kitRoot,
@@ -27371,7 +27391,7 @@ function resolveInstructionsSource(kitRoot, config) {
27371
27391
  }
27372
27392
  const declared = resolveKitEntrypointName(kitRoot);
27373
27393
  if (declared !== void 0) {
27374
- const file = path38.resolve(kitRoot, declared);
27394
+ const file = path39.resolve(kitRoot, declared);
27375
27395
  if (!fs38.existsSync(file)) {
27376
27396
  throw new InstructionsSourceMissingError(
27377
27397
  kitRoot,
@@ -27386,12 +27406,12 @@ function resolveInstructionsSource(kitRoot, config) {
27386
27406
  };
27387
27407
  }
27388
27408
  for (const name of [DEFAULT_ENTRYPOINT, PORTABLE_INSTRUCTIONS_NAME]) {
27389
- const file = path38.resolve(kitRoot, name);
27409
+ const file = path39.resolve(kitRoot, name);
27390
27410
  if (fs38.existsSync(file)) {
27391
27411
  return { file, label: name, origin: "convention" };
27392
27412
  }
27393
27413
  }
27394
- const legacy = path38.resolve(kitRoot, LEGACY_ENTRYPOINT);
27414
+ const legacy = path39.resolve(kitRoot, LEGACY_ENTRYPOINT);
27395
27415
  if (fs38.existsSync(legacy)) {
27396
27416
  return {
27397
27417
  file: legacy,
@@ -27404,7 +27424,7 @@ function resolveInstructionsSource(kitRoot, config) {
27404
27424
  }
27405
27425
  function instructionsSourcePath(kitRoot, config) {
27406
27426
  const resolved = resolveInstructionsSource(kitRoot, config);
27407
- return resolved ? resolved.file : path38.resolve(kitRoot, config.source.instructions);
27427
+ return resolved ? resolved.file : path39.resolve(kitRoot, config.source.instructions);
27408
27428
  }
27409
27429
  function instructionsSourceLabel(kitRoot, config) {
27410
27430
  const resolved = resolveInstructionsSource(kitRoot, config);
@@ -27525,7 +27545,7 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
27525
27545
  if (!shouldSkipComponent(options, "hooks")) {
27526
27546
  outcomes.push(
27527
27547
  syncHookScriptsBridge({
27528
- source: path39.resolve(sourceRoot, config.source.hooks),
27548
+ source: path40.resolve(sourceRoot, config.source.hooks),
27529
27549
  destination: profile.hook_scripts,
27530
27550
  config,
27531
27551
  sourceRoot,
@@ -27586,13 +27606,13 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
27586
27606
  }
27587
27607
  function syncProviderLoss(config, sourceRoot, mappings, lossReport) {
27588
27608
  if (!mappings.modelTiers.custom_provider) return;
27589
- const agentsDir = path39.join(sourceRoot, config.source.agents);
27609
+ const agentsDir = path40.join(sourceRoot, config.source.agents);
27590
27610
  if (!fs39.existsSync(agentsDir)) return;
27591
- for (const agentFile of ts(path39.join(agentsDir, "*.md")).sort()) {
27611
+ for (const agentFile of ts(path40.join(agentsDir, "*.md")).sort()) {
27592
27612
  const { data } = parseMarkdownFrontmatter(agentFile);
27593
27613
  const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
27594
27614
  if (hasProvider) {
27595
- const basename = path39.basename(agentFile);
27615
+ const basename = path40.basename(agentFile);
27596
27616
  addLoss(lossReport, "claude-code", "agents", {
27597
27617
  source: `agents/${basename}`,
27598
27618
  fields: [
@@ -27622,6 +27642,14 @@ function lstatOrNull(p) {
27622
27642
  return null;
27623
27643
  }
27624
27644
  }
27645
+ function recordShimState(manifest, shimPath) {
27646
+ addArtifactToManifest(manifest, {
27647
+ relativePath: SHIM_MANIFEST_KEY,
27648
+ path: shimPath,
27649
+ hash: describeArtifactState(shimPath) ?? `target:${shimPath}`,
27650
+ origin: "tangyr-managed"
27651
+ });
27652
+ }
27625
27653
  function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath, logger) {
27626
27654
  const expectedBodyHash = shimBodyHash();
27627
27655
  const shimContent = buildAgentsMdShim(shimPath, agentsMdPath, "claude-code");
@@ -27642,8 +27670,9 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
27642
27670
  origin: "tangyr-managed"
27643
27671
  });
27644
27672
  writeManifest(scopePath, manifest);
27645
- fs39.mkdirSync(path39.dirname(shimPath), { recursive: true });
27673
+ fs39.mkdirSync(path40.dirname(shimPath), { recursive: true });
27646
27674
  fs39.writeFileSync(shimPath, shimContent);
27675
+ recordShimState(manifest, shimPath);
27647
27676
  logger?.verbose(`instructions-shim: wrote @AGENTS.md shim -> ${shimPath}`);
27648
27677
  return;
27649
27678
  }
@@ -27651,12 +27680,7 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
27651
27680
  const firstNonEmptyLine = existing.split("\n").find((l) => l.trim().length > 0) ?? "";
27652
27681
  const marker = extractProvenanceMarker(firstNonEmptyLine);
27653
27682
  if (marker !== null && marker.hash === expectedBodyHash) {
27654
- addArtifactToManifest(manifest, {
27655
- relativePath: SHIM_MANIFEST_KEY,
27656
- path: shimPath,
27657
- hash: expectedBodyHash,
27658
- origin: "tangyr-managed"
27659
- });
27683
+ recordShimState(manifest, shimPath);
27660
27684
  logger?.verbose(
27661
27685
  `instructions-shim: already current, skipped -> ${shimPath}`
27662
27686
  );
@@ -27665,16 +27689,11 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
27665
27689
  backupFile(shimPath, manifest, scopePath);
27666
27690
  writeManifest(scopePath, manifest);
27667
27691
  fs39.writeFileSync(shimPath, shimContent);
27668
- addArtifactToManifest(manifest, {
27669
- relativePath: SHIM_MANIFEST_KEY,
27670
- path: shimPath,
27671
- hash: expectedBodyHash,
27672
- origin: "tangyr-managed"
27673
- });
27692
+ recordShimState(manifest, shimPath);
27674
27693
  logger?.verbose(`instructions-shim: backed up and replaced -> ${shimPath}`);
27675
27694
  }
27676
27695
  function syncDirectComponent(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
27677
- const source = directComponent.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : path39.resolve(sourceRoot, config.source[directComponent.sourceKey]);
27696
+ const source = directComponent.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : path40.resolve(sourceRoot, config.source[directComponent.sourceKey]);
27678
27697
  const sourceLabel = directComponent.sourceKey === "instructions" ? instructionsSourceLabel(sourceRoot, config) : config.source[directComponent.sourceKey];
27679
27698
  const destination = directComponent.destination;
27680
27699
  if (!fs39.existsSync(source)) {
@@ -27711,7 +27730,7 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
27711
27730
  } else if (artifactClass === "managed-compiled") {
27712
27731
  fs39.unlinkSync(destination);
27713
27732
  }
27714
- ensureDir(path39.dirname(destination));
27733
+ ensureDir(path40.dirname(destination));
27715
27734
  createRelativeSymlink(source, destination, directComponent.type, {
27716
27735
  logger,
27717
27736
  provenanceMarker: directComponent.type === "file" ? formatProvenanceMarker(
@@ -27731,7 +27750,7 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
27731
27750
  return syncSkillsSlot({
27732
27751
  config,
27733
27752
  sourceRoot,
27734
- source: path39.resolve(sourceRoot, config.source.skills),
27753
+ source: path40.resolve(sourceRoot, config.source.skills),
27735
27754
  destination,
27736
27755
  dryRun: options.dryRun,
27737
27756
  logger,
@@ -27780,7 +27799,7 @@ function syncHooks(config, sourceRoot, options, logger, destination, scriptsBrid
27780
27799
  };
27781
27800
  }
27782
27801
  function syncMcp(config, sourceRoot, options, logger, destination, manifest) {
27783
- const source = path39.resolve(sourceRoot, config.source.mcp);
27802
+ const source = path40.resolve(sourceRoot, config.source.mcp);
27784
27803
  if (!fs39.existsSync(source)) {
27785
27804
  return skippedMissingSource("mcp", source);
27786
27805
  }
@@ -27822,7 +27841,7 @@ function syncMcp(config, sourceRoot, options, logger, destination, manifest) {
27822
27841
  };
27823
27842
  }
27824
27843
  function syncSettings(config, sourceRoot, options, logger, destination, manifest) {
27825
- const source = path39.resolve(sourceRoot, config.source.settings);
27844
+ const source = path40.resolve(sourceRoot, config.source.settings);
27826
27845
  if (!fs39.existsSync(source)) {
27827
27846
  return skippedMissingSource("settings", source);
27828
27847
  }
@@ -27926,15 +27945,15 @@ function isRecord3(value) {
27926
27945
  }
27927
27946
 
27928
27947
  // src/adapters/codex.ts
27929
- var TOML3 = __toESM(require_toml(), 1);
27930
27948
  import crypto6 from "crypto";
27931
27949
  import fs42 from "fs";
27932
- import path43 from "path";
27950
+ var TOML3 = __toESM(require_toml(), 1);
27951
+ import path44 from "path";
27933
27952
 
27934
27953
  // src/compiler/agents.ts
27935
27954
  var TOML = __toESM(require_toml(), 1);
27936
27955
  var import_yaml8 = __toESM(require_dist(), 1);
27937
- import path40 from "path";
27956
+ import path41 from "path";
27938
27957
  var writeCapabilityClasses = /* @__PURE__ */ new Set(["filesystem-write", "shell-execution"]);
27939
27958
  var copilotToolAliasesByClass = {
27940
27959
  delegation: "agent",
@@ -27946,7 +27965,7 @@ var copilotToolAliasesByClass = {
27946
27965
  };
27947
27966
  function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
27948
27967
  const { data, body } = parseMarkdownFrontmatter(sourceFile);
27949
- const relativeSource = `agents/${path40.basename(sourceFile)}`;
27968
+ const relativeSource = `agents/${path41.basename(sourceFile)}`;
27950
27969
  if (target === "opencode") {
27951
27970
  return compileOpenCodeAgent(
27952
27971
  sourceFile,
@@ -27987,7 +28006,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
27987
28006
  mappings,
27988
28007
  lossReport
27989
28008
  );
27990
- const overlayKey = `agents/${path40.basename(sourceFile, ".md")}.${target}.yaml`;
28009
+ const overlayKey = `agents/${path41.basename(sourceFile, ".md")}.${target}.yaml`;
27991
28010
  const targetFields = {
27992
28011
  ...translated.fields,
27993
28012
  ...extensions[overlayKey] ?? {}
@@ -28021,7 +28040,7 @@ ${TOML.stringify({
28021
28040
  function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport) {
28022
28041
  if (typeof data.description !== "string" || data.description.trim() === "") {
28023
28042
  throw new Error(
28024
- `${path40.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
28043
+ `${path41.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
28025
28044
  );
28026
28045
  }
28027
28046
  const frontmatter = {
@@ -28075,7 +28094,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
28075
28094
  "permission",
28076
28095
  "permission-coarsening"
28077
28096
  ),
28078
- detail: `${path40.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
28097
+ detail: `${path41.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
28079
28098
  }
28080
28099
  ]
28081
28100
  });
@@ -28100,7 +28119,7 @@ ${(0, import_yaml8.stringify)(frontmatter).trim()}
28100
28119
  function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport) {
28101
28120
  if (typeof data.description !== "string" || data.description.trim() === "") {
28102
28121
  throw new Error(
28103
- `${path40.basename(sourceFile)}: Cursor agent requires a non-empty description field`
28122
+ `${path41.basename(sourceFile)}: Cursor agent requires a non-empty description field`
28104
28123
  );
28105
28124
  }
28106
28125
  const frontmatter = {
@@ -28137,7 +28156,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
28137
28156
  "permission",
28138
28157
  "permission-coarsening"
28139
28158
  ),
28140
- detail: `${path40.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
28159
+ detail: `${path41.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
28141
28160
  }
28142
28161
  ]
28143
28162
  });
@@ -28156,7 +28175,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
28156
28175
  "provider",
28157
28176
  "provider-not-representable"
28158
28177
  ),
28159
- detail: `${path40.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
28178
+ detail: `${path41.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
28160
28179
  }
28161
28180
  ]
28162
28181
  });
@@ -28188,7 +28207,7 @@ function compileClineAgent(sourceFile, _data, _body, relativeSource, lossReport)
28188
28207
  "persona",
28189
28208
  "persona-not-representable"
28190
28209
  ),
28191
- detail: `${path40.basename(sourceFile)}: Cline has no committable per-agent persona file for the VSCode extension target; configure the agent through Cline Settings \u2192 Agent.`
28210
+ detail: `${path41.basename(sourceFile)}: Cline has no committable per-agent persona file for the VSCode extension target; configure the agent through Cline Settings \u2192 Agent.`
28192
28211
  }
28193
28212
  ]
28194
28213
  });
@@ -28243,7 +28262,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
28243
28262
  field,
28244
28263
  "model-not-representable"
28245
28264
  ),
28246
- detail: `${path40.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
28265
+ detail: `${path41.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
28247
28266
  });
28248
28267
  return;
28249
28268
  }
@@ -28261,9 +28280,9 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
28261
28280
  lossReport,
28262
28281
  target,
28263
28282
  "agents",
28264
- `agents/${path40.basename(sourceFile)}`,
28283
+ `agents/${path41.basename(sourceFile)}`,
28265
28284
  "info",
28266
- `${path40.basename(sourceFile)}: ${field} is delivered through another managed surface.`
28285
+ `${path41.basename(sourceFile)}: ${field} is delivered through another managed surface.`
28267
28286
  );
28268
28287
  return;
28269
28288
  }
@@ -28272,7 +28291,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
28272
28291
  field,
28273
28292
  action: entryType,
28274
28293
  severity: resolveLossSeverity("agent-field", field, entryType),
28275
- detail: `${path40.basename(sourceFile)}: ${field} has no emitted field for this target.`
28294
+ detail: `${path41.basename(sourceFile)}: ${field} has no emitted field for this target.`
28276
28295
  });
28277
28296
  }
28278
28297
  function mapToolsToCapabilities(value, mappings) {
@@ -28303,7 +28322,7 @@ function recordCodexToolCoarsening(sourceFile, tools, sandboxMode, losses) {
28303
28322
  // reads, and the exit code it forces teaches `--ignore-errors`, which is
28304
28323
  // how the losses that ARE actionable get missed.
28305
28324
  severity: "warning",
28306
- detail: `${path40.basename(sourceFile)}: Codex has no per-agent tool allow set \u2014 ${declared.join(", ")} becomes sandbox_mode = "${String(sandboxMode)}", so agents with different tool sets that share a posture become indistinguishable.`
28325
+ detail: `${path41.basename(sourceFile)}: Codex has no per-agent tool allow set \u2014 ${declared.join(", ")} becomes sandbox_mode = "${String(sandboxMode)}", so agents with different tool sets that share a posture become indistinguishable.`
28307
28326
  });
28308
28327
  }
28309
28328
  function deriveCodexSandbox(value, mappings) {
@@ -28724,12 +28743,12 @@ function addHookLoss(lossReport, target, eventName, sourceLabel, severity, reaso
28724
28743
  // src/compiler/command-as-skill.ts
28725
28744
  var import_yaml9 = __toESM(require_dist(), 1);
28726
28745
  import fs40 from "fs";
28727
- import path41 from "path";
28746
+ import path42 from "path";
28728
28747
  var CARRIED_OVER = ["argument-hint", "agent", "launch"];
28729
28748
  function compileCommandAsSkill(commandFile, target) {
28730
- const name = path41.basename(commandFile, ".md");
28749
+ const name = path42.basename(commandFile, ".md");
28731
28750
  const { data, body } = parseMarkdownFrontmatter(commandFile);
28732
- const relativeSource = `commands/${path41.basename(commandFile)}`;
28751
+ const relativeSource = `commands/${path42.basename(commandFile)}`;
28733
28752
  const description = typeof data.description === "string" && data.description.trim().length > 0 ? data.description.trim() : `The ${name} command.`;
28734
28753
  const frontmatter = { name, description };
28735
28754
  for (const key of CARRIED_OVER) {
@@ -28756,7 +28775,7 @@ function compileCommandsAsSkills(commandsRoot, target) {
28756
28775
  return [];
28757
28776
  }
28758
28777
  return fs40.readdirSync(commandsRoot).filter((entry) => entry.endsWith(".md")).sort().map(
28759
- (entry) => compileCommandAsSkill(path41.join(commandsRoot, entry), target)
28778
+ (entry) => compileCommandAsSkill(path42.join(commandsRoot, entry), target)
28760
28779
  );
28761
28780
  }
28762
28781
 
@@ -29039,7 +29058,7 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
29039
29058
  }
29040
29059
 
29041
29060
  // src/compiler/rules.ts
29042
- import path42 from "path";
29061
+ import path43 from "path";
29043
29062
  var import_yaml10 = __toESM(require_dist(), 1);
29044
29063
  import fs41 from "fs";
29045
29064
  function compileRules(sourceRulesDir, target, _mappings, lossReport) {
@@ -29060,13 +29079,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
29060
29079
  }
29061
29080
  const appendixParts = [];
29062
29081
  const dotRulesFiles = [];
29063
- for (const ruleFile of ts(path42.join(sourceRulesDir, "*.md")).sort()) {
29082
+ for (const ruleFile of ts(path43.join(sourceRulesDir, "*.md")).sort()) {
29064
29083
  const parsed = parseRule(ruleFile);
29065
- const name = path42.basename(ruleFile, ".md");
29084
+ const name = path43.basename(ruleFile, ".md");
29066
29085
  if (parsed.mode === "exec-policy") {
29067
29086
  dotRulesFiles.push({
29068
29087
  name: `${name}.rules`,
29069
- content: `${formatProvenanceMarker("toml", `rules/${path42.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
29088
+ content: `${formatProvenanceMarker("toml", `rules/${path43.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
29070
29089
  ${parsed.body}`
29071
29090
  });
29072
29091
  continue;
@@ -29075,7 +29094,7 @@ ${parsed.body}`
29075
29094
 
29076
29095
  ${parsed.body.trim()}`);
29077
29096
  addLoss(lossReport, "codex", "rules", {
29078
- source: `rules/${path42.basename(ruleFile)}`,
29097
+ source: `rules/${path43.basename(ruleFile)}`,
29079
29098
  fields: [
29080
29099
  {
29081
29100
  field: "mode",
@@ -29085,7 +29104,7 @@ ${parsed.body.trim()}`);
29085
29104
  "mode",
29086
29105
  "rule-as-instruction"
29087
29106
  ),
29088
- detail: `${path42.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
29107
+ detail: `${path43.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
29089
29108
  }
29090
29109
  ]
29091
29110
  });
@@ -29117,14 +29136,14 @@ function isRuleMode(value) {
29117
29136
  }
29118
29137
  function compileOpenCodeRules(sourceRulesDir, lossReport) {
29119
29138
  const appendixParts = [];
29120
- for (const ruleFile of ts(path42.join(sourceRulesDir, "*.md")).sort()) {
29139
+ for (const ruleFile of ts(path43.join(sourceRulesDir, "*.md")).sort()) {
29121
29140
  const parsed = parseRule(ruleFile);
29122
- const name = path42.basename(ruleFile, ".md");
29141
+ const name = path43.basename(ruleFile, ".md");
29123
29142
  appendixParts.push(`## ${name}
29124
29143
 
29125
29144
  ${parsed.body.trim()}`);
29126
29145
  addLoss(lossReport, "opencode", "rules", {
29127
- source: `rules/${path42.basename(ruleFile)}`,
29146
+ source: `rules/${path43.basename(ruleFile)}`,
29128
29147
  fields: [
29129
29148
  {
29130
29149
  field: "rule",
@@ -29134,7 +29153,7 @@ ${parsed.body.trim()}`);
29134
29153
  "rule",
29135
29154
  "rule-path-scoping"
29136
29155
  ),
29137
- detail: `${path42.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to its instructions file`
29156
+ detail: `${path43.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to its instructions file`
29138
29157
  }
29139
29158
  ]
29140
29159
  });
@@ -29143,9 +29162,9 @@ ${parsed.body.trim()}`);
29143
29162
  }
29144
29163
  function compileCursorRules(sourceRulesDir, _lossReport) {
29145
29164
  const dotRulesFiles = [];
29146
- for (const ruleFile of ts(path42.join(sourceRulesDir, "*.md")).sort()) {
29165
+ for (const ruleFile of ts(path43.join(sourceRulesDir, "*.md")).sort()) {
29147
29166
  const content = fs41.readFileSync(ruleFile, "utf8");
29148
- const name = path42.basename(ruleFile, ".md");
29167
+ const name = path43.basename(ruleFile, ".md");
29149
29168
  let frontmatterData = {};
29150
29169
  let body = content;
29151
29170
  if (content.startsWith("---\n")) {
@@ -29174,7 +29193,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
29174
29193
  }
29175
29194
  const marker = formatProvenanceMarker(
29176
29195
  "markdown",
29177
- `rules/${path42.basename(ruleFile)}`,
29196
+ `rules/${path43.basename(ruleFile)}`,
29178
29197
  computeSourceHash(ruleFile),
29179
29198
  "cursor"
29180
29199
  );
@@ -29190,9 +29209,9 @@ ${body}`;
29190
29209
  }
29191
29210
  function compileClineRules(sourceRulesDir, lossReport) {
29192
29211
  const dotRulesFiles = [];
29193
- for (const ruleFile of ts(path42.join(sourceRulesDir, "*.md")).sort()) {
29212
+ for (const ruleFile of ts(path43.join(sourceRulesDir, "*.md")).sort()) {
29194
29213
  const content = fs41.readFileSync(ruleFile, "utf8");
29195
- const name = path42.basename(ruleFile, ".md");
29214
+ const name = path43.basename(ruleFile, ".md");
29196
29215
  let frontmatterData = {};
29197
29216
  let body = content;
29198
29217
  if (content.startsWith("---\n")) {
@@ -29209,13 +29228,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
29209
29228
  }
29210
29229
  const marker = formatProvenanceMarker(
29211
29230
  "markdown",
29212
- `rules/${path42.basename(ruleFile)}`,
29231
+ `rules/${path43.basename(ruleFile)}`,
29213
29232
  computeSourceHash(ruleFile),
29214
29233
  "cline"
29215
29234
  );
29216
29235
  if (frontmatterData.mode === "exec-policy") {
29217
29236
  addLoss(lossReport, "cline", "rules", {
29218
- source: `rules/${path42.basename(ruleFile)}`,
29237
+ source: `rules/${path43.basename(ruleFile)}`,
29219
29238
  fields: [
29220
29239
  {
29221
29240
  field: "mode",
@@ -29225,7 +29244,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
29225
29244
  "mode",
29226
29245
  "rule-mode-downgrade"
29227
29246
  ),
29228
- detail: `${path42.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
29247
+ detail: `${path43.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
29229
29248
  }
29230
29249
  ]
29231
29250
  });
@@ -29249,8 +29268,8 @@ function compileCopilotRules(sourceRulesDir) {
29249
29268
  return [];
29250
29269
  }
29251
29270
  const files = [];
29252
- for (const ruleFile of ts(path42.join(sourceRulesDir, "*.md")).sort()) {
29253
- const name = path42.basename(ruleFile, ".md");
29271
+ for (const ruleFile of ts(path43.join(sourceRulesDir, "*.md")).sort()) {
29272
+ const name = path43.basename(ruleFile, ".md");
29254
29273
  const { data } = parseMarkdownFrontmatter(ruleFile);
29255
29274
  const { body } = parseRule(ruleFile);
29256
29275
  const declared = data.paths;
@@ -29259,7 +29278,7 @@ function compileCopilotRules(sourceRulesDir) {
29259
29278
  "---",
29260
29279
  `applyTo: ${JSON.stringify(applyTo)}`,
29261
29280
  "x-tangyr:",
29262
- ` source: rules/${path42.basename(ruleFile)}`,
29281
+ ` source: rules/${path43.basename(ruleFile)}`,
29263
29282
  ` hash: ${computeSourceHash(ruleFile)}`,
29264
29283
  " target: copilot",
29265
29284
  "---"
@@ -29296,7 +29315,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
29296
29315
  rules: profile.rules
29297
29316
  };
29298
29317
  const rules = compileRules(
29299
- path43.join(sourceRoot, config.source.rules),
29318
+ path44.join(sourceRoot, config.source.rules),
29300
29319
  "codex",
29301
29320
  mappings,
29302
29321
  lossReport
@@ -29376,7 +29395,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
29376
29395
  if (!shouldSkipComponent2(options, "hooks")) {
29377
29396
  outcomes.push(
29378
29397
  syncHookScriptsBridge({
29379
- source: path43.resolve(sourceRoot, config.source.hooks),
29398
+ source: path44.resolve(sourceRoot, config.source.hooks),
29380
29399
  destination: resolveTargetPath(paths.hook_scripts),
29381
29400
  config,
29382
29401
  sourceRoot,
@@ -29477,9 +29496,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
29477
29496
  function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
29478
29497
  const cp = mappings.modelTiers.custom_provider;
29479
29498
  if (!cp) return "";
29480
- const agentsDir = path43.join(sourceRoot, config.source.agents);
29499
+ const agentsDir = path44.join(sourceRoot, config.source.agents);
29481
29500
  if (!fs42.existsSync(agentsDir)) return "";
29482
- const agentFiles = ts(path43.join(agentsDir, "*.md")).sort();
29501
+ const agentFiles = ts(path44.join(agentsDir, "*.md")).sort();
29483
29502
  const hasProviderAgent = agentFiles.some((agentFile) => {
29484
29503
  const { data } = parseMarkdownFrontmatter(agentFile);
29485
29504
  return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
@@ -29544,7 +29563,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
29544
29563
  }
29545
29564
  ];
29546
29565
  for (const ruleFile of rules.dotRulesFiles) {
29547
- const destination = path43.join(rulesRoot, ruleFile.name);
29566
+ const destination = path44.join(rulesRoot, ruleFile.name);
29548
29567
  if (options.dryRun) {
29549
29568
  logger.info(`[dry-run] rules: write ${destination}`);
29550
29569
  outcomes.push({
@@ -29583,7 +29602,7 @@ function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, lo
29583
29602
  ${agentsAppendix}`.trim();
29584
29603
  const marker = formatProvenanceMarker(
29585
29604
  "markdown",
29586
- path43.basename(instructionsSourceLabel(sourceRoot, config)),
29605
+ path44.basename(instructionsSourceLabel(sourceRoot, config)),
29587
29606
  hashString(composed),
29588
29607
  "codex"
29589
29608
  );
@@ -29613,7 +29632,7 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
29613
29632
  return syncSkillsSlot({
29614
29633
  config,
29615
29634
  sourceRoot,
29616
- source: path43.resolve(sourceRoot, config.source.skills),
29635
+ source: path44.resolve(sourceRoot, config.source.skills),
29617
29636
  destination: resolveTargetPath(paths.skills),
29618
29637
  dryRun: options.dryRun,
29619
29638
  logger,
@@ -29628,13 +29647,13 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
29628
29647
  });
29629
29648
  }
29630
29649
  function syncCommandsAsSkills(config, sourceRoot, paths, options, _lossReport, logger, manifest, scopePath) {
29631
- const commandsRoot = path43.resolve(sourceRoot, config.source.commands);
29650
+ const commandsRoot = path44.resolve(sourceRoot, config.source.commands);
29632
29651
  if (!fs42.existsSync(commandsRoot)) {
29633
29652
  return [skippedMissingSource2("commands", commandsRoot)];
29634
29653
  }
29635
29654
  const skillsRoot = resolveTargetPath(paths.skills);
29636
29655
  return compileCommandsAsSkills(commandsRoot, "codex").map((skill) => {
29637
- const destination = path43.join(skillsRoot, skill.name, "SKILL.md");
29656
+ const destination = path44.join(skillsRoot, skill.name, "SKILL.md");
29638
29657
  if (options.dryRun) {
29639
29658
  logger.info(
29640
29659
  `[dry-run] commands: compile ${skill.relativeSource} -> ${destination}`
@@ -29660,16 +29679,16 @@ function syncCommandsAsSkills(config, sourceRoot, paths, options, _lossReport, l
29660
29679
  });
29661
29680
  }
29662
29681
  function syncAgents(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
29663
- const sourceAgentsRoot = path43.join(sourceRoot, config.source.agents);
29682
+ const sourceAgentsRoot = path44.join(sourceRoot, config.source.agents);
29664
29683
  if (!fs42.existsSync(sourceAgentsRoot)) {
29665
29684
  return [skippedMissingSource2("agents", sourceAgentsRoot)];
29666
29685
  }
29667
- const sourceAgents = ts(path43.join(sourceAgentsRoot, "*.md")).sort();
29686
+ const sourceAgents = ts(path44.join(sourceAgentsRoot, "*.md")).sort();
29668
29687
  const agentsRoot = resolveTargetPath(paths.agents);
29669
29688
  return sourceAgents.map((agentFile) => {
29670
- const destination = path43.join(
29689
+ const destination = path44.join(
29671
29690
  agentsRoot,
29672
- `${path43.basename(agentFile, ".md")}.toml`
29691
+ `${path44.basename(agentFile, ".md")}.toml`
29673
29692
  );
29674
29693
  const compiled = compileAgent(
29675
29694
  agentFile,
@@ -29801,10 +29820,18 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
29801
29820
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent(destination, content, expectedHash)) {
29802
29821
  return { component, status: "skipped-current", path: destination };
29803
29822
  }
29823
+ if (artifactClass === "managed-compiled" && !options.force && hasDriftedSinceInstall(destination, manifest)) {
29824
+ logger.warn(
29825
+ `${destination}: edited since Tangyr wrote it \u2014 applying onConflict: ${config.onConflict}`
29826
+ );
29827
+ if (!handleConflict2(destination, config, options, logger, manifest, scopePath)) {
29828
+ return { component, status: "conflict", path: destination };
29829
+ }
29830
+ }
29804
29831
  if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
29805
29832
  return { component, status: "conflict", path: destination };
29806
29833
  }
29807
- ensureDir(path43.dirname(destination));
29834
+ ensureDir(path44.dirname(destination));
29808
29835
  const clearedLink = clearSymlinkAtDestination(destination);
29809
29836
  if (clearedLink !== null) {
29810
29837
  logger.verbose(
@@ -29833,7 +29860,7 @@ ${managedMcpEnd}
29833
29860
  if (current === next.trimStart()) {
29834
29861
  return false;
29835
29862
  }
29836
- ensureDir(path43.dirname(destination));
29863
+ ensureDir(path44.dirname(destination));
29837
29864
  fs42.writeFileSync(destination, next.trimStart());
29838
29865
  return true;
29839
29866
  }
@@ -29908,15 +29935,15 @@ function hashString(value) {
29908
29935
  // src/adapters/copilot.ts
29909
29936
  import crypto7 from "crypto";
29910
29937
  import fs43 from "fs";
29911
- import path45 from "path";
29938
+ import path46 from "path";
29912
29939
 
29913
29940
  // src/compiler/commands.ts
29914
29941
  var import_yaml11 = __toESM(require_dist(), 1);
29915
- import path44 from "path";
29942
+ import path45 from "path";
29916
29943
  function compileCommandPrompt(sourceFile) {
29917
29944
  const { data, body } = parseMarkdownFrontmatter(sourceFile);
29918
- const relativeSource = `commands/${path44.basename(sourceFile)}`;
29919
- const fields = promptFrontmatter(data, path44.basename(sourceFile, ".md"));
29945
+ const relativeSource = `commands/${path45.basename(sourceFile)}`;
29946
+ const fields = promptFrontmatter(data, path45.basename(sourceFile, ".md"));
29920
29947
  const marker = formatProvenanceMarker(
29921
29948
  "markdown",
29922
29949
  relativeSource,
@@ -30057,7 +30084,7 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
30057
30084
  if (!shouldSkipComponent3(options, "hooks")) {
30058
30085
  outcomes.push(
30059
30086
  syncHookScriptsBridge({
30060
- source: path45.resolve(sourceRoot, config.source.hooks),
30087
+ source: path46.resolve(sourceRoot, config.source.hooks),
30061
30088
  destination: resolveTargetPath(paths.hook_scripts),
30062
30089
  config,
30063
30090
  sourceRoot,
@@ -30138,13 +30165,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
30138
30165
  }
30139
30166
  function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
30140
30167
  if (!mappings.modelTiers.custom_provider) return;
30141
- const agentsDir = path45.join(sourceRoot, config.source.agents);
30168
+ const agentsDir = path46.join(sourceRoot, config.source.agents);
30142
30169
  if (!fs43.existsSync(agentsDir)) return;
30143
- for (const agentFile of ts(path45.join(agentsDir, "*.md")).sort()) {
30170
+ for (const agentFile of ts(path46.join(agentsDir, "*.md")).sort()) {
30144
30171
  const { data } = parseMarkdownFrontmatter(agentFile);
30145
30172
  const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
30146
30173
  if (hasProvider) {
30147
- const basename = path45.basename(agentFile);
30174
+ const basename = path46.basename(agentFile);
30148
30175
  addLoss(lossReport, "copilot", "agents", {
30149
30176
  source: `agents/${basename}`,
30150
30177
  fields: [
@@ -30177,15 +30204,15 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
30177
30204
  const contentHash = hashString2(rawContent);
30178
30205
  const marker = formatProvenanceMarker(
30179
30206
  "markdown",
30180
- path45.basename(instructionsSourceLabel(sourceRoot, config)),
30207
+ path46.basename(instructionsSourceLabel(sourceRoot, config)),
30181
30208
  contentHash,
30182
30209
  "copilot"
30183
30210
  );
30184
30211
  const composedContent = `${marker}
30185
30212
  ${rawContent}`;
30186
30213
  const projectRoot = options.projectRoot ?? process.cwd();
30187
- const agentsMdDest = path45.resolve(projectRoot, "AGENTS.md");
30188
- const mirrorDest = path45.resolve(
30214
+ const agentsMdDest = path46.resolve(projectRoot, "AGENTS.md");
30215
+ const mirrorDest = path46.resolve(
30189
30216
  projectRoot,
30190
30217
  ".github",
30191
30218
  "copilot-instructions.md"
@@ -30236,10 +30263,18 @@ function writeInstructionsFile(component, destination, content, contentHash, con
30236
30263
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent2(destination, content, contentHash)) {
30237
30264
  return { component, status: "skipped-current", path: destination };
30238
30265
  }
30266
+ if (artifactClass === "managed-compiled" && !options.force && hasDriftedSinceInstall(destination, manifest)) {
30267
+ logger.warn(
30268
+ `${destination}: edited since Tangyr wrote it \u2014 applying onConflict: ${config.onConflict}`
30269
+ );
30270
+ if (!handleConflict3(destination, config, options, logger, manifest, scopePath)) {
30271
+ return { component, status: "conflict", path: destination };
30272
+ }
30273
+ }
30239
30274
  if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
30240
30275
  return { component, status: "conflict", path: destination };
30241
30276
  }
30242
- ensureDir(path45.dirname(destination));
30277
+ ensureDir(path46.dirname(destination));
30243
30278
  const clearedLink = clearSymlinkAtDestination(destination);
30244
30279
  if (clearedLink !== null) {
30245
30280
  logger.verbose(
@@ -30256,7 +30291,7 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
30256
30291
  return syncSkillsSlot({
30257
30292
  config,
30258
30293
  sourceRoot,
30259
- source: path45.resolve(sourceRoot, config.source.skills),
30294
+ source: path46.resolve(sourceRoot, config.source.skills),
30260
30295
  destination: resolveTargetPath(paths.skills),
30261
30296
  dryRun: options.dryRun,
30262
30297
  logger,
@@ -30271,16 +30306,16 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
30271
30306
  });
30272
30307
  }
30273
30308
  function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
30274
- const sourceAgentsRoot = path45.join(sourceRoot, config.source.agents);
30309
+ const sourceAgentsRoot = path46.join(sourceRoot, config.source.agents);
30275
30310
  if (!fs43.existsSync(sourceAgentsRoot)) {
30276
30311
  return [skippedMissingSource3("agents", sourceAgentsRoot)];
30277
30312
  }
30278
- const sourceAgents = ts(path45.join(sourceAgentsRoot, "*.md")).sort();
30313
+ const sourceAgents = ts(path46.join(sourceAgentsRoot, "*.md")).sort();
30279
30314
  const agentsRoot = resolveTargetPath(paths.agents);
30280
30315
  return sourceAgents.map((agentFile) => {
30281
- const destination = path45.join(
30316
+ const destination = path46.join(
30282
30317
  agentsRoot,
30283
- `${path45.basename(agentFile, ".md")}.agent.md`
30318
+ `${path46.basename(agentFile, ".md")}.agent.md`
30284
30319
  );
30285
30320
  const compiled = compileAgent(
30286
30321
  agentFile,
@@ -30308,16 +30343,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
30308
30343
  });
30309
30344
  }
30310
30345
  function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
30311
- const sourceCommandsRoot = path45.join(sourceRoot, config.source.commands);
30346
+ const sourceCommandsRoot = path46.join(sourceRoot, config.source.commands);
30312
30347
  if (!fs43.existsSync(sourceCommandsRoot)) {
30313
30348
  return [skippedMissingSource3("commands", sourceCommandsRoot)];
30314
30349
  }
30315
- const sourceCommands = ts(path45.join(sourceCommandsRoot, "*.md")).sort();
30350
+ const sourceCommands = ts(path46.join(sourceCommandsRoot, "*.md")).sort();
30316
30351
  const promptsRoot = resolveTargetPath(paths.prompts);
30317
30352
  return sourceCommands.map((commandFile) => {
30318
- const destination = path45.join(
30353
+ const destination = path46.join(
30319
30354
  promptsRoot,
30320
- `${path45.basename(commandFile, ".md")}.prompt.md`
30355
+ `${path46.basename(commandFile, ".md")}.prompt.md`
30321
30356
  );
30322
30357
  const compiled = compileCommandPrompt(commandFile);
30323
30358
  if (options.dryRun) {
@@ -30341,7 +30376,7 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
30341
30376
  });
30342
30377
  }
30343
30378
  function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, logger) {
30344
- const destination = path45.join(
30379
+ const destination = path46.join(
30345
30380
  resolveTargetPath(paths.hooks),
30346
30381
  "tangyr-managed.json"
30347
30382
  );
@@ -30430,13 +30465,13 @@ function syncMcp3(config, sourceRoot, paths, options, lossReport, logger) {
30430
30465
  );
30431
30466
  }
30432
30467
  function syncRules2(config, sourceRoot, rulesSlot, options, logger, manifest, scopePath) {
30433
- const sourceRulesDir = path45.resolve(sourceRoot, config.source.rules);
30468
+ const sourceRulesDir = path46.resolve(sourceRoot, config.source.rules);
30434
30469
  if (!fs43.existsSync(sourceRulesDir)) {
30435
30470
  return [skippedMissingSource3("rules", sourceRulesDir)];
30436
30471
  }
30437
30472
  const destinationRoot = resolveTargetPath(rulesSlot);
30438
30473
  return compileCopilotRules(sourceRulesDir).map((file) => {
30439
- const destination = path45.join(destinationRoot, file.name);
30474
+ const destination = path46.join(destinationRoot, file.name);
30440
30475
  if (options.dryRun) {
30441
30476
  logger.info(`[dry-run] rules: compile -> ${destination}`);
30442
30477
  return {
@@ -30467,10 +30502,18 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
30467
30502
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent2(destination, content, expectedHash)) {
30468
30503
  return { component, status: "skipped-current", path: destination };
30469
30504
  }
30505
+ if (artifactClass === "managed-compiled" && !options.force && hasDriftedSinceInstall(destination, manifest)) {
30506
+ logger.warn(
30507
+ `${destination}: edited since Tangyr wrote it \u2014 applying onConflict: ${config.onConflict}`
30508
+ );
30509
+ if (!handleConflict3(destination, config, options, logger, manifest, scopePath)) {
30510
+ return { component, status: "conflict", path: destination };
30511
+ }
30512
+ }
30470
30513
  if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
30471
30514
  return { component, status: "conflict", path: destination };
30472
30515
  }
30473
- ensureDir(path45.dirname(destination));
30516
+ ensureDir(path46.dirname(destination));
30474
30517
  const clearedLink = clearSymlinkAtDestination(destination);
30475
30518
  if (clearedLink !== null) {
30476
30519
  logger.verbose(
@@ -30526,12 +30569,12 @@ function shouldSkipComponent3(options, component) {
30526
30569
  function cleanupLegacyAgents(paths, options, logger) {
30527
30570
  const currentAgentsRoot = resolveTargetPath(paths.agents);
30528
30571
  const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
30529
- if (path45.resolve(currentAgentsRoot) === path45.resolve(legacyAgentsRoot)) {
30572
+ if (path46.resolve(currentAgentsRoot) === path46.resolve(legacyAgentsRoot)) {
30530
30573
  return [];
30531
30574
  }
30532
30575
  const outcomes = [];
30533
30576
  for (const filePath of ts(
30534
- path45.join(legacyAgentsRoot, "*.agent.md")
30577
+ path46.join(legacyAgentsRoot, "*.agent.md")
30535
30578
  ).sort()) {
30536
30579
  if (!isCopilotManagedCompiledFile(filePath)) {
30537
30580
  continue;
@@ -30564,7 +30607,7 @@ function skippedMissingSource3(component, source) {
30564
30607
  // src/adapters/cursor.ts
30565
30608
  import crypto8 from "crypto";
30566
30609
  import fs44 from "fs";
30567
- import path46 from "path";
30610
+ import path47 from "path";
30568
30611
  function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
30569
30612
  const scope = options.scope ?? "global";
30570
30613
  const profile = resolveTargetPaths({
@@ -30676,7 +30719,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
30676
30719
  if (!shouldSkipComponent4(options, "hooks")) {
30677
30720
  outcomes.push(
30678
30721
  syncHookScriptsBridge({
30679
- source: path46.resolve(sourceRoot, config.source.hooks),
30722
+ source: path47.resolve(sourceRoot, config.source.hooks),
30680
30723
  destination: resolveTargetPath(paths.hook_scripts),
30681
30724
  config,
30682
30725
  sourceRoot,
@@ -30741,7 +30784,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
30741
30784
  const composed = composeCursorInstructions(config, sourceRoot, lossReport);
30742
30785
  const marker = formatProvenanceMarker(
30743
30786
  "markdown",
30744
- path46.basename(instructionsSourceLabel(sourceRoot, config)),
30787
+ path47.basename(instructionsSourceLabel(sourceRoot, config)),
30745
30788
  hashString3(composed),
30746
30789
  "cursor"
30747
30790
  );
@@ -30780,11 +30823,11 @@ function composeCursorInstructions(config, sourceRoot, lossReport) {
30780
30823
  ${personaContent}`.trim() : baseContent;
30781
30824
  }
30782
30825
  function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
30783
- const agentsDir = path46.join(sourceRoot, config.source.agents);
30826
+ const agentsDir = path47.join(sourceRoot, config.source.agents);
30784
30827
  if (!fs44.existsSync(agentsDir)) {
30785
30828
  return null;
30786
30829
  }
30787
- const agentFiles = ts(path46.join(agentsDir, "*.md")).sort();
30830
+ const agentFiles = ts(path47.join(agentsDir, "*.md")).sort();
30788
30831
  if (agentFiles.length === 0) {
30789
30832
  return null;
30790
30833
  }
@@ -30807,7 +30850,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
30807
30850
  return null;
30808
30851
  }
30809
30852
  addLoss(lossReport, "cursor", "instructions", {
30810
- source: `agents/${path46.basename(primaryFile)}`,
30853
+ source: `agents/${path47.basename(primaryFile)}`,
30811
30854
  fields: [
30812
30855
  {
30813
30856
  field: "persona",
@@ -30817,23 +30860,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
30817
30860
  "persona",
30818
30861
  "instructions-shim"
30819
30862
  ),
30820
- detail: `Primary persona from ${path46.basename(primaryFile)} folded into its instructions file (Cursor has no custom modes surface)`
30863
+ detail: `Primary persona from ${path47.basename(primaryFile)} folded into its instructions file (Cursor has no custom modes surface)`
30821
30864
  }
30822
30865
  ]
30823
30866
  });
30824
30867
  return body.trim();
30825
30868
  }
30826
30869
  function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
30827
- const sourceAgentsRoot = path46.join(sourceRoot, config.source.agents);
30870
+ const sourceAgentsRoot = path47.join(sourceRoot, config.source.agents);
30828
30871
  if (!fs44.existsSync(sourceAgentsRoot)) {
30829
30872
  return [skippedMissingSource4("agents", sourceAgentsRoot)];
30830
30873
  }
30831
- const sourceAgents = ts(path46.join(sourceAgentsRoot, "*.md")).sort();
30874
+ const sourceAgents = ts(path47.join(sourceAgentsRoot, "*.md")).sort();
30832
30875
  const agentsRoot = resolveTargetPath(paths.agents);
30833
30876
  return sourceAgents.map((agentFile) => {
30834
- const destination = path46.join(
30877
+ const destination = path47.join(
30835
30878
  agentsRoot,
30836
- `${path46.basename(agentFile, ".md")}.md`
30879
+ `${path47.basename(agentFile, ".md")}.md`
30837
30880
  );
30838
30881
  let compiled;
30839
30882
  try {
@@ -30874,14 +30917,14 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
30874
30917
  });
30875
30918
  }
30876
30919
  function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
30877
- const sourceRulesDir = path46.join(sourceRoot, config.source.rules);
30920
+ const sourceRulesDir = path47.join(sourceRoot, config.source.rules);
30878
30921
  if (!fs44.existsSync(sourceRulesDir)) {
30879
30922
  return [skippedMissingSource4("rules", sourceRulesDir)];
30880
30923
  }
30881
30924
  const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
30882
30925
  const rulesDir = resolveTargetPath(paths.rules);
30883
30926
  return compiled.dotRulesFiles.map(({ name, content }) => {
30884
- const destination = path46.join(rulesDir, name);
30927
+ const destination = path47.join(rulesDir, name);
30885
30928
  if (options.dryRun) {
30886
30929
  logger.info(`[dry-run] rules: write ${destination}`);
30887
30930
  return {
@@ -30905,15 +30948,15 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
30905
30948
  });
30906
30949
  }
30907
30950
  function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
30908
- const sourceCommandsRoot = path46.join(sourceRoot, config.source.commands);
30951
+ const sourceCommandsRoot = path47.join(sourceRoot, config.source.commands);
30909
30952
  if (!fs44.existsSync(sourceCommandsRoot)) {
30910
30953
  return [skippedMissingSource4("commands", sourceCommandsRoot)];
30911
30954
  }
30912
- const sourceCommands = ts(path46.join(sourceCommandsRoot, "*.md")).sort();
30955
+ const sourceCommands = ts(path47.join(sourceCommandsRoot, "*.md")).sort();
30913
30956
  const skillsRoot = resolveTargetPath(paths.skills);
30914
30957
  return sourceCommands.map((commandFile) => {
30915
- const baseName = path46.basename(commandFile, ".md");
30916
- const destination = path46.join(skillsRoot, baseName, "SKILL.md");
30958
+ const baseName = path47.basename(commandFile, ".md");
30959
+ const destination = path47.join(skillsRoot, baseName, "SKILL.md");
30917
30960
  const { content } = compileCommandAsSkill(commandFile, "cursor");
30918
30961
  if (options.dryRun) {
30919
30962
  logger.info(
@@ -30943,7 +30986,7 @@ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, _
30943
30986
  return syncSkillsSlot({
30944
30987
  config,
30945
30988
  sourceRoot,
30946
- source: path46.resolve(sourceRoot, config.source.skills),
30989
+ source: path47.resolve(sourceRoot, config.source.skills),
30947
30990
  destination,
30948
30991
  dryRun: options.dryRun,
30949
30992
  logger,
@@ -30991,7 +31034,7 @@ function syncHooks4(config, sourceRoot, paths, mappings, options, lossReport, lo
30991
31034
  }
30992
31035
  const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
30993
31036
  `;
30994
- ensureDir(path46.dirname(destination));
31037
+ ensureDir(path47.dirname(destination));
30995
31038
  fs44.writeFileSync(destination, hooksFileContent);
30996
31039
  return { component: "hooks", status: "success", path: destination };
30997
31040
  }
@@ -31055,13 +31098,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
31055
31098
  );
31056
31099
  }
31057
31100
  function syncProviderPin(config, sourceRoot, lossReport) {
31058
- const agentsDir = path46.join(sourceRoot, config.source.agents);
31101
+ const agentsDir = path47.join(sourceRoot, config.source.agents);
31059
31102
  if (!fs44.existsSync(agentsDir)) return;
31060
- for (const agentFile of ts(path46.join(agentsDir, "*.md")).sort()) {
31103
+ for (const agentFile of ts(path47.join(agentsDir, "*.md")).sort()) {
31061
31104
  const { data } = parseMarkdownFrontmatter(agentFile);
31062
31105
  const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
31063
31106
  if (hasCustomProvider) {
31064
- const relativeSource = `agents/${path46.basename(agentFile)}`;
31107
+ const relativeSource = `agents/${path47.basename(agentFile)}`;
31065
31108
  addLoss(lossReport, "cursor", "agents", {
31066
31109
  source: relativeSource,
31067
31110
  fields: [
@@ -31073,7 +31116,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
31073
31116
  "provider",
31074
31117
  "provider-not-representable"
31075
31118
  ),
31076
- detail: `${path46.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
31119
+ detail: `${path47.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
31077
31120
  }
31078
31121
  ]
31079
31122
  });
@@ -31088,10 +31131,18 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
31088
31131
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent3(destination, content, expectedHash)) {
31089
31132
  return { component, status: "skipped-current", path: destination };
31090
31133
  }
31134
+ if (artifactClass === "managed-compiled" && !options.force && hasDriftedSinceInstall(destination, manifest)) {
31135
+ logger.warn(
31136
+ `${destination}: edited since Tangyr wrote it \u2014 applying onConflict: ${config.onConflict}`
31137
+ );
31138
+ if (!handleConflict4(destination, config, options, logger, manifest, scopePath)) {
31139
+ return { component, status: "conflict", path: destination };
31140
+ }
31141
+ }
31091
31142
  if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
31092
31143
  return { component, status: "conflict", path: destination };
31093
31144
  }
31094
- ensureDir(path46.dirname(destination));
31145
+ ensureDir(path47.dirname(destination));
31095
31146
  const clearedLink = clearSymlinkAtDestination(destination);
31096
31147
  if (clearedLink !== null) {
31097
31148
  logger.verbose(
@@ -31158,7 +31209,7 @@ function hashString3(value) {
31158
31209
  // src/adapters/cline.ts
31159
31210
  import crypto9 from "crypto";
31160
31211
  import fs45 from "fs";
31161
- import path47 from "path";
31212
+ import path48 from "path";
31162
31213
  function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
31163
31214
  const scope = options.scope ?? "global";
31164
31215
  const profile = resolveTargetPaths({
@@ -31271,7 +31322,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
31271
31322
  function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
31272
31323
  if (scope === "global" || paths.instructions === null) {
31273
31324
  addLoss(lossReport, "cline", "instructions", {
31274
- source: path47.basename(instructionsSourceLabel(sourceRoot, config)),
31325
+ source: path48.basename(instructionsSourceLabel(sourceRoot, config)),
31275
31326
  fields: [
31276
31327
  {
31277
31328
  field: "instructions",
@@ -31296,7 +31347,7 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
31296
31347
  const baseContent = fs45.existsSync(source) ? fs45.readFileSync(source, "utf8").trim() : "";
31297
31348
  const marker = formatProvenanceMarker(
31298
31349
  "markdown",
31299
- path47.basename(instructionsSourceLabel(sourceRoot, config)),
31350
+ path48.basename(instructionsSourceLabel(sourceRoot, config)),
31300
31351
  hashString4(baseContent),
31301
31352
  "cline"
31302
31353
  );
@@ -31321,11 +31372,11 @@ ${baseContent}
31321
31372
  );
31322
31373
  }
31323
31374
  function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
31324
- const sourceAgentsRoot = path47.join(sourceRoot, config.source.agents);
31375
+ const sourceAgentsRoot = path48.join(sourceRoot, config.source.agents);
31325
31376
  if (!fs45.existsSync(sourceAgentsRoot)) {
31326
31377
  return [skippedMissingSource5("agents", sourceAgentsRoot)];
31327
31378
  }
31328
- const sourceAgents = ts(path47.join(sourceAgentsRoot, "*.md")).sort();
31379
+ const sourceAgents = ts(path48.join(sourceAgentsRoot, "*.md")).sort();
31329
31380
  return sourceAgents.map((agentFile) => {
31330
31381
  compileAgent(agentFile, "cline", mappings, extensions, lossReport);
31331
31382
  if (options.dryRun) {
@@ -31341,14 +31392,14 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
31341
31392
  });
31342
31393
  }
31343
31394
  function syncRules4(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
31344
- const sourceRulesDir = path47.join(sourceRoot, config.source.rules);
31395
+ const sourceRulesDir = path48.join(sourceRoot, config.source.rules);
31345
31396
  if (!fs45.existsSync(sourceRulesDir)) {
31346
31397
  return [skippedMissingSource5("rules", sourceRulesDir)];
31347
31398
  }
31348
31399
  const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
31349
31400
  const rulesDir = resolveTargetPath(paths.rules);
31350
31401
  return compiled.dotRulesFiles.map(({ name, content }) => {
31351
- const destination = path47.join(rulesDir, name);
31402
+ const destination = path48.join(rulesDir, name);
31352
31403
  if (options.dryRun) {
31353
31404
  logger.info(`[dry-run] rules: write ${destination}`);
31354
31405
  return {
@@ -31372,17 +31423,17 @@ function syncRules4(config, sourceRoot, paths, mappings, options, lossReport, lo
31372
31423
  });
31373
31424
  }
31374
31425
  function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
31375
- const sourceCommandsRoot = path47.join(sourceRoot, config.source.commands);
31426
+ const sourceCommandsRoot = path48.join(sourceRoot, config.source.commands);
31376
31427
  if (!fs45.existsSync(sourceCommandsRoot)) {
31377
31428
  return [skippedMissingSource5("commands", sourceCommandsRoot)];
31378
31429
  }
31379
- const sourceCommands = ts(path47.join(sourceCommandsRoot, "*.md")).sort();
31430
+ const sourceCommands = ts(path48.join(sourceCommandsRoot, "*.md")).sort();
31380
31431
  const workflowsRoot = resolveTargetPath(paths.workflows);
31381
31432
  return sourceCommands.map((commandFile) => {
31382
- const baseName = path47.basename(commandFile);
31383
- const destination = path47.join(workflowsRoot, baseName);
31433
+ const baseName = path48.basename(commandFile);
31434
+ const destination = path48.join(workflowsRoot, baseName);
31384
31435
  const commandContent = fs45.readFileSync(commandFile, "utf8");
31385
- const relativeSource = `commands/${path47.basename(commandFile)}`;
31436
+ const relativeSource = `commands/${path48.basename(commandFile)}`;
31386
31437
  const marker = formatProvenanceMarker(
31387
31438
  "markdown",
31388
31439
  relativeSource,
@@ -31420,7 +31471,7 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
31420
31471
  return syncSkillsSlot({
31421
31472
  config,
31422
31473
  sourceRoot,
31423
- source: path47.resolve(sourceRoot, config.source.skills),
31474
+ source: path48.resolve(sourceRoot, config.source.skills),
31424
31475
  destination: resolveTargetPath(paths.skills),
31425
31476
  dryRun: options.dryRun,
31426
31477
  logger,
@@ -31499,11 +31550,11 @@ function syncSettings2(lossReport) {
31499
31550
  };
31500
31551
  }
31501
31552
  function syncProviderAndModel(config, sourceRoot, lossReport) {
31502
- const agentsDir = path47.join(sourceRoot, config.source.agents);
31553
+ const agentsDir = path48.join(sourceRoot, config.source.agents);
31503
31554
  if (!fs45.existsSync(agentsDir)) return;
31504
- for (const agentFile of ts(path47.join(agentsDir, "*.md")).sort()) {
31555
+ for (const agentFile of ts(path48.join(agentsDir, "*.md")).sort()) {
31505
31556
  const { data } = parseMarkdownFrontmatter(agentFile);
31506
- const relativeSource = `agents/${path47.basename(agentFile)}`;
31557
+ const relativeSource = `agents/${path48.basename(agentFile)}`;
31507
31558
  const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
31508
31559
  if (hasCustomProvider) {
31509
31560
  addLoss(lossReport, "cline", "agents", {
@@ -31517,7 +31568,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
31517
31568
  "provider",
31518
31569
  "provider-not-representable"
31519
31570
  ),
31520
- detail: `${path47.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
31571
+ detail: `${path48.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
31521
31572
  }
31522
31573
  ]
31523
31574
  });
@@ -31535,7 +31586,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
31535
31586
  "model",
31536
31587
  "model-not-representable"
31537
31588
  ),
31538
- detail: `${path47.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
31589
+ detail: `${path48.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
31539
31590
  }
31540
31591
  ]
31541
31592
  });
@@ -31550,10 +31601,18 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
31550
31601
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent4(destination, content, expectedHash)) {
31551
31602
  return { component, status: "skipped-current", path: destination };
31552
31603
  }
31604
+ if (artifactClass === "managed-compiled" && !options.force && hasDriftedSinceInstall(destination, manifest)) {
31605
+ logger.warn(
31606
+ `${destination}: edited since Tangyr wrote it \u2014 applying onConflict: ${config.onConflict}`
31607
+ );
31608
+ if (!handleConflict5(destination, config, options, logger, manifest, scopePath)) {
31609
+ return { component, status: "conflict", path: destination };
31610
+ }
31611
+ }
31553
31612
  if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
31554
31613
  return { component, status: "conflict", path: destination };
31555
31614
  }
31556
- ensureDir(path47.dirname(destination));
31615
+ ensureDir(path48.dirname(destination));
31557
31616
  const clearedLink = clearSymlinkAtDestination(destination);
31558
31617
  if (clearedLink !== null) {
31559
31618
  logger.verbose(
@@ -31621,7 +31680,7 @@ function hashString4(value) {
31621
31680
  import crypto10 from "crypto";
31622
31681
  import fs46 from "fs";
31623
31682
  import os6 from "os";
31624
- import path48 from "path";
31683
+ import path49 from "path";
31625
31684
  var import_yaml12 = __toESM(require_dist(), 1);
31626
31685
  function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
31627
31686
  const scope = options.scope ?? "global";
@@ -31639,7 +31698,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
31639
31698
  config_doc: profile.config_doc
31640
31699
  };
31641
31700
  const rules = compileRules(
31642
- path48.join(sourceRoot, config.source.rules),
31701
+ path49.join(sourceRoot, config.source.rules),
31643
31702
  "opencode",
31644
31703
  mappings,
31645
31704
  lossReport
@@ -31759,7 +31818,7 @@ function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, l
31759
31818
  ${agentsAppendix}`.trim() : baseContent;
31760
31819
  const marker = formatProvenanceMarker(
31761
31820
  "markdown",
31762
- path48.basename(instructionsSourceLabel(sourceRoot, config)),
31821
+ path49.basename(instructionsSourceLabel(sourceRoot, config)),
31763
31822
  hashString5(composed),
31764
31823
  "opencode"
31765
31824
  );
@@ -31793,13 +31852,13 @@ ${composed}
31793
31852
  ];
31794
31853
  }
31795
31854
  function declaredInstructionsPath(paths) {
31796
- const configDir = path48.dirname(resolveTargetPath(paths.config_doc));
31855
+ const configDir = path49.dirname(resolveTargetPath(paths.config_doc));
31797
31856
  const instructions = resolveTargetPath(paths.instructions);
31798
- const relative = path48.relative(configDir, instructions);
31857
+ const relative = path49.relative(configDir, instructions);
31799
31858
  if (relative === "AGENTS.md" || relative.startsWith("..")) {
31800
31859
  return null;
31801
31860
  }
31802
- return relative.split(path48.sep).join("/");
31861
+ return relative.split(path49.sep).join("/");
31803
31862
  }
31804
31863
  function withDeclaredInstructions(existing, reference) {
31805
31864
  const listed = Array.isArray(existing) ? existing.filter((entry) => typeof entry === "string") : [];
@@ -31835,22 +31894,22 @@ function declareInstructions(paths, manifest, logger) {
31835
31894
  written,
31836
31895
  logger
31837
31896
  );
31838
- ensureDir(path48.dirname(destination));
31897
+ ensureDir(path49.dirname(destination));
31839
31898
  fs46.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
31840
31899
  `);
31841
31900
  return destination;
31842
31901
  }
31843
31902
  function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
31844
- const sourceAgentsRoot = path48.join(sourceRoot, config.source.agents);
31903
+ const sourceAgentsRoot = path49.join(sourceRoot, config.source.agents);
31845
31904
  if (!fs46.existsSync(sourceAgentsRoot)) {
31846
31905
  return [skippedMissingSource6("agents", sourceAgentsRoot)];
31847
31906
  }
31848
- const sourceAgents = ts(path48.join(sourceAgentsRoot, "*.md")).sort();
31907
+ const sourceAgents = ts(path49.join(sourceAgentsRoot, "*.md")).sort();
31849
31908
  const agentsRoot = resolveTargetPath(paths.agents);
31850
31909
  return sourceAgents.map((agentFile) => {
31851
- const destination = path48.join(
31910
+ const destination = path49.join(
31852
31911
  agentsRoot,
31853
- `${path48.basename(agentFile, ".md")}.md`
31912
+ `${path49.basename(agentFile, ".md")}.md`
31854
31913
  );
31855
31914
  let compiled;
31856
31915
  try {
@@ -31914,11 +31973,11 @@ function applyProviderModelBinding(compiled, mappings) {
31914
31973
  return `${before}${(0, import_yaml12.stringify)(fields).trim()}${after}`;
31915
31974
  }
31916
31975
  function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
31917
- const sourceCommandsRoot = path48.join(sourceRoot, config.source.commands);
31976
+ const sourceCommandsRoot = path49.join(sourceRoot, config.source.commands);
31918
31977
  if (!fs46.existsSync(sourceCommandsRoot)) {
31919
31978
  return [skippedMissingSource6("commands", sourceCommandsRoot)];
31920
31979
  }
31921
- const sourceCommands = ts(path48.join(sourceCommandsRoot, "*.md")).sort();
31980
+ const sourceCommands = ts(path49.join(sourceCommandsRoot, "*.md")).sort();
31922
31981
  const commandsRoot = resolveTargetPath(paths.commands);
31923
31982
  return sourceCommands.map((commandFile) => {
31924
31983
  const { data, body } = parseCommandFile(commandFile);
@@ -31932,7 +31991,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
31932
31991
  if (typeof data.model === "string") {
31933
31992
  frontmatter.model = data.model;
31934
31993
  }
31935
- const relativeSource = `commands/${path48.basename(commandFile)}`;
31994
+ const relativeSource = `commands/${path49.basename(commandFile)}`;
31936
31995
  const marker = formatProvenanceMarker(
31937
31996
  "markdown",
31938
31997
  relativeSource,
@@ -31948,9 +32007,9 @@ ${body.trimEnd()}
31948
32007
  ` : `${marker}
31949
32008
  ${body.trimEnd()}
31950
32009
  `;
31951
- const destination = path48.join(
32010
+ const destination = path49.join(
31952
32011
  commandsRoot,
31953
- `${path48.basename(commandFile, ".md")}.md`
32012
+ `${path49.basename(commandFile, ".md")}.md`
31954
32013
  );
31955
32014
  if (options.dryRun) {
31956
32015
  logger.info(
@@ -31980,7 +32039,7 @@ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scop
31980
32039
  return syncSkillsSlot({
31981
32040
  config,
31982
32041
  sourceRoot,
31983
- source: path48.resolve(sourceRoot, config.source.skills),
32042
+ source: path49.resolve(sourceRoot, config.source.skills),
31984
32043
  destination,
31985
32044
  dryRun: options.dryRun,
31986
32045
  logger,
@@ -32122,7 +32181,7 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings,
32122
32181
  written,
32123
32182
  logger
32124
32183
  );
32125
- ensureDir(path48.dirname(destination));
32184
+ ensureDir(path49.dirname(destination));
32126
32185
  fs46.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
32127
32186
  `);
32128
32187
  }
@@ -32134,10 +32193,18 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
32134
32193
  if (artifactClass === "managed-compiled" && !options.force && isCompiledCurrent5(destination, content, expectedHash)) {
32135
32194
  return { component, status: "skipped-current", path: destination };
32136
32195
  }
32196
+ if (artifactClass === "managed-compiled" && !options.force && hasDriftedSinceInstall(destination, manifest)) {
32197
+ logger.warn(
32198
+ `${destination}: edited since Tangyr wrote it \u2014 applying onConflict: ${config.onConflict}`
32199
+ );
32200
+ if (!handleConflict6(destination, config, options, logger, manifest, scopePath)) {
32201
+ return { component, status: "conflict", path: destination };
32202
+ }
32203
+ }
32137
32204
  if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
32138
32205
  return { component, status: "conflict", path: destination };
32139
32206
  }
32140
- ensureDir(path48.dirname(destination));
32207
+ ensureDir(path49.dirname(destination));
32141
32208
  const clearedLink = clearSymlinkAtDestination(destination);
32142
32209
  if (clearedLink !== null) {
32143
32210
  logger.verbose(
@@ -32258,10 +32325,11 @@ async function runInstallCommand(options, logger) {
32258
32325
  );
32259
32326
  }
32260
32327
  const kitName = resolvedKitName ?? config.kit;
32261
- const kitPath = kitPathOverride ?? (options.kitPath ? path49.resolve(options.kitPath) : config.kitPath);
32262
- if (!kitName && !kitPath) {
32328
+ const kitPath = kitPathOverride ?? (options.kitPath ? path50.resolve(options.kitPath) : config.kitPath);
32329
+ const conventional = conventionalKitPath(configDir);
32330
+ if (!kitName && !kitPath && !conventional) {
32263
32331
  logger.error(
32264
- "No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
32332
+ "No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml, or put the kit in ./tangyr-kit."
32265
32333
  );
32266
32334
  process.exit(1);
32267
32335
  }
@@ -32269,7 +32337,8 @@ async function runInstallCommand(options, logger) {
32269
32337
  const resolution = resolveKitSelection({
32270
32338
  kit: kitName,
32271
32339
  kitPath,
32272
- searchPaths
32340
+ searchPaths,
32341
+ conventionalPath: conventional
32273
32342
  });
32274
32343
  if (!resolution) {
32275
32344
  logger.error(
@@ -32389,8 +32458,8 @@ async function runInstallCommand(options, logger) {
32389
32458
  config: options.config,
32390
32459
  scope
32391
32460
  });
32392
- const skillsSource = path49.resolve(kitInfo.path, config.source.skills);
32393
- const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") && path49.basename(f.path) === "skills";
32461
+ const skillsSource = path50.resolve(kitInfo.path, config.source.skills);
32462
+ const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") && path50.basename(f.path) === "skills";
32394
32463
  const foreignSkillsSlots = new Set(
32395
32464
  assessResult.findings.filter(
32396
32465
  (f) => isPerSkillSkillsSlot(f) && isForeignSkillsSlotSymlink(
@@ -32403,7 +32472,7 @@ async function runInstallCommand(options, logger) {
32403
32472
  );
32404
32473
  const conflictingFindings = assessResult.findings.filter((f) => f.classification === "conflicting").filter((f) => !isPerSkillSkillsSlot(f) || foreignSkillsSlots.has(f.path)).sort((a, b) => a.path.localeCompare(b.path));
32405
32474
  const mappings = loadMappings(kitInfo.path, config, configDir);
32406
- if (postureLeavesConflicts(config.onConflict)) {
32475
+ {
32407
32476
  const foreign = findForeignInstructions(
32408
32477
  conflictingFindings,
32409
32478
  instructionsEntrypoints(tools, scope, projectRoot, mappings)
@@ -32413,7 +32482,6 @@ async function runInstallCommand(options, logger) {
32413
32482
  {
32414
32483
  code: "INSTALL_FOREIGN_INSTRUCTIONS",
32415
32484
  scope,
32416
- onConflict: config.onConflict,
32417
32485
  instructions: foreign.map((one) => ({
32418
32486
  path: one.path,
32419
32487
  targets: one.targets
@@ -32425,14 +32493,12 @@ async function runInstallCommand(options, logger) {
32425
32493
  process.stderr.write(`${payload}
32426
32494
  `);
32427
32495
  logger.error("Refusing to install: nothing has been written.");
32428
- for (const line of describeForeignInstructions(
32429
- foreign,
32430
- config.onConflict === "ask" ? "ask" : "skip",
32431
- projectRoot
32432
- )) {
32496
+ for (const line of describeForeignInstructions(foreign, projectRoot)) {
32433
32497
  logger.error(line);
32434
32498
  }
32435
- process.exit(1);
32499
+ logger.error("");
32500
+ logger.error("Exit code 2 (conflict). Nothing was written.");
32501
+ process.exit(2);
32436
32502
  }
32437
32503
  }
32438
32504
  const skippedTargetPaths = /* @__PURE__ */ new Set();
@@ -32461,7 +32527,7 @@ async function runInstallCommand(options, logger) {
32461
32527
  let instructionsLabel;
32462
32528
  try {
32463
32529
  const resolved = resolveInstructionsSource(kitInfo.path, config);
32464
- instructionsLabel = resolved ? path49.relative(kitInfo.path, resolved.file) : "(none \u2014 no instructions file resolves in this kit)";
32530
+ instructionsLabel = resolved ? path50.relative(kitInfo.path, resolved.file) : "(none \u2014 no instructions file resolves in this kit)";
32465
32531
  } catch (err) {
32466
32532
  logger.error(
32467
32533
  `[dry-run] ${err instanceof Error ? err.message : String(err)}`
@@ -32489,7 +32555,7 @@ async function runInstallCommand(options, logger) {
32489
32555
  }
32490
32556
  }
32491
32557
  logger.info(
32492
- `[dry-run] Total: ${plannedTotal} destination(s); manifest at ${path49.join(scopePath, "manifest.json")}`
32558
+ `[dry-run] Total: ${plannedTotal} destination(s); manifest at ${path50.join(scopePath, "manifest.json")}`
32493
32559
  );
32494
32560
  return;
32495
32561
  }
@@ -32693,20 +32759,20 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
32693
32759
  writeManifest(scopePath, manifest);
32694
32760
  logger.info(`
32695
32761
  Installation complete: ${installedCount} files installed.`);
32696
- logger.info(`Manifest written to ${path49.join(scopePath, "manifest.json")}`);
32762
+ logger.info(`Manifest written to ${path50.join(scopePath, "manifest.json")}`);
32697
32763
  logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
32698
32764
  logger.info(`Scope: ${scope}`);
32699
32765
  logger.info(`Tools: ${tools.join(", ")}`);
32700
32766
  reportHookRejections(
32701
32767
  installLossReport,
32702
32768
  tools,
32703
- path49.resolve(kitInfo.path, "hooks"),
32769
+ path50.resolve(kitInfo.path, "hooks"),
32704
32770
  kitInfo.components.hooks.declared
32705
32771
  );
32706
32772
  const hooksConflict = reportHooksSourceConflict(
32707
32773
  installLossReport,
32708
32774
  tools,
32709
- path49.resolve(kitInfo.path, "hooks"),
32775
+ path50.resolve(kitInfo.path, "hooks"),
32710
32776
  kitInfo.components.hooks.declared
32711
32777
  );
32712
32778
  if (hooksConflict) {
@@ -33099,17 +33165,17 @@ function installClaudeCodeSkills(config, kitInfo, manifest, options, logger, sco
33099
33165
  manifest,
33100
33166
  scopePath
33101
33167
  );
33102
- const skillsSource = path49.resolve(kitInfo.path, config.source.skills);
33168
+ const skillsSource = path50.resolve(kitInfo.path, config.source.skills);
33103
33169
  let count = 0;
33104
33170
  for (const outcome of outcomes) {
33105
33171
  if (outcome.status !== "success" && outcome.status !== "skipped-current") {
33106
33172
  continue;
33107
33173
  }
33108
- const skillName = path49.basename(outcome.path);
33174
+ const skillName = path50.basename(outcome.path);
33109
33175
  addArtifactToManifest(manifest, {
33110
33176
  relativePath: `claude-code/skills/${skillName}`,
33111
33177
  path: outcome.path,
33112
- hash: describeArtifactState(outcome.path) ?? `dir:${path49.join(skillsSource, skillName)}`,
33178
+ hash: describeArtifactState(outcome.path) ?? `dir:${path50.join(skillsSource, skillName)}`,
33113
33179
  origin: "tangyr-managed"
33114
33180
  });
33115
33181
  count++;
@@ -33123,7 +33189,7 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
33123
33189
  logger.verbose(` skipped (operator choice): ${placement.destination}`);
33124
33190
  continue;
33125
33191
  }
33126
- const destDir = path49.dirname(placement.destination);
33192
+ const destDir = path50.dirname(placement.destination);
33127
33193
  fs47.mkdirSync(destDir, { recursive: true });
33128
33194
  if (placement.type === "symlink") {
33129
33195
  if (fs47.existsSync(placement.destination) || isSymlink2(placement.destination)) {
@@ -33440,11 +33506,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
33440
33506
  if (outcome.path === mcpFile2) {
33441
33507
  return "cline/mcp.json";
33442
33508
  }
33443
- if (outcome.path.startsWith(`${workflowsRoot}${path49.sep}`)) {
33444
- return `cline/workflows/${path49.basename(outcome.path)}`;
33509
+ if (outcome.path.startsWith(`${workflowsRoot}${path50.sep}`)) {
33510
+ return `cline/workflows/${path50.basename(outcome.path)}`;
33445
33511
  }
33446
- if (outcome.path.startsWith(`${rulesRoot2}${path49.sep}`)) {
33447
- return `cline/rules/${path49.basename(outcome.path)}`;
33512
+ if (outcome.path.startsWith(`${rulesRoot2}${path50.sep}`)) {
33513
+ return `cline/rules/${path50.basename(outcome.path)}`;
33448
33514
  }
33449
33515
  return null;
33450
33516
  }
@@ -33480,14 +33546,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
33480
33546
  if (outcome.path === permissionsFile) {
33481
33547
  return "cursor/permissions.json";
33482
33548
  }
33483
- if (outcome.path.startsWith(`${agentsRoot2}${path49.sep}`)) {
33484
- return `cursor/agents/${path49.basename(outcome.path)}`;
33549
+ if (outcome.path.startsWith(`${agentsRoot2}${path50.sep}`)) {
33550
+ return `cursor/agents/${path50.basename(outcome.path)}`;
33485
33551
  }
33486
- if (outcome.path.startsWith(`${rulesRoot2}${path49.sep}`)) {
33487
- return `cursor/rules/${path49.basename(outcome.path)}`;
33552
+ if (outcome.path.startsWith(`${rulesRoot2}${path50.sep}`)) {
33553
+ return `cursor/rules/${path50.basename(outcome.path)}`;
33488
33554
  }
33489
- if (outcome.path.startsWith(`${skillsRoot2}${path49.sep}`)) {
33490
- const rel = path49.relative(skillsRoot2, outcome.path);
33555
+ if (outcome.path.startsWith(`${skillsRoot2}${path50.sep}`)) {
33556
+ const rel = path50.relative(skillsRoot2, outcome.path);
33491
33557
  return `cursor/skills/${rel}`;
33492
33558
  }
33493
33559
  return null;
@@ -33513,14 +33579,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
33513
33579
  if (outcome.path === skillsSharedRoot) {
33514
33580
  return "opencode/skills_shared";
33515
33581
  }
33516
- if (outcome.path.startsWith(`${agentsRoot2}${path49.sep}`)) {
33517
- return `opencode/agents/${path49.basename(outcome.path)}`;
33582
+ if (outcome.path.startsWith(`${agentsRoot2}${path50.sep}`)) {
33583
+ return `opencode/agents/${path50.basename(outcome.path)}`;
33518
33584
  }
33519
- if (outcome.path.startsWith(`${commandsRoot}${path49.sep}`)) {
33520
- return `opencode/commands/${path49.basename(outcome.path)}`;
33585
+ if (outcome.path.startsWith(`${commandsRoot}${path50.sep}`)) {
33586
+ return `opencode/commands/${path50.basename(outcome.path)}`;
33521
33587
  }
33522
33588
  if (outcome.path === configDocFile) {
33523
- return `opencode/${path49.basename(outcome.path)}`;
33589
+ return `opencode/${path50.basename(outcome.path)}`;
33524
33590
  }
33525
33591
  return null;
33526
33592
  }
@@ -33537,29 +33603,29 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
33537
33603
  const hooksRoot = resolveTargetPath(copilot.hooks);
33538
33604
  const mcpFile2 = resolveTargetPath(copilot.mcp_shared_file);
33539
33605
  const instructionsMirror = copilot.instructions !== null ? resolveTargetPath(copilot.instructions) : null;
33540
- if (copilot.rules !== null && outcome.path.startsWith(`${resolveTargetPath(copilot.rules)}${path49.sep}`)) {
33541
- return `copilot/rules/${path49.relative(resolveTargetPath(copilot.rules), outcome.path)}`;
33606
+ if (copilot.rules !== null && outcome.path.startsWith(`${resolveTargetPath(copilot.rules)}${path50.sep}`)) {
33607
+ return `copilot/rules/${path50.relative(resolveTargetPath(copilot.rules), outcome.path)}`;
33542
33608
  }
33543
- if (outcome.path.startsWith(`${skillsRoot2}${path49.sep}`)) {
33544
- return `copilot/skills/${path49.relative(skillsRoot2, outcome.path)}`;
33609
+ if (outcome.path.startsWith(`${skillsRoot2}${path50.sep}`)) {
33610
+ return `copilot/skills/${path50.relative(skillsRoot2, outcome.path)}`;
33545
33611
  }
33546
33612
  if (outcome.path === skillsRoot2) {
33547
33613
  return "copilot/skills";
33548
33614
  }
33549
33615
  if (instructionsMirror !== null && outcome.path === instructionsMirror) {
33550
- return `copilot/${path49.basename(outcome.path)}`;
33616
+ return `copilot/${path50.basename(outcome.path)}`;
33551
33617
  }
33552
- if (outcome.path.startsWith(`${agentsRoot2}${path49.sep}`)) {
33553
- return `copilot/agents/${path49.basename(outcome.path)}`;
33618
+ if (outcome.path.startsWith(`${agentsRoot2}${path50.sep}`)) {
33619
+ return `copilot/agents/${path50.basename(outcome.path)}`;
33554
33620
  }
33555
- if (outcome.path.startsWith(`${promptsRoot}${path49.sep}`)) {
33556
- return `copilot/prompts/${path49.basename(outcome.path)}`;
33621
+ if (outcome.path.startsWith(`${promptsRoot}${path50.sep}`)) {
33622
+ return `copilot/prompts/${path50.basename(outcome.path)}`;
33557
33623
  }
33558
- if (outcome.path.startsWith(`${hooksRoot}${path49.sep}`)) {
33559
- return `copilot/hooks/${path49.basename(outcome.path)}`;
33624
+ if (outcome.path.startsWith(`${hooksRoot}${path50.sep}`)) {
33625
+ return `copilot/hooks/${path50.basename(outcome.path)}`;
33560
33626
  }
33561
33627
  if (outcome.path === mcpFile2) {
33562
- return `copilot/${path49.basename(outcome.path)}`;
33628
+ return `copilot/${path50.basename(outcome.path)}`;
33563
33629
  }
33564
33630
  return null;
33565
33631
  }
@@ -33576,17 +33642,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
33576
33642
  if (outcome.path === skillsRoot) {
33577
33643
  return "codex/skills";
33578
33644
  }
33579
- if (outcome.path.startsWith(`${agentsRoot}${path49.sep}`)) {
33580
- return `codex/agents/${path49.basename(outcome.path)}`;
33645
+ if (outcome.path.startsWith(`${agentsRoot}${path50.sep}`)) {
33646
+ return `codex/agents/${path50.basename(outcome.path)}`;
33581
33647
  }
33582
- if (outcome.path.startsWith(`${rulesRoot}${path49.sep}`)) {
33583
- return `codex/rules/${path49.basename(outcome.path)}`;
33648
+ if (outcome.path.startsWith(`${rulesRoot}${path50.sep}`)) {
33649
+ return `codex/rules/${path50.basename(outcome.path)}`;
33584
33650
  }
33585
33651
  if (outcome.path === hooksFile) {
33586
- return `codex/${path49.basename(outcome.path)}`;
33652
+ return `codex/${path50.basename(outcome.path)}`;
33587
33653
  }
33588
33654
  if (outcome.path === mcpFile) {
33589
- return `codex/${path49.basename(outcome.path)}`;
33655
+ return `codex/${path50.basename(outcome.path)}`;
33590
33656
  }
33591
33657
  return null;
33592
33658
  }
@@ -33655,7 +33721,7 @@ function getClaudeCodePlacements(kitInfo, config, scope = "global", projectRoot,
33655
33721
  rules: resolvedPaths.rules
33656
33722
  };
33657
33723
  for (const [component, targetPath] of Object.entries(componentDirMap)) {
33658
- const componentDir = path49.join(kitInfo.path, component);
33724
+ const componentDir = path50.join(kitInfo.path, component);
33659
33725
  if (fs47.existsSync(componentDir) && fs47.statSync(componentDir).isDirectory()) {
33660
33726
  placements.push({
33661
33727
  source: componentDir,
@@ -33686,7 +33752,7 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile, config) {
33686
33752
  rules: profile.rules
33687
33753
  };
33688
33754
  for (const [component, targetPath] of Object.entries(componentDirMap)) {
33689
- const componentDir = path49.join(kitInfo.path, component);
33755
+ const componentDir = path50.join(kitInfo.path, component);
33690
33756
  if (fs47.existsSync(componentDir) && fs47.statSync(componentDir).isDirectory()) {
33691
33757
  placements.push({
33692
33758
  source: componentDir,
@@ -33703,7 +33769,7 @@ function collectAllFiles(kitInfo, config) {
33703
33769
  const files = /* @__PURE__ */ new Map();
33704
33770
  const entrypoint = resolveInstructionsSource(kitInfo.path, config);
33705
33771
  if (entrypoint) {
33706
- files.set(path49.basename(entrypoint.file), entrypoint.file);
33772
+ files.set(path50.basename(entrypoint.file), entrypoint.file);
33707
33773
  }
33708
33774
  for (const [component, reconciliation] of Object.entries(
33709
33775
  kitInfo.components
@@ -33712,8 +33778,8 @@ function collectAllFiles(kitInfo, config) {
33712
33778
  const missingSet = new Set(reconciliation.missing);
33713
33779
  for (const entry of reconciliation.declared) {
33714
33780
  if (missingSet.has(entry)) continue;
33715
- const relPath = isSkills ? path49.join(component, entry) : path49.join(component, `${entry}.md`);
33716
- files.set(relPath, path49.join(kitInfo.path, relPath));
33781
+ const relPath = isSkills ? path50.join(component, entry) : path50.join(component, `${entry}.md`);
33782
+ files.set(relPath, path50.join(kitInfo.path, relPath));
33717
33783
  }
33718
33784
  }
33719
33785
  return files;
@@ -33746,10 +33812,10 @@ function skillsSubPathKey(tool, outcomePath, mappings, scope, projectRoot) {
33746
33812
  continue;
33747
33813
  }
33748
33814
  const root = resolveTargetPath(slot);
33749
- if (!outcomePath.startsWith(`${root}${path49.sep}`)) {
33815
+ if (!outcomePath.startsWith(`${root}${path50.sep}`)) {
33750
33816
  continue;
33751
33817
  }
33752
- const inside = path49.relative(root, outcomePath).split(path49.sep).join("/");
33818
+ const inside = path50.relative(root, outcomePath).split(path50.sep).join("/");
33753
33819
  return `${tool}/skills/${inside}`;
33754
33820
  }
33755
33821
  return null;
@@ -33794,14 +33860,14 @@ async function runKitUpdateCommand(options, logger) {
33794
33860
  }
33795
33861
 
33796
33862
  // src/commands/list.ts
33797
- import path50 from "path";
33863
+ import path51 from "path";
33798
33864
  function runListCommand(options, logger) {
33799
33865
  let searchPaths = [];
33800
- let directKitPath = options.kitPath ? path50.resolve(options.kitPath) : void 0;
33866
+ let directKitPath = options.kitPath ? path51.resolve(options.kitPath) : void 0;
33801
33867
  try {
33802
33868
  const { config, configDir } = resolveConfig(options.config);
33803
33869
  searchPaths = config.kitSearchPaths ?? [
33804
- path50.join(configDir, "operating-kits")
33870
+ path51.join(configDir, "operating-kits")
33805
33871
  ];
33806
33872
  directKitPath = directKitPath ?? config.kitPath;
33807
33873
  } catch (err) {
@@ -33876,7 +33942,7 @@ function withDirectKit(kits, directKitPath) {
33876
33942
  return kits;
33877
33943
  }
33878
33944
  const directKit = loadKit(directKitPath);
33879
- if (kits.some((kit) => path50.resolve(kit.path) === directKit.path)) {
33945
+ if (kits.some((kit) => path51.resolve(kit.path) === directKit.path)) {
33880
33946
  return kits;
33881
33947
  }
33882
33948
  return [...kits, directKit];
@@ -33885,7 +33951,7 @@ function withDirectKit(kits, directKitPath) {
33885
33951
  // src/commands/probe.ts
33886
33952
  import { spawnSync as spawnSync2 } from "child_process";
33887
33953
  import fs48 from "fs";
33888
- import path51 from "path";
33954
+ import path52 from "path";
33889
33955
  function runProbeCommand(options, logger) {
33890
33956
  const { config, configDir, configSource, sourceRoot } = resolveRuntime(
33891
33957
  options,
@@ -33913,7 +33979,7 @@ function runProbeCommand(options, logger) {
33913
33979
  toProbeRow(
33914
33980
  target,
33915
33981
  key,
33916
- scope === "project" ? path51.resolve(projectRoot ?? process.cwd(), rawPath) : rawPath
33982
+ scope === "project" ? path52.resolve(projectRoot ?? process.cwd(), rawPath) : rawPath
33917
33983
  )
33918
33984
  );
33919
33985
  }
@@ -33979,7 +34045,7 @@ function commandProbeRows(target, key, command, args) {
33979
34045
  // src/commands/status.ts
33980
34046
  import crypto11 from "crypto";
33981
34047
  import fs49 from "fs";
33982
- import path52 from "path";
34048
+ import path53 from "path";
33983
34049
  function runStatusCommand(options, logger) {
33984
34050
  const { config, configDir, configSource, sourceRoot } = resolveRuntime(
33985
34051
  options,
@@ -34085,11 +34151,11 @@ function classifyTargetRows(target, config, sourceRoot, configDir, scope, projec
34085
34151
  }
34086
34152
  }
34087
34153
  function sourceMarkdownFiles(sourceRoot, componentPath) {
34088
- const root = path52.join(sourceRoot, componentPath);
34154
+ const root = path53.join(sourceRoot, componentPath);
34089
34155
  if (!fs49.existsSync(root)) {
34090
34156
  return [];
34091
34157
  }
34092
- return ts(path52.join(root, "*.md")).sort();
34158
+ return ts(path53.join(root, "*.md")).sort();
34093
34159
  }
34094
34160
  function notRepresentableRow(component, detail) {
34095
34161
  return {
@@ -34236,7 +34302,7 @@ function classifyOpenCodeFiles(config, sourceRoot, configDir, scope, projectRoot
34236
34302
  const rows = [];
34237
34303
  const instructionsSource = instructionsSourcePath(sourceRoot, config);
34238
34304
  const rules = compileRules(
34239
- path52.join(sourceRoot, config.source.rules),
34305
+ path53.join(sourceRoot, config.source.rules),
34240
34306
  "opencode",
34241
34307
  mappings,
34242
34308
  createLossReport()
@@ -34263,10 +34329,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
34263
34329
  )) {
34264
34330
  rows.push(
34265
34331
  classifyCompiledFile(
34266
- `agents/${path52.basename(agentFile, ".md")}`,
34267
- path52.join(
34332
+ `agents/${path53.basename(agentFile, ".md")}`,
34333
+ path53.join(
34268
34334
  resolveTargetPath(paths.agents),
34269
- `${path52.basename(agentFile, ".md")}.md`
34335
+ `${path53.basename(agentFile, ".md")}.md`
34270
34336
  ),
34271
34337
  "opencode",
34272
34338
  computeSourceHash(agentFile),
@@ -34281,10 +34347,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
34281
34347
  )) {
34282
34348
  rows.push(
34283
34349
  classifyCompiledFile(
34284
- `commands/${path52.basename(commandFile, ".md")}`,
34285
- path52.join(
34350
+ `commands/${path53.basename(commandFile, ".md")}`,
34351
+ path53.join(
34286
34352
  resolveTargetPath(paths.commands),
34287
- `${path52.basename(commandFile, ".md")}.md`
34353
+ `${path53.basename(commandFile, ".md")}.md`
34288
34354
  ),
34289
34355
  "opencode",
34290
34356
  computeSourceHash(commandFile),
@@ -34366,10 +34432,10 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
34366
34432
  )) {
34367
34433
  rows.push(
34368
34434
  classifyCompiledFile(
34369
- `agents/${path52.basename(agentFile, ".md")}`,
34370
- path52.join(
34435
+ `agents/${path53.basename(agentFile, ".md")}`,
34436
+ path53.join(
34371
34437
  resolveTargetPath(paths.agents),
34372
- `${path52.basename(agentFile, ".md")}.md`
34438
+ `${path53.basename(agentFile, ".md")}.md`
34373
34439
  ),
34374
34440
  "cursor",
34375
34441
  computeSourceHash(agentFile),
@@ -34386,7 +34452,7 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
34386
34452
  rows.push(
34387
34453
  classifyCompiledFile(
34388
34454
  `rules/${ruleFile.name}`,
34389
- path52.join(resolveTargetPath(paths.rules), ruleFile.name),
34455
+ path53.join(resolveTargetPath(paths.rules), ruleFile.name),
34390
34456
  "cursor",
34391
34457
  void 0,
34392
34458
  config,
@@ -34400,11 +34466,11 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
34400
34466
  sourceRoot,
34401
34467
  config.source.commands
34402
34468
  )) {
34403
- const baseName = path52.basename(commandFile, ".md");
34469
+ const baseName = path53.basename(commandFile, ".md");
34404
34470
  rows.push(
34405
34471
  classifyCompiledFile(
34406
34472
  `commands/${baseName}`,
34407
- path52.join(resolveTargetPath(paths.skills), baseName, "SKILL.md"),
34473
+ path53.join(resolveTargetPath(paths.skills), baseName, "SKILL.md"),
34408
34474
  "cursor",
34409
34475
  computeSourceHash(commandFile),
34410
34476
  config,
@@ -34487,7 +34553,7 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
34487
34553
  rows.push(
34488
34554
  classifyCompiledFile(
34489
34555
  `rules/${ruleFile.name}`,
34490
- path52.join(resolveTargetPath(paths.rules), ruleFile.name),
34556
+ path53.join(resolveTargetPath(paths.rules), ruleFile.name),
34491
34557
  "cline",
34492
34558
  void 0,
34493
34559
  config,
@@ -34503,10 +34569,10 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
34503
34569
  )) {
34504
34570
  rows.push(
34505
34571
  classifyCompiledFile(
34506
- `commands/${path52.basename(commandFile, ".md")}`,
34507
- path52.join(
34572
+ `commands/${path53.basename(commandFile, ".md")}`,
34573
+ path53.join(
34508
34574
  resolveTargetPath(paths.workflows),
34509
- path52.basename(commandFile)
34575
+ path53.basename(commandFile)
34510
34576
  ),
34511
34577
  "cline",
34512
34578
  computeSourceHash(commandFile),
@@ -34547,7 +34613,7 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
34547
34613
  return rows;
34548
34614
  }
34549
34615
  function compileRulesFiles(config, sourceRoot, target, mappings) {
34550
- const rulesSource = path52.join(sourceRoot, config.source.rules);
34616
+ const rulesSource = path53.join(sourceRoot, config.source.rules);
34551
34617
  if (!fs49.existsSync(rulesSource)) {
34552
34618
  return [];
34553
34619
  }
@@ -34578,7 +34644,7 @@ function classifyCodexFiles(config, sourceRoot, configDir, scope, projectRoot) {
34578
34644
  rules: paths.rules
34579
34645
  };
34580
34646
  const rules = compileRules(
34581
- path52.join(sourceRoot, config.source.rules),
34647
+ path53.join(sourceRoot, config.source.rules),
34582
34648
  "codex",
34583
34649
  mappings,
34584
34650
  createLossReport()
@@ -34589,10 +34655,10 @@ function classifyCodexFiles(config, sourceRoot, configDir, scope, projectRoot) {
34589
34655
  --- tangyr managed rules ---
34590
34656
  ${rules.agentsAppendix}`.trim();
34591
34657
  const agentFiles = ts(
34592
- path52.join(sourceRoot, config.source.agents, "*.md")
34658
+ path53.join(sourceRoot, config.source.agents, "*.md")
34593
34659
  ).sort();
34594
34660
  const hooksPresent = hooksSourceExists(sourceRoot, config);
34595
- const mcpSource = path52.join(sourceRoot, config.source.mcp);
34661
+ const mcpSource = path53.join(sourceRoot, config.source.mcp);
34596
34662
  const ruleRows = rules.dotRulesFiles.length === 0 ? [
34597
34663
  {
34598
34664
  component: "rules",
@@ -34603,7 +34669,7 @@ ${rules.agentsAppendix}`.trim();
34603
34669
  ] : rules.dotRulesFiles.map(
34604
34670
  (ruleFile) => classifyCompiledFile(
34605
34671
  `rules/${ruleFile.name}`,
34606
- path52.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
34672
+ path53.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
34607
34673
  "codex",
34608
34674
  void 0,
34609
34675
  config,
@@ -34628,10 +34694,10 @@ ${rules.agentsAppendix}`.trim();
34628
34694
  ),
34629
34695
  ...agentFiles.map(
34630
34696
  (agentFile) => classifyCompiledFile(
34631
- `agents/${path52.basename(agentFile, ".md")}`,
34632
- path52.join(
34697
+ `agents/${path53.basename(agentFile, ".md")}`,
34698
+ path53.join(
34633
34699
  resolveTargetPath(codexPaths.agents),
34634
- `${path52.basename(agentFile, ".md")}.toml`
34700
+ `${path53.basename(agentFile, ".md")}.toml`
34635
34701
  ),
34636
34702
  "codex",
34637
34703
  computeSourceHash(agentFile),
@@ -34725,20 +34791,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
34725
34791
  mcpSharedFile: paths.mcp_shared_file
34726
34792
  };
34727
34793
  const agentFiles = ts(
34728
- path52.join(sourceRoot, config.source.agents, "*.md")
34794
+ path53.join(sourceRoot, config.source.agents, "*.md")
34729
34795
  ).sort();
34730
34796
  const commandFiles = ts(
34731
- path52.join(sourceRoot, config.source.commands, "*.md")
34797
+ path53.join(sourceRoot, config.source.commands, "*.md")
34732
34798
  ).sort();
34733
34799
  const hooksPresent = hooksSourceExists(sourceRoot, config);
34734
- const mcpSource = path52.join(sourceRoot, config.source.mcp);
34800
+ const mcpSource = path53.join(sourceRoot, config.source.mcp);
34735
34801
  return [
34736
34802
  ...agentFiles.map(
34737
34803
  (agentFile) => classifyCompiledFile(
34738
- `agents/${path52.basename(agentFile, ".md")}`,
34739
- path52.join(
34804
+ `agents/${path53.basename(agentFile, ".md")}`,
34805
+ path53.join(
34740
34806
  resolveTargetPath(copilotPaths.agents),
34741
- `${path52.basename(agentFile, ".md")}.agent.md`
34807
+ `${path53.basename(agentFile, ".md")}.agent.md`
34742
34808
  ),
34743
34809
  "copilot",
34744
34810
  computeSourceHash(agentFile),
@@ -34755,10 +34821,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
34755
34821
  ),
34756
34822
  ...commandFiles.map(
34757
34823
  (commandFile) => classifyCompiledFile(
34758
- `commands/${path52.basename(commandFile, ".md")}`,
34759
- path52.join(
34824
+ `commands/${path53.basename(commandFile, ".md")}`,
34825
+ path53.join(
34760
34826
  resolveTargetPath(copilotPaths.prompts),
34761
- `${path52.basename(commandFile, ".md")}.prompt.md`
34827
+ `${path53.basename(commandFile, ".md")}.prompt.md`
34762
34828
  ),
34763
34829
  "copilot",
34764
34830
  computeSourceHash(commandFile),
@@ -34777,14 +34843,14 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
34777
34843
  sourceRoot
34778
34844
  ),
34779
34845
  hooksPresent ? classifyCompiledHooksByProvenance(
34780
- path52.join(
34846
+ path53.join(
34781
34847
  resolveTargetPath(copilotPaths.hooks),
34782
34848
  "tangyr-managed.json"
34783
34849
  ),
34784
34850
  "copilot"
34785
34851
  ) : notConfiguredRow(
34786
34852
  "hooks",
34787
- path52.join(
34853
+ path53.join(
34788
34854
  resolveTargetPath(copilotPaths.hooks),
34789
34855
  "tangyr-managed.json"
34790
34856
  )
@@ -34809,7 +34875,7 @@ function notConfiguredRow(component, filePath) {
34809
34875
  }
34810
34876
  function classifyDirectArtifact(artifact, config, sourceRoot) {
34811
34877
  const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
34812
- const sourcePath = artifact.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : artifact.sourceKey ? path52.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
34878
+ const sourcePath = artifact.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : artifact.sourceKey ? path53.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
34813
34879
  if (artifact.sourceKey === "skills" && artifactClass === "unmanaged-conflict") {
34814
34880
  const perSkill = classifyPerSkillSlot(artifact.path, sourceRoot);
34815
34881
  if (perSkill) {
@@ -34921,7 +34987,7 @@ function classifyPerSkillSlot(slotPath, sourceRoot) {
34921
34987
  return null;
34922
34988
  }
34923
34989
  const ours = links.filter(
34924
- (entry) => isOurSymlink(path52.join(slotPath, entry.name), sourceRoot)
34990
+ (entry) => isOurSymlink(path53.join(slotPath, entry.name), sourceRoot)
34925
34991
  );
34926
34992
  if (ours.length === 0) {
34927
34993
  return null;
@@ -34933,9 +34999,9 @@ function classifyClaudeSharedFiles(config, sourceRoot, settingsPath, claudeJsonP
34933
34999
  classifyHooks(settingsPath),
34934
35000
  classifySettings(
34935
35001
  settingsPath,
34936
- path52.resolve(sourceRoot, config.source.settings)
35002
+ path53.resolve(sourceRoot, config.source.settings)
34937
35003
  ),
34938
- classifyMcp(claudeJsonPath, path52.resolve(sourceRoot, config.source.mcp))
35004
+ classifyMcp(claudeJsonPath, path53.resolve(sourceRoot, config.source.mcp))
34939
35005
  ];
34940
35006
  }
34941
35007
  function claudeSharedFileRows(config, sourceRoot, configDir, scope, projectRoot) {
@@ -35113,7 +35179,7 @@ function hashString6(value) {
35113
35179
 
35114
35180
  // src/commands/sync.ts
35115
35181
  import fs50 from "fs";
35116
- import path53 from "path";
35182
+ import path54 from "path";
35117
35183
 
35118
35184
  // node_modules/chalk/source/vendor/ansi-styles/index.js
35119
35185
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -35650,6 +35716,8 @@ async function runSyncCommand(options, logger) {
35650
35716
  const syncOptions = toSyncOptions(options, config, configDir, configSource);
35651
35717
  const targets = activeTargets(config, options.target);
35652
35718
  const results = [];
35719
+ const recordInto = () => options.dryRun ? void 0 : kitSync?.manifest;
35720
+ const recordUnder = () => options.dryRun ? void 0 : kitSync?.scopePath;
35653
35721
  const lossReport = createLossReport();
35654
35722
  const mappings = targets.includes("copilot") || targets.includes("codex") || targets.includes("opencode") || targets.includes("cursor") || targets.includes("cline") || targets.some((target) => isDeferredTarget(target)) ? loadMappings(sourceRoot, config, configDir) : void 0;
35655
35723
  const kitSync = kitInfo ? prepareKitManifest(syncOptions.scope, syncOptions.projectRoot, kitInfo) : void 0;
@@ -35684,8 +35752,8 @@ async function runSyncCommand(options, logger) {
35684
35752
  { ...syncOptions, claudeRoot },
35685
35753
  logger,
35686
35754
  allMappings?.platformPaths,
35687
- void 0,
35688
- void 0,
35755
+ recordInto(),
35756
+ recordUnder(),
35689
35757
  allMappings,
35690
35758
  lossReport
35691
35759
  )
@@ -35699,8 +35767,8 @@ async function runSyncCommand(options, logger) {
35699
35767
  syncOptions,
35700
35768
  logger,
35701
35769
  allMappings?.platformPaths,
35702
- void 0,
35703
- void 0,
35770
+ recordInto(),
35771
+ recordUnder(),
35704
35772
  allMappings,
35705
35773
  lossReport
35706
35774
  )
@@ -35718,7 +35786,9 @@ async function runSyncCommand(options, logger) {
35718
35786
  mappings.extensions,
35719
35787
  syncOptions,
35720
35788
  lossReport,
35721
- logger
35789
+ logger,
35790
+ recordInto(),
35791
+ recordUnder()
35722
35792
  )
35723
35793
  );
35724
35794
  } else if (target === "codex") {
@@ -35733,7 +35803,9 @@ async function runSyncCommand(options, logger) {
35733
35803
  mappings.extensions,
35734
35804
  syncOptions,
35735
35805
  lossReport,
35736
- logger
35806
+ logger,
35807
+ recordInto(),
35808
+ recordUnder()
35737
35809
  )
35738
35810
  );
35739
35811
  } else if (target === "opencode") {
@@ -35748,7 +35820,9 @@ async function runSyncCommand(options, logger) {
35748
35820
  mappings.extensions,
35749
35821
  syncOptions,
35750
35822
  lossReport,
35751
- logger
35823
+ logger,
35824
+ recordInto(),
35825
+ recordUnder()
35752
35826
  )
35753
35827
  );
35754
35828
  } else if (target === "cursor") {
@@ -35763,7 +35837,9 @@ async function runSyncCommand(options, logger) {
35763
35837
  mappings.extensions,
35764
35838
  syncOptions,
35765
35839
  lossReport,
35766
- logger
35840
+ logger,
35841
+ recordInto(),
35842
+ recordUnder()
35767
35843
  )
35768
35844
  );
35769
35845
  } else if (target === "cline") {
@@ -35778,7 +35854,9 @@ async function runSyncCommand(options, logger) {
35778
35854
  mappings.extensions,
35779
35855
  syncOptions,
35780
35856
  lossReport,
35781
- logger
35857
+ logger,
35858
+ recordInto(),
35859
+ recordUnder()
35782
35860
  )
35783
35861
  );
35784
35862
  } else if (isDeferredTarget(target)) {
@@ -35793,13 +35871,13 @@ async function runSyncCommand(options, logger) {
35793
35871
  reportHookRejections(
35794
35872
  lossReport,
35795
35873
  targets,
35796
- path53.resolve(kitInfo.path, "hooks"),
35874
+ path54.resolve(kitInfo.path, "hooks"),
35797
35875
  kitInfo.components.hooks.declared
35798
35876
  );
35799
35877
  const hooksConflict = reportHooksSourceConflict(
35800
35878
  lossReport,
35801
35879
  targets,
35802
- path53.resolve(kitInfo.path, "hooks"),
35880
+ path54.resolve(kitInfo.path, "hooks"),
35803
35881
  kitInfo.components.hooks.declared
35804
35882
  );
35805
35883
  if (hooksConflict) {
@@ -35865,7 +35943,13 @@ async function runSyncCommand(options, logger) {
35865
35943
  syncOptions.scope,
35866
35944
  syncOptions.projectRoot
35867
35945
  );
35868
- updateManifest(kitInfo, kitSync);
35946
+ updateManifest(
35947
+ kitInfo,
35948
+ kitSync,
35949
+ new Set(
35950
+ results.flatMap((result) => result.outcomes).filter((outcome) => outcome.status === "success").map((outcome) => path54.resolve(outcome.path))
35951
+ )
35952
+ );
35869
35953
  logger.info(
35870
35954
  `Sync complete for kit '${kitInfo.name}': ${kitSync.diff.added.length} added, ${kitSync.diff.modified.length} modified, ${kitSync.diff.removed.length} removed, ${kitSync.diff.unchanged.length} unchanged.`
35871
35955
  );
@@ -35940,7 +36024,7 @@ function printManifestDiff(logger, kitName, diff) {
35940
36024
  logger.info(` Unchanged: ${diff.unchanged.length} file(s)`);
35941
36025
  }
35942
36026
  }
35943
- function updateManifest(kitInfo, kitSync) {
36027
+ function updateManifest(kitInfo, kitSync, written) {
35944
36028
  for (const filePath of kitSync.diff.removed) {
35945
36029
  removeFileFromManifest(kitSync.manifest, filePath);
35946
36030
  }
@@ -35955,7 +36039,7 @@ function updateManifest(kitInfo, kitSync) {
35955
36039
  }
35956
36040
  }
35957
36041
  kitSync.manifest.kit = { name: kitInfo.name, version: kitInfo.version };
35958
- refreshArtifactStates(kitSync.manifest.artifacts);
36042
+ refreshArtifactStates(kitSync.manifest.artifacts, written);
35959
36043
  writeManifest(kitSync.scopePath, kitSync.manifest);
35960
36044
  }
35961
36045
  var outcomeRecordableTargets = /* @__PURE__ */ new Set([
@@ -35984,6 +36068,7 @@ function manifestKeyForOutcome(target, outcome, mappings, scope, projectRoot) {
35984
36068
  function reconcileSyncedArtifacts(manifest, results, mappings, scope, projectRoot) {
35985
36069
  const written = /* @__PURE__ */ new Map();
35986
36070
  const refused = /* @__PURE__ */ new Set();
36071
+ const refusedPaths = /* @__PURE__ */ new Map();
35987
36072
  for (const result of results) {
35988
36073
  for (const outcome of result.outcomes) {
35989
36074
  if (outcome.status !== "success" && outcome.status !== "skipped-current" && outcome.status !== "conflict") {
@@ -36001,6 +36086,7 @@ function reconcileSyncedArtifacts(manifest, results, mappings, scope, projectRoo
36001
36086
  }
36002
36087
  if (outcome.status === "conflict") {
36003
36088
  refused.add(key);
36089
+ refusedPaths.set(key, outcome.path);
36004
36090
  } else {
36005
36091
  written.set(key, outcome.path);
36006
36092
  }
@@ -36010,6 +36096,10 @@ function reconcileSyncedArtifacts(manifest, results, mappings, scope, projectRoo
36010
36096
  if (written.has(key)) {
36011
36097
  continue;
36012
36098
  }
36099
+ const destination = refusedPaths.get(key);
36100
+ if (destination && carriesProvenanceMarker(destination)) {
36101
+ continue;
36102
+ }
36013
36103
  removeArtifactFromManifest(manifest, key);
36014
36104
  }
36015
36105
  for (const [key, destination] of written) {
@@ -36029,7 +36119,7 @@ function reconcileSyncedArtifacts(manifest, results, mappings, scope, projectRoo
36029
36119
  }
36030
36120
  }
36031
36121
  function resolveKitFilePath(kitPath, relativePath) {
36032
- const fullPath = path53.join(kitPath, relativePath);
36122
+ const fullPath = path54.join(kitPath, relativePath);
36033
36123
  return fs50.existsSync(fullPath) ? fullPath : null;
36034
36124
  }
36035
36125
  function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
@@ -36098,9 +36188,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
36098
36188
  }
36099
36189
  if (relativePath.startsWith("agents/")) {
36100
36190
  removeManagedCompiledArtifact2(
36101
- path53.join(
36191
+ path54.join(
36102
36192
  resolveTargetPath(paths.agents ?? ""),
36103
- `${path53.parse(relativePath).name}.agent.md`
36193
+ `${path54.parse(relativePath).name}.agent.md`
36104
36194
  ),
36105
36195
  "copilot",
36106
36196
  relativePath,
@@ -36110,9 +36200,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
36110
36200
  }
36111
36201
  if (relativePath.startsWith("commands/")) {
36112
36202
  removeManagedCompiledArtifact2(
36113
- path53.join(
36203
+ path54.join(
36114
36204
  resolveTargetPath(paths.prompts ?? ""),
36115
- `${path53.parse(relativePath).name}.prompt.md`
36205
+ `${path54.parse(relativePath).name}.prompt.md`
36116
36206
  ),
36117
36207
  "copilot",
36118
36208
  relativePath,
@@ -36122,7 +36212,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
36122
36212
  }
36123
36213
  if (relativePath.endsWith("hooks.json")) {
36124
36214
  removeManagedCompiledArtifact2(
36125
- path53.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
36215
+ path54.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
36126
36216
  "copilot",
36127
36217
  relativePath,
36128
36218
  logger
@@ -36152,9 +36242,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
36152
36242
  }
36153
36243
  if (relativePath.startsWith("agents/")) {
36154
36244
  removeManagedCompiledArtifact2(
36155
- path53.join(
36245
+ path54.join(
36156
36246
  resolveTargetPath(paths.agents ?? ""),
36157
- `${path53.parse(relativePath).name}.toml`
36247
+ `${path54.parse(relativePath).name}.toml`
36158
36248
  ),
36159
36249
  "codex",
36160
36250
  relativePath,
@@ -36164,9 +36254,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
36164
36254
  }
36165
36255
  if (relativePath.startsWith("rules/")) {
36166
36256
  removeManagedCompiledArtifact2(
36167
- path53.join(
36257
+ path54.join(
36168
36258
  resolveTargetPath(paths.rules ?? ""),
36169
- `${path53.parse(relativePath).name}.rules`
36259
+ `${path54.parse(relativePath).name}.rules`
36170
36260
  ),
36171
36261
  "codex",
36172
36262
  relativePath,
@@ -36205,9 +36295,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
36205
36295
  }
36206
36296
  if (relativePath.startsWith("agents/")) {
36207
36297
  removeManagedCompiledArtifact2(
36208
- path53.join(
36298
+ path54.join(
36209
36299
  resolveTargetPath(paths.agents ?? ""),
36210
- `${path53.parse(relativePath).name}.md`
36300
+ `${path54.parse(relativePath).name}.md`
36211
36301
  ),
36212
36302
  "opencode",
36213
36303
  relativePath,
@@ -36217,9 +36307,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
36217
36307
  }
36218
36308
  if (relativePath.startsWith("commands/")) {
36219
36309
  removeManagedCompiledArtifact2(
36220
- path53.join(
36310
+ path54.join(
36221
36311
  resolveTargetPath(paths.commands ?? ""),
36222
- `${path53.parse(relativePath).name}.md`
36312
+ `${path54.parse(relativePath).name}.md`
36223
36313
  ),
36224
36314
  "opencode",
36225
36315
  relativePath,
@@ -36251,9 +36341,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
36251
36341
  }
36252
36342
  if (relativePath.startsWith("agents/")) {
36253
36343
  removeManagedCompiledArtifact2(
36254
- path53.join(
36344
+ path54.join(
36255
36345
  resolveTargetPath(paths.agents ?? ""),
36256
- `${path53.parse(relativePath).name}.md`
36346
+ `${path54.parse(relativePath).name}.md`
36257
36347
  ),
36258
36348
  "cursor",
36259
36349
  relativePath,
@@ -36263,9 +36353,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
36263
36353
  }
36264
36354
  if (relativePath.startsWith("rules/")) {
36265
36355
  removeManagedCompiledArtifact2(
36266
- path53.join(
36356
+ path54.join(
36267
36357
  resolveTargetPath(paths.rules ?? ""),
36268
- `${path53.parse(relativePath).name}.mdc`
36358
+ `${path54.parse(relativePath).name}.mdc`
36269
36359
  ),
36270
36360
  "cursor",
36271
36361
  relativePath,
@@ -36275,9 +36365,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
36275
36365
  }
36276
36366
  if (relativePath.startsWith("commands/")) {
36277
36367
  removeManagedCompiledArtifact2(
36278
- path53.join(
36368
+ path54.join(
36279
36369
  resolveTargetPath(paths.skills ?? ""),
36280
- path53.parse(relativePath).name,
36370
+ path54.parse(relativePath).name,
36281
36371
  "SKILL.md"
36282
36372
  ),
36283
36373
  "cursor",
@@ -36321,9 +36411,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
36321
36411
  }
36322
36412
  if (relativePath.startsWith("rules/")) {
36323
36413
  removeManagedCompiledArtifact2(
36324
- path53.join(
36414
+ path54.join(
36325
36415
  resolveTargetPath(paths.rules ?? ""),
36326
- `${path53.parse(relativePath).name}.md`
36416
+ `${path54.parse(relativePath).name}.md`
36327
36417
  ),
36328
36418
  "cline",
36329
36419
  relativePath,
@@ -36333,9 +36423,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
36333
36423
  }
36334
36424
  if (relativePath.startsWith("commands/")) {
36335
36425
  removeManagedCompiledArtifact2(
36336
- path53.join(
36426
+ path54.join(
36337
36427
  resolveTargetPath(paths.workflows ?? ""),
36338
- path53.basename(relativePath)
36428
+ path54.basename(relativePath)
36339
36429
  ),
36340
36430
  "cline",
36341
36431
  relativePath,
@@ -36504,7 +36594,7 @@ function removeManagedHookEntries(value, expectedSource) {
36504
36594
 
36505
36595
  // src/commands/validate.ts
36506
36596
  import fs51 from "fs";
36507
- import path54 from "path";
36597
+ import path55 from "path";
36508
36598
  var SUPPORTED_KIT_FORMATS2 = [1];
36509
36599
  var SUPPORTED_DISCIPLINE_VERSIONS = [
36510
36600
  "0.14.0",
@@ -36619,11 +36709,11 @@ function checkArchetype(kit) {
36619
36709
  }
36620
36710
  function checkHookScriptsExist(kit) {
36621
36711
  const violations = [];
36622
- const hooksDir = path54.join(kit.path, "hooks");
36712
+ const hooksDir = path55.join(kit.path, "hooks");
36623
36713
  const missingSet = new Set(kit.components.hooks.missing);
36624
36714
  for (const name of kit.components.hooks.declared) {
36625
36715
  if (missingSet.has(name)) continue;
36626
- const declarationPath = path54.join(hooksDir, `${name}.md`);
36716
+ const declarationPath = path55.join(hooksDir, `${name}.md`);
36627
36717
  if (!fs51.existsSync(declarationPath)) continue;
36628
36718
  let data;
36629
36719
  try {
@@ -36634,7 +36724,7 @@ function checkHookScriptsExist(kit) {
36634
36724
  if (typeof data.command === "string" && data.command.trim().length > 0) {
36635
36725
  continue;
36636
36726
  }
36637
- const scriptPath = path54.join(hooksDir, "scripts", `${name}.ts`);
36727
+ const scriptPath = path55.join(hooksDir, "scripts", `${name}.ts`);
36638
36728
  if (!fs51.existsSync(scriptPath)) {
36639
36729
  violations.push({
36640
36730
  code: "hook-script-missing",
@@ -36648,7 +36738,7 @@ function checkHookScriptsExist(kit) {
36648
36738
  function checkOptionalSourceDocuments(kit) {
36649
36739
  const violations = [];
36650
36740
  for (const name of [".mcp.json", "settings.json", ".lsp.json"]) {
36651
- const filePath = path54.join(kit.path, name);
36741
+ const filePath = path55.join(kit.path, name);
36652
36742
  if (!fs51.existsSync(filePath)) continue;
36653
36743
  try {
36654
36744
  const parsed = JSON.parse(fs51.readFileSync(filePath, "utf8"));
@@ -36673,7 +36763,7 @@ function checkSkillSubfolderNames(kit) {
36673
36763
  const notices = [];
36674
36764
  const canonical = new Set(CANONICAL_SKILL_SUBFOLDERS);
36675
36765
  for (const name of kit.components.skills.declared) {
36676
- const skillDir = path54.join(kit.path, "skills", name);
36766
+ const skillDir = path55.join(kit.path, "skills", name);
36677
36767
  let entries;
36678
36768
  try {
36679
36769
  entries = fs51.readdirSync(skillDir, { withFileTypes: true });
@@ -36694,7 +36784,7 @@ function checkSkillSubfolderNames(kit) {
36694
36784
  return notices;
36695
36785
  }
36696
36786
  function checkHooksSourceForm(kit) {
36697
- const hooksDir = path54.join(kit.path, "hooks");
36787
+ const hooksDir = path55.join(kit.path, "hooks");
36698
36788
  const message = describeHooksSourceConflict(
36699
36789
  hooksDir,
36700
36790
  kit.components.hooks.declared
@@ -36706,12 +36796,12 @@ function checkHooksSourceForm(kit) {
36706
36796
  } : null;
36707
36797
  }
36708
36798
  function checkHookDeclarations(kit) {
36709
- const hooksDir = path54.join(kit.path, "hooks");
36799
+ const hooksDir = path55.join(kit.path, "hooks");
36710
36800
  return collectHookRejections(hooksDir, kit.components.hooks.declared).map(
36711
36801
  (r) => ({
36712
36802
  code: "hook-declaration-invalid",
36713
- location: `hooks/${path54.basename(r.file)}`,
36714
- message: `hooks: '${path54.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.`
36803
+ location: `hooks/${path55.basename(r.file)}`,
36804
+ message: `hooks: '${path55.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.`
36715
36805
  })
36716
36806
  );
36717
36807
  }
@@ -36731,11 +36821,11 @@ function checkKitFormatSupported(kit) {
36731
36821
  function checkEntrypointExists(kit) {
36732
36822
  const declared = kit.entrypoint;
36733
36823
  const entrypoint = declared ?? DEFAULT_ENTRYPOINT;
36734
- const entrypointPath = path54.join(kit.path, entrypoint);
36824
+ const entrypointPath = path55.join(kit.path, entrypoint);
36735
36825
  if (fs51.existsSync(entrypointPath)) {
36736
36826
  return null;
36737
36827
  }
36738
- const legacyPresent = declared === void 0 && fs51.existsSync(path54.join(kit.path, LEGACY_ENTRYPOINT));
36828
+ const legacyPresent = declared === void 0 && fs51.existsSync(path55.join(kit.path, LEGACY_ENTRYPOINT));
36739
36829
  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.`;
36740
36830
  return {
36741
36831
  code: "entrypoint-missing",
@@ -36794,9 +36884,9 @@ function checkComponentFrontmatter(kit) {
36794
36884
  const missingSet = new Set(kit.components[cat].missing);
36795
36885
  for (const name of kit.components[cat].declared) {
36796
36886
  if (missingSet.has(name)) continue;
36797
- const filePath = cat === "skills" ? path54.join(kit.path, cat, name, "SKILL.md") : path54.join(kit.path, cat, `${name}.md`);
36887
+ const filePath = cat === "skills" ? path55.join(kit.path, cat, name, "SKILL.md") : path55.join(kit.path, cat, `${name}.md`);
36798
36888
  if (!fs51.existsSync(filePath)) continue;
36799
- const relPath = path54.relative(kit.path, filePath);
36889
+ const relPath = path55.relative(kit.path, filePath);
36800
36890
  try {
36801
36891
  const { data } = parseMarkdownFrontmatter(filePath);
36802
36892
  for (const field of requiredFields) {
@@ -36841,7 +36931,7 @@ function checkHumanOnlyCommandInvocation(kit) {
36841
36931
  const missingSet = new Set(kit.components.commands.missing);
36842
36932
  for (const name of kit.components.commands.declared) {
36843
36933
  if (missingSet.has(name)) continue;
36844
- const filePath = path54.join(kit.path, "commands", `${name}.md`);
36934
+ const filePath = path55.join(kit.path, "commands", `${name}.md`);
36845
36935
  if (!fs51.existsSync(filePath)) continue;
36846
36936
  let data;
36847
36937
  try {
@@ -36855,7 +36945,7 @@ function checkHumanOnlyCommandInvocation(kit) {
36855
36945
  if (!barred) {
36856
36946
  violations.push({
36857
36947
  code: "command-human-only-model-invocable",
36858
- location: path54.relative(kit.path, filePath),
36948
+ location: path55.relative(kit.path, filePath),
36859
36949
  message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
36860
36950
  });
36861
36951
  }
@@ -36865,7 +36955,7 @@ function checkHumanOnlyCommandInvocation(kit) {
36865
36955
 
36866
36956
  // src/commands/verify.ts
36867
36957
  import fs52 from "fs";
36868
- import path55 from "path";
36958
+ import path56 from "path";
36869
36959
  function runVerifyCommand(options, logger) {
36870
36960
  if (options.target && !isKnownTarget(options.target)) {
36871
36961
  throwUnrecognizedTarget(options.target);
@@ -37046,7 +37136,7 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
37046
37136
  if (!slotPath) {
37047
37137
  continue;
37048
37138
  }
37049
- const fullPath = subPath ? path55.join(slotPath, subPath) : slotPath;
37139
+ const fullPath = subPath ? path56.join(slotPath, subPath) : slotPath;
37050
37140
  if (!fs52.existsSync(fullPath)) {
37051
37141
  failures.push(
37052
37142
  `claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`