@alessandroraffa/tangyr 0.15.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1298 -803
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1372,8 +1372,8 @@ var require_command = __commonJS({
1372
1372
  "use strict";
1373
1373
  var EventEmitter = __require("events").EventEmitter;
1374
1374
  var childProcess = __require("child_process");
1375
- var path46 = __require("path");
1376
- var fs45 = __require("fs");
1375
+ var path45 = __require("path");
1376
+ var fs44 = __require("fs");
1377
1377
  var process5 = __require("process");
1378
1378
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1379
1379
  var { CommanderError: CommanderError2 } = require_error();
@@ -2367,7 +2367,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2367
2367
  * @param {string} subcommandName
2368
2368
  */
2369
2369
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
2370
- if (fs45.existsSync(executableFile)) return;
2370
+ if (fs44.existsSync(executableFile)) return;
2371
2371
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
2372
2372
  const executableMissing = `'${executableFile}' does not exist
2373
2373
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -2385,11 +2385,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
2385
2385
  let launchWithNode = false;
2386
2386
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
2387
2387
  function findFile(baseDir, baseName) {
2388
- const localBin = path46.resolve(baseDir, baseName);
2389
- if (fs45.existsSync(localBin)) return localBin;
2390
- if (sourceExt.includes(path46.extname(baseName))) return void 0;
2388
+ const localBin = path45.resolve(baseDir, baseName);
2389
+ if (fs44.existsSync(localBin)) return localBin;
2390
+ if (sourceExt.includes(path45.extname(baseName))) return void 0;
2391
2391
  const foundExt = sourceExt.find(
2392
- (ext) => fs45.existsSync(`${localBin}${ext}`)
2392
+ (ext) => fs44.existsSync(`${localBin}${ext}`)
2393
2393
  );
2394
2394
  if (foundExt) return `${localBin}${foundExt}`;
2395
2395
  return void 0;
@@ -2401,21 +2401,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
2401
2401
  if (this._scriptPath) {
2402
2402
  let resolvedScriptPath;
2403
2403
  try {
2404
- resolvedScriptPath = fs45.realpathSync(this._scriptPath);
2404
+ resolvedScriptPath = fs44.realpathSync(this._scriptPath);
2405
2405
  } catch {
2406
2406
  resolvedScriptPath = this._scriptPath;
2407
2407
  }
2408
- executableDir = path46.resolve(
2409
- path46.dirname(resolvedScriptPath),
2408
+ executableDir = path45.resolve(
2409
+ path45.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 = path46.basename(
2416
+ const legacyName = path45.basename(
2417
2417
  this._scriptPath,
2418
- path46.extname(this._scriptPath)
2418
+ path45.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(path46.extname(executableFile));
2429
+ launchWithNode = sourceExt.includes(path45.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 = path46.basename(filename, path46.extname(filename));
3344
+ this._name = path45.basename(filename, path45.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(path47) {
3359
- if (path47 === void 0) return this._executableDir;
3360
- this._executableDir = path47;
3358
+ executableDir(path46) {
3359
+ if (path46 === void 0) return this._executableDir;
3360
+ this._executableDir = path46;
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, path46) {
3717
- const ctrl = callVisitor(key, node, visitor, path46);
3716
+ function visit_(key, node, visitor, path45) {
3717
+ const ctrl = callVisitor(key, node, visitor, path45);
3718
3718
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
3719
- replaceNode(key, path46, ctrl);
3720
- return visit_(key, ctrl, visitor, path46);
3719
+ replaceNode(key, path45, ctrl);
3720
+ return visit_(key, ctrl, visitor, path45);
3721
3721
  }
3722
3722
  if (typeof ctrl !== "symbol") {
3723
3723
  if (identity.isCollection(node)) {
3724
- path46 = Object.freeze(path46.concat(node));
3724
+ path45 = Object.freeze(path45.concat(node));
3725
3725
  for (let i = 0; i < node.items.length; ++i) {
3726
- const ci2 = visit_(i, node.items[i], visitor, path46);
3726
+ const ci2 = visit_(i, node.items[i], visitor, path45);
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
- path46 = Object.freeze(path46.concat(node));
3738
- const ck = visit_("key", node.key, visitor, path46);
3737
+ path45 = Object.freeze(path45.concat(node));
3738
+ const ck = visit_("key", node.key, visitor, path45);
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, path46);
3743
+ const cv = visit_("value", node.value, visitor, path45);
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, path46) {
3765
- const ctrl = await callVisitor(key, node, visitor, path46);
3764
+ async function visitAsync_(key, node, visitor, path45) {
3765
+ const ctrl = await callVisitor(key, node, visitor, path45);
3766
3766
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
3767
- replaceNode(key, path46, ctrl);
3768
- return visitAsync_(key, ctrl, visitor, path46);
3767
+ replaceNode(key, path45, ctrl);
3768
+ return visitAsync_(key, ctrl, visitor, path45);
3769
3769
  }
3770
3770
  if (typeof ctrl !== "symbol") {
3771
3771
  if (identity.isCollection(node)) {
3772
- path46 = Object.freeze(path46.concat(node));
3772
+ path45 = Object.freeze(path45.concat(node));
3773
3773
  for (let i = 0; i < node.items.length; ++i) {
3774
- const ci2 = await visitAsync_(i, node.items[i], visitor, path46);
3774
+ const ci2 = await visitAsync_(i, node.items[i], visitor, path45);
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
- path46 = Object.freeze(path46.concat(node));
3786
- const ck = await visitAsync_("key", node.key, visitor, path46);
3785
+ path45 = Object.freeze(path45.concat(node));
3786
+ const ck = await visitAsync_("key", node.key, visitor, path45);
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, path46);
3791
+ const cv = await visitAsync_("value", node.value, visitor, path45);
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, path46) {
3818
+ function callVisitor(key, node, visitor, path45) {
3819
3819
  if (typeof visitor === "function")
3820
- return visitor(key, node, path46);
3820
+ return visitor(key, node, path45);
3821
3821
  if (identity.isMap(node))
3822
- return visitor.Map?.(key, node, path46);
3822
+ return visitor.Map?.(key, node, path45);
3823
3823
  if (identity.isSeq(node))
3824
- return visitor.Seq?.(key, node, path46);
3824
+ return visitor.Seq?.(key, node, path45);
3825
3825
  if (identity.isPair(node))
3826
- return visitor.Pair?.(key, node, path46);
3826
+ return visitor.Pair?.(key, node, path45);
3827
3827
  if (identity.isScalar(node))
3828
- return visitor.Scalar?.(key, node, path46);
3828
+ return visitor.Scalar?.(key, node, path45);
3829
3829
  if (identity.isAlias(node))
3830
- return visitor.Alias?.(key, node, path46);
3830
+ return visitor.Alias?.(key, node, path45);
3831
3831
  return void 0;
3832
3832
  }
3833
- function replaceNode(key, path46, node) {
3834
- const parent = path46[path46.length - 1];
3833
+ function replaceNode(key, path45, node) {
3834
+ const parent = path45[path45.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, path46, value) {
4442
+ function collectionFromPath(schema, path45, value) {
4443
4443
  let v2 = value;
4444
- for (let i = path46.length - 1; i >= 0; --i) {
4445
- const k2 = path46[i];
4444
+ for (let i = path45.length - 1; i >= 0; --i) {
4445
+ const k2 = path45[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 = (path46) => path46 == null || typeof path46 === "object" && !!path46[Symbol.iterator]().next().done;
4464
+ var isEmptyPath = (path45) => path45 == null || typeof path45 === "object" && !!path45[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(path46, value) {
4495
- if (isEmptyPath(path46))
4494
+ addIn(path45, value) {
4495
+ if (isEmptyPath(path45))
4496
4496
  this.add(value);
4497
4497
  else {
4498
- const [key, ...rest] = path46;
4498
+ const [key, ...rest] = path45;
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(path46) {
4513
- const [key, ...rest] = path46;
4512
+ deleteIn(path45) {
4513
+ const [key, ...rest] = path45;
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(path46, keepScalar) {
4528
- const [key, ...rest] = path46;
4527
+ getIn(path45, keepScalar) {
4528
+ const [key, ...rest] = path45;
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(path46) {
4547
- const [key, ...rest] = path46;
4546
+ hasIn(path45) {
4547
+ const [key, ...rest] = path45;
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(path46, value) {
4558
- const [key, ...rest] = path46;
4557
+ setIn(path45, value) {
4558
+ const [key, ...rest] = path45;
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(path46, value) {
7070
+ addIn(path45, value) {
7071
7071
  if (assertCollection(this.contents))
7072
- this.contents.addIn(path46, value);
7072
+ this.contents.addIn(path45, 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(path46) {
7148
- if (Collection.isEmptyPath(path46)) {
7147
+ deleteIn(path45) {
7148
+ if (Collection.isEmptyPath(path45)) {
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(path46) : false;
7154
+ return assertCollection(this.contents) ? this.contents.deleteIn(path45) : 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(path46, keepScalar) {
7170
- if (Collection.isEmptyPath(path46))
7169
+ getIn(path45, keepScalar) {
7170
+ if (Collection.isEmptyPath(path45))
7171
7171
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
7172
- return identity.isCollection(this.contents) ? this.contents.getIn(path46, keepScalar) : void 0;
7172
+ return identity.isCollection(this.contents) ? this.contents.getIn(path45, 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(path46) {
7184
- if (Collection.isEmptyPath(path46))
7183
+ hasIn(path45) {
7184
+ if (Collection.isEmptyPath(path45))
7185
7185
  return this.contents !== void 0;
7186
- return identity.isCollection(this.contents) ? this.contents.hasIn(path46) : false;
7186
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path45) : 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(path46, value) {
7204
- if (Collection.isEmptyPath(path46)) {
7203
+ setIn(path45, value) {
7204
+ if (Collection.isEmptyPath(path45)) {
7205
7205
  this.contents = value;
7206
7206
  } else if (this.contents == null) {
7207
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path46), value);
7207
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path45), value);
7208
7208
  } else if (assertCollection(this.contents)) {
7209
- this.contents.setIn(path46, value);
7209
+ this.contents.setIn(path45, 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, path46) => {
9166
+ visit.itemAtPath = (cst, path45) => {
9167
9167
  let item = cst;
9168
- for (const [field, index] of path46) {
9168
+ for (const [field, index] of path45) {
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, path46) => {
9178
- const parent = visit.itemAtPath(cst, path46.slice(0, -1));
9179
- const field = path46[path46.length - 1][0];
9177
+ visit.parentCollection = (cst, path45) => {
9178
+ const parent = visit.itemAtPath(cst, path45.slice(0, -1));
9179
+ const field = path45[path45.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(path46, item, visitor) {
9186
- let ctrl = visitor(item, path46);
9185
+ function _visit(path45, item, visitor) {
9186
+ let ctrl = visitor(item, path45);
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(path46.concat([[field, i]])), token.items[i], visitor);
9193
+ const ci2 = _visit(Object.freeze(path45.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, path46);
9204
+ ctrl = ctrl(item, path45);
9205
9205
  }
9206
9206
  }
9207
- return typeof ctrl === "function" ? ctrl(item, path46) : ctrl;
9207
+ return typeof ctrl === "function" ? ctrl(item, path45) : ctrl;
9208
9208
  }
9209
9209
  exports2.visit = visit;
9210
9210
  }
@@ -10489,14 +10489,14 @@ var require_parser = __commonJS({
10489
10489
  case "scalar":
10490
10490
  case "single-quoted-scalar":
10491
10491
  case "double-quoted-scalar": {
10492
- const fs45 = this.flowScalar(this.type);
10492
+ const fs44 = this.flowScalar(this.type);
10493
10493
  if (atNextItem || it2.value) {
10494
- map.items.push({ start, key: fs45, sep: [] });
10494
+ map.items.push({ start, key: fs44, sep: [] });
10495
10495
  this.onKeyLine = true;
10496
10496
  } else if (it2.sep) {
10497
- this.stack.push(fs45);
10497
+ this.stack.push(fs44);
10498
10498
  } else {
10499
- Object.assign(it2, { key: fs45, sep: [] });
10499
+ Object.assign(it2, { key: fs44, sep: [] });
10500
10500
  this.onKeyLine = true;
10501
10501
  }
10502
10502
  return;
@@ -10624,13 +10624,13 @@ var require_parser = __commonJS({
10624
10624
  case "scalar":
10625
10625
  case "single-quoted-scalar":
10626
10626
  case "double-quoted-scalar": {
10627
- const fs45 = this.flowScalar(this.type);
10627
+ const fs44 = this.flowScalar(this.type);
10628
10628
  if (!it2 || it2.value)
10629
- fc.items.push({ start: [], key: fs45, sep: [] });
10629
+ fc.items.push({ start: [], key: fs44, sep: [] });
10630
10630
  else if (it2.sep)
10631
- this.stack.push(fs45);
10631
+ this.stack.push(fs44);
10632
10632
  else
10633
- Object.assign(it2, { key: fs45, sep: [] });
10633
+ Object.assign(it2, { key: fs44, sep: [] });
10634
10634
  return;
10635
10635
  }
10636
10636
  case "flow-map-end":
@@ -17834,8 +17834,8 @@ async function runCacheClearCommand(options, logger) {
17834
17834
  }
17835
17835
 
17836
17836
  // src/commands/cleanup.ts
17837
- import fs23 from "fs";
17838
- import path21 from "path";
17837
+ import fs24 from "fs";
17838
+ import path22 from "path";
17839
17839
 
17840
17840
  // node_modules/glob/dist/esm/index.min.js
17841
17841
  import { fileURLToPath as Wi } from "url";
@@ -20832,6 +20832,7 @@ var KNOWN_COMPONENTS = /* @__PURE__ */ new Set([
20832
20832
  "hooks",
20833
20833
  "output-styles"
20834
20834
  ]);
20835
+ var KNOWN_INSTRUCTION_FILES = /* @__PURE__ */ new Set(["AGENTS.md", "CLAUDE.md"]);
20835
20836
  var LEGACY_SOURCE_DIRECTORIES = /* @__PURE__ */ new Set([
20836
20837
  "operational-framework",
20837
20838
  "operational-machinery"
@@ -20891,7 +20892,7 @@ function isOurStaleSymlink(linkPath, managedPaths, config) {
20891
20892
  const lastSegment = path17.basename(linkTarget);
20892
20893
  const parentSegment = path17.basename(path17.dirname(linkTarget));
20893
20894
  if (isBroken) {
20894
- return KNOWN_COMPONENTS.has(lastSegment) || KNOWN_COMPONENTS.has(parentSegment) || knownFiles.has(lastSegment);
20895
+ return KNOWN_COMPONENTS.has(lastSegment) || KNOWN_COMPONENTS.has(parentSegment) || KNOWN_INSTRUCTION_FILES.has(lastSegment) || knownFiles.has(lastSegment);
20895
20896
  }
20896
20897
  const targetSegments = absoluteTarget.split(path17.sep);
20897
20898
  const traversesLegacyRoot = targetSegments.some(
@@ -20980,8 +20981,8 @@ function removeManagedEntries(filePath, parser, serializer, removeManaged, logge
20980
20981
  }
20981
20982
 
20982
20983
  // src/commands/uninstall.ts
20983
- import fs22 from "fs";
20984
- import path20 from "path";
20984
+ import fs23 from "fs";
20985
+ import path21 from "path";
20985
20986
 
20986
20987
  // src/core/managed-sources.ts
20987
20988
  var import_yaml5 = __toESM(require_dist(), 1);
@@ -21047,38 +21048,195 @@ function normalizeManagedSourcePath(rawPath) {
21047
21048
  return normalized.startsWith("./") ? normalized.slice(2) : normalized;
21048
21049
  }
21049
21050
 
21050
- // src/core/remove.ts
21051
+ // src/compiler/hook-components.ts
21052
+ var import_yaml6 = __toESM(require_dist(), 1);
21051
21053
  import fs21 from "fs";
21054
+ import path20 from "path";
21055
+ function parseHookDeclaration(filePath) {
21056
+ let raw;
21057
+ try {
21058
+ raw = fs21.readFileSync(filePath, "utf8");
21059
+ } catch {
21060
+ return null;
21061
+ }
21062
+ const fm = extractFrontmatter(raw);
21063
+ if (!fm) {
21064
+ return null;
21065
+ }
21066
+ const { name, description, events } = fm;
21067
+ if (typeof name !== "string" || !name.trim()) {
21068
+ return null;
21069
+ }
21070
+ if (typeof description !== "string" || !description.trim()) {
21071
+ return null;
21072
+ }
21073
+ if (!Array.isArray(events) || events.length === 0) {
21074
+ return null;
21075
+ }
21076
+ const parsedEvents = [];
21077
+ for (const entry of events) {
21078
+ if (!entry || typeof entry !== "object") {
21079
+ return null;
21080
+ }
21081
+ const ev = entry;
21082
+ if (typeof ev.event !== "string" || !ev.event.trim()) {
21083
+ return null;
21084
+ }
21085
+ if (typeof ev.timeout !== "number") {
21086
+ return null;
21087
+ }
21088
+ if (typeof ev.statusMessage !== "string" || !ev.statusMessage.trim()) {
21089
+ return null;
21090
+ }
21091
+ const parsed = {
21092
+ event: ev.event,
21093
+ timeout: ev.timeout,
21094
+ statusMessage: ev.statusMessage
21095
+ };
21096
+ if (typeof ev.matcher === "string" && ev.matcher.trim()) {
21097
+ parsed.matcher = ev.matcher;
21098
+ }
21099
+ parsedEvents.push(parsed);
21100
+ }
21101
+ return {
21102
+ name: name.trim(),
21103
+ description: description.trim(),
21104
+ events: parsedEvents
21105
+ };
21106
+ }
21107
+ function hookCommand(name) {
21108
+ return `npx tsx ~/.agents/hooks/scripts/${name}.ts`;
21109
+ }
21110
+ function synthesizeHooksJson(declarations) {
21111
+ const hooks = {};
21112
+ for (const decl of declarations) {
21113
+ for (const ev of decl.events) {
21114
+ if (!hooks[ev.event]) {
21115
+ hooks[ev.event] = [];
21116
+ }
21117
+ const entry = {
21118
+ hooks: [
21119
+ {
21120
+ type: "command",
21121
+ command: hookCommand(decl.name),
21122
+ timeout: ev.timeout,
21123
+ statusMessage: ev.statusMessage
21124
+ }
21125
+ ]
21126
+ };
21127
+ if (ev.matcher !== void 0) {
21128
+ const ordered = {
21129
+ matcher: ev.matcher,
21130
+ hooks: entry.hooks
21131
+ };
21132
+ hooks[ev.event].push(ordered);
21133
+ } else {
21134
+ hooks[ev.event].push(entry);
21135
+ }
21136
+ }
21137
+ }
21138
+ return { hooks };
21139
+ }
21140
+ function loadSourceHooks(hooksDir, hookNames) {
21141
+ const hooksJsonPath = path20.join(hooksDir, "hooks.json");
21142
+ if (fs21.existsSync(hooksJsonPath)) {
21143
+ const raw = fs21.readFileSync(hooksJsonPath, "utf8");
21144
+ return JSON.parse(raw);
21145
+ }
21146
+ const declarations = loadHookDeclarations(hooksDir, hookNames);
21147
+ return synthesizeHooksJson(declarations);
21148
+ }
21149
+ function loadHookDeclarations(hooksDir, hookNames) {
21150
+ let names;
21151
+ if (hookNames && hookNames.length > 0) {
21152
+ names = hookNames;
21153
+ } else {
21154
+ if (!fs21.existsSync(hooksDir) || !fs21.statSync(hooksDir).isDirectory()) {
21155
+ return [];
21156
+ }
21157
+ names = fs21.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
21158
+ }
21159
+ const declarations = [];
21160
+ for (const name of names) {
21161
+ const filePath = path20.join(hooksDir, `${name}.md`);
21162
+ const decl = parseHookDeclaration(filePath);
21163
+ if (decl) {
21164
+ declarations.push(decl);
21165
+ }
21166
+ }
21167
+ return declarations;
21168
+ }
21169
+ function extractFrontmatter(content) {
21170
+ if (!content.startsWith("---\n")) {
21171
+ return null;
21172
+ }
21173
+ const endIndex = content.indexOf("\n---", 4);
21174
+ if (endIndex === -1) {
21175
+ return null;
21176
+ }
21177
+ const rawFm = content.slice(4, endIndex);
21178
+ let parsed;
21179
+ try {
21180
+ parsed = (0, import_yaml6.parse)(rawFm);
21181
+ } catch {
21182
+ return null;
21183
+ }
21184
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
21185
+ return null;
21186
+ }
21187
+ return parsed;
21188
+ }
21189
+
21190
+ // src/core/remove.ts
21191
+ import fs22 from "fs";
21052
21192
  function removeManagedPath(managedPath) {
21053
21193
  let stat;
21054
21194
  try {
21055
- stat = fs21.lstatSync(managedPath);
21195
+ stat = fs22.lstatSync(managedPath);
21056
21196
  } catch {
21057
21197
  return;
21058
21198
  }
21059
21199
  if (stat.isSymbolicLink() || stat.isFile()) {
21060
- fs21.unlinkSync(managedPath);
21200
+ fs22.unlinkSync(managedPath);
21061
21201
  return;
21062
21202
  }
21063
21203
  if (stat.isDirectory()) {
21064
- fs21.rmSync(managedPath, { recursive: true, force: true });
21204
+ fs22.rmSync(managedPath, { recursive: true, force: true });
21065
21205
  }
21066
21206
  }
21067
21207
 
21068
21208
  // src/commands/uninstall.ts
21069
21209
  var codexManagedMcpStart = "# tangyr: managed mcp start";
21070
21210
  var codexManagedMcpEnd = "# tangyr: managed mcp end";
21211
+ var legacyClaudeSharedPermission = "Read(~/.agents/**)";
21212
+ var legacyOperatingGuideSignature = "# Agent Coding \u2014 Operating Guide\n\n_Structured authoring with LLM agents across the full artifact continuum._";
21071
21213
  var SHARED_CLAUDE_SLOTS = /* @__PURE__ */ new Set([
21072
21214
  "mcp_shared_file",
21073
21215
  "hooks"
21074
21216
  ]);
21217
+ function resolveClaudeCodePathsForRoots(roots, mappings) {
21218
+ return roots.map((root) => resolveClaudeCodeProfileForRoot(root, mappings));
21219
+ }
21075
21220
  async function runUninstallCommand(options, logger) {
21076
21221
  const scope = options.scope === "global" ? "global" : "project";
21077
21222
  const scopePath = resolveScopePath(
21078
21223
  scope,
21079
21224
  scope === "project" ? process.cwd() : void 0
21080
21225
  );
21081
- const manifest = readStrictManifest(scopePath);
21226
+ const runtime = resolveRuntimeIfAvailable(options, logger);
21227
+ const persistedManifest = readStrictManifest(scopePath);
21228
+ const manifestWasPresent = persistedManifest !== null;
21229
+ let manifest = persistedManifest;
21230
+ if (!manifest && scope === "global" && runtime?.kitInfo) {
21231
+ manifest = createEmptyManifest(
21232
+ runtime.kitInfo.archetype,
21233
+ runtime.kitInfo.kitFormat,
21234
+ "global"
21235
+ );
21236
+ logger.warn(
21237
+ `No Tangyr manifest found in ${scope} scope; reconciling ownership evidence on disk.`
21238
+ );
21239
+ }
21082
21240
  if (!manifest) {
21083
21241
  logger.error(
21084
21242
  `No Tangyr installation found in ${scope} scope (${scopePath}).`
@@ -21086,15 +21244,25 @@ async function runUninstallCommand(options, logger) {
21086
21244
  logger.info("Nothing to uninstall.");
21087
21245
  process.exit(1);
21088
21246
  }
21089
- const runtime = resolveRuntimeIfAvailable(options, logger);
21090
21247
  const selectedTools = resolveSelectedTools(options.tools, manifest, runtime);
21091
21248
  const manifestArtifacts = manifest.artifacts.filter(
21092
21249
  (file) => shouldRemoveManifestFile(file.relativePath, selectedTools)
21093
21250
  );
21094
- const kitArtifacts = runtime ? resolveKitManagedArtifacts(runtime, scope, selectedTools) : [];
21095
- logger.info(
21096
- `Found Tangyr installation: archetype ${manifest.archetype}, version ${manifest.version}`
21097
- );
21251
+ const kitArtifacts = runtime ? resolveKitManagedArtifacts(
21252
+ runtime,
21253
+ scope,
21254
+ selectedTools,
21255
+ manifest,
21256
+ options.claudeConfigDir
21257
+ ).filter((artifact) => isKitManagedArtifact(artifact, runtime)) : [];
21258
+ const useManifestPathRemoval = scope !== "global" || runtime === void 0;
21259
+ if (manifestWasPresent) {
21260
+ logger.info(
21261
+ `Found Tangyr installation: archetype ${manifest.archetype}, version ${manifest.version}`
21262
+ );
21263
+ } else {
21264
+ logger.info(`Scanning Tangyr residue for archetype ${manifest.archetype}`);
21265
+ }
21098
21266
  logger.info(`Scope: ${scope} (${scopePath})`);
21099
21267
  logger.info(
21100
21268
  `Tools: ${Array.from(selectedTools).join(", ") || manifest.tools.join(", ") || "(none)"}`
@@ -21105,8 +21273,10 @@ async function runUninstallCommand(options, logger) {
21105
21273
  }
21106
21274
  if (options.dryRun) {
21107
21275
  logger.info("\n[dry-run] Would remove:");
21108
- for (const file of manifestArtifacts) {
21109
- logger.info(` ${file.relativePath}`);
21276
+ if (useManifestPathRemoval) {
21277
+ for (const file of manifestArtifacts) {
21278
+ logger.info(` ${file.relativePath}`);
21279
+ }
21110
21280
  }
21111
21281
  for (const artifact of kitArtifacts) {
21112
21282
  logger.info(` ${artifact.path}`);
@@ -21121,7 +21291,7 @@ async function runUninstallCommand(options, logger) {
21121
21291
  }
21122
21292
  if (!options.yes) {
21123
21293
  const proceed = await dist_default5({
21124
- message: `Remove Tangyr from ${scope} scope? This will delete ${manifestArtifacts.length + kitArtifacts.length} managed file(s).`
21294
+ message: `Remove Tangyr from ${scope} scope? This will delete ${(useManifestPathRemoval ? manifestArtifacts.length : 0) + kitArtifacts.length} managed file(s).`
21125
21295
  });
21126
21296
  if (!proceed) {
21127
21297
  logger.info("Uninstallation aborted.");
@@ -21130,7 +21300,7 @@ async function runUninstallCommand(options, logger) {
21130
21300
  }
21131
21301
  const claudeRoots = scope === "global" && selectedTools.has("claude-code") ? resolveClaudeRootsForUninstall(manifest, runtime) : [];
21132
21302
  let removedCount = 0;
21133
- for (const file of manifestArtifacts) {
21303
+ for (const file of useManifestPathRemoval ? manifestArtifacts : []) {
21134
21304
  const isClaudeGlobal = file.relativePath.startsWith("claude-code/") && scope === "global";
21135
21305
  if (isClaudeGlobal && claudeRoots.length > 0) {
21136
21306
  const paths = resolveManifestKeyToMultiPaths(
@@ -21139,7 +21309,7 @@ async function runUninstallCommand(options, logger) {
21139
21309
  runtime
21140
21310
  );
21141
21311
  for (const actualPath of paths) {
21142
- if (actualPath && (fs22.existsSync(actualPath) || isSymlink(actualPath))) {
21312
+ if (actualPath && (fs23.existsSync(actualPath) || isSymlink(actualPath))) {
21143
21313
  removeManagedPath(actualPath);
21144
21314
  logger.verbose(` removed: ${actualPath}`);
21145
21315
  removedCount++;
@@ -21153,7 +21323,7 @@ async function runUninstallCommand(options, logger) {
21153
21323
  scope,
21154
21324
  runtime
21155
21325
  );
21156
- if (actualPath && (fs22.existsSync(actualPath) || isSymlink(actualPath))) {
21326
+ if (actualPath && (fs23.existsSync(actualPath) || isSymlink(actualPath))) {
21157
21327
  removeManagedPath(actualPath);
21158
21328
  logger.verbose(` removed: ${actualPath}`);
21159
21329
  removedCount++;
@@ -21168,32 +21338,46 @@ async function runUninstallCommand(options, logger) {
21168
21338
  removedCount++;
21169
21339
  }
21170
21340
  }
21341
+ const residuals = resolveKitManagedArtifacts(
21342
+ runtime,
21343
+ scope,
21344
+ selectedTools,
21345
+ manifest,
21346
+ options.claudeConfigDir
21347
+ ).filter((artifact) => isKitManagedArtifact(artifact, runtime));
21348
+ if (residuals.length > 0) {
21349
+ throw new Error(
21350
+ `Uninstall incomplete: ${residuals.length} managed artifact(s) remain: ${residuals.map((artifact) => artifact.path).join(", ")}`
21351
+ );
21352
+ }
21171
21353
  }
21172
21354
  const fullUninstall = isFullToolUninstall(manifest, selectedTools);
21173
21355
  if (fullUninstall) {
21174
21356
  for (const backup of manifest.backups) {
21175
21357
  restoreBackup(backup, logger);
21176
21358
  }
21177
- const manifestPath = path20.join(scopePath, "manifest.json");
21178
- if (fs22.existsSync(manifestPath)) {
21179
- fs22.unlinkSync(manifestPath);
21359
+ const manifestPath = path21.join(scopePath, "manifest.json");
21360
+ if (fs23.existsSync(manifestPath)) {
21361
+ fs23.unlinkSync(manifestPath);
21180
21362
  logger.verbose(` removed manifest: ${manifestPath}`);
21181
21363
  }
21182
21364
  try {
21183
- const remaining = fs22.readdirSync(scopePath);
21365
+ const remaining = fs23.readdirSync(scopePath);
21184
21366
  if (remaining.length === 0) {
21185
- fs22.rmdirSync(scopePath);
21367
+ fs23.rmdirSync(scopePath);
21186
21368
  logger.verbose(` removed empty scope directory: ${scopePath}`);
21187
21369
  }
21188
21370
  } catch {
21189
21371
  }
21190
- } else {
21372
+ } else if (manifestWasPresent) {
21191
21373
  manifest.artifacts = manifest.artifacts.filter(
21192
21374
  (file) => !shouldRemoveManifestFile(file.relativePath, selectedTools)
21193
21375
  );
21194
21376
  manifest.tools = manifest.tools.filter((tool) => !selectedTools.has(tool));
21195
21377
  writeManifest(scopePath, manifest);
21196
21378
  logger.verbose(" updated manifest for partial uninstall");
21379
+ } else {
21380
+ logger.verbose(" no manifest to update after partial residue cleanup");
21197
21381
  }
21198
21382
  logger.info(`
21199
21383
  Uninstallation complete: ${removedCount} file(s) removed.`);
@@ -21220,7 +21404,7 @@ function resolveManifestKeyToPath(key, scope, runtime) {
21220
21404
  if (!slotPath) {
21221
21405
  return null;
21222
21406
  }
21223
- return subPath ? path20.join(slotPath, subPath) : slotPath;
21407
+ return subPath ? path21.join(slotPath, subPath) : slotPath;
21224
21408
  }
21225
21409
  if (tool === "copilot") {
21226
21410
  const copilotPaths = resolveCopilotPaths(runtime, scope, projectRoot);
@@ -21228,18 +21412,18 @@ function resolveManifestKeyToPath(key, scope, runtime) {
21228
21412
  return copilotPaths.skills;
21229
21413
  }
21230
21414
  if (component.startsWith("agents/")) {
21231
- return path20.join(copilotPaths.agents, component.slice("agents/".length));
21415
+ return path21.join(copilotPaths.agents, component.slice("agents/".length));
21232
21416
  }
21233
21417
  if (component.startsWith("prompts/")) {
21234
- return path20.join(
21418
+ return path21.join(
21235
21419
  copilotPaths.prompts,
21236
21420
  component.slice("prompts/".length)
21237
21421
  );
21238
21422
  }
21239
21423
  if (component.startsWith("hooks/")) {
21240
- return path20.join(copilotPaths.hooks, component.slice("hooks/".length));
21424
+ return path21.join(copilotPaths.hooks, component.slice("hooks/".length));
21241
21425
  }
21242
- if (component === path20.basename(copilotPaths.mcpSharedFile)) {
21426
+ if (component === path21.basename(copilotPaths.mcpSharedFile)) {
21243
21427
  return copilotPaths.mcpSharedFile;
21244
21428
  }
21245
21429
  return null;
@@ -21253,15 +21437,15 @@ function resolveManifestKeyToPath(key, scope, runtime) {
21253
21437
  return codexPaths.skills;
21254
21438
  }
21255
21439
  if (component.startsWith("agents/")) {
21256
- return path20.join(codexPaths.agents, component.slice("agents/".length));
21440
+ return path21.join(codexPaths.agents, component.slice("agents/".length));
21257
21441
  }
21258
21442
  if (component.startsWith("rules/")) {
21259
- return path20.join(codexPaths.rules, component.slice("rules/".length));
21443
+ return path21.join(codexPaths.rules, component.slice("rules/".length));
21260
21444
  }
21261
- if (component === path20.basename(codexPaths.hooksSharedFile)) {
21445
+ if (component === path21.basename(codexPaths.hooksSharedFile)) {
21262
21446
  return codexPaths.hooksSharedFile;
21263
21447
  }
21264
- if (component === path20.basename(codexPaths.mcpSharedFile)) {
21448
+ if (component === path21.basename(codexPaths.mcpSharedFile)) {
21265
21449
  return codexPaths.mcpSharedFile;
21266
21450
  }
21267
21451
  return null;
@@ -21278,15 +21462,15 @@ function resolveManifestKeyToPath(key, scope, runtime) {
21278
21462
  return opencodePaths.skillsShared;
21279
21463
  }
21280
21464
  if (component.startsWith("agents/")) {
21281
- return path20.join(opencodePaths.agents, component.slice("agents/".length));
21465
+ return path21.join(opencodePaths.agents, component.slice("agents/".length));
21282
21466
  }
21283
21467
  if (component.startsWith("commands/")) {
21284
- return path20.join(
21468
+ return path21.join(
21285
21469
  opencodePaths.commands,
21286
21470
  component.slice("commands/".length)
21287
21471
  );
21288
21472
  }
21289
- if (component === path20.basename(opencodePaths.configDoc)) {
21473
+ if (component === path21.basename(opencodePaths.configDoc)) {
21290
21474
  return opencodePaths.configDoc;
21291
21475
  }
21292
21476
  return null;
@@ -21312,13 +21496,13 @@ function resolveManifestKeyToPath(key, scope, runtime) {
21312
21496
  return cursorPaths.permissionsFile;
21313
21497
  }
21314
21498
  if (component.startsWith("agents/")) {
21315
- return path20.join(cursorPaths.agents, component.slice("agents/".length));
21499
+ return path21.join(cursorPaths.agents, component.slice("agents/".length));
21316
21500
  }
21317
21501
  if (component.startsWith("rules/")) {
21318
- return path20.join(cursorPaths.rules, component.slice("rules/".length));
21502
+ return path21.join(cursorPaths.rules, component.slice("rules/".length));
21319
21503
  }
21320
21504
  if (component.startsWith("skills/")) {
21321
- return path20.join(cursorPaths.skills, component.slice("skills/".length));
21505
+ return path21.join(cursorPaths.skills, component.slice("skills/".length));
21322
21506
  }
21323
21507
  return null;
21324
21508
  }
@@ -21334,10 +21518,10 @@ function resolveManifestKeyToPath(key, scope, runtime) {
21334
21518
  return clinePaths.mcpFile;
21335
21519
  }
21336
21520
  if (component.startsWith("rules/")) {
21337
- return path20.join(clinePaths.rules, component.slice("rules/".length));
21521
+ return path21.join(clinePaths.rules, component.slice("rules/".length));
21338
21522
  }
21339
21523
  if (component.startsWith("workflows/")) {
21340
- return path20.join(
21524
+ return path21.join(
21341
21525
  clinePaths.workflows,
21342
21526
  component.slice("workflows/".length)
21343
21527
  );
@@ -21371,22 +21555,22 @@ function resolveClaudeCodePaths(runtime, scope, projectRoot) {
21371
21555
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
21372
21556
  if (scope === "global") {
21373
21557
  return {
21374
- instructions: path20.join(home, ".claude", "CLAUDE.md"),
21375
- agents: path20.join(home, ".claude", "agents"),
21376
- skills: path20.join(home, ".claude", "skills"),
21377
- commands: path20.join(home, ".claude", "commands"),
21378
- rules: path20.join(home, ".claude", "rules"),
21379
- output_styles: path20.join(home, ".claude", "output-styles")
21558
+ instructions: path21.join(home, ".claude", "CLAUDE.md"),
21559
+ agents: path21.join(home, ".claude", "agents"),
21560
+ skills: path21.join(home, ".claude", "skills"),
21561
+ commands: path21.join(home, ".claude", "commands"),
21562
+ rules: path21.join(home, ".claude", "rules"),
21563
+ output_styles: path21.join(home, ".claude", "output-styles")
21380
21564
  };
21381
21565
  }
21382
21566
  const root = projectRoot ?? process.cwd();
21383
21567
  return {
21384
- instructions: path20.join(root, "CLAUDE.md"),
21385
- agents: path20.join(root, ".claude", "agents"),
21386
- skills: path20.join(root, ".claude", "skills"),
21387
- commands: path20.join(root, ".claude", "commands"),
21388
- rules: path20.join(root, ".claude", "rules"),
21389
- output_styles: path20.join(root, ".claude", "output-styles")
21568
+ instructions: path21.join(root, "CLAUDE.md"),
21569
+ agents: path21.join(root, ".claude", "agents"),
21570
+ skills: path21.join(root, ".claude", "skills"),
21571
+ commands: path21.join(root, ".claude", "commands"),
21572
+ rules: path21.join(root, ".claude", "rules"),
21573
+ output_styles: path21.join(root, ".claude", "output-styles")
21390
21574
  };
21391
21575
  }
21392
21576
  function resolveClaudeRootsForUninstall(manifest, runtime) {
@@ -21405,12 +21589,36 @@ function resolveClaudeRootsForUninstall(manifest, runtime) {
21405
21589
  projectRoot: void 0,
21406
21590
  mappings: mappings.platformPaths
21407
21591
  })["claude-code"];
21408
- return [path20.dirname(profile.agents)];
21592
+ return [path21.dirname(profile.agents)];
21409
21593
  } catch {
21410
21594
  }
21411
21595
  }
21412
21596
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
21413
- return [path20.resolve(expandHome(`${home}/.claude`))];
21597
+ return [path21.resolve(expandHome(`${home}/.claude`))];
21598
+ }
21599
+ function resolveAllClaudeRoots(manifest, runtime, claudeConfigDirs) {
21600
+ const home = process.env.HOME ?? process.env.USERPROFILE;
21601
+ const roots = new Set(
21602
+ [
21603
+ ...resolveClaudeRootsForUninstall(manifest, runtime),
21604
+ ...resolveClaudeGlobalRoots({
21605
+ flag: claudeConfigDirs,
21606
+ env: process.env.TANGYR_CLAUDE_CONFIG_DIRS,
21607
+ config: runtime.config.claudeCodeGlobalPaths
21608
+ })
21609
+ ].map((root) => path21.resolve(root))
21610
+ );
21611
+ if (home && fs23.existsSync(home)) {
21612
+ try {
21613
+ for (const entry of fs23.readdirSync(home, { withFileTypes: true })) {
21614
+ if (entry.isDirectory() && entry.name.startsWith(".claude-")) {
21615
+ roots.add(path21.resolve(home, entry.name));
21616
+ }
21617
+ }
21618
+ } catch {
21619
+ }
21620
+ }
21621
+ return Array.from(roots).sort();
21414
21622
  }
21415
21623
  function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
21416
21624
  if (claudeRoots.length === 0) {
@@ -21423,13 +21631,13 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
21423
21631
  const rootsToResolve = isShared ? [claudeRoots[0]] : claudeRoots;
21424
21632
  if (!runtime) {
21425
21633
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
21426
- const defaultRoot = path20.resolve(expandHome(`${home}/.claude`));
21634
+ const defaultRoot = path21.resolve(expandHome(`${home}/.claude`));
21427
21635
  return rootsToResolve.flatMap((root) => {
21428
21636
  const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
21429
21637
  if (!hardcoded) {
21430
21638
  return [];
21431
21639
  }
21432
- return [subPath ? path20.join(hardcoded, subPath) : hardcoded];
21640
+ return [subPath ? path21.join(hardcoded, subPath) : hardcoded];
21433
21641
  });
21434
21642
  }
21435
21643
  try {
@@ -21448,17 +21656,17 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
21448
21656
  if (!slotPath) {
21449
21657
  return [];
21450
21658
  }
21451
- return [subPath ? path20.join(slotPath, subPath) : slotPath];
21659
+ return [subPath ? path21.join(slotPath, subPath) : slotPath];
21452
21660
  });
21453
21661
  } catch {
21454
21662
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
21455
- const defaultRoot = path20.resolve(expandHome(`${home}/.claude`));
21663
+ const defaultRoot = path21.resolve(expandHome(`${home}/.claude`));
21456
21664
  return rootsToResolve.flatMap((root) => {
21457
21665
  const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
21458
21666
  if (!hardcoded) {
21459
21667
  return [];
21460
21668
  }
21461
- return [subPath ? path20.join(hardcoded, subPath) : hardcoded];
21669
+ return [subPath ? path21.join(hardcoded, subPath) : hardcoded];
21462
21670
  });
21463
21671
  }
21464
21672
  }
@@ -21481,9 +21689,9 @@ function resolveHardcodedClaudeSlot(root, defaultRoot, slotName) {
21481
21689
  return null;
21482
21690
  }
21483
21691
  if (root === defaultRoot) {
21484
- return path20.join(root, relative);
21692
+ return path21.join(root, relative);
21485
21693
  }
21486
- return path20.join(root, relative);
21694
+ return path21.join(root, relative);
21487
21695
  }
21488
21696
  function resolveRuntimeIfAvailable(options, logger) {
21489
21697
  try {
@@ -21502,6 +21710,9 @@ function resolveSelectedTools(rawTools, manifest, runtime) {
21502
21710
  );
21503
21711
  }
21504
21712
  const selectedTools = new Set(manifest.tools);
21713
+ if (selectedTools.size === 0) {
21714
+ return new Set(ALL_TARGETS);
21715
+ }
21505
21716
  if (runtime) {
21506
21717
  for (const tool of activeTargets(runtime.config)) {
21507
21718
  selectedTools.add(tool);
@@ -21514,9 +21725,93 @@ function shouldRemoveManifestFile(relativePath, selectedTools) {
21514
21725
  return selectedTools.has(tool);
21515
21726
  }
21516
21727
  function isFullToolUninstall(manifest, selectedTools) {
21728
+ if (manifest.tools.length === 0) {
21729
+ return ALL_TARGETS.every((tool) => selectedTools.has(tool));
21730
+ }
21517
21731
  return manifest.tools.every((tool) => selectedTools.has(tool));
21518
21732
  }
21519
- function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21733
+ function addCompiledPathPlan(artifacts, artifactPath, expectedTarget, component) {
21734
+ addCompiledGlobPlans(artifacts, artifactPath, expectedTarget, component);
21735
+ }
21736
+ function addCompiledGlobPlans(artifacts, pattern, expectedTarget, component) {
21737
+ for (const artifactPath of ts(pattern).sort()) {
21738
+ let marker = null;
21739
+ try {
21740
+ marker = extractProvenanceMarker(fs23.readFileSync(artifactPath, "utf8"));
21741
+ } catch {
21742
+ continue;
21743
+ }
21744
+ if (marker?.target !== expectedTarget) {
21745
+ continue;
21746
+ }
21747
+ artifacts.push({
21748
+ component,
21749
+ path: artifactPath,
21750
+ kind: "compiled",
21751
+ expectedTarget,
21752
+ expectedSource: marker.source,
21753
+ observed: true
21754
+ });
21755
+ }
21756
+ }
21757
+ function addManagedSymlinkChildren(artifacts, directory, runtime, component) {
21758
+ let entries;
21759
+ try {
21760
+ entries = fs23.readdirSync(directory, { withFileTypes: true });
21761
+ } catch {
21762
+ return;
21763
+ }
21764
+ for (const entry of entries) {
21765
+ const artifactPath = path21.join(directory, entry.name);
21766
+ const artifactClass = classifyArtifact(
21767
+ artifactPath,
21768
+ runtime.config,
21769
+ runtime.sourceRoot
21770
+ );
21771
+ if (artifactClass === "managed-symlink" || artifactClass === "managed-stale") {
21772
+ artifacts.push({ component, path: artifactPath, kind: "direct" });
21773
+ }
21774
+ }
21775
+ }
21776
+ function resolveLegacyClaudeHookCommands(runtime) {
21777
+ const parsed = loadSourceHooks(
21778
+ resolveHooksSourceDir(runtime.sourceRoot, runtime.config),
21779
+ resolveKitHookNames(runtime.sourceRoot)
21780
+ );
21781
+ const commands = /* @__PURE__ */ new Set();
21782
+ collectStringValuesByKey(parsed, "command", commands);
21783
+ return Array.from(commands).sort();
21784
+ }
21785
+ function collectStringValuesByKey(value, keyName, values) {
21786
+ if (Array.isArray(value)) {
21787
+ for (const entry of value) {
21788
+ collectStringValuesByKey(entry, keyName, values);
21789
+ }
21790
+ return;
21791
+ }
21792
+ if (!isRecord(value)) {
21793
+ return;
21794
+ }
21795
+ if (typeof value[keyName] === "string") {
21796
+ values.add(value[keyName]);
21797
+ }
21798
+ for (const entry of Object.values(value)) {
21799
+ collectStringValuesByKey(entry, keyName, values);
21800
+ }
21801
+ }
21802
+ function addLegacyOperatingGuideCopies(artifacts, claudeRoot) {
21803
+ for (const artifactPath of [
21804
+ ...ts(path21.join(claudeRoot, "CLAUDE.md.bak.*")),
21805
+ ...ts(path21.join(claudeRoot, "AGENTS.md.bak.*"))
21806
+ ].sort()) {
21807
+ artifacts.push({
21808
+ component: "claude-code legacy operating guide backup",
21809
+ path: artifactPath,
21810
+ kind: "legacy-kit-copy"
21811
+ });
21812
+ }
21813
+ }
21814
+ function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, claudeConfigDirs) {
21520
21815
  if (!runtime.kitInfo || scope !== "global") {
21521
21816
  return [];
21522
21817
  }
@@ -21526,11 +21821,97 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21526
21821
  const opencodePaths = resolveOpenCodePaths(runtime);
21527
21822
  const cursorPaths = resolveCursorPaths(runtime);
21528
21823
  const clinePaths = resolveClinePaths(runtime);
21824
+ if (selectedTools.has("claude-code")) {
21825
+ const mappings = loadMappings(
21826
+ runtime.sourceRoot,
21827
+ runtime.config,
21828
+ runtime.configDir
21829
+ );
21830
+ const claudeRoots = resolveAllClaudeRoots(
21831
+ manifest,
21832
+ runtime,
21833
+ claudeConfigDirs
21834
+ );
21835
+ const profiles = resolveClaudeCodePathsForRoots(
21836
+ claudeRoots,
21837
+ mappings.platformPaths
21838
+ );
21839
+ const legacyHookCommands = resolveLegacyClaudeHookCommands(runtime);
21840
+ for (const profile of profiles) {
21841
+ for (const [component, artifactPath] of [
21842
+ ["instructions", profile.instructions],
21843
+ ["instructions shim", profile.instructions_shim],
21844
+ ["agents", profile.agents],
21845
+ ["commands", profile.commands],
21846
+ ["rules", profile.rules],
21847
+ ["output styles", profile.output_styles],
21848
+ ["skills", profile.skills]
21849
+ ]) {
21850
+ artifacts.push({
21851
+ component: `claude-code ${component}`,
21852
+ path: artifactPath,
21853
+ kind: "direct"
21854
+ });
21855
+ }
21856
+ for (const skill of runtime.kitInfo.components.skills.declared) {
21857
+ artifacts.push({
21858
+ component: "claude-code skill",
21859
+ path: path21.join(profile.skills, skill),
21860
+ kind: "direct"
21861
+ });
21862
+ }
21863
+ addManagedSymlinkChildren(
21864
+ artifacts,
21865
+ profile.skills,
21866
+ runtime,
21867
+ "claude-code skill residue"
21868
+ );
21869
+ artifacts.push({
21870
+ component: "claude-code settings",
21871
+ path: profile.hooks_shared_file,
21872
+ kind: "claude-hooks",
21873
+ legacyHookCommands
21874
+ });
21875
+ if (isFullToolUninstall(manifest, selectedTools)) {
21876
+ addLegacyOperatingGuideCopies(
21877
+ artifacts,
21878
+ path21.dirname(profile.instructions)
21879
+ );
21880
+ }
21881
+ }
21882
+ const sharedProfile = profiles[0];
21883
+ if (sharedProfile) {
21884
+ artifacts.push(
21885
+ {
21886
+ component: "claude-code hooks bridge",
21887
+ path: sharedProfile.hooks,
21888
+ kind: "direct"
21889
+ },
21890
+ {
21891
+ component: "claude-code mcp",
21892
+ path: sharedProfile.mcp_shared_file,
21893
+ kind: "claude-mcp"
21894
+ }
21895
+ );
21896
+ }
21897
+ }
21529
21898
  if (selectedTools.has("copilot")) {
21899
+ addCompiledGlobPlans(
21900
+ artifacts,
21901
+ path21.join(copilotPaths.agents, "*.agent.md"),
21902
+ "copilot",
21903
+ "copilot agent residue"
21904
+ );
21905
+ addCompiledGlobPlans(
21906
+ artifacts,
21907
+ path21.join(copilotPaths.prompts, "*.prompt.md"),
21908
+ "copilot",
21909
+ "copilot prompt residue"
21910
+ );
21530
21911
  for (const agentEntry of runtime.kitInfo.components.agents.declared) {
21531
21912
  artifacts.push({
21532
21913
  component: "copilot agent",
21533
- path: path20.join(copilotPaths.agents, `${agentEntry}.agent.md`),
21914
+ path: path21.join(copilotPaths.agents, `${agentEntry}.agent.md`),
21534
21915
  kind: "compiled",
21535
21916
  expectedTarget: "copilot",
21536
21917
  expectedSource: `agents/${agentEntry}.md`
@@ -21539,7 +21920,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21539
21920
  for (const commandEntry of runtime.kitInfo.components.commands.declared) {
21540
21921
  artifacts.push({
21541
21922
  component: "copilot prompt",
21542
- path: path20.join(copilotPaths.prompts, `${commandEntry}.prompt.md`),
21923
+ path: path21.join(copilotPaths.prompts, `${commandEntry}.prompt.md`),
21543
21924
  kind: "compiled",
21544
21925
  expectedTarget: "copilot",
21545
21926
  expectedSource: `commands/${commandEntry}.md`
@@ -21552,15 +21933,29 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21552
21933
  kind: "direct"
21553
21934
  });
21554
21935
  }
21936
+ artifacts.push(
21937
+ {
21938
+ component: "copilot hooks",
21939
+ path: path21.join(copilotPaths.hooks, "tangyr-managed.json"),
21940
+ kind: "managed-json",
21941
+ expectedTarget: "copilot"
21942
+ },
21943
+ {
21944
+ component: "copilot legacy hooks",
21945
+ path: path21.join(copilotPaths.hooks, "proteus-managed.json"),
21946
+ kind: "managed-json",
21947
+ expectedTarget: "copilot"
21948
+ }
21949
+ );
21555
21950
  const hooksSourcePath = resolveHooksSourceFile(
21556
21951
  runtime.sourceRoot,
21557
21952
  runtime.config
21558
21953
  );
21559
21954
  const hooksSource = hooksSourceLabel(runtime.config);
21560
- if (fs22.existsSync(hooksSourcePath)) {
21955
+ if (fs23.existsSync(hooksSourcePath)) {
21561
21956
  artifacts.push({
21562
21957
  component: "copilot hooks",
21563
- path: path20.join(copilotPaths.hooks, "tangyr-managed.json"),
21958
+ path: path21.join(copilotPaths.hooks, "tangyr-managed.json"),
21564
21959
  kind: "compiled",
21565
21960
  expectedTarget: "copilot",
21566
21961
  expectedSource: hooksSource
@@ -21571,7 +21966,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21571
21966
  runtime.config
21572
21967
  );
21573
21968
  const mcpSource = mcpSourceLabel(runtime.config);
21574
- if (fs22.existsSync(mcpSourcePath)) {
21969
+ if (fs23.existsSync(mcpSourcePath)) {
21575
21970
  artifacts.push({
21576
21971
  component: "copilot mcp",
21577
21972
  path: copilotPaths.mcpSharedFile,
@@ -21582,6 +21977,24 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21582
21977
  }
21583
21978
  }
21584
21979
  if (selectedTools.has("codex")) {
21980
+ addCompiledPathPlan(
21981
+ artifacts,
21982
+ codexPaths.instructions,
21983
+ "codex",
21984
+ "codex instruction residue"
21985
+ );
21986
+ addCompiledGlobPlans(
21987
+ artifacts,
21988
+ path21.join(codexPaths.agents, "*.toml"),
21989
+ "codex",
21990
+ "codex agent residue"
21991
+ );
21992
+ addCompiledGlobPlans(
21993
+ artifacts,
21994
+ path21.join(codexPaths.rules, "*.rules"),
21995
+ "codex",
21996
+ "codex rule residue"
21997
+ );
21585
21998
  artifacts.push({
21586
21999
  component: "codex instructions",
21587
22000
  path: codexPaths.instructions,
@@ -21592,7 +22005,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21592
22005
  for (const agentEntry of runtime.kitInfo.components.agents.declared) {
21593
22006
  artifacts.push({
21594
22007
  component: "codex agent",
21595
- path: path20.join(codexPaths.agents, `${agentEntry}.toml`),
22008
+ path: path21.join(codexPaths.agents, `${agentEntry}.toml`),
21596
22009
  kind: "compiled",
21597
22010
  expectedTarget: "codex",
21598
22011
  expectedSource: `agents/${agentEntry}.md`
@@ -21601,7 +22014,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21601
22014
  for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
21602
22015
  artifacts.push({
21603
22016
  component: "codex rule",
21604
- path: path20.join(codexPaths.rules, `${ruleEntry}.rules`),
22017
+ path: path21.join(codexPaths.rules, `${ruleEntry}.rules`),
21605
22018
  kind: "compiled",
21606
22019
  expectedTarget: "codex",
21607
22020
  expectedSource: `rules/${ruleEntry}.md`
@@ -21619,7 +22032,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21619
22032
  runtime.config
21620
22033
  );
21621
22034
  const hooksSource = hooksSourceLabel(runtime.config);
21622
- if (fs22.existsSync(hooksSourcePath)) {
22035
+ if (fs23.existsSync(hooksSourcePath)) {
21623
22036
  artifacts.push({
21624
22037
  component: "codex hooks",
21625
22038
  path: codexPaths.hooksSharedFile,
@@ -21632,7 +22045,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21632
22045
  runtime.config
21633
22046
  );
21634
22047
  const mcpSource = mcpSourceLabel(runtime.config);
21635
- if (fs22.existsSync(mcpSourcePath)) {
22048
+ if (fs23.existsSync(mcpSourcePath)) {
21636
22049
  artifacts.push({
21637
22050
  component: "codex mcp",
21638
22051
  path: codexPaths.mcpSharedFile,
@@ -21643,8 +22056,37 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21643
22056
  }
21644
22057
  }
21645
22058
  if (selectedTools.has("opencode")) {
21646
- artifacts.push({
21647
- component: "opencode instructions",
22059
+ addCompiledPathPlan(
22060
+ artifacts,
22061
+ opencodePaths.instructions,
22062
+ "opencode",
22063
+ "opencode instruction residue"
22064
+ );
22065
+ addCompiledPathPlan(
22066
+ artifacts,
22067
+ opencodePaths.configDoc,
22068
+ "opencode",
22069
+ "opencode config residue"
22070
+ );
22071
+ addCompiledGlobPlans(
22072
+ artifacts,
22073
+ path21.join(opencodePaths.agents, "*.md"),
22074
+ "opencode",
22075
+ "opencode agent residue"
22076
+ );
22077
+ addCompiledGlobPlans(
22078
+ artifacts,
22079
+ path21.join(opencodePaths.commands, "*.md"),
22080
+ "opencode",
22081
+ "opencode command residue"
22082
+ );
22083
+ artifacts.push({
22084
+ component: "opencode shared skills",
22085
+ path: opencodePaths.skillsShared,
22086
+ kind: "direct"
22087
+ });
22088
+ artifacts.push({
22089
+ component: "opencode instructions",
21648
22090
  path: opencodePaths.instructions,
21649
22091
  kind: "compiled",
21650
22092
  expectedTarget: "opencode",
@@ -21653,7 +22095,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21653
22095
  for (const agentEntry of runtime.kitInfo.components.agents.declared) {
21654
22096
  artifacts.push({
21655
22097
  component: "opencode agent",
21656
- path: path20.join(opencodePaths.agents, `${agentEntry}.md`),
22098
+ path: path21.join(opencodePaths.agents, `${agentEntry}.md`),
21657
22099
  kind: "compiled",
21658
22100
  expectedTarget: "opencode",
21659
22101
  expectedSource: `agents/${agentEntry}.md`
@@ -21662,7 +22104,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21662
22104
  for (const commandEntry of runtime.kitInfo.components.commands.declared) {
21663
22105
  artifacts.push({
21664
22106
  component: "opencode command",
21665
- path: path20.join(opencodePaths.commands, `${commandEntry}.md`),
22107
+ path: path21.join(opencodePaths.commands, `${commandEntry}.md`),
21666
22108
  kind: "compiled",
21667
22109
  expectedTarget: "opencode",
21668
22110
  expectedSource: `commands/${commandEntry}.md`
@@ -21680,7 +22122,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21680
22122
  runtime.config
21681
22123
  );
21682
22124
  const mcpSource = mcpSourceLabel(runtime.config);
21683
- if (fs22.existsSync(mcpSourcePath)) {
22125
+ if (fs23.existsSync(mcpSourcePath)) {
21684
22126
  artifacts.push({
21685
22127
  component: "opencode config",
21686
22128
  path: opencodePaths.configDoc,
@@ -21691,6 +22133,48 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21691
22133
  }
21692
22134
  }
21693
22135
  if (selectedTools.has("cursor")) {
22136
+ addCompiledPathPlan(
22137
+ artifacts,
22138
+ cursorPaths.instructions,
22139
+ "cursor",
22140
+ "cursor instruction residue"
22141
+ );
22142
+ addCompiledPathPlan(
22143
+ artifacts,
22144
+ cursorPaths.mcpFile,
22145
+ "cursor",
22146
+ "cursor mcp residue"
22147
+ );
22148
+ artifacts.push(
22149
+ {
22150
+ component: "cursor agent directory residue",
22151
+ path: cursorPaths.agents,
22152
+ kind: "direct"
22153
+ },
22154
+ {
22155
+ component: "cursor shared skills",
22156
+ path: cursorPaths.skillsShared,
22157
+ kind: "direct"
22158
+ }
22159
+ );
22160
+ addCompiledGlobPlans(
22161
+ artifacts,
22162
+ path21.join(cursorPaths.agents, "*.md"),
22163
+ "cursor",
22164
+ "cursor agent residue"
22165
+ );
22166
+ addCompiledGlobPlans(
22167
+ artifacts,
22168
+ path21.join(cursorPaths.rules, "*.mdc"),
22169
+ "cursor",
22170
+ "cursor rule residue"
22171
+ );
22172
+ addCompiledGlobPlans(
22173
+ artifacts,
22174
+ path21.join(cursorPaths.skills, "*", "SKILL.md"),
22175
+ "cursor",
22176
+ "cursor command residue"
22177
+ );
21694
22178
  artifacts.push({
21695
22179
  component: "cursor instructions",
21696
22180
  path: cursorPaths.instructions,
@@ -21701,7 +22185,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21701
22185
  for (const agentEntry of runtime.kitInfo.components.agents.declared) {
21702
22186
  artifacts.push({
21703
22187
  component: "cursor agent",
21704
- path: path20.join(cursorPaths.agents, `${agentEntry}.md`),
22188
+ path: path21.join(cursorPaths.agents, `${agentEntry}.md`),
21705
22189
  kind: "compiled",
21706
22190
  expectedTarget: "cursor",
21707
22191
  expectedSource: `agents/${agentEntry}.md`
@@ -21719,7 +22203,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21719
22203
  runtime.config
21720
22204
  );
21721
22205
  const mcpSource = mcpSourceLabel(runtime.config);
21722
- if (fs22.existsSync(mcpSourcePath)) {
22206
+ if (fs23.existsSync(mcpSourcePath)) {
21723
22207
  artifacts.push({
21724
22208
  component: "cursor mcp",
21725
22209
  path: cursorPaths.mcpFile,
@@ -21730,6 +22214,36 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21730
22214
  }
21731
22215
  }
21732
22216
  if (selectedTools.has("cline")) {
22217
+ addCompiledPathPlan(
22218
+ artifacts,
22219
+ clinePaths.mcpFile,
22220
+ "cline",
22221
+ "cline mcp residue"
22222
+ );
22223
+ addCompiledGlobPlans(
22224
+ artifacts,
22225
+ path21.join(clinePaths.rules, "*.md"),
22226
+ "cline",
22227
+ "cline rule residue"
22228
+ );
22229
+ addCompiledGlobPlans(
22230
+ artifacts,
22231
+ path21.join(clinePaths.workflows, "*.md"),
22232
+ "cline",
22233
+ "cline workflow residue"
22234
+ );
22235
+ addManagedSymlinkChildren(
22236
+ artifacts,
22237
+ clinePaths.rules,
22238
+ runtime,
22239
+ "cline rule symlink residue"
22240
+ );
22241
+ addManagedSymlinkChildren(
22242
+ artifacts,
22243
+ clinePaths.workflows,
22244
+ runtime,
22245
+ "cline workflow symlink residue"
22246
+ );
21733
22247
  if (clinePaths.instructions !== null) {
21734
22248
  artifacts.push({
21735
22249
  component: "cline instructions",
@@ -21742,7 +22256,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21742
22256
  for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
21743
22257
  artifacts.push({
21744
22258
  component: "cline rule",
21745
- path: path20.join(clinePaths.rules, `${ruleEntry}.md`),
22259
+ path: path21.join(clinePaths.rules, `${ruleEntry}.md`),
21746
22260
  kind: "compiled",
21747
22261
  expectedTarget: "cline",
21748
22262
  expectedSource: `rules/${ruleEntry}.md`
@@ -21751,7 +22265,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21751
22265
  for (const commandEntry of runtime.kitInfo.components.commands.declared) {
21752
22266
  artifacts.push({
21753
22267
  component: "cline workflow",
21754
- path: path20.join(clinePaths.workflows, `${commandEntry}.md`),
22268
+ path: path21.join(clinePaths.workflows, `${commandEntry}.md`),
21755
22269
  kind: "compiled",
21756
22270
  expectedTarget: "cline",
21757
22271
  expectedSource: `commands/${commandEntry}.md`
@@ -21769,7 +22283,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21769
22283
  runtime.config
21770
22284
  );
21771
22285
  const mcpSource = mcpSourceLabel(runtime.config);
21772
- if (fs22.existsSync(mcpSourcePath)) {
22286
+ if (fs23.existsSync(mcpSourcePath)) {
21773
22287
  artifacts.push({
21774
22288
  component: "cline mcp",
21775
22289
  path: clinePaths.mcpFile,
@@ -21779,12 +22293,57 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
21779
22293
  });
21780
22294
  }
21781
22295
  }
22296
+ if (isFullToolUninstall(manifest, selectedTools)) {
22297
+ for (const pointerName of [".operating-kit-root", ".framework-root"]) {
22298
+ artifacts.push({
22299
+ component: `shared kit pointer ${pointerName}`,
22300
+ path: resolveTargetPath(`~/.agents/${pointerName}`),
22301
+ kind: "kit-pointer",
22302
+ expectedPath: runtime.sourceRoot
22303
+ });
22304
+ }
22305
+ }
22306
+ addRecordedManifestPlans(artifacts, manifest, selectedTools, runtime);
21782
22307
  return dedupeArtifacts(artifacts);
21783
22308
  }
22309
+ function addRecordedManifestPlans(artifacts, manifest, selectedTools, runtime) {
22310
+ for (const file of manifest.artifacts) {
22311
+ if (file.origin !== "tangyr-managed" || !shouldRemoveManifestFile(file.relativePath, selectedTools)) {
22312
+ continue;
22313
+ }
22314
+ const artifactPath = resolveManifestKeyToPath(
22315
+ file.relativePath,
22316
+ "global",
22317
+ runtime
22318
+ );
22319
+ if (artifactPath) {
22320
+ artifacts.push({
22321
+ component: `${file.relativePath} (manifest)`,
22322
+ path: artifactPath,
22323
+ kind: "recorded"
22324
+ });
22325
+ }
22326
+ }
22327
+ }
21784
22328
  function removeKitManagedArtifact(artifact, runtime, logger) {
21785
22329
  if (artifact.kind === "compiled") {
21786
22330
  return removeManagedCompiledArtifact(artifact, logger);
21787
22331
  }
22332
+ if (artifact.kind === "claude-hooks") {
22333
+ return removeManagedClaudeHooksArtifact(artifact, logger);
22334
+ }
22335
+ if (artifact.kind === "claude-mcp") {
22336
+ return removeManagedClaudeMcpArtifact(artifact, logger);
22337
+ }
22338
+ if (artifact.kind === "managed-json") {
22339
+ return removeManagedJsonArtifact(artifact, logger);
22340
+ }
22341
+ if (artifact.kind === "recorded") {
22342
+ return removeRecordedArtifact(artifact, logger);
22343
+ }
22344
+ if (artifact.kind === "kit-pointer" || artifact.kind === "legacy-kit-copy") {
22345
+ return removeExactManagedFile(artifact, logger);
22346
+ }
21788
22347
  if (artifact.kind === "copilot-mcp") {
21789
22348
  return removeManagedCopilotMcpArtifact(artifact, logger);
21790
22349
  }
@@ -21796,17 +22355,78 @@ function removeKitManagedArtifact(artifact, runtime, logger) {
21796
22355
  }
21797
22356
  return removeManagedDirectArtifact(artifact, runtime, logger);
21798
22357
  }
22358
+ function isKitManagedArtifact(artifact, runtime) {
22359
+ if (artifact.kind === "direct") {
22360
+ const artifactClass = classifyArtifact(
22361
+ artifact.path,
22362
+ runtime.config,
22363
+ runtime.sourceRoot
22364
+ );
22365
+ return artifactClass === "managed-symlink" || artifactClass === "managed-stale" || artifactClass === "managed-compiled";
22366
+ }
22367
+ if (artifact.kind === "compiled") {
22368
+ if (!fs23.existsSync(artifact.path)) {
22369
+ return false;
22370
+ }
22371
+ try {
22372
+ const marker = extractProvenanceMarker(
22373
+ fs23.readFileSync(artifact.path, "utf8")
22374
+ );
22375
+ return marker?.target === artifact.expectedTarget && marker?.source === artifact.expectedSource;
22376
+ } catch {
22377
+ return false;
22378
+ }
22379
+ }
22380
+ if (artifact.kind === "recorded") {
22381
+ return fs23.existsSync(artifact.path) || isSymlink(artifact.path);
22382
+ }
22383
+ if (artifact.kind === "kit-pointer") {
22384
+ return isKitPointer(artifact);
22385
+ }
22386
+ if (artifact.kind === "legacy-kit-copy") {
22387
+ return isLegacyOperatingGuideCopy(artifact.path);
22388
+ }
22389
+ if (artifact.kind === "codex-mcp") {
22390
+ if (!fs23.existsSync(artifact.path)) {
22391
+ return false;
22392
+ }
22393
+ const section = readManagedTomlSection(
22394
+ fs23.readFileSync(artifact.path, "utf8")
22395
+ );
22396
+ const marker = section ? extractProvenanceMarker(section) : null;
22397
+ return marker?.target === artifact.expectedTarget && marker?.source === artifact.expectedSource;
22398
+ }
22399
+ const parsed = readJsonObject2(artifact.path);
22400
+ if (!parsed) {
22401
+ return false;
22402
+ }
22403
+ if (artifact.kind === "claude-hooks") {
22404
+ return containsValueByKey(parsed.hooks, "_tangyr", true) || containsValueByKey(parsed.hooks, "_proteus", true) || (artifact.legacyHookCommands ?? []).some(
22405
+ (command) => containsValueByKey(parsed.hooks, "command", command)
22406
+ ) || hasLegacyClaudeSharedPermission(parsed);
22407
+ }
22408
+ if (artifact.kind === "claude-mcp") {
22409
+ return hasManagedClaudeMcpServer(parsed);
22410
+ }
22411
+ if (artifact.kind === "managed-json") {
22412
+ return hasManagedRootMetadata(parsed, artifact.expectedTarget);
22413
+ }
22414
+ if (artifact.kind === "copilot-mcp") {
22415
+ return matchesManagedMetadata(metadataRecord(parsed._tangyr), artifact) || matchesManagedMetadata(metadataRecord(parsed._proteus), artifact);
22416
+ }
22417
+ return hasManagedCodexHooks(parsed, artifact.expectedSource);
22418
+ }
21799
22419
  function removeManagedCompiledArtifact(artifact, logger) {
21800
- if (!fs22.existsSync(artifact.path)) {
22420
+ if (!fs23.existsSync(artifact.path)) {
21801
22421
  return false;
21802
22422
  }
21803
22423
  const marker = extractProvenanceMarker(
21804
- fs22.readFileSync(artifact.path, "utf8")
22424
+ fs23.readFileSync(artifact.path, "utf8")
21805
22425
  );
21806
22426
  if (marker?.target !== artifact.expectedTarget || marker?.source !== artifact.expectedSource) {
21807
22427
  return false;
21808
22428
  }
21809
- fs22.rmSync(artifact.path, { force: true });
22429
+ fs23.rmSync(artifact.path, { force: true });
21810
22430
  logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
21811
22431
  return true;
21812
22432
  }
@@ -21823,6 +22443,80 @@ function removeManagedDirectArtifact(artifact, runtime, logger) {
21823
22443
  logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
21824
22444
  return true;
21825
22445
  }
22446
+ function removeManagedClaudeHooksArtifact(artifact, logger) {
22447
+ const parsed = readJsonObject2(artifact.path);
22448
+ if (!parsed) {
22449
+ return false;
22450
+ }
22451
+ const legacyHookCommands = new Set(artifact.legacyHookCommands ?? []);
22452
+ const hooks = removeManagedClaudeHookEntries(parsed.hooks, (entry) => {
22453
+ return entry._tangyr === true || entry._proteus === true || typeof entry.command === "string" && legacyHookCommands.has(entry.command);
22454
+ });
22455
+ const permissions = removeLegacyClaudeSharedPermission(parsed.permissions);
22456
+ const cleaned = { ...parsed };
22457
+ if (hooks === void 0) {
22458
+ delete cleaned.hooks;
22459
+ } else {
22460
+ cleaned.hooks = hooks;
22461
+ }
22462
+ if (permissions === void 0) {
22463
+ delete cleaned.permissions;
22464
+ } else {
22465
+ cleaned.permissions = permissions;
22466
+ }
22467
+ if (JSON.stringify(cleaned) === JSON.stringify(parsed)) {
22468
+ return false;
22469
+ }
22470
+ writeJsonOrRemove(artifact.path, cleaned);
22471
+ logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
22472
+ return true;
22473
+ }
22474
+ function removeManagedClaudeMcpArtifact(artifact, logger) {
22475
+ const parsed = readJsonObject2(artifact.path);
22476
+ if (!parsed || !isRecord(parsed.mcpServers)) {
22477
+ return false;
22478
+ }
22479
+ const retainedServers = Object.fromEntries(
22480
+ Object.entries(parsed.mcpServers).filter(([, server]) => {
22481
+ if (!isRecord(server)) {
22482
+ return true;
22483
+ }
22484
+ return !isRecord(server._tangyr) && !isRecord(server._proteus);
22485
+ })
22486
+ );
22487
+ if (Object.keys(retainedServers).length === Object.keys(parsed.mcpServers).length) {
22488
+ return false;
22489
+ }
22490
+ const cleaned = { ...parsed, mcpServers: retainedServers };
22491
+ writeJsonOrRemove(artifact.path, cleaned);
22492
+ logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
22493
+ return true;
22494
+ }
22495
+ function removeManagedJsonArtifact(artifact, logger) {
22496
+ const parsed = readJsonObject2(artifact.path);
22497
+ if (!parsed || !hasManagedRootMetadata(parsed, artifact.expectedTarget)) {
22498
+ return false;
22499
+ }
22500
+ fs23.rmSync(artifact.path, { force: true });
22501
+ logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
22502
+ return true;
22503
+ }
22504
+ function removeRecordedArtifact(artifact, logger) {
22505
+ if (!fs23.existsSync(artifact.path) && !isSymlink(artifact.path)) {
22506
+ return false;
22507
+ }
22508
+ removeManagedPath(artifact.path);
22509
+ logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
22510
+ return true;
22511
+ }
22512
+ function removeExactManagedFile(artifact, logger) {
22513
+ if (!fs23.existsSync(artifact.path)) {
22514
+ return false;
22515
+ }
22516
+ fs23.rmSync(artifact.path, { force: true });
22517
+ logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
22518
+ return true;
22519
+ }
21826
22520
  function removeManagedCopilotMcpArtifact(artifact, logger) {
21827
22521
  const parsed = readJsonObject2(artifact.path);
21828
22522
  if (!parsed) {
@@ -21853,10 +22547,10 @@ function removeManagedCodexHooksArtifact(artifact, logger) {
21853
22547
  return true;
21854
22548
  }
21855
22549
  function removeManagedCodexMcpArtifact(artifact, logger) {
21856
- if (!fs22.existsSync(artifact.path)) {
22550
+ if (!fs23.existsSync(artifact.path)) {
21857
22551
  return false;
21858
22552
  }
21859
- const content = fs22.readFileSync(artifact.path, "utf8");
22553
+ const content = fs23.readFileSync(artifact.path, "utf8");
21860
22554
  const managedSection = readManagedTomlSection(content);
21861
22555
  if (!managedSection) {
21862
22556
  return false;
@@ -21871,9 +22565,9 @@ function removeManagedCodexMcpArtifact(artifact, logger) {
21871
22565
  codexManagedMcpEnd
21872
22566
  );
21873
22567
  if (cleaned.trim().length === 0) {
21874
- fs22.rmSync(artifact.path, { force: true });
22568
+ fs23.rmSync(artifact.path, { force: true });
21875
22569
  } else {
21876
- fs22.writeFileSync(artifact.path, cleaned);
22570
+ fs23.writeFileSync(artifact.path, cleaned);
21877
22571
  }
21878
22572
  logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
21879
22573
  return true;
@@ -22046,16 +22740,31 @@ function resolveClinePaths(runtime, scope = "global", projectRoot) {
22046
22740
  function dedupeArtifacts(artifacts) {
22047
22741
  const byPath = /* @__PURE__ */ new Map();
22048
22742
  for (const artifact of artifacts) {
22049
- byPath.set(artifact.path, artifact);
22743
+ const current = byPath.get(artifact.path);
22744
+ if (!current || managedArtifactPlanPriority(artifact) > managedArtifactPlanPriority(current)) {
22745
+ byPath.set(artifact.path, artifact);
22746
+ }
22050
22747
  }
22051
22748
  return Array.from(byPath.values());
22052
22749
  }
22750
+ function managedArtifactPlanPriority(artifact) {
22751
+ if (artifact.observed) {
22752
+ return 3;
22753
+ }
22754
+ if (artifact.kind === "compiled") {
22755
+ return 0;
22756
+ }
22757
+ if (artifact.kind === "recorded") {
22758
+ return 1;
22759
+ }
22760
+ return 2;
22761
+ }
22053
22762
  function readJsonObject2(filePath) {
22054
- if (!fs22.existsSync(filePath)) {
22763
+ if (!fs23.existsSync(filePath)) {
22055
22764
  return null;
22056
22765
  }
22057
22766
  try {
22058
- const parsed = JSON.parse(fs22.readFileSync(filePath, "utf8"));
22767
+ const parsed = JSON.parse(fs23.readFileSync(filePath, "utf8"));
22059
22768
  return isRecord(parsed) ? parsed : null;
22060
22769
  } catch {
22061
22770
  return null;
@@ -22064,15 +22773,86 @@ function readJsonObject2(filePath) {
22064
22773
  function metadataRecord(value) {
22065
22774
  return isRecord(value) ? value : void 0;
22066
22775
  }
22776
+ function containsValueByKey(value, keyName, keyValue) {
22777
+ if (Array.isArray(value)) {
22778
+ return value.some((entry) => containsValueByKey(entry, keyName, keyValue));
22779
+ }
22780
+ if (!isRecord(value)) {
22781
+ return false;
22782
+ }
22783
+ if (value[keyName] === keyValue) {
22784
+ return true;
22785
+ }
22786
+ return Object.values(value).some(
22787
+ (entry) => containsValueByKey(entry, keyName, keyValue)
22788
+ );
22789
+ }
22790
+ function hasLegacyClaudeSharedPermission(parsed) {
22791
+ if (!isRecord(parsed.permissions) || !Array.isArray(parsed.permissions.allow)) {
22792
+ return false;
22793
+ }
22794
+ return parsed.permissions.allow.includes(legacyClaudeSharedPermission);
22795
+ }
22796
+ function removeLegacyClaudeSharedPermission(value) {
22797
+ if (!isRecord(value) || !Array.isArray(value.allow)) {
22798
+ return value;
22799
+ }
22800
+ const retainedAllow = value.allow.filter(
22801
+ (entry) => entry !== legacyClaudeSharedPermission
22802
+ );
22803
+ if (retainedAllow.length === value.allow.length) {
22804
+ return value;
22805
+ }
22806
+ const cleaned = { ...value };
22807
+ if (retainedAllow.length === 0) {
22808
+ delete cleaned.allow;
22809
+ } else {
22810
+ cleaned.allow = retainedAllow;
22811
+ }
22812
+ return Object.keys(cleaned).length === 0 ? void 0 : cleaned;
22813
+ }
22814
+ function isKitPointer(artifact) {
22815
+ if (!artifact.expectedPath || !fs23.existsSync(artifact.path)) {
22816
+ return false;
22817
+ }
22818
+ try {
22819
+ const recordedPath = fs23.readFileSync(artifact.path, "utf8").trim();
22820
+ return recordedPath.length > 0 && path21.resolve(recordedPath) === path21.resolve(artifact.expectedPath);
22821
+ } catch {
22822
+ return false;
22823
+ }
22824
+ }
22825
+ function isLegacyOperatingGuideCopy(filePath) {
22826
+ if (!fs23.existsSync(filePath)) {
22827
+ return false;
22828
+ }
22829
+ try {
22830
+ return fs23.readFileSync(filePath, "utf8").startsWith(legacyOperatingGuideSignature);
22831
+ } catch {
22832
+ return false;
22833
+ }
22834
+ }
22835
+ function hasManagedClaudeMcpServer(parsed) {
22836
+ if (!isRecord(parsed.mcpServers)) {
22837
+ return false;
22838
+ }
22839
+ return Object.values(parsed.mcpServers).some(
22840
+ (server) => isRecord(server) && (isRecord(server._tangyr) || isRecord(server._proteus))
22841
+ );
22842
+ }
22843
+ function hasManagedRootMetadata(parsed, expectedTarget) {
22844
+ const metadata = [parsed._tangyr, parsed._proteus].map(metadataRecord).find((entry) => entry?.target === expectedTarget);
22845
+ return metadata !== void 0;
22846
+ }
22067
22847
  function matchesManagedMetadata(metadata, artifact) {
22068
22848
  return metadata?.source === artifact.expectedSource && metadata?.target === artifact.expectedTarget;
22069
22849
  }
22070
22850
  function writeJsonOrRemove(filePath, parsed) {
22071
22851
  if (isEmptyJsonValue(parsed)) {
22072
- fs22.rmSync(filePath, { force: true });
22852
+ fs23.rmSync(filePath, { force: true });
22073
22853
  return;
22074
22854
  }
22075
- fs22.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
22855
+ fs23.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
22076
22856
  `);
22077
22857
  }
