@alessandroraffa/tangyr 0.16.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 +1425 -721
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -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)) {
22694
- return true;
22695
- }
22696
- } catch (error) {
22697
- 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))) {
23534
+ if (readDirectory(extensionDirectory).some(matchesExtension)) {
22708
23535
  return true;
22709
23536
  }
22710
23537
  } catch (error) {
22711
23538
  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: {
@@ -23138,15 +23981,15 @@ function toConflictPolicy2(value) {
23138
23981
  }
23139
23982
 
23140
23983
  // src/commands/install.ts
23141
- import fs36 from "fs";
23142
- import path36 from "path";
23984
+ import fs37 from "fs";
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;
@@ -23224,8 +24067,8 @@ var CHANNEL_POINTER_TYPE = "tangyr.channel-pointer.v1";
23224
24067
  var DEFAULT_CHANNEL = "stable";
23225
24068
 
23226
24069
  // src/core/materialize.ts
23227
- import fs29 from "fs";
23228
- import path27 from "path";
24070
+ import fs30 from "fs";
24071
+ import path28 from "path";
23229
24072
 
23230
24073
  // src/core/integrity.ts
23231
24074
  import crypto3 from "crypto";
@@ -23561,7 +24404,7 @@ function assertFileWithinCeiling(entryPath, byteLength) {
23561
24404
  }
23562
24405
  var WINDOWS_DRIVE_ABSOLUTE = /^[a-zA-Z]:[\\/]/u;
23563
24406
  function sanitizeBundleFilePath(entryPath, stagingDir) {
23564
- if (path27.isAbsolute(entryPath) || WINDOWS_DRIVE_ABSOLUTE.test(entryPath)) {
24407
+ if (path28.isAbsolute(entryPath) || WINDOWS_DRIVE_ABSOLUTE.test(entryPath)) {
23565
24408
  throw new IntegrityError(
23566
24409
  `Bundle file path "${entryPath}" is absolute \u2014 every file inside a bundle must use a relative path (REQ-INT-004).`
23567
24410
  );
@@ -23577,13 +24420,13 @@ function sanitizeBundleFilePath(entryPath, stagingDir) {
23577
24420
  `Bundle file path "${entryPath}" contains a ".." segment \u2014 directory traversal is rejected (REQ-INT-004).`
23578
24421
  );
23579
24422
  }
23580
- const resolved = path27.resolve(stagingDir, entryPath);
24423
+ const resolved = path28.resolve(stagingDir, entryPath);
23581
24424
  if (resolved === stagingDir) {
23582
24425
  throw new IntegrityError(
23583
24426
  `Bundle file path "${entryPath}" resolves to the staging directory itself \u2014 every entry must be a file inside it (REQ-INT-004).`
23584
24427
  );
23585
24428
  }
23586
- if (!resolved.startsWith(stagingDir + path27.sep)) {
24429
+ if (!resolved.startsWith(stagingDir + path28.sep)) {
23587
24430
  throw new IntegrityError(
23588
24431
  `Bundle file path "${entryPath}" escapes the staging directory \u2014 refusing to write (REQ-INT-004).`
23589
24432
  );
@@ -23635,10 +24478,10 @@ function verifyBundleFileHashes(bundle) {
23635
24478
  function writeStagedFiles(stagingDir, decoded) {
23636
24479
  for (const [rawPath, bytes] of decoded) {
23637
24480
  const target = sanitizeBundleFilePath(rawPath, stagingDir);
23638
- fs29.mkdirSync(path27.dirname(target), { recursive: true, mode: 448 });
24481
+ fs30.mkdirSync(path28.dirname(target), { recursive: true, mode: 448 });
23639
24482
  let existingStat;
23640
24483
  try {
23641
- existingStat = fs29.lstatSync(target);
24484
+ existingStat = fs30.lstatSync(target);
23642
24485
  } catch (error) {
23643
24486
  if (error.code !== "ENOENT") {
23644
24487
  throw error;
@@ -23649,7 +24492,7 @@ function writeStagedFiles(stagingDir, decoded) {
23649
24492
  `Refusing to write "${rawPath}" \u2014 a symbolic link already exists at the target path.`
23650
24493
  );
23651
24494
  }
23652
- fs29.writeFileSync(target, bytes, { mode: 384, flag: "wx" });
24495
+ fs30.writeFileSync(target, bytes, { mode: 384, flag: "wx" });
23653
24496
  }
23654
24497
  }
23655
24498
  function verifyWarmCacheEntry(entryDir, reference, keys, now) {
@@ -23705,14 +24548,14 @@ async function materializeRemoteKit(params) {
23705
24548
  writeStagedFiles(stagingDir, decoded);
23706
24549
  writeBundleDocument(stagingDir, bundle);
23707
24550
  writeCompletionMarker(stagingDir, reference);
23708
- if (replace && fs29.existsSync(entryDir)) {
23709
- fs29.rmSync(entryDir, { recursive: true, force: true });
24551
+ if (replace && fs30.existsSync(entryDir)) {
24552
+ fs30.rmSync(entryDir, { recursive: true, force: true });
23710
24553
  }
23711
24554
  publishCacheEntry(stagingDir, entryDir);
23712
24555
  return entryDir;
23713
24556
  } catch (error) {
23714
24557
  if (stagingDir !== void 0) {
23715
- fs29.rmSync(stagingDir, { recursive: true, force: true });
24558
+ fs30.rmSync(stagingDir, { recursive: true, force: true });
23716
24559
  }
23717
24560
  throw error;
23718
24561
  }
@@ -24048,13 +24891,13 @@ function sleep(ms2) {
24048
24891
  // src/adapters/codex.ts
24049
24892
  var TOML3 = __toESM(require_toml(), 1);
24050
24893
  import crypto5 from "crypto";
24051
- import fs31 from "fs";
24052
- import path30 from "path";
24894
+ import fs32 from "fs";
24895
+ import path31 from "path";
24053
24896
 
24054
24897
  // src/compiler/agents.ts
24055
24898
  var TOML = __toESM(require_toml(), 1);
24056
- var import_yaml7 = __toESM(require_dist(), 1);
24057
- import path28 from "path";
24899
+ var import_yaml8 = __toESM(require_dist(), 1);
24900
+ import path29 from "path";
24058
24901
 
24059
24902
  // src/compiler/loss-report.ts
24060
24903
  function createLossReport() {
@@ -24118,7 +24961,7 @@ var copilotToolAliasesByClass = {
24118
24961
  };
24119
24962
  function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
24120
24963
  const { data, body } = parseMarkdownFrontmatter(sourceFile);
24121
- const relativeSource = `agents/${path28.basename(sourceFile)}`;
24964
+ const relativeSource = `agents/${path29.basename(sourceFile)}`;
24122
24965
  if (target === "opencode") {
24123
24966
  return compileOpenCodeAgent(
24124
24967
  sourceFile,
@@ -24159,7 +25002,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
24159
25002
  mappings,
24160
25003
  lossReport
24161
25004
  );
24162
- const overlayKey = `agents/${path28.basename(sourceFile, ".md")}.${target}.yaml`;
25005
+ const overlayKey = `agents/${path29.basename(sourceFile, ".md")}.${target}.yaml`;
24163
25006
  const targetFields = {
24164
25007
  ...translated.fields,
24165
25008
  ...extensions[overlayKey] ?? {}
@@ -24179,7 +25022,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
24179
25022
  if (target === "copilot") {
24180
25023
  return `${marker}
24181
25024
  ---
24182
- ${(0, import_yaml7.stringify)(targetFields).trim()}
25025
+ ${(0, import_yaml8.stringify)(targetFields).trim()}
24183
25026
  ---
24184
25027
 
24185
25028
  ${body}`;
@@ -24193,7 +25036,7 @@ ${TOML.stringify({
24193
25036
  function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport) {
24194
25037
  if (typeof data.description !== "string" || data.description.trim() === "") {
24195
25038
  throw new Error(
24196
- `${path28.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
25039
+ `${path29.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
24197
25040
  );
24198
25041
  }
24199
25042
  const frontmatter = {
@@ -24247,7 +25090,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
24247
25090
  "permission",
24248
25091
  "permission-coarsening"
24249
25092
  ),
24250
- detail: `${path28.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
25093
+ detail: `${path29.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
24251
25094
  }
24252
25095
  ]
24253
25096
  });
@@ -24265,14 +25108,14 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
24265
25108
  );
24266
25109
  return `${marker}
24267
25110
  ---
24268
- ${(0, import_yaml7.stringify)(frontmatter).trim()}
25111
+ ${(0, import_yaml8.stringify)(frontmatter).trim()}
24269
25112
  ---
24270
25113
  `;
24271
25114
  }
24272
25115
  function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport) {
24273
25116
  if (typeof data.description !== "string" || data.description.trim() === "") {
24274
25117
  throw new Error(
24275
- `${path28.basename(sourceFile)}: Cursor agent requires a non-empty description field`
25118
+ `${path29.basename(sourceFile)}: Cursor agent requires a non-empty description field`
24276
25119
  );
24277
25120
  }
24278
25121
  const frontmatter = {
@@ -24309,7 +25152,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
24309
25152
  "permission",
24310
25153
  "permission-coarsening"
24311
25154
  ),
24312
- detail: `${path28.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
25155
+ detail: `${path29.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
24313
25156
  }
24314
25157
  ]
24315
25158
  });
@@ -24328,7 +25171,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
24328
25171
  "provider",
24329
25172
  "provider-not-representable"
24330
25173
  ),
24331
- detail: `${path28.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
25174
+ detail: `${path29.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
24332
25175
  }
24333
25176
  ]
24334
25177
  });
@@ -24344,7 +25187,7 @@ ${body.trim()}
24344
25187
  ` : "";
24345
25188
  return `${marker}
24346
25189
  ---
24347
- ${(0, import_yaml7.stringify)(frontmatter).trim()}
25190
+ ${(0, import_yaml8.stringify)(frontmatter).trim()}
24348
25191
  ---
24349
25192
  ${bodySection}`;
24350
25193
  }
@@ -24360,7 +25203,7 @@ function compileClineAgent(sourceFile, _data, _body, relativeSource, lossReport)
24360
25203
  "persona",
24361
25204
  "persona-not-representable"
24362
25205
  ),
24363
- detail: `${path28.basename(sourceFile)}: Cline has no committable per-agent persona file for the VSCode extension target; configure the agent through Cline Settings \u2192 Agent.`
25206
+ detail: `${path29.basename(sourceFile)}: Cline has no committable per-agent persona file for the VSCode extension target; configure the agent through Cline Settings \u2192 Agent.`
24364
25207
  }
24365
25208
  ]
24366
25209
  });
@@ -24408,7 +25251,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
24408
25251
  field,
24409
25252
  "model-not-representable"
24410
25253
  ),
24411
- detail: `${path28.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
25254
+ detail: `${path29.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
24412
25255
  });
24413
25256
  return;
24414
25257
  }
@@ -24426,9 +25269,9 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
24426
25269
  lossReport,
24427
25270
  target,
24428
25271
  "agents",
24429
- `agents/${path28.basename(sourceFile)}`,
25272
+ `agents/${path29.basename(sourceFile)}`,
24430
25273
  "info",
24431
- `${path28.basename(sourceFile)}: ${field} is delivered through another managed surface.`
25274
+ `${path29.basename(sourceFile)}: ${field} is delivered through another managed surface.`
24432
25275
  );
24433
25276
  return;
24434
25277
  }
@@ -24437,7 +25280,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
24437
25280
  field,
24438
25281
  action: entryType,
24439
25282
  severity: resolveLossSeverity("agent-field", field, entryType),
24440
- detail: `${path28.basename(sourceFile)}: ${field} has no emitted field for this target.`
25283
+ detail: `${path29.basename(sourceFile)}: ${field} has no emitted field for this target.`
24441
25284
  });
24442
25285
  }
24443
25286
  function mapToolsToCapabilities(value, mappings) {
@@ -25034,9 +25877,9 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
25034
25877
  }
25035
25878
 
25036
25879
  // src/compiler/rules.ts
25037
- import path29 from "path";
25038
- var import_yaml8 = __toESM(require_dist(), 1);
25039
- import fs30 from "fs";
25880
+ import path30 from "path";
25881
+ var import_yaml9 = __toESM(require_dist(), 1);
25882
+ import fs31 from "fs";
25040
25883
  function compileRules(sourceRulesDir, target, _mappings, lossReport) {
25041
25884
  if (target === "copilot") {
25042
25885
  addLoss(lossReport, "copilot", "rules", {
@@ -25073,13 +25916,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
25073
25916
  }
25074
25917
  const appendixParts = [];
25075
25918
  const dotRulesFiles = [];
25076
- for (const ruleFile of ts(path29.join(sourceRulesDir, "*.md")).sort()) {
25919
+ for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
25077
25920
  const parsed = parseRule(ruleFile);
25078
- const name = path29.basename(ruleFile, ".md");
25921
+ const name = path30.basename(ruleFile, ".md");
25079
25922
  if (parsed.mode === "exec-policy") {
25080
25923
  dotRulesFiles.push({
25081
25924
  name: `${name}.rules`,
25082
- content: `${formatProvenanceMarker("toml", `rules/${path29.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
25925
+ content: `${formatProvenanceMarker("toml", `rules/${path30.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
25083
25926
  ${parsed.body}`
25084
25927
  });
25085
25928
  continue;
@@ -25088,7 +25931,7 @@ ${parsed.body}`
25088
25931
 
25089
25932
  ${parsed.body.trim()}`);
25090
25933
  addLoss(lossReport, "codex", "rules", {
25091
- source: `rules/${path29.basename(ruleFile)}`,
25934
+ source: `rules/${path30.basename(ruleFile)}`,
25092
25935
  fields: [
25093
25936
  {
25094
25937
  field: "mode",
@@ -25098,7 +25941,7 @@ ${parsed.body.trim()}`);
25098
25941
  "mode",
25099
25942
  "rule-as-instruction"
25100
25943
  ),
25101
- detail: `${path29.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
25944
+ detail: `${path30.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
25102
25945
  }
25103
25946
  ]
25104
25947
  });
@@ -25106,7 +25949,7 @@ ${parsed.body.trim()}`);
25106
25949
  return { agentsAppendix: appendixParts.join("\n\n"), dotRulesFiles };
25107
25950
  }
25108
25951
  function parseRule(ruleFile) {
25109
- const content = fs30.readFileSync(ruleFile, "utf8");
25952
+ const content = fs31.readFileSync(ruleFile, "utf8");
25110
25953
  if (!content.startsWith("---\n")) {
25111
25954
  return { mode: "guidance", body: content };
25112
25955
  }
@@ -25114,7 +25957,7 @@ function parseRule(ruleFile) {
25114
25957
  if (endIndex === -1) {
25115
25958
  throw new Error(`${ruleFile}: frontmatter is not closed`);
25116
25959
  }
25117
- const frontmatter = (0, import_yaml8.parse)(content.slice(4, endIndex));
25960
+ const frontmatter = (0, import_yaml9.parse)(content.slice(4, endIndex));
25118
25961
  const mode = isRuleMode(frontmatter) ? frontmatter.mode : "guidance";
25119
25962
  return {
25120
25963
  mode,
@@ -25130,14 +25973,14 @@ function isRuleMode(value) {
25130
25973
  }
25131
25974
  function compileOpenCodeRules(sourceRulesDir, lossReport) {
25132
25975
  const appendixParts = [];
25133
- for (const ruleFile of ts(path29.join(sourceRulesDir, "*.md")).sort()) {
25976
+ for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
25134
25977
  const parsed = parseRule(ruleFile);
25135
- const name = path29.basename(ruleFile, ".md");
25978
+ const name = path30.basename(ruleFile, ".md");
25136
25979
  appendixParts.push(`## ${name}
25137
25980
 
25138
25981
  ${parsed.body.trim()}`);
25139
25982
  addLoss(lossReport, "opencode", "rules", {
25140
- source: `rules/${path29.basename(ruleFile)}`,
25983
+ source: `rules/${path30.basename(ruleFile)}`,
25141
25984
  fields: [
25142
25985
  {
25143
25986
  field: "rule",
@@ -25147,7 +25990,7 @@ ${parsed.body.trim()}`);
25147
25990
  "rule",
25148
25991
  "rule-path-scoping"
25149
25992
  ),
25150
- detail: `${path29.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
25993
+ detail: `${path30.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
25151
25994
  }
25152
25995
  ]
25153
25996
  });
@@ -25156,9 +25999,9 @@ ${parsed.body.trim()}`);
25156
25999
  }
25157
26000
  function compileCursorRules(sourceRulesDir, _lossReport) {
25158
26001
  const dotRulesFiles = [];
25159
- for (const ruleFile of ts(path29.join(sourceRulesDir, "*.md")).sort()) {
25160
- const content = fs30.readFileSync(ruleFile, "utf8");
25161
- const name = path29.basename(ruleFile, ".md");
26002
+ for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
26003
+ const content = fs31.readFileSync(ruleFile, "utf8");
26004
+ const name = path30.basename(ruleFile, ".md");
25162
26005
  let frontmatterData = {};
25163
26006
  let body = content;
25164
26007
  if (content.startsWith("---\n")) {
@@ -25166,7 +26009,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
25166
26009
  if (endIndex !== -1) {
25167
26010
  const frontmatterStr = content.slice(4, endIndex);
25168
26011
  try {
25169
- frontmatterData = (0, import_yaml8.parse)(frontmatterStr) ?? {};
26012
+ frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
25170
26013
  } catch {
25171
26014
  frontmatterData = {};
25172
26015
  }
@@ -25187,7 +26030,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
25187
26030
  }
25188
26031
  const marker = formatProvenanceMarker(
25189
26032
  "markdown",
25190
- `rules/${path29.basename(ruleFile)}`,
26033
+ `rules/${path30.basename(ruleFile)}`,
25191
26034
  computeSourceHash(ruleFile),
25192
26035
  "cursor"
25193
26036
  );
@@ -25203,9 +26046,9 @@ ${body}`;
25203
26046
  }
25204
26047
  function compileClineRules(sourceRulesDir, lossReport) {
25205
26048
  const dotRulesFiles = [];
25206
- for (const ruleFile of ts(path29.join(sourceRulesDir, "*.md")).sort()) {
25207
- const content = fs30.readFileSync(ruleFile, "utf8");
25208
- const name = path29.basename(ruleFile, ".md");
26049
+ for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
26050
+ const content = fs31.readFileSync(ruleFile, "utf8");
26051
+ const name = path30.basename(ruleFile, ".md");
25209
26052
  let frontmatterData = {};
25210
26053
  let body = content;
25211
26054
  if (content.startsWith("---\n")) {
@@ -25213,7 +26056,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
25213
26056
  if (endIndex !== -1) {
25214
26057
  const frontmatterStr = content.slice(4, endIndex);
25215
26058
  try {
25216
- frontmatterData = (0, import_yaml8.parse)(frontmatterStr) ?? {};
26059
+ frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
25217
26060
  } catch {
25218
26061
  frontmatterData = {};
25219
26062
  }
@@ -25222,13 +26065,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
25222
26065
  }
25223
26066
  const marker = formatProvenanceMarker(
25224
26067
  "markdown",
25225
- `rules/${path29.basename(ruleFile)}`,
26068
+ `rules/${path30.basename(ruleFile)}`,
25226
26069
  computeSourceHash(ruleFile),
25227
26070
  "cline"
25228
26071
  );
25229
26072
  if (frontmatterData.mode === "exec-policy") {
25230
26073
  addLoss(lossReport, "cline", "rules", {
25231
- source: `rules/${path29.basename(ruleFile)}`,
26074
+ source: `rules/${path30.basename(ruleFile)}`,
25232
26075
  fields: [
25233
26076
  {
25234
26077
  field: "mode",
@@ -25238,7 +26081,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
25238
26081
  "mode",
25239
26082
  "rule-mode-downgrade"
25240
26083
  ),
25241
- detail: `${path29.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
26084
+ detail: `${path30.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
25242
26085
  }
25243
26086
  ]
25244
26087
  });
@@ -25283,7 +26126,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
25283
26126
  rules: profile.rules
25284
26127
  };
25285
26128
  const rules = compileRules(
25286
- path30.join(sourceRoot, config.source.rules),
26129
+ path31.join(sourceRoot, config.source.rules),
25287
26130
  "codex",
25288
26131
  mappings,
25289
26132
  lossReport
@@ -25428,9 +26271,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
25428
26271
  function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
25429
26272
  const cp = mappings.modelTiers.custom_provider;
25430
26273
  if (!cp) return "";
25431
- const agentsDir = path30.join(sourceRoot, config.source.agents);
25432
- if (!fs31.existsSync(agentsDir)) return "";
25433
- const agentFiles = ts(path30.join(agentsDir, "*.md")).sort();
26274
+ const agentsDir = path31.join(sourceRoot, config.source.agents);
26275
+ if (!fs32.existsSync(agentsDir)) return "";
26276
+ const agentFiles = ts(path31.join(agentsDir, "*.md")).sort();
25434
26277
  const hasProviderAgent = agentFiles.some((agentFile) => {
25435
26278
  const { data } = parseMarkdownFrontmatter(agentFile);
25436
26279
  return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
@@ -25495,7 +26338,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
25495
26338
  }
25496
26339
  ];
25497
26340
  for (const ruleFile of rules.dotRulesFiles) {
25498
- const destination = path30.join(rulesRoot, ruleFile.name);
26341
+ const destination = path31.join(rulesRoot, ruleFile.name);
25499
26342
  if (options.dryRun) {
25500
26343
  logger.info(`[dry-run] rules: write ${destination}`);
25501
26344
  outcomes.push({
@@ -25523,15 +26366,15 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
25523
26366
  return outcomes;
25524
26367
  }
25525
26368
  function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
25526
- const source = path30.join(sourceRoot, config.source.instructions);
26369
+ const source = path31.join(sourceRoot, config.source.instructions);
25527
26370
  const destination = resolveTargetPath(paths.instructions);
25528
- const composed = `${fs31.readFileSync(source, "utf8").trim()}
26371
+ const composed = `${fs32.readFileSync(source, "utf8").trim()}
25529
26372
 
25530
26373
  --- tangyr managed rules ---
25531
26374
  ${agentsAppendix}`.trim();
25532
26375
  const marker = formatProvenanceMarker(
25533
26376
  "markdown",
25534
- path30.basename(config.source.instructions),
26377
+ path31.basename(config.source.instructions),
25535
26378
  hashString(composed),
25536
26379
  "codex"
25537
26380
  );
@@ -25558,9 +26401,9 @@ ${composed}
25558
26401
  );
25559
26402
  }
25560
26403
  function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopePath) {
25561
- const source = path30.resolve(sourceRoot, config.source.skills);
26404
+ const source = path31.resolve(sourceRoot, config.source.skills);
25562
26405
  const destination = resolveTargetPath(paths.skills);
25563
- if (!fs31.existsSync(source)) {
26406
+ if (!fs32.existsSync(source)) {
25564
26407
  return skippedMissingSource("skills", source);
25565
26408
  }
25566
26409
  if (options.dryRun) {
@@ -25576,29 +26419,29 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
25576
26419
  };
25577
26420
  }
25578
26421
  if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
25579
- fs31.unlinkSync(destination);
26422
+ fs32.unlinkSync(destination);
25580
26423
  logger.verbose(`Skills: created skills path ${destination}`);
25581
26424
  } else if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
25582
26425
  return { component: "skills", status: "conflict", path: destination };
25583
26426
  } else if (artifactClass === "managed-symlink") {
25584
- fs31.unlinkSync(destination);
26427
+ fs32.unlinkSync(destination);
25585
26428
  }
25586
- ensureDir(path30.dirname(destination));
26429
+ ensureDir(path31.dirname(destination));
25587
26430
  createRelativeSymlink(source, destination, "dir");
25588
26431
  logger.verbose(`Skills: created skills path ${destination}`);
25589
26432
  return { component: "skills", status: "success", path: destination };
25590
26433
  }
25591
26434
  function syncAgents(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
25592
- const sourceAgentsRoot = path30.join(sourceRoot, config.source.agents);
25593
- if (!fs31.existsSync(sourceAgentsRoot)) {
26435
+ const sourceAgentsRoot = path31.join(sourceRoot, config.source.agents);
26436
+ if (!fs32.existsSync(sourceAgentsRoot)) {
25594
26437
  return [skippedMissingSource("agents", sourceAgentsRoot)];
25595
26438
  }
25596
- const sourceAgents = ts(path30.join(sourceAgentsRoot, "*.md")).sort();
26439
+ const sourceAgents = ts(path31.join(sourceAgentsRoot, "*.md")).sort();
25597
26440
  const agentsRoot = resolveTargetPath(paths.agents);
25598
26441
  return sourceAgents.map((agentFile) => {
25599
- const destination = path30.join(
26442
+ const destination = path31.join(
25600
26443
  agentsRoot,
25601
- `${path30.basename(agentFile, ".md")}.toml`
26444
+ `${path31.basename(agentFile, ".md")}.toml`
25602
26445
  );
25603
26446
  const compiled = compileAgent(
25604
26447
  agentFile,
@@ -25634,10 +26477,10 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
25634
26477
  }
25635
26478
  const source = resolveHooksSourceFile(sourceRoot, config);
25636
26479
  const sourceLabel = hooksSourceLabel(config);
25637
- if (!fs31.existsSync(source)) {
26480
+ if (!fs32.existsSync(source)) {
25638
26481
  return skippedMissingSource("hooks", source);
25639
26482
  }
25640
- const sourceHooksJson = JSON.parse(fs31.readFileSync(source, "utf8"));
26483
+ const sourceHooksJson = JSON.parse(fs32.readFileSync(source, "utf8"));
25641
26484
  const compiled = compileHooks(
25642
26485
  sourceHooksJson,
25643
26486
  "codex",
@@ -25659,7 +26502,7 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
25659
26502
  destination,
25660
26503
  hostHooks,
25661
26504
  stringifyJson2,
25662
- !fs31.existsSync(destination),
26505
+ !fs32.existsSync(destination),
25663
26506
  logger
25664
26507
  );
25665
26508
  return {
@@ -25672,7 +26515,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
25672
26515
  const source = resolveMcpSourceFile(sourceRoot, config);
25673
26516
  const sourceLabel = mcpSourceLabel(config);
25674
26517
  const destination = resolveTargetPath(paths.mcp_shared_file);
25675
- if (!fs31.existsSync(source)) {
26518
+ if (!fs32.existsSync(source)) {
25676
26519
  if (providerToml && !options.dryRun) {
25677
26520
  const changed2 = writeTomlManagedSection(
25678
26521
  destination,
@@ -25687,7 +26530,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
25687
26530
  }
25688
26531
  return skippedMissingSource("mcp", source);
25689
26532
  }
25690
- const sourceMcpJson = JSON.parse(fs31.readFileSync(source, "utf8"));
26533
+ const sourceMcpJson = JSON.parse(fs32.readFileSync(source, "utf8"));
25691
26534
  const compiled = compileMcp(sourceMcpJson, "codex", lossReport, sourceLabel);
25692
26535
  const managedContent = providerToml ? `${compiled.trimEnd()}${providerToml}` : compiled;
25693
26536
  if (options.dryRun) {
@@ -25709,12 +26552,12 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
25709
26552
  if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
25710
26553
  return { component, status: "conflict", path: destination };
25711
26554
  }
25712
- ensureDir(path30.dirname(destination));
25713
- fs31.writeFileSync(destination, content);
26555
+ ensureDir(path31.dirname(destination));
26556
+ fs32.writeFileSync(destination, content);
25714
26557
  return { component, status: "success", path: destination };
25715
26558
  }
25716
26559
  function writeTomlManagedSection(destination, managedContent, logger) {
25717
- const current = fs31.existsSync(destination) ? fs31.readFileSync(destination, "utf8") : "";
26560
+ const current = fs32.existsSync(destination) ? fs32.readFileSync(destination, "utf8") : "";
25718
26561
  const isFirstWrite = current.length > 0 && !current.includes(managedMcpStart);
25719
26562
  if (isFirstWrite) {
25720
26563
  logger.warn(
@@ -25730,8 +26573,8 @@ ${managedMcpEnd}
25730
26573
  if (current === next.trimStart()) {
25731
26574
  return false;
25732
26575
  }
25733
- ensureDir(path30.dirname(destination));
25734
- fs31.writeFileSync(destination, next.trimStart());
26576
+ ensureDir(path31.dirname(destination));
26577
+ fs32.writeFileSync(destination, next.trimStart());
25735
26578
  return true;
25736
26579
  }
25737
26580
  function removeManagedTomlSection(content) {
@@ -25758,16 +26601,16 @@ function handleConflict(destination, config, options, logger, manifest, scopePat
25758
26601
  backupFile(destination, manifest);
25759
26602
  writeManifest(scopePath, manifest);
25760
26603
  } else {
25761
- fs31.renameSync(destination, `${destination}.bak.${Date.now()}`);
26604
+ fs32.renameSync(destination, `${destination}.bak.${Date.now()}`);
25762
26605
  }
25763
26606
  return true;
25764
26607
  }
25765
- fs31.rmSync(destination, { recursive: true, force: true });
26608
+ fs32.rmSync(destination, { recursive: true, force: true });
25766
26609
  return true;
25767
26610
  }
25768
26611
  function isCompiledCurrent(destination, expectedContent, expectedHash) {
25769
26612
  try {
25770
- const current = fs31.readFileSync(destination, "utf8");
26613
+ const current = fs32.readFileSync(destination, "utf8");
25771
26614
  const marker = extractProvenanceMarker(current);
25772
26615
  return expectedHash ? marker?.hash === expectedHash && marker.target === "codex" && current === expectedContent : current === expectedContent;
25773
26616
  } catch {
@@ -25786,16 +26629,16 @@ function shouldSkipComponent(options, component) {
25786
26629
  }
25787
26630
  function isSymlinkTo(linkPath, source) {
25788
26631
  try {
25789
- return fs31.realpathSync(linkPath) === fs31.realpathSync(source);
26632
+ return fs32.realpathSync(linkPath) === fs32.realpathSync(source);
25790
26633
  } catch {
25791
26634
  return false;
25792
26635
  }
25793
26636
  }
25794
26637
  function readJsonObject3(filePath) {
25795
- if (!fs31.existsSync(filePath)) {
26638
+ if (!fs32.existsSync(filePath)) {
25796
26639
  return {};
25797
26640
  }
25798
- const parsed = JSON.parse(fs31.readFileSync(filePath, "utf8"));
26641
+ const parsed = JSON.parse(fs32.readFileSync(filePath, "utf8"));
25799
26642
  return isRecord4(parsed) ? parsed : {};
25800
26643
  }
25801
26644
  function stringifyJson2(value) {
@@ -25811,16 +26654,16 @@ function hashString(value) {
25811
26654
 
25812
26655
  // src/adapters/copilot.ts
25813
26656
  import crypto6 from "crypto";
25814
- import fs32 from "fs";
25815
- import path32 from "path";
26657
+ import fs33 from "fs";
26658
+ import path33 from "path";
25816
26659
 
25817
26660
  // src/compiler/commands.ts
25818
- var import_yaml9 = __toESM(require_dist(), 1);
25819
- import path31 from "path";
26661
+ var import_yaml10 = __toESM(require_dist(), 1);
26662
+ import path32 from "path";
25820
26663
  function compileCommandPrompt(sourceFile) {
25821
26664
  const { data, body } = parseMarkdownFrontmatter(sourceFile);
25822
- const relativeSource = `commands/${path31.basename(sourceFile)}`;
25823
- const fields = promptFrontmatter(data, path31.basename(sourceFile, ".md"));
26665
+ const relativeSource = `commands/${path32.basename(sourceFile)}`;
26666
+ const fields = promptFrontmatter(data, path32.basename(sourceFile, ".md"));
25824
26667
  const marker = formatProvenanceMarker(
25825
26668
  "markdown",
25826
26669
  relativeSource,
@@ -25829,7 +26672,7 @@ function compileCommandPrompt(sourceFile) {
25829
26672
  );
25830
26673
  return `${marker}
25831
26674
  ---
25832
- ${(0, import_yaml9.stringify)(fields).trim()}
26675
+ ${(0, import_yaml10.stringify)(fields).trim()}
25833
26676
  ---
25834
26677
 
25835
26678
  ${body.trimEnd()}
@@ -25995,13 +26838,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
25995
26838
  }
25996
26839
  function syncProviderLoss(config, sourceRoot, mappings, lossReport) {
25997
26840
  if (!mappings.modelTiers.custom_provider) return;
25998
- const agentsDir = path32.join(sourceRoot, config.source.agents);
25999
- if (!fs32.existsSync(agentsDir)) return;
26000
- for (const agentFile of ts(path32.join(agentsDir, "*.md")).sort()) {
26841
+ const agentsDir = path33.join(sourceRoot, config.source.agents);
26842
+ if (!fs33.existsSync(agentsDir)) return;
26843
+ for (const agentFile of ts(path33.join(agentsDir, "*.md")).sort()) {
26001
26844
  const { data } = parseMarkdownFrontmatter(agentFile);
26002
26845
  const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
26003
26846
  if (hasProvider) {
26004
- const basename = path32.basename(agentFile);
26847
+ const basename = path33.basename(agentFile);
26005
26848
  addLoss(lossReport, "copilot", "agents", {
26006
26849
  source: `agents/${basename}`,
26007
26850
  fields: [
@@ -26026,23 +26869,23 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
26026
26869
  logger.verbose(message);
26027
26870
  return [{ component: "instructions", status: "skipped", path: message }];
26028
26871
  }
26029
- const source = path32.resolve(sourceRoot, config.source.instructions);
26030
- if (!fs32.existsSync(source)) {
26872
+ const source = path33.resolve(sourceRoot, config.source.instructions);
26873
+ if (!fs33.existsSync(source)) {
26031
26874
  return [skippedMissingSource2("instructions", source)];
26032
26875
  }
26033
- const rawContent = fs32.readFileSync(source, "utf8");
26876
+ const rawContent = fs33.readFileSync(source, "utf8");
26034
26877
  const contentHash = hashString2(rawContent);
26035
26878
  const marker = formatProvenanceMarker(
26036
26879
  "markdown",
26037
- path32.basename(config.source.instructions),
26880
+ path33.basename(config.source.instructions),
26038
26881
  contentHash,
26039
26882
  "copilot"
26040
26883
  );
26041
26884
  const composedContent = `${marker}
26042
26885
  ${rawContent}`;
26043
26886
  const projectRoot = options.projectRoot ?? process.cwd();
26044
- const agentsMdDest = path32.resolve(projectRoot, "AGENTS.md");
26045
- const mirrorDest = path32.resolve(
26887
+ const agentsMdDest = path33.resolve(projectRoot, "AGENTS.md");
26888
+ const mirrorDest = path33.resolve(
26046
26889
  projectRoot,
26047
26890
  ".github",
26048
26891
  "copilot-instructions.md"
@@ -26096,17 +26939,17 @@ function writeInstructionsFile(component, destination, content, contentHash, con
26096
26939
  if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
26097
26940
  return { component, status: "conflict", path: destination };
26098
26941
  }
26099
- ensureDir(path32.dirname(destination));
26100
- fs32.writeFileSync(destination, content);
26942
+ ensureDir(path33.dirname(destination));
26943
+ fs33.writeFileSync(destination, content);
26101
26944
  return { component, status: "success", path: destination };
26102
26945
  }
26103
26946
  function hashString2(value) {
26104
26947
  return `sha256:${crypto6.createHash("sha256").update(value).digest("hex")}`;
26105
26948
  }
26106
26949
  function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
26107
- const source = path32.resolve(sourceRoot, config.source.skills);
26950
+ const source = path33.resolve(sourceRoot, config.source.skills);
26108
26951
  const destination = resolveTargetPath(paths.skills);
26109
- if (!fs32.existsSync(source)) {
26952
+ if (!fs33.existsSync(source)) {
26110
26953
  return skippedMissingSource2("skills", source);
26111
26954
  }
26112
26955
  if (options.dryRun) {
@@ -26122,27 +26965,27 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
26122
26965
  };
26123
26966
  }
26124
26967
  if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
26125
- fs32.unlinkSync(destination);
26968
+ fs33.unlinkSync(destination);
26126
26969
  } else if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
26127
26970
  return { component: "skills", status: "conflict", path: destination };
26128
26971
  } else if (artifactClass === "managed-symlink") {
26129
- fs32.unlinkSync(destination);
26972
+ fs33.unlinkSync(destination);
26130
26973
  }
26131
- ensureDir(path32.dirname(destination));
26974
+ ensureDir(path33.dirname(destination));
26132
26975
  createRelativeSymlink(source, destination, "dir");
26133
26976
  return { component: "skills", status: "success", path: destination };
26134
26977
  }
26135
26978
  function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
26136
- const sourceAgentsRoot = path32.join(sourceRoot, config.source.agents);
26137
- if (!fs32.existsSync(sourceAgentsRoot)) {
26979
+ const sourceAgentsRoot = path33.join(sourceRoot, config.source.agents);
26980
+ if (!fs33.existsSync(sourceAgentsRoot)) {
26138
26981
  return [skippedMissingSource2("agents", sourceAgentsRoot)];
26139
26982
  }
26140
- const sourceAgents = ts(path32.join(sourceAgentsRoot, "*.md")).sort();
26983
+ const sourceAgents = ts(path33.join(sourceAgentsRoot, "*.md")).sort();
26141
26984
  const agentsRoot = resolveTargetPath(paths.agents);
26142
26985
  return sourceAgents.map((agentFile) => {
26143
- const destination = path32.join(
26986
+ const destination = path33.join(
26144
26987
  agentsRoot,
26145
- `${path32.basename(agentFile, ".md")}.agent.md`
26988
+ `${path33.basename(agentFile, ".md")}.agent.md`
26146
26989
  );
26147
26990
  const compiled = compileAgent(
26148
26991
  agentFile,
@@ -26170,16 +27013,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
26170
27013
  });
26171
27014
  }
26172
27015
  function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
26173
- const sourceCommandsRoot = path32.join(sourceRoot, config.source.commands);
26174
- if (!fs32.existsSync(sourceCommandsRoot)) {
27016
+ const sourceCommandsRoot = path33.join(sourceRoot, config.source.commands);
27017
+ if (!fs33.existsSync(sourceCommandsRoot)) {
26175
27018
  return [skippedMissingSource2("commands", sourceCommandsRoot)];
26176
27019
  }
26177
- const sourceCommands = ts(path32.join(sourceCommandsRoot, "*.md")).sort();
27020
+ const sourceCommands = ts(path33.join(sourceCommandsRoot, "*.md")).sort();
26178
27021
  const promptsRoot = resolveTargetPath(paths.prompts);
26179
27022
  return sourceCommands.map((commandFile) => {
26180
- const destination = path32.join(
27023
+ const destination = path33.join(
26181
27024
  promptsRoot,
26182
- `${path32.basename(commandFile, ".md")}.prompt.md`
27025
+ `${path33.basename(commandFile, ".md")}.prompt.md`
26183
27026
  );
26184
27027
  const compiled = compileCommandPrompt(commandFile);
26185
27028
  if (options.dryRun) {
@@ -26205,14 +27048,14 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
26205
27048
  function syncHooks2(config, sourceRoot, paths, mappings, options, lossReport, logger) {
26206
27049
  const source = resolveHooksSourceFile(sourceRoot, config);
26207
27050
  const sourceLabel = hooksSourceLabel(config);
26208
- const destination = path32.join(
27051
+ const destination = path33.join(
26209
27052
  resolveTargetPath(paths.hooks),
26210
27053
  "tangyr-managed.json"
26211
27054
  );
26212
- if (!fs32.existsSync(source)) {
27055
+ if (!fs33.existsSync(source)) {
26213
27056
  return skippedMissingSource2("hooks", source);
26214
27057
  }
26215
- const sourceHooksJson = JSON.parse(fs32.readFileSync(source, "utf8"));
27058
+ const sourceHooksJson = JSON.parse(fs33.readFileSync(source, "utf8"));
26216
27059
  const compiled = compileHooks(
26217
27060
  sourceHooksJson,
26218
27061
  "copilot",
@@ -26249,10 +27092,10 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger) {
26249
27092
  const source = resolveMcpSourceFile(sourceRoot, config);
26250
27093
  const sourceLabel = mcpSourceLabel(config);
26251
27094
  const destination = resolveTargetPath(paths.mcp_shared_file);
26252
- if (!fs32.existsSync(source)) {
27095
+ if (!fs33.existsSync(source)) {
26253
27096
  return skippedMissingSource2("mcp", source);
26254
27097
  }
26255
- const sourceMcpJson = JSON.parse(fs32.readFileSync(source, "utf8"));
27098
+ const sourceMcpJson = JSON.parse(fs33.readFileSync(source, "utf8"));
26256
27099
  const compiled = compileMcp(
26257
27100
  sourceMcpJson,
26258
27101
  "copilot",
@@ -26282,13 +27125,13 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
26282
27125
  if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
26283
27126
  return { component, status: "conflict", path: destination };
26284
27127
  }
26285
- ensureDir(path32.dirname(destination));
26286
- fs32.writeFileSync(destination, content);
27128
+ ensureDir(path33.dirname(destination));
27129
+ fs33.writeFileSync(destination, content);
26287
27130
  return { component, status: "success", path: destination };
26288
27131
  }
26289
27132
  function isCompiledCurrent2(destination, expectedContent, expectedHash) {
26290
27133
  try {
26291
- const current = fs32.readFileSync(destination, "utf8");
27134
+ const current = fs33.readFileSync(destination, "utf8");
26292
27135
  const marker = extractProvenanceMarker(current);
26293
27136
  return expectedHash ? marker?.hash === expectedHash && marker.target === "copilot" && current === expectedContent : current === expectedContent;
26294
27137
  } catch {
@@ -26311,11 +27154,11 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
26311
27154
  backupFile(destination, manifest);
26312
27155
  writeManifest(scopePath, manifest);
26313
27156
  } else {
26314
- fs32.renameSync(destination, `${destination}.bak.${Date.now()}`);
27157
+ fs33.renameSync(destination, `${destination}.bak.${Date.now()}`);
26315
27158
  }
26316
27159
  return true;
26317
27160
  }
26318
- fs32.rmSync(destination, { recursive: true, force: true });
27161
+ fs33.rmSync(destination, { recursive: true, force: true });
26319
27162
  return true;
26320
27163
  }
26321
27164
  function shouldSkipComponent2(options, component) {
@@ -26324,12 +27167,12 @@ function shouldSkipComponent2(options, component) {
26324
27167
  function cleanupLegacyAgents(paths, options, logger) {
26325
27168
  const currentAgentsRoot = resolveTargetPath(paths.agents);
26326
27169
  const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
26327
- if (path32.resolve(currentAgentsRoot) === path32.resolve(legacyAgentsRoot)) {
27170
+ if (path33.resolve(currentAgentsRoot) === path33.resolve(legacyAgentsRoot)) {
26328
27171
  return [];
26329
27172
  }
26330
27173
  const outcomes = [];
26331
27174
  for (const filePath of ts(
26332
- path32.join(legacyAgentsRoot, "*.agent.md")
27175
+ path33.join(legacyAgentsRoot, "*.agent.md")
26333
27176
  ).sort()) {
26334
27177
  if (!isCopilotManagedCompiledFile(filePath)) {
26335
27178
  continue;
@@ -26339,14 +27182,14 @@ function cleanupLegacyAgents(paths, options, logger) {
26339
27182
  outcomes.push({ component: "agents", status: "dry-run", path: filePath });
26340
27183
  continue;
26341
27184
  }
26342
- fs32.rmSync(filePath, { force: true });
27185
+ fs33.rmSync(filePath, { force: true });
26343
27186
  outcomes.push({ component: "agents", status: "success", path: filePath });
26344
27187
  }
26345
27188
  return outcomes;
26346
27189
  }
26347
27190
  function isCopilotManagedCompiledFile(filePath) {
26348
27191
  try {
26349
- return extractProvenanceMarker(fs32.readFileSync(filePath, "utf8"))?.target === "copilot";
27192
+ return extractProvenanceMarker(fs33.readFileSync(filePath, "utf8"))?.target === "copilot";
26350
27193
  } catch {
26351
27194
  return false;
26352
27195
  }
@@ -26360,7 +27203,7 @@ function skippedMissingSource2(component, source) {
26360
27203
  }
26361
27204
  function isSymlinkTo2(linkPath, source) {
26362
27205
  try {
26363
- return fs32.realpathSync(linkPath) === fs32.realpathSync(source);
27206
+ return fs33.realpathSync(linkPath) === fs33.realpathSync(source);
26364
27207
  } catch {
26365
27208
  return false;
26366
27209
  }
@@ -26368,8 +27211,8 @@ function isSymlinkTo2(linkPath, source) {
26368
27211
 
26369
27212
  // src/adapters/cursor.ts
26370
27213
  import crypto7 from "crypto";
26371
- import fs33 from "fs";
26372
- import path33 from "path";
27214
+ import fs34 from "fs";
27215
+ import path34 from "path";
26373
27216
  function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
26374
27217
  const scope = options.scope ?? "global";
26375
27218
  const profile = resolveTargetPaths({
@@ -26520,9 +27363,9 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
26520
27363
  return { target: "cursor", outcomes };
26521
27364
  }
26522
27365
  function syncInstructions2(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
26523
- const source = path33.join(sourceRoot, config.source.instructions);
27366
+ const source = path34.join(sourceRoot, config.source.instructions);
26524
27367
  const destination = resolveTargetPath(paths.instructions);
26525
- const baseContent = fs33.existsSync(source) ? fs33.readFileSync(source, "utf8").trim() : "";
27368
+ const baseContent = fs34.existsSync(source) ? fs34.readFileSync(source, "utf8").trim() : "";
26526
27369
  const personaContent = extractPrimaryPersonaContent(
26527
27370
  config,
26528
27371
  sourceRoot,
@@ -26535,7 +27378,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
26535
27378
  ${personaContent}`.trim() : baseContent;
26536
27379
  const marker = formatProvenanceMarker(
26537
27380
  "markdown",
26538
- path33.basename(config.source.instructions),
27381
+ path34.basename(config.source.instructions),
26539
27382
  hashString3(composed),
26540
27383
  "cursor"
26541
27384
  );
@@ -26560,11 +27403,11 @@ ${composed}
26560
27403
  );
26561
27404
  }
26562
27405
  function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
26563
- const agentsDir = path33.join(sourceRoot, config.source.agents);
26564
- if (!fs33.existsSync(agentsDir)) {
27406
+ const agentsDir = path34.join(sourceRoot, config.source.agents);
27407
+ if (!fs34.existsSync(agentsDir)) {
26565
27408
  return null;
26566
27409
  }
26567
- const agentFiles = ts(path33.join(agentsDir, "*.md")).sort();
27410
+ const agentFiles = ts(path34.join(agentsDir, "*.md")).sort();
26568
27411
  if (agentFiles.length === 0) {
26569
27412
  return null;
26570
27413
  }
@@ -26587,7 +27430,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
26587
27430
  return null;
26588
27431
  }
26589
27432
  addLoss(lossReport, "cursor", "instructions", {
26590
- source: `agents/${path33.basename(primaryFile)}`,
27433
+ source: `agents/${path34.basename(primaryFile)}`,
26591
27434
  fields: [
26592
27435
  {
26593
27436
  field: "persona",
@@ -26597,23 +27440,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
26597
27440
  "persona",
26598
27441
  "instructions-shim"
26599
27442
  ),
26600
- detail: `Primary persona from ${path33.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
27443
+ detail: `Primary persona from ${path34.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
26601
27444
  }
26602
27445
  ]
26603
27446
  });
26604
27447
  return body.trim();
26605
27448
  }
26606
27449
  function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
26607
- const sourceAgentsRoot = path33.join(sourceRoot, config.source.agents);
26608
- if (!fs33.existsSync(sourceAgentsRoot)) {
27450
+ const sourceAgentsRoot = path34.join(sourceRoot, config.source.agents);
27451
+ if (!fs34.existsSync(sourceAgentsRoot)) {
26609
27452
  return [skippedMissingSource3("agents", sourceAgentsRoot)];
26610
27453
  }
26611
- const sourceAgents = ts(path33.join(sourceAgentsRoot, "*.md")).sort();
27454
+ const sourceAgents = ts(path34.join(sourceAgentsRoot, "*.md")).sort();
26612
27455
  const agentsRoot = resolveTargetPath(paths.agents);
26613
27456
  return sourceAgents.map((agentFile) => {
26614
- const destination = path33.join(
27457
+ const destination = path34.join(
26615
27458
  agentsRoot,
26616
- `${path33.basename(agentFile, ".md")}.md`
27459
+ `${path34.basename(agentFile, ".md")}.md`
26617
27460
  );
26618
27461
  let compiled;
26619
27462
  try {
@@ -26654,14 +27497,14 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
26654
27497
  });
26655
27498
  }
26656
27499
  function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
26657
- const sourceRulesDir = path33.join(sourceRoot, config.source.rules);
26658
- if (!fs33.existsSync(sourceRulesDir)) {
27500
+ const sourceRulesDir = path34.join(sourceRoot, config.source.rules);
27501
+ if (!fs34.existsSync(sourceRulesDir)) {
26659
27502
  return [skippedMissingSource3("rules", sourceRulesDir)];
26660
27503
  }
26661
27504
  const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
26662
27505
  const rulesDir = resolveTargetPath(paths.rules);
26663
27506
  return compiled.dotRulesFiles.map(({ name, content }) => {
26664
- const destination = path33.join(rulesDir, name);
27507
+ const destination = path34.join(rulesDir, name);
26665
27508
  if (options.dryRun) {
26666
27509
  logger.info(`[dry-run] rules: write ${destination}`);
26667
27510
  return {
@@ -26685,17 +27528,17 @@ function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, lo
26685
27528
  });
26686
27529
  }
26687
27530
  function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
26688
- const sourceCommandsRoot = path33.join(sourceRoot, config.source.commands);
26689
- if (!fs33.existsSync(sourceCommandsRoot)) {
27531
+ const sourceCommandsRoot = path34.join(sourceRoot, config.source.commands);
27532
+ if (!fs34.existsSync(sourceCommandsRoot)) {
26690
27533
  return [skippedMissingSource3("commands", sourceCommandsRoot)];
26691
27534
  }
26692
- const sourceCommands = ts(path33.join(sourceCommandsRoot, "*.md")).sort();
27535
+ const sourceCommands = ts(path34.join(sourceCommandsRoot, "*.md")).sort();
26693
27536
  const skillsRoot = resolveTargetPath(paths.skills);
26694
27537
  return sourceCommands.map((commandFile) => {
26695
- const baseName = path33.basename(commandFile, ".md");
26696
- const destination = path33.join(skillsRoot, baseName, "SKILL.md");
26697
- const commandContent = fs33.readFileSync(commandFile, "utf8");
26698
- const relativeSource = `commands/${path33.basename(commandFile)}`;
27538
+ const baseName = path34.basename(commandFile, ".md");
27539
+ const destination = path34.join(skillsRoot, baseName, "SKILL.md");
27540
+ const commandContent = fs34.readFileSync(commandFile, "utf8");
27541
+ const relativeSource = `commands/${path34.basename(commandFile)}`;
26699
27542
  const marker = formatProvenanceMarker(
26700
27543
  "markdown",
26701
27544
  relativeSource,
@@ -26733,9 +27576,9 @@ ${commandContent.trim()}
26733
27576
  );
26734
27577
  });
26735
27578
  }
26736
- function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, component = "skills", destination = "", asSymlink = false) {
26737
- const source = path33.resolve(sourceRoot, config.source.skills);
26738
- if (!fs33.existsSync(source)) {
27579
+ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, component = "skills", destination = "", asSymlink = false) {
27580
+ const source = path34.resolve(sourceRoot, config.source.skills);
27581
+ if (!fs34.existsSync(source)) {
26739
27582
  return skippedMissingSource3(component, source);
26740
27583
  }
26741
27584
  if (options.dryRun) {
@@ -26749,18 +27592,18 @@ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, c
26749
27592
  return { component, status: "skipped-current", path: destination };
26750
27593
  }
26751
27594
  if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
26752
- fs33.unlinkSync(destination);
27595
+ fs34.unlinkSync(destination);
26753
27596
  } else if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
26754
27597
  return { component, status: "conflict", path: destination };
26755
27598
  } else if (artifactClass === "managed-symlink") {
26756
- fs33.unlinkSync(destination);
27599
+ fs34.unlinkSync(destination);
26757
27600
  }
26758
- ensureDir(path33.dirname(destination));
27601
+ ensureDir(path34.dirname(destination));
26759
27602
  createRelativeSymlink(source, destination, "dir");
26760
27603
  logger.verbose(`Skills: created shared skills symlink ${destination}`);
26761
27604
  return { component, status: "success", path: destination };
26762
27605
  }
26763
- if (fs33.existsSync(destination)) {
27606
+ if (fs34.existsSync(destination)) {
26764
27607
  return { component, status: "skipped-current", path: destination };
26765
27608
  }
26766
27609
  ensureDir(destination);
@@ -26771,7 +27614,7 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
26771
27614
  const source = resolveHooksSourceFile(sourceRoot, config);
26772
27615
  const sourceLabel = hooksSourceLabel(config);
26773
27616
  const destination = resolveTargetPath(paths.hooks_file);
26774
- const sourceHooksJson = fs33.existsSync(source) ? JSON.parse(fs33.readFileSync(source, "utf8")) : { hooks: {} };
27617
+ const sourceHooksJson = fs34.existsSync(source) ? JSON.parse(fs34.readFileSync(source, "utf8")) : { hooks: {} };
26775
27618
  const compiled = compileHooks(
26776
27619
  sourceHooksJson,
26777
27620
  "cursor",
@@ -26785,18 +27628,18 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
26785
27628
  }
26786
27629
  const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
26787
27630
  `;
26788
- ensureDir(path33.dirname(destination));
26789
- fs33.writeFileSync(destination, hooksFileContent);
27631
+ ensureDir(path34.dirname(destination));
27632
+ fs34.writeFileSync(destination, hooksFileContent);
26790
27633
  return { component: "hooks", status: "success", path: destination };
26791
27634
  }
26792
27635
  function syncMcp3(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
26793
27636
  const source = resolveMcpSourceFile(sourceRoot, config);
26794
27637
  const sourceLabel = mcpSourceLabel(config);
26795
27638
  const destination = resolveTargetPath(paths.mcp_file);
26796
- if (!fs33.existsSync(source)) {
27639
+ if (!fs34.existsSync(source)) {
26797
27640
  return skippedMissingSource3("mcp", source);
26798
27641
  }
26799
- const sourceMcpJson = JSON.parse(fs33.readFileSync(source, "utf8"));
27642
+ const sourceMcpJson = JSON.parse(fs34.readFileSync(source, "utf8"));
26800
27643
  const mcpJson = compileMcp(sourceMcpJson, "cursor", lossReport, sourceLabel);
26801
27644
  if (options.dryRun) {
26802
27645
  logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
@@ -26847,13 +27690,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
26847
27690
  );
26848
27691
  }
26849
27692
  function syncProviderPin(config, sourceRoot, lossReport) {
26850
- const agentsDir = path33.join(sourceRoot, config.source.agents);
26851
- if (!fs33.existsSync(agentsDir)) return;
26852
- for (const agentFile of ts(path33.join(agentsDir, "*.md")).sort()) {
27693
+ const agentsDir = path34.join(sourceRoot, config.source.agents);
27694
+ if (!fs34.existsSync(agentsDir)) return;
27695
+ for (const agentFile of ts(path34.join(agentsDir, "*.md")).sort()) {
26853
27696
  const { data } = parseMarkdownFrontmatter(agentFile);
26854
27697
  const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
26855
27698
  if (hasCustomProvider) {
26856
- const relativeSource = `agents/${path33.basename(agentFile)}`;
27699
+ const relativeSource = `agents/${path34.basename(agentFile)}`;
26857
27700
  addLoss(lossReport, "cursor", "agents", {
26858
27701
  source: relativeSource,
26859
27702
  fields: [
@@ -26865,7 +27708,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
26865
27708
  "provider",
26866
27709
  "provider-not-representable"
26867
27710
  ),
26868
- detail: `${path33.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
27711
+ detail: `${path34.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
26869
27712
  }
26870
27713
  ]
26871
27714
  });
@@ -26880,8 +27723,8 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
26880
27723
  if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
26881
27724
  return { component, status: "conflict", path: destination };
26882
27725
  }
26883
- ensureDir(path33.dirname(destination));
26884
- fs33.writeFileSync(destination, content);
27726
+ ensureDir(path34.dirname(destination));
27727
+ fs34.writeFileSync(destination, content);
26885
27728
  return { component, status: "success", path: destination };
26886
27729
  }
26887
27730
  function handleConflict3(destination, config, options, logger, manifest, scopePath) {
@@ -26900,16 +27743,16 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
26900
27743
  backupFile(destination, manifest);
26901
27744
  writeManifest(scopePath, manifest);
26902
27745
  } else {
26903
- fs33.renameSync(destination, `${destination}.bak.${Date.now()}`);
27746
+ fs34.renameSync(destination, `${destination}.bak.${Date.now()}`);
26904
27747
  }
26905
27748
  return true;
26906
27749
  }
26907
- fs33.rmSync(destination, { recursive: true, force: true });
27750
+ fs34.rmSync(destination, { recursive: true, force: true });
26908
27751
  return true;
26909
27752
  }
26910
27753
  function isCompiledCurrent3(destination, expectedContent, expectedHash) {
26911
27754
  try {
26912
- const current = fs33.readFileSync(destination, "utf8");
27755
+ const current = fs34.readFileSync(destination, "utf8");
26913
27756
  const marker = extractProvenanceMarker(current);
26914
27757
  return expectedHash ? marker?.hash === expectedHash && marker.target === "cursor" && current === expectedContent : current === expectedContent;
26915
27758
  } catch {
@@ -26928,7 +27771,7 @@ function shouldSkipComponent3(options, component) {
26928
27771
  }
26929
27772
  function isSymlinkTo3(linkPath, source) {
26930
27773
  try {
26931
- return fs33.realpathSync(linkPath) === fs33.realpathSync(source);
27774
+ return fs34.realpathSync(linkPath) === fs34.realpathSync(source);
26932
27775
  } catch {
26933
27776
  return false;
26934
27777
  }
@@ -26939,8 +27782,8 @@ function hashString3(value) {
26939
27782
 
26940
27783
  // src/adapters/cline.ts
26941
27784
  import crypto8 from "crypto";
26942
- import fs34 from "fs";
26943
- import path34 from "path";
27785
+ import fs35 from "fs";
27786
+ import path35 from "path";
26944
27787
  function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
26945
27788
  const scope = options.scope ?? "global";
26946
27789
  const profile = resolveTargetPaths({
@@ -27053,7 +27896,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
27053
27896
  function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
27054
27897
  if (scope === "global" || paths.instructions === null) {
27055
27898
  addLoss(lossReport, "cline", "instructions", {
27056
- source: path34.basename(config.source.instructions),
27899
+ source: path35.basename(config.source.instructions),
27057
27900
  fields: [
27058
27901
  {
27059
27902
  field: "instructions",
@@ -27073,12 +27916,12 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
27073
27916
  path: "cline/global/instructions: no committable global path"
27074
27917
  };
27075
27918
  }
27076
- const source = path34.join(sourceRoot, config.source.instructions);
27919
+ const source = path35.join(sourceRoot, config.source.instructions);
27077
27920
  const destination = resolveTargetPath(paths.instructions);
27078
- const baseContent = fs34.existsSync(source) ? fs34.readFileSync(source, "utf8").trim() : "";
27921
+ const baseContent = fs35.existsSync(source) ? fs35.readFileSync(source, "utf8").trim() : "";
27079
27922
  const marker = formatProvenanceMarker(
27080
27923
  "markdown",
27081
- path34.basename(config.source.instructions),
27924
+ path35.basename(config.source.instructions),
27082
27925
  hashString4(baseContent),
27083
27926
  "cline"
27084
27927
  );
@@ -27103,11 +27946,11 @@ ${baseContent}
27103
27946
  );
27104
27947
  }
27105
27948
  function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
27106
- const sourceAgentsRoot = path34.join(sourceRoot, config.source.agents);
27107
- if (!fs34.existsSync(sourceAgentsRoot)) {
27949
+ const sourceAgentsRoot = path35.join(sourceRoot, config.source.agents);
27950
+ if (!fs35.existsSync(sourceAgentsRoot)) {
27108
27951
  return [skippedMissingSource4("agents", sourceAgentsRoot)];
27109
27952
  }
27110
- const sourceAgents = ts(path34.join(sourceAgentsRoot, "*.md")).sort();
27953
+ const sourceAgents = ts(path35.join(sourceAgentsRoot, "*.md")).sort();
27111
27954
  return sourceAgents.map((agentFile) => {
27112
27955
  compileAgent(agentFile, "cline", mappings, extensions, lossReport);
27113
27956
  if (options.dryRun) {
@@ -27123,14 +27966,14 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
27123
27966
  });
27124
27967
  }
27125
27968
  function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
27126
- const sourceRulesDir = path34.join(sourceRoot, config.source.rules);
27127
- if (!fs34.existsSync(sourceRulesDir)) {
27969
+ const sourceRulesDir = path35.join(sourceRoot, config.source.rules);
27970
+ if (!fs35.existsSync(sourceRulesDir)) {
27128
27971
  return [skippedMissingSource4("rules", sourceRulesDir)];
27129
27972
  }
27130
27973
  const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
27131
27974
  const rulesDir = resolveTargetPath(paths.rules);
27132
27975
  return compiled.dotRulesFiles.map(({ name, content }) => {
27133
- const destination = path34.join(rulesDir, name);
27976
+ const destination = path35.join(rulesDir, name);
27134
27977
  if (options.dryRun) {
27135
27978
  logger.info(`[dry-run] rules: write ${destination}`);
27136
27979
  return {
@@ -27154,17 +27997,17 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
27154
27997
  });
27155
27998
  }
27156
27999
  function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
27157
- const sourceCommandsRoot = path34.join(sourceRoot, config.source.commands);
27158
- if (!fs34.existsSync(sourceCommandsRoot)) {
28000
+ const sourceCommandsRoot = path35.join(sourceRoot, config.source.commands);
28001
+ if (!fs35.existsSync(sourceCommandsRoot)) {
27159
28002
  return [skippedMissingSource4("commands", sourceCommandsRoot)];
27160
28003
  }
27161
- const sourceCommands = ts(path34.join(sourceCommandsRoot, "*.md")).sort();
28004
+ const sourceCommands = ts(path35.join(sourceCommandsRoot, "*.md")).sort();
27162
28005
  const workflowsRoot = resolveTargetPath(paths.workflows);
27163
28006
  return sourceCommands.map((commandFile) => {
27164
- const baseName = path34.basename(commandFile);
27165
- const destination = path34.join(workflowsRoot, baseName);
27166
- const commandContent = fs34.readFileSync(commandFile, "utf8");
27167
- const relativeSource = `commands/${path34.basename(commandFile)}`;
28007
+ const baseName = path35.basename(commandFile);
28008
+ const destination = path35.join(workflowsRoot, baseName);
28009
+ const commandContent = fs35.readFileSync(commandFile, "utf8");
28010
+ const relativeSource = `commands/${path35.basename(commandFile)}`;
27168
28011
  const marker = formatProvenanceMarker(
27169
28012
  "markdown",
27170
28013
  relativeSource,
@@ -27199,9 +28042,9 @@ ${commandContent.trim()}
27199
28042
  });
27200
28043
  }
27201
28044
  function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
27202
- const source = path34.resolve(sourceRoot, config.source.skills);
28045
+ const source = path35.resolve(sourceRoot, config.source.skills);
27203
28046
  const destination = resolveTargetPath(paths.skills);
27204
- if (!fs34.existsSync(source)) {
28047
+ if (!fs35.existsSync(source)) {
27205
28048
  return skippedMissingSource4("skills", source);
27206
28049
  }
27207
28050
  if (options.dryRun) {
@@ -27221,9 +28064,9 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
27221
28064
  return { component: "skills", status: "conflict", path: destination };
27222
28065
  }
27223
28066
  } else if (artifactClass === "managed-symlink") {
27224
- fs34.unlinkSync(destination);
28067
+ fs35.unlinkSync(destination);
27225
28068
  }
27226
- ensureDir(path34.dirname(destination));
28069
+ ensureDir(path35.dirname(destination));
27227
28070
  createRelativeSymlink(source, destination, "dir");
27228
28071
  logger.verbose(`Skills: created Cline skills symlink ${destination}`);
27229
28072
  return { component: "skills", status: "success", path: destination };
@@ -27231,7 +28074,7 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
27231
28074
  function syncHooks4(config, sourceRoot, mappings, options, lossReport, logger) {
27232
28075
  const source = resolveHooksSourceFile(sourceRoot, config);
27233
28076
  const sourceLabel = hooksSourceLabel(config);
27234
- const sourceHooksJson = fs34.existsSync(source) ? JSON.parse(fs34.readFileSync(source, "utf8")) : { hooks: {} };
28077
+ const sourceHooksJson = fs35.existsSync(source) ? JSON.parse(fs35.readFileSync(source, "utf8")) : { hooks: {} };
27235
28078
  compileHooks(sourceHooksJson, "cline", mappings, lossReport, sourceLabel);
27236
28079
  if (options.dryRun) {
27237
28080
  logger.info(`[dry-run] hooks: record hook-as-plugin loss for ${source}`);
@@ -27246,10 +28089,10 @@ function syncMcp4(config, sourceRoot, paths, options, lossReport, logger, manife
27246
28089
  const source = resolveMcpSourceFile(sourceRoot, config);
27247
28090
  const sourceLabel = mcpSourceLabel(config);
27248
28091
  const destination = resolveTargetPath(paths.mcp_file);
27249
- if (!fs34.existsSync(source)) {
28092
+ if (!fs35.existsSync(source)) {
27250
28093
  return skippedMissingSource4("mcp", source);
27251
28094
  }
27252
- const sourceMcpJson = JSON.parse(fs34.readFileSync(source, "utf8"));
28095
+ const sourceMcpJson = JSON.parse(fs35.readFileSync(source, "utf8"));
27253
28096
  const mcpJson = compileMcp(sourceMcpJson, "cline", lossReport, sourceLabel);
27254
28097
  if (options.dryRun) {
27255
28098
  logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
@@ -27292,11 +28135,11 @@ function syncSettings(lossReport) {
27292
28135
  };
27293
28136
  }
27294
28137
  function syncProviderAndModel(config, sourceRoot, lossReport) {
27295
- const agentsDir = path34.join(sourceRoot, config.source.agents);
27296
- if (!fs34.existsSync(agentsDir)) return;
27297
- for (const agentFile of ts(path34.join(agentsDir, "*.md")).sort()) {
28138
+ const agentsDir = path35.join(sourceRoot, config.source.agents);
28139
+ if (!fs35.existsSync(agentsDir)) return;
28140
+ for (const agentFile of ts(path35.join(agentsDir, "*.md")).sort()) {
27298
28141
  const { data } = parseMarkdownFrontmatter(agentFile);
27299
- const relativeSource = `agents/${path34.basename(agentFile)}`;
28142
+ const relativeSource = `agents/${path35.basename(agentFile)}`;
27300
28143
  const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
27301
28144
  if (hasCustomProvider) {
27302
28145
  addLoss(lossReport, "cline", "agents", {
@@ -27310,7 +28153,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
27310
28153
  "provider",
27311
28154
  "provider-not-representable"
27312
28155
  ),
27313
- detail: `${path34.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
28156
+ detail: `${path35.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
27314
28157
  }
27315
28158
  ]
27316
28159
  });
@@ -27328,7 +28171,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
27328
28171
  "model",
27329
28172
  "model-not-representable"
27330
28173
  ),
27331
- detail: `${path34.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
28174
+ detail: `${path35.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
27332
28175
  }
27333
28176
  ]
27334
28177
  });
@@ -27343,8 +28186,8 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
27343
28186
  if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
27344
28187
  return { component, status: "conflict", path: destination };
27345
28188
  }
27346
- ensureDir(path34.dirname(destination));
27347
- fs34.writeFileSync(destination, content);
28189
+ ensureDir(path35.dirname(destination));
28190
+ fs35.writeFileSync(destination, content);
27348
28191
  return { component, status: "success", path: destination };
27349
28192
  }
27350
28193
  function handleConflict4(destination, config, options, logger, manifest, scopePath) {
@@ -27363,16 +28206,16 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
27363
28206
  backupFile(destination, manifest);
27364
28207
  writeManifest(scopePath, manifest);
27365
28208
  } else {
27366
- fs34.renameSync(destination, `${destination}.bak.${Date.now()}`);
28209
+ fs35.renameSync(destination, `${destination}.bak.${Date.now()}`);
27367
28210
  }
27368
28211
  return true;
27369
28212
  }
27370
- fs34.rmSync(destination, { recursive: true, force: true });
28213
+ fs35.rmSync(destination, { recursive: true, force: true });
27371
28214
  return true;
27372
28215
  }
27373
28216
  function isCompiledCurrent4(destination, expectedContent, expectedHash) {
27374
28217
  try {
27375
- const current = fs34.readFileSync(destination, "utf8");
28218
+ const current = fs35.readFileSync(destination, "utf8");
27376
28219
  const marker = extractProvenanceMarker(current);
27377
28220
  return expectedHash ? marker?.hash === expectedHash && marker.target === "cline" && current === expectedContent : current === expectedContent;
27378
28221
  } catch {
@@ -27391,7 +28234,7 @@ function shouldSkipComponent4(options, component) {
27391
28234
  }
27392
28235
  function isSymlinkTo4(linkPath, source) {
27393
28236
  try {
27394
- return fs34.realpathSync(linkPath) === fs34.realpathSync(source);
28237
+ return fs35.realpathSync(linkPath) === fs35.realpathSync(source);
27395
28238
  } catch {
27396
28239
  return false;
27397
28240
  }
@@ -27402,10 +28245,10 @@ function hashString4(value) {
27402
28245
 
27403
28246
  // src/adapters/opencode.ts
27404
28247
  import crypto9 from "crypto";
27405
- import fs35 from "fs";
28248
+ import fs36 from "fs";
27406
28249
  import os6 from "os";
27407
- import path35 from "path";
27408
- var import_yaml10 = __toESM(require_dist(), 1);
28250
+ import path36 from "path";
28251
+ var import_yaml11 = __toESM(require_dist(), 1);
27409
28252
  function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
27410
28253
  const scope = options.scope ?? "global";
27411
28254
  const profile = resolveTargetPaths({
@@ -27422,7 +28265,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
27422
28265
  config_doc: profile.config_doc
27423
28266
  };
27424
28267
  const rules = compileRules(
27425
- path35.join(sourceRoot, config.source.rules),
28268
+ path36.join(sourceRoot, config.source.rules),
27426
28269
  "opencode",
27427
28270
  mappings,
27428
28271
  lossReport
@@ -27524,16 +28367,16 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
27524
28367
  return { target: "opencode", outcomes };
27525
28368
  }
27526
28369
  function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
27527
- const source = path35.join(sourceRoot, config.source.instructions);
28370
+ const source = path36.join(sourceRoot, config.source.instructions);
27528
28371
  const destination = resolveTargetPath(paths.instructions);
27529
- const baseContent = fs35.existsSync(source) ? fs35.readFileSync(source, "utf8").trim() : "";
28372
+ const baseContent = fs36.existsSync(source) ? fs36.readFileSync(source, "utf8").trim() : "";
27530
28373
  const composed = agentsAppendix ? `${baseContent}
27531
28374
 
27532
28375
  --- tangyr managed rules ---
27533
28376
  ${agentsAppendix}`.trim() : baseContent;
27534
28377
  const marker = formatProvenanceMarker(
27535
28378
  "markdown",
27536
- path35.basename(config.source.instructions),
28379
+ path36.basename(config.source.instructions),
27537
28380
  hashString5(composed),
27538
28381
  "opencode"
27539
28382
  );
@@ -27560,16 +28403,16 @@ ${composed}
27560
28403
  );
27561
28404
  }
27562
28405
  function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
27563
- const sourceAgentsRoot = path35.join(sourceRoot, config.source.agents);
27564
- if (!fs35.existsSync(sourceAgentsRoot)) {
28406
+ const sourceAgentsRoot = path36.join(sourceRoot, config.source.agents);
28407
+ if (!fs36.existsSync(sourceAgentsRoot)) {
27565
28408
  return [skippedMissingSource5("agents", sourceAgentsRoot)];
27566
28409
  }
27567
- const sourceAgents = ts(path35.join(sourceAgentsRoot, "*.md")).sort();
28410
+ const sourceAgents = ts(path36.join(sourceAgentsRoot, "*.md")).sort();
27568
28411
  const agentsRoot = resolveTargetPath(paths.agents);
27569
28412
  return sourceAgents.map((agentFile) => {
27570
- const destination = path35.join(
28413
+ const destination = path36.join(
27571
28414
  agentsRoot,
27572
- `${path35.basename(agentFile, ".md")}.md`
28415
+ `${path36.basename(agentFile, ".md")}.md`
27573
28416
  );
27574
28417
  let compiled;
27575
28418
  try {
@@ -27625,19 +28468,19 @@ function applyProviderModelBinding(compiled, mappings) {
27625
28468
  const after = compiled.slice(fmEnd);
27626
28469
  let fields;
27627
28470
  try {
27628
- fields = (0, import_yaml10.parse)(yamlBlock) ?? {};
28471
+ fields = (0, import_yaml11.parse)(yamlBlock) ?? {};
27629
28472
  } catch {
27630
28473
  return compiled;
27631
28474
  }
27632
28475
  fields.model = modelValue;
27633
- return `${before}${(0, import_yaml10.stringify)(fields).trim()}${after}`;
28476
+ return `${before}${(0, import_yaml11.stringify)(fields).trim()}${after}`;
27634
28477
  }
27635
28478
  function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
27636
- const sourceCommandsRoot = path35.join(sourceRoot, config.source.commands);
27637
- if (!fs35.existsSync(sourceCommandsRoot)) {
28479
+ const sourceCommandsRoot = path36.join(sourceRoot, config.source.commands);
28480
+ if (!fs36.existsSync(sourceCommandsRoot)) {
27638
28481
  return [skippedMissingSource5("commands", sourceCommandsRoot)];
27639
28482
  }
27640
- const sourceCommands = ts(path35.join(sourceCommandsRoot, "*.md")).sort();
28483
+ const sourceCommands = ts(path36.join(sourceCommandsRoot, "*.md")).sort();
27641
28484
  const commandsRoot = resolveTargetPath(paths.commands);
27642
28485
  return sourceCommands.map((commandFile) => {
27643
28486
  const { data, body } = parseCommandFile(commandFile);
@@ -27651,7 +28494,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
27651
28494
  if (typeof data.model === "string") {
27652
28495
  frontmatter.model = data.model;
27653
28496
  }
27654
- const relativeSource = `commands/${path35.basename(commandFile)}`;
28497
+ const relativeSource = `commands/${path36.basename(commandFile)}`;
27655
28498
  const marker = formatProvenanceMarker(
27656
28499
  "markdown",
27657
28500
  relativeSource,
@@ -27660,16 +28503,16 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
27660
28503
  );
27661
28504
  const content = Object.keys(frontmatter).length > 0 ? `${marker}
27662
28505
  ---
27663
- ${(0, import_yaml10.stringify)(frontmatter).trim()}
28506
+ ${(0, import_yaml11.stringify)(frontmatter).trim()}
27664
28507
  ---
27665
28508
 
27666
28509
  ${body.trimEnd()}
27667
28510
  ` : `${marker}
27668
28511
  ${body.trimEnd()}
27669
28512
  `;
27670
- const destination = path35.join(
28513
+ const destination = path36.join(
27671
28514
  commandsRoot,
27672
- `${path35.basename(commandFile, ".md")}.md`
28515
+ `${path36.basename(commandFile, ".md")}.md`
27673
28516
  );
27674
28517
  if (options.dryRun) {
27675
28518
  logger.info(
@@ -27696,8 +28539,8 @@ ${body.trimEnd()}
27696
28539
  });
27697
28540
  }
27698
28541
  function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scopePath, component = "skills", destination = "") {
27699
- const source = path35.resolve(sourceRoot, config.source.skills);
27700
- if (!fs35.existsSync(source)) {
28542
+ const source = path36.resolve(sourceRoot, config.source.skills);
28543
+ if (!fs36.existsSync(source)) {
27701
28544
  return skippedMissingSource5(component, source);
27702
28545
  }
27703
28546
  if (options.dryRun) {
@@ -27709,13 +28552,13 @@ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scop
27709
28552
  return { component, status: "skipped-current", path: destination };
27710
28553
  }
27711
28554
  if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
27712
- fs35.unlinkSync(destination);
28555
+ fs36.unlinkSync(destination);
27713
28556
  } else if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
27714
28557
  return { component, status: "conflict", path: destination };
27715
28558
  } else if (artifactClass === "managed-symlink") {
27716
- fs35.unlinkSync(destination);
28559
+ fs36.unlinkSync(destination);
27717
28560
  }
27718
- ensureDir(path35.dirname(destination));
28561
+ ensureDir(path36.dirname(destination));
27719
28562
  createRelativeSymlink(source, destination, "dir");
27720
28563
  logger.verbose(`Skills: created skills path ${destination}`);
27721
28564
  return { component, status: "success", path: destination };
@@ -27724,13 +28567,13 @@ function syncMcp5(config, sourceRoot, paths, mappings, options, lossReport, logg
27724
28567
  const source = resolveMcpSourceFile(sourceRoot, config);
27725
28568
  const sourceLabel = mcpSourceLabel(config);
27726
28569
  const destination = resolveTargetPath(paths.config_doc);
27727
- if (!fs35.existsSync(source)) {
28570
+ if (!fs36.existsSync(source)) {
27728
28571
  if (!options.dryRun) {
27729
28572
  syncConfigDoc(paths, {}, lossReport, {}, mappings);
27730
28573
  }
27731
28574
  return skippedMissingSource5("mcp", source);
27732
28575
  }
27733
- const sourceMcpJson = JSON.parse(fs35.readFileSync(source, "utf8"));
28576
+ const sourceMcpJson = JSON.parse(fs36.readFileSync(source, "utf8"));
27734
28577
  const mcpJson = compileMcp(
27735
28578
  sourceMcpJson,
27736
28579
  "opencode",
@@ -27761,7 +28604,7 @@ function syncPermissions2(config, _sourceRoot, paths, options, lossReport, logge
27761
28604
  function syncHooks5(config, sourceRoot, mappings, options, lossReport) {
27762
28605
  const source = resolveHooksSourceFile(sourceRoot, config);
27763
28606
  const sourceLabel = hooksSourceLabel(config);
27764
- const sourceHooksJson = fs35.existsSync(source) ? JSON.parse(fs35.readFileSync(source, "utf8")) : { hooks: {} };
28607
+ const sourceHooksJson = fs36.existsSync(source) ? JSON.parse(fs36.readFileSync(source, "utf8")) : { hooks: {} };
27765
28608
  compileHooks(sourceHooksJson, "opencode", mappings, lossReport, sourceLabel);
27766
28609
  const message = "hooks: Skip \u2014 OpenCode exposes hooks only as plugin code (hook-as-plugin loss recorded)";
27767
28610
  return { component: "hooks", status: "skipped", path: message };
@@ -27795,9 +28638,9 @@ function syncProviderBlock(mappings) {
27795
28638
  function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings) {
27796
28639
  const destination = resolveTargetPath(paths.config_doc);
27797
28640
  let existing = {};
27798
- if (fs35.existsSync(destination)) {
28641
+ if (fs36.existsSync(destination)) {
27799
28642
  try {
27800
- existing = JSON.parse(fs35.readFileSync(destination, "utf8"));
28643
+ existing = JSON.parse(fs36.readFileSync(destination, "utf8"));
27801
28644
  } catch {
27802
28645
  existing = {};
27803
28646
  }
@@ -27822,8 +28665,8 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
27822
28665
  };
27823
28666
  }
27824
28667
  }
27825
- ensureDir(path35.dirname(destination));
27826
- fs35.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
28668
+ ensureDir(path36.dirname(destination));
28669
+ fs36.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
27827
28670
  `);
27828
28671
  }
27829
28672
  function writeCompiledArtifact5(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
@@ -27834,8 +28677,8 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
27834
28677
  if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
27835
28678
  return { component, status: "conflict", path: destination };
27836
28679
  }
27837
- ensureDir(path35.dirname(destination));
27838
- fs35.writeFileSync(destination, content);
28680
+ ensureDir(path36.dirname(destination));
28681
+ fs36.writeFileSync(destination, content);
27839
28682
  return { component, status: "success", path: destination };
27840
28683
  }
27841
28684
  function handleConflict5(destination, config, options, logger, manifest, scopePath) {
@@ -27854,16 +28697,16 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
27854
28697
  backupFile(destination, manifest);
27855
28698
  writeManifest(scopePath, manifest);
27856
28699
  } else {
27857
- fs35.renameSync(destination, `${destination}.bak.${Date.now()}`);
28700
+ fs36.renameSync(destination, `${destination}.bak.${Date.now()}`);
27858
28701
  }
27859
28702
  return true;
27860
28703
  }
27861
- fs35.rmSync(destination, { recursive: true, force: true });
28704
+ fs36.rmSync(destination, { recursive: true, force: true });
27862
28705
  return true;
27863
28706
  }
27864
28707
  function isCompiledCurrent5(destination, expectedContent, expectedHash) {
27865
28708
  try {
27866
- const current = fs35.readFileSync(destination, "utf8");
28709
+ const current = fs36.readFileSync(destination, "utf8");
27867
28710
  const marker = extractProvenanceMarker(current);
27868
28711
  return expectedHash ? marker?.hash === expectedHash && marker.target === "opencode" && current === expectedContent : current === expectedContent;
27869
28712
  } catch {
@@ -27882,7 +28725,7 @@ function shouldSkipComponent5(options, component) {
27882
28725
  }
27883
28726
  function isSymlinkTo5(linkPath, source) {
27884
28727
  try {
27885
- return fs35.realpathSync(linkPath) === fs35.realpathSync(source);
28728
+ return fs36.realpathSync(linkPath) === fs36.realpathSync(source);
27886
28729
  } catch {
27887
28730
  return false;
27888
28731
  }
@@ -27891,7 +28734,7 @@ function hashString5(value) {
27891
28734
  return `sha256:${crypto9.createHash("sha256").update(value).digest("hex")}`;
27892
28735
  }
27893
28736
  function parseCommandFile(commandFile) {
27894
- const content = fs35.readFileSync(commandFile, "utf8");
28737
+ const content = fs36.readFileSync(commandFile, "utf8");
27895
28738
  if (!content.startsWith("---\n")) {
27896
28739
  return { data: {}, body: content };
27897
28740
  }
@@ -27900,7 +28743,7 @@ function parseCommandFile(commandFile) {
27900
28743
  return { data: {}, body: content };
27901
28744
  }
27902
28745
  try {
27903
- const data = (0, import_yaml10.parse)(content.slice(4, endIndex)) ?? {};
28746
+ const data = (0, import_yaml11.parse)(content.slice(4, endIndex)) ?? {};
27904
28747
  const body = content.slice(endIndex + "\n---".length).replace(/^\n/u, "");
27905
28748
  return { data, body };
27906
28749
  } catch {
@@ -27911,10 +28754,10 @@ function parseCommandFile(commandFile) {
27911
28754
  // src/commands/install.ts
27912
28755
  function isBackupableFile(targetPath) {
27913
28756
  try {
27914
- const lstat = fs36.lstatSync(targetPath);
28757
+ const lstat = fs37.lstatSync(targetPath);
27915
28758
  if (lstat.isDirectory()) return false;
27916
28759
  if (lstat.isSymbolicLink()) {
27917
- const stat = fs36.statSync(targetPath);
28760
+ const stat = fs37.statSync(targetPath);
27918
28761
  return stat.isFile();
27919
28762
  }
27920
28763
  return lstat.isFile();
@@ -27924,10 +28767,10 @@ function isBackupableFile(targetPath) {
27924
28767
  }
27925
28768
  function backupConflictingTarget(targetPath, scopePath) {
27926
28769
  const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/gu, "").replace("T", "T").replace(/\.\d+Z$/u, "Z");
27927
- const relativeToRoot = path36.relative("/", targetPath).replace(/^\.\.\/+/gu, "");
27928
- const backupPath = path36.join(scopePath, "backups", ts2, relativeToRoot);
27929
- fs36.mkdirSync(path36.dirname(backupPath), { recursive: true });
27930
- fs36.copyFileSync(targetPath, backupPath);
28770
+ const relativeToRoot = path37.relative("/", targetPath).replace(/^\.\.\/+/gu, "");
28771
+ const backupPath = path37.join(scopePath, "backups", ts2, relativeToRoot);
28772
+ fs37.mkdirSync(path37.dirname(backupPath), { recursive: true });
28773
+ fs37.copyFileSync(targetPath, backupPath);
27931
28774
  return backupPath;
27932
28775
  }
27933
28776
  async function runInstallCommand(options, logger) {
@@ -27956,7 +28799,7 @@ async function runInstallCommand(options, logger) {
27956
28799
  );
27957
28800
  }
27958
28801
  const kitName = resolvedKitName ?? config.kit;
27959
- const kitPath = kitPathOverride ?? (options.kitPath ? path36.resolve(options.kitPath) : config.kitPath);
28802
+ const kitPath = kitPathOverride ?? (options.kitPath ? path37.resolve(options.kitPath) : config.kitPath);
27960
28803
  if (!kitName && !kitPath) {
27961
28804
  logger.error(
27962
28805
  "No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
@@ -28097,7 +28940,7 @@ ACCEPTED CONFLICTS (backup-and-replace applied to ${conflictingFindings.length}
28097
28940
  logger.info(` source: ${finding.tool}`);
28098
28941
  logger.info(` action: backup-and-replace`);
28099
28942
  logger.info(` backup: ${backupLocation}`);
28100
- } else if (fs36.existsSync(finding.path)) {
28943
+ } else if (fs37.existsSync(finding.path)) {
28101
28944
  logger.info(` - ${finding.path}`);
28102
28945
  logger.info(` source: ${finding.tool}`);
28103
28946
  logger.info(
@@ -28208,7 +29051,7 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
28208
29051
  writeManifest(scopePath, manifest);
28209
29052
  logger.info(`
28210
29053
  Installation complete: ${installedCount} files installed.`);
28211
- logger.info(`Manifest written to ${path36.join(scopePath, "manifest.json")}`);
29054
+ logger.info(`Manifest written to ${path37.join(scopePath, "manifest.json")}`);
28212
29055
  logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
28213
29056
  logger.info(`Scope: ${scope}`);
28214
29057
  logger.info(`Tools: ${tools.join(", ")}`);
@@ -28350,13 +29193,13 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
28350
29193
  logger.verbose(` skipped (operator choice): ${placement.destination}`);
28351
29194
  continue;
28352
29195
  }
28353
- const destDir = path36.dirname(placement.destination);
28354
- fs36.mkdirSync(destDir, { recursive: true });
29196
+ const destDir = path37.dirname(placement.destination);
29197
+ fs37.mkdirSync(destDir, { recursive: true });
28355
29198
  if (placement.type === "symlink") {
28356
- if (fs36.existsSync(placement.destination) || isSymlink2(placement.destination)) {
29199
+ if (fs37.existsSync(placement.destination) || isSymlink2(placement.destination)) {
28357
29200
  removeManagedPath(placement.destination);
28358
29201
  }
28359
- fs36.symlinkSync(
29202
+ fs37.symlinkSync(
28360
29203
  placement.source,
28361
29204
  placement.destination,
28362
29205
  placement.isDir ? "dir" : "file"
@@ -28365,12 +29208,12 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
28365
29208
  ` symlink: ${placement.source} \u2192 ${placement.destination}`
28366
29209
  );
28367
29210
  } else {
28368
- fs36.copyFileSync(placement.source, placement.destination);
29211
+ fs37.copyFileSync(placement.source, placement.destination);
28369
29212
  logger.verbose(` copy: ${placement.source} \u2192 ${placement.destination}`);
28370
29213
  }
28371
29214
  addArtifactToManifest(manifest, {
28372
29215
  relativePath: placement.manifestKey,
28373
- hash: fs36.statSync(placement.source).isDirectory() ? `dir:${placement.source}` : computeSourceHash(placement.source),
29216
+ hash: fs37.statSync(placement.source).isDirectory() ? `dir:${placement.source}` : computeSourceHash(placement.source),
28374
29217
  origin: "tangyr-managed"
28375
29218
  });
28376
29219
  count++;
@@ -28617,11 +29460,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
28617
29460
  if (outcome.path === mcpFile2) {
28618
29461
  return "cline/mcp.json";
28619
29462
  }
28620
- if (outcome.path.startsWith(`${workflowsRoot}${path36.sep}`)) {
28621
- return `cline/workflows/${path36.basename(outcome.path)}`;
29463
+ if (outcome.path.startsWith(`${workflowsRoot}${path37.sep}`)) {
29464
+ return `cline/workflows/${path37.basename(outcome.path)}`;
28622
29465
  }
28623
- if (outcome.path.startsWith(`${rulesRoot2}${path36.sep}`)) {
28624
- return `cline/rules/${path36.basename(outcome.path)}`;
29466
+ if (outcome.path.startsWith(`${rulesRoot2}${path37.sep}`)) {
29467
+ return `cline/rules/${path37.basename(outcome.path)}`;
28625
29468
  }
28626
29469
  return null;
28627
29470
  }
@@ -28657,14 +29500,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
28657
29500
  if (outcome.path === permissionsFile) {
28658
29501
  return "cursor/permissions.json";
28659
29502
  }
28660
- if (outcome.path.startsWith(`${agentsRoot2}${path36.sep}`)) {
28661
- return `cursor/agents/${path36.basename(outcome.path)}`;
29503
+ if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
29504
+ return `cursor/agents/${path37.basename(outcome.path)}`;
28662
29505
  }
28663
- if (outcome.path.startsWith(`${rulesRoot2}${path36.sep}`)) {
28664
- return `cursor/rules/${path36.basename(outcome.path)}`;
29506
+ if (outcome.path.startsWith(`${rulesRoot2}${path37.sep}`)) {
29507
+ return `cursor/rules/${path37.basename(outcome.path)}`;
28665
29508
  }
28666
- if (outcome.path.startsWith(`${skillsRoot2}${path36.sep}`)) {
28667
- const rel = path36.relative(skillsRoot2, outcome.path);
29509
+ if (outcome.path.startsWith(`${skillsRoot2}${path37.sep}`)) {
29510
+ const rel = path37.relative(skillsRoot2, outcome.path);
28668
29511
  return `cursor/skills/${rel}`;
28669
29512
  }
28670
29513
  return null;
@@ -28690,14 +29533,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
28690
29533
  if (outcome.path === skillsSharedRoot) {
28691
29534
  return "opencode/skills_shared";
28692
29535
  }
28693
- if (outcome.path.startsWith(`${agentsRoot2}${path36.sep}`)) {
28694
- return `opencode/agents/${path36.basename(outcome.path)}`;
29536
+ if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
29537
+ return `opencode/agents/${path37.basename(outcome.path)}`;
28695
29538
  }
28696
- if (outcome.path.startsWith(`${commandsRoot}${path36.sep}`)) {
28697
- return `opencode/commands/${path36.basename(outcome.path)}`;
29539
+ if (outcome.path.startsWith(`${commandsRoot}${path37.sep}`)) {
29540
+ return `opencode/commands/${path37.basename(outcome.path)}`;
28698
29541
  }
28699
29542
  if (outcome.path === configDocFile) {
28700
- return `opencode/${path36.basename(outcome.path)}`;
29543
+ return `opencode/${path37.basename(outcome.path)}`;
28701
29544
  }
28702
29545
  return null;
28703
29546
  }
@@ -28711,17 +29554,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
28711
29554
  if (outcome.path === skillsRoot2) {
28712
29555
  return "copilot/skills";
28713
29556
  }
28714
- if (outcome.path.startsWith(`${agentsRoot2}${path36.sep}`)) {
28715
- return `copilot/agents/${path36.basename(outcome.path)}`;
29557
+ if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
29558
+ return `copilot/agents/${path37.basename(outcome.path)}`;
28716
29559
  }
28717
- if (outcome.path.startsWith(`${promptsRoot}${path36.sep}`)) {
28718
- return `copilot/prompts/${path36.basename(outcome.path)}`;
29560
+ if (outcome.path.startsWith(`${promptsRoot}${path37.sep}`)) {
29561
+ return `copilot/prompts/${path37.basename(outcome.path)}`;
28719
29562
  }
28720
- if (outcome.path.startsWith(`${hooksRoot}${path36.sep}`)) {
28721
- return `copilot/hooks/${path36.basename(outcome.path)}`;
29563
+ if (outcome.path.startsWith(`${hooksRoot}${path37.sep}`)) {
29564
+ return `copilot/hooks/${path37.basename(outcome.path)}`;
28722
29565
  }
28723
29566
  if (outcome.path === mcpFile2) {
28724
- return `copilot/${path36.basename(outcome.path)}`;
29567
+ return `copilot/${path37.basename(outcome.path)}`;
28725
29568
  }
28726
29569
  return null;
28727
29570
  }
@@ -28737,17 +29580,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
28737
29580
  if (outcome.path === skillsRoot) {
28738
29581
  return "codex/skills";
28739
29582
  }
28740
- if (outcome.path.startsWith(`${agentsRoot}${path36.sep}`)) {
28741
- return `codex/agents/${path36.basename(outcome.path)}`;
29583
+ if (outcome.path.startsWith(`${agentsRoot}${path37.sep}`)) {
29584
+ return `codex/agents/${path37.basename(outcome.path)}`;
28742
29585
  }
28743
- if (outcome.path.startsWith(`${rulesRoot}${path36.sep}`)) {
28744
- return `codex/rules/${path36.basename(outcome.path)}`;
29586
+ if (outcome.path.startsWith(`${rulesRoot}${path37.sep}`)) {
29587
+ return `codex/rules/${path37.basename(outcome.path)}`;
28745
29588
  }
28746
29589
  if (outcome.path === hooksFile) {
28747
- return `codex/${path36.basename(outcome.path)}`;
29590
+ return `codex/${path37.basename(outcome.path)}`;
28748
29591
  }
28749
29592
  if (outcome.path === mcpFile) {
28750
- return `codex/${path36.basename(outcome.path)}`;
29593
+ return `codex/${path37.basename(outcome.path)}`;
28751
29594
  }
28752
29595
  return null;
28753
29596
  }
@@ -28782,8 +29625,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
28782
29625
  };
28783
29626
  }
28784
29627
  const placements = [];
28785
- const claudeMd = path36.join(kitInfo.path, "CLAUDE.md");
28786
- if (fs36.existsSync(claudeMd)) {
29628
+ const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
29629
+ if (fs37.existsSync(claudeMd)) {
28787
29630
  placements.push({
28788
29631
  source: claudeMd,
28789
29632
  destination: resolvedPaths.instructions,
@@ -28799,8 +29642,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
28799
29642
  rules: resolvedPaths.rules
28800
29643
  };
28801
29644
  for (const [component, targetPath] of Object.entries(componentDirMap)) {
28802
- const componentDir = path36.join(kitInfo.path, component);
28803
- if (fs36.existsSync(componentDir) && fs36.statSync(componentDir).isDirectory()) {
29645
+ const componentDir = path37.join(kitInfo.path, component);
29646
+ if (fs37.existsSync(componentDir) && fs37.statSync(componentDir).isDirectory()) {
28804
29647
  placements.push({
28805
29648
  source: componentDir,
28806
29649
  destination: targetPath,
@@ -28814,8 +29657,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
28814
29657
  }
28815
29658
  function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
28816
29659
  const placements = [];
28817
- const claudeMd = path36.join(kitInfo.path, "CLAUDE.md");
28818
- if (fs36.existsSync(claudeMd)) {
29660
+ const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
29661
+ if (fs37.existsSync(claudeMd)) {
28819
29662
  placements.push({
28820
29663
  source: claudeMd,
28821
29664
  destination: profile.instructions,
@@ -28831,8 +29674,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
28831
29674
  rules: profile.rules
28832
29675
  };
28833
29676
  for (const [component, targetPath] of Object.entries(componentDirMap)) {
28834
- const componentDir = path36.join(kitInfo.path, component);
28835
- if (fs36.existsSync(componentDir) && fs36.statSync(componentDir).isDirectory()) {
29677
+ const componentDir = path37.join(kitInfo.path, component);
29678
+ if (fs37.existsSync(componentDir) && fs37.statSync(componentDir).isDirectory()) {
28836
29679
  placements.push({
28837
29680
  source: componentDir,
28838
29681
  destination: targetPath,
@@ -28846,8 +29689,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
28846
29689
  }
28847
29690
  function collectAllFiles(kitInfo) {
28848
29691
  const files = /* @__PURE__ */ new Map();
28849
- const claudeMd = path36.join(kitInfo.path, "CLAUDE.md");
28850
- if (fs36.existsSync(claudeMd)) {
29692
+ const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
29693
+ if (fs37.existsSync(claudeMd)) {
28851
29694
  files.set("CLAUDE.md", claudeMd);
28852
29695
  }
28853
29696
  for (const [component, reconciliation] of Object.entries(
@@ -28857,15 +29700,15 @@ function collectAllFiles(kitInfo) {
28857
29700
  const missingSet = new Set(reconciliation.missing);
28858
29701
  for (const entry of reconciliation.declared) {
28859
29702
  if (missingSet.has(entry)) continue;
28860
- const relPath = isSkills ? path36.join(component, entry) : path36.join(component, `${entry}.md`);
28861
- files.set(relPath, path36.join(kitInfo.path, relPath));
29703
+ const relPath = isSkills ? path37.join(component, entry) : path37.join(component, `${entry}.md`);
29704
+ files.set(relPath, path37.join(kitInfo.path, relPath));
28862
29705
  }
28863
29706
  }
28864
29707
  return files;
28865
29708
  }
28866
29709
  function isSymlink2(p) {
28867
29710
  try {
28868
- return fs36.lstatSync(p).isSymbolicLink();
29711
+ return fs37.lstatSync(p).isSymbolicLink();
28869
29712
  } catch {
28870
29713
  return false;
28871
29714
  }
@@ -28910,14 +29753,14 @@ async function runKitUpdateCommand(options, logger) {
28910
29753
  }
28911
29754
 
28912
29755
  // src/commands/list.ts
28913
- import path37 from "path";
29756
+ import path38 from "path";
28914
29757
  function runListCommand(options, logger) {
28915
29758
  let searchPaths = [];
28916
- let directKitPath = options.kitPath ? path37.resolve(options.kitPath) : void 0;
29759
+ let directKitPath = options.kitPath ? path38.resolve(options.kitPath) : void 0;
28917
29760
  try {
28918
29761
  const { config, configDir } = resolveConfig(options.config);
28919
29762
  searchPaths = config.kitSearchPaths ?? [
28920
- path37.join(configDir, "operating-kits")
29763
+ path38.join(configDir, "operating-kits")
28921
29764
  ];
28922
29765
  directKitPath = directKitPath ?? config.kitPath;
28923
29766
  } catch (err) {
@@ -28992,7 +29835,7 @@ function withDirectKit(kits, directKitPath) {
28992
29835
  return kits;
28993
29836
  }
28994
29837
  const directKit = loadKit(directKitPath);
28995
- if (kits.some((kit) => path37.resolve(kit.path) === directKit.path)) {
29838
+ if (kits.some((kit) => path38.resolve(kit.path) === directKit.path)) {
28996
29839
  return kits;
28997
29840
  }
28998
29841
  return [...kits, directKit];
@@ -29000,12 +29843,12 @@ function withDirectKit(kits, directKitPath) {
29000
29843
 
29001
29844
  // src/commands/probe.ts
29002
29845
  import { spawnSync as spawnSync2 } from "child_process";
29003
- import fs37 from "fs";
29004
- import path38 from "path";
29846
+ import fs38 from "fs";
29847
+ import path39 from "path";
29005
29848
  function runProbeCommand(options, logger) {
29006
29849
  const { config, configDir, sourceRoot } = resolveRuntime(options, import.meta.url);
29007
29850
  const platformPaths = readYamlObject(
29008
- path38.join(
29851
+ path39.join(
29009
29852
  resolveConfiguredPath(config.mappings, configDir, sourceRoot, "mappings"),
29010
29853
  "platform-paths.yaml"
29011
29854
  )
@@ -29039,12 +29882,12 @@ function toProbeRow(target, key, rawPath) {
29039
29882
  const resolved = resolveTargetPath(rawPath);
29040
29883
  let accessible = false;
29041
29884
  try {
29042
- fs37.accessSync(resolved);
29885
+ fs38.accessSync(resolved);
29043
29886
  accessible = true;
29044
29887
  } catch {
29045
29888
  accessible = false;
29046
29889
  }
29047
- return { target, key, path: resolved, exists: fs37.existsSync(resolved), accessible };
29890
+ return { target, key, path: resolved, exists: fs38.existsSync(resolved), accessible };
29048
29891
  }
29049
29892
  function codexRuntimeProbeRows() {
29050
29893
  const rows = commandProbeRows("codex", "binary", process.platform === "win32" ? "where.exe" : "which", ["codex"]);
@@ -29055,7 +29898,7 @@ function codexRuntimeProbeRows() {
29055
29898
  ["binary_snap", "/snap/bin/codex"],
29056
29899
  ["binary_flatpak", "/var/lib/flatpak/exports/bin/codex"]
29057
29900
  ]) {
29058
- if (fs37.existsSync(candidatePath)) {
29901
+ if (fs38.existsSync(candidatePath)) {
29059
29902
  rows.push(toProbeRow("codex", key, candidatePath));
29060
29903
  }
29061
29904
  }
@@ -29071,8 +29914,8 @@ function commandProbeRows(target, key, command, args) {
29071
29914
 
29072
29915
  // src/commands/status.ts
29073
29916
  import crypto10 from "crypto";
29074
- import fs38 from "fs";
29075
- import path39 from "path";
29917
+ import fs39 from "fs";
29918
+ import path40 from "path";
29076
29919
  function runStatusCommand(options, logger) {
29077
29920
  const { config, configDir, sourceRoot } = resolveRuntime(
29078
29921
  options,
@@ -29151,21 +29994,21 @@ function classifyCodexFiles(config, sourceRoot, configDir) {
29151
29994
  rules: paths.rules
29152
29995
  };
29153
29996
  const rules = compileRules(
29154
- path39.join(sourceRoot, config.source.rules),
29997
+ path40.join(sourceRoot, config.source.rules),
29155
29998
  "codex",
29156
29999
  mappings,
29157
30000
  createLossReport()
29158
30001
  );
29159
- const instructionsSource = fs38.readFileSync(path39.join(sourceRoot, config.source.instructions), "utf8").trim();
30002
+ const instructionsSource = fs39.readFileSync(path40.join(sourceRoot, config.source.instructions), "utf8").trim();
29160
30003
  const composedInstructions = `${instructionsSource}
29161
30004
 
29162
30005
  --- tangyr managed rules ---
29163
30006
  ${rules.agentsAppendix}`.trim();
29164
30007
  const agentFiles = ts(
29165
- path39.join(sourceRoot, config.source.agents, "*.md")
30008
+ path40.join(sourceRoot, config.source.agents, "*.md")
29166
30009
  ).sort();
29167
- const hooksSource = path39.join(sourceRoot, config.source.hooks, "hooks.json");
29168
- const mcpSource = path39.join(sourceRoot, config.source.mcp);
30010
+ const hooksSource = path40.join(sourceRoot, config.source.hooks, "hooks.json");
30011
+ const mcpSource = path40.join(sourceRoot, config.source.mcp);
29169
30012
  const ruleRows = rules.dotRulesFiles.length === 0 ? [
29170
30013
  {
29171
30014
  component: "rules",
@@ -29176,7 +30019,7 @@ ${rules.agentsAppendix}`.trim();
29176
30019
  ] : rules.dotRulesFiles.map(
29177
30020
  (ruleFile) => classifyCompiledFile(
29178
30021
  `rules/${ruleFile.name}`,
29179
- path39.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
30022
+ path40.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
29180
30023
  "codex",
29181
30024
  void 0,
29182
30025
  config,
@@ -29194,10 +30037,10 @@ ${rules.agentsAppendix}`.trim();
29194
30037
  ),
29195
30038
  ...agentFiles.map(
29196
30039
  (agentFile) => classifyCompiledFile(
29197
- `agents/${path39.basename(agentFile, ".md")}`,
29198
- path39.join(
30040
+ `agents/${path40.basename(agentFile, ".md")}`,
30041
+ path40.join(
29199
30042
  resolveTargetPath(codexPaths.agents),
29200
- `${path39.basename(agentFile, ".md")}.toml`
30043
+ `${path40.basename(agentFile, ".md")}.toml`
29201
30044
  ),
29202
30045
  "codex",
29203
30046
  computeSourceHash(agentFile),
@@ -29221,11 +30064,11 @@ ${rules.agentsAppendix}`.trim();
29221
30064
  config,
29222
30065
  sourceRoot
29223
30066
  ),
29224
- fs38.existsSync(hooksSource) ? classifyCodexHooksFile(resolveTargetPath(codexPaths.hooksSharedFile)) : notConfiguredRow(
30067
+ fs39.existsSync(hooksSource) ? classifyCodexHooksFile(resolveTargetPath(codexPaths.hooksSharedFile)) : notConfiguredRow(
29225
30068
  "hooks",
29226
30069
  resolveTargetPath(codexPaths.hooksSharedFile)
29227
30070
  ),
29228
- fs38.existsSync(mcpSource) ? classifyCompiledFile(
30071
+ fs39.existsSync(mcpSource) ? classifyCompiledFile(
29229
30072
  "mcp",
29230
30073
  resolveTargetPath(codexPaths.mcpSharedFile),
29231
30074
  "codex",
@@ -29245,7 +30088,7 @@ function classifyCodexHooksFile(filePath) {
29245
30088
  conformant: true
29246
30089
  };
29247
30090
  }
29248
- if (!fs38.existsSync(filePath)) {
30091
+ if (!fs39.existsSync(filePath)) {
29249
30092
  return {
29250
30093
  component: "hooks",
29251
30094
  className: "missing",
@@ -29277,20 +30120,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
29277
30120
  mcpSharedFile: paths.mcp_shared_file
29278
30121
  };
29279
30122
  const agentFiles = ts(
29280
- path39.join(sourceRoot, config.source.agents, "*.md")
30123
+ path40.join(sourceRoot, config.source.agents, "*.md")
29281
30124
  ).sort();
29282
30125
  const commandFiles = ts(
29283
- path39.join(sourceRoot, config.source.commands, "*.md")
30126
+ path40.join(sourceRoot, config.source.commands, "*.md")
29284
30127
  ).sort();
29285
- const hooksSource = path39.join(sourceRoot, config.source.hooks, "hooks.json");
29286
- const mcpSource = path39.join(sourceRoot, config.source.mcp);
30128
+ const hooksSource = path40.join(sourceRoot, config.source.hooks, "hooks.json");
30129
+ const mcpSource = path40.join(sourceRoot, config.source.mcp);
29287
30130
  return [
29288
30131
  ...agentFiles.map(
29289
30132
  (agentFile) => classifyCompiledFile(
29290
- `agents/${path39.basename(agentFile, ".md")}`,
29291
- path39.join(
30133
+ `agents/${path40.basename(agentFile, ".md")}`,
30134
+ path40.join(
29292
30135
  resolveTargetPath(copilotPaths.agents),
29293
- `${path39.basename(agentFile, ".md")}.agent.md`
30136
+ `${path40.basename(agentFile, ".md")}.agent.md`
29294
30137
  ),
29295
30138
  "copilot",
29296
30139
  computeSourceHash(agentFile),
@@ -29307,10 +30150,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
29307
30150
  ),
29308
30151
  ...commandFiles.map(
29309
30152
  (commandFile) => classifyCompiledFile(
29310
- `commands/${path39.basename(commandFile, ".md")}`,
29311
- path39.join(
30153
+ `commands/${path40.basename(commandFile, ".md")}`,
30154
+ path40.join(
29312
30155
  resolveTargetPath(copilotPaths.prompts),
29313
- `${path39.basename(commandFile, ".md")}.prompt.md`
30156
+ `${path40.basename(commandFile, ".md")}.prompt.md`
29314
30157
  ),
29315
30158
  "copilot",
29316
30159
  computeSourceHash(commandFile),
@@ -29328,9 +30171,9 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
29328
30171
  config,
29329
30172
  sourceRoot
29330
30173
  ),
29331
- fs38.existsSync(hooksSource) ? classifyCompiledFile(
30174
+ fs39.existsSync(hooksSource) ? classifyCompiledFile(
29332
30175
  "hooks",
29333
- path39.join(
30176
+ path40.join(
29334
30177
  resolveTargetPath(copilotPaths.hooks),
29335
30178
  "tangyr-managed.json"
29336
30179
  ),
@@ -29340,12 +30183,12 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
29340
30183
  sourceRoot
29341
30184
  ) : notConfiguredRow(
29342
30185
  "hooks",
29343
- path39.join(
30186
+ path40.join(
29344
30187
  resolveTargetPath(copilotPaths.hooks),
29345
30188
  "tangyr-managed.json"
29346
30189
  )
29347
30190
  ),
29348
- fs38.existsSync(mcpSource) ? classifyCompiledFile(
30191
+ fs39.existsSync(mcpSource) ? classifyCompiledFile(
29349
30192
  "mcp",
29350
30193
  resolveTargetPath(copilotPaths.mcpSharedFile),
29351
30194
  "copilot",
@@ -29365,7 +30208,7 @@ function notConfiguredRow(component, filePath) {
29365
30208
  }
29366
30209
  function classifyDirectArtifact(artifact, config, sourceRoot) {
29367
30210
  const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
29368
- const sourcePath = artifact.sourceKey ? path39.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
30211
+ const sourcePath = artifact.sourceKey ? path40.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
29369
30212
  if (artifactClass === "managed-symlink" && sourcePath && !isSymlinkCurrent(artifact.path, sourcePath)) {
29370
30213
  return {
29371
30214
  component: artifact.component,
@@ -29454,9 +30297,9 @@ function classifyClaudeSharedFiles(config, sourceRoot) {
29454
30297
  classifyHooks(settingsPath),
29455
30298
  classifySettings(
29456
30299
  settingsPath,
29457
- path39.resolve(sourceRoot, config.source.settings)
30300
+ path40.resolve(sourceRoot, config.source.settings)
29458
30301
  ),
29459
- classifyMcp(claudeJsonPath, path39.resolve(sourceRoot, config.source.mcp))
30302
+ classifyMcp(claudeJsonPath, path40.resolve(sourceRoot, config.source.mcp))
29460
30303
  ];
29461
30304
  }
29462
30305
  function classifyHooks(filePath) {
@@ -29520,14 +30363,14 @@ function classifyMcp(filePath, sourcePath) {
29520
30363
  }
29521
30364
  function isSymlinkCurrent(linkPath, sourcePath) {
29522
30365
  try {
29523
- return fs38.realpathSync(linkPath) === fs38.realpathSync(sourcePath);
30366
+ return fs39.realpathSync(linkPath) === fs39.realpathSync(sourcePath);
29524
30367
  } catch {
29525
30368
  return false;
29526
30369
  }
29527
30370
  }
29528
30371
  function isCompiledCurrent6(filePath, sourcePath) {
29529
30372
  try {
29530
- const marker = extractProvenanceMarker(fs38.readFileSync(filePath, "utf8"));
30373
+ const marker = extractProvenanceMarker(fs39.readFileSync(filePath, "utf8"));
29531
30374
  return marker?.hash === computeSourceHash(sourcePath) && marker.target === "claude-code";
29532
30375
  } catch {
29533
30376
  return false;
@@ -29557,7 +30400,7 @@ function classifyCompiledFile(component, filePath, target, expectedHash, config,
29557
30400
  }
29558
30401
  function readCompiledContent(filePath) {
29559
30402
  try {
29560
- return fs38.readFileSync(filePath, "utf8");
30403
+ return fs39.readFileSync(filePath, "utf8");
29561
30404
  } catch {
29562
30405
  return null;
29563
30406
  }
@@ -30103,145 +30946,6 @@ function buildAgentsMdShim(shimPath, _agentsMdPath, target) {
30103
30946
  ${SHIM_BODY}`;
30104
30947
  }
30105
30948
 
30106
- // src/compiler/hook-components.ts
30107
- var import_yaml11 = __toESM(require_dist(), 1);
30108
- import fs39 from "fs";
30109
- import path40 from "path";
30110
- function parseHookDeclaration(filePath) {
30111
- let raw;
30112
- try {
30113
- raw = fs39.readFileSync(filePath, "utf8");
30114
- } catch {
30115
- return null;
30116
- }
30117
- const fm = extractFrontmatter(raw);
30118
- if (!fm) {
30119
- return null;
30120
- }
30121
- const { name, description, events } = fm;
30122
- if (typeof name !== "string" || !name.trim()) {
30123
- return null;
30124
- }
30125
- if (typeof description !== "string" || !description.trim()) {
30126
- return null;
30127
- }
30128
- if (!Array.isArray(events) || events.length === 0) {
30129
- return null;
30130
- }
30131
- const parsedEvents = [];
30132
- for (const entry of events) {
30133
- if (!entry || typeof entry !== "object") {
30134
- return null;
30135
- }
30136
- const ev = entry;
30137
- if (typeof ev.event !== "string" || !ev.event.trim()) {
30138
- return null;
30139
- }
30140
- if (typeof ev.timeout !== "number") {
30141
- return null;
30142
- }
30143
- if (typeof ev.statusMessage !== "string" || !ev.statusMessage.trim()) {
30144
- return null;
30145
- }
30146
- const parsed = {
30147
- event: ev.event,
30148
- timeout: ev.timeout,
30149
- statusMessage: ev.statusMessage
30150
- };
30151
- if (typeof ev.matcher === "string" && ev.matcher.trim()) {
30152
- parsed.matcher = ev.matcher;
30153
- }
30154
- parsedEvents.push(parsed);
30155
- }
30156
- return {
30157
- name: name.trim(),
30158
- description: description.trim(),
30159
- events: parsedEvents
30160
- };
30161
- }
30162
- function hookCommand(name) {
30163
- return `npx tsx ~/.agents/hooks/scripts/${name}.ts`;
30164
- }
30165
- function synthesizeHooksJson(declarations) {
30166
- const hooks = {};
30167
- for (const decl of declarations) {
30168
- for (const ev of decl.events) {
30169
- if (!hooks[ev.event]) {
30170
- hooks[ev.event] = [];
30171
- }
30172
- const entry = {
30173
- hooks: [
30174
- {
30175
- type: "command",
30176
- command: hookCommand(decl.name),
30177
- timeout: ev.timeout,
30178
- statusMessage: ev.statusMessage
30179
- }
30180
- ]
30181
- };
30182
- if (ev.matcher !== void 0) {
30183
- const ordered = {
30184
- matcher: ev.matcher,
30185
- hooks: entry.hooks
30186
- };
30187
- hooks[ev.event].push(ordered);
30188
- } else {
30189
- hooks[ev.event].push(entry);
30190
- }
30191
- }
30192
- }
30193
- return { hooks };
30194
- }
30195
- function loadSourceHooks(hooksDir, hookNames) {
30196
- const hooksJsonPath = path40.join(hooksDir, "hooks.json");
30197
- if (fs39.existsSync(hooksJsonPath)) {
30198
- const raw = fs39.readFileSync(hooksJsonPath, "utf8");
30199
- return JSON.parse(raw);
30200
- }
30201
- const declarations = loadHookDeclarations(hooksDir, hookNames);
30202
- return synthesizeHooksJson(declarations);
30203
- }
30204
- function loadHookDeclarations(hooksDir, hookNames) {
30205
- let names;
30206
- if (hookNames && hookNames.length > 0) {
30207
- names = hookNames;
30208
- } else {
30209
- if (!fs39.existsSync(hooksDir) || !fs39.statSync(hooksDir).isDirectory()) {
30210
- return [];
30211
- }
30212
- names = fs39.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
30213
- }
30214
- const declarations = [];
30215
- for (const name of names) {
30216
- const filePath = path40.join(hooksDir, `${name}.md`);
30217
- const decl = parseHookDeclaration(filePath);
30218
- if (decl) {
30219
- declarations.push(decl);
30220
- }
30221
- }
30222
- return declarations;
30223
- }
30224
- function extractFrontmatter(content) {
30225
- if (!content.startsWith("---\n")) {
30226
- return null;
30227
- }
30228
- const endIndex = content.indexOf("\n---", 4);
30229
- if (endIndex === -1) {
30230
- return null;
30231
- }
30232
- const rawFm = content.slice(4, endIndex);
30233
- let parsed;
30234
- try {
30235
- parsed = (0, import_yaml11.parse)(rawFm);
30236
- } catch {
30237
- return null;
30238
- }
30239
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
30240
- return null;
30241
- }
30242
- return parsed;
30243
- }
30244
-
30245
30949
  // src/adapters/claude-code.ts
30246
30950
  function buildDirectComponents(profile) {
30247
30951
  return [