rulesync 7.4.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
  )
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  generate,
7
7
  importFromTool,
8
8
  logger
9
- } from "./chunk-UCC3WPDL.js";
9
+ } from "./chunk-WZ7IUX6M.js";
10
10
 
11
11
  // src/index.ts
12
12
  async function generate2(options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "7.4.0",
3
+ "version": "7.5.0",
4
4
  "description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
5
5
  "keywords": [
6
6
  "ai",