@alessandroraffa/tangyr 9.0.0 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +529 -287
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16362,8 +16362,8 @@ function assertSupportedNodeRuntime(nodeVersion = process.version) {
16362
16362
  }
16363
16363
 
16364
16364
  // src/commands/assess.ts
16365
- import fs12 from "fs";
16366
- import path14 from "path";
16365
+ import fs13 from "fs";
16366
+ import path15 from "path";
16367
16367
 
16368
16368
  // src/core/scope.ts
16369
16369
  import fs7 from "fs";
@@ -17263,22 +17263,107 @@ function toPosixRelativePath(root, filePath) {
17263
17263
  return path11.relative(root, filePath).split(path11.sep).join(path11.posix.sep);
17264
17264
  }
17265
17265
 
17266
+ // src/core/managed-sources.ts
17267
+ var import_yaml5 = __toESM(require_dist(), 1);
17268
+ import fs11 from "fs";
17269
+ import path12 from "path";
17270
+ function resolveKitComponentNames(sourceRoot, category) {
17271
+ const manifestPath = path12.resolve(sourceRoot, "tangyr-kit.yaml");
17272
+ if (!fs11.existsSync(manifestPath)) {
17273
+ return void 0;
17274
+ }
17275
+ try {
17276
+ const raw = fs11.readFileSync(manifestPath, "utf8");
17277
+ const doc = (0, import_yaml5.parse)(raw);
17278
+ if (doc && typeof doc === "object" && !Array.isArray(doc) && "components" in doc) {
17279
+ const components = doc.components;
17280
+ if (components && typeof components === "object" && !Array.isArray(components) && category in components) {
17281
+ const names = components[category];
17282
+ if (Array.isArray(names) && names.every((n7) => typeof n7 === "string")) {
17283
+ return names;
17284
+ }
17285
+ }
17286
+ }
17287
+ } catch {
17288
+ }
17289
+ return void 0;
17290
+ }
17291
+ function resolveKitHookNames(sourceRoot) {
17292
+ return resolveKitComponentNames(sourceRoot, "hooks");
17293
+ }
17294
+ function resolveKitSkillNames(sourceRoot) {
17295
+ return resolveKitComponentNames(sourceRoot, "skills");
17296
+ }
17297
+ function resolveKitSlotNames(sourceRoot, category) {
17298
+ return resolveKitComponentNames(sourceRoot, category);
17299
+ }
17300
+ function resolveKitEntrypointName(sourceRoot) {
17301
+ const manifestPath = path12.resolve(sourceRoot, "tangyr-kit.yaml");
17302
+ if (!fs11.existsSync(manifestPath)) {
17303
+ return void 0;
17304
+ }
17305
+ try {
17306
+ const doc = (0, import_yaml5.parse)(fs11.readFileSync(manifestPath, "utf8"));
17307
+ if (doc && typeof doc === "object" && !Array.isArray(doc)) {
17308
+ const value = doc.entrypoint;
17309
+ if (typeof value === "string" && value.trim().length > 0) {
17310
+ return value.trim();
17311
+ }
17312
+ }
17313
+ } catch {
17314
+ }
17315
+ return void 0;
17316
+ }
17317
+ function resolveHooksSourceFile(sourceRoot, config) {
17318
+ return path12.resolve(sourceRoot, config.source.hooks, "hooks.json");
17319
+ }
17320
+ function resolveHooksSourceDir(sourceRoot, config) {
17321
+ return path12.resolve(sourceRoot, config.source.hooks);
17322
+ }
17323
+ function hooksSourceExists(sourceRoot, config) {
17324
+ const hooksJsonPath = resolveHooksSourceFile(sourceRoot, config);
17325
+ if (fs11.existsSync(hooksJsonPath)) {
17326
+ return true;
17327
+ }
17328
+ const hooksDir = resolveHooksSourceDir(sourceRoot, config);
17329
+ if (!fs11.existsSync(hooksDir) || !fs11.statSync(hooksDir).isDirectory()) {
17330
+ return false;
17331
+ }
17332
+ return fs11.readdirSync(hooksDir).some((f) => f.endsWith(".md") && !f.startsWith("."));
17333
+ }
17334
+ function hooksSourceLabel(sourceRoot, config) {
17335
+ const dir = normalizeManagedSourcePath(
17336
+ config.source.hooks.replace(/\\/gu, "/")
17337
+ );
17338
+ return fs11.existsSync(resolveHooksSourceFile(sourceRoot, config)) ? path12.posix.join(dir, "hooks.json") : `${dir}/`;
17339
+ }
17340
+ function resolveMcpSourceFile(sourceRoot, config) {
17341
+ return path12.resolve(sourceRoot, config.source.mcp);
17342
+ }
17343
+ function mcpSourceLabel(config) {
17344
+ return normalizeManagedSourcePath(config.source.mcp);
17345
+ }
17346
+ function normalizeManagedSourcePath(rawPath) {
17347
+ const normalized = rawPath.replace(/\\/gu, "/");
17348
+ return normalized.startsWith("./") ? normalized.slice(2) : normalized;
17349
+ }
17350
+
17266
17351
  // src/core/foreign-instructions.ts
17267
- import path13 from "path";
17352
+ import path14 from "path";
17268
17353
 
17269
17354
  // src/core/contested-instructions.ts
17270
- import fs11 from "fs";
17271
- import path12 from "path";
17355
+ import fs12 from "fs";
17356
+ import path13 from "path";
17272
17357
  var FOLDS_RULES_INTO_INSTRUCTIONS = {
17273
17358
  codex: "its own rules slot takes only exec-policy rules, so guidance rules are folded in",
17274
17359
  opencode: "it has no rules slot of its own, so every rule is folded in"
17275
17360
  };
