agentsmesh 0.18.1 → 0.19.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.
package/dist/engine.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { z } from 'zod';
2
2
  import { stringify, parse } from 'yaml';
3
- import { join, basename, dirname, relative, win32, posix, resolve, extname } from 'path';
4
- import { readFile, rm, mkdir, readdir, stat, lstat, unlink, writeFile, rename, chmod, access, realpath } from 'fs/promises';
3
+ import { basename, join, dirname, relative, win32, posix, sep, resolve, extname } from 'path';
4
+ import { readFile, rm, mkdir, readdir, stat, lstat, unlink, writeFile, rename, chmod, access, realpath, mkdtemp, cp } from 'fs/promises';
5
5
  import { constants, existsSync, realpathSync, statSync, readFileSync } from 'fs';
6
6
  import { parse as parse$1 } from 'smol-toml';
7
7
  import { Buffer } from 'buffer';
8
- import { homedir } from 'os';
8
+ import { homedir, tmpdir } from 'os';
9
9
  import { createHash } from 'crypto';
10
10
  import { execFile } from 'child_process';
11
11
  import { fileURLToPath, pathToFileURL, URL } from 'url';
@@ -22,86 +22,6 @@ var __export = (target31, all) => {
22
22
  for (var name in all)
23
23
  __defProp(target31, name, { get: all[name], enumerable: true });
24
24
  };
25
-
26
- // src/config/core/conversions.ts
27
- function usesCommandSkillProjection(target31) {
28
- return Object.prototype.hasOwnProperty.call(DEFAULT_COMMANDS_TO_SKILLS, target31);
29
- }
30
- function usesAgentSkillProjection(target31) {
31
- return Object.prototype.hasOwnProperty.call(DEFAULT_AGENTS_TO_SKILLS, target31);
32
- }
33
- function resolveConversionValue(value, scope) {
34
- if (value === void 0) return void 0;
35
- if (typeof value === "boolean") return value;
36
- return value[scope];
37
- }
38
- function shouldConvertCommandsToSkills(config, target31, defaultEnabled, scope = "project") {
39
- const raw = config.conversions?.commands_to_skills?.[target31];
40
- const configVal = resolveConversionValue(raw, scope);
41
- if (configVal !== void 0) return configVal;
42
- if (usesCommandSkillProjection(target31)) return DEFAULT_COMMANDS_TO_SKILLS[target31];
43
- return defaultEnabled ?? false;
44
- }
45
- function shouldConvertAgentsToSkills(config, target31, defaultEnabled, scope = "project") {
46
- const raw = config.conversions?.agents_to_skills?.[target31];
47
- const configVal = resolveConversionValue(raw, scope);
48
- if (configVal !== void 0) return configVal;
49
- if (usesAgentSkillProjection(target31)) return DEFAULT_AGENTS_TO_SKILLS[target31];
50
- return defaultEnabled ?? false;
51
- }
52
- var DEFAULT_COMMANDS_TO_SKILLS, DEFAULT_AGENTS_TO_SKILLS;
53
- var init_conversions = __esm({
54
- "src/config/core/conversions.ts"() {
55
- DEFAULT_COMMANDS_TO_SKILLS = {
56
- amp: true,
57
- "codex-cli": true,
58
- goose: true,
59
- kiro: true,
60
- warp: true
61
- };
62
- DEFAULT_AGENTS_TO_SKILLS = {
63
- amp: true,
64
- "gemini-cli": false,
65
- // native .gemini/agents/*.md per agent-structures
66
- cline: true,
67
- "codex-cli": false,
68
- // native .codex/agents/*.toml per agent-structures
69
- windsurf: true,
70
- goose: true,
71
- antigravity: true,
72
- continue: true,
73
- warp: true
74
- };
75
- }
76
- });
77
-
78
- // src/targets/catalog/capabilities.ts
79
- function cap(level, flavor) {
80
- return flavor !== void 0 ? { level, flavor } : { level };
81
- }
82
- function normalizeCapabilityValue(input) {
83
- if (typeof input === "string") {
84
- return { level: input };
85
- }
86
- return input;
87
- }
88
- function normalizeTargetCapabilities(caps) {
89
- return {
90
- rules: normalizeCapabilityValue(caps.rules),
91
- additionalRules: normalizeCapabilityValue(caps.additionalRules),
92
- commands: normalizeCapabilityValue(caps.commands),
93
- agents: normalizeCapabilityValue(caps.agents),
94
- skills: normalizeCapabilityValue(caps.skills),
95
- mcp: normalizeCapabilityValue(caps.mcp),
96
- hooks: normalizeCapabilityValue(caps.hooks),
97
- ignore: normalizeCapabilityValue(caps.ignore),
98
- permissions: normalizeCapabilityValue(caps.permissions)
99
- };
100
- }
101
- var init_capabilities = __esm({
102
- "src/targets/catalog/capabilities.ts"() {
103
- }
104
- });
105
25
  function capabilityLevel(capability) {
106
26
  return typeof capability === "string" ? capability : capability.level;
107
27
  }
