rulesync 7.3.0 → 7.5.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.
package/dist/index.cjs CHANGED
@@ -1000,7 +1000,7 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
1000
1000
  return {
1001
1001
  baseDir,
1002
1002
  relativeDirPath: _SimulatedCommand.getSettablePaths().relativeDirPath,
1003
- relativeFilePath: (0, import_node_path5.basename)(relativeFilePath),
1003
+ relativeFilePath,
1004
1004
  frontmatter: result.data,
1005
1005
  body: content.trim(),
1006
1006
  validate
@@ -1057,7 +1057,7 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
1057
1057
  return new _AgentsmdCommand({
1058
1058
  baseDir,
1059
1059
  relativeDirPath: _AgentsmdCommand.getSettablePaths().relativeDirPath,
1060
- relativeFilePath: (0, import_node_path6.basename)(relativeFilePath),
1060
+ relativeFilePath,
1061
1061
  frontmatter: result.data,
1062
1062
  body: content.trim(),
1063
1063
  validate
@@ -1134,6 +1134,16 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
1134
1134
  getBody() {
1135
1135
  return this.body;
1136
1136
  }
1137
+ withRelativeFilePath(newRelativeFilePath) {
1138
+ return new _RulesyncCommand({
1139
+ baseDir: this.getBaseDir(),
1140
+ relativeDirPath: this.getRelativeDirPath(),
1141
+ relativeFilePath: newRelativeFilePath,
1142
+ frontmatter: this.getFrontmatter(),
1143
+ body: this.getBody(),
1144
+ fileContent: this.getFileContent()
1145
+ });
1146
+ }
1137
1147
  validate() {
1138
1148
  if (!this.frontmatter) {
1139
1149
  return { success: true, error: null };
@@ -1164,11 +1174,10 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
1164
1174
  if (!result.success) {
1165
1175
  throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
1166
1176
  }
1167
- const filename = (0, import_node_path7.basename)(relativeFilePath);
1168
1177
  return new _RulesyncCommand({
1169
1178
  baseDir: process.cwd(),
1170
1179
  relativeDirPath: _RulesyncCommand.getSettablePaths().relativeDirPath,
1171
- relativeFilePath: filename,
1180
+ relativeFilePath,
1172
1181
  frontmatter: result.data,
1173
1182
  body: content.trim(),
1174
1183
  fileContent
@@ -1327,7 +1336,7 @@ ${body}${turboDirective}`;
1327
1336
  return new _AntigravityCommand({
1328
1337
  baseDir,
1329
1338
  relativeDirPath: _AntigravityCommand.getSettablePaths().relativeDirPath,
1330
- relativeFilePath: (0, import_node_path8.basename)(relativeFilePath),
1339
+ relativeFilePath,
1331
1340
  frontmatter: result.data,
1332
1341
  body: content.trim(),
1333
1342
  fileContent,
@@ -1473,7 +1482,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
1473
1482
  return new _ClaudecodeCommand({
1474
1483
  baseDir,
1475
1484
  relativeDirPath: paths.relativeDirPath,
1476
- relativeFilePath: (0, import_node_path9.basename)(relativeFilePath),
1485
+ relativeFilePath,
1477
1486
  frontmatter: result.data,
1478
1487
  body: content.trim(),
1479
1488
  validate
@@ -1563,7 +1572,7 @@ var ClineCommand = class _ClineCommand extends ToolCommand {
1563
1572
  return new _ClineCommand({
1564
1573
  baseDir,
1565
1574
  relativeDirPath: paths.relativeDirPath,
1566
- relativeFilePath: (0, import_node_path10.basename)(relativeFilePath),
1575
+ relativeFilePath,
1567
1576
  fileContent: content.trim(),
1568
1577
  validate
1569
1578
  });
@@ -1650,7 +1659,7 @@ var CodexcliCommand = class _CodexcliCommand extends ToolCommand {
1650
1659
  return new _CodexcliCommand({
1651
1660
  baseDir,
1652
1661
  relativeDirPath: paths.relativeDirPath,
1653
- relativeFilePath: (0, import_node_path11.basename)(relativeFilePath),
1662
+ relativeFilePath,
1654
1663
  fileContent: content.trim(),
1655
1664
  validate
1656
1665
  });
@@ -1783,7 +1792,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
1783
1792
  return new _CopilotCommand({
1784
1793
  baseDir,
1785
1794
  relativeDirPath: paths.relativeDirPath,
1786
- relativeFilePath: (0, import_node_path12.basename)(relativeFilePath),
1795
+ relativeFilePath,
1787
1796
  frontmatter: result.data,
1788
1797
  body: content.trim(),
1789
1798
  validate
@@ -1875,7 +1884,7 @@ var CursorCommand = class _CursorCommand extends ToolCommand {
1875
1884
  return new _CursorCommand({
1876
1885
  baseDir,
1877
1886
  relativeDirPath: paths.relativeDirPath,
1878
- relativeFilePath: (0, import_node_path13.basename)(relativeFilePath),
1887
+ relativeFilePath,
1879
1888
  fileContent: content.trim(),
1880
1889
  validate
1881
1890
  });
@@ -1930,7 +1939,7 @@ var FactorydroidCommand = class _FactorydroidCommand extends SimulatedCommand {
1930
1939
  return new _FactorydroidCommand({
1931
1940
  baseDir,
1932
1941
  relativeDirPath: paths.relativeDirPath,
1933
- relativeFilePath: (0, import_node_path14.basename)(relativeFilePath),
1942
+ relativeFilePath,
1934
1943
  frontmatter: result.data,
1935
1944
  body: content.trim(),
1936
1945
  validate
@@ -2062,7 +2071,7 @@ ${geminiFrontmatter.prompt}
2062
2071
  return new _GeminiCliCommand({
2063
2072
  baseDir,
2064
2073
  relativeDirPath: paths.relativeDirPath,
2065
- relativeFilePath: (0, import_node_path15.basename)(relativeFilePath),
2074
+ relativeFilePath,
2066
2075
  fileContent,
2067
2076
  validate
2068
2077
  });
@@ -2159,7 +2168,7 @@ var KiloCommand = class _KiloCommand extends ToolCommand {
2159
2168
  return new _KiloCommand({
2160
2169
  baseDir,
2161
2170
  relativeDirPath: paths.relativeDirPath,
2162
- relativeFilePath: (0, import_node_path16.basename)(relativeFilePath),
2171
+ relativeFilePath,
2163
2172
  fileContent: content.trim(),
2164
2173
  validate
2165
2174
  });
@@ -2240,7 +2249,7 @@ var KiroCommand = class _KiroCommand extends ToolCommand {
2240
2249
  return new _KiroCommand({
2241
2250
  baseDir,
2242
2251
  relativeDirPath: paths.relativeDirPath,
2243
- relativeFilePath: (0, import_node_path17.basename)(relativeFilePath),
2252
+ relativeFilePath,
2244
2253
  fileContent: content.trim(),
2245
2254
  validate
2246
2255
  });
@@ -2372,7 +2381,7 @@ var OpenCodeCommand = class _OpenCodeCommand extends ToolCommand {
2372
2381
  return new _OpenCodeCommand({
2373
2382
  baseDir,
2374
2383
  relativeDirPath: paths.relativeDirPath,
2375
- relativeFilePath: (0, import_node_path18.basename)(relativeFilePath),
2384
+ relativeFilePath,
2376
2385
  frontmatter: result.data,
2377
2386
  body: content.trim(),
2378
2387
  validate
@@ -2517,7 +2526,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
2517
2526
  return new _RooCommand({
2518
2527
  baseDir,
2519
2528
  relativeDirPath: _RooCommand.getSettablePaths().relativeDirPath,
2520
- relativeFilePath: (0, import_node_path19.basename)(relativeFilePath),
2529
+ relativeFilePath,
2521
2530
  frontmatter: result.data,
2522
2531
  body: content.trim(),
2523
2532
  fileContent,
@@ -2564,42 +2573,78 @@ var toolCommandFactories = /* @__PURE__ */ new Map([
2564
2573
  "agentsmd",
2565
2574
  {
2566
2575
  class: AgentsmdCommand,
2567
- meta: { extension: "md", supportsProject: true, supportsGlobal: false, isSimulated: true }
2576
+ meta: {
2577
+ extension: "md",
2578
+ supportsProject: true,
2579
+ supportsGlobal: false,
2580
+ isSimulated: true,
2581
+ supportsSubdirectory: false
2582
+ }
2568
2583
  }
2569
2584
  ],
2570
2585
  [
2571
2586
  "antigravity",
2572
2587
  {
2573
2588
  class: AntigravityCommand,
2574
- meta: { extension: "md", supportsProject: true, supportsGlobal: false, isSimulated: false }
2589
+ meta: {
2590
+ extension: "md",
2591
+ supportsProject: true,
2592
+ supportsGlobal: false,
2593
+ isSimulated: false,
2594
+ supportsSubdirectory: false
2595
+ }
2575
2596
  }
2576
2597
  ],
2577
2598
  [
2578
2599
  "claudecode",
2579
2600
  {
2580
2601
  class: ClaudecodeCommand,
2581
- meta: { extension: "md", supportsProject: true, supportsGlobal: true, isSimulated: false }
2602
+ meta: {
2603
+ extension: "md",
2604
+ supportsProject: true,
2605
+ supportsGlobal: true,
2606
+ isSimulated: false,
2607
+ supportsSubdirectory: true
2608
+ }
2582
2609
  }
2583
2610
  ],
2584
2611
  [
2585
2612
  "claudecode-legacy",
2586
2613
  {
2587
2614
  class: ClaudecodeCommand,
2588
- meta: { extension: "md", supportsProject: true, supportsGlobal: true, isSimulated: false }
2615
+ meta: {
2616
+ extension: "md",
2617
+ supportsProject: true,
2618
+ supportsGlobal: true,
2619
+ isSimulated: false,
2620
+ supportsSubdirectory: true
2621
+ }
2589
2622
  }
2590
2623
  ],
2591
2624
  [
2592
2625
  "cline",
2593
2626
  {
2594
2627
  class: ClineCommand,
2595
- meta: { extension: "md", supportsProject: true, supportsGlobal: true, isSimulated: false }
2628
+ meta: {
2629
+ extension: "md",
2630
+ supportsProject: true,
2631
+ supportsGlobal: true,
2632
+ isSimulated: false,
2633
+ supportsSubdirectory: false
2634
+ }
2596
2635
  }
2597
2636
  ],
2598
2637
  [
2599
2638
  "codexcli",
2600
2639
  {
2601
2640
  class: CodexcliCommand,
2602
- meta: { extension: "md", supportsProject: false, supportsGlobal: true, isSimulated: false }
2641
+ meta: {
2642
+ extension: "md",
2643
+ supportsProject: false,
2644
+ supportsGlobal: true,
2645
+ isSimulated: false,
2646
+ supportsSubdirectory: false
2647
+ }
2603
2648
  }
2604
2649
  ],
2605
2650
  [
@@ -2610,7 +2655,8 @@ var toolCommandFactories = /* @__PURE__ */ new Map([
2610
2655
  extension: "prompt.md",
2611
2656
  supportsProject: true,
2612
2657
  supportsGlobal: false,
2613
- isSimulated: false
2658
+ isSimulated: false,
2659
+ supportsSubdirectory: false
2614
2660
  }
2615
2661
  }
2616
2662
  ],
@@ -2618,49 +2664,91 @@ var toolCommandFactories = /* @__PURE__ */ new Map([
2618
2664
  "cursor",
2619
2665
  {
2620
2666
  class: CursorCommand,
2621
- meta: { extension: "md", supportsProject: true, supportsGlobal: true, isSimulated: false }
2667
+ meta: {
2668
+ extension: "md",
2669
+ supportsProject: true,
2670
+ supportsGlobal: true,
2671
+ isSimulated: false,
2672
+ supportsSubdirectory: false
2673
+ }
2622
2674
  }
2623
2675
  ],
2624
2676
  [
2625
2677
  "factorydroid",
2626
2678
  {
2627
2679
  class: FactorydroidCommand,
2628
- meta: { extension: "md", supportsProject: true, supportsGlobal: true, isSimulated: true }
2680
+ meta: {
2681
+ extension: "md",
2682
+ supportsProject: true,
2683
+ supportsGlobal: true,
2684
+ isSimulated: true,
2685
+ supportsSubdirectory: false
2686
+ }
2629
2687
  }
2630
2688
  ],
2631
2689
  [
2632
2690
  "geminicli",
2633
2691
  {
2634
2692
  class: GeminiCliCommand,
2635
- meta: { extension: "toml", supportsProject: true, supportsGlobal: true, isSimulated: false }
2693
+ meta: {
2694
+ extension: "toml",
2695
+ supportsProject: true,
2696
+ supportsGlobal: true,
2697
+ isSimulated: false,
2698
+ supportsSubdirectory: true
2699
+ }
2636
2700
  }
2637
2701
  ],
2638
2702
  [
2639
2703
  "kilo",
2640
2704
  {
2641
2705
  class: KiloCommand,
2642
- meta: { extension: "md", supportsProject: true, supportsGlobal: true, isSimulated: false }
2706
+ meta: {
2707
+ extension: "md",
2708
+ supportsProject: true,
2709
+ supportsGlobal: true,
2710
+ isSimulated: false,
2711
+ supportsSubdirectory: false
2712
+ }
2643
2713
  }
2644
2714
  ],
2645
2715
  [
2646
2716
  "kiro",
2647
2717
  {
2648
2718
  class: KiroCommand,
2649
- meta: { extension: "md", supportsProject: true, supportsGlobal: false, isSimulated: false }
2719
+ meta: {
2720
+ extension: "md",
2721
+ supportsProject: true,
2722
+ supportsGlobal: false,
2723
+ isSimulated: false,
2724
+ supportsSubdirectory: false
2725
+ }
2650
2726
  }
2651
2727
  ],
2652
2728
  [
2653
2729
  "opencode",
2654
2730
  {
2655
2731
  class: OpenCodeCommand,
2656
- meta: { extension: "md", supportsProject: true, supportsGlobal: true, isSimulated: false }
2732
+ meta: {
2733
+ extension: "md",
2734
+ supportsProject: true,
2735
+ supportsGlobal: true,
2736
+ isSimulated: false,
2737
+ supportsSubdirectory: true
2738
+ }
2657
2739
  }
2658
2740
  ],
2659
2741
  [
2660
2742
  "roo",
2661
2743
  {
2662
2744
  class: RooCommand,
2663
- meta: { extension: "md", supportsProject: true, supportsGlobal: false, isSimulated: false }
2745
+ meta: {
2746
+ extension: "md",
2747
+ supportsProject: true,
2748
+ supportsGlobal: false,
2749
+ isSimulated: false,
2750
+ supportsSubdirectory: true
2751
+ }
2664
2752
  }
2665
2753
  ]
2666
2754
  ]);
@@ -2713,13 +2801,27 @@ var CommandsProcessor = class extends FeatureProcessor {
2713
2801
  (file) => file instanceof RulesyncCommand
2714
2802
  );
2715
2803
  const factory = this.getFactory(this.toolTarget);
2804
+ const flattenedPathOrigins = /* @__PURE__ */ new Map();
2716
2805
  const toolCommands = rulesyncCommands.map((rulesyncCommand) => {
2717
2806
  if (!factory.class.isTargetedByRulesyncCommand(rulesyncCommand)) {
2718
2807
  return null;
2719
2808
  }
2809
+ const originalRelativePath = rulesyncCommand.getRelativeFilePath();
2810
+ const commandToConvert = factory.meta.supportsSubdirectory ? rulesyncCommand : this.flattenRelativeFilePath(rulesyncCommand);
2811
+ if (!factory.meta.supportsSubdirectory) {
2812
+ const flattenedPath = commandToConvert.getRelativeFilePath();
2813
+ const firstOrigin = flattenedPathOrigins.get(flattenedPath);
2814
+ if (firstOrigin && firstOrigin !== originalRelativePath) {
2815
+ logger.warn(
2816
+ `Command path collision detected while flattening for ${this.toolTarget}: "${firstOrigin}" and "${originalRelativePath}" both map to "${flattenedPath}". The later command will overwrite the earlier one.`
2817
+ );
2818
+ } else if (!firstOrigin) {
2819
+ flattenedPathOrigins.set(flattenedPath, originalRelativePath);
2820
+ }
2821
+ }
2720
2822
  return factory.class.fromRulesyncCommand({
2721
2823
  baseDir: this.baseDir,
2722
- rulesyncCommand,
2824
+ rulesyncCommand: commandToConvert,
2723
2825
  global: this.global
2724
2826
  });
2725
2827
  }).filter((command) => command !== null);
@@ -2734,17 +2836,26 @@ var CommandsProcessor = class extends FeatureProcessor {
2734
2836
  });
2735
2837
  return rulesyncCommands;
2736
2838
  }
2839
+ flattenRelativeFilePath(rulesyncCommand) {
2840
+ const flatPath = (0, import_node_path20.basename)(rulesyncCommand.getRelativeFilePath());
2841
+ if (flatPath === rulesyncCommand.getRelativeFilePath()) return rulesyncCommand;
2842
+ return rulesyncCommand.withRelativeFilePath(flatPath);
2843
+ }
2844
+ safeRelativePath(basePath, fullPath) {
2845
+ const rel = (0, import_node_path20.relative)(basePath, fullPath);
2846
+ checkPathTraversal({ relativePath: rel, intendedRootDir: basePath });
2847
+ return rel;
2848
+ }
2737
2849
  /**
2738
2850
  * Implementation of abstract method from FeatureProcessor
2739
2851
  * Load and parse rulesync command files from .rulesync/commands/ directory
2740
2852
  */
2741
2853
  async loadRulesyncFiles() {
2742
- const rulesyncCommandPaths = await findFilesByGlobs(
2743
- (0, import_node_path20.join)(RulesyncCommand.getSettablePaths().relativeDirPath, "*.md")
2744
- );
2854
+ const basePath = RulesyncCommand.getSettablePaths().relativeDirPath;
2855
+ const rulesyncCommandPaths = await findFilesByGlobs((0, import_node_path20.join)(basePath, "**", "*.md"));
2745
2856
  const rulesyncCommands = await Promise.all(
2746
2857
  rulesyncCommandPaths.map(
2747
- (path3) => RulesyncCommand.fromFile({ relativeFilePath: (0, import_node_path20.basename)(path3) })
2858
+ (path3) => RulesyncCommand.fromFile({ relativeFilePath: this.safeRelativePath(basePath, path3) })
2748
2859
  )
2749
2860
  );
2750
2861
  logger.debug(`Successfully loaded ${rulesyncCommands.length} rulesync commands`);
@@ -2759,15 +2870,15 @@ var CommandsProcessor = class extends FeatureProcessor {
2759
2870
  } = {}) {
2760
2871
  const factory = this.getFactory(this.toolTarget);
2761
2872
  const paths = factory.class.getSettablePaths({ global: this.global });
2762
- const commandFilePaths = await findFilesByGlobs(
2763
- (0, import_node_path20.join)(this.baseDir, paths.relativeDirPath, `*.${factory.meta.extension}`)
2764
- );
2873
+ const baseDirFull = (0, import_node_path20.join)(this.baseDir, paths.relativeDirPath);
2874
+ const globPattern = factory.meta.supportsSubdirectory ? (0, import_node_path20.join)(baseDirFull, "**", `*.${factory.meta.extension}`) : (0, import_node_path20.join)(baseDirFull, `*.${factory.meta.extension}`);
2875
+ const commandFilePaths = await findFilesByGlobs(globPattern);
2765
2876
  if (forDeletion) {
2766
2877
  const toolCommands2 = commandFilePaths.map(
2767
2878
  (path3) => factory.class.forDeletion({
2768
2879
  baseDir: this.baseDir,
2769
2880
  relativeDirPath: paths.relativeDirPath,
2770
- relativeFilePath: (0, import_node_path20.basename)(path3),
2881
+ relativeFilePath: this.safeRelativePath(baseDirFull, path3),
2771
2882
  global: this.global
2772
2883
  })
2773
2884
  ).filter((cmd) => cmd.isDeletable());
@@ -2778,7 +2889,7 @@ var CommandsProcessor = class extends FeatureProcessor {
2778
2889
  commandFilePaths.map(
2779
2890
  (path3) => factory.class.fromFile({
2780
2891
  baseDir: this.baseDir,
2781
- relativeFilePath: (0, import_node_path20.basename)(path3),
2892
+ relativeFilePath: this.safeRelativePath(baseDirFull, path3),
2782
2893
  global: this.global
2783
2894
  })
2784
2895
  )
@@ -12468,14 +12579,22 @@ var CopilotRuleFrontmatterSchema = import_mini47.z.object({
12468
12579
  var CopilotRule = class _CopilotRule extends ToolRule {
12469
12580
  frontmatter;
12470
12581
  body;
12471
- static getSettablePaths(_options = {}) {
12582
+ static getSettablePaths(options = {}) {
12583
+ if (options.global) {
12584
+ return {
12585
+ root: {
12586
+ relativeDirPath: buildToolPath(".copilot", ".", options.excludeToolDir),
12587
+ relativeFilePath: "copilot-instructions.md"
12588
+ }
12589
+ };
12590
+ }
12472
12591
  return {
12473
12592
  root: {
12474
- relativeDirPath: buildToolPath(".github", ".", _options.excludeToolDir),
12593
+ relativeDirPath: buildToolPath(".github", ".", options.excludeToolDir),
12475
12594
  relativeFilePath: "copilot-instructions.md"
12476
12595
  },
12477
12596
  nonRoot: {
12478
- relativeDirPath: buildToolPath(".github", "instructions", _options.excludeToolDir)
12597
+ relativeDirPath: buildToolPath(".github", "instructions", options.excludeToolDir)
12479
12598
  }
12480
12599
  };
12481
12600
  }
@@ -12526,10 +12645,12 @@ var CopilotRule = class _CopilotRule extends ToolRule {
12526
12645
  static fromRulesyncRule({
12527
12646
  baseDir = process.cwd(),
12528
12647
  rulesyncRule,
12529
- validate = true
12648
+ validate = true,
12649
+ global = false
12530
12650
  }) {
12531
12651
  const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
12532
12652
  const root = rulesyncFrontmatter.root;
12653
+ const paths = this.getSettablePaths({ global });
12533
12654
  const copilotFrontmatter = {
12534
12655
  description: rulesyncFrontmatter.description,
12535
12656
  applyTo: rulesyncFrontmatter.globs?.length ? rulesyncFrontmatter.globs.join(",") : void 0,
@@ -12541,12 +12662,15 @@ var CopilotRule = class _CopilotRule extends ToolRule {
12541
12662
  baseDir,
12542
12663
  frontmatter: copilotFrontmatter,
12543
12664
  body,
12544
- relativeDirPath: this.getSettablePaths().root.relativeDirPath,
12545
- relativeFilePath: this.getSettablePaths().root.relativeFilePath,
12665
+ relativeDirPath: paths.root.relativeDirPath,
12666
+ relativeFilePath: paths.root.relativeFilePath,
12546
12667
  validate,
12547
12668
  root
12548
12669
  });
12549
12670
  }
12671
+ if (!paths.nonRoot) {
12672
+ throw new Error(`nonRoot path is not set for ${rulesyncRule.getRelativeFilePath()}`);
12673
+ }
12550
12674
  const originalFileName = rulesyncRule.getRelativeFilePath();
12551
12675
  const nameWithoutExt = originalFileName.replace(/\.md$/, "");
12552
12676
  const newFileName = `${nameWithoutExt}.instructions.md`;
@@ -12554,7 +12678,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
12554
12678
  baseDir,
12555
12679
  frontmatter: copilotFrontmatter,
12556
12680
  body,
12557
- relativeDirPath: this.getSettablePaths().nonRoot.relativeDirPath,
12681
+ relativeDirPath: paths.nonRoot.relativeDirPath,
12558
12682
  relativeFilePath: newFileName,
12559
12683
  validate,
12560
12684
  root
@@ -12563,25 +12687,29 @@ var CopilotRule = class _CopilotRule extends ToolRule {
12563
12687
  static async fromFile({
12564
12688
  baseDir = process.cwd(),
12565
12689
  relativeFilePath,
12566
- validate = true
12690
+ validate = true,
12691
+ global = false
12567
12692
  }) {
12568
- const isRoot = relativeFilePath === "copilot-instructions.md";
12569
- const relativePath = isRoot ? (0, import_node_path96.join)(
12570
- this.getSettablePaths().root.relativeDirPath,
12571
- this.getSettablePaths().root.relativeFilePath
12572
- ) : (0, import_node_path96.join)(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
12573
- const fileContent = await readFileContent((0, import_node_path96.join)(baseDir, relativePath));
12693
+ const paths = this.getSettablePaths({ global });
12694
+ const isRoot = relativeFilePath === paths.root.relativeFilePath;
12574
12695
  if (isRoot) {
12696
+ const relativePath2 = (0, import_node_path96.join)(paths.root.relativeDirPath, paths.root.relativeFilePath);
12697
+ const fileContent2 = await readFileContent((0, import_node_path96.join)(baseDir, relativePath2));
12575
12698
  return new _CopilotRule({
12576
12699
  baseDir,
12577
- relativeDirPath: this.getSettablePaths().root.relativeDirPath,
12578
- relativeFilePath: this.getSettablePaths().root.relativeFilePath,
12700
+ relativeDirPath: paths.root.relativeDirPath,
12701
+ relativeFilePath: paths.root.relativeFilePath,
12579
12702
  frontmatter: {},
12580
- body: fileContent.trim(),
12703
+ body: fileContent2.trim(),
12581
12704
  validate,
12582
12705
  root: isRoot
12583
12706
  });
12584
12707
  }
12708
+ if (!paths.nonRoot) {
12709
+ throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
12710
+ }
12711
+ const relativePath = (0, import_node_path96.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
12712
+ const fileContent = await readFileContent((0, import_node_path96.join)(baseDir, relativePath));
12585
12713
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
12586
12714
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
12587
12715
  if (!result.success) {
@@ -12591,7 +12719,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
12591
12719
  }
12592
12720
  return new _CopilotRule({
12593
12721
  baseDir,
12594
- relativeDirPath: this.getSettablePaths().nonRoot.relativeDirPath,
12722
+ relativeDirPath: paths.nonRoot.relativeDirPath,
12595
12723
  relativeFilePath: relativeFilePath.endsWith(".instructions.md") ? relativeFilePath : relativeFilePath.replace(/\.md$/, ".instructions.md"),
12596
12724
  frontmatter: result.data,
12597
12725
  body: content.trim(),
@@ -12602,9 +12730,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
12602
12730
  static forDeletion({
12603
12731
  baseDir = process.cwd(),
12604
12732
  relativeDirPath,
12605
- relativeFilePath
12733
+ relativeFilePath,
12734
+ global = false
12606
12735
  }) {
12607
- const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
12736
+ const paths = this.getSettablePaths({ global });
12737
+ const isRoot = relativeFilePath === paths.root.relativeFilePath;
12608
12738
  return new _CopilotRule({
12609
12739
  baseDir,
12610
12740
  relativeDirPath,
@@ -13284,46 +13414,78 @@ var KiroRule = class _KiroRule extends ToolRule {
13284
13414
  // src/features/rules/opencode-rule.ts
13285
13415
  var import_node_path103 = require("path");
13286
13416
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
13287
- static getSettablePaths(_options = {}) {
13417
+ static getSettablePaths({
13418
+ global,
13419
+ excludeToolDir
13420
+ } = {}) {
13421
+ if (global) {
13422
+ return {
13423
+ root: {
13424
+ relativeDirPath: buildToolPath(".config/opencode", ".", excludeToolDir),
13425
+ relativeFilePath: "AGENTS.md"
13426
+ }
13427
+ };
13428
+ }
13288
13429
  return {
13289
13430
  root: {
13290
13431
  relativeDirPath: ".",
13291
13432
  relativeFilePath: "AGENTS.md"
13292
13433
  },
13293
13434
  nonRoot: {
13294
- relativeDirPath: buildToolPath(".opencode", "memories", _options.excludeToolDir)
13435
+ relativeDirPath: buildToolPath(".opencode", "memories", excludeToolDir)
13295
13436
  }
13296
13437
  };
13297
13438
  }
13298
13439
  static async fromFile({
13299
13440
  baseDir = process.cwd(),
13300
13441
  relativeFilePath,
13301
- validate = true
13442
+ validate = true,
13443
+ global = false
13302
13444
  }) {
13303
- const isRoot = relativeFilePath === "AGENTS.md";
13304
- const relativePath = isRoot ? "AGENTS.md" : (0, import_node_path103.join)(".opencode", "memories", relativeFilePath);
13445
+ const paths = this.getSettablePaths({ global });
13446
+ const isRoot = relativeFilePath === paths.root.relativeFilePath;
13447
+ if (isRoot) {
13448
+ const relativePath2 = paths.root.relativeFilePath;
13449
+ const fileContent2 = await readFileContent(
13450
+ (0, import_node_path103.join)(baseDir, paths.root.relativeDirPath, relativePath2)
13451
+ );
13452
+ return new _OpenCodeRule({
13453
+ baseDir,
13454
+ relativeDirPath: paths.root.relativeDirPath,
13455
+ relativeFilePath: paths.root.relativeFilePath,
13456
+ fileContent: fileContent2,
13457
+ validate,
13458
+ root: true
13459
+ });
13460
+ }
13461
+ if (!paths.nonRoot) {
13462
+ throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
13463
+ }
13464
+ const relativePath = (0, import_node_path103.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
13305
13465
  const fileContent = await readFileContent((0, import_node_path103.join)(baseDir, relativePath));
13306
13466
  return new _OpenCodeRule({
13307
13467
  baseDir,
13308
- relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
13309
- relativeFilePath: isRoot ? "AGENTS.md" : relativeFilePath,
13468
+ relativeDirPath: paths.nonRoot.relativeDirPath,
13469
+ relativeFilePath,
13470
+ fileContent,
13310
13471
  validate,
13311
- root: isRoot,
13312
- fileContent
13472
+ root: false
13313
13473
  });
13314
13474
  }
13315
13475
  static fromRulesyncRule({
13316
13476
  baseDir = process.cwd(),
13317
13477
  rulesyncRule,
13318
- validate = true
13478
+ validate = true,
13479
+ global = false
13319
13480
  }) {
13481
+ const paths = this.getSettablePaths({ global });
13320
13482
  return new _OpenCodeRule(
13321
13483
  this.buildToolRuleParamsDefault({
13322
13484
  baseDir,
13323
13485
  rulesyncRule,
13324
13486
  validate,
13325
- rootPath: this.getSettablePaths().root,
13326
- nonRootPath: this.getSettablePaths().nonRoot
13487
+ rootPath: paths.root,
13488
+ nonRootPath: paths.nonRoot
13327
13489
  })
13328
13490
  );
13329
13491
  }
@@ -13336,9 +13498,11 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
13336
13498
  static forDeletion({
13337
13499
  baseDir = process.cwd(),
13338
13500
  relativeDirPath,
13339
- relativeFilePath
13501
+ relativeFilePath,
13502
+ global = false
13340
13503
  }) {
13341
- const isRoot = relativeFilePath === "AGENTS.md" && relativeDirPath === ".";
13504
+ const paths = this.getSettablePaths({ global });
13505
+ const isRoot = relativeFilePath === paths.root.relativeFilePath;
13342
13506
  return new _OpenCodeRule({
13343
13507
  baseDir,
13344
13508
  relativeDirPath,
@@ -13796,42 +13960,66 @@ var toolRuleFactories = /* @__PURE__ */ new Map([
13796
13960
  "antigravity",
13797
13961
  {
13798
13962
  class: AntigravityRule,
13799
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
13963
+ meta: {
13964
+ extension: "md",
13965
+ supportsGlobal: false,
13966
+ ruleDiscoveryMode: "auto"
13967
+ }
13800
13968
  }
13801
13969
  ],
13802
13970
  [
13803
13971
  "augmentcode",
13804
13972
  {
13805
13973
  class: AugmentcodeRule,
13806
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
13974
+ meta: {
13975
+ extension: "md",
13976
+ supportsGlobal: false,
13977
+ ruleDiscoveryMode: "auto"
13978
+ }
13807
13979
  }
13808
13980
  ],
13809
13981
  [
13810
13982
  "augmentcode-legacy",
13811
13983
  {
13812
13984
  class: AugmentcodeLegacyRule,
13813
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
13985
+ meta: {
13986
+ extension: "md",
13987
+ supportsGlobal: false,
13988
+ ruleDiscoveryMode: "toon"
13989
+ }
13814
13990
  }
13815
13991
  ],
13816
13992
  [
13817
13993
  "claudecode",
13818
13994
  {
13819
13995
  class: ClaudecodeRule,
13820
- meta: { extension: "md", supportsGlobal: true, ruleDiscoveryMode: "auto" }
13996
+ meta: {
13997
+ extension: "md",
13998
+ supportsGlobal: true,
13999
+ ruleDiscoveryMode: "auto"
14000
+ }
13821
14001
  }
13822
14002
  ],
13823
14003
  [
13824
14004
  "claudecode-legacy",
13825
14005
  {
13826
14006
  class: ClaudecodeLegacyRule,
13827
- meta: { extension: "md", supportsGlobal: true, ruleDiscoveryMode: "claudecode-legacy" }
14007
+ meta: {
14008
+ extension: "md",
14009
+ supportsGlobal: true,
14010
+ ruleDiscoveryMode: "claudecode-legacy"
14011
+ }
13828
14012
  }
13829
14013
  ],
13830
14014
  [
13831
14015
  "cline",
13832
14016
  {
13833
14017
  class: ClineRule,
13834
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
14018
+ meta: {
14019
+ extension: "md",
14020
+ supportsGlobal: false,
14021
+ ruleDiscoveryMode: "auto"
14022
+ }
13835
14023
  }
13836
14024
  ],
13837
14025
  [
@@ -13854,7 +14042,7 @@ var toolRuleFactories = /* @__PURE__ */ new Map([
13854
14042
  class: CopilotRule,
13855
14043
  meta: {
13856
14044
  extension: "md",
13857
- supportsGlobal: false,
14045
+ supportsGlobal: true,
13858
14046
  ruleDiscoveryMode: "auto"
13859
14047
  }
13860
14048
  }
@@ -13904,42 +14092,66 @@ var toolRuleFactories = /* @__PURE__ */ new Map([
13904
14092
  "junie",
13905
14093
  {
13906
14094
  class: JunieRule,
13907
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
14095
+ meta: {
14096
+ extension: "md",
14097
+ supportsGlobal: false,
14098
+ ruleDiscoveryMode: "toon"
14099
+ }
13908
14100
  }
13909
14101
  ],
13910
14102
  [
13911
14103
  "kilo",
13912
14104
  {
13913
14105
  class: KiloRule,
13914
- meta: { extension: "md", supportsGlobal: true, ruleDiscoveryMode: "auto" }
14106
+ meta: {
14107
+ extension: "md",
14108
+ supportsGlobal: true,
14109
+ ruleDiscoveryMode: "auto"
14110
+ }
13915
14111
  }
13916
14112
  ],
13917
14113
  [
13918
14114
  "kiro",
13919
14115
  {
13920
14116
  class: KiroRule,
13921
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
14117
+ meta: {
14118
+ extension: "md",
14119
+ supportsGlobal: false,
14120
+ ruleDiscoveryMode: "toon"
14121
+ }
13922
14122
  }
13923
14123
  ],
13924
14124
  [
13925
14125
  "opencode",
13926
14126
  {
13927
14127
  class: OpenCodeRule,
13928
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
14128
+ meta: {
14129
+ extension: "md",
14130
+ supportsGlobal: true,
14131
+ ruleDiscoveryMode: "toon"
14132
+ }
13929
14133
  }
13930
14134
  ],
13931
14135
  [
13932
14136
  "qwencode",
13933
14137
  {
13934
14138
  class: QwencodeRule,
13935
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
14139
+ meta: {
14140
+ extension: "md",
14141
+ supportsGlobal: false,
14142
+ ruleDiscoveryMode: "toon"
14143
+ }
13936
14144
  }
13937
14145
  ],
13938
14146
  [
13939
14147
  "replit",
13940
14148
  {
13941
14149
  class: ReplitRule,
13942
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
14150
+ meta: {
14151
+ extension: "md",
14152
+ supportsGlobal: false,
14153
+ ruleDiscoveryMode: "auto"
14154
+ }
13943
14155
  }
13944
14156
  ],
13945
14157
  [
@@ -13961,14 +14173,22 @@ var toolRuleFactories = /* @__PURE__ */ new Map([
13961
14173
  "warp",
13962
14174
  {
13963
14175
  class: WarpRule,
13964
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
14176
+ meta: {
14177
+ extension: "md",
14178
+ supportsGlobal: false,
14179
+ ruleDiscoveryMode: "toon"
14180
+ }
13965
14181
  }
13966
14182
  ],
13967
14183
  [
13968
14184
  "windsurf",
13969
14185
  {
13970
14186
  class: WindsurfRule,
13971
- meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
14187
+ meta: {
14188
+ extension: "md",
14189
+ supportsGlobal: false,
14190
+ ruleDiscoveryMode: "auto"
14191
+ }
13972
14192
  }
13973
14193
  ]
13974
14194
  ]);
@@ -14116,7 +14336,9 @@ var RulesProcessor = class extends FeatureProcessor {
14116
14336
  })
14117
14337
  );
14118
14338
  } else if (this.toolTarget === "claudecode-legacy") {
14119
- const paths = ClaudecodeLegacyRule.getSettablePaths({ global: this.global });
14339
+ const paths = ClaudecodeLegacyRule.getSettablePaths({
14340
+ global: this.global
14341
+ });
14120
14342
  toolRules.push(
14121
14343
  new ClaudecodeLegacyRule({
14122
14344
  baseDir: this.baseDir,
@@ -14202,7 +14424,10 @@ var RulesProcessor = class extends FeatureProcessor {
14202
14424
  const rulesyncRules = await Promise.all(
14203
14425
  files.map((file) => {
14204
14426
  const relativeFilePath = (0, import_node_path109.relative)(rulesyncBaseDir, file);
14205
- checkPathTraversal({ relativePath: relativeFilePath, intendedRootDir: rulesyncBaseDir });
14427
+ checkPathTraversal({
14428
+ relativePath: relativeFilePath,
14429
+ intendedRootDir: rulesyncBaseDir
14430
+ });
14206
14431
  return RulesyncRule.fromFile({
14207
14432
  relativeFilePath
14208
14433
  });
@@ -14253,7 +14478,9 @@ var RulesProcessor = class extends FeatureProcessor {
14253
14478
  } = {}) {
14254
14479
  try {
14255
14480
  const factory = this.getFactory(this.toolTarget);
14256
- const settablePaths = factory.class.getSettablePaths({ global: this.global });
14481
+ const settablePaths = factory.class.getSettablePaths({
14482
+ global: this.global
14483
+ });
14257
14484
  const rootToolRules = await (async () => {
14258
14485
  if (!settablePaths.root) {
14259
14486
  return [];
@@ -14335,7 +14562,10 @@ var RulesProcessor = class extends FeatureProcessor {
14335
14562
  return await Promise.all(
14336
14563
  nonRootFilePaths.map((filePath) => {
14337
14564
  const relativeFilePath = (0, import_node_path109.relative)(nonRootBaseDir, filePath);
14338
- checkPathTraversal({ relativePath: relativeFilePath, intendedRootDir: nonRootBaseDir });
14565
+ checkPathTraversal({
14566
+ relativePath: relativeFilePath,
14567
+ intendedRootDir: nonRootBaseDir
14568
+ });
14339
14569
  return factory.class.fromFile({
14340
14570
  baseDir: this.baseDir,
14341
14571
  relativeFilePath,