rulesync 3.19.0 → 3.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +52 -15
  2. package/dist/index.cjs +1417 -802
  3. package/dist/index.js +1284 -669
  4. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -107,9 +107,9 @@ var logger = new Logger();
107
107
  // src/cli/commands/generate.ts
108
108
  var import_es_toolkit2 = require("es-toolkit");
109
109
 
110
- // src/commands/commands-processor.ts
111
- var import_node_path12 = require("path");
112
- var import_mini9 = require("zod/mini");
110
+ // src/config/config-resolver.ts
111
+ var import_node_path2 = require("path");
112
+ var import_jsonc_parser = require("jsonc-parser");
113
113
 
114
114
  // src/utils/file.ts
115
115
  var import_node_fs = require("fs");
@@ -132,14 +132,24 @@ async function readOrInitializeFileContent(filePath, initialContent = "") {
132
132
  return initialContent;
133
133
  }
134
134
  }
135
- function resolvePath(relativePath, baseDir) {
136
- if (!baseDir) return relativePath;
137
- const resolved = (0, import_node_path.resolve)(baseDir, relativePath);
138
- const rel = (0, import_node_path.relative)(baseDir, resolved);
135
+ function checkPathTraversal({
136
+ relativePath,
137
+ intendedRootDir
138
+ }) {
139
+ const segments = relativePath.split(/[/\\]/);
140
+ if (segments.includes("..")) {
141
+ throw new Error(`Path traversal detected: ${relativePath}`);
142
+ }
143
+ const resolved = (0, import_node_path.resolve)(intendedRootDir, relativePath);
144
+ const rel = (0, import_node_path.relative)(intendedRootDir, resolved);
139
145
  if (rel.startsWith("..") || (0, import_node_path.resolve)(resolved) !== resolved) {
140
146
  throw new Error(`Path traversal detected: ${relativePath}`);
141
147
  }
142
- return resolved;
148
+ }
149
+ function resolvePath(relativePath, baseDir) {
150
+ if (!baseDir) return relativePath;
151
+ checkPathTraversal({ relativePath, intendedRootDir: baseDir });
152
+ return (0, import_node_path.resolve)(baseDir, relativePath);
143
153
  }
144
154
  async function directoryExists(dirPath) {
145
155
  try {
@@ -202,16 +212,263 @@ function validateBaseDir(baseDir) {
202
212
  if (baseDir.trim() === "") {
203
213
  throw new Error("baseDir cannot be an empty string");
204
214
  }
205
- if (baseDir.includes("..")) {
206
- throw new Error(`baseDir cannot contain directory traversal (..): ${baseDir}`);
215
+ checkPathTraversal({ relativePath: baseDir, intendedRootDir: process.cwd() });
216
+ }
217
+
218
+ // src/config/config.ts
219
+ var import_mini3 = require("zod/mini");
220
+
221
+ // src/types/tool-targets.ts
222
+ var import_mini2 = require("zod/mini");
223
+ var ALL_TOOL_TARGETS = [
224
+ "agentsmd",
225
+ "amazonqcli",
226
+ "augmentcode",
227
+ "augmentcode-legacy",
228
+ "copilot",
229
+ "cursor",
230
+ "cline",
231
+ "claudecode",
232
+ "codexcli",
233
+ "opencode",
234
+ "qwencode",
235
+ "roo",
236
+ "geminicli",
237
+ "kiro",
238
+ "junie",
239
+ "warp",
240
+ "windsurf"
241
+ ];
242
+ var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
243
+ var ToolTargetSchema = import_mini2.z.enum(ALL_TOOL_TARGETS);
244
+ var ToolTargetsSchema = import_mini2.z.array(ToolTargetSchema);
245
+ var RulesyncTargetsSchema = import_mini2.z.array(import_mini2.z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
246
+
247
+ // src/config/config.ts
248
+ var ConfigParamsSchema = import_mini3.z.object({
249
+ baseDirs: import_mini3.z.array(import_mini3.z.string()),
250
+ targets: RulesyncTargetsSchema,
251
+ features: RulesyncFeaturesSchema,
252
+ verbose: import_mini3.z.boolean(),
253
+ delete: import_mini3.z.boolean(),
254
+ // New non-experimental options
255
+ global: (0, import_mini3.optional)(import_mini3.z.boolean()),
256
+ simulatedCommands: (0, import_mini3.optional)(import_mini3.z.boolean()),
257
+ simulatedSubagents: (0, import_mini3.optional)(import_mini3.z.boolean()),
258
+ modularMcp: (0, import_mini3.optional)(import_mini3.z.boolean()),
259
+ // Deprecated experimental options (for backward compatibility)
260
+ experimentalGlobal: (0, import_mini3.optional)(import_mini3.z.boolean()),
261
+ experimentalSimulateCommands: (0, import_mini3.optional)(import_mini3.z.boolean()),
262
+ experimentalSimulateSubagents: (0, import_mini3.optional)(import_mini3.z.boolean())
263
+ });
264
+ var PartialConfigParamsSchema = import_mini3.z.partial(ConfigParamsSchema);
265
+ var RequiredConfigParamsSchema = import_mini3.z.required(ConfigParamsSchema);
266
+ var Config = class {
267
+ baseDirs;
268
+ targets;
269
+ features;
270
+ verbose;
271
+ delete;
272
+ global;
273
+ simulatedCommands;
274
+ simulatedSubagents;
275
+ modularMcp;
276
+ constructor({
277
+ baseDirs,
278
+ targets,
279
+ features,
280
+ verbose,
281
+ delete: isDelete,
282
+ global,
283
+ simulatedCommands,
284
+ simulatedSubagents,
285
+ modularMcp,
286
+ experimentalGlobal,
287
+ experimentalSimulateCommands,
288
+ experimentalSimulateSubagents
289
+ }) {
290
+ this.baseDirs = baseDirs;
291
+ this.targets = targets;
292
+ this.features = features;
293
+ this.verbose = verbose;
294
+ this.delete = isDelete;
295
+ this.global = global ?? experimentalGlobal ?? false;
296
+ this.simulatedCommands = simulatedCommands ?? experimentalSimulateCommands ?? false;
297
+ this.simulatedSubagents = simulatedSubagents ?? experimentalSimulateSubagents ?? false;
298
+ this.modularMcp = modularMcp ?? false;
299
+ }
300
+ getBaseDirs() {
301
+ return this.baseDirs;
302
+ }
303
+ getTargets() {
304
+ if (this.targets.includes("*")) {
305
+ return [...ALL_TOOL_TARGETS];
306
+ }
307
+ return this.targets.filter((target) => target !== "*");
308
+ }
309
+ getFeatures() {
310
+ if (this.features.includes("*")) {
311
+ return [...ALL_FEATURES];
312
+ }
313
+ return this.features.filter((feature) => feature !== "*");
314
+ }
315
+ getVerbose() {
316
+ return this.verbose;
317
+ }
318
+ getDelete() {
319
+ return this.delete;
320
+ }
321
+ getGlobal() {
322
+ return this.global;
323
+ }
324
+ getSimulatedCommands() {
325
+ return this.simulatedCommands;
326
+ }
327
+ getSimulatedSubagents() {
328
+ return this.simulatedSubagents;
329
+ }
330
+ getModularMcp() {
331
+ return this.modularMcp;
332
+ }
333
+ // Deprecated getters for backward compatibility
334
+ /** @deprecated Use getGlobal() instead */
335
+ getExperimentalGlobal() {
336
+ return this.global;
337
+ }
338
+ /** @deprecated Use getSimulatedCommands() instead */
339
+ getExperimentalSimulateCommands() {
340
+ return this.simulatedCommands;
341
+ }
342
+ /** @deprecated Use getSimulatedSubagents() instead */
343
+ getExperimentalSimulateSubagents() {
344
+ return this.simulatedSubagents;
345
+ }
346
+ };
347
+
348
+ // src/config/config-resolver.ts
349
+ var defaults = {
350
+ targets: ["agentsmd"],
351
+ features: ["rules"],
352
+ verbose: false,
353
+ delete: false,
354
+ baseDirs: [process.cwd()],
355
+ configPath: "rulesync.jsonc",
356
+ global: false,
357
+ simulatedCommands: false,
358
+ simulatedSubagents: false,
359
+ modularMcp: false,
360
+ experimentalGlobal: false,
361
+ experimentalSimulateCommands: false,
362
+ experimentalSimulateSubagents: false
363
+ };
364
+ var ConfigResolver = class {
365
+ static async resolve({
366
+ targets,
367
+ features,
368
+ verbose,
369
+ delete: isDelete,
370
+ baseDirs,
371
+ configPath = defaults.configPath,
372
+ global,
373
+ simulatedCommands,
374
+ simulatedSubagents,
375
+ modularMcp,
376
+ experimentalGlobal,
377
+ experimentalSimulateCommands,
378
+ experimentalSimulateSubagents
379
+ }) {
380
+ const validatedConfigPath = resolvePath(configPath, process.cwd());
381
+ let configByFile = {};
382
+ if (await fileExists(validatedConfigPath)) {
383
+ try {
384
+ const fileContent = await readFileContent(validatedConfigPath);
385
+ const jsonData = (0, import_jsonc_parser.parse)(fileContent);
386
+ configByFile = PartialConfigParamsSchema.parse(jsonData);
387
+ } catch (error) {
388
+ logger.error(`Failed to load config file: ${formatError(error)}`);
389
+ throw error;
390
+ }
391
+ }
392
+ const deprecatedGlobal = experimentalGlobal ?? configByFile.experimentalGlobal;
393
+ const deprecatedCommands = experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands;
394
+ const deprecatedSubagents = experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents;
395
+ if (deprecatedGlobal !== void 0) {
396
+ warnDeprecatedOptions({ experimentalGlobal: deprecatedGlobal });
397
+ }
398
+ if (deprecatedCommands !== void 0) {
399
+ warnDeprecatedOptions({ experimentalSimulateCommands: deprecatedCommands });
400
+ }
401
+ if (deprecatedSubagents !== void 0) {
402
+ warnDeprecatedOptions({ experimentalSimulateSubagents: deprecatedSubagents });
403
+ }
404
+ const resolvedGlobal = global ?? configByFile.global ?? experimentalGlobal ?? configByFile.experimentalGlobal ?? defaults.global;
405
+ const resolvedSimulatedCommands = simulatedCommands ?? configByFile.simulatedCommands ?? experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands ?? defaults.simulatedCommands;
406
+ const resolvedSimulatedSubagents = simulatedSubagents ?? configByFile.simulatedSubagents ?? experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents ?? defaults.simulatedSubagents;
407
+ const configParams = {
408
+ targets: targets ?? configByFile.targets ?? defaults.targets,
409
+ features: features ?? configByFile.features ?? defaults.features,
410
+ verbose: verbose ?? configByFile.verbose ?? defaults.verbose,
411
+ delete: isDelete ?? configByFile.delete ?? defaults.delete,
412
+ baseDirs: getBaseDirsInLightOfGlobal({
413
+ baseDirs: baseDirs ?? configByFile.baseDirs ?? defaults.baseDirs,
414
+ global: resolvedGlobal
415
+ }),
416
+ global: resolvedGlobal,
417
+ simulatedCommands: resolvedSimulatedCommands,
418
+ simulatedSubagents: resolvedSimulatedSubagents,
419
+ modularMcp: modularMcp ?? configByFile.modularMcp ?? defaults.modularMcp
420
+ };
421
+ return new Config(configParams);
422
+ }
423
+ };
424
+ function warnDeprecatedOptions({
425
+ experimentalGlobal,
426
+ experimentalSimulateCommands,
427
+ experimentalSimulateSubagents
428
+ }) {
429
+ if (experimentalGlobal !== void 0) {
430
+ logger.warn("'experimentalGlobal' option is deprecated. Please use 'global' instead.");
431
+ }
432
+ if (experimentalSimulateCommands !== void 0) {
433
+ logger.warn(
434
+ "'experimentalSimulateCommands' option is deprecated. Please use 'simulatedCommands' instead."
435
+ );
436
+ }
437
+ if (experimentalSimulateSubagents !== void 0) {
438
+ logger.warn(
439
+ "'experimentalSimulateSubagents' option is deprecated. Please use 'simulatedSubagents' instead."
440
+ );
207
441
  }
208
- const normalized = (0, import_node_path.resolve)(baseDir);
209
- const rel = (0, import_node_path.relative)(process.cwd(), normalized);
210
- if (rel.startsWith("..")) {
211
- throw new Error(`baseDir cannot contain directory traversal (..): ${baseDir}`);
442
+ }
443
+ function getBaseDirsInLightOfGlobal({
444
+ baseDirs,
445
+ global
446
+ }) {
447
+ if (global) {
448
+ return [getHomeDirectory()];
212
449
  }
450
+ const resolvedBaseDirs = baseDirs.map((baseDir) => (0, import_node_path2.resolve)(baseDir));
451
+ resolvedBaseDirs.forEach((baseDir) => {
452
+ validateBaseDir(baseDir);
453
+ });
454
+ return resolvedBaseDirs;
213
455
  }
214
456
 
457
+ // src/constants/rulesync-paths.ts
458
+ var import_node_path3 = require("path");
459
+ var RULESYNC_CONFIG_RELATIVE_FILE_PATH = "rulesync.jsonc";
460
+ var RULESYNC_RELATIVE_DIR_PATH = ".rulesync";
461
+ var RULESYNC_RULES_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "rules");
462
+ var RULESYNC_COMMANDS_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "commands");
463
+ var RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "subagents");
464
+ var RULESYNC_MCP_RELATIVE_FILE_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "mcp.json");
465
+ var RULESYNC_IGNORE_RELATIVE_FILE_PATH = ".rulesyncignore";
466
+ var RULESYNC_OVERVIEW_FILE_NAME = "overview.md";
467
+
468
+ // src/features/commands/commands-processor.ts
469
+ var import_node_path14 = require("path");
470
+ var import_mini10 = require("zod/mini");
471
+
215
472
  // src/types/feature-processor.ts
216
473
  var FeatureProcessor = class {
217
474
  baseDir;
@@ -242,8 +499,8 @@ var FeatureProcessor = class {
242
499
  }
243
500
  };
244
501
 
245
- // src/commands/agentsmd-command.ts
246
- var import_node_path4 = require("path");
502
+ // src/features/commands/agentsmd-command.ts
503
+ var import_node_path6 = require("path");
247
504
 
248
505
  // src/utils/frontmatter.ts
249
506
  var import_gray_matter = __toESM(require("gray-matter"), 1);
@@ -294,12 +551,12 @@ function parseFrontmatter(content) {
294
551
  return { frontmatter, body };
295
552
  }
296
553
 
297
- // src/commands/simulated-command.ts
298
- var import_node_path3 = require("path");
299
- var import_mini2 = require("zod/mini");
554
+ // src/features/commands/simulated-command.ts
555
+ var import_node_path5 = require("path");
556
+ var import_mini4 = require("zod/mini");
300
557
 
301
558
  // src/types/ai-file.ts
302
- var import_node_path2 = __toESM(require("path"), 1);
559
+ var import_node_path4 = __toESM(require("path"), 1);
303
560
  var AiFile = class {
304
561
  /**
305
562
  * @example "."
@@ -354,11 +611,11 @@ var AiFile = class {
354
611
  return this.relativeFilePath;
355
612
  }
356
613
  getFilePath() {
357
- const fullPath = import_node_path2.default.join(this.baseDir, this.relativeDirPath, this.relativeFilePath);
358
- const resolvedFull = (0, import_node_path2.resolve)(fullPath);
359
- const resolvedBase = (0, import_node_path2.resolve)(this.baseDir);
360
- const rel = (0, import_node_path2.relative)(resolvedBase, resolvedFull);
361
- if (rel.startsWith("..") || import_node_path2.default.isAbsolute(rel)) {
614
+ const fullPath = import_node_path4.default.join(this.baseDir, this.relativeDirPath, this.relativeFilePath);
615
+ const resolvedFull = (0, import_node_path4.resolve)(fullPath);
616
+ const resolvedBase = (0, import_node_path4.resolve)(this.baseDir);
617
+ const rel = (0, import_node_path4.relative)(resolvedBase, resolvedFull);
618
+ if (rel.startsWith("..") || import_node_path4.default.isAbsolute(rel)) {
362
619
  throw new Error(
363
620
  `Path traversal detected: Final path escapes baseDir. baseDir="${this.baseDir}", relativeDirPath="${this.relativeDirPath}", relativeFilePath="${this.relativeFilePath}"`
364
621
  );
@@ -369,14 +626,14 @@ var AiFile = class {
369
626
  return this.fileContent;
370
627
  }
371
628
  getRelativePathFromCwd() {
372
- return import_node_path2.default.join(this.relativeDirPath, this.relativeFilePath);
629
+ return import_node_path4.default.join(this.relativeDirPath, this.relativeFilePath);
373
630
  }
374
631
  setFileContent(newFileContent) {
375
632
  this.fileContent = newFileContent;
376
633
  }
377
634
  };
378
635
 
379
- // src/commands/tool-command.ts
636
+ // src/features/commands/tool-command.ts
380
637
  var ToolCommand = class extends AiFile {
381
638
  static getSettablePaths() {
382
639
  throw new Error("Please implement this method in the subclass.");
@@ -446,9 +703,9 @@ var ToolCommand = class extends AiFile {
446
703
  }
447
704
  };
448
705
 
449
- // src/commands/simulated-command.ts
450
- var SimulatedCommandFrontmatterSchema = import_mini2.z.object({
451
- description: import_mini2.z.string()
706
+ // src/features/commands/simulated-command.ts
707
+ var SimulatedCommandFrontmatterSchema = import_mini4.z.object({
708
+ description: import_mini4.z.string()
452
709
  });
453
710
  var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
454
711
  frontmatter;
@@ -458,7 +715,7 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
458
715
  const result = SimulatedCommandFrontmatterSchema.safeParse(frontmatter);
459
716
  if (!result.success) {
460
717
  throw new Error(
461
- `Invalid frontmatter in ${(0, import_node_path3.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
718
+ `Invalid frontmatter in ${(0, import_node_path5.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
462
719
  );
463
720
  }
464
721
  }
@@ -508,7 +765,7 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
508
765
  return {
509
766
  success: false,
510
767
  error: new Error(
511
- `Invalid frontmatter in ${(0, import_node_path3.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
768
+ `Invalid frontmatter in ${(0, import_node_path5.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
512
769
  )
513
770
  };
514
771
  }
@@ -518,7 +775,7 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
518
775
  relativeFilePath,
519
776
  validate = true
520
777
  }) {
521
- const filePath = (0, import_node_path3.join)(
778
+ const filePath = (0, import_node_path5.join)(
522
779
  baseDir,
523
780
  _SimulatedCommand.getSettablePaths().relativeDirPath,
524
781
  relativeFilePath
@@ -532,7 +789,7 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
532
789
  return {
533
790
  baseDir,
534
791
  relativeDirPath: _SimulatedCommand.getSettablePaths().relativeDirPath,
535
- relativeFilePath: (0, import_node_path3.basename)(relativeFilePath),
792
+ relativeFilePath: (0, import_node_path5.basename)(relativeFilePath),
536
793
  frontmatter: result.data,
537
794
  body: content.trim(),
538
795
  validate
@@ -540,11 +797,11 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
540
797
  }
541
798
  };
542
799
 
543
- // src/commands/agentsmd-command.ts
800
+ // src/features/commands/agentsmd-command.ts
544
801
  var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
545
802
  static getSettablePaths() {
546
803
  return {
547
- relativeDirPath: (0, import_node_path4.join)(".agents", "commands")
804
+ relativeDirPath: (0, import_node_path6.join)(".agents", "commands")
548
805
  };
549
806
  }
550
807
  static fromRulesyncCommand({
@@ -561,7 +818,7 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
561
818
  relativeFilePath,
562
819
  validate = true
563
820
  }) {
564
- const filePath = (0, import_node_path4.join)(
821
+ const filePath = (0, import_node_path6.join)(
565
822
  baseDir,
566
823
  _AgentsmdCommand.getSettablePaths().relativeDirPath,
567
824
  relativeFilePath
@@ -575,7 +832,7 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
575
832
  return new _AgentsmdCommand({
576
833
  baseDir,
577
834
  relativeDirPath: _AgentsmdCommand.getSettablePaths().relativeDirPath,
578
- relativeFilePath: (0, import_node_path4.basename)(relativeFilePath),
835
+ relativeFilePath: (0, import_node_path6.basename)(relativeFilePath),
579
836
  frontmatter: result.data,
580
837
  body: content.trim(),
581
838
  validate
@@ -589,13 +846,13 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
589
846
  }
590
847
  };
591
848
 
592
- // src/commands/claudecode-command.ts
593
- var import_node_path6 = require("path");
594
- var import_mini5 = require("zod/mini");
849
+ // src/features/commands/claudecode-command.ts
850
+ var import_node_path8 = require("path");
851
+ var import_mini6 = require("zod/mini");
595
852
 
596
- // src/commands/rulesync-command.ts
597
- var import_node_path5 = require("path");
598
- var import_mini4 = require("zod/mini");
853
+ // src/features/commands/rulesync-command.ts
854
+ var import_node_path7 = require("path");
855
+ var import_mini5 = require("zod/mini");
599
856
 
600
857
  // src/types/rulesync-file.ts
601
858
  var RulesyncFile = class extends AiFile {
@@ -607,36 +864,10 @@ var RulesyncFile = class extends AiFile {
607
864
  }
608
865
  };
609
866
 
610
- // src/types/tool-targets.ts
611
- var import_mini3 = require("zod/mini");
612
- var ALL_TOOL_TARGETS = [
613
- "agentsmd",
614
- "amazonqcli",
615
- "augmentcode",
616
- "augmentcode-legacy",
617
- "copilot",
618
- "cursor",
619
- "cline",
620
- "claudecode",
621
- "codexcli",
622
- "opencode",
623
- "qwencode",
624
- "roo",
625
- "geminicli",
626
- "kiro",
627
- "junie",
628
- "warp",
629
- "windsurf"
630
- ];
631
- var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
632
- var ToolTargetSchema = import_mini3.z.enum(ALL_TOOL_TARGETS);
633
- var ToolTargetsSchema = import_mini3.z.array(ToolTargetSchema);
634
- var RulesyncTargetsSchema = import_mini3.z.array(import_mini3.z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
635
-
636
- // src/commands/rulesync-command.ts
637
- var RulesyncCommandFrontmatterSchema = import_mini4.z.object({
867
+ // src/features/commands/rulesync-command.ts
868
+ var RulesyncCommandFrontmatterSchema = import_mini5.z.object({
638
869
  targets: RulesyncTargetsSchema,
639
- description: import_mini4.z.string()
870
+ description: import_mini5.z.string()
640
871
  });
641
872
  var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
642
873
  frontmatter;
@@ -646,7 +877,7 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
646
877
  const result = RulesyncCommandFrontmatterSchema.safeParse(frontmatter);
647
878
  if (!result.success) {
648
879
  throw new Error(
649
- `Invalid frontmatter in ${(0, import_node_path5.join)(rest.baseDir ?? process.cwd(), rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
880
+ `Invalid frontmatter in ${(0, import_node_path7.join)(rest.baseDir ?? process.cwd(), rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
650
881
  );
651
882
  }
652
883
  }
@@ -659,7 +890,7 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
659
890
  }
660
891
  static getSettablePaths() {
661
892
  return {
662
- relativeDirPath: (0, import_node_path5.join)(".rulesync", "commands")
893
+ relativeDirPath: RULESYNC_COMMANDS_RELATIVE_DIR_PATH
663
894
  };
664
895
  }
665
896
  getFrontmatter() {
@@ -679,7 +910,7 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
679
910
  return {
680
911
  success: false,
681
912
  error: new Error(
682
- `Invalid frontmatter in ${(0, import_node_path5.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
913
+ `Invalid frontmatter in ${(0, import_node_path7.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
683
914
  )
684
915
  };
685
916
  }
@@ -687,15 +918,18 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
687
918
  static async fromFile({
688
919
  relativeFilePath
689
920
  }) {
690
- const fileContent = await readFileContent(
691
- (0, import_node_path5.join)(_RulesyncCommand.getSettablePaths().relativeDirPath, relativeFilePath)
921
+ const filePath = (0, import_node_path7.join)(
922
+ process.cwd(),
923
+ _RulesyncCommand.getSettablePaths().relativeDirPath,
924
+ relativeFilePath
692
925
  );
926
+ const fileContent = await readFileContent(filePath);
693
927
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
694
928
  const result = RulesyncCommandFrontmatterSchema.safeParse(frontmatter);
695
929
  if (!result.success) {
696
930
  throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
697
931
  }
698
- const filename = (0, import_node_path5.basename)(relativeFilePath);
932
+ const filename = (0, import_node_path7.basename)(relativeFilePath);
699
933
  return new _RulesyncCommand({
700
934
  baseDir: process.cwd(),
701
935
  relativeDirPath: _RulesyncCommand.getSettablePaths().relativeDirPath,
@@ -707,9 +941,9 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
707
941
  }
708
942
  };
709
943
 
710
- // src/commands/claudecode-command.ts
711
- var ClaudecodeCommandFrontmatterSchema = import_mini5.z.object({
712
- description: import_mini5.z.string()
944
+ // src/features/commands/claudecode-command.ts
945
+ var ClaudecodeCommandFrontmatterSchema = import_mini6.z.object({
946
+ description: import_mini6.z.string()
713
947
  });
714
948
  var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
715
949
  frontmatter;
@@ -719,7 +953,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
719
953
  const result = ClaudecodeCommandFrontmatterSchema.safeParse(frontmatter);
720
954
  if (!result.success) {
721
955
  throw new Error(
722
- `Invalid frontmatter in ${(0, import_node_path6.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
956
+ `Invalid frontmatter in ${(0, import_node_path8.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
723
957
  );
724
958
  }
725
959
  }
@@ -732,7 +966,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
732
966
  }
733
967
  static getSettablePaths(_options = {}) {
734
968
  return {
735
- relativeDirPath: (0, import_node_path6.join)(".claude", "commands")
969
+ relativeDirPath: (0, import_node_path8.join)(".claude", "commands")
736
970
  };
737
971
  }
738
972
  getBody() {
@@ -790,7 +1024,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
790
1024
  return {
791
1025
  success: false,
792
1026
  error: new Error(
793
- `Invalid frontmatter in ${(0, import_node_path6.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
1027
+ `Invalid frontmatter in ${(0, import_node_path8.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
794
1028
  )
795
1029
  };
796
1030
  }
@@ -808,7 +1042,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
808
1042
  global = false
809
1043
  }) {
810
1044
  const paths = this.getSettablePaths({ global });
811
- const filePath = (0, import_node_path6.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1045
+ const filePath = (0, import_node_path8.join)(baseDir, paths.relativeDirPath, relativeFilePath);
812
1046
  const fileContent = await readFileContent(filePath);
813
1047
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
814
1048
  const result = ClaudecodeCommandFrontmatterSchema.safeParse(frontmatter);
@@ -818,7 +1052,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
818
1052
  return new _ClaudecodeCommand({
819
1053
  baseDir,
820
1054
  relativeDirPath: paths.relativeDirPath,
821
- relativeFilePath: (0, import_node_path6.basename)(relativeFilePath),
1055
+ relativeFilePath: (0, import_node_path8.basename)(relativeFilePath),
822
1056
  frontmatter: result.data,
823
1057
  body: content.trim(),
824
1058
  validate
@@ -826,15 +1060,15 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
826
1060
  }
827
1061
  };
828
1062
 
829
- // src/commands/codexcli-command.ts
830
- var import_node_path7 = require("path");
1063
+ // src/features/commands/codexcli-command.ts
1064
+ var import_node_path9 = require("path");
831
1065
  var CodexcliCommand = class _CodexcliCommand extends ToolCommand {
832
1066
  static getSettablePaths({ global } = {}) {
833
1067
  if (!global) {
834
1068
  throw new Error("CodexcliCommand only supports global mode. Please pass { global: true }.");
835
1069
  }
836
1070
  return {
837
- relativeDirPath: (0, import_node_path7.join)(".codex", "prompts")
1071
+ relativeDirPath: (0, import_node_path9.join)(".codex", "prompts")
838
1072
  };
839
1073
  }
840
1074
  toRulesyncCommand() {
@@ -887,25 +1121,25 @@ var CodexcliCommand = class _CodexcliCommand extends ToolCommand {
887
1121
  global = false
888
1122
  }) {
889
1123
  const paths = this.getSettablePaths({ global });
890
- const filePath = (0, import_node_path7.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1124
+ const filePath = (0, import_node_path9.join)(baseDir, paths.relativeDirPath, relativeFilePath);
891
1125
  const fileContent = await readFileContent(filePath);
892
1126
  const { body: content } = parseFrontmatter(fileContent);
893
1127
  return new _CodexcliCommand({
894
1128
  baseDir,
895
1129
  relativeDirPath: paths.relativeDirPath,
896
- relativeFilePath: (0, import_node_path7.basename)(relativeFilePath),
1130
+ relativeFilePath: (0, import_node_path9.basename)(relativeFilePath),
897
1131
  fileContent: content.trim(),
898
1132
  validate
899
1133
  });
900
1134
  }
901
1135
  };
902
1136
 
903
- // src/commands/copilot-command.ts
904
- var import_node_path8 = require("path");
905
- var import_mini6 = require("zod/mini");
906
- var CopilotCommandFrontmatterSchema = import_mini6.z.object({
907
- mode: import_mini6.z.literal("agent"),
908
- description: import_mini6.z.string()
1137
+ // src/features/commands/copilot-command.ts
1138
+ var import_node_path10 = require("path");
1139
+ var import_mini7 = require("zod/mini");
1140
+ var CopilotCommandFrontmatterSchema = import_mini7.z.object({
1141
+ mode: import_mini7.z.literal("agent"),
1142
+ description: import_mini7.z.string()
909
1143
  });
910
1144
  var CopilotCommand = class _CopilotCommand extends ToolCommand {
911
1145
  frontmatter;
@@ -915,7 +1149,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
915
1149
  const result = CopilotCommandFrontmatterSchema.safeParse(frontmatter);
916
1150
  if (!result.success) {
917
1151
  throw new Error(
918
- `Invalid frontmatter in ${(0, import_node_path8.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
1152
+ `Invalid frontmatter in ${(0, import_node_path10.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
919
1153
  );
920
1154
  }
921
1155
  }
@@ -928,7 +1162,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
928
1162
  }
929
1163
  static getSettablePaths() {
930
1164
  return {
931
- relativeDirPath: (0, import_node_path8.join)(".github", "prompts")
1165
+ relativeDirPath: (0, import_node_path10.join)(".github", "prompts")
932
1166
  };
933
1167
  }
934
1168
  getBody() {
@@ -965,7 +1199,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
965
1199
  return {
966
1200
  success: false,
967
1201
  error: new Error(
968
- `Invalid frontmatter in ${(0, import_node_path8.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
1202
+ `Invalid frontmatter in ${(0, import_node_path10.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
969
1203
  )
970
1204
  };
971
1205
  }
@@ -999,7 +1233,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
999
1233
  validate = true
1000
1234
  }) {
1001
1235
  const paths = this.getSettablePaths();
1002
- const filePath = (0, import_node_path8.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1236
+ const filePath = (0, import_node_path10.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1003
1237
  const fileContent = await readFileContent(filePath);
1004
1238
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
1005
1239
  const result = CopilotCommandFrontmatterSchema.safeParse(frontmatter);
@@ -1009,7 +1243,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
1009
1243
  return new _CopilotCommand({
1010
1244
  baseDir,
1011
1245
  relativeDirPath: paths.relativeDirPath,
1012
- relativeFilePath: (0, import_node_path8.basename)(relativeFilePath),
1246
+ relativeFilePath: (0, import_node_path10.basename)(relativeFilePath),
1013
1247
  frontmatter: result.data,
1014
1248
  body: content.trim(),
1015
1249
  validate
@@ -1023,12 +1257,12 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
1023
1257
  }
1024
1258
  };
1025
1259
 
1026
- // src/commands/cursor-command.ts
1027
- var import_node_path9 = require("path");
1260
+ // src/features/commands/cursor-command.ts
1261
+ var import_node_path11 = require("path");
1028
1262
  var CursorCommand = class _CursorCommand extends ToolCommand {
1029
1263
  static getSettablePaths(_options = {}) {
1030
1264
  return {
1031
- relativeDirPath: (0, import_node_path9.join)(".cursor", "commands")
1265
+ relativeDirPath: (0, import_node_path11.join)(".cursor", "commands")
1032
1266
  };
1033
1267
  }
1034
1268
  toRulesyncCommand() {
@@ -1081,26 +1315,26 @@ var CursorCommand = class _CursorCommand extends ToolCommand {
1081
1315
  global = false
1082
1316
  }) {
1083
1317
  const paths = this.getSettablePaths({ global });
1084
- const filePath = (0, import_node_path9.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1318
+ const filePath = (0, import_node_path11.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1085
1319
  const fileContent = await readFileContent(filePath);
1086
1320
  const { body: content } = parseFrontmatter(fileContent);
1087
1321
  return new _CursorCommand({
1088
1322
  baseDir,
1089
1323
  relativeDirPath: paths.relativeDirPath,
1090
- relativeFilePath: (0, import_node_path9.basename)(relativeFilePath),
1324
+ relativeFilePath: (0, import_node_path11.basename)(relativeFilePath),
1091
1325
  fileContent: content.trim(),
1092
1326
  validate
1093
1327
  });
1094
1328
  }
1095
1329
  };
1096
1330
 
1097
- // src/commands/geminicli-command.ts
1098
- var import_node_path10 = require("path");
1331
+ // src/features/commands/geminicli-command.ts
1332
+ var import_node_path12 = require("path");
1099
1333
  var import_smol_toml = require("smol-toml");
1100
- var import_mini7 = require("zod/mini");
1101
- var GeminiCliCommandFrontmatterSchema = import_mini7.z.object({
1102
- description: import_mini7.z.optional(import_mini7.z.string()),
1103
- prompt: import_mini7.z.string()
1334
+ var import_mini8 = require("zod/mini");
1335
+ var GeminiCliCommandFrontmatterSchema = import_mini8.z.object({
1336
+ description: import_mini8.z.optional(import_mini8.z.string()),
1337
+ prompt: import_mini8.z.string()
1104
1338
  });
1105
1339
  var GeminiCliCommand = class _GeminiCliCommand extends ToolCommand {
1106
1340
  frontmatter;
@@ -1113,7 +1347,7 @@ var GeminiCliCommand = class _GeminiCliCommand extends ToolCommand {
1113
1347
  }
1114
1348
  static getSettablePaths(_options = {}) {
1115
1349
  return {
1116
- relativeDirPath: (0, import_node_path10.join)(".gemini", "commands")
1350
+ relativeDirPath: (0, import_node_path12.join)(".gemini", "commands")
1117
1351
  };
1118
1352
  }
1119
1353
  parseTomlContent(content) {
@@ -1190,12 +1424,12 @@ ${geminiFrontmatter.prompt}
1190
1424
  global = false
1191
1425
  }) {
1192
1426
  const paths = this.getSettablePaths({ global });
1193
- const filePath = (0, import_node_path10.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1427
+ const filePath = (0, import_node_path12.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1194
1428
  const fileContent = await readFileContent(filePath);
1195
1429
  return new _GeminiCliCommand({
1196
1430
  baseDir,
1197
1431
  relativeDirPath: paths.relativeDirPath,
1198
- relativeFilePath: (0, import_node_path10.basename)(relativeFilePath),
1432
+ relativeFilePath: (0, import_node_path12.basename)(relativeFilePath),
1199
1433
  fileContent,
1200
1434
  validate
1201
1435
  });
@@ -1216,19 +1450,19 @@ ${geminiFrontmatter.prompt}
1216
1450
  }
1217
1451
  };
1218
1452
 
1219
- // src/commands/roo-command.ts
1220
- var import_node_path11 = require("path");
1221
- var import_mini8 = require("zod/mini");
1222
- var RooCommandFrontmatterSchema = import_mini8.z.object({
1223
- description: import_mini8.z.string(),
1224
- "argument-hint": (0, import_mini8.optional)(import_mini8.z.string())
1453
+ // src/features/commands/roo-command.ts
1454
+ var import_node_path13 = require("path");
1455
+ var import_mini9 = require("zod/mini");
1456
+ var RooCommandFrontmatterSchema = import_mini9.z.object({
1457
+ description: import_mini9.z.string(),
1458
+ "argument-hint": (0, import_mini9.optional)(import_mini9.z.string())
1225
1459
  });
1226
1460
  var RooCommand = class _RooCommand extends ToolCommand {
1227
1461
  frontmatter;
1228
1462
  body;
1229
1463
  static getSettablePaths() {
1230
1464
  return {
1231
- relativeDirPath: (0, import_node_path11.join)(".roo", "commands")
1465
+ relativeDirPath: (0, import_node_path13.join)(".roo", "commands")
1232
1466
  };
1233
1467
  }
1234
1468
  constructor({ frontmatter, body, ...rest }) {
@@ -1236,7 +1470,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1236
1470
  const result = RooCommandFrontmatterSchema.safeParse(frontmatter);
1237
1471
  if (!result.success) {
1238
1472
  throw new Error(
1239
- `Invalid frontmatter in ${(0, import_node_path11.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
1473
+ `Invalid frontmatter in ${(0, import_node_path13.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
1240
1474
  );
1241
1475
  }
1242
1476
  }
@@ -1302,7 +1536,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1302
1536
  return {
1303
1537
  success: false,
1304
1538
  error: new Error(
1305
- `Invalid frontmatter in ${(0, import_node_path11.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
1539
+ `Invalid frontmatter in ${(0, import_node_path13.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
1306
1540
  )
1307
1541
  };
1308
1542
  }
@@ -1318,7 +1552,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1318
1552
  relativeFilePath,
1319
1553
  validate = true
1320
1554
  }) {
1321
- const filePath = (0, import_node_path11.join)(baseDir, _RooCommand.getSettablePaths().relativeDirPath, relativeFilePath);
1555
+ const filePath = (0, import_node_path13.join)(baseDir, _RooCommand.getSettablePaths().relativeDirPath, relativeFilePath);
1322
1556
  const fileContent = await readFileContent(filePath);
1323
1557
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
1324
1558
  const result = RooCommandFrontmatterSchema.safeParse(frontmatter);
@@ -1328,7 +1562,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1328
1562
  return new _RooCommand({
1329
1563
  baseDir,
1330
1564
  relativeDirPath: _RooCommand.getSettablePaths().relativeDirPath,
1331
- relativeFilePath: (0, import_node_path11.basename)(relativeFilePath),
1565
+ relativeFilePath: (0, import_node_path13.basename)(relativeFilePath),
1332
1566
  frontmatter: result.data,
1333
1567
  body: content.trim(),
1334
1568
  fileContent,
@@ -1337,7 +1571,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1337
1571
  }
1338
1572
  };
1339
1573
 
1340
- // src/commands/commands-processor.ts
1574
+ // src/features/commands/commands-processor.ts
1341
1575
  var commandsProcessorToolTargets = [
1342
1576
  "agentsmd",
1343
1577
  "claudecode",
@@ -1346,7 +1580,7 @@ var commandsProcessorToolTargets = [
1346
1580
  "copilot",
1347
1581
  "cursor"
1348
1582
  ];
1349
- var CommandsProcessorToolTargetSchema = import_mini9.z.enum(
1583
+ var CommandsProcessorToolTargetSchema = import_mini10.z.enum(
1350
1584
  // codexcli is not in the list of tool targets but we add it here because it is a valid tool target for global mode generation
1351
1585
  commandsProcessorToolTargets.concat("codexcli")
1352
1586
  );
@@ -1464,11 +1698,11 @@ var CommandsProcessor = class extends FeatureProcessor {
1464
1698
  */
1465
1699
  async loadRulesyncFiles() {
1466
1700
  const rulesyncCommandPaths = await findFilesByGlobs(
1467
- (0, import_node_path12.join)(RulesyncCommand.getSettablePaths().relativeDirPath, "*.md")
1701
+ (0, import_node_path14.join)(RulesyncCommand.getSettablePaths().relativeDirPath, "*.md")
1468
1702
  );
1469
1703
  const rulesyncCommands = (await Promise.allSettled(
1470
1704
  rulesyncCommandPaths.map(
1471
- (path2) => RulesyncCommand.fromFile({ relativeFilePath: (0, import_node_path12.basename)(path2) })
1705
+ (path2) => RulesyncCommand.fromFile({ relativeFilePath: (0, import_node_path14.basename)(path2) })
1472
1706
  )
1473
1707
  )).filter((result) => result.status === "fulfilled").map((result) => result.value);
1474
1708
  logger.info(`Successfully loaded ${rulesyncCommands.length} rulesync commands`);
@@ -1507,7 +1741,7 @@ var CommandsProcessor = class extends FeatureProcessor {
1507
1741
  extension
1508
1742
  }) {
1509
1743
  const commandFilePaths = await findFilesByGlobs(
1510
- (0, import_node_path12.join)(this.baseDir, relativeDirPath, `*.${extension}`)
1744
+ (0, import_node_path14.join)(this.baseDir, relativeDirPath, `*.${extension}`)
1511
1745
  );
1512
1746
  const toolCommands = (await Promise.allSettled(
1513
1747
  commandFilePaths.map((path2) => {
@@ -1515,40 +1749,40 @@ var CommandsProcessor = class extends FeatureProcessor {
1515
1749
  case "agentsmd":
1516
1750
  return AgentsmdCommand.fromFile({
1517
1751
  baseDir: this.baseDir,
1518
- relativeFilePath: (0, import_node_path12.basename)(path2)
1752
+ relativeFilePath: (0, import_node_path14.basename)(path2)
1519
1753
  });
1520
1754
  case "claudecode":
1521
1755
  return ClaudecodeCommand.fromFile({
1522
1756
  baseDir: this.baseDir,
1523
- relativeFilePath: (0, import_node_path12.basename)(path2),
1757
+ relativeFilePath: (0, import_node_path14.basename)(path2),
1524
1758
  global: this.global
1525
1759
  });
1526
1760
  case "geminicli":
1527
1761
  return GeminiCliCommand.fromFile({
1528
1762
  baseDir: this.baseDir,
1529
- relativeFilePath: (0, import_node_path12.basename)(path2),
1763
+ relativeFilePath: (0, import_node_path14.basename)(path2),
1530
1764
  global: this.global
1531
1765
  });
1532
1766
  case "roo":
1533
1767
  return RooCommand.fromFile({
1534
1768
  baseDir: this.baseDir,
1535
- relativeFilePath: (0, import_node_path12.basename)(path2)
1769
+ relativeFilePath: (0, import_node_path14.basename)(path2)
1536
1770
  });
1537
1771
  case "copilot":
1538
1772
  return CopilotCommand.fromFile({
1539
1773
  baseDir: this.baseDir,
1540
- relativeFilePath: (0, import_node_path12.basename)(path2)
1774
+ relativeFilePath: (0, import_node_path14.basename)(path2)
1541
1775
  });
1542
1776
  case "cursor":
1543
1777
  return CursorCommand.fromFile({
1544
1778
  baseDir: this.baseDir,
1545
- relativeFilePath: (0, import_node_path12.basename)(path2),
1779
+ relativeFilePath: (0, import_node_path14.basename)(path2),
1546
1780
  global: this.global
1547
1781
  });
1548
1782
  case "codexcli":
1549
1783
  return CodexcliCommand.fromFile({
1550
1784
  baseDir: this.baseDir,
1551
- relativeFilePath: (0, import_node_path12.basename)(path2),
1785
+ relativeFilePath: (0, import_node_path14.basename)(path2),
1552
1786
  global: this.global
1553
1787
  });
1554
1788
  default:
@@ -1655,354 +1889,139 @@ var CommandsProcessor = class extends FeatureProcessor {
1655
1889
  }
1656
1890
  };
1657
1891
 
1658
- // src/config/config-resolver.ts
1659
- var import_node_path13 = require("path");
1660
- var import_jsonc_parser = require("jsonc-parser");
1892
+ // src/features/ignore/ignore-processor.ts
1893
+ var import_mini11 = require("zod/mini");
1661
1894
 
1662
- // src/config/config.ts
1663
- var import_mini10 = require("zod/mini");
1664
- var ConfigParamsSchema = import_mini10.z.object({
1665
- baseDirs: import_mini10.z.array(import_mini10.z.string()),
1666
- targets: RulesyncTargetsSchema,
1667
- features: RulesyncFeaturesSchema,
1668
- verbose: import_mini10.z.boolean(),
1669
- delete: import_mini10.z.boolean(),
1670
- // New non-experimental options
1671
- global: (0, import_mini10.optional)(import_mini10.z.boolean()),
1672
- simulatedCommands: (0, import_mini10.optional)(import_mini10.z.boolean()),
1673
- simulatedSubagents: (0, import_mini10.optional)(import_mini10.z.boolean()),
1674
- modularMcp: (0, import_mini10.optional)(import_mini10.z.boolean()),
1675
- // Deprecated experimental options (for backward compatibility)
1676
- experimentalGlobal: (0, import_mini10.optional)(import_mini10.z.boolean()),
1677
- experimentalSimulateCommands: (0, import_mini10.optional)(import_mini10.z.boolean()),
1678
- experimentalSimulateSubagents: (0, import_mini10.optional)(import_mini10.z.boolean())
1679
- });
1680
- var PartialConfigParamsSchema = import_mini10.z.partial(ConfigParamsSchema);
1681
- var RequiredConfigParamsSchema = import_mini10.z.required(ConfigParamsSchema);
1682
- var Config = class {
1683
- baseDirs;
1684
- targets;
1685
- features;
1686
- verbose;
1687
- delete;
1688
- global;
1689
- simulatedCommands;
1690
- simulatedSubagents;
1691
- modularMcp;
1692
- constructor({
1693
- baseDirs,
1694
- targets,
1695
- features,
1696
- verbose,
1697
- delete: isDelete,
1698
- global,
1699
- simulatedCommands,
1700
- simulatedSubagents,
1701
- modularMcp,
1702
- experimentalGlobal,
1703
- experimentalSimulateCommands,
1704
- experimentalSimulateSubagents
1705
- }) {
1706
- this.baseDirs = baseDirs;
1707
- this.targets = targets;
1708
- this.features = features;
1709
- this.verbose = verbose;
1710
- this.delete = isDelete;
1711
- this.global = global ?? experimentalGlobal ?? false;
1712
- this.simulatedCommands = simulatedCommands ?? experimentalSimulateCommands ?? false;
1713
- this.simulatedSubagents = simulatedSubagents ?? experimentalSimulateSubagents ?? false;
1714
- this.modularMcp = modularMcp ?? false;
1895
+ // src/features/ignore/amazonqcli-ignore.ts
1896
+ var import_node_path16 = require("path");
1897
+
1898
+ // src/types/tool-file.ts
1899
+ var ToolFile = class extends AiFile {
1900
+ };
1901
+
1902
+ // src/features/ignore/rulesync-ignore.ts
1903
+ var import_node_path15 = require("path");
1904
+ var RulesyncIgnore = class _RulesyncIgnore extends RulesyncFile {
1905
+ validate() {
1906
+ return { success: true, error: null };
1715
1907
  }
1716
- getBaseDirs() {
1717
- return this.baseDirs;
1908
+ static getSettablePaths() {
1909
+ return {
1910
+ relativeDirPath: ".",
1911
+ relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH
1912
+ };
1718
1913
  }
1719
- getTargets() {
1720
- if (this.targets.includes("*")) {
1721
- return [...ALL_TOOL_TARGETS];
1722
- }
1723
- return this.targets.filter((target) => target !== "*");
1914
+ static async fromFile() {
1915
+ const baseDir = process.cwd();
1916
+ const filePath = (0, import_node_path15.join)(baseDir, this.getSettablePaths().relativeFilePath);
1917
+ const fileContent = await readFileContent(filePath);
1918
+ return new _RulesyncIgnore({
1919
+ baseDir,
1920
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
1921
+ relativeFilePath: this.getSettablePaths().relativeFilePath,
1922
+ fileContent
1923
+ });
1724
1924
  }
1725
- getFeatures() {
1726
- if (this.features.includes("*")) {
1727
- return [...ALL_FEATURES];
1925
+ };
1926
+
1927
+ // src/features/ignore/tool-ignore.ts
1928
+ var ToolIgnore = class extends ToolFile {
1929
+ patterns;
1930
+ constructor(params) {
1931
+ super({
1932
+ ...params,
1933
+ validate: true
1934
+ });
1935
+ this.patterns = this.fileContent.split(/\r?\n|\r/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
1936
+ if (params.validate) {
1937
+ const result = this.validate();
1938
+ if (!result.success) {
1939
+ throw result.error;
1940
+ }
1728
1941
  }
1729
- return this.features.filter((feature) => feature !== "*");
1730
1942
  }
1731
- getVerbose() {
1732
- return this.verbose;
1943
+ static getSettablePaths() {
1944
+ throw new Error("Please implement this method in the subclass.");
1733
1945
  }
1734
- getDelete() {
1735
- return this.delete;
1946
+ getPatterns() {
1947
+ return this.patterns;
1736
1948
  }
1737
- getGlobal() {
1738
- return this.global;
1949
+ validate() {
1950
+ return { success: true, error: null };
1739
1951
  }
1740
- getSimulatedCommands() {
1741
- return this.simulatedCommands;
1952
+ static fromRulesyncIgnore(_params) {
1953
+ throw new Error("Please implement this method in the subclass.");
1742
1954
  }
1743
- getSimulatedSubagents() {
1744
- return this.simulatedSubagents;
1955
+ toRulesyncIgnoreDefault() {
1956
+ return new RulesyncIgnore({
1957
+ baseDir: ".",
1958
+ relativeDirPath: ".",
1959
+ relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
1960
+ fileContent: this.fileContent
1961
+ });
1745
1962
  }
1746
- getModularMcp() {
1747
- return this.modularMcp;
1963
+ static async fromFile(_params) {
1964
+ throw new Error("Please implement this method in the subclass.");
1748
1965
  }
1749
- // Deprecated getters for backward compatibility
1750
- /** @deprecated Use getGlobal() instead */
1751
- getExperimentalGlobal() {
1752
- return this.global;
1966
+ };
1967
+
1968
+ // src/features/ignore/amazonqcli-ignore.ts
1969
+ var AmazonqcliIgnore = class _AmazonqcliIgnore extends ToolIgnore {
1970
+ static getSettablePaths() {
1971
+ return {
1972
+ relativeDirPath: ".",
1973
+ relativeFilePath: ".amazonqignore"
1974
+ };
1753
1975
  }
1754
- /** @deprecated Use getSimulatedCommands() instead */
1755
- getExperimentalSimulateCommands() {
1756
- return this.simulatedCommands;
1976
+ /**
1977
+ * Convert to RulesyncIgnore format
1978
+ */
1979
+ toRulesyncIgnore() {
1980
+ return this.toRulesyncIgnoreDefault();
1757
1981
  }
1758
- /** @deprecated Use getSimulatedSubagents() instead */
1759
- getExperimentalSimulateSubagents() {
1760
- return this.simulatedSubagents;
1982
+ /**
1983
+ * Create AmazonqcliIgnore from RulesyncIgnore
1984
+ * Supports conversion from unified rulesync format to Amazon Q CLI specific format
1985
+ */
1986
+ static fromRulesyncIgnore({
1987
+ baseDir = process.cwd(),
1988
+ rulesyncIgnore
1989
+ }) {
1990
+ const body = rulesyncIgnore.getFileContent();
1991
+ return new _AmazonqcliIgnore({
1992
+ baseDir,
1993
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
1994
+ relativeFilePath: this.getSettablePaths().relativeFilePath,
1995
+ fileContent: body
1996
+ });
1997
+ }
1998
+ /**
1999
+ * Create AmazonqcliIgnore from file path
2000
+ * Supports both proposed .q-ignore and .amazonqignore formats
2001
+ */
2002
+ static async fromFile({
2003
+ baseDir = process.cwd(),
2004
+ validate = true
2005
+ }) {
2006
+ const fileContent = await readFileContent(
2007
+ (0, import_node_path16.join)(
2008
+ baseDir,
2009
+ this.getSettablePaths().relativeDirPath,
2010
+ this.getSettablePaths().relativeFilePath
2011
+ )
2012
+ );
2013
+ return new _AmazonqcliIgnore({
2014
+ baseDir,
2015
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
2016
+ relativeFilePath: this.getSettablePaths().relativeFilePath,
2017
+ fileContent,
2018
+ validate
2019
+ });
1761
2020
  }
1762
2021
  };
1763
2022
 
1764
- // src/config/config-resolver.ts
1765
- var defaults = {
1766
- targets: ["agentsmd"],
1767
- features: ["rules"],
1768
- verbose: false,
1769
- delete: false,
1770
- baseDirs: [process.cwd()],
1771
- configPath: "rulesync.jsonc",
1772
- global: false,
1773
- simulatedCommands: false,
1774
- simulatedSubagents: false,
1775
- modularMcp: false,
1776
- experimentalGlobal: false,
1777
- experimentalSimulateCommands: false,
1778
- experimentalSimulateSubagents: false
1779
- };
1780
- var ConfigResolver = class {
1781
- static async resolve({
1782
- targets,
1783
- features,
1784
- verbose,
1785
- delete: isDelete,
1786
- baseDirs,
1787
- configPath = defaults.configPath,
1788
- global,
1789
- simulatedCommands,
1790
- simulatedSubagents,
1791
- modularMcp,
1792
- experimentalGlobal,
1793
- experimentalSimulateCommands,
1794
- experimentalSimulateSubagents
1795
- }) {
1796
- const validatedConfigPath = resolvePath(configPath, process.cwd());
1797
- let configByFile = {};
1798
- if (await fileExists(validatedConfigPath)) {
1799
- try {
1800
- const fileContent = await readFileContent(validatedConfigPath);
1801
- const jsonData = (0, import_jsonc_parser.parse)(fileContent);
1802
- configByFile = PartialConfigParamsSchema.parse(jsonData);
1803
- } catch (error) {
1804
- logger.error(`Failed to load config file: ${formatError(error)}`);
1805
- throw error;
1806
- }
1807
- }
1808
- const deprecatedGlobal = experimentalGlobal ?? configByFile.experimentalGlobal;
1809
- const deprecatedCommands = experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands;
1810
- const deprecatedSubagents = experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents;
1811
- if (deprecatedGlobal !== void 0) {
1812
- warnDeprecatedOptions({ experimentalGlobal: deprecatedGlobal });
1813
- }
1814
- if (deprecatedCommands !== void 0) {
1815
- warnDeprecatedOptions({ experimentalSimulateCommands: deprecatedCommands });
1816
- }
1817
- if (deprecatedSubagents !== void 0) {
1818
- warnDeprecatedOptions({ experimentalSimulateSubagents: deprecatedSubagents });
1819
- }
1820
- const resolvedGlobal = global ?? configByFile.global ?? experimentalGlobal ?? configByFile.experimentalGlobal ?? defaults.global;
1821
- const resolvedSimulatedCommands = simulatedCommands ?? configByFile.simulatedCommands ?? experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands ?? defaults.simulatedCommands;
1822
- const resolvedSimulatedSubagents = simulatedSubagents ?? configByFile.simulatedSubagents ?? experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents ?? defaults.simulatedSubagents;
1823
- const configParams = {
1824
- targets: targets ?? configByFile.targets ?? defaults.targets,
1825
- features: features ?? configByFile.features ?? defaults.features,
1826
- verbose: verbose ?? configByFile.verbose ?? defaults.verbose,
1827
- delete: isDelete ?? configByFile.delete ?? defaults.delete,
1828
- baseDirs: getBaseDirsInLightOfGlobal({
1829
- baseDirs: baseDirs ?? configByFile.baseDirs ?? defaults.baseDirs,
1830
- global: resolvedGlobal
1831
- }),
1832
- global: resolvedGlobal,
1833
- simulatedCommands: resolvedSimulatedCommands,
1834
- simulatedSubagents: resolvedSimulatedSubagents,
1835
- modularMcp: modularMcp ?? configByFile.modularMcp ?? defaults.modularMcp
1836
- };
1837
- return new Config(configParams);
1838
- }
1839
- };
1840
- function warnDeprecatedOptions({
1841
- experimentalGlobal,
1842
- experimentalSimulateCommands,
1843
- experimentalSimulateSubagents
1844
- }) {
1845
- if (experimentalGlobal !== void 0) {
1846
- logger.warn("'experimentalGlobal' option is deprecated. Please use 'global' instead.");
1847
- }
1848
- if (experimentalSimulateCommands !== void 0) {
1849
- logger.warn(
1850
- "'experimentalSimulateCommands' option is deprecated. Please use 'simulatedCommands' instead."
1851
- );
1852
- }
1853
- if (experimentalSimulateSubagents !== void 0) {
1854
- logger.warn(
1855
- "'experimentalSimulateSubagents' option is deprecated. Please use 'simulatedSubagents' instead."
1856
- );
1857
- }
1858
- }
1859
- function getBaseDirsInLightOfGlobal({
1860
- baseDirs,
1861
- global
1862
- }) {
1863
- if (global) {
1864
- return [getHomeDirectory()];
1865
- }
1866
- const resolvedBaseDirs = baseDirs.map((baseDir) => (0, import_node_path13.resolve)(baseDir));
1867
- resolvedBaseDirs.forEach((baseDir) => {
1868
- validateBaseDir(baseDir);
1869
- });
1870
- return resolvedBaseDirs;
1871
- }
1872
-
1873
- // src/ignore/ignore-processor.ts
1874
- var import_mini11 = require("zod/mini");
1875
-
1876
- // src/ignore/amazonqcli-ignore.ts
1877
- var import_node_path15 = require("path");
1878
-
1879
- // src/types/tool-file.ts
1880
- var ToolFile = class extends AiFile {
1881
- };
1882
-
1883
- // src/ignore/rulesync-ignore.ts
1884
- var import_node_path14 = require("path");
1885
- var RulesyncIgnore = class _RulesyncIgnore extends RulesyncFile {
1886
- validate() {
1887
- return { success: true, error: null };
1888
- }
1889
- static getSettablePaths() {
1890
- return {
1891
- relativeDirPath: ".",
1892
- relativeFilePath: ".rulesyncignore"
1893
- };
1894
- }
1895
- static async fromFile() {
1896
- const baseDir = process.cwd();
1897
- const filePath = (0, import_node_path14.join)(baseDir, this.getSettablePaths().relativeFilePath);
1898
- const fileContent = await readFileContent(filePath);
1899
- return new _RulesyncIgnore({
1900
- baseDir,
1901
- relativeDirPath: this.getSettablePaths().relativeDirPath,
1902
- relativeFilePath: this.getSettablePaths().relativeFilePath,
1903
- fileContent
1904
- });
1905
- }
1906
- };
1907
-
1908
- // src/ignore/tool-ignore.ts
1909
- var ToolIgnore = class extends ToolFile {
1910
- patterns;
1911
- constructor(params) {
1912
- super({
1913
- ...params,
1914
- validate: true
1915
- });
1916
- this.patterns = this.fileContent.split(/\r?\n|\r/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
1917
- if (params.validate) {
1918
- const result = this.validate();
1919
- if (!result.success) {
1920
- throw result.error;
1921
- }
1922
- }
1923
- }
1924
- static getSettablePaths() {
1925
- throw new Error("Please implement this method in the subclass.");
1926
- }
1927
- getPatterns() {
1928
- return this.patterns;
1929
- }
1930
- validate() {
1931
- return { success: true, error: null };
1932
- }
1933
- static fromRulesyncIgnore(_params) {
1934
- throw new Error("Please implement this method in the subclass.");
1935
- }
1936
- toRulesyncIgnoreDefault() {
1937
- return new RulesyncIgnore({
1938
- baseDir: ".",
1939
- relativeDirPath: ".",
1940
- relativeFilePath: ".rulesyncignore",
1941
- fileContent: this.fileContent
1942
- });
1943
- }
1944
- static async fromFile(_params) {
1945
- throw new Error("Please implement this method in the subclass.");
1946
- }
1947
- };
1948
-
1949
- // src/ignore/amazonqcli-ignore.ts
1950
- var AmazonqcliIgnore = class _AmazonqcliIgnore extends ToolIgnore {
1951
- static getSettablePaths() {
1952
- return {
1953
- relativeDirPath: ".",
1954
- relativeFilePath: ".amazonqignore"
1955
- };
1956
- }
1957
- /**
1958
- * Convert to RulesyncIgnore format
1959
- */
1960
- toRulesyncIgnore() {
1961
- return this.toRulesyncIgnoreDefault();
1962
- }
1963
- /**
1964
- * Create AmazonqcliIgnore from RulesyncIgnore
1965
- * Supports conversion from unified rulesync format to Amazon Q CLI specific format
1966
- */
1967
- static fromRulesyncIgnore({
1968
- baseDir = process.cwd(),
1969
- rulesyncIgnore
1970
- }) {
1971
- const body = rulesyncIgnore.getFileContent();
1972
- return new _AmazonqcliIgnore({
1973
- baseDir,
1974
- relativeDirPath: this.getSettablePaths().relativeDirPath,
1975
- relativeFilePath: this.getSettablePaths().relativeFilePath,
1976
- fileContent: body
1977
- });
1978
- }
1979
- /**
1980
- * Create AmazonqcliIgnore from file path
1981
- * Supports both proposed .q-ignore and .amazonqignore formats
1982
- */
1983
- static async fromFile({
1984
- baseDir = process.cwd(),
1985
- validate = true
1986
- }) {
1987
- const fileContent = await readFileContent(
1988
- (0, import_node_path15.join)(
1989
- baseDir,
1990
- this.getSettablePaths().relativeDirPath,
1991
- this.getSettablePaths().relativeFilePath
1992
- )
1993
- );
1994
- return new _AmazonqcliIgnore({
1995
- baseDir,
1996
- relativeDirPath: this.getSettablePaths().relativeDirPath,
1997
- relativeFilePath: this.getSettablePaths().relativeFilePath,
1998
- fileContent,
1999
- validate
2000
- });
2001
- }
2002
- };
2003
-
2004
- // src/ignore/augmentcode-ignore.ts
2005
- var import_node_path16 = require("path");
2023
+ // src/features/ignore/augmentcode-ignore.ts
2024
+ var import_node_path17 = require("path");
2006
2025
  var AugmentcodeIgnore = class _AugmentcodeIgnore extends ToolIgnore {
2007
2026
  static getSettablePaths() {
2008
2027
  return {
@@ -2040,7 +2059,7 @@ var AugmentcodeIgnore = class _AugmentcodeIgnore extends ToolIgnore {
2040
2059
  validate = true
2041
2060
  }) {
2042
2061
  const fileContent = await readFileContent(
2043
- (0, import_node_path16.join)(
2062
+ (0, import_node_path17.join)(
2044
2063
  baseDir,
2045
2064
  this.getSettablePaths().relativeDirPath,
2046
2065
  this.getSettablePaths().relativeFilePath
@@ -2056,8 +2075,8 @@ var AugmentcodeIgnore = class _AugmentcodeIgnore extends ToolIgnore {
2056
2075
  }
2057
2076
  };
2058
2077
 
2059
- // src/ignore/claudecode-ignore.ts
2060
- var import_node_path17 = require("path");
2078
+ // src/features/ignore/claudecode-ignore.ts
2079
+ var import_node_path18 = require("path");
2061
2080
  var import_es_toolkit = require("es-toolkit");
2062
2081
  var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
2063
2082
  constructor(params) {
@@ -2093,7 +2112,7 @@ var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
2093
2112
  const fileContent = rulesyncIgnore.getFileContent();
2094
2113
  const patterns = fileContent.split(/\r?\n|\r/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
2095
2114
  const deniedValues = patterns.map((pattern) => `Read(${pattern})`);
2096
- const filePath = (0, import_node_path17.join)(
2115
+ const filePath = (0, import_node_path18.join)(
2097
2116
  baseDir,
2098
2117
  this.getSettablePaths().relativeDirPath,
2099
2118
  this.getSettablePaths().relativeFilePath
@@ -2121,7 +2140,7 @@ var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
2121
2140
  validate = true
2122
2141
  }) {
2123
2142
  const fileContent = await readFileContent(
2124
- (0, import_node_path17.join)(
2143
+ (0, import_node_path18.join)(
2125
2144
  baseDir,
2126
2145
  this.getSettablePaths().relativeDirPath,
2127
2146
  this.getSettablePaths().relativeFilePath
@@ -2137,8 +2156,8 @@ var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
2137
2156
  }
2138
2157
  };
2139
2158
 
2140
- // src/ignore/cline-ignore.ts
2141
- var import_node_path18 = require("path");
2159
+ // src/features/ignore/cline-ignore.ts
2160
+ var import_node_path19 = require("path");
2142
2161
  var ClineIgnore = class _ClineIgnore extends ToolIgnore {
2143
2162
  static getSettablePaths() {
2144
2163
  return {
@@ -2175,7 +2194,7 @@ var ClineIgnore = class _ClineIgnore extends ToolIgnore {
2175
2194
  validate = true
2176
2195
  }) {
2177
2196
  const fileContent = await readFileContent(
2178
- (0, import_node_path18.join)(
2197
+ (0, import_node_path19.join)(
2179
2198
  baseDir,
2180
2199
  this.getSettablePaths().relativeDirPath,
2181
2200
  this.getSettablePaths().relativeFilePath
@@ -2191,8 +2210,8 @@ var ClineIgnore = class _ClineIgnore extends ToolIgnore {
2191
2210
  }
2192
2211
  };
2193
2212
 
2194
- // src/ignore/cursor-ignore.ts
2195
- var import_node_path19 = require("path");
2213
+ // src/features/ignore/cursor-ignore.ts
2214
+ var import_node_path20 = require("path");
2196
2215
  var CursorIgnore = class _CursorIgnore extends ToolIgnore {
2197
2216
  static getSettablePaths() {
2198
2217
  return {
@@ -2204,7 +2223,7 @@ var CursorIgnore = class _CursorIgnore extends ToolIgnore {
2204
2223
  return new RulesyncIgnore({
2205
2224
  baseDir: ".",
2206
2225
  relativeDirPath: ".",
2207
- relativeFilePath: ".rulesyncignore",
2226
+ relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
2208
2227
  fileContent: this.fileContent
2209
2228
  });
2210
2229
  }
@@ -2225,7 +2244,7 @@ var CursorIgnore = class _CursorIgnore extends ToolIgnore {
2225
2244
  validate = true
2226
2245
  }) {
2227
2246
  const fileContent = await readFileContent(
2228
- (0, import_node_path19.join)(
2247
+ (0, import_node_path20.join)(
2229
2248
  baseDir,
2230
2249
  this.getSettablePaths().relativeDirPath,
2231
2250
  this.getSettablePaths().relativeFilePath
@@ -2241,8 +2260,8 @@ var CursorIgnore = class _CursorIgnore extends ToolIgnore {
2241
2260
  }
2242
2261
  };
2243
2262
 
2244
- // src/ignore/geminicli-ignore.ts
2245
- var import_node_path20 = require("path");
2263
+ // src/features/ignore/geminicli-ignore.ts
2264
+ var import_node_path21 = require("path");
2246
2265
  var GeminiCliIgnore = class _GeminiCliIgnore extends ToolIgnore {
2247
2266
  static getSettablePaths() {
2248
2267
  return {
@@ -2269,7 +2288,7 @@ var GeminiCliIgnore = class _GeminiCliIgnore extends ToolIgnore {
2269
2288
  validate = true
2270
2289
  }) {
2271
2290
  const fileContent = await readFileContent(
2272
- (0, import_node_path20.join)(
2291
+ (0, import_node_path21.join)(
2273
2292
  baseDir,
2274
2293
  this.getSettablePaths().relativeDirPath,
2275
2294
  this.getSettablePaths().relativeFilePath
@@ -2285,8 +2304,8 @@ var GeminiCliIgnore = class _GeminiCliIgnore extends ToolIgnore {
2285
2304
  }
2286
2305
  };
2287
2306
 
2288
- // src/ignore/junie-ignore.ts
2289
- var import_node_path21 = require("path");
2307
+ // src/features/ignore/junie-ignore.ts
2308
+ var import_node_path22 = require("path");
2290
2309
  var JunieIgnore = class _JunieIgnore extends ToolIgnore {
2291
2310
  static getSettablePaths() {
2292
2311
  return {
@@ -2313,7 +2332,7 @@ var JunieIgnore = class _JunieIgnore extends ToolIgnore {
2313
2332
  validate = true
2314
2333
  }) {
2315
2334
  const fileContent = await readFileContent(
2316
- (0, import_node_path21.join)(
2335
+ (0, import_node_path22.join)(
2317
2336
  baseDir,
2318
2337
  this.getSettablePaths().relativeDirPath,
2319
2338
  this.getSettablePaths().relativeFilePath
@@ -2329,8 +2348,8 @@ var JunieIgnore = class _JunieIgnore extends ToolIgnore {
2329
2348
  }
2330
2349
  };
2331
2350
 
2332
- // src/ignore/kiro-ignore.ts
2333
- var import_node_path22 = require("path");
2351
+ // src/features/ignore/kiro-ignore.ts
2352
+ var import_node_path23 = require("path");
2334
2353
  var KiroIgnore = class _KiroIgnore extends ToolIgnore {
2335
2354
  static getSettablePaths() {
2336
2355
  return {
@@ -2357,7 +2376,7 @@ var KiroIgnore = class _KiroIgnore extends ToolIgnore {
2357
2376
  validate = true
2358
2377
  }) {
2359
2378
  const fileContent = await readFileContent(
2360
- (0, import_node_path22.join)(
2379
+ (0, import_node_path23.join)(
2361
2380
  baseDir,
2362
2381
  this.getSettablePaths().relativeDirPath,
2363
2382
  this.getSettablePaths().relativeFilePath
@@ -2373,8 +2392,8 @@ var KiroIgnore = class _KiroIgnore extends ToolIgnore {
2373
2392
  }
2374
2393
  };
2375
2394
 
2376
- // src/ignore/qwencode-ignore.ts
2377
- var import_node_path23 = require("path");
2395
+ // src/features/ignore/qwencode-ignore.ts
2396
+ var import_node_path24 = require("path");
2378
2397
  var QwencodeIgnore = class _QwencodeIgnore extends ToolIgnore {
2379
2398
  static getSettablePaths() {
2380
2399
  return {
@@ -2401,7 +2420,7 @@ var QwencodeIgnore = class _QwencodeIgnore extends ToolIgnore {
2401
2420
  validate = true
2402
2421
  }) {
2403
2422
  const fileContent = await readFileContent(
2404
- (0, import_node_path23.join)(
2423
+ (0, import_node_path24.join)(
2405
2424
  baseDir,
2406
2425
  this.getSettablePaths().relativeDirPath,
2407
2426
  this.getSettablePaths().relativeFilePath
@@ -2417,8 +2436,8 @@ var QwencodeIgnore = class _QwencodeIgnore extends ToolIgnore {
2417
2436
  }
2418
2437
  };
2419
2438
 
2420
- // src/ignore/roo-ignore.ts
2421
- var import_node_path24 = require("path");
2439
+ // src/features/ignore/roo-ignore.ts
2440
+ var import_node_path25 = require("path");
2422
2441
  var RooIgnore = class _RooIgnore extends ToolIgnore {
2423
2442
  static getSettablePaths() {
2424
2443
  return {
@@ -2445,7 +2464,7 @@ var RooIgnore = class _RooIgnore extends ToolIgnore {
2445
2464
  validate = true
2446
2465
  }) {
2447
2466
  const fileContent = await readFileContent(
2448
- (0, import_node_path24.join)(
2467
+ (0, import_node_path25.join)(
2449
2468
  baseDir,
2450
2469
  this.getSettablePaths().relativeDirPath,
2451
2470
  this.getSettablePaths().relativeFilePath
@@ -2461,8 +2480,8 @@ var RooIgnore = class _RooIgnore extends ToolIgnore {
2461
2480
  }
2462
2481
  };
2463
2482
 
2464
- // src/ignore/windsurf-ignore.ts
2465
- var import_node_path25 = require("path");
2483
+ // src/features/ignore/windsurf-ignore.ts
2484
+ var import_node_path26 = require("path");
2466
2485
  var WindsurfIgnore = class _WindsurfIgnore extends ToolIgnore {
2467
2486
  static getSettablePaths() {
2468
2487
  return {
@@ -2489,7 +2508,7 @@ var WindsurfIgnore = class _WindsurfIgnore extends ToolIgnore {
2489
2508
  validate = true
2490
2509
  }) {
2491
2510
  const fileContent = await readFileContent(
2492
- (0, import_node_path25.join)(
2511
+ (0, import_node_path26.join)(
2493
2512
  baseDir,
2494
2513
  this.getSettablePaths().relativeDirPath,
2495
2514
  this.getSettablePaths().relativeFilePath
@@ -2505,7 +2524,7 @@ var WindsurfIgnore = class _WindsurfIgnore extends ToolIgnore {
2505
2524
  }
2506
2525
  };
2507
2526
 
2508
- // src/ignore/ignore-processor.ts
2527
+ // src/features/ignore/ignore-processor.ts
2509
2528
  var ignoreProcessorToolTargets = [
2510
2529
  "amazonqcli",
2511
2530
  "augmentcode",
@@ -2606,7 +2625,7 @@ var IgnoreProcessor = class extends FeatureProcessor {
2606
2625
  (file) => file instanceof RulesyncIgnore
2607
2626
  );
2608
2627
  if (!rulesyncIgnore) {
2609
- throw new Error(`No .rulesyncignore found.`);
2628
+ throw new Error(`No ${RULESYNC_IGNORE_RELATIVE_FILE_PATH} found.`);
2610
2629
  }
2611
2630
  const toolIgnores = await Promise.all(
2612
2631
  [rulesyncIgnore].map(async (rulesyncIgnore2) => {
@@ -2693,14 +2712,14 @@ var IgnoreProcessor = class extends FeatureProcessor {
2693
2712
  }
2694
2713
  };
2695
2714
 
2696
- // src/mcp/mcp-processor.ts
2715
+ // src/features/mcp/mcp-processor.ts
2697
2716
  var import_mini13 = require("zod/mini");
2698
2717
 
2699
- // src/mcp/amazonqcli-mcp.ts
2700
- var import_node_path27 = require("path");
2718
+ // src/features/mcp/amazonqcli-mcp.ts
2719
+ var import_node_path28 = require("path");
2701
2720
 
2702
- // src/mcp/rulesync-mcp.ts
2703
- var import_node_path26 = require("path");
2721
+ // src/features/mcp/rulesync-mcp.ts
2722
+ var import_node_path27 = require("path");
2704
2723
  var import_object = require("es-toolkit/object");
2705
2724
  var import_mini12 = require("zod/mini");
2706
2725
  var McpTransportTypeSchema = import_mini12.z.enum(["stdio", "sse", "http"]);
@@ -2751,11 +2770,11 @@ var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
2751
2770
  static getSettablePaths() {
2752
2771
  return {
2753
2772
  recommended: {
2754
- relativeDirPath: ".rulesync",
2773
+ relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
2755
2774
  relativeFilePath: "mcp.json"
2756
2775
  },
2757
2776
  legacy: {
2758
- relativeDirPath: ".rulesync",
2777
+ relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
2759
2778
  relativeFilePath: ".mcp.json"
2760
2779
  }
2761
2780
  };
@@ -2780,12 +2799,12 @@ var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
2780
2799
  }) {
2781
2800
  const baseDir = process.cwd();
2782
2801
  const paths = this.getSettablePaths();
2783
- const recommendedPath = (0, import_node_path26.join)(
2802
+ const recommendedPath = (0, import_node_path27.join)(
2784
2803
  baseDir,
2785
2804
  paths.recommended.relativeDirPath,
2786
2805
  paths.recommended.relativeFilePath
2787
2806
  );
2788
- const legacyPath = (0, import_node_path26.join)(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
2807
+ const legacyPath = (0, import_node_path27.join)(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
2789
2808
  if (await fileExists(recommendedPath)) {
2790
2809
  const fileContent2 = await readFileContent(recommendedPath);
2791
2810
  return new _RulesyncMcp({
@@ -2844,7 +2863,7 @@ var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
2844
2863
  }
2845
2864
  };
2846
2865
 
2847
- // src/mcp/tool-mcp.ts
2866
+ // src/features/mcp/tool-mcp.ts
2848
2867
  var ToolMcp = class extends ToolFile {
2849
2868
  constructor({ ...rest }) {
2850
2869
  super({
@@ -2870,7 +2889,7 @@ var ToolMcp = class extends ToolFile {
2870
2889
  } = {}) {
2871
2890
  return new RulesyncMcp({
2872
2891
  baseDir: this.baseDir,
2873
- relativeDirPath: ".rulesync",
2892
+ relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
2874
2893
  relativeFilePath: ".mcp.json",
2875
2894
  fileContent: fileContent ?? this.fileContent
2876
2895
  });
@@ -2883,7 +2902,7 @@ var ToolMcp = class extends ToolFile {
2883
2902
  }
2884
2903
  };
2885
2904
 
2886
- // src/mcp/amazonqcli-mcp.ts
2905
+ // src/features/mcp/amazonqcli-mcp.ts
2887
2906
  var AmazonqcliMcp = class _AmazonqcliMcp extends ToolMcp {
2888
2907
  json;
2889
2908
  constructor(params) {
@@ -2904,7 +2923,7 @@ var AmazonqcliMcp = class _AmazonqcliMcp extends ToolMcp {
2904
2923
  validate = true
2905
2924
  }) {
2906
2925
  const fileContent = await readFileContent(
2907
- (0, import_node_path27.join)(
2926
+ (0, import_node_path28.join)(
2908
2927
  baseDir,
2909
2928
  this.getSettablePaths().relativeDirPath,
2910
2929
  this.getSettablePaths().relativeFilePath
@@ -2939,11 +2958,11 @@ var AmazonqcliMcp = class _AmazonqcliMcp extends ToolMcp {
2939
2958
  }
2940
2959
  };
2941
2960
 
2942
- // src/mcp/claudecode-mcp.ts
2943
- var import_node_path29 = require("path");
2961
+ // src/features/mcp/claudecode-mcp.ts
2962
+ var import_node_path30 = require("path");
2944
2963
 
2945
- // src/mcp/modular-mcp.ts
2946
- var import_node_path28 = require("path");
2964
+ // src/features/mcp/modular-mcp.ts
2965
+ var import_node_path29 = require("path");
2947
2966
  var ModularMcp = class _ModularMcp extends AiFile {
2948
2967
  json;
2949
2968
  constructor(params) {
@@ -2998,7 +3017,7 @@ var ModularMcp = class _ModularMcp extends AiFile {
2998
3017
  args: [
2999
3018
  "-y",
3000
3019
  "@kimuson/modular-mcp",
3001
- (0, import_node_path28.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath)
3020
+ (0, import_node_path29.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath)
3002
3021
  ],
3003
3022
  env: {}
3004
3023
  }
@@ -3030,7 +3049,7 @@ var ModularMcp = class _ModularMcp extends AiFile {
3030
3049
  }
3031
3050
  };
3032
3051
 
3033
- // src/mcp/claudecode-mcp.ts
3052
+ // src/features/mcp/claudecode-mcp.ts
3034
3053
  var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
3035
3054
  json;
3036
3055
  constructor(params) {
@@ -3059,7 +3078,7 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
3059
3078
  }) {
3060
3079
  const paths = this.getSettablePaths({ global });
3061
3080
  const fileContent = await readOrInitializeFileContent(
3062
- (0, import_node_path29.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3081
+ (0, import_node_path30.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3063
3082
  JSON.stringify({ mcpServers: {} }, null, 2)
3064
3083
  );
3065
3084
  const json = JSON.parse(fileContent);
@@ -3081,7 +3100,7 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
3081
3100
  }) {
3082
3101
  const paths = this.getSettablePaths({ global });
3083
3102
  const fileContent = await readOrInitializeFileContent(
3084
- (0, import_node_path29.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3103
+ (0, import_node_path30.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3085
3104
  JSON.stringify({ mcpServers: {} }, null, 2)
3086
3105
  );
3087
3106
  const json = JSON.parse(fileContent);
@@ -3111,8 +3130,8 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
3111
3130
  }
3112
3131
  };
3113
3132
 
3114
- // src/mcp/cline-mcp.ts
3115
- var import_node_path30 = require("path");
3133
+ // src/features/mcp/cline-mcp.ts
3134
+ var import_node_path31 = require("path");
3116
3135
  var ClineMcp = class _ClineMcp extends ToolMcp {
3117
3136
  json;
3118
3137
  constructor(params) {
@@ -3133,7 +3152,7 @@ var ClineMcp = class _ClineMcp extends ToolMcp {
3133
3152
  validate = true
3134
3153
  }) {
3135
3154
  const fileContent = await readFileContent(
3136
- (0, import_node_path30.join)(
3155
+ (0, import_node_path31.join)(
3137
3156
  baseDir,
3138
3157
  this.getSettablePaths().relativeDirPath,
3139
3158
  this.getSettablePaths().relativeFilePath
@@ -3168,8 +3187,8 @@ var ClineMcp = class _ClineMcp extends ToolMcp {
3168
3187
  }
3169
3188
  };
3170
3189
 
3171
- // src/mcp/codexcli-mcp.ts
3172
- var import_node_path31 = require("path");
3190
+ // src/features/mcp/codexcli-mcp.ts
3191
+ var import_node_path32 = require("path");
3173
3192
  var smolToml = __toESM(require("smol-toml"), 1);
3174
3193
  var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
3175
3194
  toml;
@@ -3205,7 +3224,7 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
3205
3224
  }) {
3206
3225
  const paths = this.getSettablePaths({ global });
3207
3226
  const fileContent = await readFileContent(
3208
- (0, import_node_path31.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath)
3227
+ (0, import_node_path32.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath)
3209
3228
  );
3210
3229
  return new _CodexcliMcp({
3211
3230
  baseDir,
@@ -3222,7 +3241,7 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
3222
3241
  global = false
3223
3242
  }) {
3224
3243
  const paths = this.getSettablePaths({ global });
3225
- const configTomlFilePath = (0, import_node_path31.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath);
3244
+ const configTomlFilePath = (0, import_node_path32.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath);
3226
3245
  const configTomlFileContent = await readOrInitializeFileContent(
3227
3246
  configTomlFilePath,
3228
3247
  smolToml.stringify({})
@@ -3242,7 +3261,7 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
3242
3261
  toRulesyncMcp() {
3243
3262
  return new RulesyncMcp({
3244
3263
  baseDir: this.baseDir,
3245
- relativeDirPath: ".rulesync",
3264
+ relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
3246
3265
  relativeFilePath: ".mcp.json",
3247
3266
  fileContent: JSON.stringify({ mcpServers: this.toml.mcp_servers ?? {} }, null, 2)
3248
3267
  });
@@ -3262,8 +3281,8 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
3262
3281
  }
3263
3282
  };
3264
3283
 
3265
- // src/mcp/copilot-mcp.ts
3266
- var import_node_path32 = require("path");
3284
+ // src/features/mcp/copilot-mcp.ts
3285
+ var import_node_path33 = require("path");
3267
3286
  var CopilotMcp = class _CopilotMcp extends ToolMcp {
3268
3287
  json;
3269
3288
  constructor(params) {
@@ -3284,7 +3303,7 @@ var CopilotMcp = class _CopilotMcp extends ToolMcp {
3284
3303
  validate = true
3285
3304
  }) {
3286
3305
  const fileContent = await readFileContent(
3287
- (0, import_node_path32.join)(
3306
+ (0, import_node_path33.join)(
3288
3307
  baseDir,
3289
3308
  this.getSettablePaths().relativeDirPath,
3290
3309
  this.getSettablePaths().relativeFilePath
@@ -3319,8 +3338,8 @@ var CopilotMcp = class _CopilotMcp extends ToolMcp {
3319
3338
  }
3320
3339
  };
3321
3340
 
3322
- // src/mcp/cursor-mcp.ts
3323
- var import_node_path33 = require("path");
3341
+ // src/features/mcp/cursor-mcp.ts
3342
+ var import_node_path34 = require("path");
3324
3343
  var CursorMcp = class _CursorMcp extends ToolMcp {
3325
3344
  json;
3326
3345
  constructor(params) {
@@ -3341,7 +3360,7 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
3341
3360
  validate = true
3342
3361
  }) {
3343
3362
  const fileContent = await readFileContent(
3344
- (0, import_node_path33.join)(
3363
+ (0, import_node_path34.join)(
3345
3364
  baseDir,
3346
3365
  this.getSettablePaths().relativeDirPath,
3347
3366
  this.getSettablePaths().relativeFilePath
@@ -3387,8 +3406,8 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
3387
3406
  }
3388
3407
  };
3389
3408
 
3390
- // src/mcp/geminicli-mcp.ts
3391
- var import_node_path34 = require("path");
3409
+ // src/features/mcp/geminicli-mcp.ts
3410
+ var import_node_path35 = require("path");
3392
3411
  var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
3393
3412
  json;
3394
3413
  constructor(params) {
@@ -3417,7 +3436,7 @@ var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
3417
3436
  }) {
3418
3437
  const paths = this.getSettablePaths({ global });
3419
3438
  const fileContent = await readOrInitializeFileContent(
3420
- (0, import_node_path34.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3439
+ (0, import_node_path35.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3421
3440
  JSON.stringify({ mcpServers: {} }, null, 2)
3422
3441
  );
3423
3442
  const json = JSON.parse(fileContent);
@@ -3438,7 +3457,7 @@ var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
3438
3457
  }) {
3439
3458
  const paths = this.getSettablePaths({ global });
3440
3459
  const fileContent = await readOrInitializeFileContent(
3441
- (0, import_node_path34.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3460
+ (0, import_node_path35.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3442
3461
  JSON.stringify({ mcpServers: {} }, null, 2)
3443
3462
  );
3444
3463
  const json = JSON.parse(fileContent);
@@ -3461,8 +3480,8 @@ var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
3461
3480
  }
3462
3481
  };
3463
3482
 
3464
- // src/mcp/roo-mcp.ts
3465
- var import_node_path35 = require("path");
3483
+ // src/features/mcp/roo-mcp.ts
3484
+ var import_node_path36 = require("path");
3466
3485
  var RooMcp = class _RooMcp extends ToolMcp {
3467
3486
  json;
3468
3487
  constructor(params) {
@@ -3483,7 +3502,7 @@ var RooMcp = class _RooMcp extends ToolMcp {
3483
3502
  validate = true
3484
3503
  }) {
3485
3504
  const fileContent = await readFileContent(
3486
- (0, import_node_path35.join)(
3505
+ (0, import_node_path36.join)(
3487
3506
  baseDir,
3488
3507
  this.getSettablePaths().relativeDirPath,
3489
3508
  this.getSettablePaths().relativeFilePath
@@ -3519,7 +3538,7 @@ var RooMcp = class _RooMcp extends ToolMcp {
3519
3538
  }
3520
3539
  };
3521
3540
 
3522
- // src/mcp/mcp-processor.ts
3541
+ // src/features/mcp/mcp-processor.ts
3523
3542
  var mcpProcessorToolTargets = [
3524
3543
  "amazonqcli",
3525
3544
  "claudecode",
@@ -3675,7 +3694,7 @@ var McpProcessor = class extends FeatureProcessor {
3675
3694
  (file) => file instanceof RulesyncMcp
3676
3695
  );
3677
3696
  if (!rulesyncMcp) {
3678
- throw new Error(`No .rulesync/mcp.json found.`);
3697
+ throw new Error(`No ${RULESYNC_MCP_RELATIVE_FILE_PATH} found.`);
3679
3698
  }
3680
3699
  const toolMcps = await Promise.all(
3681
3700
  [rulesyncMcp].map(async (rulesyncMcp2) => {
@@ -3765,19 +3784,19 @@ var McpProcessor = class extends FeatureProcessor {
3765
3784
  }
3766
3785
  };
3767
3786
 
3768
- // src/rules/rules-processor.ts
3769
- var import_node_path65 = require("path");
3787
+ // src/features/rules/rules-processor.ts
3788
+ var import_node_path66 = require("path");
3770
3789
  var import_fast_xml_parser = require("fast-xml-parser");
3771
3790
  var import_mini22 = require("zod/mini");
3772
3791
 
3773
- // src/subagents/agentsmd-subagent.ts
3774
- var import_node_path37 = require("path");
3792
+ // src/features/subagents/agentsmd-subagent.ts
3793
+ var import_node_path38 = require("path");
3775
3794
 
3776
- // src/subagents/simulated-subagent.ts
3777
- var import_node_path36 = require("path");
3795
+ // src/features/subagents/simulated-subagent.ts
3796
+ var import_node_path37 = require("path");
3778
3797
  var import_mini14 = require("zod/mini");
3779
3798
 
3780
- // src/subagents/tool-subagent.ts
3799
+ // src/features/subagents/tool-subagent.ts
3781
3800
  var ToolSubagent = class extends ToolFile {
3782
3801
  static getSettablePaths() {
3783
3802
  throw new Error("Please implement this method in the subclass.");
@@ -3809,7 +3828,7 @@ var ToolSubagent = class extends ToolFile {
3809
3828
  }
3810
3829
  };
3811
3830
 
3812
- // src/subagents/simulated-subagent.ts
3831
+ // src/features/subagents/simulated-subagent.ts
3813
3832
  var SimulatedSubagentFrontmatterSchema = import_mini14.z.object({
3814
3833
  name: import_mini14.z.string(),
3815
3834
  description: import_mini14.z.string()
@@ -3822,7 +3841,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3822
3841
  const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
3823
3842
  if (!result.success) {
3824
3843
  throw new Error(
3825
- `Invalid frontmatter in ${(0, import_node_path36.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
3844
+ `Invalid frontmatter in ${(0, import_node_path37.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
3826
3845
  );
3827
3846
  }
3828
3847
  }
@@ -3873,7 +3892,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3873
3892
  return {
3874
3893
  success: false,
3875
3894
  error: new Error(
3876
- `Invalid frontmatter in ${(0, import_node_path36.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
3895
+ `Invalid frontmatter in ${(0, import_node_path37.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
3877
3896
  )
3878
3897
  };
3879
3898
  }
@@ -3883,7 +3902,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3883
3902
  relativeFilePath,
3884
3903
  validate = true
3885
3904
  }) {
3886
- const filePath = (0, import_node_path36.join)(baseDir, this.getSettablePaths().relativeDirPath, relativeFilePath);
3905
+ const filePath = (0, import_node_path37.join)(baseDir, this.getSettablePaths().relativeDirPath, relativeFilePath);
3887
3906
  const fileContent = await readFileContent(filePath);
3888
3907
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
3889
3908
  const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
@@ -3893,7 +3912,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3893
3912
  return {
3894
3913
  baseDir,
3895
3914
  relativeDirPath: this.getSettablePaths().relativeDirPath,
3896
- relativeFilePath: (0, import_node_path36.basename)(relativeFilePath),
3915
+ relativeFilePath: (0, import_node_path37.basename)(relativeFilePath),
3897
3916
  frontmatter: result.data,
3898
3917
  body: content.trim(),
3899
3918
  validate
@@ -3901,11 +3920,11 @@ var SimulatedSubagent = class extends ToolSubagent {
3901
3920
  }
3902
3921
  };
3903
3922
 
3904
- // src/subagents/agentsmd-subagent.ts
3923
+ // src/features/subagents/agentsmd-subagent.ts
3905
3924
  var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
3906
3925
  static getSettablePaths() {
3907
3926
  return {
3908
- relativeDirPath: (0, import_node_path37.join)(".agents", "subagents")
3927
+ relativeDirPath: (0, import_node_path38.join)(".agents", "subagents")
3909
3928
  };
3910
3929
  }
3911
3930
  static async fromFile(params) {
@@ -3924,12 +3943,12 @@ var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
3924
3943
  }
3925
3944
  };
3926
3945
 
3927
- // src/subagents/codexcli-subagent.ts
3928
- var import_node_path38 = require("path");
3946
+ // src/features/subagents/codexcli-subagent.ts
3947
+ var import_node_path39 = require("path");
3929
3948
  var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
3930
3949
  static getSettablePaths() {
3931
3950
  return {
3932
- relativeDirPath: (0, import_node_path38.join)(".codex", "subagents")
3951
+ relativeDirPath: (0, import_node_path39.join)(".codex", "subagents")
3933
3952
  };
3934
3953
  }
3935
3954
  static async fromFile(params) {
@@ -3948,12 +3967,12 @@ var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
3948
3967
  }
3949
3968
  };
3950
3969
 
3951
- // src/subagents/copilot-subagent.ts
3952
- var import_node_path39 = require("path");
3970
+ // src/features/subagents/copilot-subagent.ts
3971
+ var import_node_path40 = require("path");
3953
3972
  var CopilotSubagent = class _CopilotSubagent extends SimulatedSubagent {
3954
3973
  static getSettablePaths() {
3955
3974
  return {
3956
- relativeDirPath: (0, import_node_path39.join)(".github", "subagents")
3975
+ relativeDirPath: (0, import_node_path40.join)(".github", "subagents")
3957
3976
  };
3958
3977
  }
3959
3978
  static async fromFile(params) {
@@ -3972,12 +3991,12 @@ var CopilotSubagent = class _CopilotSubagent extends SimulatedSubagent {
3972
3991
  }
3973
3992
  };
3974
3993
 
3975
- // src/subagents/cursor-subagent.ts
3976
- var import_node_path40 = require("path");
3994
+ // src/features/subagents/cursor-subagent.ts
3995
+ var import_node_path41 = require("path");
3977
3996
  var CursorSubagent = class _CursorSubagent extends SimulatedSubagent {
3978
3997
  static getSettablePaths() {
3979
3998
  return {
3980
- relativeDirPath: (0, import_node_path40.join)(".cursor", "subagents")
3999
+ relativeDirPath: (0, import_node_path41.join)(".cursor", "subagents")
3981
4000
  };
3982
4001
  }
3983
4002
  static async fromFile(params) {
@@ -3996,12 +4015,12 @@ var CursorSubagent = class _CursorSubagent extends SimulatedSubagent {
3996
4015
  }
3997
4016
  };
3998
4017
 
3999
- // src/subagents/geminicli-subagent.ts
4000
- var import_node_path41 = require("path");
4018
+ // src/features/subagents/geminicli-subagent.ts
4019
+ var import_node_path42 = require("path");
4001
4020
  var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
4002
4021
  static getSettablePaths() {
4003
4022
  return {
4004
- relativeDirPath: (0, import_node_path41.join)(".gemini", "subagents")
4023
+ relativeDirPath: (0, import_node_path42.join)(".gemini", "subagents")
4005
4024
  };
4006
4025
  }
4007
4026
  static async fromFile(params) {
@@ -4020,12 +4039,12 @@ var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
4020
4039
  }
4021
4040
  };
4022
4041
 
4023
- // src/subagents/roo-subagent.ts
4024
- var import_node_path42 = require("path");
4042
+ // src/features/subagents/roo-subagent.ts
4043
+ var import_node_path43 = require("path");
4025
4044
  var RooSubagent = class _RooSubagent extends SimulatedSubagent {
4026
4045
  static getSettablePaths() {
4027
4046
  return {
4028
- relativeDirPath: (0, import_node_path42.join)(".roo", "subagents")
4047
+ relativeDirPath: (0, import_node_path43.join)(".roo", "subagents")
4029
4048
  };
4030
4049
  }
4031
4050
  static async fromFile(params) {
@@ -4044,16 +4063,16 @@ var RooSubagent = class _RooSubagent extends SimulatedSubagent {
4044
4063
  }
4045
4064
  };
4046
4065
 
4047
- // src/subagents/subagents-processor.ts
4048
- var import_node_path45 = require("path");
4066
+ // src/features/subagents/subagents-processor.ts
4067
+ var import_node_path46 = require("path");
4049
4068
  var import_mini17 = require("zod/mini");
4050
4069
 
4051
- // src/subagents/claudecode-subagent.ts
4052
- var import_node_path44 = require("path");
4070
+ // src/features/subagents/claudecode-subagent.ts
4071
+ var import_node_path45 = require("path");
4053
4072
  var import_mini16 = require("zod/mini");
4054
4073
 
4055
- // src/subagents/rulesync-subagent.ts
4056
- var import_node_path43 = require("path");
4074
+ // src/features/subagents/rulesync-subagent.ts
4075
+ var import_node_path44 = require("path");
4057
4076
  var import_mini15 = require("zod/mini");
4058
4077
  var RulesyncSubagentModelSchema = import_mini15.z.enum(["opus", "sonnet", "haiku", "inherit"]);
4059
4078
  var RulesyncSubagentFrontmatterSchema = import_mini15.z.object({
@@ -4074,19 +4093,20 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4074
4093
  const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
4075
4094
  if (!result.success) {
4076
4095
  throw new Error(
4077
- `Invalid frontmatter in ${(0, import_node_path43.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
4096
+ `Invalid frontmatter in ${(0, import_node_path44.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
4078
4097
  );
4079
4098
  }
4080
4099
  }
4081
4100
  super({
4082
- ...rest
4101
+ ...rest,
4102
+ fileContent: stringifyFrontmatter(body, frontmatter)
4083
4103
  });
4084
4104
  this.frontmatter = frontmatter;
4085
4105
  this.body = body;
4086
4106
  }
4087
4107
  static getSettablePaths() {
4088
4108
  return {
4089
- relativeDirPath: (0, import_node_path43.join)(".rulesync", "subagents")
4109
+ relativeDirPath: RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH
4090
4110
  };
4091
4111
  }
4092
4112
  getFrontmatter() {
@@ -4106,7 +4126,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4106
4126
  return {
4107
4127
  success: false,
4108
4128
  error: new Error(
4109
- `Invalid frontmatter in ${(0, import_node_path43.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
4129
+ `Invalid frontmatter in ${(0, import_node_path44.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
4110
4130
  )
4111
4131
  };
4112
4132
  }
@@ -4115,26 +4135,25 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4115
4135
  relativeFilePath
4116
4136
  }) {
4117
4137
  const fileContent = await readFileContent(
4118
- (0, import_node_path43.join)(process.cwd(), ".rulesync", "subagents", relativeFilePath)
4138
+ (0, import_node_path44.join)(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, relativeFilePath)
4119
4139
  );
4120
4140
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4121
4141
  const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
4122
4142
  if (!result.success) {
4123
4143
  throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
4124
4144
  }
4125
- const filename = (0, import_node_path43.basename)(relativeFilePath);
4145
+ const filename = (0, import_node_path44.basename)(relativeFilePath);
4126
4146
  return new _RulesyncSubagent({
4127
4147
  baseDir: process.cwd(),
4128
4148
  relativeDirPath: this.getSettablePaths().relativeDirPath,
4129
4149
  relativeFilePath: filename,
4130
4150
  frontmatter: result.data,
4131
- body: content.trim(),
4132
- fileContent
4151
+ body: content.trim()
4133
4152
  });
4134
4153
  }
4135
4154
  };
4136
4155
 
4137
- // src/subagents/claudecode-subagent.ts
4156
+ // src/features/subagents/claudecode-subagent.ts
4138
4157
  var ClaudecodeSubagentFrontmatterSchema = import_mini16.z.object({
4139
4158
  name: import_mini16.z.string(),
4140
4159
  description: import_mini16.z.string(),
@@ -4148,7 +4167,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4148
4167
  const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
4149
4168
  if (!result.success) {
4150
4169
  throw new Error(
4151
- `Invalid frontmatter in ${(0, import_node_path44.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
4170
+ `Invalid frontmatter in ${(0, import_node_path45.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
4152
4171
  );
4153
4172
  }
4154
4173
  }
@@ -4160,7 +4179,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4160
4179
  }
4161
4180
  static getSettablePaths(_options = {}) {
4162
4181
  return {
4163
- relativeDirPath: (0, import_node_path44.join)(".claude", "agents")
4182
+ relativeDirPath: (0, import_node_path45.join)(".claude", "agents")
4164
4183
  };
4165
4184
  }
4166
4185
  getFrontmatter() {
@@ -4180,15 +4199,13 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4180
4199
  }
4181
4200
  }
4182
4201
  };
4183
- const fileContent = stringifyFrontmatter(this.body, rulesyncFrontmatter);
4184
4202
  return new RulesyncSubagent({
4185
4203
  baseDir: ".",
4186
4204
  // RulesyncCommand baseDir is always the project root directory
4187
4205
  frontmatter: rulesyncFrontmatter,
4188
4206
  body: this.body,
4189
- relativeDirPath: (0, import_node_path44.join)(".rulesync", "subagents"),
4207
+ relativeDirPath: RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH,
4190
4208
  relativeFilePath: this.getRelativeFilePath(),
4191
- fileContent,
4192
4209
  validate: true
4193
4210
  });
4194
4211
  }
@@ -4228,7 +4245,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4228
4245
  return {
4229
4246
  success: false,
4230
4247
  error: new Error(
4231
- `Invalid frontmatter in ${(0, import_node_path44.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
4248
+ `Invalid frontmatter in ${(0, import_node_path45.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
4232
4249
  )
4233
4250
  };
4234
4251
  }
@@ -4246,7 +4263,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4246
4263
  global = false
4247
4264
  }) {
4248
4265
  const paths = this.getSettablePaths({ global });
4249
- const filePath = (0, import_node_path44.join)(baseDir, paths.relativeDirPath, relativeFilePath);
4266
+ const filePath = (0, import_node_path45.join)(baseDir, paths.relativeDirPath, relativeFilePath);
4250
4267
  const fileContent = await readFileContent(filePath);
4251
4268
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4252
4269
  const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
@@ -4265,7 +4282,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4265
4282
  }
4266
4283
  };
4267
4284
 
4268
- // src/subagents/subagents-processor.ts
4285
+ // src/features/subagents/subagents-processor.ts
4269
4286
  var subagentsProcessorToolTargets = [
4270
4287
  "agentsmd",
4271
4288
  "claudecode",
@@ -4400,7 +4417,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
4400
4417
  * Load and parse rulesync subagent files from .rulesync/subagents/ directory
4401
4418
  */
4402
4419
  async loadRulesyncFiles() {
4403
- const subagentsDir = (0, import_node_path45.join)(this.baseDir, RulesyncSubagent.getSettablePaths().relativeDirPath);
4420
+ const subagentsDir = (0, import_node_path46.join)(this.baseDir, RulesyncSubagent.getSettablePaths().relativeDirPath);
4404
4421
  const dirExists = await directoryExists(subagentsDir);
4405
4422
  if (!dirExists) {
4406
4423
  logger.debug(`Rulesync subagents directory not found: ${subagentsDir}`);
@@ -4415,7 +4432,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
4415
4432
  logger.info(`Found ${mdFiles.length} subagent files in ${subagentsDir}`);
4416
4433
  const rulesyncSubagents = [];
4417
4434
  for (const mdFile of mdFiles) {
4418
- const filepath = (0, import_node_path45.join)(subagentsDir, mdFile);
4435
+ const filepath = (0, import_node_path46.join)(subagentsDir, mdFile);
4419
4436
  try {
4420
4437
  const rulesyncSubagent = await RulesyncSubagent.fromFile({
4421
4438
  relativeFilePath: mdFile,
@@ -4534,8 +4551,8 @@ var SubagentsProcessor = class extends FeatureProcessor {
4534
4551
  relativeDirPath,
4535
4552
  fromFile
4536
4553
  }) {
4537
- const paths = await findFilesByGlobs((0, import_node_path45.join)(this.baseDir, relativeDirPath, "*.md"));
4538
- const subagents = (await Promise.allSettled(paths.map((path2) => fromFile((0, import_node_path45.basename)(path2))))).filter((r) => r.status === "fulfilled").map((r) => r.value);
4554
+ const paths = await findFilesByGlobs((0, import_node_path46.join)(this.baseDir, relativeDirPath, "*.md"));
4555
+ const subagents = (await Promise.allSettled(paths.map((path2) => fromFile((0, import_node_path46.basename)(path2))))).filter((r) => r.status === "fulfilled").map((r) => r.value);
4539
4556
  logger.info(`Successfully loaded ${subagents.length} ${relativeDirPath} subagents`);
4540
4557
  return subagents;
4541
4558
  }
@@ -4561,14 +4578,14 @@ var SubagentsProcessor = class extends FeatureProcessor {
4561
4578
  }
4562
4579
  };
4563
4580
 
4564
- // src/rules/agentsmd-rule.ts
4581
+ // src/features/rules/agentsmd-rule.ts
4582
+ var import_node_path49 = require("path");
4583
+
4584
+ // src/features/rules/tool-rule.ts
4565
4585
  var import_node_path48 = require("path");
4566
4586
 
4567
- // src/rules/tool-rule.ts
4587
+ // src/features/rules/rulesync-rule.ts
4568
4588
  var import_node_path47 = require("path");
4569
-
4570
- // src/rules/rulesync-rule.ts
4571
- var import_node_path46 = require("path");
4572
4589
  var import_mini18 = require("zod/mini");
4573
4590
  var RulesyncRuleFrontmatterSchema = import_mini18.z.object({
4574
4591
  root: import_mini18.z.optional(import_mini18.z.optional(import_mini18.z.boolean())),
@@ -4597,7 +4614,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4597
4614
  const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
4598
4615
  if (!result.success) {
4599
4616
  throw new Error(
4600
- `Invalid frontmatter in ${(0, import_node_path46.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
4617
+ `Invalid frontmatter in ${(0, import_node_path47.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
4601
4618
  );
4602
4619
  }
4603
4620
  }
@@ -4611,10 +4628,10 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4611
4628
  static getSettablePaths() {
4612
4629
  return {
4613
4630
  recommended: {
4614
- relativeDirPath: (0, import_node_path46.join)(".rulesync", "rules")
4631
+ relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH
4615
4632
  },
4616
4633
  legacy: {
4617
- relativeDirPath: ".rulesync"
4634
+ relativeDirPath: RULESYNC_RELATIVE_DIR_PATH
4618
4635
  }
4619
4636
  };
4620
4637
  }
@@ -4632,7 +4649,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4632
4649
  return {
4633
4650
  success: false,
4634
4651
  error: new Error(
4635
- `Invalid frontmatter in ${(0, import_node_path46.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
4652
+ `Invalid frontmatter in ${(0, import_node_path47.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
4636
4653
  )
4637
4654
  };
4638
4655
  }
@@ -4641,12 +4658,12 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4641
4658
  relativeFilePath,
4642
4659
  validate = true
4643
4660
  }) {
4644
- const legacyPath = (0, import_node_path46.join)(
4661
+ const legacyPath = (0, import_node_path47.join)(
4645
4662
  process.cwd(),
4646
4663
  this.getSettablePaths().legacy.relativeDirPath,
4647
4664
  relativeFilePath
4648
4665
  );
4649
- const recommendedPath = (0, import_node_path46.join)(
4666
+ const recommendedPath = (0, import_node_path47.join)(
4650
4667
  this.getSettablePaths().recommended.relativeDirPath,
4651
4668
  relativeFilePath
4652
4669
  );
@@ -4665,7 +4682,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4665
4682
  agentsmd: result.data.agentsmd,
4666
4683
  cursor: result.data.cursor
4667
4684
  };
4668
- const filename = (0, import_node_path46.basename)(legacyPath);
4685
+ const filename = (0, import_node_path47.basename)(legacyPath);
4669
4686
  return new _RulesyncRule({
4670
4687
  baseDir: process.cwd(),
4671
4688
  relativeDirPath: this.getSettablePaths().recommended.relativeDirPath,
@@ -4679,7 +4696,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4679
4696
  relativeFilePath,
4680
4697
  validate = true
4681
4698
  }) {
4682
- const filePath = (0, import_node_path46.join)(
4699
+ const filePath = (0, import_node_path47.join)(
4683
4700
  process.cwd(),
4684
4701
  this.getSettablePaths().recommended.relativeDirPath,
4685
4702
  relativeFilePath
@@ -4698,7 +4715,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4698
4715
  agentsmd: result.data.agentsmd,
4699
4716
  cursor: result.data.cursor
4700
4717
  };
4701
- const filename = (0, import_node_path46.basename)(filePath);
4718
+ const filename = (0, import_node_path47.basename)(filePath);
4702
4719
  return new _RulesyncRule({
4703
4720
  baseDir: process.cwd(),
4704
4721
  relativeDirPath: this.getSettablePaths().recommended.relativeDirPath,
@@ -4713,7 +4730,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4713
4730
  }
4714
4731
  };
4715
4732
 
4716
- // src/rules/tool-rule.ts
4733
+ // src/features/rules/tool-rule.ts
4717
4734
  var ToolRule = class extends ToolFile {
4718
4735
  root;
4719
4736
  description;
@@ -4773,7 +4790,7 @@ var ToolRule = class extends ToolFile {
4773
4790
  rulesyncRule,
4774
4791
  validate = true,
4775
4792
  rootPath = { relativeDirPath: ".", relativeFilePath: "AGENTS.md" },
4776
- nonRootPath = { relativeDirPath: (0, import_node_path47.join)(".agents", "memories") }
4793
+ nonRootPath = { relativeDirPath: (0, import_node_path48.join)(".agents", "memories") }
4777
4794
  }) {
4778
4795
  const params = this.buildToolRuleParamsDefault({
4779
4796
  baseDir,
@@ -4784,17 +4801,16 @@ var ToolRule = class extends ToolFile {
4784
4801
  });
4785
4802
  const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
4786
4803
  if (!rulesyncFrontmatter.root && rulesyncFrontmatter.agentsmd?.subprojectPath) {
4787
- params.relativeDirPath = (0, import_node_path47.join)(rulesyncFrontmatter.agentsmd.subprojectPath);
4804
+ params.relativeDirPath = (0, import_node_path48.join)(rulesyncFrontmatter.agentsmd.subprojectPath);
4788
4805
  params.relativeFilePath = "AGENTS.md";
4789
4806
  }
4790
4807
  return params;
4791
4808
  }
4792
4809
  toRulesyncRuleDefault() {
4793
4810
  return new RulesyncRule({
4794
- baseDir: ".",
4795
- // RulesyncRule baseDir is always the project root directory
4796
- relativeDirPath: (0, import_node_path47.join)(".rulesync", "rules"),
4797
- relativeFilePath: this.getRelativeFilePath(),
4811
+ baseDir: process.cwd(),
4812
+ relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
4813
+ relativeFilePath: this.isRoot() ? RULESYNC_OVERVIEW_FILE_NAME : this.getRelativeFilePath(),
4798
4814
  frontmatter: {
4799
4815
  root: this.isRoot(),
4800
4816
  targets: ["*"],
@@ -4834,7 +4850,7 @@ var ToolRule = class extends ToolFile {
4834
4850
  }
4835
4851
  };
4836
4852
 
4837
- // src/rules/agentsmd-rule.ts
4853
+ // src/features/rules/agentsmd-rule.ts
4838
4854
  var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4839
4855
  constructor({ fileContent, root, ...rest }) {
4840
4856
  super({
@@ -4850,7 +4866,7 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4850
4866
  relativeFilePath: "AGENTS.md"
4851
4867
  },
4852
4868
  nonRoot: {
4853
- relativeDirPath: (0, import_node_path48.join)(".agents", "memories")
4869
+ relativeDirPath: (0, import_node_path49.join)(".agents", "memories")
4854
4870
  }
4855
4871
  };
4856
4872
  }
@@ -4860,8 +4876,8 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4860
4876
  validate = true
4861
4877
  }) {
4862
4878
  const isRoot = relativeFilePath === "AGENTS.md";
4863
- const relativePath = isRoot ? "AGENTS.md" : (0, import_node_path48.join)(".agents", "memories", relativeFilePath);
4864
- const fileContent = await readFileContent((0, import_node_path48.join)(baseDir, relativePath));
4879
+ const relativePath = isRoot ? "AGENTS.md" : (0, import_node_path49.join)(".agents", "memories", relativeFilePath);
4880
+ const fileContent = await readFileContent((0, import_node_path49.join)(baseDir, relativePath));
4865
4881
  return new _AgentsMdRule({
4866
4882
  baseDir,
4867
4883
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -4900,13 +4916,13 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4900
4916
  }
4901
4917
  };
4902
4918
 
4903
- // src/rules/amazonqcli-rule.ts
4904
- var import_node_path49 = require("path");
4919
+ // src/features/rules/amazonqcli-rule.ts
4920
+ var import_node_path50 = require("path");
4905
4921
  var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4906
4922
  static getSettablePaths() {
4907
4923
  return {
4908
4924
  nonRoot: {
4909
- relativeDirPath: (0, import_node_path49.join)(".amazonq", "rules")
4925
+ relativeDirPath: (0, import_node_path50.join)(".amazonq", "rules")
4910
4926
  }
4911
4927
  };
4912
4928
  }
@@ -4916,7 +4932,7 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4916
4932
  validate = true
4917
4933
  }) {
4918
4934
  const fileContent = await readFileContent(
4919
- (0, import_node_path49.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4935
+ (0, import_node_path50.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4920
4936
  );
4921
4937
  return new _AmazonQCliRule({
4922
4938
  baseDir,
@@ -4955,8 +4971,8 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4955
4971
  }
4956
4972
  };
4957
4973
 
4958
- // src/rules/augmentcode-legacy-rule.ts
4959
- var import_node_path50 = require("path");
4974
+ // src/features/rules/augmentcode-legacy-rule.ts
4975
+ var import_node_path51 = require("path");
4960
4976
  var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
4961
4977
  toRulesyncRule() {
4962
4978
  const rulesyncFrontmatter = {
@@ -4970,7 +4986,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
4970
4986
  // RulesyncRule baseDir is always the project root directory
4971
4987
  frontmatter: rulesyncFrontmatter,
4972
4988
  body: this.getFileContent(),
4973
- relativeDirPath: (0, import_node_path50.join)(".rulesync", "rules"),
4989
+ relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
4974
4990
  relativeFilePath: this.getRelativeFilePath(),
4975
4991
  validate: true
4976
4992
  });
@@ -4982,7 +4998,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
4982
4998
  relativeFilePath: ".augment-guidelines"
4983
4999
  },
4984
5000
  nonRoot: {
4985
- relativeDirPath: (0, import_node_path50.join)(".augment", "rules")
5001
+ relativeDirPath: (0, import_node_path51.join)(".augment", "rules")
4986
5002
  }
4987
5003
  };
4988
5004
  }
@@ -5017,8 +5033,8 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
5017
5033
  }) {
5018
5034
  const settablePaths = this.getSettablePaths();
5019
5035
  const isRoot = relativeFilePath === settablePaths.root.relativeFilePath;
5020
- const relativePath = isRoot ? settablePaths.root.relativeFilePath : (0, import_node_path50.join)(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
5021
- const fileContent = await readFileContent((0, import_node_path50.join)(baseDir, relativePath));
5036
+ const relativePath = isRoot ? settablePaths.root.relativeFilePath : (0, import_node_path51.join)(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
5037
+ const fileContent = await readFileContent((0, import_node_path51.join)(baseDir, relativePath));
5022
5038
  return new _AugmentcodeLegacyRule({
5023
5039
  baseDir,
5024
5040
  relativeDirPath: isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath,
@@ -5030,8 +5046,8 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
5030
5046
  }
5031
5047
  };
5032
5048
 
5033
- // src/rules/augmentcode-rule.ts
5034
- var import_node_path51 = require("path");
5049
+ // src/features/rules/augmentcode-rule.ts
5050
+ var import_node_path52 = require("path");
5035
5051
  var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5036
5052
  toRulesyncRule() {
5037
5053
  return this.toRulesyncRuleDefault();
@@ -5039,7 +5055,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5039
5055
  static getSettablePaths() {
5040
5056
  return {
5041
5057
  nonRoot: {
5042
- relativeDirPath: (0, import_node_path51.join)(".augment", "rules")
5058
+ relativeDirPath: (0, import_node_path52.join)(".augment", "rules")
5043
5059
  }
5044
5060
  };
5045
5061
  }
@@ -5063,7 +5079,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5063
5079
  validate = true
5064
5080
  }) {
5065
5081
  const fileContent = await readFileContent(
5066
- (0, import_node_path51.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5082
+ (0, import_node_path52.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5067
5083
  );
5068
5084
  const { body: content } = parseFrontmatter(fileContent);
5069
5085
  return new _AugmentcodeRule({
@@ -5085,8 +5101,8 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5085
5101
  }
5086
5102
  };
5087
5103
 
5088
- // src/rules/claudecode-rule.ts
5089
- var import_node_path52 = require("path");
5104
+ // src/features/rules/claudecode-rule.ts
5105
+ var import_node_path53 = require("path");
5090
5106
  var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5091
5107
  static getSettablePaths({
5092
5108
  global
@@ -5105,7 +5121,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5105
5121
  relativeFilePath: "CLAUDE.md"
5106
5122
  },
5107
5123
  nonRoot: {
5108
- relativeDirPath: (0, import_node_path52.join)(".claude", "memories")
5124
+ relativeDirPath: (0, import_node_path53.join)(".claude", "memories")
5109
5125
  }
5110
5126
  };
5111
5127
  }
@@ -5120,7 +5136,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5120
5136
  if (isRoot) {
5121
5137
  const relativePath2 = paths.root.relativeFilePath;
5122
5138
  const fileContent2 = await readFileContent(
5123
- (0, import_node_path52.join)(baseDir, paths.root.relativeDirPath, relativePath2)
5139
+ (0, import_node_path53.join)(baseDir, paths.root.relativeDirPath, relativePath2)
5124
5140
  );
5125
5141
  return new _ClaudecodeRule({
5126
5142
  baseDir,
@@ -5134,8 +5150,8 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5134
5150
  if (!paths.nonRoot) {
5135
5151
  throw new Error("nonRoot path is not set");
5136
5152
  }
5137
- const relativePath = (0, import_node_path52.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
5138
- const fileContent = await readFileContent((0, import_node_path52.join)(baseDir, relativePath));
5153
+ const relativePath = (0, import_node_path53.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
5154
+ const fileContent = await readFileContent((0, import_node_path53.join)(baseDir, relativePath));
5139
5155
  return new _ClaudecodeRule({
5140
5156
  baseDir,
5141
5157
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -5176,8 +5192,8 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5176
5192
  }
5177
5193
  };
5178
5194
 
5179
- // src/rules/cline-rule.ts
5180
- var import_node_path53 = require("path");
5195
+ // src/features/rules/cline-rule.ts
5196
+ var import_node_path54 = require("path");
5181
5197
  var import_mini19 = require("zod/mini");
5182
5198
  var ClineRuleFrontmatterSchema = import_mini19.z.object({
5183
5199
  description: import_mini19.z.string()
@@ -5222,7 +5238,7 @@ var ClineRule = class _ClineRule extends ToolRule {
5222
5238
  validate = true
5223
5239
  }) {
5224
5240
  const fileContent = await readFileContent(
5225
- (0, import_node_path53.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5241
+ (0, import_node_path54.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5226
5242
  );
5227
5243
  return new _ClineRule({
5228
5244
  baseDir,
@@ -5234,8 +5250,8 @@ var ClineRule = class _ClineRule extends ToolRule {
5234
5250
  }
5235
5251
  };
5236
5252
 
5237
- // src/rules/codexcli-rule.ts
5238
- var import_node_path54 = require("path");
5253
+ // src/features/rules/codexcli-rule.ts
5254
+ var import_node_path55 = require("path");
5239
5255
  var CodexcliRule = class _CodexcliRule extends ToolRule {
5240
5256
  static getSettablePaths({
5241
5257
  global
@@ -5254,7 +5270,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
5254
5270
  relativeFilePath: "AGENTS.md"
5255
5271
  },
5256
5272
  nonRoot: {
5257
- relativeDirPath: (0, import_node_path54.join)(".codex", "memories")
5273
+ relativeDirPath: (0, import_node_path55.join)(".codex", "memories")
5258
5274
  }
5259
5275
  };
5260
5276
  }
@@ -5269,7 +5285,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
5269
5285
  if (isRoot) {
5270
5286
  const relativePath2 = paths.root.relativeFilePath;
5271
5287
  const fileContent2 = await readFileContent(
5272
- (0, import_node_path54.join)(baseDir, paths.root.relativeDirPath, relativePath2)
5288
+ (0, import_node_path55.join)(baseDir, paths.root.relativeDirPath, relativePath2)
5273
5289
  );
5274
5290
  return new _CodexcliRule({
5275
5291
  baseDir,
@@ -5283,8 +5299,8 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
5283
5299
  if (!paths.nonRoot) {
5284
5300
  throw new Error("nonRoot path is not set");
5285
5301
  }
5286
- const relativePath = (0, import_node_path54.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
5287
- const fileContent = await readFileContent((0, import_node_path54.join)(baseDir, relativePath));
5302
+ const relativePath = (0, import_node_path55.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
5303
+ const fileContent = await readFileContent((0, import_node_path55.join)(baseDir, relativePath));
5288
5304
  return new _CodexcliRule({
5289
5305
  baseDir,
5290
5306
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -5325,8 +5341,8 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
5325
5341
  }
5326
5342
  };
5327
5343
 
5328
- // src/rules/copilot-rule.ts
5329
- var import_node_path55 = require("path");
5344
+ // src/features/rules/copilot-rule.ts
5345
+ var import_node_path56 = require("path");
5330
5346
  var import_mini20 = require("zod/mini");
5331
5347
  var CopilotRuleFrontmatterSchema = import_mini20.z.object({
5332
5348
  description: import_mini20.z.optional(import_mini20.z.string()),
@@ -5342,7 +5358,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5342
5358
  relativeFilePath: "copilot-instructions.md"
5343
5359
  },
5344
5360
  nonRoot: {
5345
- relativeDirPath: (0, import_node_path55.join)(".github", "instructions")
5361
+ relativeDirPath: (0, import_node_path56.join)(".github", "instructions")
5346
5362
  }
5347
5363
  };
5348
5364
  }
@@ -5351,7 +5367,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5351
5367
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
5352
5368
  if (!result.success) {
5353
5369
  throw new Error(
5354
- `Invalid frontmatter in ${(0, import_node_path55.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5370
+ `Invalid frontmatter in ${(0, import_node_path56.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5355
5371
  );
5356
5372
  }
5357
5373
  }
@@ -5382,7 +5398,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5382
5398
  baseDir: this.getBaseDir(),
5383
5399
  frontmatter: rulesyncFrontmatter,
5384
5400
  body: this.body,
5385
- relativeDirPath: (0, import_node_path55.join)(".rulesync", "rules"),
5401
+ relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
5386
5402
  relativeFilePath,
5387
5403
  validate: true
5388
5404
  });
@@ -5429,11 +5445,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5429
5445
  validate = true
5430
5446
  }) {
5431
5447
  const isRoot = relativeFilePath === "copilot-instructions.md";
5432
- const relativePath = isRoot ? (0, import_node_path55.join)(
5448
+ const relativePath = isRoot ? (0, import_node_path56.join)(
5433
5449
  this.getSettablePaths().root.relativeDirPath,
5434
5450
  this.getSettablePaths().root.relativeFilePath
5435
- ) : (0, import_node_path55.join)(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
5436
- const fileContent = await readFileContent((0, import_node_path55.join)(baseDir, relativePath));
5451
+ ) : (0, import_node_path56.join)(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
5452
+ const fileContent = await readFileContent((0, import_node_path56.join)(baseDir, relativePath));
5437
5453
  if (isRoot) {
5438
5454
  return new _CopilotRule({
5439
5455
  baseDir,
@@ -5452,7 +5468,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5452
5468
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
5453
5469
  if (!result.success) {
5454
5470
  throw new Error(
5455
- `Invalid frontmatter in ${(0, import_node_path55.join)(baseDir, relativeFilePath)}: ${formatError(result.error)}`
5471
+ `Invalid frontmatter in ${(0, import_node_path56.join)(baseDir, relativeFilePath)}: ${formatError(result.error)}`
5456
5472
  );
5457
5473
  }
5458
5474
  return new _CopilotRule({
@@ -5476,7 +5492,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5476
5492
  return {
5477
5493
  success: false,
5478
5494
  error: new Error(
5479
- `Invalid frontmatter in ${(0, import_node_path55.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5495
+ `Invalid frontmatter in ${(0, import_node_path56.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5480
5496
  )
5481
5497
  };
5482
5498
  }
@@ -5495,8 +5511,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5495
5511
  }
5496
5512
  };
5497
5513
 
5498
- // src/rules/cursor-rule.ts
5499
- var import_node_path56 = require("path");
5514
+ // src/features/rules/cursor-rule.ts
5515
+ var import_node_path57 = require("path");
5500
5516
  var import_mini21 = require("zod/mini");
5501
5517
  var CursorRuleFrontmatterSchema = import_mini21.z.object({
5502
5518
  description: import_mini21.z.optional(import_mini21.z.string()),
@@ -5509,7 +5525,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5509
5525
  static getSettablePaths() {
5510
5526
  return {
5511
5527
  nonRoot: {
5512
- relativeDirPath: (0, import_node_path56.join)(".cursor", "rules")
5528
+ relativeDirPath: (0, import_node_path57.join)(".cursor", "rules")
5513
5529
  }
5514
5530
  };
5515
5531
  }
@@ -5518,7 +5534,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5518
5534
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
5519
5535
  if (!result.success) {
5520
5536
  throw new Error(
5521
- `Invalid frontmatter in ${(0, import_node_path56.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5537
+ `Invalid frontmatter in ${(0, import_node_path57.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5522
5538
  );
5523
5539
  }
5524
5540
  }
@@ -5590,7 +5606,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5590
5606
  return new RulesyncRule({
5591
5607
  frontmatter: rulesyncFrontmatter,
5592
5608
  body: this.body,
5593
- relativeDirPath: (0, import_node_path56.join)(".rulesync", "rules"),
5609
+ relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
5594
5610
  relativeFilePath: this.relativeFilePath.replace(/\.mdc$/, ".md"),
5595
5611
  validate: true
5596
5612
  });
@@ -5635,19 +5651,19 @@ var CursorRule = class _CursorRule extends ToolRule {
5635
5651
  validate = true
5636
5652
  }) {
5637
5653
  const fileContent = await readFileContent(
5638
- (0, import_node_path56.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5654
+ (0, import_node_path57.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5639
5655
  );
5640
5656
  const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
5641
5657
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
5642
5658
  if (!result.success) {
5643
5659
  throw new Error(
5644
- `Invalid frontmatter in ${(0, import_node_path56.join)(baseDir, relativeFilePath)}: ${formatError(result.error)}`
5660
+ `Invalid frontmatter in ${(0, import_node_path57.join)(baseDir, relativeFilePath)}: ${formatError(result.error)}`
5645
5661
  );
5646
5662
  }
5647
5663
  return new _CursorRule({
5648
5664
  baseDir,
5649
5665
  relativeDirPath: this.getSettablePaths().nonRoot.relativeDirPath,
5650
- relativeFilePath: (0, import_node_path56.basename)(relativeFilePath),
5666
+ relativeFilePath: (0, import_node_path57.basename)(relativeFilePath),
5651
5667
  frontmatter: result.data,
5652
5668
  body: content.trim(),
5653
5669
  validate
@@ -5664,7 +5680,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5664
5680
  return {
5665
5681
  success: false,
5666
5682
  error: new Error(
5667
- `Invalid frontmatter in ${(0, import_node_path56.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5683
+ `Invalid frontmatter in ${(0, import_node_path57.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5668
5684
  )
5669
5685
  };
5670
5686
  }
@@ -5683,8 +5699,8 @@ var CursorRule = class _CursorRule extends ToolRule {
5683
5699
  }
5684
5700
  };
5685
5701
 
5686
- // src/rules/geminicli-rule.ts
5687
- var import_node_path57 = require("path");
5702
+ // src/features/rules/geminicli-rule.ts
5703
+ var import_node_path58 = require("path");
5688
5704
  var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5689
5705
  static getSettablePaths({
5690
5706
  global
@@ -5703,7 +5719,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5703
5719
  relativeFilePath: "GEMINI.md"
5704
5720
  },
5705
5721
  nonRoot: {
5706
- relativeDirPath: (0, import_node_path57.join)(".gemini", "memories")
5722
+ relativeDirPath: (0, import_node_path58.join)(".gemini", "memories")
5707
5723
  }
5708
5724
  };
5709
5725
  }
@@ -5718,7 +5734,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5718
5734
  if (isRoot) {
5719
5735
  const relativePath2 = paths.root.relativeFilePath;
5720
5736
  const fileContent2 = await readFileContent(
5721
- (0, import_node_path57.join)(baseDir, paths.root.relativeDirPath, relativePath2)
5737
+ (0, import_node_path58.join)(baseDir, paths.root.relativeDirPath, relativePath2)
5722
5738
  );
5723
5739
  return new _GeminiCliRule({
5724
5740
  baseDir,
@@ -5732,8 +5748,8 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5732
5748
  if (!paths.nonRoot) {
5733
5749
  throw new Error("nonRoot path is not set");
5734
5750
  }
5735
- const relativePath = (0, import_node_path57.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
5736
- const fileContent = await readFileContent((0, import_node_path57.join)(baseDir, relativePath));
5751
+ const relativePath = (0, import_node_path58.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
5752
+ const fileContent = await readFileContent((0, import_node_path58.join)(baseDir, relativePath));
5737
5753
  return new _GeminiCliRule({
5738
5754
  baseDir,
5739
5755
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -5774,8 +5790,8 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5774
5790
  }
5775
5791
  };
5776
5792
 
5777
- // src/rules/junie-rule.ts
5778
- var import_node_path58 = require("path");
5793
+ // src/features/rules/junie-rule.ts
5794
+ var import_node_path59 = require("path");
5779
5795
  var JunieRule = class _JunieRule extends ToolRule {
5780
5796
  static getSettablePaths() {
5781
5797
  return {
@@ -5784,7 +5800,7 @@ var JunieRule = class _JunieRule extends ToolRule {
5784
5800
  relativeFilePath: "guidelines.md"
5785
5801
  },
5786
5802
  nonRoot: {
5787
- relativeDirPath: (0, import_node_path58.join)(".junie", "memories")
5803
+ relativeDirPath: (0, import_node_path59.join)(".junie", "memories")
5788
5804
  }
5789
5805
  };
5790
5806
  }
@@ -5794,8 +5810,8 @@ var JunieRule = class _JunieRule extends ToolRule {
5794
5810
  validate = true
5795
5811
  }) {
5796
5812
  const isRoot = relativeFilePath === "guidelines.md";
5797
- const relativePath = isRoot ? "guidelines.md" : (0, import_node_path58.join)(".junie", "memories", relativeFilePath);
5798
- const fileContent = await readFileContent((0, import_node_path58.join)(baseDir, relativePath));
5813
+ const relativePath = isRoot ? "guidelines.md" : (0, import_node_path59.join)(".junie", "memories", relativeFilePath);
5814
+ const fileContent = await readFileContent((0, import_node_path59.join)(baseDir, relativePath));
5799
5815
  return new _JunieRule({
5800
5816
  baseDir,
5801
5817
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -5834,13 +5850,13 @@ var JunieRule = class _JunieRule extends ToolRule {
5834
5850
  }
5835
5851
  };
5836
5852
 
5837
- // src/rules/kiro-rule.ts
5838
- var import_node_path59 = require("path");
5853
+ // src/features/rules/kiro-rule.ts
5854
+ var import_node_path60 = require("path");
5839
5855
  var KiroRule = class _KiroRule extends ToolRule {
5840
5856
  static getSettablePaths() {
5841
5857
  return {
5842
5858
  nonRoot: {
5843
- relativeDirPath: (0, import_node_path59.join)(".kiro", "steering")
5859
+ relativeDirPath: (0, import_node_path60.join)(".kiro", "steering")
5844
5860
  }
5845
5861
  };
5846
5862
  }
@@ -5850,7 +5866,7 @@ var KiroRule = class _KiroRule extends ToolRule {
5850
5866
  validate = true
5851
5867
  }) {
5852
5868
  const fileContent = await readFileContent(
5853
- (0, import_node_path59.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5869
+ (0, import_node_path60.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5854
5870
  );
5855
5871
  return new _KiroRule({
5856
5872
  baseDir,
@@ -5889,8 +5905,8 @@ var KiroRule = class _KiroRule extends ToolRule {
5889
5905
  }
5890
5906
  };
5891
5907
 
5892
- // src/rules/opencode-rule.ts
5893
- var import_node_path60 = require("path");
5908
+ // src/features/rules/opencode-rule.ts
5909
+ var import_node_path61 = require("path");
5894
5910
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5895
5911
  static getSettablePaths() {
5896
5912
  return {
@@ -5899,7 +5915,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5899
5915
  relativeFilePath: "AGENTS.md"
5900
5916
  },
5901
5917
  nonRoot: {
5902
- relativeDirPath: (0, import_node_path60.join)(".opencode", "memories")
5918
+ relativeDirPath: (0, import_node_path61.join)(".opencode", "memories")
5903
5919
  }
5904
5920
  };
5905
5921
  }
@@ -5909,8 +5925,8 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5909
5925
  validate = true
5910
5926
  }) {
5911
5927
  const isRoot = relativeFilePath === "AGENTS.md";
5912
- const relativePath = isRoot ? "AGENTS.md" : (0, import_node_path60.join)(".opencode", "memories", relativeFilePath);
5913
- const fileContent = await readFileContent((0, import_node_path60.join)(baseDir, relativePath));
5928
+ const relativePath = isRoot ? "AGENTS.md" : (0, import_node_path61.join)(".opencode", "memories", relativeFilePath);
5929
+ const fileContent = await readFileContent((0, import_node_path61.join)(baseDir, relativePath));
5914
5930
  return new _OpenCodeRule({
5915
5931
  baseDir,
5916
5932
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -5949,8 +5965,8 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5949
5965
  }
5950
5966
  };
5951
5967
 
5952
- // src/rules/qwencode-rule.ts
5953
- var import_node_path61 = require("path");
5968
+ // src/features/rules/qwencode-rule.ts
5969
+ var import_node_path62 = require("path");
5954
5970
  var QwencodeRule = class _QwencodeRule extends ToolRule {
5955
5971
  static getSettablePaths() {
5956
5972
  return {
@@ -5959,7 +5975,7 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
5959
5975
  relativeFilePath: "QWEN.md"
5960
5976
  },
5961
5977
  nonRoot: {
5962
- relativeDirPath: (0, import_node_path61.join)(".qwen", "memories")
5978
+ relativeDirPath: (0, import_node_path62.join)(".qwen", "memories")
5963
5979
  }
5964
5980
  };
5965
5981
  }
@@ -5969,8 +5985,8 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
5969
5985
  validate = true
5970
5986
  }) {
5971
5987
  const isRoot = relativeFilePath === "QWEN.md";
5972
- const relativePath = isRoot ? "QWEN.md" : (0, import_node_path61.join)(".qwen", "memories", relativeFilePath);
5973
- const fileContent = await readFileContent((0, import_node_path61.join)(baseDir, relativePath));
5988
+ const relativePath = isRoot ? "QWEN.md" : (0, import_node_path62.join)(".qwen", "memories", relativeFilePath);
5989
+ const fileContent = await readFileContent((0, import_node_path62.join)(baseDir, relativePath));
5974
5990
  return new _QwencodeRule({
5975
5991
  baseDir,
5976
5992
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -6006,13 +6022,13 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
6006
6022
  }
6007
6023
  };
6008
6024
 
6009
- // src/rules/roo-rule.ts
6010
- var import_node_path62 = require("path");
6025
+ // src/features/rules/roo-rule.ts
6026
+ var import_node_path63 = require("path");
6011
6027
  var RooRule = class _RooRule extends ToolRule {
6012
6028
  static getSettablePaths() {
6013
6029
  return {
6014
6030
  nonRoot: {
6015
- relativeDirPath: (0, import_node_path62.join)(".roo", "rules")
6031
+ relativeDirPath: (0, import_node_path63.join)(".roo", "rules")
6016
6032
  }
6017
6033
  };
6018
6034
  }
@@ -6022,7 +6038,7 @@ var RooRule = class _RooRule extends ToolRule {
6022
6038
  validate = true
6023
6039
  }) {
6024
6040
  const fileContent = await readFileContent(
6025
- (0, import_node_path62.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6041
+ (0, import_node_path63.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6026
6042
  );
6027
6043
  return new _RooRule({
6028
6044
  baseDir,
@@ -6076,8 +6092,8 @@ var RooRule = class _RooRule extends ToolRule {
6076
6092
  }
6077
6093
  };
6078
6094
 
6079
- // src/rules/warp-rule.ts
6080
- var import_node_path63 = require("path");
6095
+ // src/features/rules/warp-rule.ts
6096
+ var import_node_path64 = require("path");
6081
6097
  var WarpRule = class _WarpRule extends ToolRule {
6082
6098
  constructor({ fileContent, root, ...rest }) {
6083
6099
  super({
@@ -6093,7 +6109,7 @@ var WarpRule = class _WarpRule extends ToolRule {
6093
6109
  relativeFilePath: "WARP.md"
6094
6110
  },
6095
6111
  nonRoot: {
6096
- relativeDirPath: (0, import_node_path63.join)(".warp", "memories")
6112
+ relativeDirPath: (0, import_node_path64.join)(".warp", "memories")
6097
6113
  }
6098
6114
  };
6099
6115
  }
@@ -6103,8 +6119,8 @@ var WarpRule = class _WarpRule extends ToolRule {
6103
6119
  validate = true
6104
6120
  }) {
6105
6121
  const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
6106
- const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : (0, import_node_path63.join)(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
6107
- const fileContent = await readFileContent((0, import_node_path63.join)(baseDir, relativePath));
6122
+ const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : (0, import_node_path64.join)(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
6123
+ const fileContent = await readFileContent((0, import_node_path64.join)(baseDir, relativePath));
6108
6124
  return new _WarpRule({
6109
6125
  baseDir,
6110
6126
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : ".warp",
@@ -6143,13 +6159,13 @@ var WarpRule = class _WarpRule extends ToolRule {
6143
6159
  }
6144
6160
  };
6145
6161
 
6146
- // src/rules/windsurf-rule.ts
6147
- var import_node_path64 = require("path");
6162
+ // src/features/rules/windsurf-rule.ts
6163
+ var import_node_path65 = require("path");
6148
6164
  var WindsurfRule = class _WindsurfRule extends ToolRule {
6149
6165
  static getSettablePaths() {
6150
6166
  return {
6151
6167
  nonRoot: {
6152
- relativeDirPath: (0, import_node_path64.join)(".windsurf", "rules")
6168
+ relativeDirPath: (0, import_node_path65.join)(".windsurf", "rules")
6153
6169
  }
6154
6170
  };
6155
6171
  }
@@ -6159,7 +6175,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
6159
6175
  validate = true
6160
6176
  }) {
6161
6177
  const fileContent = await readFileContent(
6162
- (0, import_node_path64.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6178
+ (0, import_node_path65.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6163
6179
  );
6164
6180
  return new _WindsurfRule({
6165
6181
  baseDir,
@@ -6197,7 +6213,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
6197
6213
  }
6198
6214
  };
6199
6215
 
6200
- // src/rules/rules-processor.ts
6216
+ // src/features/rules/rules-processor.ts
6201
6217
  var rulesProcessorToolTargets = [
6202
6218
  "agentsmd",
6203
6219
  "amazonqcli",
@@ -6559,10 +6575,10 @@ var RulesProcessor = class extends FeatureProcessor {
6559
6575
  * Load and parse rulesync rule files from .rulesync/rules/ directory
6560
6576
  */
6561
6577
  async loadRulesyncFiles() {
6562
- const files = await findFilesByGlobs((0, import_node_path65.join)(".rulesync", "rules", "*.md"));
6578
+ const files = await findFilesByGlobs((0, import_node_path66.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md"));
6563
6579
  logger.debug(`Found ${files.length} rulesync files`);
6564
6580
  const rulesyncRules = await Promise.all(
6565
- files.map((file) => RulesyncRule.fromFile({ relativeFilePath: (0, import_node_path65.basename)(file) }))
6581
+ files.map((file) => RulesyncRule.fromFile({ relativeFilePath: (0, import_node_path66.basename)(file) }))
6566
6582
  );
6567
6583
  const rootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().root);
6568
6584
  if (rootRules.length > 1) {
@@ -6580,10 +6596,10 @@ var RulesProcessor = class extends FeatureProcessor {
6580
6596
  return rulesyncRules;
6581
6597
  }
6582
6598
  async loadRulesyncFilesLegacy() {
6583
- const legacyFiles = await findFilesByGlobs((0, import_node_path65.join)(".rulesync", "*.md"));
6599
+ const legacyFiles = await findFilesByGlobs((0, import_node_path66.join)(RULESYNC_RELATIVE_DIR_PATH, "*.md"));
6584
6600
  logger.debug(`Found ${legacyFiles.length} legacy rulesync files`);
6585
6601
  return Promise.all(
6586
- legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: (0, import_node_path65.basename)(file) }))
6602
+ legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: (0, import_node_path66.basename)(file) }))
6587
6603
  );
6588
6604
  }
6589
6605
  /**
@@ -6647,13 +6663,13 @@ var RulesProcessor = class extends FeatureProcessor {
6647
6663
  return [];
6648
6664
  }
6649
6665
  const rootFilePaths = await findFilesByGlobs(
6650
- (0, import_node_path65.join)(this.baseDir, root.relativeDirPath ?? ".", root.relativeFilePath)
6666
+ (0, import_node_path66.join)(this.baseDir, root.relativeDirPath ?? ".", root.relativeFilePath)
6651
6667
  );
6652
6668
  return await Promise.all(
6653
6669
  rootFilePaths.map(
6654
6670
  (filePath) => root.fromFile({
6655
6671
  baseDir: this.baseDir,
6656
- relativeFilePath: (0, import_node_path65.basename)(filePath),
6672
+ relativeFilePath: (0, import_node_path66.basename)(filePath),
6657
6673
  global: this.global
6658
6674
  })
6659
6675
  )
@@ -6665,13 +6681,13 @@ var RulesProcessor = class extends FeatureProcessor {
6665
6681
  return [];
6666
6682
  }
6667
6683
  const nonRootFilePaths = await findFilesByGlobs(
6668
- (0, import_node_path65.join)(this.baseDir, nonRoot.relativeDirPath, `*.${nonRoot.extension}`)
6684
+ (0, import_node_path66.join)(this.baseDir, nonRoot.relativeDirPath, `*.${nonRoot.extension}`)
6669
6685
  );
6670
6686
  return await Promise.all(
6671
6687
  nonRootFilePaths.map(
6672
6688
  (filePath) => nonRoot.fromFile({
6673
6689
  baseDir: this.baseDir,
6674
- relativeFilePath: (0, import_node_path65.basename)(filePath),
6690
+ relativeFilePath: (0, import_node_path66.basename)(filePath),
6675
6691
  global: this.global
6676
6692
  })
6677
6693
  )
@@ -7041,14 +7057,14 @@ s/<command> [arguments]
7041
7057
  This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
7042
7058
  The \`s\` in \`s/\` stands for *simulate*. Because custom slash commands are not built-in, this syntax provides a pseudo way to invoke them.
7043
7059
 
7044
- When users call a custom slash command, you have to look for the markdown file, \`${(0, import_node_path65.join)(commands.relativeDirPath, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
7060
+ When users call a custom slash command, you have to look for the markdown file, \`${(0, import_node_path66.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
7045
7061
  const subagentsSection = subagents ? `## Simulated Subagents
7046
7062
 
7047
7063
  Simulated subagents are specialized AI assistants that can be invoked to handle specific types of tasks. In this case, it can be appear something like custom slash commands simply. Simulated subagents can be called by custom slash commands.
7048
7064
 
7049
- When users call a simulated subagent, it will look for the corresponding markdown file, \`${(0, import_node_path65.join)(subagents.relativeDirPath, "{subagent}.md")}\`, and execute its contents as the block of operations.
7065
+ When users call a simulated subagent, it will look for the corresponding markdown file, \`${(0, import_node_path66.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
7050
7066
 
7051
- For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${(0, import_node_path65.join)(subagents.relativeDirPath, "planner.md")}\`, and execute its contents as the block of operations.` : "";
7067
+ For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${(0, import_node_path66.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
7052
7068
  const result = [
7053
7069
  overview,
7054
7070
  ...this.simulateCommands && CommandsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [commandsSection] : [],
@@ -7063,7 +7079,7 @@ async function generateCommand(options) {
7063
7079
  const config = await ConfigResolver.resolve(options);
7064
7080
  logger.setVerbose(config.getVerbose());
7065
7081
  logger.info("Generating files...");
7066
- if (!await fileExists(".rulesync")) {
7082
+ if (!await fileExists(RULESYNC_RELATIVE_DIR_PATH)) {
7067
7083
  logger.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
7068
7084
  process.exit(1);
7069
7085
  }
@@ -7262,9 +7278,9 @@ async function generateSubagents(config) {
7262
7278
  }
7263
7279
 
7264
7280
  // src/cli/commands/gitignore.ts
7265
- var import_node_path66 = require("path");
7281
+ var import_node_path67 = require("path");
7266
7282
  var gitignoreCommand = async () => {
7267
- const gitignorePath = (0, import_node_path66.join)(process.cwd(), ".gitignore");
7283
+ const gitignorePath = (0, import_node_path67.join)(process.cwd(), ".gitignore");
7268
7284
  const rulesFilesToIgnore = [
7269
7285
  "# Generated by rulesync - AI tool configuration files",
7270
7286
  // AGENTS.md
@@ -7505,24 +7521,26 @@ async function importSubagents(config, tool) {
7505
7521
  }
7506
7522
 
7507
7523
  // src/cli/commands/init.ts
7508
- var import_node_path67 = require("path");
7524
+ var import_node_path68 = require("path");
7509
7525
  async function initCommand() {
7510
7526
  logger.info("Initializing rulesync...");
7511
- await ensureDir(".rulesync");
7527
+ await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
7512
7528
  await createSampleFiles();
7513
7529
  await createConfigFile();
7514
7530
  logger.success("rulesync initialized successfully!");
7515
7531
  logger.info("Next steps:");
7516
- logger.info(`1. Edit .rulesync/**/*.md, .rulesync/mcp.json and .rulesyncignore`);
7532
+ logger.info(
7533
+ `1. Edit ${RULESYNC_RELATIVE_DIR_PATH}/**/*.md, ${RULESYNC_MCP_RELATIVE_FILE_PATH} and ${RULESYNC_IGNORE_RELATIVE_FILE_PATH}`
7534
+ );
7517
7535
  logger.info("2. Run 'rulesync generate' to create configuration files");
7518
7536
  }
7519
7537
  async function createConfigFile() {
7520
- if (await fileExists("rulesync.jsonc")) {
7521
- logger.info("Skipped rulesync.jsonc (already exists)");
7538
+ if (await fileExists(RULESYNC_CONFIG_RELATIVE_FILE_PATH)) {
7539
+ logger.info(`Skipped ${RULESYNC_CONFIG_RELATIVE_FILE_PATH} (already exists)`);
7522
7540
  return;
7523
7541
  }
7524
7542
  await writeFileContent(
7525
- "rulesync.jsonc",
7543
+ RULESYNC_CONFIG_RELATIVE_FILE_PATH,
7526
7544
  JSON.stringify(
7527
7545
  {
7528
7546
  targets: ["copilot", "cursor", "claudecode", "codexcli"],
@@ -7539,11 +7557,11 @@ async function createConfigFile() {
7539
7557
  2
7540
7558
  )
7541
7559
  );
7542
- logger.success("Created rulesync.jsonc");
7560
+ logger.success(`Created ${RULESYNC_CONFIG_RELATIVE_FILE_PATH}`);
7543
7561
  }
7544
7562
  async function createSampleFiles() {
7545
7563
  const sampleRuleFile = {
7546
- filename: "overview.md",
7564
+ filename: RULESYNC_OVERVIEW_FILE_NAME,
7547
7565
  content: `---
7548
7566
  root: true
7549
7567
  targets: ["*"]
@@ -7666,14 +7684,14 @@ Attention, again, you are just the planner, so though you can read any files and
7666
7684
  await ensureDir(commandPaths.relativeDirPath);
7667
7685
  await ensureDir(subagentPaths.relativeDirPath);
7668
7686
  await ensureDir(ignorePaths.relativeDirPath);
7669
- const ruleFilepath = (0, import_node_path67.join)(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
7687
+ const ruleFilepath = (0, import_node_path68.join)(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
7670
7688
  if (!await fileExists(ruleFilepath)) {
7671
7689
  await writeFileContent(ruleFilepath, sampleRuleFile.content);
7672
7690
  logger.success(`Created ${ruleFilepath}`);
7673
7691
  } else {
7674
7692
  logger.info(`Skipped ${ruleFilepath} (already exists)`);
7675
7693
  }
7676
- const mcpFilepath = (0, import_node_path67.join)(
7694
+ const mcpFilepath = (0, import_node_path68.join)(
7677
7695
  mcpPaths.recommended.relativeDirPath,
7678
7696
  mcpPaths.recommended.relativeFilePath
7679
7697
  );
@@ -7683,21 +7701,21 @@ Attention, again, you are just the planner, so though you can read any files and
7683
7701
  } else {
7684
7702
  logger.info(`Skipped ${mcpFilepath} (already exists)`);
7685
7703
  }
7686
- const commandFilepath = (0, import_node_path67.join)(commandPaths.relativeDirPath, sampleCommandFile.filename);
7704
+ const commandFilepath = (0, import_node_path68.join)(commandPaths.relativeDirPath, sampleCommandFile.filename);
7687
7705
  if (!await fileExists(commandFilepath)) {
7688
7706
  await writeFileContent(commandFilepath, sampleCommandFile.content);
7689
7707
  logger.success(`Created ${commandFilepath}`);
7690
7708
  } else {
7691
7709
  logger.info(`Skipped ${commandFilepath} (already exists)`);
7692
7710
  }
7693
- const subagentFilepath = (0, import_node_path67.join)(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
7711
+ const subagentFilepath = (0, import_node_path68.join)(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
7694
7712
  if (!await fileExists(subagentFilepath)) {
7695
7713
  await writeFileContent(subagentFilepath, sampleSubagentFile.content);
7696
7714
  logger.success(`Created ${subagentFilepath}`);
7697
7715
  } else {
7698
7716
  logger.info(`Skipped ${subagentFilepath} (already exists)`);
7699
7717
  }
7700
- const ignoreFilepath = (0, import_node_path67.join)(ignorePaths.relativeDirPath, ignorePaths.relativeFilePath);
7718
+ const ignoreFilepath = (0, import_node_path68.join)(ignorePaths.relativeDirPath, ignorePaths.relativeFilePath);
7701
7719
  if (!await fileExists(ignoreFilepath)) {
7702
7720
  await writeFileContent(ignoreFilepath, sampleIgnoreFile.content);
7703
7721
  logger.success(`Created ${ignoreFilepath}`);
@@ -7707,31 +7725,408 @@ Attention, again, you are just the planner, so though you can read any files and
7707
7725
  }
7708
7726
 
7709
7727
  // src/cli/commands/mcp.ts
7710
- var import_node_path68 = require("path");
7711
7728
  var import_fastmcp = require("fastmcp");
7729
+
7730
+ // src/mcp/commands.ts
7731
+ var import_node_path69 = require("path");
7712
7732
  var import_mini23 = require("zod/mini");
7713
- var MAX_RULE_SIZE_BYTES = 1024 * 1024;
7714
- var MAX_RULES_COUNT = 1e3;
7715
- var RULES_DIR_PREFIX = ".rulesync/rules";
7716
- function validateRulePath(relativePathFromCwd) {
7717
- const normalizedPath = relativePathFromCwd.replace(/\\/g, "/");
7718
- if (!normalizedPath.startsWith(`${RULES_DIR_PREFIX}/`)) {
7719
- throw new Error(`Invalid rule path: must be within ${RULES_DIR_PREFIX}/ directory`);
7733
+ var maxCommandSizeBytes = 1024 * 1024;
7734
+ var maxCommandsCount = 1e3;
7735
+ async function listCommands() {
7736
+ const commandsDir = (0, import_node_path69.join)(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
7737
+ try {
7738
+ const files = await listDirectoryFiles(commandsDir);
7739
+ const mdFiles = files.filter((file) => file.endsWith(".md"));
7740
+ const commands = await Promise.all(
7741
+ mdFiles.map(async (file) => {
7742
+ try {
7743
+ const command = await RulesyncCommand.fromFile({
7744
+ relativeFilePath: file
7745
+ });
7746
+ const frontmatter = command.getFrontmatter();
7747
+ return {
7748
+ relativePathFromCwd: (0, import_node_path69.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
7749
+ frontmatter
7750
+ };
7751
+ } catch (error) {
7752
+ logger.error(`Failed to read command file ${file}: ${formatError(error)}`);
7753
+ return null;
7754
+ }
7755
+ })
7756
+ );
7757
+ return commands.filter((command) => command !== null);
7758
+ } catch (error) {
7759
+ logger.error(`Failed to read commands directory: ${formatError(error)}`);
7760
+ return [];
7761
+ }
7762
+ }
7763
+ async function getCommand({ relativePathFromCwd }) {
7764
+ checkPathTraversal({
7765
+ relativePath: relativePathFromCwd,
7766
+ intendedRootDir: process.cwd()
7767
+ });
7768
+ const filename = (0, import_node_path69.basename)(relativePathFromCwd);
7769
+ try {
7770
+ const command = await RulesyncCommand.fromFile({
7771
+ relativeFilePath: filename
7772
+ });
7773
+ return {
7774
+ relativePathFromCwd: (0, import_node_path69.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
7775
+ frontmatter: command.getFrontmatter(),
7776
+ body: command.getBody()
7777
+ };
7778
+ } catch (error) {
7779
+ throw new Error(`Failed to read command file ${relativePathFromCwd}: ${formatError(error)}`, {
7780
+ cause: error
7781
+ });
7782
+ }
7783
+ }
7784
+ async function putCommand({
7785
+ relativePathFromCwd,
7786
+ frontmatter,
7787
+ body
7788
+ }) {
7789
+ checkPathTraversal({
7790
+ relativePath: relativePathFromCwd,
7791
+ intendedRootDir: process.cwd()
7792
+ });
7793
+ const filename = (0, import_node_path69.basename)(relativePathFromCwd);
7794
+ const estimatedSize = JSON.stringify(frontmatter).length + body.length;
7795
+ if (estimatedSize > maxCommandSizeBytes) {
7796
+ throw new Error(
7797
+ `Command size ${estimatedSize} bytes exceeds maximum ${maxCommandSizeBytes} bytes (1MB)`
7798
+ );
7799
+ }
7800
+ try {
7801
+ const existingCommands = await listCommands();
7802
+ const isUpdate = existingCommands.some(
7803
+ (command2) => command2.relativePathFromCwd === (0, import_node_path69.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
7804
+ );
7805
+ if (!isUpdate && existingCommands.length >= maxCommandsCount) {
7806
+ throw new Error(`Maximum number of commands (${maxCommandsCount}) reached`);
7807
+ }
7808
+ const fileContent = stringifyFrontmatter(body, frontmatter);
7809
+ const command = new RulesyncCommand({
7810
+ baseDir: process.cwd(),
7811
+ relativeDirPath: RULESYNC_COMMANDS_RELATIVE_DIR_PATH,
7812
+ relativeFilePath: filename,
7813
+ frontmatter,
7814
+ body,
7815
+ fileContent,
7816
+ validate: true
7817
+ });
7818
+ const commandsDir = (0, import_node_path69.join)(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
7819
+ await ensureDir(commandsDir);
7820
+ await writeFileContent(command.getFilePath(), command.getFileContent());
7821
+ return {
7822
+ relativePathFromCwd: (0, import_node_path69.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
7823
+ frontmatter: command.getFrontmatter(),
7824
+ body: command.getBody()
7825
+ };
7826
+ } catch (error) {
7827
+ throw new Error(`Failed to write command file ${relativePathFromCwd}: ${formatError(error)}`, {
7828
+ cause: error
7829
+ });
7830
+ }
7831
+ }
7832
+ async function deleteCommand({ relativePathFromCwd }) {
7833
+ checkPathTraversal({
7834
+ relativePath: relativePathFromCwd,
7835
+ intendedRootDir: process.cwd()
7836
+ });
7837
+ const filename = (0, import_node_path69.basename)(relativePathFromCwd);
7838
+ const fullPath = (0, import_node_path69.join)(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
7839
+ try {
7840
+ await removeFile(fullPath);
7841
+ return {
7842
+ relativePathFromCwd: (0, import_node_path69.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
7843
+ };
7844
+ } catch (error) {
7845
+ throw new Error(`Failed to delete command file ${relativePathFromCwd}: ${formatError(error)}`, {
7846
+ cause: error
7847
+ });
7848
+ }
7849
+ }
7850
+ var commandToolSchemas = {
7851
+ listCommands: import_mini23.z.object({}),
7852
+ getCommand: import_mini23.z.object({
7853
+ relativePathFromCwd: import_mini23.z.string()
7854
+ }),
7855
+ putCommand: import_mini23.z.object({
7856
+ relativePathFromCwd: import_mini23.z.string(),
7857
+ frontmatter: RulesyncCommandFrontmatterSchema,
7858
+ body: import_mini23.z.string()
7859
+ }),
7860
+ deleteCommand: import_mini23.z.object({
7861
+ relativePathFromCwd: import_mini23.z.string()
7862
+ })
7863
+ };
7864
+ var commandTools = {
7865
+ listCommands: {
7866
+ name: "listCommands",
7867
+ description: `List all commands from ${(0, import_node_path69.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
7868
+ parameters: commandToolSchemas.listCommands,
7869
+ execute: async () => {
7870
+ const commands = await listCommands();
7871
+ const output = { commands };
7872
+ return JSON.stringify(output, null, 2);
7873
+ }
7874
+ },
7875
+ getCommand: {
7876
+ name: "getCommand",
7877
+ description: "Get detailed information about a specific command. relativePathFromCwd parameter is required.",
7878
+ parameters: commandToolSchemas.getCommand,
7879
+ execute: async (args) => {
7880
+ const result = await getCommand({ relativePathFromCwd: args.relativePathFromCwd });
7881
+ return JSON.stringify(result, null, 2);
7882
+ }
7883
+ },
7884
+ putCommand: {
7885
+ name: "putCommand",
7886
+ description: "Create or update a command (upsert operation). relativePathFromCwd, frontmatter, and body parameters are required.",
7887
+ parameters: commandToolSchemas.putCommand,
7888
+ execute: async (args) => {
7889
+ const result = await putCommand({
7890
+ relativePathFromCwd: args.relativePathFromCwd,
7891
+ frontmatter: args.frontmatter,
7892
+ body: args.body
7893
+ });
7894
+ return JSON.stringify(result, null, 2);
7895
+ }
7896
+ },
7897
+ deleteCommand: {
7898
+ name: "deleteCommand",
7899
+ description: "Delete a command file. relativePathFromCwd parameter is required.",
7900
+ parameters: commandToolSchemas.deleteCommand,
7901
+ execute: async (args) => {
7902
+ const result = await deleteCommand({ relativePathFromCwd: args.relativePathFromCwd });
7903
+ return JSON.stringify(result, null, 2);
7904
+ }
7905
+ }
7906
+ };
7907
+
7908
+ // src/mcp/ignore.ts
7909
+ var import_node_path70 = require("path");
7910
+ var import_mini24 = require("zod/mini");
7911
+ var maxIgnoreFileSizeBytes = 100 * 1024;
7912
+ async function getIgnoreFile() {
7913
+ const ignoreFilePath = (0, import_node_path70.join)(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
7914
+ try {
7915
+ const content = await readFileContent(ignoreFilePath);
7916
+ return {
7917
+ relativePathFromCwd: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
7918
+ content
7919
+ };
7920
+ } catch (error) {
7921
+ throw new Error(`Failed to read .rulesyncignore file: ${formatError(error)}`, {
7922
+ cause: error
7923
+ });
7924
+ }
7925
+ }
7926
+ async function putIgnoreFile({ content }) {
7927
+ const ignoreFilePath = (0, import_node_path70.join)(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
7928
+ const contentSizeBytes = Buffer.byteLength(content, "utf8");
7929
+ if (contentSizeBytes > maxIgnoreFileSizeBytes) {
7930
+ throw new Error(
7931
+ `Ignore file size ${contentSizeBytes} bytes exceeds maximum ${maxIgnoreFileSizeBytes} bytes (100KB)`
7932
+ );
7933
+ }
7934
+ try {
7935
+ await ensureDir(process.cwd());
7936
+ await writeFileContent(ignoreFilePath, content);
7937
+ return {
7938
+ relativePathFromCwd: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
7939
+ content
7940
+ };
7941
+ } catch (error) {
7942
+ throw new Error(`Failed to write .rulesyncignore file: ${formatError(error)}`, {
7943
+ cause: error
7944
+ });
7945
+ }
7946
+ }
7947
+ async function deleteIgnoreFile() {
7948
+ const ignoreFilePath = (0, import_node_path70.join)(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
7949
+ try {
7950
+ await removeFile(ignoreFilePath);
7951
+ return {
7952
+ relativePathFromCwd: RULESYNC_IGNORE_RELATIVE_FILE_PATH
7953
+ };
7954
+ } catch (error) {
7955
+ throw new Error(`Failed to delete .rulesyncignore file: ${formatError(error)}`, {
7956
+ cause: error
7957
+ });
7720
7958
  }
7959
+ }
7960
+ var ignoreToolSchemas = {
7961
+ getIgnoreFile: import_mini24.z.object({}),
7962
+ putIgnoreFile: import_mini24.z.object({
7963
+ content: import_mini24.z.string()
7964
+ }),
7965
+ deleteIgnoreFile: import_mini24.z.object({})
7966
+ };
7967
+ var ignoreTools = {
7968
+ getIgnoreFile: {
7969
+ name: "getIgnoreFile",
7970
+ description: "Get the content of the .rulesyncignore file from the project root.",
7971
+ parameters: ignoreToolSchemas.getIgnoreFile,
7972
+ execute: async () => {
7973
+ const result = await getIgnoreFile();
7974
+ return JSON.stringify(result, null, 2);
7975
+ }
7976
+ },
7977
+ putIgnoreFile: {
7978
+ name: "putIgnoreFile",
7979
+ description: "Create or update the .rulesyncignore file (upsert operation). content parameter is required.",
7980
+ parameters: ignoreToolSchemas.putIgnoreFile,
7981
+ execute: async (args) => {
7982
+ const result = await putIgnoreFile({ content: args.content });
7983
+ return JSON.stringify(result, null, 2);
7984
+ }
7985
+ },
7986
+ deleteIgnoreFile: {
7987
+ name: "deleteIgnoreFile",
7988
+ description: "Delete the .rulesyncignore file from the project root.",
7989
+ parameters: ignoreToolSchemas.deleteIgnoreFile,
7990
+ execute: async () => {
7991
+ const result = await deleteIgnoreFile();
7992
+ return JSON.stringify(result, null, 2);
7993
+ }
7994
+ }
7995
+ };
7996
+
7997
+ // src/mcp/mcp.ts
7998
+ var import_node_path71 = require("path");
7999
+ var import_mini25 = require("zod/mini");
8000
+ var maxMcpSizeBytes = 1024 * 1024;
8001
+ async function getMcpFile() {
7721
8002
  try {
7722
- resolvePath(normalizedPath, process.cwd());
8003
+ const rulesyncMcp = await RulesyncMcp.fromFile({
8004
+ validate: true,
8005
+ modularMcp: false
8006
+ });
8007
+ const relativePathFromCwd = (0, import_node_path71.join)(
8008
+ rulesyncMcp.getRelativeDirPath(),
8009
+ rulesyncMcp.getRelativeFilePath()
8010
+ );
8011
+ return {
8012
+ relativePathFromCwd,
8013
+ content: rulesyncMcp.getFileContent()
8014
+ };
7723
8015
  } catch (error) {
7724
- throw new Error(`Path validation failed: ${formatError(error)}`, { cause: error });
8016
+ throw new Error(`Failed to read MCP file: ${formatError(error)}`, {
8017
+ cause: error
8018
+ });
7725
8019
  }
7726
- const filename = (0, import_node_path68.basename)(normalizedPath);
7727
- if (!/^[a-zA-Z0-9_-]+\.md$/.test(filename)) {
8020
+ }
8021
+ async function putMcpFile({ content }) {
8022
+ if (content.length > maxMcpSizeBytes) {
7728
8023
  throw new Error(
7729
- `Invalid filename: ${filename}. Must match pattern [a-zA-Z0-9_-]+.md (alphanumeric, hyphens, underscores only)`
8024
+ `MCP file size ${content.length} bytes exceeds maximum ${maxMcpSizeBytes} bytes (1MB)`
8025
+ );
8026
+ }
8027
+ try {
8028
+ JSON.parse(content);
8029
+ } catch (error) {
8030
+ throw new Error(`Invalid JSON format in MCP file: ${formatError(error)}`, {
8031
+ cause: error
8032
+ });
8033
+ }
8034
+ try {
8035
+ const baseDir = process.cwd();
8036
+ const paths = RulesyncMcp.getSettablePaths();
8037
+ const relativeDirPath = paths.recommended.relativeDirPath;
8038
+ const relativeFilePath = paths.recommended.relativeFilePath;
8039
+ const fullPath = (0, import_node_path71.join)(baseDir, relativeDirPath, relativeFilePath);
8040
+ const rulesyncMcp = new RulesyncMcp({
8041
+ baseDir,
8042
+ relativeDirPath,
8043
+ relativeFilePath,
8044
+ fileContent: content,
8045
+ validate: true,
8046
+ modularMcp: false
8047
+ });
8048
+ await ensureDir((0, import_node_path71.join)(baseDir, relativeDirPath));
8049
+ await writeFileContent(fullPath, content);
8050
+ const relativePathFromCwd = (0, import_node_path71.join)(relativeDirPath, relativeFilePath);
8051
+ return {
8052
+ relativePathFromCwd,
8053
+ content: rulesyncMcp.getFileContent()
8054
+ };
8055
+ } catch (error) {
8056
+ throw new Error(`Failed to write MCP file: ${formatError(error)}`, {
8057
+ cause: error
8058
+ });
8059
+ }
8060
+ }
8061
+ async function deleteMcpFile() {
8062
+ try {
8063
+ const baseDir = process.cwd();
8064
+ const paths = RulesyncMcp.getSettablePaths();
8065
+ const recommendedPath = (0, import_node_path71.join)(
8066
+ baseDir,
8067
+ paths.recommended.relativeDirPath,
8068
+ paths.recommended.relativeFilePath
8069
+ );
8070
+ const legacyPath = (0, import_node_path71.join)(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
8071
+ await removeFile(recommendedPath);
8072
+ await removeFile(legacyPath);
8073
+ const relativePathFromCwd = (0, import_node_path71.join)(
8074
+ paths.recommended.relativeDirPath,
8075
+ paths.recommended.relativeFilePath
7730
8076
  );
8077
+ return {
8078
+ relativePathFromCwd
8079
+ };
8080
+ } catch (error) {
8081
+ throw new Error(`Failed to delete MCP file: ${formatError(error)}`, {
8082
+ cause: error
8083
+ });
7731
8084
  }
7732
8085
  }
8086
+ var mcpToolSchemas = {
8087
+ getMcpFile: import_mini25.z.object({}),
8088
+ putMcpFile: import_mini25.z.object({
8089
+ content: import_mini25.z.string()
8090
+ }),
8091
+ deleteMcpFile: import_mini25.z.object({})
8092
+ };
8093
+ var mcpTools = {
8094
+ getMcpFile: {
8095
+ name: "getMcpFile",
8096
+ description: `Get the MCP configuration file (${RULESYNC_MCP_RELATIVE_FILE_PATH}).`,
8097
+ parameters: mcpToolSchemas.getMcpFile,
8098
+ execute: async () => {
8099
+ const result = await getMcpFile();
8100
+ return JSON.stringify(result, null, 2);
8101
+ }
8102
+ },
8103
+ putMcpFile: {
8104
+ name: "putMcpFile",
8105
+ description: "Create or update the MCP configuration file (upsert operation). content parameter is required and must be valid JSON.",
8106
+ parameters: mcpToolSchemas.putMcpFile,
8107
+ execute: async (args) => {
8108
+ const result = await putMcpFile({ content: args.content });
8109
+ return JSON.stringify(result, null, 2);
8110
+ }
8111
+ },
8112
+ deleteMcpFile: {
8113
+ name: "deleteMcpFile",
8114
+ description: "Delete the MCP configuration file.",
8115
+ parameters: mcpToolSchemas.deleteMcpFile,
8116
+ execute: async () => {
8117
+ const result = await deleteMcpFile();
8118
+ return JSON.stringify(result, null, 2);
8119
+ }
8120
+ }
8121
+ };
8122
+
8123
+ // src/mcp/rules.ts
8124
+ var import_node_path72 = require("path");
8125
+ var import_mini26 = require("zod/mini");
8126
+ var maxRuleSizeBytes = 1024 * 1024;
8127
+ var maxRulesCount = 1e3;
7733
8128
  async function listRules() {
7734
- const rulesDir = (0, import_node_path68.join)(process.cwd(), ".rulesync", "rules");
8129
+ const rulesDir = (0, import_node_path72.join)(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
7735
8130
  try {
7736
8131
  const files = await listDirectoryFiles(rulesDir);
7737
8132
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -7744,7 +8139,7 @@ async function listRules() {
7744
8139
  });
7745
8140
  const frontmatter = rule.getFrontmatter();
7746
8141
  return {
7747
- relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "rules", file),
8142
+ relativePathFromCwd: (0, import_node_path72.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
7748
8143
  frontmatter
7749
8144
  };
7750
8145
  } catch (error) {
@@ -7760,15 +8155,18 @@ async function listRules() {
7760
8155
  }
7761
8156
  }
7762
8157
  async function getRule({ relativePathFromCwd }) {
7763
- validateRulePath(relativePathFromCwd);
7764
- const filename = (0, import_node_path68.basename)(relativePathFromCwd);
8158
+ checkPathTraversal({
8159
+ relativePath: relativePathFromCwd,
8160
+ intendedRootDir: process.cwd()
8161
+ });
8162
+ const filename = (0, import_node_path72.basename)(relativePathFromCwd);
7765
8163
  try {
7766
8164
  const rule = await RulesyncRule.fromFile({
7767
8165
  relativeFilePath: filename,
7768
8166
  validate: true
7769
8167
  });
7770
8168
  return {
7771
- relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "rules", filename),
8169
+ relativePathFromCwd: (0, import_node_path72.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
7772
8170
  frontmatter: rule.getFrontmatter(),
7773
8171
  body: rule.getBody()
7774
8172
  };
@@ -7783,35 +8181,38 @@ async function putRule({
7783
8181
  frontmatter,
7784
8182
  body
7785
8183
  }) {
7786
- validateRulePath(relativePathFromCwd);
7787
- const filename = (0, import_node_path68.basename)(relativePathFromCwd);
8184
+ checkPathTraversal({
8185
+ relativePath: relativePathFromCwd,
8186
+ intendedRootDir: process.cwd()
8187
+ });
8188
+ const filename = (0, import_node_path72.basename)(relativePathFromCwd);
7788
8189
  const estimatedSize = JSON.stringify(frontmatter).length + body.length;
7789
- if (estimatedSize > MAX_RULE_SIZE_BYTES) {
8190
+ if (estimatedSize > maxRuleSizeBytes) {
7790
8191
  throw new Error(
7791
- `Rule size ${estimatedSize} bytes exceeds maximum ${MAX_RULE_SIZE_BYTES} bytes (1MB)`
8192
+ `Rule size ${estimatedSize} bytes exceeds maximum ${maxRuleSizeBytes} bytes (1MB)`
7792
8193
  );
7793
8194
  }
7794
8195
  try {
7795
8196
  const existingRules = await listRules();
7796
8197
  const isUpdate = existingRules.some(
7797
- (rule2) => rule2.relativePathFromCwd === (0, import_node_path68.join)(".rulesync", "rules", filename)
8198
+ (rule2) => rule2.relativePathFromCwd === (0, import_node_path72.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
7798
8199
  );
7799
- if (!isUpdate && existingRules.length >= MAX_RULES_COUNT) {
7800
- throw new Error(`Maximum number of rules (${MAX_RULES_COUNT}) reached`);
8200
+ if (!isUpdate && existingRules.length >= maxRulesCount) {
8201
+ throw new Error(`Maximum number of rules (${maxRulesCount}) reached`);
7801
8202
  }
7802
8203
  const rule = new RulesyncRule({
7803
8204
  baseDir: process.cwd(),
7804
- relativeDirPath: ".rulesync/rules",
8205
+ relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
7805
8206
  relativeFilePath: filename,
7806
8207
  frontmatter,
7807
8208
  body,
7808
8209
  validate: true
7809
8210
  });
7810
- const rulesDir = (0, import_node_path68.join)(process.cwd(), ".rulesync", "rules");
8211
+ const rulesDir = (0, import_node_path72.join)(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
7811
8212
  await ensureDir(rulesDir);
7812
8213
  await writeFileContent(rule.getFilePath(), rule.getFileContent());
7813
8214
  return {
7814
- relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "rules", filename),
8215
+ relativePathFromCwd: (0, import_node_path72.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
7815
8216
  frontmatter: rule.getFrontmatter(),
7816
8217
  body: rule.getBody()
7817
8218
  };
@@ -7822,13 +8223,16 @@ async function putRule({
7822
8223
  }
7823
8224
  }
7824
8225
  async function deleteRule({ relativePathFromCwd }) {
7825
- validateRulePath(relativePathFromCwd);
7826
- const filename = (0, import_node_path68.basename)(relativePathFromCwd);
7827
- const fullPath = (0, import_node_path68.join)(process.cwd(), ".rulesync", "rules", filename);
8226
+ checkPathTraversal({
8227
+ relativePath: relativePathFromCwd,
8228
+ intendedRootDir: process.cwd()
8229
+ });
8230
+ const filename = (0, import_node_path72.basename)(relativePathFromCwd);
8231
+ const fullPath = (0, import_node_path72.join)(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
7828
8232
  try {
7829
8233
  await removeFile(fullPath);
7830
8234
  return {
7831
- relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "rules", filename)
8235
+ relativePathFromCwd: (0, import_node_path72.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
7832
8236
  };
7833
8237
  } catch (error) {
7834
8238
  throw new Error(`Failed to delete rule file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -7836,42 +8240,44 @@ async function deleteRule({ relativePathFromCwd }) {
7836
8240
  });
7837
8241
  }
7838
8242
  }
7839
- async function mcpCommand({ version }) {
7840
- const server = new import_fastmcp.FastMCP({
7841
- name: "rulesync-mcp-server",
7842
- // Type assertion is safe here because version comes from package.json which follows semver
7843
- // eslint-disable-next-line no-type-assertion/no-type-assertion
7844
- version
7845
- });
7846
- server.addTool({
8243
+ var ruleToolSchemas = {
8244
+ listRules: import_mini26.z.object({}),
8245
+ getRule: import_mini26.z.object({
8246
+ relativePathFromCwd: import_mini26.z.string()
8247
+ }),
8248
+ putRule: import_mini26.z.object({
8249
+ relativePathFromCwd: import_mini26.z.string(),
8250
+ frontmatter: RulesyncRuleFrontmatterSchema,
8251
+ body: import_mini26.z.string()
8252
+ }),
8253
+ deleteRule: import_mini26.z.object({
8254
+ relativePathFromCwd: import_mini26.z.string()
8255
+ })
8256
+ };
8257
+ var ruleTools = {
8258
+ listRules: {
7847
8259
  name: "listRules",
7848
- description: "List all rules from .rulesync/rules/*.md with their frontmatter",
7849
- parameters: import_mini23.z.object({}),
8260
+ description: `List all rules from ${(0, import_node_path72.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
8261
+ parameters: ruleToolSchemas.listRules,
7850
8262
  execute: async () => {
7851
8263
  const rules = await listRules();
7852
8264
  const output = { rules };
7853
8265
  return JSON.stringify(output, null, 2);
7854
8266
  }
7855
- });
7856
- server.addTool({
8267
+ },
8268
+ getRule: {
7857
8269
  name: "getRule",
7858
8270
  description: "Get detailed information about a specific rule. relativePathFromCwd parameter is required.",
7859
- parameters: import_mini23.z.object({
7860
- relativePathFromCwd: import_mini23.z.string()
7861
- }),
8271
+ parameters: ruleToolSchemas.getRule,
7862
8272
  execute: async (args) => {
7863
8273
  const result = await getRule({ relativePathFromCwd: args.relativePathFromCwd });
7864
8274
  return JSON.stringify(result, null, 2);
7865
8275
  }
7866
- });
7867
- server.addTool({
8276
+ },
8277
+ putRule: {
7868
8278
  name: "putRule",
7869
8279
  description: "Create or update a rule (upsert operation). relativePathFromCwd, frontmatter, and body parameters are required.",
7870
- parameters: import_mini23.z.object({
7871
- relativePathFromCwd: import_mini23.z.string(),
7872
- frontmatter: RulesyncRuleFrontmatterSchema,
7873
- body: import_mini23.z.string()
7874
- }),
8280
+ parameters: ruleToolSchemas.putRule,
7875
8281
  execute: async (args) => {
7876
8282
  const result = await putRule({
7877
8283
  relativePathFromCwd: args.relativePathFromCwd,
@@ -7880,18 +8286,227 @@ async function mcpCommand({ version }) {
7880
8286
  });
7881
8287
  return JSON.stringify(result, null, 2);
7882
8288
  }
7883
- });
7884
- server.addTool({
8289
+ },
8290
+ deleteRule: {
7885
8291
  name: "deleteRule",
7886
8292
  description: "Delete a rule file. relativePathFromCwd parameter is required.",
7887
- parameters: import_mini23.z.object({
7888
- relativePathFromCwd: import_mini23.z.string()
7889
- }),
8293
+ parameters: ruleToolSchemas.deleteRule,
7890
8294
  execute: async (args) => {
7891
8295
  const result = await deleteRule({ relativePathFromCwd: args.relativePathFromCwd });
7892
8296
  return JSON.stringify(result, null, 2);
7893
8297
  }
8298
+ }
8299
+ };
8300
+
8301
+ // src/mcp/subagents.ts
8302
+ var import_node_path73 = require("path");
8303
+ var import_mini27 = require("zod/mini");
8304
+ var maxSubagentSizeBytes = 1024 * 1024;
8305
+ var maxSubagentsCount = 1e3;
8306
+ async function listSubagents() {
8307
+ const subagentsDir = (0, import_node_path73.join)(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
8308
+ try {
8309
+ const files = await listDirectoryFiles(subagentsDir);
8310
+ const mdFiles = files.filter((file) => file.endsWith(".md"));
8311
+ const subagents = await Promise.all(
8312
+ mdFiles.map(async (file) => {
8313
+ try {
8314
+ const subagent = await RulesyncSubagent.fromFile({
8315
+ relativeFilePath: file,
8316
+ validate: true
8317
+ });
8318
+ const frontmatter = subagent.getFrontmatter();
8319
+ return {
8320
+ relativePathFromCwd: (0, import_node_path73.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
8321
+ frontmatter
8322
+ };
8323
+ } catch (error) {
8324
+ logger.error(`Failed to read subagent file ${file}: ${formatError(error)}`);
8325
+ return null;
8326
+ }
8327
+ })
8328
+ );
8329
+ return subagents.filter(
8330
+ (subagent) => subagent !== null
8331
+ );
8332
+ } catch (error) {
8333
+ logger.error(`Failed to read subagents directory: ${formatError(error)}`);
8334
+ return [];
8335
+ }
8336
+ }
8337
+ async function getSubagent({ relativePathFromCwd }) {
8338
+ checkPathTraversal({
8339
+ relativePath: relativePathFromCwd,
8340
+ intendedRootDir: process.cwd()
8341
+ });
8342
+ const filename = (0, import_node_path73.basename)(relativePathFromCwd);
8343
+ try {
8344
+ const subagent = await RulesyncSubagent.fromFile({
8345
+ relativeFilePath: filename,
8346
+ validate: true
8347
+ });
8348
+ return {
8349
+ relativePathFromCwd: (0, import_node_path73.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
8350
+ frontmatter: subagent.getFrontmatter(),
8351
+ body: subagent.getBody()
8352
+ };
8353
+ } catch (error) {
8354
+ throw new Error(`Failed to read subagent file ${relativePathFromCwd}: ${formatError(error)}`, {
8355
+ cause: error
8356
+ });
8357
+ }
8358
+ }
8359
+ async function putSubagent({
8360
+ relativePathFromCwd,
8361
+ frontmatter,
8362
+ body
8363
+ }) {
8364
+ checkPathTraversal({
8365
+ relativePath: relativePathFromCwd,
8366
+ intendedRootDir: process.cwd()
8367
+ });
8368
+ const filename = (0, import_node_path73.basename)(relativePathFromCwd);
8369
+ const estimatedSize = JSON.stringify(frontmatter).length + body.length;
8370
+ if (estimatedSize > maxSubagentSizeBytes) {
8371
+ throw new Error(
8372
+ `Subagent size ${estimatedSize} bytes exceeds maximum ${maxSubagentSizeBytes} bytes (1MB)`
8373
+ );
8374
+ }
8375
+ try {
8376
+ const existingSubagents = await listSubagents();
8377
+ const isUpdate = existingSubagents.some(
8378
+ (subagent2) => subagent2.relativePathFromCwd === (0, import_node_path73.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
8379
+ );
8380
+ if (!isUpdate && existingSubagents.length >= maxSubagentsCount) {
8381
+ throw new Error(`Maximum number of subagents (${maxSubagentsCount}) reached`);
8382
+ }
8383
+ const subagent = new RulesyncSubagent({
8384
+ baseDir: process.cwd(),
8385
+ relativeDirPath: RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH,
8386
+ relativeFilePath: filename,
8387
+ frontmatter,
8388
+ body,
8389
+ validate: true
8390
+ });
8391
+ const subagentsDir = (0, import_node_path73.join)(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
8392
+ await ensureDir(subagentsDir);
8393
+ await writeFileContent(subagent.getFilePath(), subagent.getFileContent());
8394
+ return {
8395
+ relativePathFromCwd: (0, import_node_path73.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
8396
+ frontmatter: subagent.getFrontmatter(),
8397
+ body: subagent.getBody()
8398
+ };
8399
+ } catch (error) {
8400
+ throw new Error(`Failed to write subagent file ${relativePathFromCwd}: ${formatError(error)}`, {
8401
+ cause: error
8402
+ });
8403
+ }
8404
+ }
8405
+ async function deleteSubagent({ relativePathFromCwd }) {
8406
+ checkPathTraversal({
8407
+ relativePath: relativePathFromCwd,
8408
+ intendedRootDir: process.cwd()
8409
+ });
8410
+ const filename = (0, import_node_path73.basename)(relativePathFromCwd);
8411
+ const fullPath = (0, import_node_path73.join)(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
8412
+ try {
8413
+ await removeFile(fullPath);
8414
+ return {
8415
+ relativePathFromCwd: (0, import_node_path73.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
8416
+ };
8417
+ } catch (error) {
8418
+ throw new Error(
8419
+ `Failed to delete subagent file ${relativePathFromCwd}: ${formatError(error)}`,
8420
+ {
8421
+ cause: error
8422
+ }
8423
+ );
8424
+ }
8425
+ }
8426
+ var subagentToolSchemas = {
8427
+ listSubagents: import_mini27.z.object({}),
8428
+ getSubagent: import_mini27.z.object({
8429
+ relativePathFromCwd: import_mini27.z.string()
8430
+ }),
8431
+ putSubagent: import_mini27.z.object({
8432
+ relativePathFromCwd: import_mini27.z.string(),
8433
+ frontmatter: RulesyncSubagentFrontmatterSchema,
8434
+ body: import_mini27.z.string()
8435
+ }),
8436
+ deleteSubagent: import_mini27.z.object({
8437
+ relativePathFromCwd: import_mini27.z.string()
8438
+ })
8439
+ };
8440
+ var subagentTools = {
8441
+ listSubagents: {
8442
+ name: "listSubagents",
8443
+ description: `List all subagents from ${(0, import_node_path73.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
8444
+ parameters: subagentToolSchemas.listSubagents,
8445
+ execute: async () => {
8446
+ const subagents = await listSubagents();
8447
+ const output = { subagents };
8448
+ return JSON.stringify(output, null, 2);
8449
+ }
8450
+ },
8451
+ getSubagent: {
8452
+ name: "getSubagent",
8453
+ description: "Get detailed information about a specific subagent. relativePathFromCwd parameter is required.",
8454
+ parameters: subagentToolSchemas.getSubagent,
8455
+ execute: async (args) => {
8456
+ const result = await getSubagent({ relativePathFromCwd: args.relativePathFromCwd });
8457
+ return JSON.stringify(result, null, 2);
8458
+ }
8459
+ },
8460
+ putSubagent: {
8461
+ name: "putSubagent",
8462
+ description: "Create or update a subagent (upsert operation). relativePathFromCwd, frontmatter, and body parameters are required.",
8463
+ parameters: subagentToolSchemas.putSubagent,
8464
+ execute: async (args) => {
8465
+ const result = await putSubagent({
8466
+ relativePathFromCwd: args.relativePathFromCwd,
8467
+ frontmatter: args.frontmatter,
8468
+ body: args.body
8469
+ });
8470
+ return JSON.stringify(result, null, 2);
8471
+ }
8472
+ },
8473
+ deleteSubagent: {
8474
+ name: "deleteSubagent",
8475
+ description: "Delete a subagent file. relativePathFromCwd parameter is required.",
8476
+ parameters: subagentToolSchemas.deleteSubagent,
8477
+ execute: async (args) => {
8478
+ const result = await deleteSubagent({ relativePathFromCwd: args.relativePathFromCwd });
8479
+ return JSON.stringify(result, null, 2);
8480
+ }
8481
+ }
8482
+ };
8483
+
8484
+ // src/cli/commands/mcp.ts
8485
+ async function mcpCommand({ version }) {
8486
+ const server = new import_fastmcp.FastMCP({
8487
+ name: "Rulesync MCP Server",
8488
+ // eslint-disable-next-line no-type-assertion/no-type-assertion
8489
+ version,
8490
+ instructions: "This server handles Rulesync files including rules, commands, MCP, ignore files, and subagents for any AI agents. It should be used when you need those files."
7894
8491
  });
8492
+ server.addTool(ruleTools.listRules);
8493
+ server.addTool(ruleTools.getRule);
8494
+ server.addTool(ruleTools.putRule);
8495
+ server.addTool(ruleTools.deleteRule);
8496
+ server.addTool(commandTools.listCommands);
8497
+ server.addTool(commandTools.getCommand);
8498
+ server.addTool(commandTools.putCommand);
8499
+ server.addTool(commandTools.deleteCommand);
8500
+ server.addTool(subagentTools.listSubagents);
8501
+ server.addTool(subagentTools.getSubagent);
8502
+ server.addTool(subagentTools.putSubagent);
8503
+ server.addTool(subagentTools.deleteSubagent);
8504
+ server.addTool(ignoreTools.getIgnoreFile);
8505
+ server.addTool(ignoreTools.putIgnoreFile);
8506
+ server.addTool(ignoreTools.deleteIgnoreFile);
8507
+ server.addTool(mcpTools.getMcpFile);
8508
+ server.addTool(mcpTools.putMcpFile);
8509
+ server.addTool(mcpTools.deleteMcpFile);
7895
8510
  logger.info("Rulesync MCP server started via stdio");
7896
8511
  void server.start({
7897
8512
  transportType: "stdio"
@@ -7899,7 +8514,7 @@ async function mcpCommand({ version }) {
7899
8514
  }
7900
8515
 
7901
8516
  // src/cli/index.ts
7902
- var getVersion = () => "3.19.0";
8517
+ var getVersion = () => "3.21.0";
7903
8518
  var main = async () => {
7904
8519
  const program = new import_commander.Command();
7905
8520
  const version = getVersion();