@@ -125,7 +45,7 @@ function validateCapabilityImplementations(descriptor31, capabilities17, ctx, pa
125
45
  function validateDescriptor(value) {
126
46
  return targetDescriptorSchema.parse(value);
127
47
  }
128
- var capabilityLevelSchema, capabilitiesSchema, generatorsSchema, pathResolversSchema, layoutSchema, globalSupportSchema, legacyGlobalKeys, generatorRequirements, settingsBackedFeatures, targetDescriptorSchemaBase, targetDescriptorSchema;
48
+ var capabilityLevelSchema, capabilitiesSchema, generatorsSchema, pathResolversSchema, layoutSchema, globalSupportSchema, legacyGlobalKeys, generatorRequirements, settingsBackedFeatures, conversionDefaultsSchema, metadataSchema, targetDescriptorSchemaBase, targetDescriptorSchema;
129
49
  var init_target_descriptor_schema = __esm({
130
50
  "src/targets/catalog/target-descriptor.schema.ts"() {
131
51
  capabilityLevelSchema = z.union([
@@ -189,8 +109,19 @@ var init_target_descriptor_schema = __esm({
189
109
  { feature: "permissions", generator: "generatePermissions" }
190
110
  ];
191
111
  settingsBackedFeatures = ["mcp", "hooks", "ignore", "permissions"];
112
+ conversionDefaultsSchema = z.object({
113
+ commandsToSkills: z.boolean().optional(),
114
+ agentsToSkills: z.boolean().optional()
115
+ }).strict();
116
+ metadataSchema = z.object({
117
+ displayName: z.string().min(1),
118
+ category: z.enum(["cli", "ide", "agent-platform"]),
119
+ officialUrl: z.string().min(1),
120
+ shortDescription: z.string().min(1)
121
+ }).passthrough();
192
122
  targetDescriptorSchemaBase = z.object({
193
123
  id: z.string().regex(/^[a-z][a-z0-9-]*$/, "Target id must be lowercase with hyphens"),
124
+ metadata: metadataSchema,
194
125
  generators: generatorsSchema,
195
126
  capabilities: capabilitiesSchema,
196
127
  emptyImportMessage: z.string(),
@@ -198,7 +129,13 @@ var init_target_descriptor_schema = __esm({
198
129
  project: layoutSchema,
199
130
  globalSupport: globalSupportSchema.optional(),
200
131
  buildImportPaths: z.function(),
201
- detectionPaths: z.array(z.string())
132
+ detectionPaths: z.array(z.string()),
133
+ excludeFromStarterInit: z.boolean().optional(),
134
+ conversionDefaults: conversionDefaultsSchema.optional(),
135
+ emitScopedSettings: z.function().optional(),
136
+ mergeGeneratedOutputContent: z.function().optional(),
137
+ postProcessHookOutputs: z.function().optional(),
138
+ preservesManualActivation: z.boolean().optional()
202
139
  }).passthrough();
203
140
  targetDescriptorSchema = targetDescriptorSchemaBase.superRefine((value, ctx) => {
204
141
  for (const key of legacyGlobalKeys) {
@@ -223,10 +160,15 @@ var init_target_descriptor_schema = __esm({
223
160
 
224
161
  // src/targets/catalog/registry.ts
225
162
  function builtinDescriptors() {
226
- if (!_builtinDescriptors) {
227
- _builtinDescriptors = new Map(BUILTIN_TARGETS.map((d) => [d.id, d]));
163
+ if (_builtinDescriptors) return _builtinDescriptors;
164
+ const defined = BUILTIN_TARGETS.filter(
165
+ (d) => d !== void 0 && typeof d.id === "string"
166
+ );
167
+ const map = new Map(defined.map((d) => [d.id, d]));
168
+ if (defined.length === BUILTIN_TARGETS.length) {
169
+ _builtinDescriptors = map;
228
170
  }
229
- return _builtinDescriptors;
171
+ return map;
230
172
  }
231
173
  function registerTargetDescriptor(descriptor31) {
232
174
  const validated = validateDescriptor(descriptor31);
@@ -238,6 +180,10 @@ function getDescriptor(name) {
238
180
  function getAllDescriptors() {
239
181
  return [...descriptorRegistry.values()];
240
182
  }
183
+ function getAllRegisteredDescriptorIds() {
184
+ const ids = /* @__PURE__ */ new Set([...builtinDescriptors().keys(), ...descriptorRegistry.keys()]);
185
+ return [...ids];
186
+ }
241
187
  var descriptorRegistry, _builtinDescriptors;
242
188
  var init_registry = __esm({
243
189
  "src/targets/catalog/registry.ts"() {
@@ -247,6 +193,65 @@ var init_registry = __esm({
247
193
  }
248
194
  });
249
195
 
196
+ // src/config/core/conversions.ts
197
+ function builtinDefault(target31, key) {
198
+ return getDescriptor(target31)?.conversionDefaults?.[key];
199
+ }
200
+ function resolveConversionValue(value, scope) {
201
+ if (value === void 0) return void 0;
202
+ if (typeof value === "boolean") return value;
203
+ return value[scope];
204
+ }
205
+ function shouldConvertCommandsToSkills(config, target31, defaultEnabled, scope = "project") {
206
+ const raw = config.conversions?.commands_to_skills?.[target31];
207
+ const configVal = resolveConversionValue(raw, scope);
208
+ if (configVal !== void 0) return configVal;
209
+ const builtin = builtinDefault(target31, "commandsToSkills");
210
+ if (builtin !== void 0) return builtin;
211
+ return defaultEnabled ?? false;
212
+ }
213
+ function shouldConvertAgentsToSkills(config, target31, defaultEnabled, scope = "project") {
214
+ const raw = config.conversions?.agents_to_skills?.[target31];
215
+ const configVal = resolveConversionValue(raw, scope);
216
+ if (configVal !== void 0) return configVal;
217
+ const builtin = builtinDefault(target31, "agentsToSkills");
218
+ if (builtin !== void 0) return builtin;
219
+ return defaultEnabled ?? false;
220
+ }
221
+ var init_conversions = __esm({
222
+ "src/config/core/conversions.ts"() {
223
+ init_registry();
224
+ }
225
+ });
226
+
227
+ // src/targets/catalog/capabilities.ts
228
+ function cap(level, flavor) {
229
+ return flavor !== void 0 ? { level, flavor } : { level };
230
+ }
231
+ function normalizeCapabilityValue(input) {
232
+ if (typeof input === "string") {
233
+ return { level: input };
234
+ }
235
+ return input;
236
+ }
237
+ function normalizeTargetCapabilities(caps) {
238
+ return {
239
+ rules: normalizeCapabilityValue(caps.rules),
240
+ additionalRules: normalizeCapabilityValue(caps.additionalRules),
241
+ commands: normalizeCapabilityValue(caps.commands),
242
+ agents: normalizeCapabilityValue(caps.agents),
243
+ skills: normalizeCapabilityValue(caps.skills),
244
+ mcp: normalizeCapabilityValue(caps.mcp),
245
+ hooks: normalizeCapabilityValue(caps.hooks),
246
+ ignore: normalizeCapabilityValue(caps.ignore),
247
+ permissions: normalizeCapabilityValue(caps.permissions)
248
+ };
249
+ }
250
+ var init_capabilities = __esm({
251
+ "src/targets/catalog/capabilities.ts"() {
252
+ }
253
+ });
254
+
250
255
  // src/targets/catalog/shared-artifact-owner.ts
251
256
  function ownerTargetIdForSharedPath(path) {
252
257
  for (const descriptor31 of BUILTIN_TARGETS) {
@@ -364,6 +369,32 @@ function parseFrontmatter(content) {
364
369
  const frontmatter = yamlStr === "" ? {} : parse(yamlStr) ?? {};
365
370
  return { frontmatter, body };
366
371
  }
372
+ function extractBody(content) {
373
+ if (content.indexOf("---") !== 0) return content.trim();
374
+ const close = content.indexOf("---", 3);
375
+ if (close === -1) return content.trim();
376
+ return content.slice(close + 3).trim();
377
+ }
378
+ function tryParseFrontmatter(content, filePath) {
379
+ try {
380
+ return { ok: true, value: parseFrontmatter(content) };
381
+ } catch (err) {
382
+ const message = err instanceof Error ? err.message : String(err);
383
+ const wrapped = new Error(`Failed to parse frontmatter in ${filePath}: ${message}`, {
384
+ cause: err
385
+ });
386
+ return { ok: false, error: wrapped, bodyFallback: extractBody(content) };
387
+ }
388
+ }
389
+ function parseOrSkipFrontmatter(content, filePath, onParseError) {
390
+ const result = tryParseFrontmatter(content, filePath);
391
+ if (result.ok) return result.value;
392
+ if (onParseError) {
393
+ onParseError(result.error, filePath);
394
+ return null;
395
+ }
396
+ throw result.error;
397
+ }
367
398
  function serializeFrontmatter(frontmatter, body) {
368
399
  const keys = Object.keys(frontmatter);
369
400
  if (keys.length === 0) return body;
@@ -682,7 +713,18 @@ var init_fs_text_encoding = __esm({
682
713
  EXECUTABLE_SCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([".sh", ".bash", ".zsh"]);
683
714
  }
684
715
  });
685
- async function readDirRecursive(dir, visited) {
716
+ function shouldSkipRecursiveBranch(segments) {
717
+ if (segments.length > MAX_RECURSIVE_DEPTH) return true;
718
+ const counts = /* @__PURE__ */ new Map();
719
+ for (const segment of segments) {
720
+ const count = (counts.get(segment) ?? 0) + 1;
721
+ if (count >= MAX_SEGMENT_REPETITIONS) return true;
722
+ counts.set(segment, count);
723
+ }
724
+ return false;
725
+ }
726
+ async function readDirRecursive(dir, visited, branchSegments) {
727
+ const currentBranchSegments = branchSegments ?? [basename(dir)];
686
728
  let canonicalDir;
687
729
  try {
688
730
  canonicalDir = await realpath(dir);
@@ -708,7 +750,9 @@ async function readDirRecursive(dir, visited) {
708
750
  () => false
709
751
  );
710
752
  if (walkChild) {
711
- files.push(...await readDirRecursive(full, seen));
753
+ const nextSegments = [...currentBranchSegments, ent.name];
754
+ if (shouldSkipRecursiveBranch(nextSegments)) continue;
755
+ files.push(...await readDirRecursive(full, seen, nextSegments));
712
756
  } else {
713
757
  files.push(full);
714
758
  }
@@ -724,9 +768,12 @@ async function readDirRecursive(dir, visited) {
724
768
  );
725
769
  }
726
770
  }
771
+ var MAX_RECURSIVE_DEPTH, MAX_SEGMENT_REPETITIONS;
727
772
  var init_fs_traverse = __esm({
728
773
  "src/utils/filesystem/fs-traverse.ts"() {
729
774
  init_errors();
775
+ MAX_RECURSIVE_DEPTH = 32;
776
+ MAX_SEGMENT_REPETITIONS = 3;
730
777
  }
731
778
  });
732
779
  async function readFileSafe(path) {
@@ -1932,7 +1979,9 @@ function shouldRewritePathToken(fullContent, start, end, matchText, rewriteBareP
1932
1979
  }
1933
1980
  if (before === "@") return true;
1934
1981
  if (before === "(") {
1935
- return after === ")" || after === "#" || after === "?" || after === " " || after === " ";
1982
+ if (fullContent[start - 2] === "]") {
1983
+ return after === ")" || after === "#" || after === "?" || after === " " || after === " ";
1984
+ }
1936
1985
  }
1937
1986
  if (!rewriteBarePathTokens) return false;
1938
1987
  if (isRootRelativePathToken(normalizedCandidate)) return true;
@@ -2326,6 +2375,85 @@ var init_descriptor_default_mappers = __esm({
2326
2375
  }
2327
2376
  });
2328
2377
 
2378
+ // src/install/importers/boilerplate-filter.ts
2379
+ function boilerplateKind(filename) {
2380
+ const lower = filename.toLowerCase();
2381
+ const dotIdx = lower.lastIndexOf(".");
2382
+ const stem = dotIdx > 0 ? lower.slice(0, dotIdx) : lower;
2383
+ return BOILERPLATE_STEMS.get(stem);
2384
+ }
2385
+ function isBoilerplate(filename) {
2386
+ return boilerplateKind(filename) !== void 0;
2387
+ }
2388
+ function isPreservedBoilerplate(filename) {
2389
+ return boilerplateKind(filename) === "preserved";
2390
+ }
2391
+ function isNoiseBoilerplate(filename) {
2392
+ return boilerplateKind(filename) === "noise";
2393
+ }
2394
+ function isRepoNonContentDir(name) {
2395
+ return NON_CONTENT_DIRS.has(name);
2396
+ }
2397
+ function isRepoNonContentFile(name) {
2398
+ return NON_CONTENT_FILES.has(name);
2399
+ }
2400
+ var BOILERPLATE_STEMS, NON_CONTENT_DIRS, NON_CONTENT_FILES;
2401
+ var init_boilerplate_filter = __esm({
2402
+ "src/install/importers/boilerplate-filter.ts"() {
2403
+ BOILERPLATE_STEMS = /* @__PURE__ */ new Map([
2404
+ // Noise — upstream-repo housekeeping with no downstream value.
2405
+ ["contributing", "noise"],
2406
+ ["changelog", "noise"],
2407
+ ["changes", "noise"],
2408
+ ["history", "noise"],
2409
+ ["code_of_conduct", "noise"],
2410
+ ["security", "noise"],
2411
+ ["support", "noise"],
2412
+ ["maintainers", "noise"],
2413
+ ["governance", "noise"],
2414
+ ["authors", "noise"],
2415
+ ["contributors", "noise"],
2416
+ ["codeowners", "noise"],
2417
+ ["citation", "noise"],
2418
+ ["acknowledgments", "noise"],
2419
+ ["acknowledgements", "noise"],
2420
+ // Preserved — installed alongside content but never treated as an entity.
2421
+ // LICENSE family: legal attribution required by MIT/Apache/BSD/GPL.
2422
+ ["license", "preserved"],
2423
+ ["license-mit", "preserved"],
2424
+ ["license-apache", "preserved"],
2425
+ ["license-bsd", "preserved"],
2426
+ ["license-gpl", "preserved"],
2427
+ ["notice", "preserved"],
2428
+ ["copying", "preserved"],
2429
+ ["copyright", "preserved"],
2430
+ // README: skill-specific context (overview, usage, prerequisites) that
2431
+ // explains the skill to the downstream consumer. Filtered from entity
2432
+ // discovery so it can never become a phantom rule/command/agent named
2433
+ // "README", but kept as a supporting file so the docs travel with the install.
2434
+ ["readme", "preserved"]
2435
+ ]);
2436
+ NON_CONTENT_DIRS = /* @__PURE__ */ new Set([
2437
+ ".git",
2438
+ ".github",
2439
+ ".gitlab",
2440
+ "node_modules",
2441
+ ".vscode",
2442
+ ".idea"
2443
+ ]);
2444
+ NON_CONTENT_FILES = /* @__PURE__ */ new Set([
2445
+ "package.json",
2446
+ "package-lock.json",
2447
+ "pnpm-lock.yaml",
2448
+ "yarn.lock",
2449
+ ".gitignore",
2450
+ ".gitattributes",
2451
+ ".editorconfig",
2452
+ ".DS_Store"
2453
+ ]);
2454
+ }
2455
+ });
2456
+
2329
2457
  // src/targets/catalog/import-descriptor.ts
2330
2458
  function resolveScopedSources(paths, scope) {
2331
2459
  if (!paths) return [];
@@ -2359,18 +2487,32 @@ async function runSingleFile(spec, sources, projectRoot, fromTool, normalize) {
2359
2487
  const destPath = join(destDir, spec.canonicalRootFilename);
2360
2488
  const normalizeTo = (destinationFile) => normalize(content, srcPath, destinationFile);
2361
2489
  if (spec.map) {
2362
- const mapping = await spec.map({
2363
- absolutePath: srcPath,
2364
- relativePath: rel2,
2365
- content,
2366
- destDir,
2367
- normalizeTo
2368
- });
2490
+ let mapping;
2491
+ try {
2492
+ mapping = await spec.map({
2493
+ absolutePath: srcPath,
2494
+ relativePath: rel2,
2495
+ content,
2496
+ destDir,
2497
+ normalizeTo
2498
+ });
2499
+ } catch (err) {
2500
+ const msg = err instanceof Error ? err.message : String(err);
2501
+ process.stderr.write(`\u26A0 skipping ${srcPath}: ${msg}
2502
+ `);
2503
+ continue;
2504
+ }
2369
2505
  if (!mapping) continue;
2370
2506
  await writeFileAtomic(mapping.destPath, mapping.content);
2371
2507
  return [{ fromTool, fromPath: srcPath, toPath: mapping.toPath, feature: spec.feature }];
2372
2508
  }
2373
- const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
2509
+ const result = tryParseFrontmatter(normalizeTo(destPath), srcPath);
2510
+ if (!result.ok) {
2511
+ process.stderr.write(`\u26A0 skipping ${srcPath}: ${result.error.message}
2512
+ `);
2513
+ continue;
2514
+ }
2515
+ const { frontmatter, body } = result.value;
2374
2516
  const remapped = spec.frontmatterRemap ? spec.frontmatterRemap(frontmatter) : frontmatter;
2375
2517
  const outFm = spec.markAsRoot ? { ...remapped, root: true } : remapped;
2376
2518
  const outContent = await serializeImportedRuleWithFallback(destPath, outFm, body);
@@ -2399,13 +2541,22 @@ async function runDirectory(spec, sources, projectRoot, fromTool, normalize) {
2399
2541
  fromTool,
2400
2542
  normalize,
2401
2543
  mapEntry: async ({ srcPath, relativePath, content, normalizeTo }) => {
2402
- const mapping = await mapper({
2403
- absolutePath: srcPath,
2404
- relativePath,
2405
- content,
2406
- destDir,
2407
- normalizeTo: (destinationFile) => normalizeTo(destinationFile)
2408
- });
2544
+ if (isPreservedBoilerplate(basename(srcPath))) return null;
2545
+ let mapping;
2546
+ try {
2547
+ mapping = await mapper({
2548
+ absolutePath: srcPath,
2549
+ relativePath,
2550
+ content,
2551
+ destDir,
2552
+ normalizeTo: (destinationFile) => normalizeTo(destinationFile)
2553
+ });
2554
+ } catch (err) {
2555
+ const msg = err instanceof Error ? err.message : String(err);
2556
+ process.stderr.write(`\u26A0 skipping ${srcPath}: ${msg}
2557
+ `);
2558
+ return null;
2559
+ }
2409
2560
  if (!mapping) return null;
2410
2561
  return {
2411
2562
  destPath: mapping.destPath,
@@ -2546,6 +2697,7 @@ var init_descriptor_import_runner = __esm({
2546
2697
  init_import_metadata();
2547
2698
  init_import_orchestrator();
2548
2699
  init_descriptor_default_mappers();
2700
+ init_boilerplate_filter();
2549
2701
  init_import_descriptor();
2550
2702
  }
2551
2703
  });
@@ -3423,7 +3575,7 @@ var init_crush = __esm({
3423
3575
  });
3424
3576
 
3425
3577
  // src/targets/cursor/constants.ts
3426
- var CURSOR_TARGET, CURSOR_COMPAT_AGENTS, CURSOR_LEGACY_RULES, CURSOR_RULES_DIR, CURSOR_GENERAL_RULE, CURSOR_COMMANDS_DIR, CURSOR_AGENTS_DIR, CURSOR_SKILLS_DIR, CURSOR_MCP, CURSOR_HOOKS, CURSOR_SETTINGS, CURSOR_IGNORE, CURSOR_INDEXING_IGNORE, CURSOR_GLOBAL_EXPORT_DIR, CURSOR_GLOBAL_USER_RULES, CURSOR_DOT_CURSOR_AGENTS, CURSOR_GLOBAL_MCP_EXPORT, CURSOR_GLOBAL_SKILLS_DIR, CURSOR_GLOBAL_AGENTS_DIR, CURSOR_CANONICAL_RULES_DIR, CURSOR_CANONICAL_COMMANDS_DIR, CURSOR_CANONICAL_AGENTS_DIR, CURSOR_CANONICAL_SKILLS_DIR, CURSOR_CANONICAL_MCP, CURSOR_CANONICAL_PERMISSIONS, CURSOR_CANONICAL_HOOKS, CURSOR_CANONICAL_IGNORE;
3578
+ var CURSOR_TARGET, CURSOR_COMPAT_AGENTS, CURSOR_LEGACY_RULES, CURSOR_RULES_DIR, CURSOR_GENERAL_RULE, CURSOR_COMMANDS_DIR, CURSOR_AGENTS_DIR, CURSOR_SKILLS_DIR, CURSOR_MCP, CURSOR_HOOKS, CURSOR_SETTINGS, CURSOR_IGNORE, CURSOR_INDEXING_IGNORE, CURSOR_GLOBAL_EXPORT_DIR, CURSOR_GLOBAL_USER_RULES, CURSOR_DOT_CURSOR_AGENTS, CURSOR_CANONICAL_RULES_DIR, CURSOR_CANONICAL_COMMANDS_DIR, CURSOR_CANONICAL_AGENTS_DIR, CURSOR_CANONICAL_SKILLS_DIR, CURSOR_CANONICAL_MCP, CURSOR_CANONICAL_PERMISSIONS, CURSOR_CANONICAL_HOOKS, CURSOR_CANONICAL_IGNORE;
3427
3579
  var init_constants11 = __esm({
3428
3580
  "src/targets/cursor/constants.ts"() {
3429
3581
  CURSOR_TARGET = "cursor";
@@ -3442,9 +3594,6 @@ var init_constants11 = __esm({
3442
3594
  CURSOR_GLOBAL_EXPORT_DIR = ".agentsmesh-exports/cursor";
3443
3595
  CURSOR_GLOBAL_USER_RULES = `${CURSOR_GLOBAL_EXPORT_DIR}/user-rules.md`;
3444
3596
  CURSOR_DOT_CURSOR_AGENTS = ".cursor/AGENTS.md";
3445
- CURSOR_GLOBAL_MCP_EXPORT = CURSOR_MCP;
3446
- CURSOR_GLOBAL_SKILLS_DIR = CURSOR_SKILLS_DIR;
3447
- CURSOR_GLOBAL_AGENTS_DIR = CURSOR_AGENTS_DIR;
3448
3597
  CURSOR_CANONICAL_RULES_DIR = ".agentsmesh/rules";
3449
3598
  CURSOR_CANONICAL_COMMANDS_DIR = ".agentsmesh/commands";
3450
3599
  CURSOR_CANONICAL_AGENTS_DIR = ".agentsmesh/agents";
@@ -4575,7 +4724,7 @@ var init_linter2 = __esm({
4575
4724
  });
4576
4725
 
4577
4726
  // src/targets/amazon-q/index.ts
4578
- var target2, project2, global, globalCapabilities, descriptor2;
4727
+ var target2, project2, globalLayout2, globalCapabilities, descriptor2;
4579
4728
  var init_amazon_q2 = __esm({
4580
4729
  "src/targets/amazon-q/index.ts"() {
4581
4730
  init_generator2();
@@ -4606,7 +4755,7 @@ var init_amazon_q2 = __esm({
4606
4755
  }
4607
4756
  }
4608
4757
  };
4609
- global = {
4758
+ globalLayout2 = {
4610
4759
  managedOutputs: {
4611
4760
  dirs: [AMAZON_Q_GLOBAL_RULES_DIR],
4612
4761
  files: [AMAZON_Q_GLOBAL_MCP_FILE]
@@ -4669,7 +4818,7 @@ var init_amazon_q2 = __esm({
4669
4818
  globalSupport: {
4670
4819
  capabilities: globalCapabilities,
4671
4820
  detectionPaths: [AMAZON_Q_GLOBAL_RULES_DIR, AMAZON_Q_GLOBAL_MCP_FILE],
4672
- layout: global
4821
+ layout: globalLayout2
4673
4822
  },
4674
4823
  importer: {
4675
4824
  rules: {
@@ -4739,13 +4888,22 @@ var init_generator3 = __esm({
4739
4888
 
4740
4889
  // src/targets/catalog/skill-mirror.ts
4741
4890
  function mirrorSkillsToAgents(path, skillsDir, activeTargets) {
4742
- if (path.startsWith(`${skillsDir}/`) && !activeTargets.includes("codex-cli")) {
4891
+ const hasNativeWriter = activeTargets.some((id) => NATIVE_AGENTS_SKILL_WRITERS.includes(id));
4892
+ if (path.startsWith(`${skillsDir}/`) && !hasNativeWriter) {
4743
4893
  return `.agents/skills/${path.slice(skillsDir.length + 1)}`;
4744
4894
  }
4745
4895
  return null;
4746
4896
  }
4897
+ var NATIVE_AGENTS_SKILL_WRITERS;
4747
4898
  var init_skill_mirror = __esm({
4748
4899
  "src/targets/catalog/skill-mirror.ts"() {
4900
+ NATIVE_AGENTS_SKILL_WRITERS = [
4901
+ "amp",
4902
+ "antigravity",
4903
+ "codex-cli",
4904
+ "goose",
4905
+ "replit-agent"
4906
+ ];
4749
4907
  }
4750
4908
  });
4751
4909
  async function importAmpMcp(projectRoot, settingsPath, results) {
@@ -4887,7 +5045,7 @@ function mergeAmpSettings(existing, newContent) {
4887
5045
  }
4888
5046
  return JSON.stringify(base, null, 2);
4889
5047
  }
4890
- var target3, project3, globalLayout2, capabilities2, descriptor3;
5048
+ var target3, project3, globalLayout3, capabilities2, descriptor3;
4891
5049
  var init_amp2 = __esm({
4892
5050
  "src/targets/amp/index.ts"() {
4893
5051
  init_command_skill();
@@ -4927,7 +5085,7 @@ var init_amp2 = __esm({
4927
5085
  }
4928
5086
  }
4929
5087
  };
4930
- globalLayout2 = {
5088
+ globalLayout3 = {
4931
5089
  rootInstructionPath: AMP_GLOBAL_ROOT_FILE,
4932
5090
  skillDir: AMP_GLOBAL_SKILLS_DIR,
4933
5091
  managedOutputs: {
@@ -4990,7 +5148,7 @@ var init_amp2 = __esm({
4990
5148
  globalSupport: {
4991
5149
  capabilities: capabilities2,
4992
5150
  detectionPaths: [AMP_GLOBAL_ROOT_FILE, AMP_GLOBAL_MCP_FILE],
4993
- layout: globalLayout2
5151
+ layout: globalLayout3
4994
5152
  },
4995
5153
  importer: {
4996
5154
  rules: {
@@ -5024,7 +5182,8 @@ var init_amp2 = __esm({
5024
5182
  ".agents/skills/": "consumer"
5025
5183
  },
5026
5184
  buildImportPaths: buildAmpImportPaths,
5027
- detectionPaths: [AMP_ROOT_FILE, AMP_MCP_FILE]
5185
+ detectionPaths: [AMP_ROOT_FILE, AMP_MCP_FILE],
5186
+ conversionDefaults: { commandsToSkills: true, agentsToSkills: true }
5028
5187
  };
5029
5188
  }
5030
5189
  });
@@ -5264,7 +5423,7 @@ var init_linter4 = __esm({
5264
5423
  });
5265
5424
 
5266
5425
  // src/targets/antigravity/index.ts
5267
- var target4, project4, global2, globalCapabilities2, descriptor4;
5426
+ var target4, project4, globalLayout4, globalCapabilities2, descriptor4;
5268
5427
  var init_antigravity2 = __esm({
5269
5428
  "src/targets/antigravity/index.ts"() {
5270
5429
  init_capabilities();
@@ -5288,6 +5447,20 @@ var init_antigravity2 = __esm({
5288
5447
  project4 = {
5289
5448
  rootInstructionPath: ANTIGRAVITY_RULES_ROOT,
5290
5449
  skillDir: ".agents/skills",
5450
+ // managedOutputs is the sole signal `cleanupStaleGeneratedOutputs` uses to
5451
+ // decide which dirs/files to scan when reconciling post-uninstall state.
5452
+ // Antigravity emits across three dirs:
5453
+ // - `.agents/rules` (rules)
5454
+ // - `.agents/workflows` (commands → workflows projection)
5455
+ // - `.agents/skills` (agents → skills projection + native skills)
5456
+ // Without all three here, projected outputs from an uninstalled pack would
5457
+ // linger in the user's project. The root rule file and (suppressed) MCP
5458
+ // config are listed under `files` so a flip from one root style to another
5459
+ // doesn't leave both behind.
5460
+ managedOutputs: {
5461
+ dirs: [ANTIGRAVITY_RULES_DIR, ANTIGRAVITY_WORKFLOWS_DIR, ANTIGRAVITY_SKILLS_DIR],
5462
+ files: [ANTIGRAVITY_RULES_ROOT]
5463
+ },
5291
5464
  rewriteGeneratedPath(path) {
5292
5465
  if (path === ANTIGRAVITY_MCP_CONFIG) return null;
5293
5466
  return path;
@@ -5304,7 +5477,7 @@ var init_antigravity2 = __esm({
5304
5477
  }
5305
5478
  }
5306
5479
  };
5307
- global2 = {
5480
+ globalLayout4 = {
5308
5481
  rootInstructionPath: ANTIGRAVITY_GLOBAL_ROOT,
5309
5482
  renderPrimaryRootInstruction: renderAntigravityGlobalInstructions,
5310
5483
  skillDir: ANTIGRAVITY_GLOBAL_SKILLS_DIR,
@@ -5332,7 +5505,7 @@ var init_antigravity2 = __esm({
5332
5505
  return `${ANTIGRAVITY_GLOBAL_WORKFLOWS_DIR}/${name}.md`;
5333
5506
  },
5334
5507
  agentPath(name) {
5335
- return `${ANTIGRAVITY_SKILLS_DIR}/${projectedAgentSkillDirName(name)}/SKILL.md`;
5508
+ return `${ANTIGRAVITY_GLOBAL_SKILLS_DIR}/${projectedAgentSkillDirName(name)}/SKILL.md`;
5336
5509
  }
5337
5510
  }
5338
5511
  };
@@ -5379,7 +5552,7 @@ var init_antigravity2 = __esm({
5379
5552
  ".gemini/antigravity/workflows",
5380
5553
  ".gemini/antigravity/mcp_config.json"
5381
5554
  ],
5382
- layout: global2
5555
+ layout: globalLayout4
5383
5556
  },
5384
5557
  importer: {
5385
5558
  rules: {
@@ -5420,7 +5593,8 @@ var init_antigravity2 = __esm({
5420
5593
  ".agents/rules/",
5421
5594
  ".agents/skills/",
5422
5595
  ".agents/workflows/"
5423
- ]
5596
+ ],
5597
+ conversionDefaults: { agentsToSkills: true }
5424
5598
  };
5425
5599
  }
5426
5600
  });
@@ -5752,7 +5926,7 @@ function buildSettingsContent(canonical) {
5752
5926
  if (Object.keys(settings).length === 0) return null;
5753
5927
  return JSON.stringify(settings, null, 2);
5754
5928
  }
5755
- var target5, project5, globalLayout3, capabilities3, globalCapabilities3, descriptor5;
5929
+ var target5, project5, globalLayout5, capabilities3, globalCapabilities3, descriptor5;
5756
5930
  var init_augment_code2 = __esm({
5757
5931
  "src/targets/augment-code/index.ts"() {
5758
5932
  init_generator5();
@@ -5787,7 +5961,7 @@ var init_augment_code2 = __esm({
5787
5961
  }
5788
5962
  }
5789
5963
  };
5790
- globalLayout3 = {
5964
+ globalLayout5 = {
5791
5965
  skillDir: AUGMENT_CODE_GLOBAL_SKILLS_DIR,
5792
5966
  managedOutputs: {
5793
5967
  dirs: [
@@ -5873,7 +6047,7 @@ var init_augment_code2 = __esm({
5873
6047
  AUGMENT_CODE_GLOBAL_SKILLS_DIR,
5874
6048
  AUGMENT_CODE_GLOBAL_SETTINGS_FILE
5875
6049
  ],
5876
- layout: globalLayout3
6050
+ layout: globalLayout5
5877
6051
  },
5878
6052
  emitScopedSettings(canonical) {
5879
6053
  const content = buildSettingsContent(canonical);
@@ -6273,6 +6447,19 @@ async function importClaudeSkills(projectRoot, results, normalize) {
6273
6447
  const skillDir = dirname(skillMdPath);
6274
6448
  const skillName = basename(skillDir);
6275
6449
  const destSkillDir = join(destBase, skillName);
6450
+ const skillMdContent = await readFileSafe(skillMdPath);
6451
+ if (skillMdContent === null) continue;
6452
+ const normalizedSkillMd = normalize(
6453
+ skillMdContent,
6454
+ skillMdPath,
6455
+ join(destSkillDir, "SKILL.md")
6456
+ );
6457
+ const skillMdParsed = tryParseFrontmatter(normalizedSkillMd, skillMdPath);
6458
+ if (!skillMdParsed.ok) {
6459
+ process.stderr.write(`\u26A0 skipping ${skillMdPath}: ${skillMdParsed.error.message}
6460
+ `);
6461
+ continue;
6462
+ }
6276
6463
  const skillFiles = await readDirRecursive(skillDir);
6277
6464
  for (const filePath of skillFiles) {
6278
6465
  const fileContent = await readFileSafe(filePath);
@@ -6281,13 +6468,12 @@ async function importClaudeSkills(projectRoot, results, normalize) {
6281
6468
  const destPath = join(destSkillDir, relPath);
6282
6469
  await mkdirp(dirname(destPath));
6283
6470
  const normalized = normalize(fileContent, filePath, destPath);
6284
- const parsed = relPath === "SKILL.md" ? parseFrontmatter(normalized) : null;
6285
6471
  await writeFileAtomic(
6286
6472
  destPath,
6287
6473
  relPath === "SKILL.md" ? await serializeImportedSkillWithFallback(
6288
6474
  destPath,
6289
- parsed?.frontmatter ?? {},
6290
- parsed?.body ?? ""
6475
+ skillMdParsed.value.frontmatter,
6476
+ skillMdParsed.value.body
6291
6477
  ) : normalized
6292
6478
  );
6293
6479
  const toPath = `${CLAUDE_CANONICAL_SKILLS_DIR}/${skillName}/${relPath}`;
@@ -6408,7 +6594,7 @@ var init_linter6 = __esm({
6408
6594
  });
6409
6595
 
6410
6596
  // src/targets/claude-code/index.ts
6411
- var target6, project6, global3, globalCapabilities4, descriptor6;
6597
+ var target6, project6, globalLayout6, globalCapabilities4, descriptor6;
6412
6598
  var init_claude_code2 = __esm({
6413
6599
  "src/targets/claude-code/index.ts"() {
6414
6600
  init_generator6();
@@ -6452,7 +6638,7 @@ var init_claude_code2 = __esm({
6452
6638
  }
6453
6639
  }
6454
6640
  };
6455
- global3 = {
6641
+ globalLayout6 = {
6456
6642
  rootInstructionPath: CLAUDE_ROOT,
6457
6643
  skillDir: ".claude/skills",
6458
6644
  renderPrimaryRootInstruction: renderClaudeGlobalPrimaryInstructions,
@@ -6531,7 +6717,7 @@ var init_claude_code2 = __esm({
6531
6717
  ".claude.json",
6532
6718
  ".agents/skills"
6533
6719
  ],
6534
- layout: global3,
6720
+ layout: globalLayout6,
6535
6721
  scopeExtras: generateClaudeGlobalExtras
6536
6722
  },
6537
6723
  importer: {
@@ -7321,7 +7507,7 @@ var init_lint4 = __esm({
7321
7507
  });
7322
7508
 
7323
7509
  // src/targets/cline/index.ts
7324
- var target7, project7, globalLayout4, globalCapabilities5, descriptor7;
7510
+ var target7, project7, globalLayout7, globalCapabilities5, descriptor7;
7325
7511
  var init_cline2 = __esm({
7326
7512
  "src/targets/cline/index.ts"() {
7327
7513
  init_generator7();
@@ -7369,7 +7555,7 @@ var init_cline2 = __esm({
7369
7555
  }
7370
7556
  }
7371
7557
  };
7372
- globalLayout4 = {
7558
+ globalLayout7 = {
7373
7559
  skillDir: CLINE_SKILLS_DIR,
7374
7560
  managedOutputs: {
7375
7561
  dirs: [
@@ -7461,10 +7647,11 @@ var init_cline2 = __esm({
7461
7647
  CLINE_MCP_SETTINGS,
7462
7648
  CLINE_IGNORE
7463
7649
  ],
7464
- layout: globalLayout4
7650
+ layout: globalLayout7
7465
7651
  },
7466
7652
  buildImportPaths: buildClineImportPaths,
7467
- detectionPaths: [".clinerules", ".cline"]
7653
+ detectionPaths: [".clinerules", ".cline"],
7654
+ conversionDefaults: { agentsToSkills: true }
7468
7655
  };
7469
7656
  }
7470
7657
  });
@@ -8244,7 +8431,7 @@ var init_codex_rule_paths = __esm({
8244
8431
  init_instruction_mirror();
8245
8432
  }
8246
8433
  });
8247
- var target8, project8, global4, globalCapabilities6, descriptor8;
8434
+ var target8, project8, globalLayout8, globalCapabilities6, descriptor8;
8248
8435
  var init_codex_cli2 = __esm({
8249
8436
  "src/targets/codex-cli/index.ts"() {
8250
8437
  init_generator9();
@@ -8290,7 +8477,7 @@ var init_codex_cli2 = __esm({
8290
8477
  }
8291
8478
  }
8292
8479
  };
8293
- global4 = {
8480
+ globalLayout8 = {
8294
8481
  rootInstructionPath: CODEX_GLOBAL_AGENTS_MD,
8295
8482
  renderPrimaryRootInstruction: renderCodexGlobalInstructions,
8296
8483
  extraRuleOutputPaths(rule) {
@@ -8368,7 +8555,7 @@ var init_codex_cli2 = __esm({
8368
8555
  ".codex/rules",
8369
8556
  ".agents/skills"
8370
8557
  ],
8371
- layout: global4
8558
+ layout: globalLayout8
8372
8559
  },
8373
8560
  buildImportPaths: buildCodexCliImportPaths,
8374
8561
  sharedArtifacts: {
@@ -8381,7 +8568,9 @@ var init_codex_cli2 = __esm({
8381
8568
  ".codex/config.toml",
8382
8569
  ".codex/agents",
8383
8570
  ".codex/rules"
8384
- ]
8571
+ ],
8572
+ excludeFromStarterInit: true,
8573
+ conversionDefaults: { commandsToSkills: true, agentsToSkills: false }
8385
8574
  };
8386
8575
  }
8387
8576
  });
@@ -8744,7 +8933,7 @@ var init_scope_extras = __esm({
8744
8933
  });
8745
8934
 
8746
8935
  // src/targets/continue/index.ts
8747
- var target9, project9, globalLayout5, globalCapabilities7, descriptor9;
8936
+ var target9, project9, globalLayout9, globalCapabilities7, descriptor9;
8748
8937
  var init_continue2 = __esm({
8749
8938
  "src/targets/continue/index.ts"() {
8750
8939
  init_projected_agent_skill();
@@ -8786,7 +8975,7 @@ var init_continue2 = __esm({
8786
8975
  }
8787
8976
  }
8788
8977
  };
8789
- globalLayout5 = {
8978
+ globalLayout9 = {
8790
8979
  rootInstructionPath: CONTINUE_ROOT_RULE,
8791
8980
  outputFamilies: [
8792
8981
  { id: "compat-agents", kind: "additional", explicitPaths: [CONTINUE_GLOBAL_AGENTS_MD] }
@@ -8860,7 +9049,7 @@ var init_continue2 = __esm({
8860
9049
  ".continue/mcpServers",
8861
9050
  CONTINUE_SKILLS_DIR
8862
9051
  ],
8863
- layout: globalLayout5,
9052
+ layout: globalLayout9,
8864
9053
  scopeExtras: generateContinueScopeExtras
8865
9054
  },
8866
9055
  importer: {
@@ -8882,7 +9071,8 @@ var init_continue2 = __esm({
8882
9071
  }
8883
9072
  },
8884
9073
  buildImportPaths: buildContinueImportPaths,
8885
- detectionPaths: [".continue/rules", ".continue/skills", ".continue/mcpServers"]
9074
+ detectionPaths: [".continue/rules", ".continue/skills", ".continue/mcpServers"],
9075
+ conversionDefaults: { agentsToSkills: true }
8886
9076
  };
8887
9077
  }
8888
9078
  });
@@ -9532,7 +9722,7 @@ var init_scope_extras2 = __esm({
9532
9722
  };
9533
9723
  }
9534
9724
  });
9535
- var target10, project10, global5, globalCapabilities8, descriptor10;
9725
+ var target10, project10, globalLayout10, globalCapabilities8, descriptor10;
9536
9726
  var init_copilot2 = __esm({
9537
9727
  "src/targets/copilot/index.ts"() {
9538
9728
  init_generator11();
@@ -9586,7 +9776,7 @@ var init_copilot2 = __esm({
9586
9776
  }
9587
9777
  }
9588
9778
  };
9589
- global5 = {
9779
+ globalLayout10 = {
9590
9780
  rootInstructionPath: COPILOT_GLOBAL_INSTRUCTIONS,
9591
9781
  renderPrimaryRootInstruction: renderCopilotGlobalInstructions,
9592
9782
  outputFamilies: [
@@ -9692,7 +9882,7 @@ var init_copilot2 = __esm({
9692
9882
  COPILOT_GLOBAL_PROMPTS_DIR,
9693
9883
  COPILOT_GLOBAL_AGENTS_SKILLS_DIR
9694
9884
  ],
9695
- layout: global5,
9885
+ layout: globalLayout10,
9696
9886
  scopeExtras: generateCopilotGlobalExtras
9697
9887
  },
9698
9888
  importer: {
@@ -10074,7 +10264,7 @@ var init_settings = __esm({
10074
10264
  });
10075
10265
 
10076
10266
  // src/targets/crush/index.ts
10077
- var target11, project11, globalLayout6, capabilities4, globalCapabilities9, descriptor11;
10267
+ var target11, project11, globalLayout11, capabilities4, globalCapabilities9, descriptor11;
10078
10268
  var init_crush2 = __esm({
10079
10269
  "src/targets/crush/index.ts"() {
10080
10270
  init_command_skill();
@@ -10119,7 +10309,7 @@ var init_crush2 = __esm({
10119
10309
  }
10120
10310
  }
10121
10311
  };
10122
- globalLayout6 = {
10312
+ globalLayout11 = {
10123
10313
  rootInstructionPath: CRUSH_GLOBAL_ROOT_FILE,
10124
10314
  skillDir: CRUSH_GLOBAL_SKILLS_DIR,
10125
10315
  managedOutputs: {
@@ -10192,7 +10382,7 @@ var init_crush2 = __esm({
10192
10382
  globalSupport: {
10193
10383
  capabilities: globalCapabilities9,
10194
10384
  detectionPaths: [CRUSH_GLOBAL_ROOT_FILE, CRUSH_GLOBAL_CONFIG_FILE, CRUSH_GLOBAL_SKILLS_DIR],
10195
- layout: globalLayout6
10385
+ layout: globalLayout11
10196
10386
  },
10197
10387
  mergeGeneratedOutputContent(existing, pending, newContent, resolvedPath) {
10198
10388
  const base = pending?.content ?? existing;
@@ -10774,20 +10964,20 @@ async function hasGlobalCursorArtifacts(projectRoot) {
10774
10964
  const candidates = [
10775
10965
  join(projectRoot, CURSOR_DOT_CURSOR_AGENTS),
10776
10966
  join(projectRoot, CURSOR_GLOBAL_USER_RULES),
10777
- join(projectRoot, CURSOR_GLOBAL_MCP_EXPORT),
10967
+ join(projectRoot, CURSOR_MCP),
10778
10968
  join(projectRoot, CURSOR_HOOKS),
10779
10969
  join(projectRoot, CURSOR_IGNORE),
10780
- join(projectRoot, CURSOR_GLOBAL_SKILLS_DIR),
10781
- join(projectRoot, CURSOR_GLOBAL_AGENTS_DIR),
10970
+ join(projectRoot, CURSOR_SKILLS_DIR),
10971
+ join(projectRoot, CURSOR_AGENTS_DIR),
10782
10972
  join(projectRoot, CURSOR_COMMANDS_DIR)
10783
10973
  ];
10784
10974
  for (const p of candidates) {
10785
- const stat7 = await readFileSafe(p);
10786
- if (stat7 !== null && stat7.trim() !== "") return true;
10975
+ const stat8 = await readFileSafe(p);
10976
+ if (stat8 !== null && stat8.trim() !== "") return true;
10787
10977
  }
10788
- const skillFiles = await readDirRecursive(join(projectRoot, CURSOR_GLOBAL_SKILLS_DIR));
10978
+ const skillFiles = await readDirRecursive(join(projectRoot, CURSOR_SKILLS_DIR));
10789
10979
  if (skillFiles.some((f) => f.endsWith(".md"))) return true;
10790
- const agentFiles = await readDirRecursive(join(projectRoot, CURSOR_GLOBAL_AGENTS_DIR));
10980
+ const agentFiles = await readDirRecursive(join(projectRoot, CURSOR_AGENTS_DIR));
10791
10981
  if (agentFiles.some((f) => f.endsWith(".md"))) return true;
10792
10982
  const commandFiles = await readDirRecursive(join(projectRoot, CURSOR_COMMANDS_DIR));
10793
10983
  if (commandFiles.some((f) => f.endsWith(".md"))) return true;
@@ -10844,7 +11034,7 @@ async function importGlobalDotCursorAgents(projectRoot, results, normalize) {
10844
11034
  });
10845
11035
  }
10846
11036
  async function importGlobalMcp(projectRoot, results) {
10847
- const mcpPath = join(projectRoot, CURSOR_GLOBAL_MCP_EXPORT);
11037
+ const mcpPath = join(projectRoot, CURSOR_MCP);
10848
11038
  const content = await readFileSafe(mcpPath);
10849
11039
  if (content === null || content.trim() === "") return;
10850
11040
  let parsed;
@@ -10865,7 +11055,7 @@ async function importGlobalMcp(projectRoot, results) {
10865
11055
  });
10866
11056
  }
10867
11057
  async function importGlobalAgents(projectRoot, results, normalize) {
10868
- const agentsDir = join(projectRoot, CURSOR_GLOBAL_AGENTS_DIR);
11058
+ const agentsDir = join(projectRoot, CURSOR_AGENTS_DIR);
10869
11059
  const destDir = join(projectRoot, CURSOR_CANONICAL_AGENTS_DIR);
10870
11060
  results.push(
10871
11061
  ...await importFileDirectory({
@@ -10914,7 +11104,7 @@ async function importFromCursorGlobalExports(projectRoot) {
10914
11104
  if (!rootWritten) rootWritten = await importGlobalUserRules(projectRoot, results, normalize);
10915
11105
  if (!rootWritten) await importGlobalDotCursorAgents(projectRoot, results, normalize);
10916
11106
  await importGlobalMcp(projectRoot, results);
10917
- await importSkills3(projectRoot, results, normalize, CURSOR_GLOBAL_SKILLS_DIR);
11107
+ await importSkills3(projectRoot, results, normalize, CURSOR_SKILLS_DIR);
10918
11108
  await importGlobalAgents(projectRoot, results, normalize);
10919
11109
  await importGlobalCommands(projectRoot, results, normalize);
10920
11110
  await importSettings2(projectRoot, results);
@@ -11088,7 +11278,7 @@ var init_lint9 = __esm({
11088
11278
  });
11089
11279
 
11090
11280
  // src/targets/cursor/index.ts
11091
- var target12, project12, global6, globalCapabilities10, descriptor12;
11281
+ var target12, project12, globalLayout12, globalCapabilities10, descriptor12;
11092
11282
  var init_cursor2 = __esm({
11093
11283
  "src/targets/cursor/index.ts"() {
11094
11284
  init_generator14();
@@ -11138,7 +11328,7 @@ var init_cursor2 = __esm({
11138
11328
  }
11139
11329
  }
11140
11330
  };
11141
- global6 = {
11331
+ globalLayout12 = {
11142
11332
  rootInstructionPath: CURSOR_GENERAL_RULE,
11143
11333
  outputFamilies: [
11144
11334
  {
@@ -11147,18 +11337,13 @@ var init_cursor2 = __esm({
11147
11337
  explicitPaths: [CURSOR_COMPAT_AGENTS, CURSOR_DOT_CURSOR_AGENTS]
11148
11338
  }
11149
11339
  ],
11150
- skillDir: CURSOR_GLOBAL_SKILLS_DIR,
11340
+ skillDir: CURSOR_SKILLS_DIR,
11151
11341
  managedOutputs: {
11152
- dirs: [
11153
- CURSOR_RULES_DIR,
11154
- CURSOR_COMMANDS_DIR,
11155
- CURSOR_GLOBAL_AGENTS_DIR,
11156
- CURSOR_GLOBAL_SKILLS_DIR
11157
- ],
11342
+ dirs: [CURSOR_RULES_DIR, CURSOR_COMMANDS_DIR, CURSOR_AGENTS_DIR, CURSOR_SKILLS_DIR],
11158
11343
  files: [
11159
11344
  CURSOR_GENERAL_RULE,
11160
11345
  CURSOR_DOT_CURSOR_AGENTS,
11161
- CURSOR_GLOBAL_MCP_EXPORT,
11346
+ CURSOR_MCP,
11162
11347
  CURSOR_HOOKS,
11163
11348
  CURSOR_IGNORE,
11164
11349
  CURSOR_GLOBAL_USER_RULES
@@ -11187,7 +11372,7 @@ var init_cursor2 = __esm({
11187
11372
  return `${CURSOR_COMMANDS_DIR}/${name}.md`;
11188
11373
  },
11189
11374
  agentPath(name, _config) {
11190
- return `${CURSOR_GLOBAL_AGENTS_DIR}/${name}.md`;
11375
+ return `${CURSOR_AGENTS_DIR}/${name}.md`;
11191
11376
  }
11192
11377
  }
11193
11378
  };
@@ -11239,11 +11424,11 @@ var init_cursor2 = __esm({
11239
11424
  CURSOR_HOOKS,
11240
11425
  CURSOR_IGNORE,
11241
11426
  CURSOR_SKILLS_DIR,
11242
- CURSOR_GLOBAL_AGENTS_DIR,
11427
+ CURSOR_AGENTS_DIR,
11243
11428
  CURSOR_COMMANDS_DIR,
11244
11429
  CURSOR_GLOBAL_USER_RULES
11245
11430
  ],
11246
- layout: global6
11431
+ layout: globalLayout12
11247
11432
  },
11248
11433
  importer: {
11249
11434
  // Project-only declarable features. Rules/mcp/skills/settings/ignore stay
@@ -11402,7 +11587,7 @@ var init_lint10 = __esm({
11402
11587
  });
11403
11588
 
11404
11589
  // src/targets/deepagents-cli/index.ts
11405
- var target13, project13, globalLayout7, capabilities5, globalCapabilities11, descriptor13;
11590
+ var target13, project13, globalLayout13, capabilities5, globalCapabilities11, descriptor13;
11406
11591
  var init_deepagents_cli2 = __esm({
11407
11592
  "src/targets/deepagents-cli/index.ts"() {
11408
11593
  init_command_skill();
@@ -11442,7 +11627,7 @@ var init_deepagents_cli2 = __esm({
11442
11627
  }
11443
11628
  }
11444
11629
  };
11445
- globalLayout7 = {
11630
+ globalLayout13 = {
11446
11631
  rootInstructionPath: DEEPAGENTS_CLI_GLOBAL_ROOT_FILE,
11447
11632
  skillDir: DEEPAGENTS_CLI_GLOBAL_SKILLS_DIR,
11448
11633
  managedOutputs: {
@@ -11513,7 +11698,7 @@ var init_deepagents_cli2 = __esm({
11513
11698
  globalSupport: {
11514
11699
  capabilities: globalCapabilities11,
11515
11700
  detectionPaths: [DEEPAGENTS_CLI_GLOBAL_ROOT_FILE, DEEPAGENTS_CLI_GLOBAL_MCP_FILE],
11516
- layout: globalLayout7
11701
+ layout: globalLayout13
11517
11702
  },
11518
11703
  importer: {
11519
11704
  rules: {
@@ -11735,7 +11920,7 @@ var init_lint11 = __esm({
11735
11920
  });
11736
11921
 
11737
11922
  // src/targets/factory-droid/index.ts
11738
- var target14, project14, globalLayout8, capabilities6, descriptor14;
11923
+ var target14, project14, globalLayout14, capabilities6, descriptor14;
11739
11924
  var init_factory_droid2 = __esm({
11740
11925
  "src/targets/factory-droid/index.ts"() {
11741
11926
  init_generator16();
@@ -11774,7 +11959,7 @@ var init_factory_droid2 = __esm({
11774
11959
  }
11775
11960
  }
11776
11961
  };
11777
- globalLayout8 = {
11962
+ globalLayout14 = {
11778
11963
  rootInstructionPath: FACTORY_DROID_GLOBAL_ROOT_FILE,
11779
11964
  skillDir: FACTORY_DROID_GLOBAL_SKILLS_DIR,
11780
11965
  managedOutputs: {
@@ -11841,7 +12026,7 @@ var init_factory_droid2 = __esm({
11841
12026
  FACTORY_DROID_GLOBAL_MCP_FILE,
11842
12027
  FACTORY_DROID_GLOBAL_DROIDS_DIR
11843
12028
  ],
11844
- layout: globalLayout8
12029
+ layout: globalLayout14
11845
12030
  },
11846
12031
  importer: {
11847
12032
  rules: {
@@ -12784,7 +12969,7 @@ var init_scoped_settings_emit = __esm({
12784
12969
  });
12785
12970
 
12786
12971
  // src/targets/gemini-cli/index.ts
12787
- var target15, project15, global7, globalCapabilities12, descriptor15;
12972
+ var target15, project15, globalLayout15, globalCapabilities12, descriptor15;
12788
12973
  var init_gemini_cli2 = __esm({
12789
12974
  "src/targets/gemini-cli/index.ts"() {
12790
12975
  init_generator18();
@@ -12854,7 +13039,7 @@ var init_gemini_cli2 = __esm({
12854
13039
  }
12855
13040
  }
12856
13041
  };
12857
- global7 = {
13042
+ globalLayout15 = {
12858
13043
  rootInstructionPath: GEMINI_GLOBAL_ROOT,
12859
13044
  outputFamilies: [
12860
13045
  { id: "compat-agents", kind: "additional", explicitPaths: [GEMINI_GLOBAL_COMPAT_AGENTS] }
@@ -12965,7 +13150,7 @@ var init_gemini_cli2 = __esm({
12965
13150
  GEMINI_GLOBAL_SKILLS_DIR,
12966
13151
  GEMINI_GLOBAL_AGENTS_DIR
12967
13152
  ],
12968
- layout: global7
13153
+ layout: globalLayout15
12969
13154
  },
12970
13155
  importer: {
12971
13156
  rules: {
@@ -12986,7 +13171,8 @@ var init_gemini_cli2 = __esm({
12986
13171
  }
12987
13172
  },
12988
13173
  buildImportPaths: buildGeminiCliImportPaths,
12989
- detectionPaths: ["GEMINI.md", ".gemini"]
13174
+ detectionPaths: ["GEMINI.md", ".gemini"],
13175
+ conversionDefaults: { agentsToSkills: false }
12990
13176
  };
12991
13177
  }
12992
13178
  });
@@ -13113,7 +13299,7 @@ var init_lint13 = __esm({
13113
13299
  });
13114
13300
 
13115
13301
  // src/targets/goose/index.ts
13116
- var target16, project16, globalLayout9, capabilities7, descriptor16;
13302
+ var target16, project16, globalLayout16, capabilities7, descriptor16;
13117
13303
  var init_goose2 = __esm({
13118
13304
  "src/targets/goose/index.ts"() {
13119
13305
  init_command_skill();
@@ -13154,7 +13340,7 @@ var init_goose2 = __esm({
13154
13340
  }
13155
13341
  }
13156
13342
  };
13157
- globalLayout9 = {
13343
+ globalLayout16 = {
13158
13344
  rootInstructionPath: GOOSE_GLOBAL_ROOT_FILE,
13159
13345
  skillDir: GOOSE_GLOBAL_SKILLS_DIR,
13160
13346
  managedOutputs: {
@@ -13164,9 +13350,6 @@ var init_goose2 = __esm({
13164
13350
  rewriteGeneratedPath(path) {
13165
13351
  if (path === GOOSE_ROOT_FILE) return GOOSE_GLOBAL_ROOT_FILE;
13166
13352
  if (path === GOOSE_IGNORE) return GOOSE_GLOBAL_IGNORE;
13167
- if (path.startsWith(`${GOOSE_SKILLS_DIR}/`)) {
13168
- return path;
13169
- }
13170
13353
  return path;
13171
13354
  },
13172
13355
  mirrorGlobalPath(path, activeTargets) {
@@ -13217,7 +13400,7 @@ var init_goose2 = __esm({
13217
13400
  globalSupport: {
13218
13401
  capabilities: capabilities7,
13219
13402
  detectionPaths: [GOOSE_GLOBAL_ROOT_FILE, GOOSE_GLOBAL_IGNORE, GOOSE_GLOBAL_SKILLS_DIR],
13220
- layout: globalLayout9
13403
+ layout: globalLayout16
13221
13404
  },
13222
13405
  importer: {
13223
13406
  rules: {
@@ -13246,7 +13429,8 @@ var init_goose2 = __esm({
13246
13429
  ".agents/skills/": "consumer"
13247
13430
  },
13248
13431
  buildImportPaths: buildGooseImportPaths,
13249
- detectionPaths: [GOOSE_ROOT_FILE, GOOSE_IGNORE]
13432
+ detectionPaths: [GOOSE_ROOT_FILE, GOOSE_IGNORE],
13433
+ conversionDefaults: { commandsToSkills: true, agentsToSkills: true }
13250
13434
  };
13251
13435
  }
13252
13436
  });
@@ -13642,7 +13826,7 @@ var init_lint15 = __esm({
13642
13826
  });
13643
13827
 
13644
13828
  // src/targets/junie/index.ts
13645
- var target18, project18, global8, globalCapabilities13, descriptor18;
13829
+ var target18, project18, globalLayout17, globalCapabilities13, descriptor18;
13646
13830
  var init_junie2 = __esm({
13647
13831
  "src/targets/junie/index.ts"() {
13648
13832
  init_generator21();
@@ -13682,7 +13866,7 @@ var init_junie2 = __esm({
13682
13866
  }
13683
13867
  }
13684
13868
  };
13685
- global8 = {
13869
+ globalLayout17 = {
13686
13870
  rootInstructionPath: JUNIE_GLOBAL_AGENTS_MD,
13687
13871
  renderPrimaryRootInstruction: renderJunieGlobalInstructions,
13688
13872
  skillDir: JUNIE_GLOBAL_SKILLS_DIR,
@@ -13780,7 +13964,7 @@ var init_junie2 = __esm({
13780
13964
  JUNIE_GLOBAL_COMMANDS_DIR,
13781
13965
  JUNIE_GLOBAL_MCP_FILE
13782
13966
  ],
13783
- layout: global8
13967
+ layout: globalLayout17
13784
13968
  },
13785
13969
  importer: {
13786
13970
  rules: {
@@ -14177,7 +14361,7 @@ var init_lint16 = __esm({
14177
14361
  });
14178
14362
 
14179
14363
  // src/targets/kilo-code/index.ts
14180
- var target19, project19, globalLayout10, capabilities9, descriptor19;
14364
+ var target19, project19, globalLayout18, capabilities9, descriptor19;
14181
14365
  var init_kilo_code2 = __esm({
14182
14366
  "src/targets/kilo-code/index.ts"() {
14183
14367
  init_generator22();
@@ -14218,7 +14402,7 @@ var init_kilo_code2 = __esm({
14218
14402
  }
14219
14403
  }
14220
14404
  };
14221
- globalLayout10 = {
14405
+ globalLayout18 = {
14222
14406
  rootInstructionPath: KILO_CODE_GLOBAL_AGENTS_MD,
14223
14407
  skillDir: KILO_CODE_GLOBAL_SKILLS_DIR,
14224
14408
  managedOutputs: {
@@ -14289,7 +14473,7 @@ var init_kilo_code2 = __esm({
14289
14473
  KILO_CODE_GLOBAL_MCP_FILE,
14290
14474
  KILO_CODE_GLOBAL_IGNORE
14291
14475
  ],
14292
- layout: globalLayout10
14476
+ layout: globalLayout18
14293
14477
  },
14294
14478
  importer: {
14295
14479
  rules: [
@@ -14699,7 +14883,7 @@ var init_lint17 = __esm({
14699
14883
  });
14700
14884
 
14701
14885
  // src/targets/kiro/index.ts
14702
- var target20, project20, global9, globalCapabilities14, descriptor20;
14886
+ var target20, project20, globalLayout19, globalCapabilities14, descriptor20;
14703
14887
  var init_kiro2 = __esm({
14704
14888
  "src/targets/kiro/index.ts"() {
14705
14889
  init_command_skill();
@@ -14741,7 +14925,7 @@ var init_kiro2 = __esm({
14741
14925
  }
14742
14926
  }
14743
14927
  };
14744
- global9 = {
14928
+ globalLayout19 = {
14745
14929
  rootInstructionPath: KIRO_GLOBAL_STEERING_AGENTS_MD,
14746
14930
  skillDir: KIRO_GLOBAL_SKILLS_DIR,
14747
14931
  managedOutputs: {
@@ -14840,7 +15024,7 @@ var init_kiro2 = __esm({
14840
15024
  KIRO_GLOBAL_MCP_FILE,
14841
15025
  KIRO_GLOBAL_IGNORE
14842
15026
  ],
14843
- layout: global9
15027
+ layout: globalLayout19
14844
15028
  },
14845
15029
  importer: {
14846
15030
  agents: {
@@ -14874,7 +15058,8 @@ var init_kiro2 = __esm({
14874
15058
  KIRO_HOOKS_DIR,
14875
15059
  KIRO_MCP_FILE,
14876
15060
  KIRO_IGNORE
14877
- ]
15061
+ ],
15062
+ conversionDefaults: { commandsToSkills: true }
14878
15063
  };
14879
15064
  }
14880
15065
  });
@@ -15173,7 +15358,7 @@ var init_lint18 = __esm({
15173
15358
  });
15174
15359
 
15175
15360
  // src/targets/opencode/index.ts
15176
- var target21, project21, globalLayout11, capabilities10, descriptor21;
15361
+ var target21, project21, globalLayout20, capabilities10, descriptor21;
15177
15362
  var init_opencode2 = __esm({
15178
15363
  "src/targets/opencode/index.ts"() {
15179
15364
  init_generator24();
@@ -15213,7 +15398,7 @@ var init_opencode2 = __esm({
15213
15398
  }
15214
15399
  }
15215
15400
  };
15216
- globalLayout11 = {
15401
+ globalLayout20 = {
15217
15402
  rootInstructionPath: OPENCODE_GLOBAL_AGENTS_MD,
15218
15403
  skillDir: OPENCODE_GLOBAL_SKILLS_DIR,
15219
15404
  managedOutputs: {
@@ -15285,7 +15470,7 @@ var init_opencode2 = __esm({
15285
15470
  OPENCODE_GLOBAL_SKILLS_DIR,
15286
15471
  OPENCODE_GLOBAL_CONFIG_FILE
15287
15472
  ],
15288
- layout: globalLayout11
15473
+ layout: globalLayout20
15289
15474
  },
15290
15475
  importer: {
15291
15476
  rules: [
@@ -15478,7 +15663,7 @@ var init_lint19 = __esm({
15478
15663
  });
15479
15664
 
15480
15665
  // src/targets/pi-agent/index.ts
15481
- var target22, project22, globalLayout12, capabilities11, descriptor22;
15666
+ var target22, project22, globalLayout21, capabilities11, descriptor22;
15482
15667
  var init_pi_agent2 = __esm({
15483
15668
  "src/targets/pi-agent/index.ts"() {
15484
15669
  init_command_skill();
@@ -15518,7 +15703,7 @@ var init_pi_agent2 = __esm({
15518
15703
  }
15519
15704
  }
15520
15705
  };
15521
- globalLayout12 = {
15706
+ globalLayout21 = {
15522
15707
  rootInstructionPath: PI_AGENT_GLOBAL_ROOT_FILE,
15523
15708
  skillDir: PI_AGENT_GLOBAL_SKILLS_DIR,
15524
15709
  managedOutputs: {
@@ -15581,7 +15766,7 @@ var init_pi_agent2 = __esm({
15581
15766
  globalSupport: {
15582
15767
  capabilities: capabilities11,
15583
15768
  detectionPaths: [PI_AGENT_GLOBAL_ROOT_FILE],
15584
- layout: globalLayout12
15769
+ layout: globalLayout21
15585
15770
  },
15586
15771
  importer: {
15587
15772
  rules: {
@@ -15727,7 +15912,7 @@ var init_linter23 = __esm({
15727
15912
  });
15728
15913
 
15729
15914
  // src/targets/qwen-code/index.ts
15730
- var target23, project23, globalLayout13, capabilities12, globalCapabilities15, descriptor23;
15915
+ var target23, project23, globalLayout22, capabilities12, globalCapabilities15, descriptor23;
15731
15916
  var init_qwen_code2 = __esm({
15732
15917
  "src/targets/qwen-code/index.ts"() {
15733
15918
  init_generator26();
@@ -15766,7 +15951,7 @@ var init_qwen_code2 = __esm({
15766
15951
  }
15767
15952
  }
15768
15953
  };
15769
- globalLayout13 = {
15954
+ globalLayout22 = {
15770
15955
  rootInstructionPath: QWEN_GLOBAL_ROOT,
15771
15956
  skillDir: QWEN_GLOBAL_SKILLS_DIR,
15772
15957
  managedOutputs: {
@@ -15847,7 +16032,7 @@ var init_qwen_code2 = __esm({
15847
16032
  QWEN_GLOBAL_AGENTS_DIR,
15848
16033
  QWEN_GLOBAL_SKILLS_DIR
15849
16034
  ],
15850
- layout: globalLayout13
16035
+ layout: globalLayout22
15851
16036
  },
15852
16037
  importer: {
15853
16038
  rules: [
@@ -16336,7 +16521,7 @@ function computeStatus5(existing, content) {
16336
16521
  if (existing !== content) return "updated";
16337
16522
  return "unchanged";
16338
16523
  }
16339
- var target25, project25, generateRooGlobalExtras, global10, globalCapabilities16, descriptor25;
16524
+ var target25, project25, generateRooGlobalExtras, globalLayout23, globalCapabilities16, descriptor25;
16340
16525
  var init_roo_code2 = __esm({
16341
16526
  "src/targets/roo-code/index.ts"() {
16342
16527
  init_fs();
@@ -16399,7 +16584,7 @@ var init_roo_code2 = __esm({
16399
16584
  }
16400
16585
  ];
16401
16586
  };
16402
- global10 = {
16587
+ globalLayout23 = {
16403
16588
  rootInstructionPath: ROO_CODE_GLOBAL_AGENTS_MD,
16404
16589
  skillDir: ROO_CODE_GLOBAL_SKILLS_DIR,
16405
16590
  managedOutputs: {
@@ -16500,7 +16685,7 @@ var init_roo_code2 = __esm({
16500
16685
  ROO_CODE_GLOBAL_AGENTS_MD,
16501
16686
  ROO_CODE_GLOBAL_MODES_FILE
16502
16687
  ],
16503
- layout: global10,
16688
+ layout: globalLayout23,
16504
16689
  scopeExtras: generateRooGlobalExtras
16505
16690
  },
16506
16691
  importer: {
@@ -16692,7 +16877,7 @@ var init_lint21 = __esm({
16692
16877
  });
16693
16878
 
16694
16879
  // src/targets/rovodev/index.ts
16695
- var target26, project26, globalLayout14, capabilities14, globalCapabilities17, descriptor26;
16880
+ var target26, project26, globalLayout24, capabilities14, globalCapabilities17, descriptor26;
16696
16881
  var init_rovodev2 = __esm({
16697
16882
  "src/targets/rovodev/index.ts"() {
16698
16883
  init_command_skill();
@@ -16733,7 +16918,7 @@ var init_rovodev2 = __esm({
16733
16918
  }
16734
16919
  }
16735
16920
  };
16736
- globalLayout14 = {
16921
+ globalLayout24 = {
16737
16922
  rootInstructionPath: ROVODEV_GLOBAL_ROOT_FILE,
16738
16923
  skillDir: ROVODEV_GLOBAL_SKILLS_DIR,
16739
16924
  managedOutputs: {
@@ -16807,7 +16992,7 @@ var init_rovodev2 = __esm({
16807
16992
  globalSupport: {
16808
16993
  capabilities: globalCapabilities17,
16809
16994
  detectionPaths: [ROVODEV_GLOBAL_DIR, ROVODEV_GLOBAL_ROOT_FILE, ROVODEV_GLOBAL_SKILLS_DIR],
16810
- layout: globalLayout14
16995
+ layout: globalLayout24
16811
16996
  },
16812
16997
  importer: {
16813
16998
  rules: {
@@ -16976,7 +17161,7 @@ var init_linter27 = __esm({
16976
17161
  });
16977
17162
 
16978
17163
  // src/targets/trae/index.ts
16979
- var target27, project27, global11, globalCapabilities18, descriptor27;
17164
+ var target27, project27, globalLayout25, globalCapabilities18, descriptor27;
16980
17165
  var init_trae2 = __esm({
16981
17166
  "src/targets/trae/index.ts"() {
16982
17167
  init_generator30();
@@ -17013,7 +17198,7 @@ var init_trae2 = __esm({
17013
17198
  }
17014
17199
  }
17015
17200
  };
17016
- global11 = {
17201
+ globalLayout25 = {
17017
17202
  rootInstructionPath: TRAE_GLOBAL_ROOT_RULE,
17018
17203
  skillDir: TRAE_GLOBAL_SKILLS_DIR,
17019
17204
  managedOutputs: {
@@ -17096,7 +17281,7 @@ var init_trae2 = __esm({
17096
17281
  TRAE_GLOBAL_SKILLS_DIR,
17097
17282
  TRAE_GLOBAL_MCP_FILE
17098
17283
  ],
17099
- layout: global11
17284
+ layout: globalLayout25
17100
17285
  },
17101
17286
  importer: {
17102
17287
  mcp: {
@@ -17243,7 +17428,7 @@ var init_lint22 = __esm({
17243
17428
  });
17244
17429
 
17245
17430
  // src/targets/warp/index.ts
17246
- var target28, project28, globalLayout15, capabilities15, globalCapabilities19, descriptor28;
17431
+ var target28, project28, globalLayout26, capabilities15, globalCapabilities19, descriptor28;
17247
17432
  var init_warp2 = __esm({
17248
17433
  "src/targets/warp/index.ts"() {
17249
17434
  init_command_skill();
@@ -17284,7 +17469,7 @@ var init_warp2 = __esm({
17284
17469
  }
17285
17470
  }
17286
17471
  };
17287
- globalLayout15 = {
17472
+ globalLayout26 = {
17288
17473
  rootInstructionPath: void 0,
17289
17474
  skillDir: WARP_GLOBAL_SKILLS_DIR,
17290
17475
  managedOutputs: {
@@ -17302,7 +17487,7 @@ var init_warp2 = __esm({
17302
17487
  },
17303
17488
  paths: {
17304
17489
  rulePath() {
17305
- return WARP_GLOBAL_SKILLS_DIR;
17490
+ return null;
17306
17491
  },
17307
17492
  commandPath(name) {
17308
17493
  return `${WARP_GLOBAL_SKILLS_DIR}/${commandSkillDirName(name)}/SKILL.md`;
@@ -17356,7 +17541,7 @@ var init_warp2 = __esm({
17356
17541
  globalSupport: {
17357
17542
  capabilities: globalCapabilities19,
17358
17543
  detectionPaths: [WARP_GLOBAL_SKILLS_DIR],
17359
- layout: globalLayout15
17544
+ layout: globalLayout26
17360
17545
  },
17361
17546
  importer: {
17362
17547
  rules: {
@@ -17380,7 +17565,8 @@ var init_warp2 = __esm({
17380
17565
  }
17381
17566
  },
17382
17567
  buildImportPaths: buildWarpImportPaths,
17383
- detectionPaths: [WARP_ROOT_FILE, WARP_LEGACY_ROOT_FILE, WARP_MCP_FILE]
17568
+ detectionPaths: [WARP_ROOT_FILE, WARP_LEGACY_ROOT_FILE, WARP_MCP_FILE],
17569
+ conversionDefaults: { commandsToSkills: true, agentsToSkills: true }
17384
17570
  };
17385
17571
  }
17386
17572
  });
@@ -18005,7 +18191,7 @@ function directoryScopedRuleDir2(globs) {
18005
18191
  if (dirs.length !== globs.length) return null;
18006
18192
  return dirs.every((dir) => dir === dirs[0]) ? dirs[0] : null;
18007
18193
  }
18008
- var target29, project29, global12, globalCapabilities20, descriptor29;
18194
+ var target29, project29, globalLayout27, globalCapabilities20, descriptor29;
18009
18195
  var init_windsurf2 = __esm({
18010
18196
  "src/targets/windsurf/index.ts"() {
18011
18197
  init_generator33();
@@ -18059,7 +18245,7 @@ var init_windsurf2 = __esm({
18059
18245
  }
18060
18246
  }
18061
18247
  };
18062
- global12 = {
18248
+ globalLayout27 = {
18063
18249
  rootInstructionPath: WINDSURF_GLOBAL_RULES,
18064
18250
  skillDir: WINDSURF_GLOBAL_SKILLS_DIR,
18065
18251
  managedOutputs: {
@@ -18163,10 +18349,11 @@ var init_windsurf2 = __esm({
18163
18349
  WINDSURF_GLOBAL_MCP_FILE,
18164
18350
  WINDSURF_GLOBAL_IGNORE
18165
18351
  ],
18166
- layout: global12
18352
+ layout: globalLayout27
18167
18353
  },
18168
18354
  buildImportPaths: buildWindsurfImportPaths,
18169
- detectionPaths: [".windsurfrules", ".windsurf"]
18355
+ detectionPaths: [".windsurfrules", ".windsurf"],
18356
+ conversionDefaults: { agentsToSkills: true }
18170
18357
  };
18171
18358
  }
18172
18359
  });
@@ -18327,7 +18514,7 @@ function mergeZedSettings(existing, newContent) {
18327
18514
  }
18328
18515
  return JSON.stringify(base, null, 2);
18329
18516
  }
18330
- var target30, project30, globalLayout16, capabilities16, globalCapabilities21, descriptor30;
18517
+ var target30, project30, globalLayout28, capabilities16, globalCapabilities21, descriptor30;
18331
18518
  var init_zed2 = __esm({
18332
18519
  "src/targets/zed/index.ts"() {
18333
18520
  init_generator34();
@@ -18360,7 +18547,7 @@ var init_zed2 = __esm({
18360
18547
  }
18361
18548
  }
18362
18549
  };
18363
- globalLayout16 = {
18550
+ globalLayout28 = {
18364
18551
  rootInstructionPath: void 0,
18365
18552
  managedOutputs: {
18366
18553
  dirs: [],
@@ -18425,7 +18612,7 @@ var init_zed2 = __esm({
18425
18612
  globalSupport: {
18426
18613
  capabilities: globalCapabilities21,
18427
18614
  detectionPaths: [ZED_GLOBAL_SETTINGS_FILE],
18428
- layout: globalLayout16
18615
+ layout: globalLayout28
18429
18616
  },
18430
18617
  importer: {
18431
18618
  rules: {
@@ -19031,13 +19218,79 @@ function rewriteGeneratedReferences(results, canonical, config, projectRoot, sco
19031
19218
  // src/core/reference/validate-generated-markdown-links.ts
19032
19219
  init_path_helpers();
19033
19220
  init_link_rebaser_helpers();
19034
- var INLINE_MD_LINK = /!?\[[^\]]*\]\(([^)]+)\)/g;
19035
- var REF_LINK_DEF = /^\s*\[[^\]\n]+\]:\s*(?:<([^>\n]*)>|(\S+))/gm;
19036
- function isMarkdownLikeOutput(relativePath) {
19037
- return relativePath.endsWith(".md") || relativePath.endsWith(".mdc");
19221
+
19222
+ // src/utils/output/logger.ts
19223
+ var C = {
19224
+ green: "\x1B[32m",
19225
+ red: "\x1B[31m",
19226
+ yellow: "\x1B[33m",
19227
+ cyan: "\x1B[36m",
19228
+ reset: "\x1B[0m"
19229
+ };
19230
+ function out(text) {
19231
+ {
19232
+ process.stdout.write(text);
19233
+ }
19038
19234
  }
19039
- function isOffsetInRanges(offset, ranges) {
19040
- return ranges.some(([start, end]) => offset >= start && offset < end);
19235
+ function noColor() {
19236
+ return process.env.NO_COLOR !== void 0 && process.env.NO_COLOR !== "";
19237
+ }
19238
+ function c(code, text) {
19239
+ return noColor() ? text : `${code}${text}${C.reset}`;
19240
+ }
19241
+ function pad(str, width) {
19242
+ const len = [...str].length;
19243
+ return str + " ".repeat(Math.max(0, width - len));
19244
+ }
19245
+ var logger = {
19246
+ info(msg) {
19247
+ out(c(C.cyan, msg) + "\n");
19248
+ },
19249
+ warn(msg) {
19250
+ process.stderr.write(c(C.yellow, "\u26A0 ") + msg + "\n");
19251
+ },
19252
+ error(msg) {
19253
+ process.stderr.write(c(C.red, "\u2717 ") + msg + "\n");
19254
+ },
19255
+ success(msg) {
19256
+ out(c(C.green, "\u2713 ") + msg + "\n");
19257
+ },
19258
+ debug(msg) {
19259
+ if (process.env.AGENTSMESH_DEBUG === "1") {
19260
+ out(c(C.cyan, "[debug] ") + msg + "\n");
19261
+ }
19262
+ },
19263
+ table(rows) {
19264
+ if (rows.length === 0) return;
19265
+ const cols = rows[0].length;
19266
+ const widths = [];
19267
+ for (let j = 0; j < cols; j++) {
19268
+ let max = 0;
19269
+ for (let i = 0; i < rows.length; i++) {
19270
+ const len = [...rows[i][j]].length;
19271
+ if (len > max) max = len;
19272
+ }
19273
+ widths[j] = max;
19274
+ }
19275
+ const border = "+" + widths.map((w) => "-".repeat(w + 2)).join("+") + "+";
19276
+ out(border + "\n");
19277
+ for (let i = 0; i < rows.length; i++) {
19278
+ const row = rows[i];
19279
+ const line = "| " + row.map((cell, j) => pad(cell, widths[j])).join(" | ") + " |";
19280
+ out(line + "\n");
19281
+ }
19282
+ out(border + "\n");
19283
+ }
19284
+ };
19285
+
19286
+ // src/core/reference/validate-generated-markdown-links.ts
19287
+ var INLINE_MD_LINK = /!?\[[^\]]*\]\(([^)]+)\)/g;
19288
+ var REF_LINK_DEF = /^\s*\[[^\]\n]+\]:\s*(?:<([^>\n]*)>|(\S+))/gm;
19289
+ function isMarkdownLikeOutput(relativePath) {
19290
+ return relativePath.endsWith(".md") || relativePath.endsWith(".mdc");
19291
+ }
19292
+ function isOffsetInRanges(offset, ranges) {
19293
+ return ranges.some(([start, end]) => offset >= start && offset < end);
19041
19294
  }
19042
19295
  function parseMarkdownLinkDestination(raw) {
19043
19296
  let s = raw.trim();
@@ -19046,7 +19299,7 @@ function parseMarkdownLinkDestination(raw) {
19046
19299
  if (s.startsWith("<") && s.endsWith(">")) s = s.slice(1, -1).trim();
19047
19300
  return s;
19048
19301
  }
19049
- function shouldSkipLocalValidation(pathPart) {
19302
+ function shouldSkipLocalValidation(pathPart, projectRoot) {
19050
19303
  const t = pathPart.trim();
19051
19304
  if (!t) return true;
19052
19305
  if (t.startsWith("#")) return true;
@@ -19057,8 +19310,66 @@ function shouldSkipLocalValidation(pathPart) {
19057
19310
  if (/^ftp:/i.test(t)) return true;
19058
19311
  if (/^[a-zA-Z]:[\\/]/.test(t)) return false;
19059
19312
  if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(t)) return true;
19313
+ if (t.startsWith("/")) {
19314
+ const normalizedRoot = normalizeForProject(projectRoot, projectRoot);
19315
+ const normalizedAbs = normalizeForProject(projectRoot, t);
19316
+ if (!normalizedAbs.startsWith(`${normalizedRoot}/`) && normalizedAbs !== normalizedRoot) {
19317
+ return true;
19318
+ }
19319
+ }
19060
19320
  return false;
19061
19321
  }
19322
+ function isSkillGeneratedOutput(relativePath) {
19323
+ return /(?:^|\/)[^/]+\/skills\/[^/]+\//.test(relativePath);
19324
+ }
19325
+ var OUTPUT_DIR_TO_FEATURE = {
19326
+ rules: "rules",
19327
+ steering: "rules",
19328
+ commands: "commands",
19329
+ agents: "agents",
19330
+ skills: "skills",
19331
+ // factory-droid: native agent definitions land in `.factory/droids/<name>.md`.
19332
+ // Treat the directory as the agents feature so pack-originated key matching
19333
+ // recognizes those outputs and downgrades broken links to advisory warnings.
19334
+ droids: "agents",
19335
+ // copilot project layout: rules emit per-glob into `.github/instructions/`,
19336
+ // commands into `.github/prompts/`. Map both to their canonical features so
19337
+ // pack-originated outputs from those dirs match the same keys as their
19338
+ // canonical counterparts.
19339
+ instructions: "rules",
19340
+ prompts: "commands"
19341
+ };
19342
+ var TOP_LEVEL_DIR_TO_FEATURE = {
19343
+ ".clinerules": "rules"
19344
+ };
19345
+ var COMPOUND_MARKDOWN_SUFFIXES = [".agent.md", ".instructions.md", ".prompt.md"];
19346
+ function stripMarkdownExt(name) {
19347
+ for (const suffix of COMPOUND_MARKDOWN_SUFFIXES) {
19348
+ if (name.endsWith(suffix)) return name.slice(0, -suffix.length);
19349
+ }
19350
+ if (name.endsWith(".mdc")) return name.slice(0, -4);
19351
+ if (name.endsWith(".md")) return name.slice(0, -3);
19352
+ return name;
19353
+ }
19354
+ function canonicalKeyFromOutputPath(relativePath) {
19355
+ const m = /^[^/]+\/([^/]+)\/([^/]+)/.exec(relativePath);
19356
+ if (m) {
19357
+ const feature = OUTPUT_DIR_TO_FEATURE[m[1] ?? ""];
19358
+ if (feature) {
19359
+ let name = m[2] ?? "";
19360
+ if (feature !== "skills") name = stripMarkdownExt(name);
19361
+ return `${feature}/${name}`;
19362
+ }
19363
+ }
19364
+ const m2 = /^([^/]+)\/([^/]+)/.exec(relativePath);
19365
+ if (m2) {
19366
+ const feature = TOP_LEVEL_DIR_TO_FEATURE[m2[1] ?? ""];
19367
+ if (feature) {
19368
+ return `${feature}/${stripMarkdownExt(m2[2] ?? "")}`;
19369
+ }
19370
+ }
19371
+ return null;
19372
+ }
19062
19373
  function pathExistsForGenerate(absolutePath, planned) {
19063
19374
  if (planned.has(absolutePath)) return true;
19064
19375
  try {
@@ -19081,7 +19392,7 @@ function resolveMarkdownLinkTargets(rawDestination, projectRoot, destinationFile
19081
19392
  } catch {
19082
19393
  decoded = pathPart;
19083
19394
  }
19084
- if (shouldSkipLocalValidation(decoded)) return [];
19395
+ if (shouldSkipLocalValidation(decoded, projectRoot)) return [];
19085
19396
  let candidates = resolveProjectPath(decoded, projectRoot, destinationFileAbs);
19086
19397
  if (candidates.length === 0) {
19087
19398
  const api = pathApi(projectRoot);
@@ -19135,10 +19446,32 @@ function findBrokenMarkdownLinks(results, projectRoot) {
19135
19446
  }
19136
19447
  return broken;
19137
19448
  }
19138
- function validateGeneratedMarkdownLinks(results, projectRoot) {
19449
+ function validateGeneratedMarkdownLinks(results, projectRoot, options = {}) {
19139
19450
  const broken = findBrokenMarkdownLinks(results, projectRoot);
19140
19451
  if (broken.length === 0) return;
19141
- const lines = broken.map(
19452
+ const packKeys = options.packOriginatedKeys;
19453
+ const errors = [];
19454
+ const warnings = [];
19455
+ for (const b of broken) {
19456
+ const key = canonicalKeyFromOutputPath(b.generatePath);
19457
+ const isPackOriginated = packKeys !== void 0 && key !== null && packKeys.has(key);
19458
+ if (isSkillGeneratedOutput(b.generatePath) || isPackOriginated) {
19459
+ warnings.push(b);
19460
+ } else {
19461
+ errors.push(b);
19462
+ }
19463
+ }
19464
+ if (warnings.length > 0) {
19465
+ const lines2 = warnings.map(
19466
+ (b) => ` ${b.generatePath} (${b.target}): "${b.rawLink}" \u2192 not found`
19467
+ );
19468
+ logger.warn(
19469
+ `Third-party content contains ${warnings.length} broken local link${warnings.length === 1 ? "" : "s"} (warning only; outputs from installed packs and skill subtrees are treated as advisory):
19470
+ ${lines2.join("\n")}`
19471
+ );
19472
+ }
19473
+ if (errors.length === 0) return;
19474
+ const lines = errors.map(
19142
19475
  (b) => ` ${b.generatePath} (${b.target}): "${b.rawLink}" \u2192 not found (tried: ${b.checkedPaths.join(", ")})`
19143
19476
  );
19144
19477
  throw new Error(
@@ -19147,6 +19480,37 @@ ${lines.join("\n")}
19147
19480
  Fix canonical sources or generators so every local link targets an existing file or folder.`
19148
19481
  );
19149
19482
  }
19483
+ var PACK_MARKERS = [
19484
+ `${sep}.agentsmesh${sep}packs${sep}`,
19485
+ "/.agentsmesh/packs/"
19486
+ ];
19487
+ function isUnderPacks(sourcePath) {
19488
+ return PACK_MARKERS.some((marker) => sourcePath.includes(marker));
19489
+ }
19490
+ function buildPackOriginatedKeys(canonical) {
19491
+ const keys = /* @__PURE__ */ new Set();
19492
+ for (const rule of canonical.rules) {
19493
+ if (isUnderPacks(rule.source)) {
19494
+ const name = rule.root ? "_root" : ruleNameFromSource(rule.source);
19495
+ if (name) keys.add(`rules/${name}`);
19496
+ }
19497
+ }
19498
+ for (const agent of canonical.agents) {
19499
+ if (isUnderPacks(agent.source)) keys.add(`agents/${agent.name}`);
19500
+ }
19501
+ for (const cmd of canonical.commands) {
19502
+ if (isUnderPacks(cmd.source)) keys.add(`commands/${cmd.name}`);
19503
+ }
19504
+ for (const skill of canonical.skills) {
19505
+ if (isUnderPacks(skill.source)) keys.add(`skills/${skill.name}`);
19506
+ }
19507
+ return keys;
19508
+ }
19509
+ function ruleNameFromSource(source) {
19510
+ const slash = source.replace(/\\/g, "/");
19511
+ const base = slash.split("/").pop() ?? "";
19512
+ return base.endsWith(".md") ? base.slice(0, -3) : base;
19513
+ }
19150
19514
 
19151
19515
  // src/core/generate/collision.ts
19152
19516
  init_target_ids();
@@ -19174,6 +19538,19 @@ function mergeDuplicateMetadata(preferred, other) {
19174
19538
  function trimmedContent(content) {
19175
19539
  return content.trim();
19176
19540
  }
19541
+ var OPTIONAL_AGENTS_BLOCKS = [
19542
+ /<!-- agentsmesh:embedded-rules:start -->[\s\S]*?<!-- agentsmesh:embedded-rules:end -->\n*/g
19543
+ ];
19544
+ function normalizeAgentsContent(content) {
19545
+ let out2 = content;
19546
+ for (const block of OPTIONAL_AGENTS_BLOCKS) {
19547
+ out2 = out2.replace(block, "");
19548
+ }
19549
+ return out2.trim().replace(/\n{2,}/g, "\n\n");
19550
+ }
19551
+ function hasOptionalAgentsBlock(content) {
19552
+ return /<!-- agentsmesh:embedded-rules:start -->/.test(content);
19553
+ }
19177
19554
  function richerAgentsResult(left, right) {
19178
19555
  if (!left.path.endsWith(AGENTS_SUFFIX) || left.path !== right.path) return null;
19179
19556
  const leftTrimmed = trimmedContent(left.content);
@@ -19181,8 +19558,15 @@ function richerAgentsResult(left, right) {
19181
19558
  if (!leftTrimmed || !rightTrimmed) return null;
19182
19559
  const leftContainsRight = leftTrimmed.includes(rightTrimmed);
19183
19560
  const rightContainsLeft = rightTrimmed.includes(leftTrimmed);
19184
- if (leftContainsRight === rightContainsLeft) return null;
19185
- return leftContainsRight ? left : right;
19561
+ if (leftContainsRight !== rightContainsLeft) {
19562
+ return leftContainsRight ? left : right;
19563
+ }
19564
+ if (normalizeAgentsContent(left.content) === normalizeAgentsContent(right.content)) {
19565
+ const leftHas = hasOptionalAgentsBlock(left.content);
19566
+ const rightHas = hasOptionalAgentsBlock(right.content);
19567
+ if (leftHas !== rightHas) return leftHas ? left : right;
19568
+ }
19569
+ return null;
19186
19570
  }
19187
19571
  function richerCodexAgentsResult(left, right) {
19188
19572
  if (!left.path.endsWith(AGENTS_SUFFIX) || left.path !== right.path) return null;
@@ -19487,7 +19871,9 @@ async function generate(ctx) {
19487
19871
  targets,
19488
19872
  sharedPaths
19489
19873
  );
19490
- validateGeneratedMarkdownLinks(rewrittenResults, projectRoot);
19874
+ validateGeneratedMarkdownLinks(rewrittenResults, projectRoot, {
19875
+ packOriginatedKeys: buildPackOriginatedKeys(canonical)
19876
+ });
19491
19877
  return resolveOutputCollisions(rewrittenResults.map(refreshResultStatus));
19492
19878
  }
19493
19879
  function computeSharedRootInstructionPaths(results, scope) {
@@ -19524,72 +19910,6 @@ init_errors();
19524
19910
 
19525
19911
  // src/config/core/loader.ts
19526
19912
  init_fs();
19527
-
19528
- // src/utils/output/logger.ts
19529
- var C = {
19530
- green: "\x1B[32m",
19531
- red: "\x1B[31m",
19532
- yellow: "\x1B[33m",
19533
- cyan: "\x1B[36m",
19534
- reset: "\x1B[0m"
19535
- };
19536
- function out(text) {
19537
- {
19538
- process.stdout.write(text);
19539
- }
19540
- }
19541
- function noColor() {
19542
- return process.env.NO_COLOR !== void 0 && process.env.NO_COLOR !== "";
19543
- }
19544
- function c(code, text) {
19545
- return noColor() ? text : `${code}${text}${C.reset}`;
19546
- }
19547
- function pad(str, width) {
19548
- const len = [...str].length;
19549
- return str + " ".repeat(Math.max(0, width - len));
19550
- }
19551
- var logger = {
19552
- info(msg) {
19553
- out(c(C.cyan, msg) + "\n");
19554
- },
19555
- warn(msg) {
19556
- process.stderr.write(c(C.yellow, "\u26A0 ") + msg + "\n");
19557
- },
19558
- error(msg) {
19559
- process.stderr.write(c(C.red, "\u2717 ") + msg + "\n");
19560
- },
19561
- success(msg) {
19562
- out(c(C.green, "\u2713 ") + msg + "\n");
19563
- },
19564
- debug(msg) {
19565
- if (process.env.AGENTSMESH_DEBUG === "1") {
19566
- out(c(C.cyan, "[debug] ") + msg + "\n");
19567
- }
19568
- },
19569
- table(rows) {
19570
- if (rows.length === 0) return;
19571
- const cols = rows[0].length;
19572
- const widths = [];
19573
- for (let j = 0; j < cols; j++) {
19574
- let max = 0;
19575
- for (let i = 0; i < rows.length; i++) {
19576
- const len = [...rows[i][j]].length;
19577
- if (len > max) max = len;
19578
- }
19579
- widths[j] = max;
19580
- }
19581
- const border = "+" + widths.map((w) => "-".repeat(w + 2)).join("+") + "+";
19582
- out(border + "\n");
19583
- for (let i = 0; i < rows.length; i++) {
19584
- const row = rows[i];
19585
- const line = "| " + row.map((cell, j) => pad(cell, widths[j])).join(" | ") + " |";
19586
- out(line + "\n");
19587
- }
19588
- out(border + "\n");
19589
- }
19590
- };
19591
-
19592
- // src/config/core/loader.ts
19593
19913
  init_errors();
19594
19914
 
19595
19915
  // src/config/core/schema.ts
@@ -19606,6 +19926,7 @@ var VALID_FEATURES = [
19606
19926
  ];
19607
19927
  var targetSchema = z.enum(TARGET_IDS);
19608
19928
  var featureSchema = z.enum(VALID_FEATURES);
19929
+ var installAsSchema = z.enum(["rules", "commands", "agents", "skills"]);
19609
19930
  var extendPickSchema = z.object({
19610
19931
  skills: z.array(z.string()).optional(),
19611
19932
  commands: z.array(z.string()).optional(),
@@ -19617,6 +19938,7 @@ var extendSourceSchema = z.object({
19617
19938
  source: z.string(),
19618
19939
  version: z.string().optional(),
19619
19940
  target: targetSchema.optional(),
19941
+ as: installAsSchema.optional(),
19620
19942
  features: z.array(featureSchema),
19621
19943
  /** Repo-relative POSIX path for discovery (skill packs, nested .agentsmesh). */
19622
19944
  path: z.string().optional(),
@@ -19696,10 +20018,12 @@ async function loadConfig(configPath) {
19696
20018
  }
19697
20019
  return result.data;
19698
20020
  }
20021
+ var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
19699
20022
  function deepMergeObjects(base, overrides2) {
19700
20023
  const result = { ...base };
19701
20024
  for (const [k, v] of Object.entries(overrides2)) {
19702
20025
  if (v === null || v === void 0) continue;
20026
+ if (PROTOTYPE_POLLUTION_KEYS.has(k)) continue;
19703
20027
  const baseVal = result[k];
19704
20028
  if (typeof v === "object" && !Array.isArray(v) && v !== null && typeof baseVal === "object" && baseVal !== null && !Array.isArray(baseVal)) {
19705
20029
  result[k] = deepMergeObjects(
@@ -19907,7 +20231,28 @@ async function runGit(args, cwd) {
19907
20231
 
19908
20232
  // src/config/remote/github-remote.ts
19909
20233
  init_fs();
19910
- var MAX_TARBALL_BYTES = 500 * 1024 * 1024;
20234
+ var DEFAULT_MAX_TARBALL_MB = 500;
20235
+ var MIN_MAX_TARBALL_MB = 1;
20236
+ var MAX_MAX_TARBALL_MB = 4096;
20237
+ function resolveMaxTarballBytes() {
20238
+ const raw = process.env.AGENTSMESH_MAX_TARBALL_MB;
20239
+ if (raw === void 0 || raw === "") return DEFAULT_MAX_TARBALL_MB * 1024 * 1024;
20240
+ const parsed = Number(raw);
20241
+ if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) {
20242
+ console.warn(
20243
+ `[agentsmesh] AGENTSMESH_MAX_TARBALL_MB="${raw}" is not an integer; using default ${DEFAULT_MAX_TARBALL_MB} MiB.`
20244
+ );
20245
+ return DEFAULT_MAX_TARBALL_MB * 1024 * 1024;
20246
+ }
20247
+ if (parsed < MIN_MAX_TARBALL_MB || parsed > MAX_MAX_TARBALL_MB) {
20248
+ console.warn(
20249
+ `[agentsmesh] AGENTSMESH_MAX_TARBALL_MB=${parsed} is outside [${MIN_MAX_TARBALL_MB}, ${MAX_MAX_TARBALL_MB}]; using default ${DEFAULT_MAX_TARBALL_MB} MiB.`
20250
+ );
20251
+ return DEFAULT_MAX_TARBALL_MB * 1024 * 1024;
20252
+ }
20253
+ return parsed * 1024 * 1024;
20254
+ }
20255
+ var MAX_TARBALL_BYTES = resolveMaxTarballBytes();
19911
20256
  async function readBoundedResponse(res, maxBytes) {
19912
20257
  const lenHeader = typeof res.headers?.get === "function" ? res.headers.get("content-length") : null;
19913
20258
  if (lenHeader !== null) {
@@ -20115,7 +20460,9 @@ function parseGitSource(source) {
20115
20460
  } catch {
20116
20461
  return null;
20117
20462
  }
20118
- if (!["https:", "http:", "ssh:", "file:"].includes(parsedUrl.protocol)) {
20463
+ const allowInsecure = process.env.AGENTSMESH_ALLOW_INSECURE_GIT === "1" || process.env.AGENTSMESH_ALLOW_INSECURE_GIT === "true";
20464
+ const allowedProtocols = allowInsecure ? ["https:", "http:", "ssh:", "file:"] : ["https:", "ssh:", "file:"];
20465
+ if (!allowedProtocols.includes(parsedUrl.protocol)) {
20119
20466
  return null;
20120
20467
  }
20121
20468
  return { url, ref };
@@ -20257,6 +20604,7 @@ async function resolveExtendPaths(config, configDir, options = {}) {
20257
20604
  resolvedPath: fetched.resolvedPath,
20258
20605
  features: [...ext.features],
20259
20606
  target: ext.target,
20607
+ as: ext.as,
20260
20608
  version: fetched.version,
20261
20609
  path: ext.path,
20262
20610
  pick: ext.pick
@@ -20274,6 +20622,7 @@ async function resolveExtendPaths(config, configDir, options = {}) {
20274
20622
  resolvedPath,
20275
20623
  features: [...ext.features],
20276
20624
  target: ext.target,
20625
+ as: ext.as,
20277
20626
  path: ext.path,
20278
20627
  pick: ext.pick
20279
20628
  });
@@ -20374,6 +20723,28 @@ function assertNoBasenameCollisions(feature, paths, stripExt) {
20374
20723
  seen.set(slug, p);
20375
20724
  }
20376
20725
  }
20726
+ var ALTERNATE_RESOURCE_FORMATS = /* @__PURE__ */ new Set([".toml", ".yaml", ".yml", ".json"]);
20727
+ function warnIfUnrecognizedResourceFormats(featureLabel, dir, allFiles, parsedFiles, opts = {}) {
20728
+ if (allFiles.length === 0) return;
20729
+ const parsed = new Set(parsedFiles);
20730
+ const handled = opts.handledByOtherReader;
20731
+ const formats = /* @__PURE__ */ new Set();
20732
+ let droppedCount = 0;
20733
+ for (const f of allFiles) {
20734
+ if (parsed.has(f)) continue;
20735
+ if (basename(f).startsWith(".")) continue;
20736
+ const ext = extname(f).toLowerCase();
20737
+ if (!ALTERNATE_RESOURCE_FORMATS.has(ext)) continue;
20738
+ if (handled?.has(ext)) continue;
20739
+ formats.add(ext);
20740
+ droppedCount++;
20741
+ }
20742
+ if (droppedCount === 0) return;
20743
+ const formatList = [...formats].sort().join(", ");
20744
+ logger.warn(
20745
+ `Skipped ${droppedCount} ${featureLabel} file(s) in ${dir} (format${formats.size === 1 ? "" : "s"}: ${formatList}). agentsmesh ${featureLabel} are parsed from .md files only.`
20746
+ );
20747
+ }
20377
20748
 
20378
20749
  // src/canonical/features/rules.ts
20379
20750
  var VALID_TRIGGERS = ["always_on", "model_decision", "glob", "manual"];
@@ -20382,18 +20753,23 @@ function toStrArray(v) {
20382
20753
  if (typeof v === "string") return v ? [v] : [];
20383
20754
  return [];
20384
20755
  }
20385
- async function parseRules(rulesDir) {
20756
+ async function parseRules(rulesDir, opts = {}) {
20386
20757
  const files = await readDirRecursive(rulesDir);
20387
20758
  const mdFiles = files.filter((f) => {
20388
20759
  if (!f.endsWith(".md")) return false;
20389
20760
  const name = basename(f, ".md");
20390
20761
  return name === "_root" || !name.startsWith("_");
20391
20762
  });
20763
+ warnIfUnrecognizedResourceFormats("rules", rulesDir, files, mdFiles, {
20764
+ handledByOtherReader: opts.handledByOtherReader
20765
+ });
20392
20766
  const rules = [];
20393
20767
  for (const path of mdFiles) {
20394
20768
  const content = await readFileSafe(path);
20395
20769
  if (!content) continue;
20396
- const { frontmatter, body } = parseFrontmatter(content);
20770
+ const parsed = parseOrSkipFrontmatter(content, path, opts.onParseError);
20771
+ if (!parsed) continue;
20772
+ const { frontmatter, body } = parsed;
20397
20773
  const name = basename(path, ".md");
20398
20774
  assertCanonicalName("rule", name);
20399
20775
  const rootFromFilename = name === "_root";
@@ -20434,15 +20810,20 @@ function toToolsArray2(v) {
20434
20810
  }
20435
20811
  return [];
20436
20812
  }
20437
- async function parseCommands(commandsDir) {
20813
+ async function parseCommands(commandsDir, opts = {}) {
20438
20814
  const files = await readDirRecursive(commandsDir);
20439
20815
  const mdFiles = files.filter((f) => f.endsWith(".md") && !basename(f).startsWith("_"));
20816
+ warnIfUnrecognizedResourceFormats("commands", commandsDir, files, mdFiles, {
20817
+ handledByOtherReader: opts.handledByOtherReader
20818
+ });
20440
20819
  assertNoBasenameCollisions("command", mdFiles, ".md");
20441
20820
  const commands = [];
20442
20821
  for (const path of mdFiles) {
20443
20822
  const content = await readFileSafe(path);
20444
20823
  if (!content) continue;
20445
- const { frontmatter, body } = parseFrontmatter(content);
20824
+ const parsed = parseOrSkipFrontmatter(content, path, opts.onParseError);
20825
+ if (!parsed) continue;
20826
+ const { frontmatter, body } = parsed;
20446
20827
  const name = basename(path, ".md");
20447
20828
  assertCanonicalName("command", name);
20448
20829
  const fromCamel = toToolsArray2(frontmatter.allowedTools);
@@ -20489,15 +20870,20 @@ function toHooks2(v) {
20489
20870
  }
20490
20871
  return {};
20491
20872
  }
20492
- async function parseAgents(agentsDir) {
20873
+ async function parseAgents(agentsDir, opts = {}) {
20493
20874
  const files = await readDirRecursive(agentsDir);
20494
20875
  const mdFiles = files.filter((f) => f.endsWith(".md") && !basename(f).startsWith("_"));
20876
+ warnIfUnrecognizedResourceFormats("agents", agentsDir, files, mdFiles, {
20877
+ handledByOtherReader: opts.handledByOtherReader
20878
+ });
20495
20879
  assertNoBasenameCollisions("agent", mdFiles, ".md");
20496
20880
  const agents = [];
20497
20881
  for (const path of mdFiles) {
20498
20882
  const content = await readFileSafe(path);
20499
20883
  if (!content) continue;
20500
- const { frontmatter, body } = parseFrontmatter(content);
20884
+ const parsed = parseOrSkipFrontmatter(content, path, opts.onParseError);
20885
+ if (!parsed) continue;
20886
+ const { frontmatter, body } = parsed;
20501
20887
  const name = basename(path, ".md");
20502
20888
  assertCanonicalName("agent", name);
20503
20889
  const toolsCamel = toStrArray2(frontmatter.tools);
@@ -20536,11 +20922,18 @@ async function parseAgents(agentsDir) {
20536
20922
  // src/canonical/features/skills.ts
20537
20923
  init_fs();
20538
20924
  init_markdown();
20925
+ init_boilerplate_filter();
20539
20926
  async function readContent(path) {
20540
20927
  const c2 = await readFileSafe(path);
20541
20928
  return c2 ?? "";
20542
20929
  }
20543
20930
  var SKILL_FILE = "SKILL.md";
20931
+ var DOC_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdx", ".rst", ".txt"]);
20932
+ function isMarkdownLikeDoc(name) {
20933
+ const dot = name.lastIndexOf(".");
20934
+ if (dot < 0) return true;
20935
+ return DOC_EXTENSIONS.has(name.slice(dot).toLowerCase());
20936
+ }
20544
20937
  var EXCLUDED_DIR_PREFIXES = [".git", "node_modules"];
20545
20938
  function sanitizeSkillName(raw) {
20546
20939
  return raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
@@ -20555,16 +20948,20 @@ async function listSupportingFiles(skillDir) {
20555
20948
  const firstSegment = name.split("/")[0];
20556
20949
  if (EXCLUDED_DIR_PREFIXES.some((p) => firstSegment === p)) continue;
20557
20950
  if (name === ".DS_Store" || name.endsWith("/.DS_Store")) continue;
20951
+ const baseName = name.includes("/") ? name.slice(name.lastIndexOf("/") + 1) : name;
20952
+ if (isMarkdownLikeDoc(baseName) && isNoiseBoilerplate(baseName)) continue;
20558
20953
  const content = await readContent(absPath);
20559
20954
  result.push({ relativePath: name, absolutePath: absPath, content });
20560
20955
  }
20561
20956
  return result.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
20562
20957
  }
20563
- async function parseSkillDirectory(skillDir) {
20958
+ async function parseSkillDirectory(skillDir, opts = {}) {
20564
20959
  const skillPath = join(skillDir, SKILL_FILE);
20565
20960
  const content = await readFileSafe(skillPath);
20566
20961
  if (!content) return null;
20567
- const { frontmatter, body } = parseFrontmatter(content);
20962
+ const parsed = parseOrSkipFrontmatter(content, skillPath, opts.onParseError);
20963
+ if (!parsed) return null;
20964
+ const { frontmatter, body } = parsed;
20568
20965
  const supportingFiles = await listSupportingFiles(skillDir);
20569
20966
  const fmName = typeof frontmatter.name === "string" ? sanitizeSkillName(frontmatter.name) : "";
20570
20967
  const name = fmName || basename(skillDir);
@@ -20577,7 +20974,7 @@ async function parseSkillDirectory(skillDir) {
20577
20974
  supportingFiles
20578
20975
  };
20579
20976
  }
20580
- async function parseSkills(skillsDir) {
20977
+ async function parseSkills(skillsDir, opts = {}) {
20581
20978
  let entries;
20582
20979
  try {
20583
20980
  entries = await readdir(skillsDir, { withFileTypes: true });
@@ -20593,7 +20990,9 @@ async function parseSkills(skillsDir) {
20593
20990
  const skillPath = join(skillDir, SKILL_FILE);
20594
20991
  const content = await readFileSafe(skillPath);
20595
20992
  if (!content) continue;
20596
- const { frontmatter, body } = parseFrontmatter(content);
20993
+ const parsed = parseOrSkipFrontmatter(content, skillPath, opts.onParseError);
20994
+ if (!parsed) continue;
20995
+ const { frontmatter, body } = parsed;
20597
20996
  const supportingFiles = await listSupportingFiles(skillDir);
20598
20997
  skills.push({
20599
20998
  source: skillPath,
@@ -20798,14 +21197,14 @@ async function parseIgnore(ignorePath) {
20798
21197
 
20799
21198
  // src/canonical/load/loader.ts
20800
21199
  init_fs();
20801
- async function loadCanonicalFiles(canonicalDirOrProjectRoot) {
21200
+ async function loadCanonicalFiles(canonicalDirOrProjectRoot, opts = {}) {
20802
21201
  const nestedCanonicalDir = join(canonicalDirOrProjectRoot, ".agentsmesh");
20803
21202
  const canonicalDir = await exists(nestedCanonicalDir) ? nestedCanonicalDir : canonicalDirOrProjectRoot;
20804
21203
  const [rules, commands, agents, skills, mcp, permissions, hooks, ignore] = await Promise.all([
20805
- parseRules(join(canonicalDir, "rules")),
20806
- parseCommands(join(canonicalDir, "commands")),
20807
- parseAgents(join(canonicalDir, "agents")),
20808
- parseSkills(join(canonicalDir, "skills")),
21204
+ parseRules(join(canonicalDir, "rules"), opts),
21205
+ parseCommands(join(canonicalDir, "commands"), opts),
21206
+ parseAgents(join(canonicalDir, "agents"), opts),
21207
+ parseSkills(join(canonicalDir, "skills"), opts),
20809
21208
  parseMcp(join(canonicalDir, "mcp.json")),
20810
21209
  parsePermissions(join(canonicalDir, "permissions.yaml")),
20811
21210
  parseHooks(join(canonicalDir, "hooks.yaml")),
@@ -20908,132 +21307,57 @@ function mergeIgnore(base, overlay) {
20908
21307
 
20909
21308
  // src/config/resolve/native-format-detector.ts
20910
21309
  init_fs();
20911
- var TARGET_SIGNATURES = [
20912
- {
20913
- target: "claude-code",
20914
- paths: [
20915
- "CLAUDE.md",
20916
- ".claude/rules",
20917
- ".claude/commands",
20918
- ".claude/agents",
20919
- ".claude/skills",
20920
- ".claude/settings.json",
20921
- ".claudeignore"
20922
- ]
20923
- },
20924
- {
20925
- target: "cursor",
20926
- paths: [".cursorrules", ".cursor/rules", ".cursor", ".cursor/mcp.json"]
20927
- },
20928
- {
20929
- target: "copilot",
20930
- paths: [
20931
- ".github/copilot-instructions.md",
20932
- ".github/copilot",
20933
- ".github/instructions",
20934
- ".github/prompts",
20935
- ".github/skills",
20936
- ".github/agents",
20937
- ".github/hooks"
20938
- ]
20939
- },
20940
- {
20941
- target: "gemini-cli",
20942
- paths: ["GEMINI.md", ".gemini", ".gemini/settings.json"]
20943
- },
20944
- {
20945
- target: "codex-cli",
20946
- paths: [".codex", ".codex/config.toml", "AGENTS.md", "codex.md"]
20947
- },
20948
- {
20949
- target: "windsurf",
20950
- paths: [".windsurfrules", ".windsurf", ".windsurf/workflows"]
20951
- },
20952
- {
20953
- target: "cline",
20954
- paths: [".clinerules", ".cline"]
20955
- },
20956
- {
20957
- target: "continue",
20958
- paths: [".continue", ".continuerc.json"]
20959
- },
20960
- {
20961
- target: "junie",
20962
- paths: [".junie", ".junie/guidelines.md"]
20963
- },
20964
- {
20965
- target: "kiro",
20966
- paths: [".kiro", ".kiro/steering", ".kiro/settings/mcp.json"]
20967
- },
20968
- {
20969
- target: "kilo-code",
20970
- paths: [
20971
- ".kilo",
20972
- ".kilo/rules",
20973
- ".kilo/commands",
20974
- ".kilo/agents",
20975
- ".kilo/skills",
20976
- ".kilocodeignore",
20977
- ".kilocode",
20978
- ".kilocodemodes",
20979
- "kilo.jsonc",
20980
- "kilo.json"
20981
- ]
21310
+ init_builtin_targets();
21311
+ var PATH_OWNER_COUNT = (() => {
21312
+ const map = /* @__PURE__ */ new Map();
21313
+ for (const d of BUILTIN_TARGETS) {
21314
+ for (const p of d.detectionPaths) {
21315
+ map.set(p, (map.get(p) ?? 0) + 1);
21316
+ }
20982
21317
  }
20983
- ];
21318
+ return map;
21319
+ })();
21320
+ function compare(a, b) {
21321
+ if (a.uniqueHits !== b.uniqueHits) return b.uniqueHits - a.uniqueHits;
21322
+ if (a.sharedScore !== b.sharedScore) return b.sharedScore - a.sharedScore;
21323
+ return a.id.localeCompare(b.id);
21324
+ }
20984
21325
  async function detectNativeFormat(repoPath) {
20985
- let bestTarget = null;
20986
- let bestScore = 0;
20987
- for (const sig of TARGET_SIGNATURES) {
20988
- let score = 0;
20989
- for (const rel2 of sig.paths) {
20990
- if (await exists(join(repoPath, rel2))) score++;
21326
+ const scores = [];
21327
+ for (const descriptor31 of BUILTIN_TARGETS) {
21328
+ let uniqueHits = 0;
21329
+ let sharedScore = 0;
21330
+ for (const rel2 of descriptor31.detectionPaths) {
21331
+ if (!await exists(join(repoPath, rel2))) continue;
21332
+ const owners = PATH_OWNER_COUNT.get(rel2) ?? 1;
21333
+ if (owners === 1) uniqueHits += 1;
21334
+ else sharedScore += 1 / owners;
20991
21335
  }
20992
- if (score > bestScore) {
20993
- bestScore = score;
20994
- bestTarget = sig.target;
21336
+ if (uniqueHits > 0 || sharedScore > 0) {
21337
+ scores.push({ id: descriptor31.id, uniqueHits, sharedScore });
20995
21338
  }
20996
21339
  }
20997
- return bestScore > 0 ? bestTarget : null;
21340
+ if (scores.length === 0) return null;
21341
+ scores.sort(compare);
21342
+ const winner = scores[0];
21343
+ if (winner.uniqueHits === 0) return null;
21344
+ return winner.id;
20998
21345
  }
20999
- var KNOWN_NATIVE_PATHS = TARGET_SIGNATURES.map((sig) => sig.paths[0]).filter(
21000
- (p) => p !== void 0
21001
- );
21346
+ var KNOWN_NATIVE_PATHS = BUILTIN_TARGETS.map(
21347
+ (d) => d.detectionPaths[0]
21348
+ ).filter((p) => p !== void 0);
21002
21349
 
21003
21350
  // src/canonical/extends/extend-load.ts
21004
21351
  init_fs();
21005
21352
 
21006
21353
  // src/canonical/extends/native-extends-importer.ts
21007
- init_importer6();
21008
- init_importer12();
21009
- init_importer10();
21010
- init_importer15();
21011
- init_importer8();
21012
- init_importer29();
21013
- init_importer7();
21014
- init_importer9();
21015
- init_importer18();
21016
- init_importer20();
21017
- init_importer19();
21018
- var NATIVE_IMPORTERS = {
21019
- "claude-code": importFromClaudeCode,
21020
- cursor: importFromCursor,
21021
- copilot: importFromCopilot,
21022
- "gemini-cli": importFromGemini,
21023
- "codex-cli": importFromCodex,
21024
- windsurf: importFromWindsurf,
21025
- cline: importFromCline,
21026
- continue: importFromContinue,
21027
- junie: importFromJunie,
21028
- kiro: importFromKiro,
21029
- "kilo-code": importFromKiloCode
21030
- };
21354
+ init_registry();
21031
21355
  async function importNativeToCanonical(repoPath, targetName) {
21032
- const importFn = NATIVE_IMPORTERS[targetName];
21033
- if (!importFn) {
21356
+ const descriptor31 = getDescriptor(targetName);
21357
+ if (!descriptor31) {
21034
21358
  throw new Error(`No importer registered for native target: ${targetName}`);
21035
21359
  }
21036
- return importFn(repoPath);
21360
+ return descriptor31.generators.importFrom(repoPath);
21037
21361
  }
21038
21362
 
21039
21363
  // src/canonical/load/skill-pack-load.ts
@@ -21053,17 +21377,176 @@ async function isSkillPackLayout(root) {
21053
21377
  }
21054
21378
  return false;
21055
21379
  }
21056
- async function loadSkillsAtExtendPath(skillsRoot) {
21380
+ async function loadSkillsAtExtendPath(skillsRoot, opts = {}) {
21057
21381
  if (!await exists(skillsRoot)) return [];
21058
21382
  if (await exists(join(skillsRoot, SKILL))) {
21059
- const one = await parseSkillDirectory(skillsRoot);
21383
+ const one = await parseSkillDirectory(skillsRoot, opts);
21060
21384
  return one ? [one] : [];
21061
21385
  }
21062
- return parseSkills(skillsRoot);
21386
+ return parseSkills(skillsRoot, opts);
21063
21387
  }
21064
21388
 
21065
21389
  // src/canonical/load/load-canonical-slice.ts
21066
21390
  init_fs();
21391
+ init_boilerplate_filter();
21392
+ async function importAgents(agentsDir, opts = {}) {
21393
+ const agents = await parseAgents(agentsDir, opts);
21394
+ return agents.filter((entity) => !isBoilerplate(basename(entity.source)));
21395
+ }
21396
+ async function importCommands2(commandsDir, opts = {}) {
21397
+ const commands = await parseCommands(commandsDir, opts);
21398
+ return commands.filter((entity) => !isBoilerplate(basename(entity.source)));
21399
+ }
21400
+ async function importRules2(rulesDir, opts = {}) {
21401
+ const rules = await parseRules(rulesDir, opts);
21402
+ return rules.filter((entity) => !isBoilerplate(basename(entity.source)));
21403
+ }
21404
+ init_fs();
21405
+ init_registry();
21406
+ init_boilerplate_filter();
21407
+ function directorySpecsFor(importer, kind) {
21408
+ const raw = importer?.[kind];
21409
+ if (!raw) return [];
21410
+ const specs = Array.isArray(raw) ? raw : [raw];
21411
+ const out2 = [];
21412
+ for (const s of specs) {
21413
+ if (s.mode !== "directory" || !s.map || !s.extensions) continue;
21414
+ out2.push({ extensions: s.extensions, map: s.map });
21415
+ }
21416
+ return out2;
21417
+ }
21418
+ function isMarkdownExtension(ext) {
21419
+ return ext.toLowerCase().endsWith(".md");
21420
+ }
21421
+ function hasNonMdEntityMapper(targetId, kind) {
21422
+ for (const spec of directorySpecsFor(getDescriptor(targetId)?.importer, kind)) {
21423
+ if (spec.extensions.some((ext) => !isMarkdownExtension(ext))) return true;
21424
+ }
21425
+ return false;
21426
+ }
21427
+ function nonMdEntityExtensions(targetId, kind) {
21428
+ const out2 = /* @__PURE__ */ new Set();
21429
+ for (const spec of directorySpecsFor(getDescriptor(targetId)?.importer, kind)) {
21430
+ for (const ext of spec.extensions) {
21431
+ if (!isMarkdownExtension(ext)) out2.add(ext.toLowerCase());
21432
+ }
21433
+ }
21434
+ return out2;
21435
+ }
21436
+ function targetsWithNonMdEntityMapper(kind) {
21437
+ return getAllRegisteredDescriptorIds().filter((id) => hasNonMdEntityMapper(id, kind));
21438
+ }
21439
+ var CANONICAL_PARSERS = {
21440
+ rules: parseRules,
21441
+ commands: parseCommands,
21442
+ agents: parseAgents
21443
+ };
21444
+ var INSTALL_IMPORTERS = {
21445
+ rules: importRules2,
21446
+ commands: importCommands2,
21447
+ agents: importAgents
21448
+ };
21449
+ async function parseEntityDir(kind, dir, opts) {
21450
+ return CANONICAL_PARSERS[kind](dir, opts);
21451
+ }
21452
+ async function importEntities(kind, dir, opts) {
21453
+ return INSTALL_IMPORTERS[kind](dir, opts);
21454
+ }
21455
+ async function readToolNativeEntities(srcDir, targetId, kind, parseOpts = {}) {
21456
+ const specs = directorySpecsFor(getDescriptor(targetId)?.importer, kind);
21457
+ const allFiles = await readDirRecursive(srcDir);
21458
+ const nonMdExtensions = /* @__PURE__ */ new Set();
21459
+ for (const spec of specs) {
21460
+ for (const ext of spec.extensions) {
21461
+ if (!isMarkdownExtension(ext)) nonMdExtensions.add(ext.toLowerCase());
21462
+ }
21463
+ }
21464
+ const matched = allFiles.filter(
21465
+ (path) => [...nonMdExtensions].some((ext) => path.toLowerCase().endsWith(ext)) && !isBoilerplate(basename(path))
21466
+ );
21467
+ if (matched.length === 0) return { entities: [], cleanup: async () => {
21468
+ } };
21469
+ const stageDir = await mkdtemp(join(tmpdir(), `am-tool-${kind}-${targetId}-`));
21470
+ const cleanup = async () => {
21471
+ await rm(stageDir, { recursive: true, force: true });
21472
+ };
21473
+ try {
21474
+ for (const absPath of matched) {
21475
+ const content = await readFileSafe(absPath);
21476
+ if (content === null) continue;
21477
+ const relPath = relative(srcDir, absPath).replaceAll("\\", "/");
21478
+ let mapping = null;
21479
+ for (const spec of specs) {
21480
+ const claimsExt = spec.extensions.some(
21481
+ (e) => absPath.toLowerCase().endsWith(e.toLowerCase())
21482
+ );
21483
+ if (!claimsExt) continue;
21484
+ const r = await spec.map({
21485
+ absolutePath: absPath,
21486
+ relativePath: relPath,
21487
+ content,
21488
+ destDir: stageDir,
21489
+ normalizeTo: () => content
21490
+ });
21491
+ if (r) {
21492
+ mapping = r;
21493
+ break;
21494
+ }
21495
+ }
21496
+ if (!mapping) continue;
21497
+ await mkdirp(dirname(mapping.destPath));
21498
+ await writeFileAtomic(mapping.destPath, mapping.content);
21499
+ }
21500
+ const entities = await parseEntityDir(kind, stageDir, parseOpts);
21501
+ return { entities, cleanup };
21502
+ } catch (err) {
21503
+ await cleanup();
21504
+ throw err;
21505
+ }
21506
+ }
21507
+ async function readEntityDirWithMappers(srcDir, kind, opts = {}) {
21508
+ const restrict = opts.restrictToTarget;
21509
+ const targets = restrict ? hasNonMdEntityMapper(restrict, kind) ? [restrict] : [] : targetsWithNonMdEntityMapper(kind);
21510
+ const handledExts = /* @__PURE__ */ new Set();
21511
+ for (const id of targets) {
21512
+ for (const ext of nonMdEntityExtensions(id, kind)) handledExts.add(ext);
21513
+ }
21514
+ const canonical = await importEntities(kind, srcDir, {
21515
+ ...opts.parseOpts,
21516
+ handledByOtherReader: handledExts.size > 0 ? handledExts : void 0
21517
+ });
21518
+ const cleanups = [];
21519
+ const slugOf = (e) => basename(e.source).replace(/\.[^.]+$/, "");
21520
+ const byKey = /* @__PURE__ */ new Map();
21521
+ for (const e of canonical) byKey.set(slugOf(e), e);
21522
+ for (const id of targets) {
21523
+ const staged = await readToolNativeEntities(srcDir, id, kind, opts.parseOpts ?? {});
21524
+ cleanups.push(staged.cleanup);
21525
+ for (const e of staged.entities) {
21526
+ const key = slugOf(e);
21527
+ if (!byKey.has(key)) byKey.set(key, e);
21528
+ }
21529
+ }
21530
+ const entities = [...byKey.values()].sort((a, b) => slugOf(a).localeCompare(slugOf(b)));
21531
+ const cleanup = async () => {
21532
+ await Promise.allSettled(cleanups.map((fn) => fn()));
21533
+ };
21534
+ return { entities, cleanup };
21535
+ }
21536
+ async function readCommandsDirWithMappers(srcDir, opts = {}) {
21537
+ const result = await readEntityDirWithMappers(srcDir, "commands", opts);
21538
+ return { commands: [...result.entities], cleanup: result.cleanup };
21539
+ }
21540
+ async function readRulesDirWithMappers(srcDir, opts = {}) {
21541
+ const result = await readEntityDirWithMappers(srcDir, "rules", opts);
21542
+ return { rules: [...result.entities], cleanup: result.cleanup };
21543
+ }
21544
+ async function readAgentsDirWithMappers(srcDir, opts = {}) {
21545
+ const result = await readEntityDirWithMappers(srcDir, "agents", opts);
21546
+ return { agents: [...result.entities], cleanup: result.cleanup };
21547
+ }
21548
+
21549
+ // src/canonical/load/load-canonical-slice.ts
21067
21550
  function emptyCanonical() {
21068
21551
  return {
21069
21552
  rules: [],
@@ -21109,65 +21592,350 @@ async function normalizeSlicePath(absolutePath) {
21109
21592
  `Single-file install only supports .md files under rules/, commands/, or agents/. Got: ${absolutePath}`
21110
21593
  );
21111
21594
  }
21112
- async function parseRulesAt(sliceRoot) {
21113
- const base = basename(sliceRoot);
21114
- if (base === "rules") {
21115
- return parseRules(sliceRoot);
21116
- }
21117
- const nested = join(sliceRoot, "rules");
21118
- if (await exists(nested)) {
21119
- return parseRules(nested);
21120
- }
21121
- return [];
21595
+ async function resolveEntityDir(sliceRoot, kindDirName) {
21596
+ if (basename(sliceRoot) === kindDirName) return sliceRoot;
21597
+ const nested = join(sliceRoot, kindDirName);
21598
+ return await exists(nested) ? nested : null;
21122
21599
  }
21123
- async function parseCommandsAt(sliceRoot) {
21124
- const base = basename(sliceRoot);
21125
- if (base === "commands") {
21126
- return parseCommands(sliceRoot);
21127
- }
21128
- const nested = join(sliceRoot, "commands");
21129
- if (await exists(nested)) {
21130
- return parseCommands(nested);
21600
+ async function parseRulesAt(sliceRoot, opts, enableTargetMappers) {
21601
+ const noop = async () => {
21602
+ };
21603
+ const rulesDir = await resolveEntityDir(sliceRoot, "rules");
21604
+ if (!rulesDir) return { rules: [], cleanup: noop };
21605
+ if (!enableTargetMappers) {
21606
+ return { rules: await importRules2(rulesDir, opts), cleanup: noop };
21131
21607
  }
21132
- return [];
21608
+ const result = await readRulesDirWithMappers(rulesDir, { parseOpts: opts });
21609
+ return { rules: [...result.rules], cleanup: result.cleanup };
21133
21610
  }
21134
- async function parseAgentsAt(sliceRoot) {
21135
- const base = basename(sliceRoot);
21136
- if (base === "agents") {
21137
- return parseAgents(sliceRoot);
21611
+ async function parseCommandsAt(sliceRoot, opts, enableTargetMappers) {
21612
+ const noop = async () => {
21613
+ };
21614
+ const commandsDir = await resolveEntityDir(sliceRoot, "commands");
21615
+ if (!commandsDir) return { commands: [], cleanup: noop };
21616
+ if (!enableTargetMappers) {
21617
+ return { commands: await importCommands2(commandsDir, opts), cleanup: noop };
21138
21618
  }
21139
- const nested = join(sliceRoot, "agents");
21140
- if (await exists(nested)) {
21141
- return parseAgents(nested);
21619
+ const result = await readCommandsDirWithMappers(commandsDir, { parseOpts: opts });
21620
+ return { commands: [...result.commands], cleanup: result.cleanup };
21621
+ }
21622
+ async function parseAgentsAt(sliceRoot, opts, enableTargetMappers) {
21623
+ const noop = async () => {
21624
+ };
21625
+ const agentsDir = await resolveEntityDir(sliceRoot, "agents");
21626
+ if (!agentsDir) return { agents: [], cleanup: noop };
21627
+ if (!enableTargetMappers) {
21628
+ return { agents: await importAgents(agentsDir, opts), cleanup: noop };
21142
21629
  }
21143
- return [];
21630
+ const result = await readAgentsDirWithMappers(agentsDir, { parseOpts: opts });
21631
+ return { agents: [...result.agents], cleanup: result.cleanup };
21144
21632
  }
21145
- async function loadSkillsForPartialSlice(sliceRoot) {
21633
+ async function loadSkillsForPartialSlice(sliceRoot, opts) {
21146
21634
  if (await isSkillPackLayout(sliceRoot)) {
21147
- return loadSkillsAtExtendPath(sliceRoot);
21635
+ return loadSkillsAtExtendPath(sliceRoot, opts);
21148
21636
  }
21149
21637
  const nestedSkills = join(sliceRoot, "skills");
21150
21638
  if (await isSkillPackLayout(nestedSkills)) {
21151
- return loadSkillsAtExtendPath(nestedSkills);
21639
+ return loadSkillsAtExtendPath(nestedSkills, opts);
21152
21640
  }
21153
21641
  return [];
21154
21642
  }
21155
- async function loadCanonicalSliceAtPath(sliceRoot) {
21643
+ async function loadCanonicalSliceAtPath(sliceRoot, opts = {}) {
21644
+ const noop = async () => {
21645
+ };
21156
21646
  const ab = join(sliceRoot, ".agentsmesh");
21157
21647
  if (await exists(ab)) {
21158
- return loadCanonicalFiles(sliceRoot);
21648
+ return { canonical: await loadCanonicalFiles(sliceRoot, opts), cleanup: noop };
21159
21649
  }
21650
+ const enableMappers = opts.enableTargetEntityMappers ?? false;
21160
21651
  const partial = emptyCanonical();
21161
- partial.rules = await parseRulesAt(sliceRoot);
21162
- partial.commands = await parseCommandsAt(sliceRoot);
21163
- partial.agents = await parseAgentsAt(sliceRoot);
21164
- partial.skills = await loadSkillsForPartialSlice(sliceRoot);
21652
+ const rulesResult = await parseRulesAt(sliceRoot, opts, enableMappers);
21653
+ partial.rules = rulesResult.rules;
21654
+ const commandsResult = await parseCommandsAt(sliceRoot, opts, enableMappers);
21655
+ partial.commands = commandsResult.commands;
21656
+ const agentsResult = await parseAgentsAt(sliceRoot, opts, enableMappers);
21657
+ partial.agents = agentsResult.agents;
21658
+ partial.skills = await loadSkillsForPartialSlice(sliceRoot, opts);
21659
+ const mergedCleanup = async () => {
21660
+ await Promise.allSettled([
21661
+ rulesResult.cleanup(),
21662
+ commandsResult.cleanup(),
21663
+ agentsResult.cleanup()
21664
+ ]);
21665
+ };
21165
21666
  if (isCanonicalSliceEmpty(partial)) {
21667
+ await mergedCleanup();
21166
21668
  throw new Error(
21167
- `No installable resources at ${sliceRoot}. Expected .agentsmesh/, or rules/, commands/, agents/, or Anthropic-style skills (SKILL.md).`
21669
+ `No installable resources at ${sliceRoot}. Expected .agentsmesh/, or rules/, commands/, agents/, or Anthropic-style skills (SKILL.md). Hint: pass --as commands|agents|rules|skills to force a kind for flat markdown directories.`
21168
21670
  );
21169
21671
  }
21170
- return partial;
21672
+ return { canonical: partial, cleanup: mergedCleanup };
21673
+ }
21674
+
21675
+ // src/install/manual/manual-install-scope.ts
21676
+ init_fs();
21677
+
21678
+ // src/install/source/skill-repo-filter.ts
21679
+ init_fs();
21680
+ init_markdown();
21681
+ init_boilerplate_filter();
21682
+ async function readSkillFrontmatterName(skillMdPath) {
21683
+ const content = await readFileSafe(skillMdPath);
21684
+ if (!content) return "";
21685
+ const parsed = tryParseFrontmatter(content, skillMdPath);
21686
+ if (!parsed.ok) return "";
21687
+ const { frontmatter } = parsed.value;
21688
+ if (typeof frontmatter.name !== "string") return "";
21689
+ return frontmatter.name.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
21690
+ }
21691
+ async function cpFilteredSkill(sourceRoot, destDir) {
21692
+ await cp(sourceRoot, destDir, {
21693
+ recursive: true,
21694
+ filter: (src) => {
21695
+ const rel2 = relative(sourceRoot, src).replace(/\\/g, "/");
21696
+ if (rel2 === "") return true;
21697
+ const first = rel2.split("/")[0];
21698
+ if (isRepoNonContentDir(first)) return false;
21699
+ if (!rel2.includes("/")) {
21700
+ if (isNoiseBoilerplate(rel2)) return false;
21701
+ if (isRepoNonContentFile(rel2)) return false;
21702
+ }
21703
+ return true;
21704
+ }
21705
+ });
21706
+ }
21707
+
21708
+ // src/install/manual/manual-install-scope.ts
21709
+ init_boilerplate_filter();
21710
+
21711
+ // src/install/manual/mdc-reader.ts
21712
+ init_markdown();
21713
+ function toStrArray3(v) {
21714
+ if (Array.isArray(v)) return v.filter((x) => typeof x === "string");
21715
+ if (typeof v === "string") return v ? [v] : [];
21716
+ return [];
21717
+ }
21718
+ function normalizeCursorKeys(fm) {
21719
+ const out2 = { ...fm };
21720
+ const isRoot = fm.alwaysApply === true;
21721
+ out2.root = isRoot;
21722
+ delete out2.alwaysApply;
21723
+ if (!isRoot) {
21724
+ const globs = toStrArray3(fm.globs);
21725
+ const description = typeof fm.description === "string" ? fm.description.trim() : "";
21726
+ if (globs.length > 0) {
21727
+ out2.trigger = "glob";
21728
+ } else if (description.length > 0) {
21729
+ out2.trigger = "model_decision";
21730
+ } else {
21731
+ out2.trigger = "manual";
21732
+ }
21733
+ }
21734
+ return out2;
21735
+ }
21736
+ function normalizeWindsurfKeys(fm) {
21737
+ const out2 = { ...fm };
21738
+ if (out2.trigger === "always") {
21739
+ out2.trigger = "always_on";
21740
+ }
21741
+ if (typeof out2.glob === "string") {
21742
+ out2.globs = toStrArray3(out2.globs).length > 0 ? toStrArray3(out2.globs) : [out2.glob];
21743
+ delete out2.glob;
21744
+ }
21745
+ return out2;
21746
+ }
21747
+ function normalizeMdcToCanonical(content) {
21748
+ const parsed = tryParseFrontmatter(content, "<mdc>");
21749
+ if (!parsed.ok) return parsed.bodyFallback;
21750
+ const { frontmatter, body } = parsed.value;
21751
+ if (Object.keys(frontmatter).length === 0 && !content.startsWith("---")) return content;
21752
+ let normalized;
21753
+ if ("alwaysApply" in frontmatter) {
21754
+ normalized = normalizeCursorKeys(frontmatter);
21755
+ } else if ("trigger" in frontmatter || "glob" in frontmatter) {
21756
+ normalized = normalizeWindsurfKeys(frontmatter);
21757
+ } else {
21758
+ normalized = frontmatter;
21759
+ }
21760
+ return serializeFrontmatter(normalized, body.trim());
21761
+ }
21762
+ function sanitizeNameSegment(segment) {
21763
+ return segment.toLowerCase().replace(/[^a-z0-9.-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
21764
+ }
21765
+ function computeDestName(file) {
21766
+ const isMdc = file.toLowerCase().endsWith(".mdc");
21767
+ return isMdc ? basename(file).replace(/\.mdc$/i, ".md") : basename(file);
21768
+ }
21769
+ function namespacedName(sourceRoot, file, bareName) {
21770
+ const rel2 = relative(sourceRoot, file).replace(/\\/g, "/");
21771
+ const segments = rel2.split("/");
21772
+ segments.pop();
21773
+ if (segments.length === 0) return bareName;
21774
+ const prefix = sanitizeNameSegment(segments[segments.length - 1]);
21775
+ if (!prefix) return bareName;
21776
+ return `${prefix}-${bareName}`;
21777
+ }
21778
+
21779
+ // src/install/manual/manual-install-scope.ts
21780
+ async function createStageRoot() {
21781
+ const stageBase = await mkdtemp(join(tmpdir(), "am-install-manual-"));
21782
+ const discoveryRoot = join(stageBase, "repo");
21783
+ await mkdirp(join(discoveryRoot, ".agentsmesh"));
21784
+ return {
21785
+ discoveryRoot,
21786
+ cleanup: async () => {
21787
+ await rm(stageBase, { recursive: true, force: true });
21788
+ }
21789
+ };
21790
+ }
21791
+ function isAcceptedFile(file, acceptMdc) {
21792
+ const lower = file.toLowerCase();
21793
+ if (lower.endsWith(".md")) return true;
21794
+ if (acceptMdc && lower.endsWith(".mdc")) return true;
21795
+ return false;
21796
+ }
21797
+ async function stageSingleFile(sourcePath, destinationDir, acceptMdc) {
21798
+ if (!isAcceptedFile(sourcePath, acceptMdc)) {
21799
+ throw new Error(`Manual install only supports .md files for this collection: ${sourcePath}`);
21800
+ }
21801
+ await mkdirp(destinationDir);
21802
+ if (sourcePath.toLowerCase().endsWith(".mdc")) {
21803
+ const content = await readFileSafe(sourcePath);
21804
+ if (!content) return;
21805
+ const destName = basename(sourcePath).replace(/\.mdc$/i, ".md");
21806
+ await writeFile(join(destinationDir, destName), normalizeMdcToCanonical(content));
21807
+ } else {
21808
+ await cp(sourcePath, join(destinationDir, basename(sourcePath)));
21809
+ }
21810
+ }
21811
+ async function stageMarkdownCollection(sourceRoot, destinationDir, acceptMdc) {
21812
+ const info = await stat(sourceRoot);
21813
+ if (info.isFile()) return stageSingleFile(sourceRoot, destinationDir, acceptMdc);
21814
+ const files = (await readDirRecursive(sourceRoot)).filter(
21815
+ (file) => isAcceptedFile(file, acceptMdc) && !isBoilerplate(basename(file))
21816
+ );
21817
+ if (files.length === 0) {
21818
+ throw new Error(
21819
+ `No installable files found under ${sourceRoot} for manual install. Try a different --path to point at the directory holding *.md (or *.mdc) files, or omit --as so agentsmesh can auto-detect the layout.`
21820
+ );
21821
+ }
21822
+ const bareCounts = /* @__PURE__ */ new Map();
21823
+ for (const file of files) {
21824
+ const name = computeDestName(file);
21825
+ bareCounts.set(name, (bareCounts.get(name) ?? 0) + 1);
21826
+ }
21827
+ const usedNames = /* @__PURE__ */ new Map();
21828
+ await mkdirp(destinationDir);
21829
+ for (const file of files) {
21830
+ const bare = computeDestName(file);
21831
+ const hasCollision = (bareCounts.get(bare) ?? 0) > 1;
21832
+ let destName = hasCollision ? namespacedName(sourceRoot, file, bare) : bare;
21833
+ if (usedNames.has(destName) && usedNames.get(destName) !== file) {
21834
+ const rel2 = relative(sourceRoot, file).replace(/\\/g, "/").split("/").map(sanitizeNameSegment).filter(Boolean);
21835
+ const ext = bare.includes(".") ? "." + bare.split(".").pop() : "";
21836
+ const stem = rel2.join("-").replace(/\.(md|mdc)$/i, "");
21837
+ destName = stem + ext || destName;
21838
+ }
21839
+ if (usedNames.has(destName)) {
21840
+ throw new Error(
21841
+ `Manual install could not resolve duplicate name "${destName}" under ${sourceRoot} (${usedNames.get(destName)} and ${file}).`
21842
+ );
21843
+ }
21844
+ usedNames.set(destName, file);
21845
+ const isMdc = file.toLowerCase().endsWith(".mdc");
21846
+ if (isMdc) {
21847
+ const content = await readFileSafe(file);
21848
+ if (!content) continue;
21849
+ await writeFile(join(destinationDir, destName), normalizeMdcToCanonical(content));
21850
+ } else {
21851
+ await cp(file, join(destinationDir, destName));
21852
+ }
21853
+ }
21854
+ }
21855
+ async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNames) {
21856
+ if (preferredSkillNames.length === 0) {
21857
+ return false;
21858
+ }
21859
+ const wanted = new Set(preferredSkillNames);
21860
+ const matches = /* @__PURE__ */ new Map();
21861
+ for (const file of await readDirRecursive(sourceRoot)) {
21862
+ if (!file.endsWith("/SKILL.md") && !file.endsWith("\\SKILL.md")) continue;
21863
+ const skillDir = dirname(file);
21864
+ const skillName = basename(skillDir);
21865
+ if (!wanted.has(skillName)) continue;
21866
+ const previous = matches.get(skillName);
21867
+ if (previous && previous !== skillDir) {
21868
+ throw new Error(
21869
+ `Manual skill replay found duplicate skill "${skillName}" under ${sourceRoot} (${previous} and ${skillDir}).`
21870
+ );
21871
+ }
21872
+ matches.set(skillName, skillDir);
21873
+ }
21874
+ if (matches.size !== preferredSkillNames.length) return false;
21875
+ await mkdirp(destinationDir);
21876
+ for (const skillName of preferredSkillNames) {
21877
+ await cp(matches.get(skillName), join(destinationDir, skillName), { recursive: true });
21878
+ }
21879
+ return true;
21880
+ }
21881
+ async function stageSkills(sourceRoot, destinationDir, options = {}) {
21882
+ const info = await stat(sourceRoot);
21883
+ if (info.isFile()) {
21884
+ if (basename(sourceRoot) !== "SKILL.md") {
21885
+ throw new Error(`Manual skill install expects SKILL.md or a skill directory: ${sourceRoot}`);
21886
+ }
21887
+ const skillName = basename(dirname(sourceRoot));
21888
+ const skillDir = join(destinationDir, skillName);
21889
+ await mkdirp(skillDir);
21890
+ await cp(dirname(sourceRoot), skillDir, { recursive: true });
21891
+ return;
21892
+ }
21893
+ if (await isSkillPackLayout(sourceRoot)) {
21894
+ if ((await stat(join(sourceRoot, "SKILL.md")).catch(() => null))?.isFile()) {
21895
+ if (await stagePreferredSkills(sourceRoot, destinationDir, options.preferredSkillNames ?? [])) {
21896
+ return;
21897
+ }
21898
+ const fmName = await readSkillFrontmatterName(join(sourceRoot, "SKILL.md"));
21899
+ const skillName = fmName || basename(sourceRoot);
21900
+ const skillDir = join(destinationDir, skillName);
21901
+ await mkdirp(destinationDir);
21902
+ await cpFilteredSkill(sourceRoot, skillDir);
21903
+ return;
21904
+ }
21905
+ if (await stagePreferredSkills(sourceRoot, destinationDir, options.preferredSkillNames ?? [])) {
21906
+ return;
21907
+ }
21908
+ await mkdirp(destinationDir);
21909
+ const entries = await readDirRecursive(sourceRoot);
21910
+ const roots = /* @__PURE__ */ new Set();
21911
+ for (const file of entries.filter(
21912
+ (entry) => entry.endsWith("/SKILL.md") || entry.endsWith("\\SKILL.md")
21913
+ )) {
21914
+ roots.add(relative(sourceRoot, dirname(file)).split(/[\\/]/)[0]);
21915
+ }
21916
+ for (const root of roots) {
21917
+ await cp(join(sourceRoot, root), join(destinationDir, root), { recursive: true });
21918
+ }
21919
+ return;
21920
+ }
21921
+ throw new Error(
21922
+ `Manual skill install expects a skill directory or skills collection at ${sourceRoot}.`
21923
+ );
21924
+ }
21925
+ async function stageManualInstallScope(sourceRoot, as, options = {}) {
21926
+ const staged = await createStageRoot();
21927
+ try {
21928
+ const destDir = join(staged.discoveryRoot, ".agentsmesh", as);
21929
+ if (as === "skills") {
21930
+ await stageSkills(sourceRoot, destDir, options);
21931
+ } else {
21932
+ await stageMarkdownCollection(sourceRoot, destDir, as === "rules");
21933
+ }
21934
+ return staged;
21935
+ } catch (error) {
21936
+ await staged.cleanup();
21937
+ throw error;
21938
+ }
21171
21939
  }
21172
21940
 
21173
21941
  // src/canonical/extends/extend-load.ts
@@ -21185,6 +21953,18 @@ function emptyCanonical2() {
21185
21953
  }
21186
21954
  async function loadCanonicalForExtend(ext) {
21187
21955
  const base = ext.resolvedPath;
21956
+ if (ext.as !== void 0) {
21957
+ const rawRoot2 = ext.path ? join(base, ext.path) : base;
21958
+ if (!await exists(rawRoot2)) {
21959
+ throw new Error(`Extend "${ext.name}": path does not exist: ${rawRoot2}`);
21960
+ }
21961
+ const staged = await stageManualInstallScope(rawRoot2, ext.as);
21962
+ try {
21963
+ return loadCanonicalFiles(join(staged.discoveryRoot, ".agentsmesh"));
21964
+ } finally {
21965
+ await staged.cleanup();
21966
+ }
21967
+ }
21188
21968
  if (!ext.path) {
21189
21969
  const agentsmeshDir = join(base, ".agentsmesh");
21190
21970
  if (!await exists(agentsmeshDir)) {
@@ -21222,7 +22002,8 @@ Expected one of: .agentsmesh/, ${KNOWN_NATIVE_PATHS.join(", ")}.`
21222
22002
  }
21223
22003
  const { sliceRoot } = await normalizeSlicePath(rawRoot);
21224
22004
  try {
21225
- return await loadCanonicalSliceAtPath(sliceRoot);
22005
+ const { canonical } = await loadCanonicalSliceAtPath(sliceRoot);
22006
+ return canonical;
21226
22007
  } catch (err) {
21227
22008
  const msg = err instanceof Error ? err.message : String(err);
21228
22009
  const wrapped = new Error(`Extend "${ext.name}": ${msg}`);
@@ -21308,7 +22089,15 @@ var packMetadataSchema = z.object({
21308
22089
  path: z.string().optional(),
21309
22090
  paths: z.array(z.string().min(1)).min(1).optional(),
21310
22091
  as: manualInstallAsSchema.optional(),
21311
- content_hash: z.string()
22092
+ content_hash: z.string(),
22093
+ /**
22094
+ * SPDX identifier of the LICENSE / NOTICE / COPYING file at the pack root,
22095
+ * or `null` when the file is missing or its text matches no known
22096
+ * fingerprint. Detected at materialize time from the upstream bytes — never
22097
+ * inferred from `package.json` or other secondary signals. See
22098
+ * `src/install/license/detect-license.ts`.
22099
+ */
22100
+ license: z.string().nullable().optional()
21312
22101
  });
21313
22102
 
21314
22103
  // src/install/pack/pack-reader.ts
@@ -21461,15 +22250,30 @@ function isLocalSource(source) {
21461
22250
  // these on win32, and they must not be misinterpreted as bare npm package names.
21462
22251
  /^[A-Za-z]:[/\\]/.test(source);
21463
22252
  }
22253
+ function canonicalize(path) {
22254
+ try {
22255
+ return realpathSync(path);
22256
+ } catch {
22257
+ return path;
22258
+ }
22259
+ }
22260
+ function assertSourceInsideProjectRoot(resolvedPath, projectRoot) {
22261
+ const rootAbs = canonicalize(resolve(projectRoot));
22262
+ const sourceAbs = canonicalize(resolvedPath);
22263
+ if (sourceAbs === rootAbs || sourceAbs.startsWith(`${rootAbs}${sep}`)) return;
22264
+ throw new Error(`Plugin source resolves outside project root (escapes ${rootAbs}): ${sourceAbs}`);
22265
+ }
21464
22266
  async function importPluginModule(entry, projectRoot) {
21465
22267
  const { source } = entry;
21466
22268
  let importTarget;
21467
22269
  if (isLocalSource(source)) {
21468
22270
  const raw = source.startsWith("file:") ? fileURLToPath(source) : source;
21469
22271
  const resolved = resolve(projectRoot, raw);
22272
+ assertSourceInsideProjectRoot(resolved, projectRoot);
21470
22273
  importTarget = pathToFileURL(resolved).href;
21471
22274
  } else {
21472
22275
  const resolved = resolveNpmSpecifier(source, projectRoot);
22276
+ assertSourceInsideProjectRoot(resolved, projectRoot);
21473
22277
  importTarget = pathToFileURL(resolved).href;
21474
22278
  }
21475
22279
  const mod = await import(importTarget);
@@ -21559,11 +22363,7 @@ var TARGET_CATALOG = Object.fromEntries(
21559
22363
  ])
21560
22364
  );
21561
22365
  function getTargetCatalogEntry(id) {
21562
- const entry = TARGET_CATALOG[id];
21563
- if (!entry) {
21564
- throw new Error(`Unknown target: ${id}`);
21565
- }
21566
- return entry;
22366
+ return TARGET_CATALOG[id];
21567
22367
  }
21568
22368
 
21569
22369
  // src/core/lint/linter.ts
@@ -21833,13 +22633,16 @@ function formatDiffSummary(summary) {
21833
22633
 
21834
22634
  // src/config/core/lock.ts
21835
22635
  init_fs();
22636
+
22637
+ // src/utils/crypto/hash.ts
22638
+ init_fs_text_encoding();
21836
22639
  function hashContent(content) {
21837
22640
  return createHash("sha256").update(content, "utf8").digest("hex");
21838
22641
  }
21839
22642
  async function hashFile(path) {
21840
22643
  try {
21841
- const content = await readFile(path, "utf8");
21842
- return hashContent(content);
22644
+ const bytes = await readFile(path);
22645
+ return createHash("sha256").update(bytes).digest("hex");
21843
22646
  } catch (err) {
21844
22647
  if (err instanceof Error && "code" in err && err.code === "ENOENT") {
21845
22648
  return null;