17276
17361
  function markerTarget(destination) {
17277
17362
  try {
17278
- if (fs11.lstatSync(destination).isSymbolicLink()) {
17363
+ if (fs12.lstatSync(destination).isSymbolicLink()) {
17279
17364
  return null;
17280
17365
  }
17281
- const firstNonEmpty = fs11.readFileSync(destination, "utf8").split("\n").find((line) => line.trim().length > 0) ?? "";
17366
+ const firstNonEmpty = fs12.readFileSync(destination, "utf8").split("\n").find((line) => line.trim().length > 0) ?? "";
17282
17367
  return extractProvenanceMarker(firstNonEmpty)?.target ?? null;
17283
17368
  } catch {
17284
17369
  return null;
@@ -17287,7 +17372,7 @@ function markerTarget(destination) {
17287
17372
  function findContestedInstructions(instructionsByTarget) {
17288
17373
  const byPath = /* @__PURE__ */ new Map();
17289
17374
  for (const [target, destination] of instructionsByTarget) {
17290
- const resolved = path12.resolve(destination);
17375
+ const resolved = path13.resolve(destination);
17291
17376
  byPath.set(resolved, [...byPath.get(resolved) ?? [], target]);
17292
17377
  }
17293
17378
  const contested = [];
@@ -17349,7 +17434,7 @@ function instructionsByActiveTarget(tools, scope, projectRoot, mappings) {
17349
17434
  }
17350
17435
  }
17351
17436
  if (scope === "project" && projectRoot && tools.includes("copilot")) {
17352
- byTarget.set("copilot", path12.join(projectRoot, "AGENTS.md"));
17437
+ byTarget.set("copilot", path13.join(projectRoot, "AGENTS.md"));
17353
17438
  }
17354
17439
  return byTarget;
17355
17440
  }
@@ -17358,7 +17443,7 @@ function instructionsByActiveTarget(tools, scope, projectRoot, mappings) {
17358
17443
  function instructionsEntrypoints(tools, scope, projectRoot, mappings) {
17359
17444
  const byPath = /* @__PURE__ */ new Map();
17360
17445
  const add = (destination, tool) => {
17361
- const resolved2 = path13.resolve(destination);
17446
+ const resolved2 = path14.resolve(destination);
17362
17447
  const targets = byPath.get(resolved2) ?? [];
17363
17448
  if (!targets.includes(tool)) {
17364
17449
  targets.push(tool);
@@ -17389,7 +17474,7 @@ function instructionsEntrypoints(tools, scope, projectRoot, mappings) {
17389
17474
  function findForeignInstructions(conflicting, entrypoints) {
17390
17475
  const found2 = /* @__PURE__ */ new Map();
17391
17476
  for (const finding of conflicting) {
17392
- const resolved = path13.resolve(finding.path);
17477
+ const resolved = path14.resolve(finding.path);
17393
17478
  const targets = entrypoints.get(resolved);
17394
17479
  if (targets && !found2.has(resolved)) {
17395
17480
  found2.set(resolved, { path: resolved, targets });
@@ -17402,7 +17487,7 @@ function describeForeignInstructions(foreign, projectRoot) {
17402
17487
  if (!projectRoot) {
17403
17488
  return target;
17404
17489
  }
17405
- const relative = path13.relative(projectRoot, target);
17490
+ const relative = path14.relative(projectRoot, target);
17406
17491
  return relative.startsWith("..") ? target : relative;
17407
17492
  };
17408
17493
  const width = Math.max(...foreign.map((one) => display2(one.path).length));
@@ -17549,10 +17634,10 @@ function collectAssessFindings(scope, projectRoot, toolFilter, assessOptions) {
17549
17634
  }
17550
17635
  for (const target of probe.paths) {
17551
17636
  const resolvedPath = resolveTargetPath(target.path);
17552
- if (!fs12.existsSync(resolvedPath)) {
17637
+ if (!fs13.existsSync(resolvedPath)) {
17553
17638
  continue;
17554
17639
  }
17555
- const stat = fs12.lstatSync(resolvedPath);
17640
+ const stat = fs13.lstatSync(resolvedPath);
17556
17641
  findings.push({
17557
17642
  path: resolvedPath,
17558
17643
  tool: probe.tool,
@@ -17580,16 +17665,17 @@ function collectAssessFindings(scope, projectRoot, toolFilter, assessOptions) {
17580
17665
  if (finding.classification !== "conflicting") {
17581
17666
  continue;
17582
17667
  }
17583
- const resolved = path14.resolve(finding.path);
17668
+ const resolved = path15.resolve(finding.path);
17584
17669
  const ours = recorded.has(resolved) || finding.type === "directory" && holdsOnlyRecorded(resolved, recorded);
17585
17670
  if (ours) {
17586
17671
  finding.classification = "compatible";
17587
17672
  finding.description = `${finding.description} (recorded by this installation)`;
17588
17673
  }
17589
17674
  }
17590
- if (fs12.existsSync(path14.join(scopePath, "manifest.json"))) {
17675
+ expandPerEntrySlots(findings, recorded, scope, projectRoot, assessOptions);
17676
+ if (fs13.existsSync(path15.join(scopePath, "manifest.json"))) {
17591
17677
  findings.push({
17592
- path: path14.join(scopePath, "manifest.json"),
17678
+ path: path15.join(scopePath, "manifest.json"),
17593
17679
  tool: "tangyr",
17594
17680
  type: "file",
17595
17681
  classification: "compatible",
@@ -17733,7 +17819,7 @@ function collectProjectScopeFindings(projectRoot, tools, options) {
17733
17819
  for (const { resolvedPath, description, classification } of probePaths) {
17734
17820
  let stat;
17735
17821
  try {
17736
- stat = fs12.lstatSync(resolvedPath);
17822
+ stat = fs13.lstatSync(resolvedPath);
17737
17823
  } catch {
17738
17824
  continue;
17739
17825
  }
@@ -17750,6 +17836,87 @@ function collectProjectScopeFindings(projectRoot, tools, options) {
17750
17836
  }
17751
17837
  return findings;
17752
17838
  }
17839
+ function expandPerEntrySlots(findings, recorded, scope, projectRoot, options) {
17840
+ const slots = perEntrySlotPaths(scope, projectRoot, options);
17841
+ if (slots.size === 0) {
17842
+ return;
17843
+ }
17844
+ for (let index = findings.length - 1; index >= 0; index--) {
17845
+ const finding = findings[index];
17846
+ if (finding.classification !== "conflicting" || finding.type !== "directory" || !slots.has(path15.resolve(finding.path))) {
17847
+ continue;
17848
+ }
17849
+ const wanted = slots.get(path15.resolve(finding.path)) ?? /* @__PURE__ */ new Set();
17850
+ let entries;
17851
+ try {
17852
+ entries = fs13.readdirSync(finding.path);
17853
+ } catch {
17854
+ continue;
17855
+ }
17856
+ const foreign = entries.filter((entry) => wanted.has(entry)).map((entry) => path15.join(finding.path, entry)).filter((entry) => !recorded.has(path15.resolve(entry))).filter((entry) => !carriesProvenanceMarker(entry));
17857
+ findings.splice(
17858
+ index,
17859
+ 1,
17860
+ ...foreign.map((entry) => ({
17861
+ path: entry,
17862
+ tool: finding.tool,
17863
+ type: "file",
17864
+ classification: "conflicting",
17865
+ description: `${finding.description} \u2014 this entry is not ours`
17866
+ }))
17867
+ );
17868
+ }
17869
+ }
17870
+ function perEntrySlotPaths(scope, projectRoot, options) {
17871
+ const slots = /* @__PURE__ */ new Map();
17872
+ let config;
17873
+ let configDir;
17874
+ let kitPath;
17875
+ try {
17876
+ ({ config, configDir } = resolveConfig(options.config));
17877
+ kitPath = resolveKitPath(config, configDir);
17878
+ if (!kitPath) {
17879
+ return slots;
17880
+ }
17881
+ } catch {
17882
+ return slots;
17883
+ }
17884
+ let profile;
17885
+ try {
17886
+ profile = resolveTargetPaths({
17887
+ scope,
17888
+ projectRoot,
17889
+ mappings: loadMappings(kitPath, config, configDir).platformPaths
17890
+ })["claude-code"];
17891
+ } catch {
17892
+ return slots;
17893
+ }
17894
+ const kit = kitPath;
17895
+ const named = (slot, category, sourceKey, extension) => {
17896
+ if (typeof slot !== "string") {
17897
+ return;
17898
+ }
17899
+ const source = path15.resolve(kit, String(config.source[sourceKey]));
17900
+ const declared = resolveKitSlotNames(kit, category);
17901
+ const names = declared?.map((name) => `${name}${extension}`) ?? listSourceEntries(source, extension);
17902
+ slots.set(path15.resolve(slot), new Set(names));
17903
+ };
17904
+ named(profile.agents, "agents", "agents", ".md");
17905
+ named(profile.commands, "commands", "commands", ".md");
17906
+ named(profile.rules, "rules", "rules", ".md");
17907
+ named(profile.output_styles, "output-styles", "outputStyles", ".md");
17908
+ named(profile.skills, "skills", "skills", "");
17909
+ return slots;
17910
+ }
17911
+ function listSourceEntries(source, extension) {
17912
+ try {
17913
+ return fs13.readdirSync(source, { withFileTypes: true }).filter((entry) => !entry.name.startsWith(".")).filter(
17914
+ (entry) => extension === "" ? entry.isDirectory() : entry.isFile() && entry.name.endsWith(extension)
17915
+ ).map((entry) => entry.name);
17916
+ } catch {
17917
+ return [];
17918
+ }
17919
+ }
17753
17920
  function requestedAssessTools(toolFilter) {
17754
17921
  return toolFilter ?? [...DEFAULT_ASSESS_TARGETS];
17755
17922
  }
@@ -17784,7 +17951,7 @@ function alwaysOnProjectFiles(tool, projectRoot) {
17784
17951
  if (tool === "claude-code") {
17785
17952
  return [
17786
17953
  {
17787
- resolvedPath: path14.resolve(projectRoot, "CLAUDE.md"),
17954
+ resolvedPath: path15.resolve(projectRoot, "CLAUDE.md"),
17788
17955
  description: "Project-level Claude instructions",
17789
17956
  classification: "conflicting"
17790
17957
  }
@@ -17793,7 +17960,7 @@ function alwaysOnProjectFiles(tool, projectRoot) {
17793
17960
  if (tool === "copilot") {
17794
17961
  return [
17795
17962
  {
17796
- resolvedPath: path14.resolve(
17963
+ resolvedPath: path15.resolve(
17797
17964
  projectRoot,
17798
17965
  ".github/copilot-instructions.md"
17799
17966
  ),
@@ -17805,7 +17972,7 @@ function alwaysOnProjectFiles(tool, projectRoot) {
17805
17972
  if (tool === "codex") {
17806
17973
  return [
17807
17974
  {
17808
- resolvedPath: path14.resolve(projectRoot, "AGENTS.md"),
17975
+ resolvedPath: path15.resolve(projectRoot, "AGENTS.md"),
17809
17976
  description: "Codex project instructions",
17810
17977
  classification: "conflicting"
17811
17978
  }
@@ -17842,11 +18009,11 @@ function recordedArtifactPaths(scopePath) {
17842
18009
  }
17843
18010
  for (const artifact of manifest.artifacts) {
17844
18011
  if (artifact.path) {
17845
- paths.add(path14.resolve(artifact.path));
18012
+ paths.add(path15.resolve(artifact.path));
17846
18013
  }
17847
18014
  }
17848
18015
  for (const link of manifest.managedLinks) {
17849
- paths.add(path14.resolve(link.path));
18016
+ paths.add(path15.resolve(link.path));
17850
18017
  }
17851
18018
  } catch {
17852
18019
  }
@@ -17855,15 +18022,15 @@ function recordedArtifactPaths(scopePath) {
17855
18022
  function holdsOnlyRecorded(dir, recorded) {
17856
18023
  let entries;
17857
18024
  try {
17858
- entries = fs12.readdirSync(dir, { withFileTypes: true });
18025
+ entries = fs13.readdirSync(dir, { withFileTypes: true });
17859
18026
  } catch {
17860
18027
  return false;
17861
18028
  }
17862
18029
  if (entries.length === 0) {
17863
- return [...recorded].some((p) => p.startsWith(`${dir}${path14.sep}`));
18030
+ return [...recorded].some((p) => p.startsWith(`${dir}${path15.sep}`));
17864
18031
  }
17865
18032
  for (const entry of entries) {
17866
- const full = path14.join(dir, entry.name);
18033
+ const full = path15.join(dir, entry.name);
17867
18034
  if (entry.isDirectory() && !entry.isSymbolicLink()) {
17868
18035
  if (!holdsOnlyRecorded(full, recorded)) {
17869
18036
  return false;
@@ -17878,7 +18045,7 @@ function holdsOnlyRecorded(dir, recorded) {
17878
18045
  }
17879
18046
 
17880
18047
  // src/commands/auth.ts
17881
- import fs15 from "fs";
18048
+ import fs16 from "fs";
17882
18049
 
17883
18050
  // src/core/transport.ts
17884
18051
  var KIT_CONTRACT_VERSION = "1";
@@ -17967,11 +18134,11 @@ function createFetchKitTransport(options = {}) {
17967
18134
  }
17968
18135
 
17969
18136
  // src/core/credentials.ts
17970
- import fs13 from "fs";
18137
+ import fs14 from "fs";
17971
18138
  import os3 from "os";
17972
- import path15 from "path";
17973
- var CREDENTIALS_DIR = path15.join(os3.homedir(), ".tangyr");
17974
- var CREDENTIALS_PATH = path15.join(CREDENTIALS_DIR, "credentials.json");
18139
+ import path16 from "path";
18140
+ var CREDENTIALS_DIR = path16.join(os3.homedir(), ".tangyr");
18141
+ var CREDENTIALS_PATH = path16.join(CREDENTIALS_DIR, "credentials.json");
17975
18142
  function isCurrentCredentialRecord(value) {
17976
18143
  if (typeof value !== "object" || value === null) {
17977
18144
  return false;
@@ -17980,10 +18147,10 @@ function isCurrentCredentialRecord(value) {
17980
18147
  return record.schema === 2 && typeof record.clientId === "string" && record.clientId.length > 0 && typeof record.clientSecret === "string" && record.clientSecret.length > 0 && (record.validation === "validated" || record.validation === "unvalidated") && typeof record.storedAt === "string";
17981
18148
  }
17982
18149
  function readStoredCredentials() {
17983
- if (!fs13.existsSync(CREDENTIALS_PATH)) {
18150
+ if (!fs14.existsSync(CREDENTIALS_PATH)) {
17984
18151
  return null;
17985
18152
  }
17986
- const raw = fs13.readFileSync(CREDENTIALS_PATH, "utf8");
18153
+ const raw = fs14.readFileSync(CREDENTIALS_PATH, "utf8");
17987
18154
  const parsed = JSON.parse(raw);
17988
18155
  if (!isCurrentCredentialRecord(parsed)) {
17989
18156
  throw new CredentialsLegacyError();
@@ -17993,13 +18160,13 @@ function readStoredCredentials() {
17993
18160
  function ensureCredentialsDir(logger) {
17994
18161
  let created = false;
17995
18162
  try {
17996
- created = fs13.mkdirSync(CREDENTIALS_DIR, { recursive: true, mode: 448 }) !== void 0;
18163
+ created = fs14.mkdirSync(CREDENTIALS_DIR, { recursive: true, mode: 448 }) !== void 0;
17997
18164
  } catch (err) {
17998
18165
  if (err.code !== "EEXIST") {
17999
18166
  throw err;
18000
18167
  }
18001
18168
  }
18002
- if (fs13.lstatSync(CREDENTIALS_DIR).isSymbolicLink()) {
18169
+ if (fs14.lstatSync(CREDENTIALS_DIR).isSymbolicLink()) {
18003
18170
  throw new Error(
18004
18171
  `Refusing to write credentials: "${CREDENTIALS_DIR}" already exists as a symbolic link, not a directory. Remove it and run 'tangyr auth login' again.`
18005
18172
  );
@@ -18013,7 +18180,7 @@ function ensureCredentialsDir(logger) {
18013
18180
  return;
18014
18181
  }
18015
18182
  try {
18016
- fs13.chmodSync(CREDENTIALS_DIR, 448);
18183
+ fs14.chmodSync(CREDENTIALS_DIR, 448);
18017
18184
  } catch {
18018
18185
  logger.warn(
18019
18186
  "Could not set owner-only (0700) permissions on the credentials directory on this platform; at-rest protection is reduced (REQ-AUT-007)."
@@ -18026,41 +18193,41 @@ function writeStoredCredentials(record, logger) {
18026
18193
  `;
18027
18194
  const tmpPath = `${CREDENTIALS_PATH}.tmp`;
18028
18195
  try {
18029
- fs13.writeFileSync(tmpPath, content, { mode: 384, flag: "wx" });
18196
+ fs14.writeFileSync(tmpPath, content, { mode: 384, flag: "wx" });
18030
18197
  } catch (err) {
18031
18198
  if (err.code === "EEXIST") {
18032
- fs13.unlinkSync(tmpPath);
18033
- fs13.writeFileSync(tmpPath, content, { mode: 384, flag: "wx" });
18199
+ fs14.unlinkSync(tmpPath);
18200
+ fs14.writeFileSync(tmpPath, content, { mode: 384, flag: "wx" });
18034
18201
  } else {
18035
18202
  throw err;
18036
18203
  }
18037
18204
  }
18038
18205
  try {
18039
- fs13.renameSync(tmpPath, CREDENTIALS_PATH);
18206
+ fs14.renameSync(tmpPath, CREDENTIALS_PATH);
18040
18207
  } catch (renameErr) {
18041
18208
  try {
18042
18209
  try {
18043
- const destStat = fs13.lstatSync(CREDENTIALS_PATH);
18210
+ const destStat = fs14.lstatSync(CREDENTIALS_PATH);
18044
18211
  if (destStat.isSymbolicLink()) {
18045
- fs13.unlinkSync(CREDENTIALS_PATH);
18212
+ fs14.unlinkSync(CREDENTIALS_PATH);
18046
18213
  }
18047
18214
  } catch {
18048
18215
  }
18049
- fs13.copyFileSync(tmpPath, CREDENTIALS_PATH);
18216
+ fs14.copyFileSync(tmpPath, CREDENTIALS_PATH);
18050
18217
  try {
18051
- fs13.chmodSync(CREDENTIALS_PATH, 384);
18218
+ fs14.chmodSync(CREDENTIALS_PATH, 384);
18052
18219
  } catch {
18053
18220
  logger.warn(
18054
18221
  "Could not set owner-only (0600) permissions on the credentials file on this platform; at-rest protection is reduced (REQ-AUT-007)."
18055
18222
  );
18056
18223
  }
18057
18224
  try {
18058
- fs13.unlinkSync(tmpPath);
18225
+ fs14.unlinkSync(tmpPath);
18059
18226
  } catch {
18060
18227
  }
18061
18228
  } catch (copyErr) {
18062
18229
  try {
18063
- fs13.unlinkSync(tmpPath);
18230
+ fs14.unlinkSync(tmpPath);
18064
18231
  } catch {
18065
18232
  }
18066
18233
  throw new Error(
@@ -18105,16 +18272,16 @@ function resolveCredentialNonInteractive() {
18105
18272
  }
18106
18273
 
18107
18274
  // src/core/freshness.ts
18108
- import fs14 from "fs";
18109
- import path16 from "path";
18275
+ import fs15 from "fs";
18276
+ import path17 from "path";
18110
18277
  var AUTHORIZATION_FRESHNESS_TTL_MS = 24 * 60 * 60 * 1e3;
18111
18278
  var FRESHNESS_STATE_FILENAME = ".tangyr-freshness.json";
18112
18279
  function resolveFreshnessStatePath(cacheRoot) {
18113
- return path16.join(cacheRoot, FRESHNESS_STATE_FILENAME);
18280
+ return path17.join(cacheRoot, FRESHNESS_STATE_FILENAME);
18114
18281
  }
18115
18282
  function readFreshnessStateFile(statePath) {
18116
18283
  try {
18117
- const raw = fs14.readFileSync(statePath, "utf8");
18284
+ const raw = fs15.readFileSync(statePath, "utf8");
18118
18285
  const parsed = JSON.parse(raw);
18119
18286
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
18120
18287
  return {};
@@ -18134,13 +18301,13 @@ function readLastAuthorizedAt(cacheRoot, originUrl) {
18134
18301
  return Number.isNaN(parsed.getTime()) ? void 0 : parsed;
18135
18302
  }
18136
18303
  function writeLastAuthorizedAt(cacheRoot, originUrl, at2) {
18137
- fs14.mkdirSync(cacheRoot, { recursive: true, mode: 448 });
18304
+ fs15.mkdirSync(cacheRoot, { recursive: true, mode: 448 });
18138
18305
  const statePath = resolveFreshnessStatePath(cacheRoot);
18139
18306
  const state = readFreshnessStateFile(statePath);
18140
18307
  state[originUrl] = at2.toISOString();
18141
18308
  const tmpPath = `${statePath}.tmp`;
18142
- fs14.writeFileSync(tmpPath, JSON.stringify(state), { mode: 384 });
18143
- fs14.renameSync(tmpPath, statePath);
18309
+ fs15.writeFileSync(tmpPath, JSON.stringify(state), { mode: 384 });
18310
+ fs15.renameSync(tmpPath, statePath);
18144
18311
  }
18145
18312
  function isWithinFreshnessWindow(lastAuthorizedAt, now) {
18146
18313
  if (lastAuthorizedAt === void 0) {
@@ -18361,21 +18528,21 @@ async function runAuthStatusCommand(options, logger, transport = createFetchKitT
18361
18528
  }
18362
18529
  }
18363
18530
  function runAuthLogoutCommand(_options, logger) {
18364
- if (!fs15.existsSync(CREDENTIALS_PATH)) {
18531
+ if (!fs16.existsSync(CREDENTIALS_PATH)) {
18365
18532
  logger.info("No credential found. Nothing to remove.");
18366
18533
  return;
18367
18534
  }
18368
- fs15.unlinkSync(CREDENTIALS_PATH);
18535
+ fs16.unlinkSync(CREDENTIALS_PATH);
18369
18536
  logger.info("Credential removed.");
18370
18537
  }
18371
18538
 
18372
18539
  // src/commands/cache.ts
18373
- import fs17 from "fs";
18374
- import path18 from "path";
18540
+ import fs18 from "fs";
18541
+ import path19 from "path";
18375
18542
 
18376
18543
  // src/core/cache.ts
18377
- import fs16 from "fs";
18378
- import path17 from "path";
18544
+ import fs17 from "fs";
18545
+ import path18 from "path";
18379
18546
 
18380
18547
  // src/core/kit-reference.ts
18381
18548
  var BARE_URL = /^https?:\/\//u;
@@ -18434,10 +18601,10 @@ function resolveCacheRoot(env2 = process.env) {
18434
18601
  );
18435
18602
  }
18436
18603
  function cacheEntryPath(cacheRoot, reference) {
18437
- const entry = path17.join(cacheRoot, reference.name, reference.version);
18438
- const resolvedRoot = path17.resolve(cacheRoot);
18439
- const resolvedEntry = path17.resolve(entry);
18440
- if (!resolvedEntry.startsWith(resolvedRoot + path17.sep)) {
18604
+ const entry = path18.join(cacheRoot, reference.name, reference.version);
18605
+ const resolvedRoot = path18.resolve(cacheRoot);
18606
+ const resolvedEntry = path18.resolve(entry);
18607
+ if (!resolvedEntry.startsWith(resolvedRoot + path18.sep)) {
18441
18608
  throw new IntegrityError(
18442
18609
  `Cache entry path for "${reference.name}@${reference.version}" resolves outside the cache root \u2014 refusing to write.`
18443
18610
  );
@@ -18450,14 +18617,14 @@ function writeCompletionMarker(entryDir, reference) {
18450
18617
  version: reference.version,
18451
18618
  completedAt: (/* @__PURE__ */ new Date()).toISOString()
18452
18619
  };
18453
- fs16.writeFileSync(
18454
- path17.join(entryDir, CACHE_COMPLETION_MARKER),
18620
+ fs17.writeFileSync(
18621
+ path18.join(entryDir, CACHE_COMPLETION_MARKER),
18455
18622
  JSON.stringify(marker)
18456
18623
  );
18457
18624
  }
18458
18625
  function writeBundleDocument(entryDir, bundle) {
18459
- fs16.writeFileSync(
18460
- path17.join(entryDir, BUNDLE_DOCUMENT_FILENAME),
18626
+ fs17.writeFileSync(
18627
+ path18.join(entryDir, BUNDLE_DOCUMENT_FILENAME),
18461
18628
  JSON.stringify(bundle),
18462
18629
  {
18463
18630
  mode: 384
@@ -18465,10 +18632,10 @@ function writeBundleDocument(entryDir, bundle) {
18465
18632
  );
18466
18633
  }
18467
18634
  function readBundleDocument(entryDir) {
18468
- const documentPath = path17.join(entryDir, BUNDLE_DOCUMENT_FILENAME);
18635
+ const documentPath = path18.join(entryDir, BUNDLE_DOCUMENT_FILENAME);
18469
18636
  let raw;
18470
18637
  try {
18471
- raw = fs16.readFileSync(documentPath, "utf8");
18638
+ raw = fs17.readFileSync(documentPath, "utf8");
18472
18639
  } catch (error) {
18473
18640
  if (error.code === "ENOENT") {
18474
18641
  return void 0;
@@ -18487,11 +18654,11 @@ function readBundleDocument(entryDir) {
18487
18654
  }
18488
18655
  function isCompleteCacheEntry(entryDir) {
18489
18656
  try {
18490
- if (!fs16.statSync(entryDir).isDirectory()) {
18657
+ if (!fs17.statSync(entryDir).isDirectory()) {
18491
18658
  return false;
18492
18659
  }
18493
- const markerPath = path17.join(entryDir, CACHE_COMPLETION_MARKER);
18494
- const raw = fs16.readFileSync(markerPath, "utf8");
18660
+ const markerPath = path18.join(entryDir, CACHE_COMPLETION_MARKER);
18661
+ const raw = fs17.readFileSync(markerPath, "utf8");
18495
18662
  JSON.parse(raw);
18496
18663
  return true;
18497
18664
  } catch {
@@ -18499,53 +18666,53 @@ function isCompleteCacheEntry(entryDir) {
18499
18666
  }
18500
18667
  }
18501
18668
  function createStagingDir(cacheRoot, reference) {
18502
- const stagingRoot = path17.join(cacheRoot, ".staging");
18503
- fs16.mkdirSync(stagingRoot, { recursive: true, mode: 448 });
18504
- const prefix = path17.join(
18669
+ const stagingRoot = path18.join(cacheRoot, ".staging");
18670
+ fs17.mkdirSync(stagingRoot, { recursive: true, mode: 448 });
18671
+ const prefix = path18.join(
18505
18672
  stagingRoot,
18506
18673
  `${reference.name}-${reference.version}-`
18507
18674
  );
18508
- return fs16.mkdtempSync(prefix);
18675
+ return fs17.mkdtempSync(prefix);
18509
18676
  }
18510
18677
  function publishCacheEntry(stagingDir, entryDir) {
18511
- fs16.mkdirSync(path17.dirname(entryDir), { recursive: true, mode: 448 });
18678
+ fs17.mkdirSync(path18.dirname(entryDir), { recursive: true, mode: 448 });
18512
18679
  try {
18513
- fs16.renameSync(stagingDir, entryDir);
18680
+ fs17.renameSync(stagingDir, entryDir);
18514
18681
  return;
18515
18682
  } catch (error) {
18516
- const entryExists = fs16.existsSync(entryDir);
18683
+ const entryExists = fs17.existsSync(entryDir);
18517
18684
  if (entryExists && isCompleteCacheEntry(entryDir)) {
18518
- fs16.rmSync(stagingDir, { recursive: true, force: true });
18685
+ fs17.rmSync(stagingDir, { recursive: true, force: true });
18519
18686
  return;
18520
18687
  }
18521
18688
  if (entryExists) {
18522
- fs16.rmSync(entryDir, { recursive: true, force: true });
18689
+ fs17.rmSync(entryDir, { recursive: true, force: true });
18523
18690
  try {
18524
- fs16.renameSync(stagingDir, entryDir);
18691
+ fs17.renameSync(stagingDir, entryDir);
18525
18692
  return;
18526
18693
  } catch (retryError) {
18527
- fs16.rmSync(stagingDir, { recursive: true, force: true });
18694
+ fs17.rmSync(stagingDir, { recursive: true, force: true });
18528
18695
  throw retryError;
18529
18696
  }
18530
18697
  }
18531
18698
  if (error.code === "EXDEV") {
18532
18699
  const stagedMarker = JSON.parse(
18533
- fs16.readFileSync(path17.join(stagingDir, CACHE_COMPLETION_MARKER), "utf8")
18700
+ fs17.readFileSync(path18.join(stagingDir, CACHE_COMPLETION_MARKER), "utf8")
18534
18701
  );
18535
- fs16.cpSync(stagingDir, entryDir, {
18702
+ fs17.cpSync(stagingDir, entryDir, {
18536
18703
  recursive: true,
18537
18704
  preserveTimestamps: false,
18538
- mode: fs16.constants.COPYFILE_EXCL,
18539
- filter: (source) => path17.basename(source) !== CACHE_COMPLETION_MARKER
18705
+ mode: fs17.constants.COPYFILE_EXCL,
18706
+ filter: (source) => path18.basename(source) !== CACHE_COMPLETION_MARKER
18540
18707
  });
18541
18708
  writeCompletionMarker(entryDir, {
18542
18709
  name: stagedMarker.name,
18543
18710
  version: stagedMarker.version
18544
18711
  });
18545
- fs16.rmSync(stagingDir, { recursive: true, force: true });
18712
+ fs17.rmSync(stagingDir, { recursive: true, force: true });
18546
18713
  return;
18547
18714
  }
18548
- fs16.rmSync(stagingDir, { recursive: true, force: true });
18715
+ fs17.rmSync(stagingDir, { recursive: true, force: true });
18549
18716
  throw error;
18550
18717
  }
18551
18718
  }
@@ -18553,12 +18720,12 @@ function isReservedCacheRootName(name) {
18553
18720
  return name.startsWith(".");
18554
18721
  }
18555
18722
  function listCacheEntryDirectories(cacheRoot) {
18556
- if (!fs16.existsSync(cacheRoot)) {
18723
+ if (!fs17.existsSync(cacheRoot)) {
18557
18724
  return [];
18558
18725
  }
18559
- return fs16.readdirSync(cacheRoot, { withFileTypes: true }).filter(
18726
+ return fs17.readdirSync(cacheRoot, { withFileTypes: true }).filter(
18560
18727
  (entry) => entry.isDirectory() && !isReservedCacheRootName(entry.name)
18561
- ).map((entry) => path17.join(cacheRoot, entry.name));
18728
+ ).map((entry) => path18.join(cacheRoot, entry.name));
18562
18729
  }
18563
18730
  function resolveCacheClearTarget(cacheRoot, raw) {
18564
18731
  if (raw.includes("@")) {
@@ -18576,10 +18743,10 @@ function resolveCacheClearTarget(cacheRoot, raw) {
18576
18743
  `Cache clear target "${raw}" must not begin with "." \u2014 reserved cache-root filenames are excluded from removal by name, not only from the no-argument enumeration form.`
18577
18744
  );
18578
18745
  }
18579
- const resolvedRoot = path17.resolve(cacheRoot);
18580
- const target = path17.join(cacheRoot, raw);
18581
- const resolvedTarget = path17.resolve(target);
18582
- if (!resolvedTarget.startsWith(resolvedRoot + path17.sep)) {
18746
+ const resolvedRoot = path18.resolve(cacheRoot);
18747
+ const target = path18.join(cacheRoot, raw);
18748
+ const resolvedTarget = path18.resolve(target);
18749
+ if (!resolvedTarget.startsWith(resolvedRoot + path18.sep)) {
18583
18750
  throw new IntegrityError(
18584
18751
  `Cache clear target "${raw}" resolves outside the cache root \u2014 refusing to remove.`
18585
18752
  );
@@ -18591,7 +18758,7 @@ function resolveCacheClearTarget(cacheRoot, raw) {
18591
18758
  async function runCacheClearCommand(options, logger) {
18592
18759
  const cacheRoot = resolveCacheRoot();
18593
18760
  const targets = options.target === void 0 ? listCacheEntryDirectories(cacheRoot) : [resolveCacheClearTarget(cacheRoot, options.target)];
18594
- const existing = targets.filter((target) => fs17.existsSync(target));
18761
+ const existing = targets.filter((target) => fs18.existsSync(target));
18595
18762
  if (existing.length === 0) {
18596
18763
  if (options.target === void 0) {
18597
18764
  logger.info("Cache is already empty. Nothing to remove.");
@@ -18610,7 +18777,7 @@ async function runCacheClearCommand(options, logger) {
18610
18777
  return;
18611
18778
  }
18612
18779
  if (!options.yes) {
18613
- const label = options.target ?? existing.map((target) => path18.basename(target)).join(", ");
18780
+ const label = options.target ?? existing.map((target) => path19.basename(target)).join(", ");
18614
18781
  const proceed = await dist_default5({
18615
18782
  message: `Remove ${existing.length} cached ${existing.length === 1 ? "entry" : "entries"} (${label})?`
18616
18783
  });
@@ -18620,7 +18787,7 @@ async function runCacheClearCommand(options, logger) {
18620
18787
  }
18621
18788
  }
18622
18789
  for (const target of existing) {
18623
- fs17.rmSync(target, { recursive: true, force: true });
18790
+ fs18.rmSync(target, { recursive: true, force: true });
18624
18791
  logger.info(`Removed ${target}`);
18625
18792
  }
18626
18793
  logger.info(
@@ -18679,14 +18846,14 @@ var hs = new RegExp(pe, "g");
18679
18846
  var as = /\\\\/g;
18680
18847
  var ls = /\\{/g;
18681
18848
  var cs = /\\}/g;
18682
- var fs18 = /\\,/g;
18849
+ var fs19 = /\\,/g;
18683
18850
  var us = /\\./g;
18684
18851
  var ds = 1e5;
18685
18852
  function Ht(n7) {
18686
18853
  return isNaN(n7) ? n7.charCodeAt(0) : parseInt(n7, 10);
18687
18854
  }
18688
18855
  function ps(n7) {
18689
- return n7.replace(as, fe).replace(ls, ue).replace(cs, qt).replace(fs18, de).replace(us, pe);
18856
+ return n7.replace(as, fe).replace(ls, ue).replace(cs, qt).replace(fs19, de).replace(us, pe);
18690
18857
  }
18691
18858
  function ms(n7) {
18692
18859
  return n7.replace(is, "\\").replace(rs, "{").replace(ns, "}").replace(os4, ",").replace(hs, ".");
@@ -21617,8 +21784,8 @@ var Ze = Object.assign(Je, { glob: Je, globSync: ts, sync: Ui, globStream: Qe, s
21617
21784
  Ze.glob = Ze;
21618
21785
 
21619
21786
  // src/core/ownership.ts
21620
- import fs19 from "fs";
21621
- import path19 from "path";
21787
+ import fs20 from "fs";
21788
+ import path20 from "path";
21622
21789
  var KNOWN_COMPONENTS = /* @__PURE__ */ new Set([
21623
21790
  "agents",
21624
21791
  "skills",
@@ -21633,8 +21800,8 @@ var LEGACY_SOURCE_DIRECTORIES = /* @__PURE__ */ new Set([
21633
21800
  "operational-machinery"
21634
21801
  ]);
21635
21802
  function classifyArtifact(artifactPath, config, sourceRoot) {
21636
- const resolvedArtifactPath = path19.resolve(artifactPath);
21637
- if (!fs19.existsSync(resolvedArtifactPath) && !isBrokenSymlink(resolvedArtifactPath)) {
21803
+ const resolvedArtifactPath = path20.resolve(artifactPath);
21804
+ if (!fs20.existsSync(resolvedArtifactPath) && !isBrokenSymlink(resolvedArtifactPath)) {
21638
21805
  return "missing";
21639
21806
  }
21640
21807
  if (isOurSymlink(resolvedArtifactPath, sourceRoot)) {
@@ -21654,42 +21821,42 @@ function classifyArtifact(artifactPath, config, sourceRoot) {
21654
21821
  }
21655
21822
  function isOurSymlink(linkPath, machineryRoot) {
21656
21823
  try {
21657
- const linkTarget = fs19.readlinkSync(linkPath);
21658
- const absoluteTarget = path19.resolve(path19.dirname(linkPath), linkTarget);
21659
- const relative = path19.relative(machineryRoot, absoluteTarget);
21660
- return !relative.startsWith("..") && !path19.isAbsolute(relative);
21824
+ const linkTarget = fs20.readlinkSync(linkPath);
21825
+ const absoluteTarget = path20.resolve(path20.dirname(linkPath), linkTarget);
21826
+ const relative = path20.relative(machineryRoot, absoluteTarget);
21827
+ return !relative.startsWith("..") && !path20.isAbsolute(relative);
21661
21828
  } catch {
21662
21829
  return false;
21663
21830
  }
21664
21831
  }
21665
21832
  function isOurStaleSymlink(linkPath, managedPaths, config) {
21666
- const resolvedLinkPath = path19.resolve(linkPath);
21833
+ const resolvedLinkPath = path20.resolve(linkPath);
21667
21834
  if (!managedPaths.has(resolvedLinkPath)) {
21668
21835
  return false;
21669
21836
  }
21670
21837
  try {
21671
- const linkTarget = fs19.readlinkSync(resolvedLinkPath);
21672
- const absoluteTarget = path19.resolve(
21673
- path19.dirname(resolvedLinkPath),
21838
+ const linkTarget = fs20.readlinkSync(resolvedLinkPath);
21839
+ const absoluteTarget = path20.resolve(
21840
+ path20.dirname(resolvedLinkPath),
21674
21841
  linkTarget
21675
21842
  );
21676
21843
  let isBroken = false;
21677
21844
  try {
21678
- fs19.realpathSync(resolvedLinkPath);
21845
+ fs20.realpathSync(resolvedLinkPath);
21679
21846
  } catch {
21680
21847
  isBroken = true;
21681
21848
  }
21682
21849
  const knownFiles = new Set(
21683
21850
  Object.values(config.source).map(
21684
- (sourcePath) => path19.basename(sourcePath)
21851
+ (sourcePath) => path20.basename(sourcePath)
21685
21852
  )
21686
21853
  );
21687
- const lastSegment = path19.basename(linkTarget);
21688
- const parentSegment = path19.basename(path19.dirname(linkTarget));
21854
+ const lastSegment = path20.basename(linkTarget);
21855
+ const parentSegment = path20.basename(path20.dirname(linkTarget));
21689
21856
  if (isBroken) {
21690
21857
  return KNOWN_COMPONENTS.has(lastSegment) || KNOWN_COMPONENTS.has(parentSegment) || KNOWN_INSTRUCTION_FILES.has(lastSegment) || knownFiles.has(lastSegment);
21691
21858
  }
21692
- const targetSegments = absoluteTarget.split(path19.sep);
21859
+ const targetSegments = absoluteTarget.split(path20.sep);
21693
21860
  const traversesLegacyRoot = targetSegments.some(
21694
21861
  (segment) => LEGACY_SOURCE_DIRECTORIES.has(segment)
21695
21862
  );
@@ -21703,12 +21870,12 @@ function isOurStaleSymlink(linkPath, managedPaths, config) {
21703
21870
  }
21704
21871
  function isBrokenSymlink(filePath) {
21705
21872
  try {
21706
- fs19.lstatSync(filePath);
21873
+ fs20.lstatSync(filePath);
21707
21874
  } catch {
21708
21875
  return false;
21709
21876
  }
21710
21877
  try {
21711
- fs19.realpathSync(filePath);
21878
+ fs20.realpathSync(filePath);
21712
21879
  return false;
21713
21880
  } catch {
21714
21881
  return true;
@@ -21716,26 +21883,26 @@ function isBrokenSymlink(filePath) {
21716
21883
  }
21717
21884
  function isManagedCompiledFile(filePath) {
21718
21885
  try {
21719
- const stat = fs19.lstatSync(filePath);
21886
+ const stat = fs20.lstatSync(filePath);
21720
21887
  if (!stat.isFile() || stat.isSymbolicLink()) {
21721
21888
  return false;
21722
21889
  }
21723
- return extractProvenanceMarker(fs19.readFileSync(filePath, "utf8")) !== null;
21890
+ return extractProvenanceMarker(fs20.readFileSync(filePath, "utf8")) !== null;
21724
21891
  } catch {
21725
21892
  return false;
21726
21893
  }
21727
21894
  }
21728
21895
 
21729
21896
  // src/core/merge.ts
21730
- import fs20 from "fs";
21731
- import path20 from "path";
21897
+ import fs21 from "fs";
21898
+ import path21 from "path";
21732
21899
  function readSharedFile(filePath, parser) {
21733
- if (!fs20.existsSync(filePath)) {
21900
+ if (!fs21.existsSync(filePath)) {
21734
21901
  return { parsed: parser(""), unparseable: false };
21735
21902
  }
21736
21903
  try {
21737
21904
  return {
21738
- parsed: parser(fs20.readFileSync(filePath, "utf8")),
21905
+ parsed: parser(fs21.readFileSync(filePath, "utf8")),
21739
21906
  unparseable: false
21740
21907
  };
21741
21908
  } catch {
@@ -21744,13 +21911,13 @@ function readSharedFile(filePath, parser) {
21744
21911
  }
21745
21912
  function writeSharedFile(filePath, parsed, serializer, logger) {
21746
21913
  const serialized = serializer(parsed);
21747
- if (fs20.existsSync(filePath) && fs20.readFileSync(filePath, "utf8") === serialized) {
21914
+ if (fs21.existsSync(filePath) && fs21.readFileSync(filePath, "utf8") === serialized) {
21748
21915
  return false;
21749
21916
  }
21750
21917
  let realTarget = null;
21751
21918
  try {
21752
- if (fs20.lstatSync(filePath).isSymbolicLink()) {
21753
- realTarget = fs20.realpathSync(filePath);
21919
+ if (fs21.lstatSync(filePath).isSymbolicLink()) {
21920
+ realTarget = fs21.realpathSync(filePath);
21754
21921
  }
21755
21922
  } catch {
21756
21923
  realTarget = null;
@@ -21760,12 +21927,12 @@ function writeSharedFile(filePath, parsed, serializer, logger) {
21760
21927
  `tangyr: ${filePath} is a symlink \u2014 the file being modified is ${realTarget}`
21761
21928
  );
21762
21929
  }
21763
- fs20.mkdirSync(path20.dirname(filePath), { recursive: true });
21764
- fs20.writeFileSync(filePath, serialized);
21930
+ fs21.mkdirSync(path21.dirname(filePath), { recursive: true });
21931
+ fs21.writeFileSync(filePath, serialized);
21765
21932
  return true;
21766
21933
  }
21767
21934
  function removeManagedEntries(filePath, parser, serializer, removeManaged, logger, options) {
21768
- if (!fs20.existsSync(filePath)) {
21935
+ if (!fs21.existsSync(filePath)) {
21769
21936
  return;
21770
21937
  }
21771
21938
  const readResult = readSharedFile(filePath, parser);
@@ -21777,98 +21944,16 @@ function removeManagedEntries(filePath, parser, serializer, removeManaged, logge
21777
21944
  }
21778
21945
  const cleaned = removeManaged(readResult.parsed);
21779
21946
  if (options?.removeFileWhen?.(readResult.parsed, cleaned)) {
21780
- fs20.rmSync(filePath, { force: true });
21947
+ fs21.rmSync(filePath, { force: true });
21781
21948
  return;
21782
21949
  }
21783
- fs20.writeFileSync(filePath, serializer(cleaned));
21950
+ fs21.writeFileSync(filePath, serializer(cleaned));
21784
21951
  }
21785
21952
 
21786
21953
  // src/commands/uninstall.ts
21787
21954
  import fs29 from "fs";
21788
21955
  import path29 from "path";
21789
21956
 
21790
- // src/core/managed-sources.ts
21791
- var import_yaml5 = __toESM(require_dist(), 1);
21792
- import fs21 from "fs";
21793
- import path21 from "path";
21794
- function resolveKitComponentNames(sourceRoot, category) {
21795
- const manifestPath = path21.resolve(sourceRoot, "tangyr-kit.yaml");
21796
- if (!fs21.existsSync(manifestPath)) {
21797
- return void 0;
21798
- }
21799
- try {
21800
- const raw = fs21.readFileSync(manifestPath, "utf8");
21801
- const doc = (0, import_yaml5.parse)(raw);
21802
- if (doc && typeof doc === "object" && !Array.isArray(doc) && "components" in doc) {
21803
- const components = doc.components;
21804
- if (components && typeof components === "object" && !Array.isArray(components) && category in components) {
21805
- const names = components[category];
21806
- if (Array.isArray(names) && names.every((n7) => typeof n7 === "string")) {
21807
- return names;
21808
- }
21809
- }
21810
- }
21811
- } catch {
21812
- }
21813
- return void 0;
21814
- }
21815
- function resolveKitHookNames(sourceRoot) {
21816
- return resolveKitComponentNames(sourceRoot, "hooks");
21817
- }
21818
- function resolveKitSkillNames(sourceRoot) {
21819
- return resolveKitComponentNames(sourceRoot, "skills");
21820
- }
21821
- function resolveKitEntrypointName(sourceRoot) {
21822
- const manifestPath = path21.resolve(sourceRoot, "tangyr-kit.yaml");
21823
- if (!fs21.existsSync(manifestPath)) {
21824
- return void 0;
21825
- }
21826
- try {
21827
- const doc = (0, import_yaml5.parse)(fs21.readFileSync(manifestPath, "utf8"));
21828
- if (doc && typeof doc === "object" && !Array.isArray(doc)) {
21829
- const value = doc.entrypoint;
21830
- if (typeof value === "string" && value.trim().length > 0) {
21831
- return value.trim();
21832
- }
21833
- }
21834
- } catch {
21835
- }
21836
- return void 0;
21837
- }
21838
- function resolveHooksSourceFile(sourceRoot, config) {
21839
- return path21.resolve(sourceRoot, config.source.hooks, "hooks.json");
21840
- }
21841
- function resolveHooksSourceDir(sourceRoot, config) {
21842
- return path21.resolve(sourceRoot, config.source.hooks);
21843
- }
21844
- function hooksSourceExists(sourceRoot, config) {
21845
- const hooksJsonPath = resolveHooksSourceFile(sourceRoot, config);
21846
- if (fs21.existsSync(hooksJsonPath)) {
21847
- return true;
21848
- }
21849
- const hooksDir = resolveHooksSourceDir(sourceRoot, config);
21850
- if (!fs21.existsSync(hooksDir) || !fs21.statSync(hooksDir).isDirectory()) {
21851
- return false;
21852
- }
21853
- return fs21.readdirSync(hooksDir).some((f) => f.endsWith(".md") && !f.startsWith("."));
21854
- }
21855
- function hooksSourceLabel(sourceRoot, config) {
21856
- const dir = normalizeManagedSourcePath(
21857
- config.source.hooks.replace(/\\/gu, "/")
21858
- );
21859
- return fs21.existsSync(resolveHooksSourceFile(sourceRoot, config)) ? path21.posix.join(dir, "hooks.json") : `${dir}/`;
21860
- }
21861
- function resolveMcpSourceFile(sourceRoot, config) {
21862
- return path21.resolve(sourceRoot, config.source.mcp);
21863
- }
21864
- function mcpSourceLabel(config) {
21865
- return normalizeManagedSourcePath(config.source.mcp);
21866
- }
21867
- function normalizeManagedSourcePath(rawPath) {
21868
- const normalized = rawPath.replace(/\\/gu, "/");
21869
- return normalized.startsWith("./") ? normalized.slice(2) : normalized;
21870
- }
21871
-
21872
21957
  // src/compiler/hook-components.ts
21873
21958
  import fs23 from "fs";
21874
21959
  import path23 from "path";
@@ -24916,12 +25001,26 @@ function restoreBackup(backup, logger) {
24916
25001
  });
24917
25002
  fs29.rmSync(backup.backupLocation, { recursive: true, force: true });
24918
25003
  } else {
25004
+ if (isEmptyDirectory(backup.originalPath)) {
25005
+ fs29.rmdirSync(backup.originalPath);
25006
+ }
24919
25007
  fs29.renameSync(backup.backupLocation, backup.originalPath);
24920
25008
  }
24921
25009
  logger.verbose(
24922
25010
  ` restored: ${backup.backupLocation} \u2192 ${backup.originalPath}`
24923
25011
  );
24924
25012
  }
25013
+ function isEmptyDirectory(candidate) {
25014
+ try {
25015
+ const stat = fs29.lstatSync(candidate);
25016
+ if (!stat.isDirectory()) {
25017
+ return false;
25018
+ }
25019
+ return fs29.readdirSync(candidate).length === 0;
25020
+ } catch {
25021
+ return false;
25022
+ }
25023
+ }
24925
25024
  function isSymlink(p) {
24926
25025
  try {
24927
25026
  return fs29.lstatSync(p).isSymbolicLink();
@@ -27173,9 +27272,10 @@ function buildAgentsMdShim(_shimPath, _agentsMdPath, target) {
27173
27272
  ${SHIM_BODY}`;
27174
27273
  }
27175
27274
 
27176
- // src/core/skills-slot.ts
27275
+ // src/core/linked-slot.ts
27177
27276
  import fs37 from "fs";
27178
27277
  import path37 from "path";
27278
+ var SKILL_ENTRY = { component: "skills", kind: "dir" };
27179
27279
  function isForeignSkillsSlotSymlink(destination, config, sourceRoot, source) {
27180
27280
  if (!isSymlinkPath(destination)) {
27181
27281
  return false;
@@ -27188,16 +27288,17 @@ function isForeignSkillsSlotSymlink(destination, config, sourceRoot, source) {
27188
27288
  }
27189
27289
  function syncSkillsSlot(sync) {
27190
27290
  const { source, destination, logger } = sync;
27291
+ const entry = sync.entry ?? SKILL_ENTRY;
27191
27292
  if (!fs37.existsSync(source)) {
27192
27293
  return [
27193
27294
  {
27194
- component: "skills",
27295
+ component: entry.component,
27195
27296
  status: "skipped",
27196
27297
  path: `${source}: source not configured`
27197
27298
  }
27198
27299
  ];
27199
27300
  }
27200
- const declaredNames = resolveKitSkillNames(sync.sourceRoot);
27301
+ const declaredNames = sync.declared ?? (entry.component === "skills" ? resolveKitSkillNames(sync.sourceRoot) : void 0);
27201
27302
  const foreignSlotSymlink = isForeignSkillsSlotSymlink(
27202
27303
  destination,
27203
27304
  sync.config,
@@ -27208,56 +27309,103 @@ function syncSkillsSlot(sync) {
27208
27309
  if (sync.dryRun) {
27209
27310
  if (foreignSlotSymlink) {
27210
27311
  logger.info(
27211
- `[dry-run] skills: ${destination} is a symlink Tangyr did not create \u2014 unmanaged conflict, slot left alone`
27312
+ `[dry-run] ${entry.component}: ${destination} is a symlink Tangyr did not create \u2014 unmanaged conflict, slot left alone`
27212
27313
  );
27213
- return [{ component: "skills", status: "conflict", path: destination }];
27314
+ return [
27315
+ { component: entry.component, status: "conflict", path: destination }
27316
+ ];
27214
27317
  }
27215
27318
  const outcomes2 = [];
27216
27319
  if (isLegacyWholesaleSymlink) {
27217
- for (const name of foreignSkillNames(source, declaredNames)) {
27320
+ for (const name of foreignSkillNames(source, declaredNames, entry)) {
27321
+ const file = entryFileName(name, entry);
27218
27322
  logger.info(
27219
- `[dry-run] skills: migrate foreign skill ${path37.join(source, name)} -> ${path37.join(destination, name)}`
27323
+ `[dry-run] ${entry.component}: migrate undeclared ${path37.join(source, file)} -> ${path37.join(destination, file)}`
27220
27324
  );
27221
27325
  }
27222
27326
  logger.info(
27223
- `[dry-run] skills: replace wholesale symlink with real directory ${destination}`
27327
+ `[dry-run] ${entry.component}: replace wholesale symlink with real directory ${destination}`
27224
27328
  );
27225
27329
  }
27226
- for (const name of declaredNames ?? listSkillDirNames(source)) {
27227
- const skillDestination = path37.join(destination, name);
27330
+ for (const name of declaredNames ?? listEntryNames(source, entry)) {
27331
+ const file = entryFileName(name, entry);
27332
+ const entryDestination = path37.join(destination, file);
27228
27333
  logger.info(
27229
- `[dry-run] skills: symlink ${path37.join(source, name)} -> ${skillDestination}`
27334
+ `[dry-run] ${entry.component}: symlink ${path37.join(source, file)} -> ${entryDestination}`
27230
27335
  );
27231
27336
  outcomes2.push({
27232
- component: "skills",
27337
+ component: entry.component,
27233
27338
  status: "dry-run",
27234
- path: skillDestination
27339
+ path: entryDestination
27235
27340
  });
27236
27341
  }
27237
27342
  return outcomes2;
27238
27343
  }
27239
27344
  if (foreignSlotSymlink) {
27240
27345
  if (!sync.onUnmanagedConflict(destination) || isSymlinkPath(destination)) {
27241
- return [{ component: "skills", status: "conflict", path: destination }];
27346
+ return [
27347
+ { component: entry.component, status: "conflict", path: destination }
27348
+ ];
27242
27349
  }
27243
27350
  }
27244
27351
  if (isLegacyWholesaleSymlink) {
27245
- migrateWholesaleSkillsSymlink(source, destination, declaredNames, logger);
27352
+ migrateWholesaleSkillsSymlink(
27353
+ source,
27354
+ destination,
27355
+ declaredNames,
27356
+ entry,
27357
+ logger
27358
+ );
27246
27359
  }
27247
27360
  ensureDir(destination);
27248
27361
  const outcomes = [];
27249
- for (const name of declaredNames ?? listSkillDirNames(source)) {
27250
- outcomes.push(syncSingleSkill(sync, name));
27362
+ for (const name of declaredNames ?? listEntryNames(source, entry)) {
27363
+ outcomes.push(syncSingleSkill(sync, name, entry));
27251
27364
  }
27365
+ pruneUndeclaredLinks(source, destination, declaredNames, entry, logger);
27252
27366
  return outcomes;
27253
27367
  }
27254
- function syncSingleSkill(sync, name) {
27368
+ function pruneUndeclaredLinks(source, destination, declaredNames, entry, logger) {
27369
+ if (!declaredNames) {
27370
+ return;
27371
+ }
27372
+ const declared = new Set(
27373
+ declaredNames.map((name) => entryFileName(name, entry))
27374
+ );
27375
+ let present;
27376
+ try {
27377
+ present = fs37.readdirSync(destination, { withFileTypes: true });
27378
+ } catch {
27379
+ return;
27380
+ }
27381
+ for (const found2 of present) {
27382
+ if (!found2.isSymbolicLink() || declared.has(found2.name)) {
27383
+ continue;
27384
+ }
27385
+ const link = path37.join(destination, found2.name);
27386
+ let target;
27387
+ try {
27388
+ target = path37.resolve(destination, fs37.readlinkSync(link));
27389
+ } catch {
27390
+ continue;
27391
+ }
27392
+ if (path37.dirname(target) !== path37.resolve(source)) {
27393
+ continue;
27394
+ }
27395
+ fs37.unlinkSync(link);
27396
+ logger.verbose(
27397
+ ` ${entry.component}: removed ${link} \u2014 the kit no longer declares it`
27398
+ );
27399
+ }
27400
+ }
27401
+ function syncSingleSkill(sync, name, entry) {
27255
27402
  const { config, sourceRoot, source, destination } = sync;
27256
- const skillSource = path37.join(source, name);
27257
- const skillDestination = path37.join(destination, name);
27403
+ const file = entryFileName(name, entry);
27404
+ const skillSource = path37.join(source, file);
27405
+ const skillDestination = path37.join(destination, file);
27258
27406
  if (!fs37.existsSync(skillSource)) {
27259
27407
  return {
27260
- component: "skills",
27408
+ component: entry.component,
27261
27409
  status: "skipped",
27262
27410
  path: `${skillSource}: source not configured`
27263
27411
  };
@@ -27265,7 +27413,7 @@ function syncSingleSkill(sync, name) {
27265
27413
  const artifactClass = classifyArtifact(skillDestination, config, sourceRoot);
27266
27414
  if (artifactClass === "managed-symlink" && isSymlinkTo2(skillDestination, skillSource)) {
27267
27415
  return {
27268
- component: "skills",
27416
+ component: entry.component,
27269
27417
  status: "skipped-current",
27270
27418
  path: skillDestination
27271
27419
  };
@@ -27273,44 +27421,63 @@ function syncSingleSkill(sync, name) {
27273
27421
  if (artifactClass === "managed-stale" && isOurStaleSymlink(skillDestination, /* @__PURE__ */ new Set([skillDestination]), config)) {
27274
27422
  fs37.unlinkSync(skillDestination);
27275
27423
  } else if (artifactClass === "unmanaged-conflict" && !sync.onUnmanagedConflict(skillDestination)) {
27276
- return { component: "skills", status: "conflict", path: skillDestination };
27424
+ return {
27425
+ component: entry.component,
27426
+ status: "conflict",
27427
+ path: skillDestination
27428
+ };
27277
27429
  } else if (artifactClass === "managed-symlink") {
27278
27430
  fs37.unlinkSync(skillDestination);
27279
27431
  }
27280
- createRelativeSymlink(skillSource, skillDestination, "dir");
27281
- return { component: "skills", status: "success", path: skillDestination };
27432
+ createRelativeSymlink(skillSource, skillDestination, entry.kind);
27433
+ return {
27434
+ component: entry.component,
27435
+ status: "success",
27436
+ path: skillDestination
27437
+ };
27282
27438
  }
27283
- function migrateWholesaleSkillsSymlink(source, destination, declaredNames, logger) {
27284
- const foreignNames = foreignSkillNames(source, declaredNames);
27439
+ function migrateWholesaleSkillsSymlink(source, destination, declaredNames, entry, logger) {
27440
+ const foreignNames = foreignSkillNames(source, declaredNames, entry);
27285
27441
  fs37.unlinkSync(destination);
27286
27442
  ensureDir(destination);
27287
27443
  for (const name of foreignNames) {
27288
- const from = path37.join(source, name);
27289
- const to = path37.join(destination, name);
27444
+ const file = entryFileName(name, entry);
27445
+ const from = path37.join(source, file);
27446
+ const to = path37.join(destination, file);
27290
27447
  if (fs37.existsSync(to)) {
27291
27448
  logger.warn(
27292
- `skills migration: ${to} already exists \u2014 skipping ${from} to avoid overwrite. Nothing in the kit was changed.`
27449
+ `${entry.component} migration: ${to} already exists \u2014 skipping ${from} to avoid overwrite. Nothing in the kit was changed.`
27293
27450
  );
27294
27451
  continue;
27295
27452
  }
27296
27453
  fs37.cpSync(from, to, { recursive: true, verbatimSymlinks: true });
27297
27454
  logger.warn(
27298
- `skills migration: '${name}' is present under the kit's skills/ but is not declared in its manifest. Copied ${from} -> ${to} so the harness can read it. The original is left in the kit deliberately: this command does not modify a kit. Remove ${from} yourself if it does not belong there, or declare it in tangyr-kit.yaml if it does.`
27455
+ `${entry.component} migration: '${name}' is present in the kit's ${entry.component}/ but is not declared in its manifest. Copied ${from} -> ${to} so the harness can read it. The original is left in the kit deliberately: this command does not modify a kit. Remove ${from} yourself if it does not belong there, or declare it in tangyr-kit.yaml if it does.`
27299
27456
  );
27300
27457
  }
27301
27458
  }
27302
- function foreignSkillNames(source, declaredNames) {
27459
+ function foreignSkillNames(source, declaredNames, entry) {
27303
27460
  if (!declaredNames) {
27304
27461
  return [];
27305
27462
  }
27306
27463
  const declaredSet = new Set(declaredNames);
27307
- return listSkillDirNames(source).filter((name) => !declaredSet.has(name));
27464
+ return listEntryNames(source, entry).filter((name) => !declaredSet.has(name));
27308
27465
  }
27309
- function listSkillDirNames(dir) {
27466
+ function listEntryNames(dir, entry) {
27310
27467
  if (!fs37.existsSync(dir)) {
27311
27468
  return [];
27312
27469
  }
27313
- return fs37.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
27470
+ const found2 = fs37.readdirSync(dir, { withFileTypes: true });
27471
+ if (entry.kind === "dir") {
27472
+ return found2.filter((one) => one.isDirectory() && !one.name.startsWith(".")).map((one) => one.name);
27473
+ }
27474
+ const extension = entry.extension ?? "";
27475
+ return found2.filter(
27476
+ (one) => one.isFile() && !one.name.startsWith(".") && one.name.endsWith(extension)
27477
+ ).map((one) => one.name.slice(0, one.name.length - extension.length));
27478
+ }
27479
+ function entryFileName(name, entry) {
27480
+ return entry.kind === "dir" ? name : `${name}${entry.extension ?? ""}`;
27314
27481
  }
27315
27482
  function isSymlinkPath(filePath) {
27316
27483
  try {
@@ -27500,6 +27667,20 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
27500
27667
  if (shouldSkipComponent(options, directComponent.component)) {
27501
27668
  continue;
27502
27669
  }
27670
+ if (directComponent.type === "dir") {
27671
+ outcomes.push(
27672
+ ...syncClaudeCodeSlot(
27673
+ config,
27674
+ sourceRoot,
27675
+ options,
27676
+ logger,
27677
+ directComponent,
27678
+ manifest,
27679
+ scopePath
27680
+ )
27681
+ );
27682
+ continue;
27683
+ }
27503
27684
  outcomes.push(
27504
27685
  syncDirectComponent(
27505
27686
  config,
@@ -27692,6 +27873,52 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
27692
27873
  recordShimState(manifest, shimPath);
27693
27874
  logger?.verbose(`instructions-shim: backed up and replaced -> ${shimPath}`);
27694
27875
  }
27876
+ var SLOT_ENTRIES = {
27877
+ agents: {
27878
+ category: "agents",
27879
+ entry: { component: "agents", kind: "file", extension: ".md" }
27880
+ },
27881
+ commands: {
27882
+ category: "commands",
27883
+ entry: { component: "commands", kind: "file", extension: ".md" }
27884
+ },
27885
+ rules: {
27886
+ category: "rules",
27887
+ entry: { component: "rules", kind: "file", extension: ".md" }
27888
+ },
27889
+ "output-styles": {
27890
+ category: null,
27891
+ entry: { component: "output-styles", kind: "file", extension: ".md" }
27892
+ }
27893
+ };
27894
+ function syncClaudeCodeSlot(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
27895
+ const shape = SLOT_ENTRIES[directComponent.component];
27896
+ const source = path40.resolve(
27897
+ sourceRoot,
27898
+ config.source[directComponent.sourceKey]
27899
+ );
27900
+ if (!shape) {
27901
+ return [skippedMissingSource(directComponent.component, source)];
27902
+ }
27903
+ return syncSkillsSlot({
27904
+ config,
27905
+ sourceRoot,
27906
+ source,
27907
+ destination: directComponent.destination,
27908
+ dryRun: options.dryRun,
27909
+ logger,
27910
+ entry: shape.entry,
27911
+ declared: shape.category === null ? void 0 : resolveKitSlotNames(sourceRoot, shape.category),
27912
+ onUnmanagedConflict: (conflictPath) => handleConflict(
27913
+ conflictPath,
27914
+ config,
27915
+ options,
27916
+ logger,
27917
+ manifest,
27918
+ scopePath
27919
+ )
27920
+ });
27921
+ }
27695
27922
  function syncDirectComponent(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
27696
27923
  const source = directComponent.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : path40.resolve(sourceRoot, config.source[directComponent.sourceKey]);
27697
27924
  const sourceLabel = directComponent.sourceKey === "instructions" ? instructionsSourceLabel(sourceRoot, config) : config.source[directComponent.sourceKey];
@@ -32458,8 +32685,28 @@ async function runInstallCommand(options, logger) {
32458
32685
  config: options.config,
32459
32686
  scope
32460
32687
  });
32688
+ const claudeProfileForConflicts = (() => {
32689
+ try {
32690
+ return resolveTargetPaths({
32691
+ scope,
32692
+ projectRoot,
32693
+ mappings: loadMappings(kitInfo.path, config, configDir).platformPaths
32694
+ })["claude-code"];
32695
+ } catch {
32696
+ return void 0;
32697
+ }
32698
+ })();
32461
32699
  const skillsSource = path50.resolve(kitInfo.path, config.source.skills);
32462
- const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") && path50.basename(f.path) === "skills";
32700
+ const perEntrySlots = new Set(
32701
+ [
32702
+ claudeProfileForConflicts?.agents,
32703
+ claudeProfileForConflicts?.commands,
32704
+ claudeProfileForConflicts?.rules,
32705
+ claudeProfileForConflicts?.output_styles,
32706
+ claudeProfileForConflicts?.skills
32707
+ ].filter((slot) => typeof slot === "string")
32708
+ );
32709
+ const isPerSkillSkillsSlot = (f) => f.tool === "copilot" && path50.basename(f.path) === "skills" || f.tool === "claude-code" && perEntrySlots.has(f.path);
32463
32710
  const foreignSkillsSlots = new Set(
32464
32711
  assessResult.findings.filter(
32465
32712
  (f) => isPerSkillSkillsSlot(f) && isForeignSkillsSlotSymlink(
@@ -33038,7 +33285,13 @@ function installClaudeCodeAdapterSlots(args) {
33038
33285
  { component: "hooks", slot: "hooks_shared_file" },
33039
33286
  { component: "settings", slot: "settings_shared_file" },
33040
33287
  { component: "mcp", slot: "mcp_shared_file" },
33041
- { component: "output-styles", slot: "output_styles" }
33288
+ { component: "output-styles", slot: "output_styles" },
33289
+ // Filled one entry at a time, so they are the adapter's work and not a
33290
+ // placement's. The slot root is still what `skippedTargetPaths` is asked
33291
+ // about: an operator who declined the whole directory declined all of it.
33292
+ { component: "agents", slot: "agents" },
33293
+ { component: "commands", slot: "commands" },
33294
+ { component: "rules", slot: "rules" }
33042
33295
  ];
33043
33296
  const scopePath = resolveScopePath(
33044
33297
  scope,
@@ -33119,6 +33372,15 @@ function claudeCodeOutcomeToManifestKey(profile, outcome, scope, projectRoot, ma
33119
33372
  return `claude-code/${slot}`;
33120
33373
  }
33121
33374
  }
33375
+ for (const [slot, slotPath] of Object.entries(profile)) {
33376
+ if (typeof slotPath !== "string") {
33377
+ continue;
33378
+ }
33379
+ const prefix = `${slotPath}${path50.sep}`;
33380
+ if (outcome.path.startsWith(prefix)) {
33381
+ return `claude-code/${slot}/${outcome.path.slice(prefix.length)}`;
33382
+ }
33383
+ }
33122
33384
  return null;
33123
33385
  }
33124
33386
  function resolveClaudeCodeSkillsDestination(scope, projectRoot, mappings) {
@@ -33468,6 +33730,19 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
33468
33730
  if (shared) {
33469
33731
  return shared;
33470
33732
  }
33733
+ if (tool === "claude-code") {
33734
+ return claudeCodeOutcomeToManifestKey(
33735
+ resolveTargetPaths({
33736
+ scope,
33737
+ projectRoot,
33738
+ mappings: mappings.platformPaths
33739
+ })["claude-code"],
33740
+ outcome,
33741
+ scope,
33742
+ projectRoot,
33743
+ mappings
33744
+ );
33745
+ }
33471
33746
  if (tool !== "copilot" && tool !== "codex" && tool !== "opencode" && tool !== "cursor" && tool !== "cline") {
33472
33747
  if (isDeferredTarget(tool)) {
33473
33748
  throw new Error(
@@ -33715,23 +33990,6 @@ function getClaudeCodePlacements(kitInfo, config, scope = "global", projectRoot,
33715
33990
  isDir: false
33716
33991
  });
33717
33992
  }
33718
- const componentDirMap = {
33719
- agents: resolvedPaths.agents,
33720
- commands: resolvedPaths.commands,
33721
- rules: resolvedPaths.rules
33722
- };
33723
- for (const [component, targetPath] of Object.entries(componentDirMap)) {
33724
- const componentDir = path50.join(kitInfo.path, component);
33725
- if (fs47.existsSync(componentDir) && fs47.statSync(componentDir).isDirectory()) {
33726
- placements.push({
33727
- source: componentDir,
33728
- destination: targetPath,
33729
- manifestKey: `claude-code/${component}`,
33730
- type: "symlink",
33731
- isDir: true
33732
- });
33733
- }
33734
- }
33735
33993
  return placements;
33736
33994
  }
33737
33995
  function getClaudeCodePlacementsFromProfile(kitInfo, profile, config) {
@@ -33746,23 +34004,6 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile, config) {
33746
34004
  isDir: false
33747
34005
  });
33748
34006
  }
33749
- const componentDirMap = {
33750
- agents: profile.agents,
33751
- commands: profile.commands,
33752
- rules: profile.rules
33753
- };
33754
- for (const [component, targetPath] of Object.entries(componentDirMap)) {
33755
- const componentDir = path50.join(kitInfo.path, component);
33756
- if (fs47.existsSync(componentDir) && fs47.statSync(componentDir).isDirectory()) {
33757
- placements.push({
33758
- source: componentDir,
33759
- destination: targetPath,
33760
- manifestKey: `claude-code/${component}`,
33761
- type: "symlink",
33762
- isDir: true
33763
- });
33764
- }
33765
- }
33766
34007
  return placements;
33767
34008
  }
33768
34009
  function collectAllFiles(kitInfo, config) {
@@ -36043,6 +36284,7 @@ function updateManifest(kitInfo, kitSync, written) {
36043
36284
  writeManifest(kitSync.scopePath, kitSync.manifest);
36044
36285
  }
36045
36286
  var outcomeRecordableTargets = /* @__PURE__ */ new Set([
36287
+ "claude-code",
36046
36288
  "copilot",
36047
36289
  "codex",
36048
36290
  "opencode",