22078
22858
  function isEmptyJsonValue(value) {
@@ -22152,6 +22932,31 @@ function removeManagedValueByKey(value, keyName, keyValue) {
22152
22932
  });
22153
22933
  return entries.length > 0 ? Object.fromEntries(entries) : void 0;
22154
22934
  }
22935
+ function removeManagedClaudeHookEntries(value, isManagedEntry) {
22936
+ if (Array.isArray(value)) {
22937
+ const retained = value.flatMap((entry) => {
22938
+ const cleaned2 = removeManagedClaudeHookEntries(entry, isManagedEntry);
22939
+ return cleaned2 === void 0 ? [] : [cleaned2];
22940
+ });
22941
+ return retained.length > 0 ? retained : void 0;
22942
+ }
22943
+ if (!isRecord(value)) {
22944
+ return value;
22945
+ }
22946
+ if (isManagedEntry(value)) {
22947
+ return void 0;
22948
+ }
22949
+ const hadHookChildren = Object.hasOwn(value, "hooks");
22950
+ const entries = Object.entries(value).flatMap(([key, entry]) => {
22951
+ const cleaned2 = removeManagedClaudeHookEntries(entry, isManagedEntry);
22952
+ return cleaned2 === void 0 ? [] : [[key, cleaned2]];
22953
+ });
22954
+ const cleaned = entries.length > 0 ? Object.fromEntries(entries) : void 0;
22955
+ if (hadHookChildren && (!cleaned || !("hooks" in cleaned))) {
22956
+ return void 0;
22957
+ }
22958
+ return cleaned;
22959
+ }
22155
22960
  function readManagedTomlSection(content) {
22156
22961
  const start = content.indexOf(codexManagedMcpStart);
22157
22962
  const end = content.indexOf(codexManagedMcpEnd);
@@ -22173,20 +22978,20 @@ function removeDelimitedManagedSection(content, startMarker, endMarker) {
22173
22978
  return `${content.slice(0, start)}${content.slice(removalEnd)}`;
22174
22979
  }
22175
22980
  function restoreBackup(backup, logger) {
22176
- if (!fs22.existsSync(backup.backupLocation)) {
22981
+ if (!fs23.existsSync(backup.backupLocation)) {
22177
22982
  logger.warn(` backup not found: ${backup.backupLocation}`);
22178
22983
  return;
22179
22984
  }
22180
- const destDir = path20.dirname(backup.originalPath);
22181
- fs22.mkdirSync(destDir, { recursive: true });
22182
- fs22.renameSync(backup.backupLocation, backup.originalPath);
22985
+ const destDir = path21.dirname(backup.originalPath);
22986
+ fs23.mkdirSync(destDir, { recursive: true });
22987
+ fs23.renameSync(backup.backupLocation, backup.originalPath);
22183
22988
  logger.verbose(
22184
22989
  ` restored: ${backup.backupLocation} \u2192 ${backup.originalPath}`
22185
22990
  );
22186
22991
  }
22187
22992
  function isSymlink(p) {
22188
22993
  try {
22189
- return fs22.lstatSync(p).isSymbolicLink();
22994
+ return fs23.lstatSync(p).isSymbolicLink();
22190
22995
  } catch {
22191
22996
  return false;
22192
22997
  }
@@ -22260,7 +23065,7 @@ function cleanupClaudeCode(config, sourceRoot, configDir, logger, scope) {
22260
23065
  )) {
22261
23066
  const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
22262
23067
  if (artifactClass === "managed-symlink" || artifactClass === "managed-compiled" || artifactClass === "managed-stale") {
22263
- fs23.rmSync(artifact.path, { recursive: true, force: true });
23068
+ fs24.rmSync(artifact.path, { recursive: true, force: true });
22264
23069
  logger.info(`${artifact.component}: removed ${artifact.path}`);
22265
23070
  }
22266
23071
  }
@@ -22316,7 +23121,7 @@ function cleanupCopilot(config, sourceRoot, configDir, logger) {
22316
23121
  logger
22317
23122
  );
22318
23123
  removeManagedJsonFile(
22319
- path21.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
23124
+ path22.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
22320
23125
  "_tangyr",
22321
23126
  logger
22322
23127
  );
@@ -22473,40 +23278,40 @@ function removeManagedValueByKey2(value, keyName, keyValue) {
22473
23278
  function removeManagedDirectPath(artifactPath, config, sourceRoot, component, logger) {
22474
23279
  const artifactClass = classifyArtifact(artifactPath, config, sourceRoot);
22475
23280
  if (artifactClass === "managed-symlink" || artifactClass === "managed-compiled" || artifactClass === "managed-stale") {
22476
- fs23.rmSync(artifactPath, { recursive: true, force: true });
23281
+ fs24.rmSync(artifactPath, { recursive: true, force: true });
22477
23282
  logger.info(`${component}: removed ${artifactPath}`);
22478
23283
  }
22479
23284
  }
22480
23285
  function removeManagedCompiledFiles(dir, pattern, expectedTarget, logger) {
22481
- for (const filePath of ts(path21.join(dir, pattern)).sort()) {
23286
+ for (const filePath of ts(path22.join(dir, pattern)).sort()) {
22482
23287
  removeManagedCompiledFile(filePath, expectedTarget, logger);
22483
23288
  }
22484
23289
  }
22485
23290
  function removeManagedCompiledFile(filePath, expectedTarget, logger) {
22486
- if (!fs23.existsSync(filePath)) {
23291
+ if (!fs24.existsSync(filePath)) {
22487
23292
  return;
22488
23293
  }
22489
- const marker = extractProvenanceMarker(fs23.readFileSync(filePath, "utf8"));
23294
+ const marker = extractProvenanceMarker(fs24.readFileSync(filePath, "utf8"));
22490
23295
  if (marker?.target === expectedTarget) {
22491
- fs23.rmSync(filePath, { force: true });
23296
+ fs24.rmSync(filePath, { force: true });
22492
23297
  logger.info(`removed ${filePath}`);
22493
23298
  }
22494
23299
  }
22495
23300
  function removeManagedJsonFile(filePath, markerKey, logger) {
22496
- if (!fs23.existsSync(filePath)) {
23301
+ if (!fs24.existsSync(filePath)) {
22497
23302
  return;
22498
23303
  }
22499
23304
  const parsed = readJsonObject(filePath);
22500
23305
  if (isRecord(parsed[markerKey])) {
22501
- fs23.rmSync(filePath, { force: true });
23306
+ fs24.rmSync(filePath, { force: true });
22502
23307
  logger.info(`removed ${filePath}`);
22503
23308
  }
22504
23309
  }
22505
23310
  function removeCodexManagedTomlSection(filePath, logger) {
22506
- if (!fs23.existsSync(filePath)) {
23311
+ if (!fs24.existsSync(filePath)) {
22507
23312
  return;
22508
23313
  }
22509
- const content = fs23.readFileSync(filePath, "utf8");
23314
+ const content = fs24.readFileSync(filePath, "utf8");
22510
23315
  const next = removeDelimitedManagedSection2(
22511
23316
  content,
22512
23317
  codexManagedMcpStart2,
@@ -22515,7 +23320,7 @@ function removeCodexManagedTomlSection(filePath, logger) {
22515
23320
  if (next === content) {
22516
23321
  return;
22517
23322
  }
22518
- fs23.writeFileSync(filePath, next);
23323
+ fs24.writeFileSync(filePath, next);
22519
23324
  logger.info(`mcp: removed managed section from ${filePath}`);
22520
23325
  }
22521
23326
  function removeDelimitedManagedSection2(content, startMarker, endMarker) {
@@ -22587,9 +23392,9 @@ function toVerbosity(value) {
22587
23392
  }
22588
23393
 
22589
23394
  // src/commands/detect.ts
22590
- import fs24 from "fs";
23395
+ import fs25 from "fs";
22591
23396
  import os5 from "os";
22592
- import path22 from "path";
23397
+ import path23 from "path";
22593
23398
  import { spawnSync } from "child_process";
22594
23399
  var copilotEditorCommands = [
22595
23400
  "code",
@@ -22623,18 +23428,27 @@ var bundledCopilotManifestPathsByPlatform = {
22623
23428
  "/Applications/Windsurf.app/Contents/Resources/app/extensions/copilot/package.json"
22624
23429
  ]
22625
23430
  };
22626
- function detectTargets(logger) {
23431
+ var bundledCursorExecutablePathsByPlatform = {
23432
+ darwin: ["/Applications/Cursor.app/Contents/Resources/app/bin/cursor"]
23433
+ };
23434
+ function detectTargets(logger, dependencies = {}) {
23435
+ const spawnSyncImpl = dependencies.spawnSyncImpl ?? defaultSpawnSync;
23436
+ const pathExists = dependencies.pathExists ?? fs25.existsSync;
23437
+ const homeDirectory = dependencies.homeDirectory ?? os5.homedir();
23438
+ const platform = dependencies.platform ?? process.platform;
23439
+ const locator = platform === "win32" ? "where.exe" : "which";
23440
+ const hasCommand = (command) => commandExists(locator, [command], logger, spawnSyncImpl);
22627
23441
  const result = {
22628
- "claude-code": commandExists(
22629
- process.platform === "win32" ? "where.exe" : "which",
22630
- ["claude"],
22631
- logger
22632
- ),
22633
- copilot: detectsCopilot(logger),
22634
- codex: commandExists(
22635
- process.platform === "win32" ? "where.exe" : "which",
22636
- ["codex"],
22637
- logger
23442
+ "claude-code": hasCommand("claude"),
23443
+ copilot: detectsCopilot(logger, dependencies),
23444
+ codex: hasCommand("codex"),
23445
+ opencode: hasCommand("opencode"),
23446
+ cursor: hasCommand("cursor") || cursorExecutablePaths(platform, homeDirectory).some(pathExists),
23447
+ cline: hasCommand("cline") || detectEditorExtension(
23448
+ "Cline",
23449
+ isClineExtensionEntry,
23450
+ logger,
23451
+ dependencies
22638
23452
  )
22639
23453
  };
22640
23454
  return result;
@@ -22650,14 +23464,41 @@ function runDetectCommand(options, logger) {
22650
23464
  }
22651
23465
  process.exitCode = Object.values(result).some(Boolean) ? 0 : 3;
22652
23466
  }
22653
- function detectsCopilot(logger) {
22654
- return detectCopilot(logger);
23467
+ function detectsCopilot(logger, dependencies = {}) {
23468
+ return detectCopilot(logger, dependencies);
22655
23469
  }
22656
23470
  function detectCopilot(logger, dependencies = {}) {
23471
+ const pathExists = dependencies.pathExists ?? fs25.existsSync;
23472
+ const readFile = dependencies.readFile ?? ((filePath) => fs25.readFileSync(filePath, "utf8"));
23473
+ const platform = dependencies.platform ?? process.platform;
23474
+ if (detectEditorExtension(
23475
+ "Copilot",
23476
+ isCopilotExtensionEntry,
23477
+ logger,
23478
+ dependencies
23479
+ )) {
23480
+ return true;
23481
+ }
23482
+ for (const manifestPath of bundledCopilotManifestPathsByPlatform[platform] ?? []) {
23483
+ if (!pathExists(manifestPath)) {
23484
+ continue;
23485
+ }
23486
+ try {
23487
+ if (isBundledCopilotManifest(readFile(manifestPath))) {
23488
+ return true;
23489
+ }
23490
+ } catch (error) {
23491
+ logger?.verbose(
23492
+ `${manifestPath}: failed to inspect bundled Copilot runtime (${formatReadError(error)})`
23493
+ );
23494
+ }
23495
+ }
23496
+ return false;
23497
+ }
23498
+ function detectEditorExtension(label, matchesExtension, logger, dependencies = {}) {
22657
23499
  const spawnSyncImpl = dependencies.spawnSyncImpl ?? defaultSpawnSync;
22658
- const pathExists = dependencies.pathExists ?? fs24.existsSync;
22659
- const readDirectory = dependencies.readDirectory ?? fs24.readdirSync;
22660
- const readFile = dependencies.readFile ?? ((filePath) => fs24.readFileSync(filePath, "utf8"));
23500
+ const pathExists = dependencies.pathExists ?? fs25.existsSync;
23501
+ const readDirectory = dependencies.readDirectory ?? fs25.readdirSync;
22661
23502
  const homeDirectory = dependencies.homeDirectory ?? os5.homedir();
22662
23503
  const platform = dependencies.platform ?? process.platform;
22663
23504
  const commandCandidates = [
@@ -22680,41 +23521,40 @@ function detectCopilot(logger, dependencies = {}) {
22680
23521
  if (result.status !== 0) {
22681
23522
  continue;
22682
23523
  }
22683
- if (splitOutputEntries(result.stdout).some(isCopilotExtensionEntry)) {
23524
+ if (splitOutputEntries(result.stdout).some(matchesExtension)) {
22684
23525
  return true;
22685
23526
  }
22686
23527
  }
22687
23528
  for (const relativeDirectory of copilotExtensionDirectories) {
22688
- const extensionDirectory = path22.join(homeDirectory, relativeDirectory);
23529
+ const extensionDirectory = path23.join(homeDirectory, relativeDirectory);
22689
23530
  if (!pathExists(extensionDirectory)) {
22690
23531
  continue;
22691
23532
  }
22692
23533
  try {
22693
- if (readDirectory(extensionDirectory).some(isCopilotExtensionEntry)) {
23534
+ if (readDirectory(extensionDirectory).some(matchesExtension)) {
22694
23535
  return true;
22695
23536
  }
22696
23537
  } catch (error) {
22697
23538
  logger?.verbose(
22698
- `${extensionDirectory}: failed to inspect Copilot extensions (${formatReadError(error)})`
22699
- );
22700
- }
22701
- }
22702
- for (const manifestPath of bundledCopilotManifestPathsByPlatform[platform] ?? []) {
22703
- if (!pathExists(manifestPath)) {
22704
- continue;
22705
- }
22706
- try {
22707
- if (isBundledCopilotManifest(readFile(manifestPath))) {
22708
- return true;
22709
- }
22710
- } catch (error) {
22711
- logger?.verbose(
22712
- `${manifestPath}: failed to inspect bundled Copilot runtime (${formatReadError(error)})`
23539
+ `${extensionDirectory}: failed to inspect ${label} extensions (${formatReadError(error)})`
22713
23540
  );
22714
23541
  }
22715
23542
  }
22716
23543
  return false;
22717
23544
  }
23545
+ function cursorExecutablePaths(platform, homeDirectory) {
23546
+ const systemPaths = bundledCursorExecutablePathsByPlatform[platform] ?? [];
23547
+ if (platform !== "darwin") {
23548
+ return [...systemPaths];
23549
+ }
23550
+ return [
23551
+ ...systemPaths,
23552
+ path23.join(
23553
+ homeDirectory,
23554
+ "Applications/Cursor.app/Contents/Resources/app/bin/cursor"
23555
+ )
23556
+ ];
23557
+ }
22718
23558
  function defaultSpawnSync(command, args) {
22719
23559
  return spawnSync(command, args, { encoding: "utf8" });
22720
23560
  }
@@ -22727,6 +23567,9 @@ function splitOutputEntries(stdout) {
22727
23567
  function isCopilotExtensionEntry(entry) {
22728
23568
  return /^github\.copilot(?:-chat)?(?:@|-)/u.test(entry);
22729
23569
  }
23570
+ function isClineExtensionEntry(entry) {
23571
+ return /^saoudrizwan\.claude-dev(?:@|-)/u.test(entry);
23572
+ }
22730
23573
  function isBundledCopilotManifest(rawManifest) {
22731
23574
  const parsed = JSON.parse(rawManifest);
22732
23575
  if (!isRecord2(parsed)) {
@@ -22745,8 +23588,8 @@ function formatReadError(error) {
22745
23588
  }
22746
23589
  return String(error);
22747
23590
  }
22748
- function commandExists(command, args, logger) {
22749
- const result = spawnSync(command, args, { encoding: "utf8" });
23591
+ function commandExists(command, args, logger, spawnSyncImpl = defaultSpawnSync) {
23592
+ const result = spawnSyncImpl(command, args);
22750
23593
  if (result.error) {
22751
23594
  logDetectionError(`${command} ${args.join(" ")}`, result.error, logger);
22752
23595
  return false;
@@ -22766,25 +23609,25 @@ function logDetectionError(attemptedCommand, error, logger) {
22766
23609
  }
22767
23610
 
22768
23611
  // src/commands/doctor.ts
22769
- import fs26 from "fs";
22770
- import path24 from "path";
23612
+ import fs27 from "fs";
23613
+ import path25 from "path";
22771
23614
 
22772
23615
  // src/utils/fs.ts
22773
- import fs25 from "fs";
22774
- import path23 from "path";
23616
+ import fs26 from "fs";
23617
+ import path24 from "path";
22775
23618
  function ensureDir(dirPath) {
22776
- fs25.mkdirSync(dirPath, { recursive: true });
23619
+ fs26.mkdirSync(dirPath, { recursive: true });
22777
23620
  }
22778
23621
  function createRelativeSymlink(source, destination, type, options) {
22779
- const absoluteSource = path23.resolve(source);
22780
- const relative = path23.relative(realPathOrInput(path23.dirname(destination)), absoluteSource);
23622
+ const absoluteSource = path24.resolve(source);
23623
+ const relative = path24.relative(realPathOrInput(path24.dirname(destination)), absoluteSource);
22781
23624
  if (process.platform === "win32" && type === "dir") {
22782
- fs25.symlinkSync(absoluteSource, destination, "junction");
23625
+ fs26.symlinkSync(absoluteSource, destination, "junction");
22783
23626
  return;
22784
23627
  }
22785
23628
  if (process.platform === "win32" && type === "file") {
22786
23629
  try {
22787
- fs25.symlinkSync(relative, destination, "file");
23630
+ fs26.symlinkSync(relative, destination, "file");
22788
23631
  } catch (error) {
22789
23632
  if (!hasErrorCode(error, "EPERM")) {
22790
23633
  throw error;
@@ -22799,12 +23642,12 @@ function createRelativeSymlink(source, destination, type, options) {
22799
23642
  }
22800
23643
  return;
22801
23644
  }
22802
- fs25.symlinkSync(relative, destination, type);
23645
+ fs26.symlinkSync(relative, destination, type);
22803
23646
  }
22804
23647
  function createManagedCopy(source, destination, provenanceMarker, _logger) {
22805
- ensureDir(path23.dirname(destination));
22806
- const content = fs25.readFileSync(source, "utf8");
22807
- fs25.writeFileSync(destination, `${provenanceMarker}
23648
+ ensureDir(path24.dirname(destination));
23649
+ const content = fs26.readFileSync(source, "utf8");
23650
+ fs26.writeFileSync(destination, `${provenanceMarker}
22808
23651
  ${content}`);
22809
23652
  }
22810
23653
  function hasErrorCode(error, expectedCode) {
@@ -22812,7 +23655,7 @@ function hasErrorCode(error, expectedCode) {
22812
23655
  }
22813
23656
  function realPathOrInput(filePath) {
22814
23657
  try {
22815
- return fs25.realpathSync(filePath);
23658
+ return fs26.realpathSync(filePath);
22816
23659
  } catch {
22817
23660
  return filePath;
22818
23661
  }
@@ -22825,17 +23668,17 @@ function runDoctorCommand(options, logger) {
22825
23668
  import.meta.url
22826
23669
  );
22827
23670
  const findings = [];
22828
- if (!fs26.existsSync(configPath)) {
23671
+ if (!fs27.existsSync(configPath)) {
22829
23672
  findings.push(`${configPath}: missing`);
22830
23673
  }
22831
- const hooksJsonPath = path24.join(
23674
+ const hooksJsonPath = path25.join(
22832
23675
  sourceRoot,
22833
23676
  config.source.hooks,
22834
23677
  "hooks.json"
22835
23678
  );
22836
- if (fs26.existsSync(hooksJsonPath)) {
23679
+ if (fs27.existsSync(hooksJsonPath)) {
22837
23680
  try {
22838
- JSON.parse(fs26.readFileSync(hooksJsonPath, "utf8"));
23681
+ JSON.parse(fs27.readFileSync(hooksJsonPath, "utf8"));
22839
23682
  } catch (err) {
22840
23683
  findings.push(
22841
23684
  `hooks/hooks.json: ${err instanceof Error ? err.message : String(err)}`
@@ -22900,19 +23743,19 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
22900
23743
  projectRoot
22901
23744
  )) {
22902
23745
  const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
22903
- const sourcePath = artifact.sourceKey ? path24.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
23746
+ const sourcePath = artifact.sourceKey ? path25.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
22904
23747
  if (artifactClass === "managed-stale") {
22905
23748
  findings.push(
22906
23749
  `${artifact.component}: managed stale artifact at ${artifact.path}`
22907
23750
  );
22908
23751
  if (options.fix && sourcePath && isOurStaleSymlink(
22909
23752
  artifact.path,
22910
- /* @__PURE__ */ new Set([path24.resolve(artifact.path)]),
23753
+ /* @__PURE__ */ new Set([path25.resolve(artifact.path)]),
22911
23754
  config
22912
23755
  )) {
22913
- fs26.unlinkSync(artifact.path);
22914
- ensureDir(path24.dirname(artifact.path));
22915
- const symlinkType = fs26.statSync(sourcePath).isDirectory() ? "dir" : "file";
23756
+ fs27.unlinkSync(artifact.path);
23757
+ ensureDir(path25.dirname(artifact.path));
23758
+ const symlinkType = fs27.statSync(sourcePath).isDirectory() ? "dir" : "file";
22916
23759
  createRelativeSymlink(sourcePath, artifact.path, symlinkType, {
22917
23760
  logger,
22918
23761
  provenanceMarker: symlinkType === "file" && artifact.sourceKey ? formatProvenanceMarker(
@@ -22925,8 +23768,8 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
22925
23768
  logger.info(`${artifact.component}: recreated managed symlink`);
22926
23769
  }
22927
23770
  }
22928
- if (options.fix && !fs26.existsSync(path24.dirname(artifact.path))) {
22929
- ensureDir(path24.dirname(artifact.path));
23771
+ if (options.fix && !fs27.existsSync(path25.dirname(artifact.path))) {
23772
+ ensureDir(path25.dirname(artifact.path));
22930
23773
  }
22931
23774
  checkParentWritablePath(artifact.path, artifact.component, findings);
22932
23775
  }
@@ -22941,7 +23784,7 @@ function checkCopilot(config, sourceRoot, configDir, findings) {
22941
23784
  continue;
22942
23785
  }
22943
23786
  const label = `copilot: ${rawPath}`;
22944
- if (key.endsWith("_shared_file") || path24.extname(rawPath).length > 0) {
23787
+ if (key.endsWith("_shared_file") || path25.extname(rawPath).length > 0) {
22945
23788
  checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
22946
23789
  continue;
22947
23790
  }
@@ -22961,7 +23804,7 @@ function checkCodex(config, sourceRoot, configDir, findings, logger) {
22961
23804
  continue;
22962
23805
  }
22963
23806
  const label = `codex: ${rawPath}`;
22964
- if (key.endsWith("_shared_file") || path24.extname(rawPath).length > 0) {
23807
+ if (key.endsWith("_shared_file") || path25.extname(rawPath).length > 0) {
22965
23808
  checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
22966
23809
  continue;
22967
23810
  }
@@ -22978,33 +23821,33 @@ function resolveHooksScriptPath(config, sourceRoot, configDir) {
22978
23821
  scope: "global",
22979
23822
  mappings: mappings.platformPaths
22980
23823
  });
22981
- return path24.join(profile["claude-code"].hooks, "scripts");
23824
+ return path25.join(profile["claude-code"].hooks, "scripts");
22982
23825
  } catch {
22983
23826
  return resolveTargetPath("~/.agents/hooks/scripts");
22984
23827
  }
22985
23828
  }
22986
23829
  function checkParentWritablePath(targetPath, label, findings) {
22987
- checkWritablePath(path24.dirname(targetPath), `${label} parent`, findings);
23830
+ checkWritablePath(path25.dirname(targetPath), `${label} parent`, findings);
22988
23831
  }
22989
23832
  function checkWritablePath(checkPath, label, findings) {
22990
- if (!fs26.existsSync(checkPath)) {
23833
+ if (!fs27.existsSync(checkPath)) {
22991
23834
  findings.push(`${label}: path does not exist`);
22992
23835
  return;
22993
23836
  }
22994
23837
  try {
22995
- fs26.accessSync(checkPath, fs26.constants.R_OK | fs26.constants.W_OK);
23838
+ fs27.accessSync(checkPath, fs27.constants.R_OK | fs27.constants.W_OK);
22996
23839
  } catch {
22997
23840
  findings.push(`${label}: path is not readable and writable`);
22998
23841
  }
22999
23842
  }
23000
23843
  function walkHookScripts(dir) {
23001
- if (!fs26.existsSync(dir)) {
23844
+ if (!fs27.existsSync(dir)) {
23002
23845
  return [];
23003
23846
  }
23004
- return fs26.readdirSync(dir).map((entry) => path24.join(dir, entry)).filter((entryPath) => fs26.statSync(entryPath).isFile());
23847
+ return fs27.readdirSync(dir).map((entry) => path25.join(dir, entry)).filter((entryPath) => fs27.statSync(entryPath).isFile());
23005
23848
  }
23006
23849
  function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
23007
- if (!fs26.existsSync(scriptRoot)) {
23850
+ if (!fs27.existsSync(scriptRoot)) {
23008
23851
  return;
23009
23852
  }
23010
23853
  if (hasSymlinkAncestor(scriptRoot, resolveTargetPath("~/.agents")) || isInside(realPathOrInput2(scriptRoot), realPathOrInput2(sourceRoot))) {
@@ -23014,49 +23857,49 @@ function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
23014
23857
  return;
23015
23858
  }
23016
23859
  for (const scriptPath of walkHookScripts(scriptRoot)) {
23017
- fs26.chmodSync(scriptPath, 493);
23860
+ fs27.chmodSync(scriptPath, 493);
23018
23861
  }
23019
23862
  }
23020
23863
  function hasSymlinkAncestor(targetPath, stopAt) {
23021
- const relative = path24.relative(
23022
- path24.resolve(stopAt),
23023
- path24.resolve(targetPath)
23864
+ const relative = path25.relative(
23865
+ path25.resolve(stopAt),
23866
+ path25.resolve(targetPath)
23024
23867
  );
23025
- if (relative.startsWith("..") || path24.isAbsolute(relative)) {
23868
+ if (relative.startsWith("..") || path25.isAbsolute(relative)) {
23026
23869
  return false;
23027
23870
  }
23028
- return relative.split(path24.sep).some((_segment, index, segments) => {
23029
- const candidate = path24.join(
23030
- path24.resolve(stopAt),
23871
+ return relative.split(path25.sep).some((_segment, index, segments) => {
23872
+ const candidate = path25.join(
23873
+ path25.resolve(stopAt),
23031
23874
  ...segments.slice(0, index + 1)
23032
23875
  );
23033
23876
  try {
23034
- return fs26.lstatSync(candidate).isSymbolicLink();
23877
+ return fs27.lstatSync(candidate).isSymbolicLink();
23035
23878
  } catch {
23036
23879
  return false;
23037
23880
  }
23038
23881
  });
23039
23882
  }
23040
23883
  function isInside(childPath, parentPath) {
23041
- const relative = path24.relative(parentPath, childPath);
23042
- return relative.length === 0 || !relative.startsWith("..") && !path24.isAbsolute(relative);
23884
+ const relative = path25.relative(parentPath, childPath);
23885
+ return relative.length === 0 || !relative.startsWith("..") && !path25.isAbsolute(relative);
23043
23886
  }
23044
23887
  function realPathOrInput2(filePath) {
23045
23888
  try {
23046
- return fs26.realpathSync(filePath);
23889
+ return fs27.realpathSync(filePath);
23047
23890
  } catch {
23048
23891
  return filePath;
23049
23892
  }
23050
23893
  }
23051
23894
 
23052
23895
  // src/commands/init.ts
23053
- import fs27 from "fs";
23054
- import path25 from "path";
23055
- var import_yaml6 = __toESM(require_dist(), 1);
23896
+ import fs28 from "fs";
23897
+ import path26 from "path";
23898
+ var import_yaml7 = __toESM(require_dist(), 1);
23056
23899
  async function runInitCommand(_options, logger) {
23057
23900
  const sourceRoot = await dist_default6({
23058
23901
  message: "Canonical Tangyr kit root",
23059
- default: path25.resolve("projects/tangyr/agent-coding")
23902
+ default: path26.resolve("projects/tangyr/agent-coding")
23060
23903
  });
23061
23904
  const componentCount = [
23062
23905
  "CLAUDE.md",
@@ -23066,7 +23909,7 @@ async function runInitCommand(_options, logger) {
23066
23909
  "rules",
23067
23910
  "hooks"
23068
23911
  ].filter(
23069
- (relativePath) => fs27.existsSync(path25.join(sourceRoot, relativePath))
23912
+ (relativePath) => fs28.existsSync(path26.join(sourceRoot, relativePath))
23070
23913
  ).length;
23071
23914
  const detectedTargets = detectTargets(logger);
23072
23915
  const enabledTargets = await dist_default4({
@@ -23084,8 +23927,8 @@ async function runInitCommand(_options, logger) {
23084
23927
  value
23085
23928
  }))
23086
23929
  });
23087
- const configPath = path25.join(sourceRoot, "tangyr.config.yaml");
23088
- if (fs27.existsSync(configPath)) {
23930
+ const configPath = path26.join(sourceRoot, "tangyr.config.yaml");
23931
+ if (fs28.existsSync(configPath)) {
23089
23932
  const overwrite = await dist_default5({
23090
23933
  message: `${configPath} exists. Overwrite?`,
23091
23934
  default: false
@@ -23095,9 +23938,9 @@ async function runInitCommand(_options, logger) {
23095
23938
  return;
23096
23939
  }
23097
23940
  }
23098
- fs27.writeFileSync(
23941
+ fs28.writeFileSync(
23099
23942
  configPath,
23100
- (0, import_yaml6.stringify)({
23943
+ (0, import_yaml7.stringify)({
23101
23944
  schema: 1,
23102
23945
  kitPath: ".",
23103
23946
  source: {
@@ -23142,11 +23985,11 @@ import fs37 from "fs";
23142
23985
  import path37 from "path";
23143
23986
 
23144
23987
  // src/core/channel-state.ts
23145
- import fs28 from "fs";
23146
- import path26 from "path";
23988
+ import fs29 from "fs";
23989
+ import path27 from "path";
23147
23990
  var CHANNEL_STATE_FILENAME = ".tangyr-channels.json";
23148
23991
  function stateFilePath(cacheRoot) {
23149
- return path26.join(cacheRoot, CHANNEL_STATE_FILENAME);
23992
+ return path27.join(cacheRoot, CHANNEL_STATE_FILENAME);
23150
23993
  }
23151
23994
  function channelKey(kit, channel) {
23152
23995
  return `${kit}/${channel}`;
@@ -23155,7 +23998,7 @@ function readState(cacheRoot) {
23155
23998
  const filePath = stateFilePath(cacheRoot);
23156
23999
  let raw;
23157
24000
  try {
23158
- raw = fs28.readFileSync(filePath, "utf8");
24001
+ raw = fs29.readFileSync(filePath, "utf8");
23159
24002
  } catch (err) {
23160
24003
  if (err.code === "ENOENT") {
23161
24004
  return { state: {} };
@@ -23202,13 +24045,13 @@ function writeChannelSequence(params) {
23202
24045
  [key]: { sequence, version, seenAt: now.toISOString() }
23203
24046
  };
23204
24047
  const filePath = stateFilePath(cacheRoot);
23205
- fs28.mkdirSync(path26.dirname(filePath), { recursive: true, mode: 448 });
24048
+ fs29.mkdirSync(path27.dirname(filePath), { recursive: true, mode: 448 });
23206
24049
  const tempPath = `${filePath}.${process.pid}.tmp`;
23207
- fs28.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
24050
+ fs29.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
23208
24051
  `, {
23209
24052
  mode: 384
23210
24053
  });
23211
- fs28.renameSync(tempPath, filePath);
24054
+ fs29.renameSync(tempPath, filePath);
23212
24055
  }
23213
24056
  function assertChannelNotRolledBack(params) {
23214
24057
  const { originUrl, kit, channel, seen, seenVersion, incoming } = params;
@@ -23220,7 +24063,6 @@ function assertChannelNotRolledBack(params) {
23220
24063
  }
23221
24064
 
23222
24065
  // src/core/bundle.ts
23223
- var DENY_LIST_TYPE = "tangyr.deny-list.v2";
23224
24066
  var CHANNEL_POINTER_TYPE = "tangyr.channel-pointer.v1";
23225
24067
  var DEFAULT_CHANNEL = "stable";
23226
24068
 
@@ -23344,47 +24186,6 @@ function verifyBundle(bundle, keys, expectedIdentity, now) {
23344
24186
  verifyBundleSignature(bundle, keys, now);
23345
24187
  verifyIdentity(bundle.manifest, expectedIdentity);
23346
24188
  }
23347
- function verifyDenyList(denyList, keys, now) {
23348
- if (denyList === null || typeof denyList !== "object") {
23349
- throw new IntegrityError(DENY_LIST_MALFORMED);
23350
- }
23351
- const actualKeys = Object.keys(denyList).sort();
23352
- const expectedKeys = [
23353
- "entries",
23354
- "expiresAt",
23355
- "issuedAt",
23356
- "keyId",
23357
- "sequence",
23358
- "signature",
23359
- "type"
23360
- ];
23361
- if (actualKeys.length !== expectedKeys.length || actualKeys.some((key, index) => key !== expectedKeys[index])) {
23362
- throw new IntegrityError(
23363
- `${DENY_LIST_MALFORMED} Expected exactly [${expectedKeys.join(", ")}], got [${actualKeys.join(", ")}].`
23364
- );
23365
- }
23366
- const list = denyList;
23367
- const shapeOk = list.type === DENY_LIST_TYPE && typeof list.keyId === "string" && typeof list.signature === "string" && list.signature.length > 0 && Number.isSafeInteger(list.sequence) && list.sequence >= 0 && typeof list.issuedAt === "string" && typeof list.expiresAt === "string" && Array.isArray(list.entries) && list.entries.every((entry) => typeof entry === "string");
23368
- if (!shapeOk) {
23369
- throw new IntegrityError(DENY_LIST_MALFORMED);
23370
- }
23371
- const { signature, ...signed } = list;
23372
- verifySignedPayload(
23373
- canonicalJsonBytes(signed),
23374
- signature,
23375
- list.keyId,
23376
- keys,
23377
- now
23378
- );
23379
- assertFreshnessWindow(
23380
- list.issuedAt,
23381
- list.expiresAt,
23382
- now,
23383
- "An expired revocation deny-list is not evidence that nothing is revoked \u2014 the publisher must re-sign and republish it."
23384
- );
23385
- return list;
23386
- }
23387
- var DENY_LIST_MALFORMED = "Revocation deny-list response is malformed, unsigned, or corrupted \u2014 treated as an integrity failure, never as an absent deny-list (REQ-INT-009).";
23388
24189
  function assertFreshnessWindow(issuedAt, expiresAt, now, expiryConsequence) {
23389
24190
  const utcDesignatorPattern = /Z|[+-]\d{2}:\d{2}$/;
23390
24191
  if (!utcDesignatorPattern.test(issuedAt) || !utcDesignatorPattern.test(expiresAt)) {
@@ -23437,101 +24238,32 @@ function verifyChannelPointer(pointer, expectedKit, expectedChannel, keys, now)
23437
24238
  `${CHANNEL_POINTER_MALFORMED} Expected exactly [${expectedKeys.join(", ")}], got [${actualKeys.join(", ")}].`
23438
24239
  );
23439
24240
  }
23440
- const candidate = pointer;
23441
- const shapeOk = candidate.type === CHANNEL_POINTER_TYPE && typeof candidate.keyId === "string" && typeof candidate.kit === "string" && candidate.kit.length > 0 && typeof candidate.channel === "string" && candidate.channel.length > 0 && typeof candidate.version === "string" && candidate.version.length > 0 && typeof candidate.signature === "string" && candidate.signature.length > 0 && Number.isSafeInteger(candidate.sequence) && candidate.sequence >= 0 && typeof candidate.issuedAt === "string" && typeof candidate.expiresAt === "string";
23442
- if (!shapeOk) {
23443
- throw new IntegrityError(CHANNEL_POINTER_MALFORMED);
23444
- }
23445
- const { signature, ...signed } = candidate;
23446
- verifySignedPayload(
23447
- canonicalJsonBytes(signed),
23448
- signature,
23449
- candidate.keyId,
23450
- keys,
23451
- now
23452
- );
23453
- if (candidate.kit !== expectedKit || candidate.channel !== expectedChannel) {
23454
- throw new IntegrityError(
23455
- `Channel pointer is signed for ${candidate.kit}/${candidate.channel} but was served as ${expectedKit}/${expectedChannel}. A pointer the publisher signed for one channel is being presented as another's \u2014 refusing.`
23456
- );
23457
- }
23458
- assertPathSafeComponent("version", candidate.version);
23459
- assertFreshnessWindow(
23460
- candidate.issuedAt,
23461
- candidate.expiresAt,
23462
- now,
23463
- "An expired channel pointer is not evidence that it still names the newest version \u2014 the publisher must re-sign and republish it."
23464
- );
23465
- return candidate;
23466
- }
23467
-
23468
- // src/core/revocation-state.ts
23469
- import fs29 from "fs";
23470
- import path27 from "path";
23471
- var REVOCATION_STATE_FILENAME = ".tangyr-revocation.json";
23472
- function stateFilePath2(cacheRoot) {
23473
- return path27.join(cacheRoot, REVOCATION_STATE_FILENAME);
23474
- }
23475
- function readState2(cacheRoot) {
23476
- const filePath = stateFilePath2(cacheRoot);
23477
- let raw;
23478
- try {
23479
- raw = fs29.readFileSync(filePath, "utf8");
23480
- } catch (err) {
23481
- if (err.code === "ENOENT") {
23482
- return { state: {} };
23483
- }
23484
- return {
23485
- state: {},
23486
- warning: `Could not read ${filePath} (${err.message}); the deny-list replay guard starts from nothing for this run.`
23487
- };
23488
- }
23489
- let parsed;
23490
- try {
23491
- parsed = JSON.parse(raw);
23492
- } catch {
23493
- return {
23494
- state: {},
23495
- warning: `${filePath} is not valid JSON; the deny-list replay guard starts from nothing for this run.`
23496
- };
23497
- }
23498
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
23499
- return {
23500
- state: {},
23501
- warning: `${filePath} does not contain an object; the deny-list replay guard starts from nothing for this run.`
23502
- };
23503
- }
23504
- return { state: parsed };
23505
- }
23506
- function readRevocationSequence(cacheRoot, originUrl) {
23507
- const { state, warning } = readState2(cacheRoot);
23508
- const record = state[originUrl];
23509
- const sequence = record !== void 0 && Number.isSafeInteger(record.sequence) ? record.sequence : void 0;
23510
- return warning === void 0 ? { sequence } : { sequence, warning };
23511
- }
23512
- function writeRevocationSequence(cacheRoot, originUrl, sequence, now) {
23513
- const { state } = readState2(cacheRoot);
23514
- const existing = state[originUrl]?.sequence;
23515
- if (existing !== void 0 && existing >= sequence) {
23516
- return;
23517
- }
23518
- state[originUrl] = { sequence, seenAt: now.toISOString() };
23519
- const filePath = stateFilePath2(cacheRoot);
23520
- fs29.mkdirSync(path27.dirname(filePath), { recursive: true, mode: 448 });
23521
- const tempPath = `${filePath}.${process.pid}.tmp`;
23522
- fs29.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
23523
- `, {
23524
- mode: 384
23525
- });
23526
- fs29.renameSync(tempPath, filePath);
23527
- }
23528
- function assertSequenceNotReplayed(params) {
23529
- const { originUrl, seen, incoming } = params;
23530
- if (seen !== void 0 && incoming < seen) {
24241
+ const candidate = pointer;
24242
+ const shapeOk = candidate.type === CHANNEL_POINTER_TYPE && typeof candidate.keyId === "string" && typeof candidate.kit === "string" && candidate.kit.length > 0 && typeof candidate.channel === "string" && candidate.channel.length > 0 && typeof candidate.version === "string" && candidate.version.length > 0 && typeof candidate.signature === "string" && candidate.signature.length > 0 && Number.isSafeInteger(candidate.sequence) && candidate.sequence >= 0 && typeof candidate.issuedAt === "string" && typeof candidate.expiresAt === "string";
24243
+ if (!shapeOk) {
24244
+ throw new IntegrityError(CHANNEL_POINTER_MALFORMED);
24245
+ }
24246
+ const { signature, ...signed } = candidate;
24247
+ verifySignedPayload(
24248
+ canonicalJsonBytes(signed),
24249
+ signature,
24250
+ candidate.keyId,
24251
+ keys,
24252
+ now
24253
+ );
24254
+ if (candidate.kit !== expectedKit || candidate.channel !== expectedChannel) {
23531
24255
  throw new IntegrityError(
23532
- `Revocation deny-list from ${originUrl} carries sequence ${incoming}, behind the highest already accepted (${seen}). That is a replay of a superseded deny-list, which would silently un-revoke a kit \u2014 refusing (REQ-INT-009).`
24256
+ `Channel pointer is signed for ${candidate.kit}/${candidate.channel} but was served as ${expectedKit}/${expectedChannel}. A pointer the publisher signed for one channel is being presented as another's \u2014 refusing.`
23533
24257
  );
23534
24258
  }
24259
+ assertPathSafeComponent("version", candidate.version);
24260
+ assertFreshnessWindow(
24261
+ candidate.issuedAt,
24262
+ candidate.expiresAt,
24263
+ now,
24264
+ "An expired channel pointer is not evidence that it still names the newest version \u2014 the publisher must re-sign and republish it."
24265
+ );
24266
+ return candidate;
23535
24267
  }
23536
24268
 
23537
24269
  // src/core/materialize.ts
@@ -23579,7 +24311,6 @@ async function withBoundedRetry(operation, sleep2, logger) {
23579
24311
  );
23580
24312
  }
23581
24313
  var BUNDLE_OBJECT_PATH_PREFIX = "/v1/kits";
23582
- var DENY_LIST_OBJECT_PATH = "/v1/deny-list";
23583
24314
  async function fetchVerifiedBundle(params) {
23584
24315
  const { originUrl, reference, transport, keys, now, logger, sleep: sleep2 } = params;
23585
24316
  const credentials = resolveCredentialNonInteractive();
@@ -23633,76 +24364,6 @@ async function fetchVerifiedBundle(params) {
23633
24364
  }
23634
24365
  return parsed;
23635
24366
  }
23636
- async function assertReferenceNotRevoked(params) {
23637
- const {
23638
- originUrl,
23639
- reference,
23640
- cacheRoot,
23641
- transport,
23642
- keys,
23643
- now,
23644
- logger,
23645
- sleep: sleep2
23646
- } = params;
23647
- const credentials = resolveCredentialNonInteractive();
23648
- const denyList = await withBoundedRetry(
23649
- async () => {
23650
- const controller = new AbortController();
23651
- const response = await transport.fetchObjectStream(
23652
- originUrl,
23653
- DENY_LIST_OBJECT_PATH,
23654
- credentials,
23655
- controller.signal
23656
- );
23657
- if (response.status === 401 || response.status === 403) {
23658
- throw new AuthenticationError(
23659
- `The origin rejected the credential (HTTP ${response.status}) fetching the revocation deny-list. Set TANGYR_ACCESS_CLIENT_ID and TANGYR_ACCESS_CLIENT_SECRET, or run 'tangyr auth login'.`
23660
- );
23661
- }
23662
- if (response.status !== 200) {
23663
- throw new Error(
23664
- `Unexpected HTTP ${response.status} fetching the revocation deny-list from ${originUrl}${DENY_LIST_OBJECT_PATH}.`
23665
- );
23666
- }
23667
- const buffer = await readBoundedStream(
23668
- response.body,
23669
- MAX_TOTAL_BUNDLE_BYTES,
23670
- () => controller.abort()
23671
- );
23672
- let parsed;
23673
- try {
23674
- parsed = JSON.parse(buffer.toString("utf8"));
23675
- } catch {
23676
- throw new IntegrityError(
23677
- "Revocation deny-list response is not valid JSON \u2014 rejecting (REQ-INT-009)."
23678
- );
23679
- }
23680
- return verifyDenyList(parsed, keys, now);
23681
- },
23682
- sleep2,
23683
- logger
23684
- );
23685
- const seen = readRevocationSequence(cacheRoot, originUrl);
23686
- if (seen.warning) {
23687
- logger.warn(seen.warning);
23688
- }
23689
- assertSequenceNotReplayed({
23690
- originUrl,
23691
- seen: seen.sequence,
23692
- incoming: denyList.sequence
23693
- });
23694
- writeRevocationSequence(cacheRoot, originUrl, denyList.sequence, now);
23695
- const key = `${reference.name}@${reference.version}`;
23696
- if (denyList.entries.includes(key)) {
23697
- const entryDir = cacheEntryPath(cacheRoot, reference);
23698
- if (fs30.existsSync(entryDir)) {
23699
- fs30.rmSync(entryDir, { recursive: true, force: true });
23700
- }
23701
- throw new IntegrityError(
23702
- `"${key}" is present on the signed revocation deny-list \u2014 refusing to materialize or install; any existing cache entry has been invalidated (REQ-INT-009).`
23703
- );
23704
- }
23705
- }
23706
24367
  function parseVersionTriple(version) {
23707
24368
  const leading = version.split("-")[0];
23708
24369
  const parts = leading.split(".");
@@ -23873,16 +24534,6 @@ async function materializeRemoteKit(params) {
23873
24534
  logger,
23874
24535
  sleep: sleep2
23875
24536
  });
23876
- await assertReferenceNotRevoked({
23877
- originUrl,
23878
- reference,
23879
- cacheRoot,
23880
- transport,
23881
- keys,
23882
- now,
23883
- logger,
23884
- sleep: sleep2
23885
- });
23886
24537
  assertCliVersionCompatible(bundle.manifest.minCliVersion, CLI_VERSION);
23887
24538
  const decoded = verifyBundleFileHashes(bundle);
23888
24539
  if (decoded.has(CACHE_COMPLETION_MARKER) || decoded.has(BUNDLE_DOCUMENT_FILENAME)) {
@@ -24081,7 +24732,7 @@ async function resolveKitSource(params) {
24081
24732
  }
24082
24733
  function degradedWarmReturn() {
24083
24734
  process.stderr.write(
24084
- `Degraded: proceeding on the warm cache for "${reference.name}@${reference.version}" after a network failure during the authorization-freshness re-check \u2014 revocation and freshness were not re-checked. Run with --refresh once connectivity is restored.
24735
+ `Degraded: proceeding on the warm cache for "${reference.name}@${reference.version}" after a network failure during the authorization-freshness re-check \u2014 freshness was not re-checked. Run with --refresh once connectivity is restored.
24085
24736
  `
24086
24737
  );
24087
24738
  return {
@@ -24123,23 +24774,6 @@ async function resolveKitSource(params) {
24123
24774
  );
24124
24775
  }
24125
24776
  if (probeOutcome.outcome === "success") {
24126
- try {
24127
- await assertReferenceNotRevoked({
24128
- originUrl: config.source.url,
24129
- reference,
24130
- cacheRoot,
24131
- transport,
24132
- keys,
24133
- now,
24134
- logger,
24135
- sleep: sleep2
24136
- });
24137
- } catch (error) {
24138
- if (!(error instanceof RemoteUnavailableError)) {
24139
- throw error;
24140
- }
24141
- return degradedWarmReturn();
24142
- }
24143
24777
  writeLastAuthorizedAt(cacheRoot, config.source.url, now);
24144
24778
  const warning = formatAdvanceExpiryWarning(
24145
24779
  probeOutcome.metadata.expiresAt,
@@ -24262,7 +24896,7 @@ import path31 from "path";
24262
24896
 
24263
24897
  // src/compiler/agents.ts
24264
24898
  var TOML = __toESM(require_toml(), 1);
24265
- var import_yaml7 = __toESM(require_dist(), 1);
24899
+ var import_yaml8 = __toESM(require_dist(), 1);
24266
24900
  import path29 from "path";
24267
24901
 
24268
24902
  // src/compiler/loss-report.ts
@@ -24388,7 +25022,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
24388
25022
  if (target === "copilot") {
24389
25023
  return `${marker}
24390
25024
  ---
24391
- ${(0, import_yaml7.stringify)(targetFields).trim()}
25025
+ ${(0, import_yaml8.stringify)(targetFields).trim()}
24392
25026
  ---
24393
25027
 
24394
25028
  ${body}`;
@@ -24474,7 +25108,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
24474
25108
  );
24475
25109
  return `${marker}
24476
25110
  ---
24477
- ${(0, import_yaml7.stringify)(frontmatter).trim()}
25111
+ ${(0, import_yaml8.stringify)(frontmatter).trim()}
24478
25112
  ---
24479
25113
  `;
24480
25114
  }
@@ -24553,7 +25187,7 @@ ${body.trim()}
24553
25187
  ` : "";
24554
25188
  return `${marker}
24555
25189
  ---
24556
- ${(0, import_yaml7.stringify)(frontmatter).trim()}
25190
+ ${(0, import_yaml8.stringify)(frontmatter).trim()}
24557
25191
  ---
24558
25192
  ${bodySection}`;
24559
25193
  }
@@ -25244,7 +25878,7 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
25244
25878
 
25245
25879
  // src/compiler/rules.ts
25246
25880
  import path30 from "path";
25247
- var import_yaml8 = __toESM(require_dist(), 1);
25881
+ var import_yaml9 = __toESM(require_dist(), 1);
25248
25882
  import fs31 from "fs";
25249
25883
  function compileRules(sourceRulesDir, target, _mappings, lossReport) {
25250
25884
  if (target === "copilot") {
@@ -25323,7 +25957,7 @@ function parseRule(ruleFile) {
25323
25957
  if (endIndex === -1) {
25324
25958
  throw new Error(`${ruleFile}: frontmatter is not closed`);
25325
25959
  }
25326
- const frontmatter = (0, import_yaml8.parse)(content.slice(4, endIndex));
25960
+ const frontmatter = (0, import_yaml9.parse)(content.slice(4, endIndex));
25327
25961
  const mode = isRuleMode(frontmatter) ? frontmatter.mode : "guidance";
25328
25962
  return {
25329
25963
  mode,
@@ -25375,7 +26009,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
25375
26009
  if (endIndex !== -1) {
25376
26010
  const frontmatterStr = content.slice(4, endIndex);
25377
26011
  try {
25378
- frontmatterData = (0, import_yaml8.parse)(frontmatterStr) ?? {};
26012
+ frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
25379
26013
  } catch {
25380
26014
  frontmatterData = {};
25381
26015
  }
@@ -25422,7 +26056,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
25422
26056
  if (endIndex !== -1) {
25423
26057
  const frontmatterStr = content.slice(4, endIndex);
25424
26058
  try {
25425
- frontmatterData = (0, import_yaml8.parse)(frontmatterStr) ?? {};
26059
+ frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
25426
26060
  } catch {
25427
26061
  frontmatterData = {};
25428
26062
  }
@@ -26024,7 +26658,7 @@ import fs33 from "fs";
26024
26658
  import path33 from "path";
26025
26659
 
26026
26660
  // src/compiler/commands.ts
26027
- var import_yaml9 = __toESM(require_dist(), 1);
26661
+ var import_yaml10 = __toESM(require_dist(), 1);
26028
26662
  import path32 from "path";
26029
26663
  function compileCommandPrompt(sourceFile) {
26030
26664
  const { data, body } = parseMarkdownFrontmatter(sourceFile);
@@ -26038,7 +26672,7 @@ function compileCommandPrompt(sourceFile) {
26038
26672
  );
26039
26673
  return `${marker}
26040
26674
  ---
26041
- ${(0, import_yaml9.stringify)(fields).trim()}
26675
+ ${(0, import_yaml10.stringify)(fields).trim()}
26042
26676
  ---
26043
26677
 
26044
26678
  ${body.trimEnd()}
@@ -27614,7 +28248,7 @@ import crypto9 from "crypto";
27614
28248
  import fs36 from "fs";
27615
28249
  import os6 from "os";
27616
28250
  import path36 from "path";
27617
- var import_yaml10 = __toESM(require_dist(), 1);
28251
+ var import_yaml11 = __toESM(require_dist(), 1);
27618
28252
  function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
27619
28253
  const scope = options.scope ?? "global";
27620
28254
  const profile = resolveTargetPaths({
@@ -27834,12 +28468,12 @@ function applyProviderModelBinding(compiled, mappings) {
27834
28468
  const after = compiled.slice(fmEnd);
27835
28469
  let fields;
27836
28470
  try {
27837
- fields = (0, import_yaml10.parse)(yamlBlock) ?? {};
28471
+ fields = (0, import_yaml11.parse)(yamlBlock) ?? {};
27838
28472
  } catch {
27839
28473
  return compiled;
27840
28474
  }
27841
28475
  fields.model = modelValue;
27842
- return `${before}${(0, import_yaml10.stringify)(fields).trim()}${after}`;
28476
+ return `${before}${(0, import_yaml11.stringify)(fields).trim()}${after}`;
27843
28477
  }
27844
28478
  function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
27845
28479
  const sourceCommandsRoot = path36.join(sourceRoot, config.source.commands);
@@ -27869,7 +28503,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
27869
28503
  );
27870
28504
  const content = Object.keys(frontmatter).length > 0 ? `${marker}
27871
28505
  ---
27872
- ${(0, import_yaml10.stringify)(frontmatter).trim()}
28506
+ ${(0, import_yaml11.stringify)(frontmatter).trim()}
27873
28507
  ---
27874
28508
 
27875
28509
  ${body.trimEnd()}
@@ -28109,7 +28743,7 @@ function parseCommandFile(commandFile) {
28109
28743
  return { data: {}, body: content };
28110
28744
  }
28111
28745
  try {
28112
- const data = (0, import_yaml10.parse)(content.slice(4, endIndex)) ?? {};
28746
+ const data = (0, import_yaml11.parse)(content.slice(4, endIndex)) ?? {};
28113
28747
  const body = content.slice(endIndex + "\n---".length).replace(/^\n/u, "");
28114
28748
  return { data, body };
28115
28749
  } catch {
@@ -29797,8 +30431,8 @@ function hashString6(value) {
29797
30431
  }
29798
30432
 
29799
30433
  // src/commands/sync.ts
29800
- import fs42 from "fs";
29801
- import path43 from "path";
30434
+ import fs41 from "fs";
30435
+ import path42 from "path";
29802
30436
 
29803
30437
  // node_modules/chalk/source/vendor/ansi-styles/index.js
29804
30438
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -30296,8 +30930,8 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
30296
30930
  var source_default = chalk;
30297
30931
 
30298
30932
  // src/adapters/claude-code.ts
30299
- import fs41 from "fs";
30300
- import path42 from "path";
30933
+ import fs40 from "fs";
30934
+ import path41 from "path";
30301
30935
 
30302
30936
  // src/core/shim.ts
30303
30937
  import crypto11 from "crypto";
@@ -30312,145 +30946,6 @@ function buildAgentsMdShim(shimPath, _agentsMdPath, target) {
30312
30946
  ${SHIM_BODY}`;
30313
30947
  }
30314
30948
 
30315
- // src/compiler/hook-components.ts
30316
- var import_yaml11 = __toESM(require_dist(), 1);
30317
- import fs40 from "fs";
30318
- import path41 from "path";
30319
- function parseHookDeclaration(filePath) {
30320
- let raw;
30321
- try {
30322
- raw = fs40.readFileSync(filePath, "utf8");
30323
- } catch {
30324
- return null;
30325
- }
30326
- const fm = extractFrontmatter(raw);
30327
- if (!fm) {
30328
- return null;
30329
- }
30330
- const { name, description, events } = fm;
30331
- if (typeof name !== "string" || !name.trim()) {
30332
- return null;
30333
- }
30334
- if (typeof description !== "string" || !description.trim()) {
30335
- return null;
30336
- }
30337
- if (!Array.isArray(events) || events.length === 0) {
30338
- return null;
30339
- }
30340
- const parsedEvents = [];
30341
- for (const entry of events) {
30342
- if (!entry || typeof entry !== "object") {
30343
- return null;
30344
- }
30345
- const ev = entry;
30346
- if (typeof ev.event !== "string" || !ev.event.trim()) {
30347
- return null;
30348
- }
30349
- if (typeof ev.timeout !== "number") {
30350
- return null;
30351
- }
30352
- if (typeof ev.statusMessage !== "string" || !ev.statusMessage.trim()) {
30353
- return null;
30354
- }
30355
- const parsed = {
30356
- event: ev.event,
30357
- timeout: ev.timeout,
30358
- statusMessage: ev.statusMessage
30359
- };
30360
- if (typeof ev.matcher === "string" && ev.matcher.trim()) {
30361
- parsed.matcher = ev.matcher;
30362
- }
30363
- parsedEvents.push(parsed);
30364
- }
30365
- return {
30366
- name: name.trim(),
30367
- description: description.trim(),
30368
- events: parsedEvents
30369
- };
30370
- }
30371
- function hookCommand(name) {
30372
- return `npx tsx ~/.agents/hooks/scripts/${name}.ts`;
30373
- }
30374
- function synthesizeHooksJson(declarations) {
30375
- const hooks = {};
30376
- for (const decl of declarations) {
30377
- for (const ev of decl.events) {
30378
- if (!hooks[ev.event]) {
30379
- hooks[ev.event] = [];
30380
- }
30381
- const entry = {
30382
- hooks: [
30383
- {
30384
- type: "command",
30385
- command: hookCommand(decl.name),
30386
- timeout: ev.timeout,
30387
- statusMessage: ev.statusMessage
30388
- }
30389
- ]
30390
- };
30391
- if (ev.matcher !== void 0) {
30392
- const ordered = {
30393
- matcher: ev.matcher,
30394
- hooks: entry.hooks
30395
- };
30396
- hooks[ev.event].push(ordered);
30397
- } else {
30398
- hooks[ev.event].push(entry);
30399
- }
30400
- }
30401
- }
30402
- return { hooks };
30403
- }
30404
- function loadSourceHooks(hooksDir, hookNames) {
30405
- const hooksJsonPath = path41.join(hooksDir, "hooks.json");
30406
- if (fs40.existsSync(hooksJsonPath)) {
30407
- const raw = fs40.readFileSync(hooksJsonPath, "utf8");
30408
- return JSON.parse(raw);
30409
- }
30410
- const declarations = loadHookDeclarations(hooksDir, hookNames);
30411
- return synthesizeHooksJson(declarations);
30412
- }
30413
- function loadHookDeclarations(hooksDir, hookNames) {
30414
- let names;
30415
- if (hookNames && hookNames.length > 0) {
30416
- names = hookNames;
30417
- } else {
30418
- if (!fs40.existsSync(hooksDir) || !fs40.statSync(hooksDir).isDirectory()) {
30419
- return [];
30420
- }
30421
- names = fs40.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
30422
- }
30423
- const declarations = [];
30424
- for (const name of names) {
30425
- const filePath = path41.join(hooksDir, `${name}.md`);
30426
- const decl = parseHookDeclaration(filePath);
30427
- if (decl) {
30428
- declarations.push(decl);
30429
- }
30430
- }
30431
- return declarations;
30432
- }
30433
- function extractFrontmatter(content) {
30434
- if (!content.startsWith("---\n")) {
30435
- return null;
30436
- }
30437
- const endIndex = content.indexOf("\n---", 4);
30438
- if (endIndex === -1) {
30439
- return null;
30440
- }
30441
- const rawFm = content.slice(4, endIndex);
30442
- let parsed;
30443
- try {
30444
- parsed = (0, import_yaml11.parse)(rawFm);
30445
- } catch {
30446
- return null;
30447
- }
30448
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
30449
- return null;
30450
- }
30451
- return parsed;
30452
- }
30453
-
30454
30949
  // src/adapters/claude-code.ts
30455
30950
  function buildDirectComponents(profile) {
30456
30951
  return [
@@ -30546,7 +31041,7 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
30546
31041
  }
30547
31042
  if (!shouldSkipComponent6(options, "instructions") && manifest && scopePath) {
30548
31043
  const shimPath = profile.instructions_shim;
30549
- const agentsMdPath = path42.resolve(sourceRoot, config.source.instructions);
31044
+ const agentsMdPath = path41.resolve(sourceRoot, config.source.instructions);
30550
31045
  if (!options.dryRun) {
30551
31046
  applyClaudeCodeShimUpgrade(
30552
31047
  shimPath,
@@ -30600,13 +31095,13 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
30600
31095
  }
30601
31096
  function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
30602
31097
  if (!mappings.modelTiers.custom_provider) return;
30603
- const agentsDir = path42.join(sourceRoot, config.source.agents);
30604
- if (!fs41.existsSync(agentsDir)) return;
30605
- for (const agentFile of ts(path42.join(agentsDir, "*.md")).sort()) {
31098
+ const agentsDir = path41.join(sourceRoot, config.source.agents);
31099
+ if (!fs40.existsSync(agentsDir)) return;
31100
+ for (const agentFile of ts(path41.join(agentsDir, "*.md")).sort()) {
30606
31101
  const { data } = parseMarkdownFrontmatter(agentFile);
30607
31102
  const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
30608
31103
  if (hasProvider) {
30609
- const basename = path42.basename(agentFile);
31104
+ const basename = path41.basename(agentFile);
30610
31105
  addLoss(lossReport, "claude-code", "agents", {
30611
31106
  source: `agents/${basename}`,
30612
31107
  fields: [
@@ -30631,19 +31126,19 @@ function shouldSkipComponent6(options, component) {
30631
31126
  function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath, logger) {
30632
31127
  const expectedBodyHash = shimBodyHash();
30633
31128
  const shimContent = buildAgentsMdShim(shimPath, agentsMdPath, "claude-code");
30634
- if (!fs41.existsSync(shimPath)) {
31129
+ if (!fs40.existsSync(shimPath)) {
30635
31130
  manifest.artifacts.push({
30636
- relativePath: path42.relative(scopePath, shimPath),
31131
+ relativePath: path41.relative(scopePath, shimPath),
30637
31132
  hash: expectedBodyHash,
30638
31133
  origin: "tangyr-managed"
30639
31134
  });
30640
31135
  writeManifest(scopePath, manifest);
30641
- fs41.mkdirSync(path42.dirname(shimPath), { recursive: true });
30642
- fs41.writeFileSync(shimPath, shimContent);
31136
+ fs40.mkdirSync(path41.dirname(shimPath), { recursive: true });
31137
+ fs40.writeFileSync(shimPath, shimContent);
30643
31138
  logger?.verbose(`instructions-shim: wrote @AGENTS.md shim -> ${shimPath}`);
30644
31139
  return;
30645
31140
  }
30646
- const existing = fs41.readFileSync(shimPath, "utf8");
31141
+ const existing = fs40.readFileSync(shimPath, "utf8");
30647
31142
  const firstNonEmptyLine = existing.split("\n").find((l) => l.trim().length > 0) ?? "";
30648
31143
  const marker = extractProvenanceMarker(firstNonEmptyLine);
30649
31144
  if (marker !== null && marker.hash === expectedBodyHash) {
@@ -30654,21 +31149,21 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
30654
31149
  }
30655
31150
  backupFile(shimPath, manifest);
30656
31151
  writeManifest(scopePath, manifest);
30657
- fs41.writeFileSync(shimPath, shimContent);
31152
+ fs40.writeFileSync(shimPath, shimContent);
30658
31153
  manifest.artifacts.push({
30659
- relativePath: path42.relative(scopePath, shimPath),
31154
+ relativePath: path41.relative(scopePath, shimPath),
30660
31155
  hash: expectedBodyHash,
30661
31156
  origin: "tangyr-managed"
30662
31157
  });
30663
31158
  logger?.verbose(`instructions-shim: backed up and replaced -> ${shimPath}`);
30664
31159
  }
30665
31160
  function syncDirectComponent(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
30666
- const source = path42.resolve(
31161
+ const source = path41.resolve(
30667
31162
  sourceRoot,
30668
31163
  config.source[directComponent.sourceKey]
30669
31164
  );
30670
31165
  const destination = directComponent.destination;
30671
- if (!fs41.existsSync(source)) {
31166
+ if (!fs40.existsSync(source)) {
30672
31167
  return skippedMissingSource6(directComponent.component, source);
30673
31168
  }
30674
31169
  if (options.dryRun) {
@@ -30690,7 +31185,7 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
30690
31185
  };
30691
31186
  }
30692
31187
  if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
30693
- fs41.unlinkSync(destination);
31188
+ fs40.unlinkSync(destination);
30694
31189
  } else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
30695
31190
  return {
30696
31191
  component: directComponent.component,
@@ -30698,9 +31193,9 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
30698
31193
  path: destination
30699
31194
  };
30700
31195
  } else if (artifactClass === "managed-symlink") {
30701
- fs41.unlinkSync(destination);
31196
+ fs40.unlinkSync(destination);
30702
31197
  }
30703
- ensureDir(path42.dirname(destination));
31198
+ ensureDir(path41.dirname(destination));
30704
31199
  createRelativeSymlink(source, destination, directComponent.type, {
30705
31200
  logger,
30706
31201
  provenanceMarker: directComponent.type === "file" ? formatProvenanceMarker(
@@ -30717,8 +31212,8 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
30717
31212
  };
30718
31213
  }
30719
31214
  function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination, manifest, scopePath) {
30720
- const source = path42.resolve(sourceRoot, config.source.skills);
30721
- if (!fs41.existsSync(source)) {
31215
+ const source = path41.resolve(sourceRoot, config.source.skills);
31216
+ if (!fs40.existsSync(source)) {
30722
31217
  return [skippedMissingSource6("skills", source)];
30723
31218
  }
30724
31219
  const declaredNames = resolveKitSkillNames(sourceRoot);
@@ -30728,7 +31223,7 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
30728
31223
  if (isLegacyWholesaleSymlink) {
30729
31224
  for (const name of foreignSkillNames(source, declaredNames)) {
30730
31225
  logger.info(
30731
- `[dry-run] skills: migrate foreign skill ${path42.join(source, name)} -> ${path42.join(destination, name)}`
31226
+ `[dry-run] skills: migrate foreign skill ${path41.join(source, name)} -> ${path41.join(destination, name)}`
30732
31227
  );
30733
31228
  }
30734
31229
  logger.info(
@@ -30736,9 +31231,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
30736
31231
  );
30737
31232
  }
30738
31233
  for (const name of declaredNames ?? listSkillDirNames(source)) {
30739
- const skillDestination = path42.join(destination, name);
31234
+ const skillDestination = path41.join(destination, name);
30740
31235
  logger.info(
30741
- `[dry-run] skills: symlink ${path42.join(source, name)} -> ${skillDestination}`
31236
+ `[dry-run] skills: symlink ${path41.join(source, name)} -> ${skillDestination}`
30742
31237
  );
30743
31238
  outcomes2.push({
30744
31239
  component: "skills",
@@ -30771,9 +31266,9 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
30771
31266
  return outcomes;
30772
31267
  }
30773
31268
  function syncSingleSkill(config, sourceRoot, options, logger, source, destination, name, manifest, scopePath) {
30774
- const skillSource = path42.join(source, name);
30775
- const skillDestination = path42.join(destination, name);
30776
- if (!fs41.existsSync(skillSource)) {
31269
+ const skillSource = path41.join(source, name);
31270
+ const skillDestination = path41.join(destination, name);
31271
+ if (!fs40.existsSync(skillSource)) {
30777
31272
  return skippedMissingSource6("skills", skillSource);
30778
31273
  }
30779
31274
  const artifactClass = classifyArtifact(skillDestination, config, sourceRoot);
@@ -30785,7 +31280,7 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
30785
31280
  };
30786
31281
  }
30787
31282
  if (artifactClass === "managed-stale" && isOurStaleSymlink(skillDestination, /* @__PURE__ */ new Set([skillDestination]), config)) {
30788
- fs41.unlinkSync(skillDestination);
31283
+ fs40.unlinkSync(skillDestination);
30789
31284
  } else if (artifactClass === "unmanaged-conflict" && !handleConflict6(
30790
31285
  skillDestination,
30791
31286
  config,
@@ -30796,25 +31291,25 @@ function syncSingleSkill(config, sourceRoot, options, logger, source, destinatio
30796
31291
  )) {
30797
31292
  return { component: "skills", status: "conflict", path: skillDestination };
30798
31293
  } else if (artifactClass === "managed-symlink") {
30799
- fs41.unlinkSync(skillDestination);
31294
+ fs40.unlinkSync(skillDestination);
30800
31295
  }
30801
31296
  createRelativeSymlink(skillSource, skillDestination, "dir");
30802
31297
  return { component: "skills", status: "success", path: skillDestination };
30803
31298
  }
30804
31299
  function migrateWholesaleSkillsSymlink(source, destination, declaredNames, logger) {
30805
31300
  const foreignNames = foreignSkillNames(source, declaredNames);
30806
- fs41.unlinkSync(destination);
31301
+ fs40.unlinkSync(destination);
30807
31302
  ensureDir(destination);
30808
31303
  for (const name of foreignNames) {
30809
- const from = path42.join(source, name);
30810
- const to = path42.join(destination, name);
30811
- if (fs41.existsSync(to)) {
31304
+ const from = path41.join(source, name);
31305
+ const to = path41.join(destination, name);
31306
+ if (fs40.existsSync(to)) {
30812
31307
  logger.warn(
30813
31308
  `skills migration: ${to} already exists \u2014 skipping move of ${from} to avoid overwrite`
30814
31309
  );
30815
31310
  continue;
30816
31311
  }
30817
- fs41.renameSync(from, to);
31312
+ fs40.renameSync(from, to);
30818
31313
  logger.info(`skills migration: moved ${from} -> ${to}`);
30819
31314
  }
30820
31315
  }
@@ -30826,21 +31321,21 @@ function foreignSkillNames(source, declaredNames) {
30826
31321
  return listSkillDirNames(source).filter((name) => !declaredSet.has(name));
30827
31322
  }
30828
31323
  function listSkillDirNames(dir) {
30829
- if (!fs41.existsSync(dir)) {
31324
+ if (!fs40.existsSync(dir)) {
30830
31325
  return [];
30831
31326
  }
30832
- return fs41.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
31327
+ return fs40.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
30833
31328
  }
30834
31329
  function isSymlinkPath(filePath) {
30835
31330
  try {
30836
- return fs41.lstatSync(filePath).isSymbolicLink();
31331
+ return fs40.lstatSync(filePath).isSymbolicLink();
30837
31332
  } catch {
30838
31333
  return false;
30839
31334
  }
30840
31335
  }
30841
31336
  function syncHookScriptsBridge(config, sourceRoot, options, logger, destination, manifest, scopePath) {
30842
- const source = path42.resolve(sourceRoot, config.source.hooks);
30843
- if (!fs41.existsSync(source)) {
31337
+ const source = path41.resolve(sourceRoot, config.source.hooks);
31338
+ if (!fs40.existsSync(source)) {
30844
31339
  return skippedMissingSource6("hooks", source);
30845
31340
  }
30846
31341
  if (options.dryRun) {
@@ -30852,13 +31347,13 @@ function syncHookScriptsBridge(config, sourceRoot, options, logger, destination,
30852
31347
  return { component: "hooks", status: "skipped-current", path: destination };
30853
31348
  }
30854
31349
  if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
30855
- fs41.unlinkSync(destination);
31350
+ fs40.unlinkSync(destination);
30856
31351
  } else if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
30857
31352
  return { component: "hooks", status: "conflict", path: destination };
30858
31353
  } else if (artifactClass === "managed-symlink") {
30859
- fs41.unlinkSync(destination);
31354
+ fs40.unlinkSync(destination);
30860
31355
  }
30861
- ensureDir(path42.dirname(destination));
31356
+ ensureDir(path41.dirname(destination));
30862
31357
  createRelativeSymlink(source, destination, "dir");
30863
31358
  return { component: "hooks", status: "success", path: destination };
30864
31359
  }
@@ -30881,7 +31376,7 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
30881
31376
  destination,
30882
31377
  settings,
30883
31378
  stringifyJson3,
30884
- !fs41.existsSync(destination),
31379
+ !fs40.existsSync(destination),
30885
31380
  logger
30886
31381
  );
30887
31382
  return {
@@ -30891,8 +31386,8 @@ function syncHooks6(config, sourceRoot, options, logger, destination) {
30891
31386
  };
30892
31387
  }
30893
31388
  function syncMcp6(config, sourceRoot, options, logger, destination) {
30894
- const source = path42.resolve(sourceRoot, config.source.mcp);
30895
- if (!fs41.existsSync(source)) {
31389
+ const source = path41.resolve(sourceRoot, config.source.mcp);
31390
+ if (!fs40.existsSync(source)) {
30896
31391
  return skippedMissingSource6("mcp", source);
30897
31392
  }
30898
31393
  if (options.dryRun) {
@@ -30917,7 +31412,7 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
30917
31412
  destination,
30918
31413
  hostConfig,
30919
31414
  stringifyJson3,
30920
- !fs41.existsSync(destination),
31415
+ !fs40.existsSync(destination),
30921
31416
  logger
30922
31417
  );
30923
31418
  return {
@@ -30927,8 +31422,8 @@ function syncMcp6(config, sourceRoot, options, logger, destination) {
30927
31422
  };
30928
31423
  }
30929
31424
  function syncSettings2(config, sourceRoot, options, logger, destination) {
30930
- const source = path42.resolve(sourceRoot, config.source.settings);
30931
- if (!fs41.existsSync(source)) {
31425
+ const source = path41.resolve(sourceRoot, config.source.settings);
31426
+ if (!fs40.existsSync(source)) {
30932
31427
  return skippedMissingSource6("settings", source);
30933
31428
  }
30934
31429
  if (options.dryRun) {
@@ -30946,7 +31441,7 @@ function syncSettings2(config, sourceRoot, options, logger, destination) {
30946
31441
  destination,
30947
31442
  settings,
30948
31443
  stringifyJson3,
30949
- !fs41.existsSync(destination),
31444
+ !fs40.existsSync(destination),
30950
31445
  logger
30951
31446
  );
30952
31447
  return {
@@ -30971,11 +31466,11 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
30971
31466
  backupFile(destination, manifest);
30972
31467
  writeManifest(scopePath, manifest);
30973
31468
  } else {
30974
- fs41.renameSync(destination, `${destination}.bak.${Date.now()}`);
31469
+ fs40.renameSync(destination, `${destination}.bak.${Date.now()}`);
30975
31470
  }
30976
31471
  return true;
30977
31472
  }
30978
- fs41.rmSync(destination, { recursive: true, force: true });
31473
+ fs40.rmSync(destination, { recursive: true, force: true });
30979
31474
  return true;
30980
31475
  }
30981
31476
  function skippedMissingSource6(component, source) {
@@ -30987,16 +31482,16 @@ function skippedMissingSource6(component, source) {
30987
31482
  }
30988
31483
  function isSymlinkTo6(linkPath, source) {
30989
31484
  try {
30990
- return fs41.realpathSync(linkPath) === fs41.realpathSync(source);
31485
+ return fs40.realpathSync(linkPath) === fs40.realpathSync(source);
30991
31486
  } catch {
30992
31487
  return false;
30993
31488
  }
30994
31489
  }
30995
31490
  function readJsonObject4(filePath) {
30996
- if (!fs41.existsSync(filePath)) {
31491
+ if (!fs40.existsSync(filePath)) {
30997
31492
  return {};
30998
31493
  }
30999
- const parsed = JSON.parse(fs41.readFileSync(filePath, "utf8"));
31494
+ const parsed = JSON.parse(fs40.readFileSync(filePath, "utf8"));
31000
31495
  return isRecord5(parsed) ? parsed : {};
31001
31496
  }
31002
31497
  function markManaged(value) {
@@ -31262,7 +31757,7 @@ function writeLossReport(filePath, report) {
31262
31757
  if (!filePath) {
31263
31758
  return;
31264
31759
  }
31265
- fs42.writeFileSync(filePath, `${JSON.stringify(report, null, 2)}
31760
+ fs41.writeFileSync(filePath, `${JSON.stringify(report, null, 2)}
31266
31761
  `);
31267
31762
  }
31268
31763
  function prepareKitManifest(scope, projectRoot, kitInfo) {
@@ -31303,8 +31798,8 @@ function updateManifest(kitInfo, kitSync) {
31303
31798
  writeManifest(kitSync.scopePath, kitSync.manifest);
31304
31799
  }
31305
31800
  function resolveKitFilePath(kitPath, relativePath) {
31306
- const fullPath = path43.join(kitPath, relativePath);
31307
- return fs42.existsSync(fullPath) ? fullPath : null;
31801
+ const fullPath = path42.join(kitPath, relativePath);
31802
+ return fs41.existsSync(fullPath) ? fullPath : null;
31308
31803
  }
31309
31804
  function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
31310
31805
  if (removedSourcePaths.length === 0 || !mappings) {
@@ -31365,9 +31860,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
31365
31860
  }
31366
31861
  if (relativePath.startsWith("agents/")) {
31367
31862
  removeManagedCompiledArtifact2(
31368
- path43.join(
31863
+ path42.join(
31369
31864
  resolveTargetPath(paths.agents ?? ""),
31370
- `${path43.parse(relativePath).name}.agent.md`
31865
+ `${path42.parse(relativePath).name}.agent.md`
31371
31866
  ),
31372
31867
  "copilot",
31373
31868
  relativePath,
@@ -31377,9 +31872,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
31377
31872
  }
31378
31873
  if (relativePath.startsWith("commands/")) {
31379
31874
  removeManagedCompiledArtifact2(
31380
- path43.join(
31875
+ path42.join(
31381
31876
  resolveTargetPath(paths.prompts ?? ""),
31382
- `${path43.parse(relativePath).name}.prompt.md`
31877
+ `${path42.parse(relativePath).name}.prompt.md`
31383
31878
  ),
31384
31879
  "copilot",
31385
31880
  relativePath,
@@ -31389,7 +31884,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
31389
31884
  }
31390
31885
  if (relativePath.endsWith("hooks.json")) {
31391
31886
  removeManagedCompiledArtifact2(
31392
- path43.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
31887
+ path42.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
31393
31888
  "copilot",
31394
31889
  relativePath,
31395
31890
  logger
@@ -31419,9 +31914,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
31419
31914
  }
31420
31915
  if (relativePath.startsWith("agents/")) {
31421
31916
  removeManagedCompiledArtifact2(
31422
- path43.join(
31917
+ path42.join(
31423
31918
  resolveTargetPath(paths.agents ?? ""),
31424
- `${path43.parse(relativePath).name}.toml`
31919
+ `${path42.parse(relativePath).name}.toml`
31425
31920
  ),
31426
31921
  "codex",
31427
31922
  relativePath,
@@ -31431,9 +31926,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
31431
31926
  }
31432
31927
  if (relativePath.startsWith("rules/")) {
31433
31928
  removeManagedCompiledArtifact2(
31434
- path43.join(
31929
+ path42.join(
31435
31930
  resolveTargetPath(paths.rules ?? ""),
31436
- `${path43.parse(relativePath).name}.rules`
31931
+ `${path42.parse(relativePath).name}.rules`
31437
31932
  ),
31438
31933
  "codex",
31439
31934
  relativePath,
@@ -31472,9 +31967,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
31472
31967
  }
31473
31968
  if (relativePath.startsWith("agents/")) {
31474
31969
  removeManagedCompiledArtifact2(
31475
- path43.join(
31970
+ path42.join(
31476
31971
  resolveTargetPath(paths.agents ?? ""),
31477
- `${path43.parse(relativePath).name}.md`
31972
+ `${path42.parse(relativePath).name}.md`
31478
31973
  ),
31479
31974
  "opencode",
31480
31975
  relativePath,
@@ -31484,9 +31979,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
31484
31979
  }
31485
31980
  if (relativePath.startsWith("commands/")) {
31486
31981
  removeManagedCompiledArtifact2(
31487
- path43.join(
31982
+ path42.join(
31488
31983
  resolveTargetPath(paths.commands ?? ""),
31489
- `${path43.parse(relativePath).name}.md`
31984
+ `${path42.parse(relativePath).name}.md`
31490
31985
  ),
31491
31986
  "opencode",
31492
31987
  relativePath,
@@ -31518,9 +32013,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
31518
32013
  }
31519
32014
  if (relativePath.startsWith("agents/")) {
31520
32015
  removeManagedCompiledArtifact2(
31521
- path43.join(
32016
+ path42.join(
31522
32017
  resolveTargetPath(paths.agents ?? ""),
31523
- `${path43.parse(relativePath).name}.md`
32018
+ `${path42.parse(relativePath).name}.md`
31524
32019
  ),
31525
32020
  "cursor",
31526
32021
  relativePath,
@@ -31530,9 +32025,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
31530
32025
  }
31531
32026
  if (relativePath.startsWith("rules/")) {
31532
32027
  removeManagedCompiledArtifact2(
31533
- path43.join(
32028
+ path42.join(
31534
32029
  resolveTargetPath(paths.rules ?? ""),
31535
- `${path43.parse(relativePath).name}.mdc`
32030
+ `${path42.parse(relativePath).name}.mdc`
31536
32031
  ),
31537
32032
  "cursor",
31538
32033
  relativePath,
@@ -31542,9 +32037,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
31542
32037
  }
31543
32038
  if (relativePath.startsWith("commands/")) {
31544
32039
  removeManagedCompiledArtifact2(
31545
- path43.join(
32040
+ path42.join(
31546
32041
  resolveTargetPath(paths.skills ?? ""),
31547
- path43.parse(relativePath).name,
32042
+ path42.parse(relativePath).name,
31548
32043
  "SKILL.md"
31549
32044
  ),
31550
32045
  "cursor",
@@ -31588,9 +32083,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
31588
32083
  }
31589
32084
  if (relativePath.startsWith("rules/")) {
31590
32085
  removeManagedCompiledArtifact2(
31591
- path43.join(
32086
+ path42.join(
31592
32087
  resolveTargetPath(paths.rules ?? ""),
31593
- `${path43.parse(relativePath).name}.md`
32088
+ `${path42.parse(relativePath).name}.md`
31594
32089
  ),
31595
32090
  "cline",
31596
32091
  relativePath,
@@ -31600,9 +32095,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
31600
32095
  }
31601
32096
  if (relativePath.startsWith("commands/")) {
31602
32097
  removeManagedCompiledArtifact2(
31603
- path43.join(
32098
+ path42.join(
31604
32099
  resolveTargetPath(paths.workflows ?? ""),
31605
- path43.basename(relativePath)
32100
+ path42.basename(relativePath)
31606
32101
  ),
31607
32102
  "cline",
31608
32103
  relativePath,
@@ -31620,17 +32115,17 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
31620
32115
  }
31621
32116
  }
31622
32117
  function removeManagedCompiledArtifact2(artifactPath, expectedTarget, expectedSource, logger) {
31623
- if (!fs42.existsSync(artifactPath)) {
32118
+ if (!fs41.existsSync(artifactPath)) {
31624
32119
  return;
31625
32120
  }
31626
- if (!fs42.statSync(artifactPath).isFile()) {
32121
+ if (!fs41.statSync(artifactPath).isFile()) {
31627
32122
  return;
31628
32123
  }
31629
- const marker = extractProvenanceMarker(fs42.readFileSync(artifactPath, "utf8"));
32124
+ const marker = extractProvenanceMarker(fs41.readFileSync(artifactPath, "utf8"));
31630
32125
  if (marker?.source !== expectedSource || marker.target !== expectedTarget) {
31631
32126
  return;
31632
32127
  }
31633
- fs42.rmSync(artifactPath, { force: true });
32128
+ fs41.rmSync(artifactPath, { force: true });
31634
32129
  logger.verbose(` removed stale target artifact: ${artifactPath}`);
31635
32130
  }
31636
32131
  function removeManagedCopilotMcpArtifact2(artifactPath, expectedSource, logger) {
@@ -31661,10 +32156,10 @@ function removeManagedCodexHooksArtifact2(artifactPath, expectedSource, logger)
31661
32156
  logger.verbose(` removed stale target artifact: ${artifactPath}`);
31662
32157
  }
31663
32158
  function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
31664
- if (!fs42.existsSync(artifactPath)) {
32159
+ if (!fs41.existsSync(artifactPath)) {
31665
32160
  return;
31666
32161
  }
31667
- const content = fs42.readFileSync(artifactPath, "utf8");
32162
+ const content = fs41.readFileSync(artifactPath, "utf8");
31668
32163
  const startMarker = "# tangyr: managed mcp start";
31669
32164
  const endMarker = "# tangyr: managed mcp end";
31670
32165
  const startIndex = content.indexOf(startMarker);
@@ -31681,19 +32176,19 @@ function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
31681
32176
  const after = content.slice(endIndex + endMarker.length).trimStart();
31682
32177
  const cleaned = [before, after].filter((entry) => entry.length > 0).join("\n\n");
31683
32178
  if (cleaned.length === 0) {
31684
- fs42.rmSync(artifactPath, { force: true });
32179
+ fs41.rmSync(artifactPath, { force: true });
31685
32180
  } else {
31686
- fs42.writeFileSync(artifactPath, `${cleaned}
32181
+ fs41.writeFileSync(artifactPath, `${cleaned}
31687
32182
  `);
31688
32183
  }
31689
32184
  logger.verbose(` removed stale target artifact: ${artifactPath}`);
31690
32185
  }
31691
32186
  function readJsonObject5(filePath) {
31692
- if (!fs42.existsSync(filePath)) {
32187
+ if (!fs41.existsSync(filePath)) {
31693
32188
  return null;
31694
32189
  }
31695
32190
  try {
31696
- const parsed = JSON.parse(fs42.readFileSync(filePath, "utf8"));
32191
+ const parsed = JSON.parse(fs41.readFileSync(filePath, "utf8"));
31697
32192
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
31698
32193
  } catch {
31699
32194
  return null;
@@ -31707,10 +32202,10 @@ function readJsonMetadata(value) {
31707
32202
  }
31708
32203
  function writeJsonOrRemove2(filePath, parsed) {
31709
32204
  if (isEmptyJsonValue2(parsed)) {
31710
- fs42.rmSync(filePath, { force: true });
32205
+ fs41.rmSync(filePath, { force: true });
31711
32206
  return;
31712
32207
  }
31713
- fs42.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
32208
+ fs41.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
31714
32209
  `);
31715
32210
  }
31716
32211
  function isEmptyJsonValue2(value) {
@@ -31770,8 +32265,8 @@ function removeManagedHookEntries(value, expectedSource) {
31770
32265
  }
31771
32266
 
31772
32267
  // src/commands/validate.ts
31773
- import fs43 from "fs";
31774
- import path44 from "path";
32268
+ import fs42 from "fs";
32269
+ import path43 from "path";
31775
32270
  var SUPPORTED_KIT_FORMATS2 = [1];
31776
32271
  var SUPPORTED_DISCIPLINE_VERSIONS = [
31777
32272
  "0.14.0",
@@ -31855,8 +32350,8 @@ function checkKitFormatSupported(kit) {
31855
32350
  }
31856
32351
  function checkEntrypointExists(kit) {
31857
32352
  const entrypoint = "CLAUDE.md";
31858
- const entrypointPath = path44.join(kit.path, entrypoint);
31859
- if (!fs43.existsSync(entrypointPath)) {
32353
+ const entrypointPath = path43.join(kit.path, entrypoint);
32354
+ if (!fs42.existsSync(entrypointPath)) {
31860
32355
  return {
31861
32356
  code: "entrypoint-missing",
31862
32357
  location: entrypoint,
@@ -31913,9 +32408,9 @@ function checkComponentFrontmatter(kit) {
31913
32408
  const missingSet = new Set(kit.components[cat].missing);
31914
32409
  for (const name of kit.components[cat].declared) {
31915
32410
  if (missingSet.has(name)) continue;
31916
- const filePath = cat === "skills" ? path44.join(kit.path, cat, name, "SKILL.md") : path44.join(kit.path, cat, `${name}.md`);
31917
- if (!fs43.existsSync(filePath)) continue;
31918
- const relPath = path44.relative(kit.path, filePath);
32411
+ const filePath = cat === "skills" ? path43.join(kit.path, cat, name, "SKILL.md") : path43.join(kit.path, cat, `${name}.md`);
32412
+ if (!fs42.existsSync(filePath)) continue;
32413
+ const relPath = path43.relative(kit.path, filePath);
31919
32414
  try {
31920
32415
  const { data } = parseMarkdownFrontmatter(filePath);
31921
32416
  for (const field of requiredFields) {
@@ -31940,10 +32435,10 @@ function checkComponentFrontmatter(kit) {
31940
32435
  }
31941
32436
  function checkReservedRootNames(kit) {
31942
32437
  const violations = [];
31943
- if (!fs43.existsSync(kit.path) || !fs43.statSync(kit.path).isDirectory()) {
32438
+ if (!fs42.existsSync(kit.path) || !fs42.statSync(kit.path).isDirectory()) {
31944
32439
  return violations;
31945
32440
  }
31946
- const entries = fs43.readdirSync(kit.path, { withFileTypes: true });
32441
+ const entries = fs42.readdirSync(kit.path, { withFileTypes: true });
31947
32442
  for (const entry of entries) {
31948
32443
  if (RESERVED_ROOT_NAMES.includes(entry.name)) {
31949
32444
  violations.push({
@@ -31960,8 +32455,8 @@ function checkHumanOnlyCommandInvocation(kit) {
31960
32455
  const missingSet = new Set(kit.components.commands.missing);
31961
32456
  for (const name of kit.components.commands.declared) {
31962
32457
  if (missingSet.has(name)) continue;
31963
- const filePath = path44.join(kit.path, "commands", `${name}.md`);
31964
- if (!fs43.existsSync(filePath)) continue;
32458
+ const filePath = path43.join(kit.path, "commands", `${name}.md`);
32459
+ if (!fs42.existsSync(filePath)) continue;
31965
32460
  let data;
31966
32461
  try {
31967
32462
  ({ data } = parseMarkdownFrontmatter(filePath));
@@ -31974,7 +32469,7 @@ function checkHumanOnlyCommandInvocation(kit) {
31974
32469
  if (!barred) {
31975
32470
  violations.push({
31976
32471
  code: "command-human-only-model-invocable",
31977
- location: path44.relative(kit.path, filePath),
32472
+ location: path43.relative(kit.path, filePath),
31978
32473
  message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
31979
32474
  });
31980
32475
  }
@@ -31983,8 +32478,8 @@ function checkHumanOnlyCommandInvocation(kit) {
31983
32478
  }
31984
32479
 
31985
32480
  // src/commands/verify.ts
31986
- import fs44 from "fs";
31987
- import path45 from "path";
32481
+ import fs43 from "fs";
32482
+ import path44 from "path";
31988
32483
  function runVerifyCommand(options, logger) {
31989
32484
  const { config, configDir, sourceRoot, kitInfo } = resolveRuntime(
31990
32485
  options,
@@ -32075,8 +32570,8 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
32075
32570
  if (!slotPath) {
32076
32571
  continue;
32077
32572
  }
32078
- const fullPath = subPath ? path45.join(slotPath, subPath) : slotPath;
32079
- if (!fs44.existsSync(fullPath)) {
32573
+ const fullPath = subPath ? path44.join(slotPath, subPath) : slotPath;
32574
+ if (!fs43.existsSync(fullPath)) {
32080
32575
  failures.push(
32081
32576
  `claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`
32082
32577
  );