rulesync 8.18.0 → 8.19.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.
@@ -1158,11 +1158,18 @@ import * as smolToml from "smol-toml";
1158
1158
  // src/utils/frontmatter.ts
1159
1159
  import matter from "gray-matter";
1160
1160
  import { dump, load } from "js-yaml";
1161
+
1162
+ // src/utils/type-guards.ts
1163
+ function isRecord(value) {
1164
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1165
+ }
1161
1166
  function isPlainObject(value) {
1162
- if (value === null || typeof value !== "object") return false;
1163
- const prototype = Object.getPrototypeOf(value);
1164
- return prototype === Object.prototype || prototype === null;
1167
+ if (!isRecord(value)) return false;
1168
+ const proto = Object.getPrototypeOf(value);
1169
+ return proto === null || proto === Object.prototype;
1165
1170
  }
1171
+
1172
+ // src/utils/frontmatter.ts
1166
1173
  function deepRemoveNullishValue(value) {
1167
1174
  if (value === null || value === void 0) {
1168
1175
  return void 0;
@@ -1753,11 +1760,6 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
1753
1760
  import { basename, join as join7 } from "path";
1754
1761
  import { z as z6 } from "zod/mini";
1755
1762
 
1756
- // src/utils/type-guards.ts
1757
- function isRecord(value) {
1758
- return typeof value === "object" && value !== null && !Array.isArray(value);
1759
- }
1760
-
1761
1763
  // src/features/commands/rulesync-command.ts
1762
1764
  import { join as join6 } from "path";
1763
1765
  import { z as z5 } from "zod/mini";
@@ -7760,7 +7762,7 @@ var ToolMcp = class extends ToolFile {
7760
7762
  super({
7761
7763
  ...rest,
7762
7764
  validate: true
7763
- // Skip validation during construction
7765
+ // ToolMcp runs subclass validation below when requested
7764
7766
  });
7765
7767
  if (rest.validate) {
7766
7768
  const result = this.validate();
@@ -7818,17 +7820,26 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
7818
7820
  return this.json;
7819
7821
  }
7820
7822
  /**
7821
- * In global mode, ~/.claude/.claude.json should not be deleted
7822
- * as it may contain other user settings.
7823
+ * In global mode, ~/.claude.json should not be deleted as it is the
7824
+ * user's primary Claude Code config and contains many other settings
7825
+ * managed by Claude Code itself (feature flags, project trust list,
7826
+ * hooks, user settings, model selection, etc.).
7823
7827
  * In local mode, .mcp.json can be safely deleted.
7824
7828
  */
7825
7829
  isDeletable() {
7826
7830
  return !this.global;
7827
7831
  }
7832
+ /**
7833
+ * Legacy global path used by rulesync ≤ v8.17.0. The documented store
7834
+ * is `~/.claude.json`; `fromFile` falls back here with a deprecation
7835
+ * warning (mirrors PR #333). Never modified or removed by rulesync.
7836
+ */
7837
+ static LEGACY_GLOBAL_DIR = ".claude";
7838
+ static LEGACY_GLOBAL_FILE = ".claude.json";
7828
7839
  static getSettablePaths({ global } = {}) {
7829
7840
  if (global) {
7830
7841
  return {
7831
- relativeDirPath: ".claude",
7842
+ relativeDirPath: ".",
7832
7843
  relativeFilePath: ".claude.json"
7833
7844
  };
7834
7845
  }
@@ -7840,19 +7851,52 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
7840
7851
  static async fromFile({
7841
7852
  outputRoot = process.cwd(),
7842
7853
  validate = true,
7843
- global = false
7854
+ global = false,
7855
+ logger
7844
7856
  }) {
7845
7857
  const paths = this.getSettablePaths({ global });
7846
- const fileContent = await readFileContentOrNull(
7847
- join49(outputRoot, paths.relativeDirPath, paths.relativeFilePath)
7848
- ) ?? '{"mcpServers":{}}';
7849
- const json = JSON.parse(fileContent);
7850
- const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
7858
+ const recommendedPath = join49(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
7859
+ if (await fileExists(recommendedPath)) {
7860
+ const fileContent = await readFileContent(recommendedPath);
7861
+ const json = JSON.parse(fileContent);
7862
+ const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
7863
+ return new _ClaudecodeMcp({
7864
+ outputRoot,
7865
+ relativeDirPath: paths.relativeDirPath,
7866
+ relativeFilePath: paths.relativeFilePath,
7867
+ fileContent: JSON.stringify(newJson, null, 2),
7868
+ validate,
7869
+ global
7870
+ });
7871
+ }
7872
+ if (global) {
7873
+ const legacyPath = join49(
7874
+ outputRoot,
7875
+ _ClaudecodeMcp.LEGACY_GLOBAL_DIR,
7876
+ _ClaudecodeMcp.LEGACY_GLOBAL_FILE
7877
+ );
7878
+ if (await fileExists(legacyPath)) {
7879
+ logger?.warn(
7880
+ `Warning: using deprecated path "${legacyPath}". Please migrate to "${recommendedPath}"`
7881
+ );
7882
+ const fileContent = await readFileContent(legacyPath);
7883
+ const json = JSON.parse(fileContent);
7884
+ const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
7885
+ return new _ClaudecodeMcp({
7886
+ outputRoot,
7887
+ relativeDirPath: _ClaudecodeMcp.LEGACY_GLOBAL_DIR,
7888
+ relativeFilePath: _ClaudecodeMcp.LEGACY_GLOBAL_FILE,
7889
+ fileContent: JSON.stringify(newJson, null, 2),
7890
+ validate,
7891
+ global
7892
+ });
7893
+ }
7894
+ }
7851
7895
  return new _ClaudecodeMcp({
7852
7896
  outputRoot,
7853
7897
  relativeDirPath: paths.relativeDirPath,
7854
7898
  relativeFilePath: paths.relativeFilePath,
7855
- fileContent: JSON.stringify(newJson, null, 2),
7899
+ fileContent: JSON.stringify({ mcpServers: {} }, null, 2),
7856
7900
  validate,
7857
7901
  global
7858
7902
  });
@@ -7881,7 +7925,7 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
7881
7925
  }
7882
7926
  toRulesyncMcp() {
7883
7927
  return this.toRulesyncMcpDefault({
7884
- fileContent: JSON.stringify({ mcpServers: this.json.mcpServers }, null, 2)
7928
+ fileContent: JSON.stringify({ mcpServers: this.json.mcpServers ?? {} }, null, 2)
7885
7929
  });
7886
7930
  }
7887
7931
  validate() {
@@ -7985,11 +8029,6 @@ import { join as join51 } from "path";
7985
8029
  import * as smolToml3 from "smol-toml";
7986
8030
  var MAX_REMOVE_EMPTY_ENTRIES_DEPTH = 32;
7987
8031
  var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
7988
- function isPlainObject2(value) {
7989
- if (!isRecord(value)) return false;
7990
- const proto = Object.getPrototypeOf(value);
7991
- return proto === null || proto === Object.prototype;
7992
- }
7993
8032
  function convertFromCodexFormat(codexMcp) {
7994
8033
  const result = {};
7995
8034
  for (const [name, config] of Object.entries(codexMcp)) {
@@ -8145,7 +8184,7 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
8145
8184
  for (const [key, value] of Object.entries(obj)) {
8146
8185
  if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
8147
8186
  if (value === null) continue;
8148
- if (isPlainObject2(value)) {
8187
+ if (isPlainObject(value)) {
8149
8188
  const cleaned = this.removeEmptyEntries(value, depth + 1);
8150
8189
  if (Object.keys(cleaned).length === 0) continue;
8151
8190
  filtered[key] = cleaned;
@@ -9991,7 +10030,8 @@ var McpProcessor = class extends FeatureProcessor {
9991
10030
  await factory.class.fromFile({
9992
10031
  outputRoot: this.outputRoot,
9993
10032
  validate: true,
9994
- global: this.global
10033
+ global: this.global,
10034
+ logger: this.logger
9995
10035
  })
9996
10036
  ];
9997
10037
  this.logger.debug(`Successfully loaded ${toolMcps.length} ${this.toolTarget} MCP files`);
@@ -19147,15 +19187,52 @@ var OpenCodeStyleSubagent = class extends ToolSubagent {
19147
19187
  // src/features/subagents/kilo-subagent.ts
19148
19188
  var KiloSubagentFrontmatterSchema = z71.looseObject({
19149
19189
  description: z71.optional(z71.string()),
19150
- // Kilo's documented default for user-defined agents is "all":
19151
- // available both as a top-level pick and as a subagent.
19152
19190
  mode: z71._default(z71.string(), "all"),
19153
- name: z71.optional(z71.string())
19191
+ name: z71.optional(z71.string()),
19192
+ displayName: z71.optional(z71.string()),
19193
+ deprecated: z71.optional(z71.boolean()),
19194
+ native: z71.optional(z71.boolean()),
19195
+ hidden: z71.optional(z71.boolean()),
19196
+ top_p: z71.optional(z71.number()),
19197
+ temperature: z71.optional(z71.number()),
19198
+ color: z71.optional(z71.string()),
19199
+ permission: z71.optional(z71.string()),
19200
+ model: z71.optional(z71.string()),
19201
+ variant: z71.optional(z71.string()),
19202
+ prompt: z71.optional(z71.string()),
19203
+ options: z71.optional(z71.looseObject({})),
19204
+ steps: z71.optional(z71.array(z71.looseObject({}))),
19205
+ disable: z71.optional(z71.boolean())
19154
19206
  });
19155
19207
  var KiloSubagent = class _KiloSubagent extends OpenCodeStyleSubagent {
19208
+ constructor(params) {
19209
+ super(params);
19210
+ if (params.validate !== false) {
19211
+ const result = this.validate();
19212
+ if (!result.success) {
19213
+ throw result.error;
19214
+ }
19215
+ }
19216
+ }
19156
19217
  getToolTarget() {
19157
19218
  return "kilo";
19158
19219
  }
19220
+ getFrontmatter() {
19221
+ return this.frontmatter;
19222
+ }
19223
+ validate() {
19224
+ const result = KiloSubagentFrontmatterSchema.safeParse(this.frontmatter);
19225
+ if (result.success) {
19226
+ this.frontmatter = result.data;
19227
+ return { success: true, error: null };
19228
+ }
19229
+ return {
19230
+ success: false,
19231
+ error: new Error(
19232
+ `Invalid frontmatter in ${join118(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
19233
+ )
19234
+ };
19235
+ }
19159
19236
  static getSettablePaths({
19160
19237
  global = false
19161
19238
  } = {}) {
@@ -19171,11 +19248,17 @@ var KiloSubagent = class _KiloSubagent extends OpenCodeStyleSubagent {
19171
19248
  }) {
19172
19249
  const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
19173
19250
  const kiloSection = rulesyncFrontmatter.kilo ?? {};
19174
- const kiloFrontmatter = KiloSubagentFrontmatterSchema.parse({
19251
+ const parseResult = KiloSubagentFrontmatterSchema.safeParse({
19175
19252
  ...kiloSection,
19176
19253
  description: rulesyncFrontmatter.description,
19177
19254
  ...rulesyncFrontmatter.name && { name: rulesyncFrontmatter.name }
19178
19255
  });
19256
+ if (!parseResult.success) {
19257
+ throw new Error(
19258
+ `Invalid frontmatter in ${rulesyncSubagent.getRelativeFilePath()}: ${formatError(parseResult.error)}`
19259
+ );
19260
+ }
19261
+ const kiloFrontmatter = parseResult.data;
19179
19262
  const body = rulesyncSubagent.getBody();
19180
19263
  const fileContent = stringifyFrontmatter(body, kiloFrontmatter);
19181
19264
  const paths = this.getSettablePaths({ global });
@@ -19486,7 +19569,8 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends OpenCodeStyleSubagent {
19486
19569
  static forDeletion({
19487
19570
  outputRoot = process.cwd(),
19488
19571
  relativeDirPath,
19489
- relativeFilePath
19572
+ relativeFilePath,
19573
+ global = false
19490
19574
  }) {
19491
19575
  return new _OpenCodeSubagent({
19492
19576
  outputRoot,
@@ -19495,7 +19579,8 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends OpenCodeStyleSubagent {
19495
19579
  frontmatter: { description: "", mode: "subagent" },
19496
19580
  body: "",
19497
19581
  fileContent: "",
19498
- validate: false
19582
+ validate: false,
19583
+ global
19499
19584
  });
19500
19585
  }
19501
19586
  };
@@ -21299,8 +21384,8 @@ var CopilotRuleFrontmatterSchema = z78.object({
21299
21384
  applyTo: z78.optional(z78.string()),
21300
21385
  excludeAgent: z78.optional(z78.union([z78.literal("code-review"), z78.literal("coding-agent")]))
21301
21386
  });
21302
- var normalizeRelativePath = (path4) => path4.replace(/\\/g, "/").replace(/\/+/g, "/");
21303
- var sameRelativePath = (leftDir, leftFile, rightDir, rightFile) => normalizeRelativePath(join133(leftDir, leftFile)) === normalizeRelativePath(join133(rightDir, rightFile));
21387
+ var normalizeRelativePath = (p) => toPosixPath(p).replace(/\/+/g, "/");
21388
+ var sameRelativePath = (left, right) => normalizeRelativePath(join133(left.dir, left.file)) === normalizeRelativePath(join133(right.dir, right.file));
21304
21389
  var CopilotRule = class _CopilotRule extends ToolRule {
21305
21390
  frontmatter;
21306
21391
  body;
@@ -21419,10 +21504,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
21419
21504
  }) {
21420
21505
  const paths = this.getSettablePaths({ global });
21421
21506
  const isRoot = relativeDirPath ? sameRelativePath(
21422
- relativeDirPath,
21423
- relativeFilePath,
21424
- paths.root.relativeDirPath,
21425
- paths.root.relativeFilePath
21507
+ { dir: relativeDirPath, file: relativeFilePath },
21508
+ { dir: paths.root.relativeDirPath, file: paths.root.relativeFilePath }
21426
21509
  ) : relativeFilePath === paths.root.relativeFilePath;
21427
21510
  const resolvedRelativeDirPath = relativeDirPath ?? (isRoot ? paths.root.relativeDirPath : paths.nonRoot?.relativeDirPath ?? paths.root.relativeDirPath);
21428
21511
  if (isRoot) {
@@ -21468,10 +21551,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
21468
21551
  }) {
21469
21552
  const paths = this.getSettablePaths({ global });
21470
21553
  const isRoot = sameRelativePath(
21471
- relativeDirPath,
21472
- relativeFilePath,
21473
- paths.root.relativeDirPath,
21474
- paths.root.relativeFilePath
21554
+ { dir: relativeDirPath, file: relativeFilePath },
21555
+ { dir: paths.root.relativeDirPath, file: paths.root.relativeFilePath }
21475
21556
  );
21476
21557
  return new _CopilotRule({
21477
21558
  outputRoot,
@@ -1191,11 +1191,18 @@ var smolToml = __toESM(require("smol-toml"), 1);
1191
1191
  // src/utils/frontmatter.ts
1192
1192
  var import_gray_matter = __toESM(require("gray-matter"), 1);
1193
1193
  var import_js_yaml = require("js-yaml");
1194
+
1195
+ // src/utils/type-guards.ts
1196
+ function isRecord(value) {
1197
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1198
+ }
1194
1199
  function isPlainObject(value) {
1195
- if (value === null || typeof value !== "object") return false;
1196
- const prototype = Object.getPrototypeOf(value);
1197
- return prototype === Object.prototype || prototype === null;
1200
+ if (!isRecord(value)) return false;
1201
+ const proto = Object.getPrototypeOf(value);
1202
+ return proto === null || proto === Object.prototype;
1198
1203
  }
1204
+
1205
+ // src/utils/frontmatter.ts
1199
1206
  function deepRemoveNullishValue(value) {
1200
1207
  if (value === null || value === void 0) {
1201
1208
  return void 0;
@@ -1786,11 +1793,6 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
1786
1793
  var import_node_path10 = require("path");
1787
1794
  var import_mini6 = require("zod/mini");
1788
1795
 
1789
- // src/utils/type-guards.ts
1790
- function isRecord(value) {
1791
- return typeof value === "object" && value !== null && !Array.isArray(value);
1792
- }
1793
-
1794
1796
  // src/features/commands/rulesync-command.ts
1795
1797
  var import_node_path9 = require("path");
1796
1798
  var import_mini5 = require("zod/mini");
@@ -7793,7 +7795,7 @@ var ToolMcp = class extends ToolFile {
7793
7795
  super({
7794
7796
  ...rest,
7795
7797
  validate: true
7796
- // Skip validation during construction
7798
+ // ToolMcp runs subclass validation below when requested
7797
7799
  });
7798
7800
  if (rest.validate) {
7799
7801
  const result = this.validate();
@@ -7851,17 +7853,26 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
7851
7853
  return this.json;
7852
7854
  }
7853
7855
  /**
7854
- * In global mode, ~/.claude/.claude.json should not be deleted
7855
- * as it may contain other user settings.
7856
+ * In global mode, ~/.claude.json should not be deleted as it is the
7857
+ * user's primary Claude Code config and contains many other settings
7858
+ * managed by Claude Code itself (feature flags, project trust list,
7859
+ * hooks, user settings, model selection, etc.).
7856
7860
  * In local mode, .mcp.json can be safely deleted.
7857
7861
  */
7858
7862
  isDeletable() {
7859
7863
  return !this.global;
7860
7864
  }
7865
+ /**
7866
+ * Legacy global path used by rulesync ≤ v8.17.0. The documented store
7867
+ * is `~/.claude.json`; `fromFile` falls back here with a deprecation
7868
+ * warning (mirrors PR #333). Never modified or removed by rulesync.
7869
+ */
7870
+ static LEGACY_GLOBAL_DIR = ".claude";
7871
+ static LEGACY_GLOBAL_FILE = ".claude.json";
7861
7872
  static getSettablePaths({ global } = {}) {
7862
7873
  if (global) {
7863
7874
  return {
7864
- relativeDirPath: ".claude",
7875
+ relativeDirPath: ".",
7865
7876
  relativeFilePath: ".claude.json"
7866
7877
  };
7867
7878
  }
@@ -7873,19 +7884,52 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
7873
7884
  static async fromFile({
7874
7885
  outputRoot = process.cwd(),
7875
7886
  validate = true,
7876
- global = false
7887
+ global = false,
7888
+ logger: logger5
7877
7889
  }) {
7878
7890
  const paths = this.getSettablePaths({ global });
7879
- const fileContent = await readFileContentOrNull(
7880
- (0, import_node_path52.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath)
7881
- ) ?? '{"mcpServers":{}}';
7882
- const json = JSON.parse(fileContent);
7883
- const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
7891
+ const recommendedPath = (0, import_node_path52.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
7892
+ if (await fileExists(recommendedPath)) {
7893
+ const fileContent = await readFileContent(recommendedPath);
7894
+ const json = JSON.parse(fileContent);
7895
+ const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
7896
+ return new _ClaudecodeMcp({
7897
+ outputRoot,
7898
+ relativeDirPath: paths.relativeDirPath,
7899
+ relativeFilePath: paths.relativeFilePath,
7900
+ fileContent: JSON.stringify(newJson, null, 2),
7901
+ validate,
7902
+ global
7903
+ });
7904
+ }
7905
+ if (global) {
7906
+ const legacyPath = (0, import_node_path52.join)(
7907
+ outputRoot,
7908
+ _ClaudecodeMcp.LEGACY_GLOBAL_DIR,
7909
+ _ClaudecodeMcp.LEGACY_GLOBAL_FILE
7910
+ );
7911
+ if (await fileExists(legacyPath)) {
7912
+ logger5?.warn(
7913
+ `Warning: using deprecated path "${legacyPath}". Please migrate to "${recommendedPath}"`
7914
+ );
7915
+ const fileContent = await readFileContent(legacyPath);
7916
+ const json = JSON.parse(fileContent);
7917
+ const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
7918
+ return new _ClaudecodeMcp({
7919
+ outputRoot,
7920
+ relativeDirPath: _ClaudecodeMcp.LEGACY_GLOBAL_DIR,
7921
+ relativeFilePath: _ClaudecodeMcp.LEGACY_GLOBAL_FILE,
7922
+ fileContent: JSON.stringify(newJson, null, 2),
7923
+ validate,
7924
+ global
7925
+ });
7926
+ }
7927
+ }
7884
7928
  return new _ClaudecodeMcp({
7885
7929
  outputRoot,
7886
7930
  relativeDirPath: paths.relativeDirPath,
7887
7931
  relativeFilePath: paths.relativeFilePath,
7888
- fileContent: JSON.stringify(newJson, null, 2),
7932
+ fileContent: JSON.stringify({ mcpServers: {} }, null, 2),
7889
7933
  validate,
7890
7934
  global
7891
7935
  });
@@ -7914,7 +7958,7 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
7914
7958
  }
7915
7959
  toRulesyncMcp() {
7916
7960
  return this.toRulesyncMcpDefault({
7917
- fileContent: JSON.stringify({ mcpServers: this.json.mcpServers }, null, 2)
7961
+ fileContent: JSON.stringify({ mcpServers: this.json.mcpServers ?? {} }, null, 2)
7918
7962
  });
7919
7963
  }
7920
7964
  validate() {
@@ -8018,11 +8062,6 @@ var import_node_path54 = require("path");
8018
8062
  var smolToml3 = __toESM(require("smol-toml"), 1);
8019
8063
  var MAX_REMOVE_EMPTY_ENTRIES_DEPTH = 32;
8020
8064
  var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
8021
- function isPlainObject2(value) {
8022
- if (!isRecord(value)) return false;
8023
- const proto = Object.getPrototypeOf(value);
8024
- return proto === null || proto === Object.prototype;
8025
- }
8026
8065
  function convertFromCodexFormat(codexMcp) {
8027
8066
  const result = {};
8028
8067
  for (const [name, config] of Object.entries(codexMcp)) {
@@ -8178,7 +8217,7 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
8178
8217
  for (const [key, value] of Object.entries(obj)) {
8179
8218
  if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
8180
8219
  if (value === null) continue;
8181
- if (isPlainObject2(value)) {
8220
+ if (isPlainObject(value)) {
8182
8221
  const cleaned = this.removeEmptyEntries(value, depth + 1);
8183
8222
  if (Object.keys(cleaned).length === 0) continue;
8184
8223
  filtered[key] = cleaned;
@@ -10024,7 +10063,8 @@ var McpProcessor = class extends FeatureProcessor {
10024
10063
  await factory.class.fromFile({
10025
10064
  outputRoot: this.outputRoot,
10026
10065
  validate: true,
10027
- global: this.global
10066
+ global: this.global,
10067
+ logger: this.logger
10028
10068
  })
10029
10069
  ];
10030
10070
  this.logger.debug(`Successfully loaded ${toolMcps.length} ${this.toolTarget} MCP files`);
@@ -19180,15 +19220,52 @@ var OpenCodeStyleSubagent = class extends ToolSubagent {
19180
19220
  // src/features/subagents/kilo-subagent.ts
19181
19221
  var KiloSubagentFrontmatterSchema = import_mini71.z.looseObject({
19182
19222
  description: import_mini71.z.optional(import_mini71.z.string()),
19183
- // Kilo's documented default for user-defined agents is "all":
19184
- // available both as a top-level pick and as a subagent.
19185
19223
  mode: import_mini71.z._default(import_mini71.z.string(), "all"),
19186
- name: import_mini71.z.optional(import_mini71.z.string())
19224
+ name: import_mini71.z.optional(import_mini71.z.string()),
19225
+ displayName: import_mini71.z.optional(import_mini71.z.string()),
19226
+ deprecated: import_mini71.z.optional(import_mini71.z.boolean()),
19227
+ native: import_mini71.z.optional(import_mini71.z.boolean()),
19228
+ hidden: import_mini71.z.optional(import_mini71.z.boolean()),
19229
+ top_p: import_mini71.z.optional(import_mini71.z.number()),
19230
+ temperature: import_mini71.z.optional(import_mini71.z.number()),
19231
+ color: import_mini71.z.optional(import_mini71.z.string()),
19232
+ permission: import_mini71.z.optional(import_mini71.z.string()),
19233
+ model: import_mini71.z.optional(import_mini71.z.string()),
19234
+ variant: import_mini71.z.optional(import_mini71.z.string()),
19235
+ prompt: import_mini71.z.optional(import_mini71.z.string()),
19236
+ options: import_mini71.z.optional(import_mini71.z.looseObject({})),
19237
+ steps: import_mini71.z.optional(import_mini71.z.array(import_mini71.z.looseObject({}))),
19238
+ disable: import_mini71.z.optional(import_mini71.z.boolean())
19187
19239
  });
19188
19240
  var KiloSubagent = class _KiloSubagent extends OpenCodeStyleSubagent {
19241
+ constructor(params) {
19242
+ super(params);
19243
+ if (params.validate !== false) {
19244
+ const result = this.validate();
19245
+ if (!result.success) {
19246
+ throw result.error;
19247
+ }
19248
+ }
19249
+ }
19189
19250
  getToolTarget() {
19190
19251
  return "kilo";
19191
19252
  }
19253
+ getFrontmatter() {
19254
+ return this.frontmatter;
19255
+ }
19256
+ validate() {
19257
+ const result = KiloSubagentFrontmatterSchema.safeParse(this.frontmatter);
19258
+ if (result.success) {
19259
+ this.frontmatter = result.data;
19260
+ return { success: true, error: null };
19261
+ }
19262
+ return {
19263
+ success: false,
19264
+ error: new Error(
19265
+ `Invalid frontmatter in ${(0, import_node_path121.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
19266
+ )
19267
+ };
19268
+ }
19192
19269
  static getSettablePaths({
19193
19270
  global = false
19194
19271
  } = {}) {
@@ -19204,11 +19281,17 @@ var KiloSubagent = class _KiloSubagent extends OpenCodeStyleSubagent {
19204
19281
  }) {
19205
19282
  const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
19206
19283
  const kiloSection = rulesyncFrontmatter.kilo ?? {};
19207
- const kiloFrontmatter = KiloSubagentFrontmatterSchema.parse({
19284
+ const parseResult = KiloSubagentFrontmatterSchema.safeParse({
19208
19285
  ...kiloSection,
19209
19286
  description: rulesyncFrontmatter.description,
19210
19287
  ...rulesyncFrontmatter.name && { name: rulesyncFrontmatter.name }
19211
19288
  });
19289
+ if (!parseResult.success) {
19290
+ throw new Error(
19291
+ `Invalid frontmatter in ${rulesyncSubagent.getRelativeFilePath()}: ${formatError(parseResult.error)}`
19292
+ );
19293
+ }
19294
+ const kiloFrontmatter = parseResult.data;
19212
19295
  const body = rulesyncSubagent.getBody();
19213
19296
  const fileContent = stringifyFrontmatter(body, kiloFrontmatter);
19214
19297
  const paths = this.getSettablePaths({ global });
@@ -19519,7 +19602,8 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends OpenCodeStyleSubagent {
19519
19602
  static forDeletion({
19520
19603
  outputRoot = process.cwd(),
19521
19604
  relativeDirPath,
19522
- relativeFilePath
19605
+ relativeFilePath,
19606
+ global = false
19523
19607
  }) {
19524
19608
  return new _OpenCodeSubagent({
19525
19609
  outputRoot,
@@ -19528,7 +19612,8 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends OpenCodeStyleSubagent {
19528
19612
  frontmatter: { description: "", mode: "subagent" },
19529
19613
  body: "",
19530
19614
  fileContent: "",
19531
- validate: false
19615
+ validate: false,
19616
+ global
19532
19617
  });
19533
19618
  }
19534
19619
  };
@@ -21332,8 +21417,8 @@ var CopilotRuleFrontmatterSchema = import_mini78.z.object({
21332
21417
  applyTo: import_mini78.z.optional(import_mini78.z.string()),
21333
21418
  excludeAgent: import_mini78.z.optional(import_mini78.z.union([import_mini78.z.literal("code-review"), import_mini78.z.literal("coding-agent")]))
21334
21419
  });
21335
- var normalizeRelativePath = (path5) => path5.replace(/\\/g, "/").replace(/\/+/g, "/");
21336
- var sameRelativePath = (leftDir, leftFile, rightDir, rightFile) => normalizeRelativePath((0, import_node_path136.join)(leftDir, leftFile)) === normalizeRelativePath((0, import_node_path136.join)(rightDir, rightFile));
21420
+ var normalizeRelativePath = (p) => toPosixPath(p).replace(/\/+/g, "/");
21421
+ var sameRelativePath = (left, right) => normalizeRelativePath((0, import_node_path136.join)(left.dir, left.file)) === normalizeRelativePath((0, import_node_path136.join)(right.dir, right.file));
21337
21422
  var CopilotRule = class _CopilotRule extends ToolRule {
21338
21423
  frontmatter;
21339
21424
  body;
@@ -21452,10 +21537,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
21452
21537
  }) {
21453
21538
  const paths = this.getSettablePaths({ global });
21454
21539
  const isRoot = relativeDirPath ? sameRelativePath(
21455
- relativeDirPath,
21456
- relativeFilePath,
21457
- paths.root.relativeDirPath,
21458
- paths.root.relativeFilePath
21540
+ { dir: relativeDirPath, file: relativeFilePath },
21541
+ { dir: paths.root.relativeDirPath, file: paths.root.relativeFilePath }
21459
21542
  ) : relativeFilePath === paths.root.relativeFilePath;
21460
21543
  const resolvedRelativeDirPath = relativeDirPath ?? (isRoot ? paths.root.relativeDirPath : paths.nonRoot?.relativeDirPath ?? paths.root.relativeDirPath);
21461
21544
  if (isRoot) {
@@ -21501,10 +21584,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
21501
21584
  }) {
21502
21585
  const paths = this.getSettablePaths({ global });
21503
21586
  const isRoot = sameRelativePath(
21504
- relativeDirPath,
21505
- relativeFilePath,
21506
- paths.root.relativeDirPath,
21507
- paths.root.relativeFilePath
21587
+ { dir: relativeDirPath, file: relativeFilePath },
21588
+ { dir: paths.root.relativeDirPath, file: paths.root.relativeFilePath }
21508
21589
  );
21509
21590
  return new _CopilotRule({
21510
21591
  outputRoot,
@@ -31793,7 +31874,7 @@ function wrapCommand({
31793
31874
  }
31794
31875
 
31795
31876
  // src/cli/index.ts
31796
- var getVersion = () => "8.18.0";
31877
+ var getVersion = () => "8.19.0";
31797
31878
  function wrapCommand2(name, errorCode, handler) {
31798
31879
  return wrapCommand({ name, errorCode, handler, getVersion });
31799
31880
  }
package/dist/cli/index.js CHANGED
@@ -79,7 +79,7 @@ import {
79
79
  stringifyFrontmatter,
80
80
  toPosixPath,
81
81
  writeFileContent
82
- } from "../chunk-KDGHMXTY.js";
82
+ } from "../chunk-66SPWRYP.js";
83
83
 
84
84
  // src/cli/index.ts
85
85
  import { Command } from "commander";
@@ -6485,7 +6485,7 @@ function wrapCommand({
6485
6485
  }
6486
6486
 
6487
6487
  // src/cli/index.ts
6488
- var getVersion = () => "8.18.0";
6488
+ var getVersion = () => "8.19.0";
6489
6489
  function wrapCommand2(name, errorCode, handler) {
6490
6490
  return wrapCommand({ name, errorCode, handler, getVersion });
6491
6491
  }
package/dist/index.cjs CHANGED
@@ -1064,11 +1064,18 @@ var smolToml = __toESM(require("smol-toml"), 1);
1064
1064
  // src/utils/frontmatter.ts
1065
1065
  var import_gray_matter = __toESM(require("gray-matter"), 1);
1066
1066
  var import_js_yaml = require("js-yaml");
1067
+
1068
+ // src/utils/type-guards.ts
1069
+ function isRecord(value) {
1070
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1071
+ }
1067
1072
  function isPlainObject(value) {
1068
- if (value === null || typeof value !== "object") return false;
1069
- const prototype = Object.getPrototypeOf(value);
1070
- return prototype === Object.prototype || prototype === null;
1073
+ if (!isRecord(value)) return false;
1074
+ const proto = Object.getPrototypeOf(value);
1075
+ return proto === null || proto === Object.prototype;
1071
1076
  }
1077
+
1078
+ // src/utils/frontmatter.ts
1072
1079
  function deepRemoveNullishValue(value) {
1073
1080
  if (value === null || value === void 0) {
1074
1081
  return void 0;
@@ -1659,11 +1666,6 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
1659
1666
  var import_node_path10 = require("path");
1660
1667
  var import_mini6 = require("zod/mini");
1661
1668
 
1662
- // src/utils/type-guards.ts
1663
- function isRecord(value) {
1664
- return typeof value === "object" && value !== null && !Array.isArray(value);
1665
- }
1666
-
1667
1669
  // src/features/commands/rulesync-command.ts
1668
1670
  var import_node_path9 = require("path");
1669
1671
  var import_mini5 = require("zod/mini");
@@ -7666,7 +7668,7 @@ var ToolMcp = class extends ToolFile {
7666
7668
  super({
7667
7669
  ...rest,
7668
7670
  validate: true
7669
- // Skip validation during construction
7671
+ // ToolMcp runs subclass validation below when requested
7670
7672
  });
7671
7673
  if (rest.validate) {
7672
7674
  const result = this.validate();
@@ -7724,17 +7726,26 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
7724
7726
  return this.json;
7725
7727
  }
7726
7728
  /**
7727
- * In global mode, ~/.claude/.claude.json should not be deleted
7728
- * as it may contain other user settings.
7729
+ * In global mode, ~/.claude.json should not be deleted as it is the
7730
+ * user's primary Claude Code config and contains many other settings
7731
+ * managed by Claude Code itself (feature flags, project trust list,
7732
+ * hooks, user settings, model selection, etc.).
7729
7733
  * In local mode, .mcp.json can be safely deleted.
7730
7734
  */
7731
7735
  isDeletable() {
7732
7736
  return !this.global;
7733
7737
  }
7738
+ /**
7739
+ * Legacy global path used by rulesync ≤ v8.17.0. The documented store
7740
+ * is `~/.claude.json`; `fromFile` falls back here with a deprecation
7741
+ * warning (mirrors PR #333). Never modified or removed by rulesync.
7742
+ */
7743
+ static LEGACY_GLOBAL_DIR = ".claude";
7744
+ static LEGACY_GLOBAL_FILE = ".claude.json";
7734
7745
  static getSettablePaths({ global } = {}) {
7735
7746
  if (global) {
7736
7747
  return {
7737
- relativeDirPath: ".claude",
7748
+ relativeDirPath: ".",
7738
7749
  relativeFilePath: ".claude.json"
7739
7750
  };
7740
7751
  }
@@ -7746,19 +7757,52 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
7746
7757
  static async fromFile({
7747
7758
  outputRoot = process.cwd(),
7748
7759
  validate = true,
7749
- global = false
7760
+ global = false,
7761
+ logger
7750
7762
  }) {
7751
7763
  const paths = this.getSettablePaths({ global });
7752
- const fileContent = await readFileContentOrNull(
7753
- (0, import_node_path52.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath)
7754
- ) ?? '{"mcpServers":{}}';
7755
- const json = JSON.parse(fileContent);
7756
- const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
7764
+ const recommendedPath = (0, import_node_path52.join)(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
7765
+ if (await fileExists(recommendedPath)) {
7766
+ const fileContent = await readFileContent(recommendedPath);
7767
+ const json = JSON.parse(fileContent);
7768
+ const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
7769
+ return new _ClaudecodeMcp({
7770
+ outputRoot,
7771
+ relativeDirPath: paths.relativeDirPath,
7772
+ relativeFilePath: paths.relativeFilePath,
7773
+ fileContent: JSON.stringify(newJson, null, 2),
7774
+ validate,
7775
+ global
7776
+ });
7777
+ }
7778
+ if (global) {
7779
+ const legacyPath = (0, import_node_path52.join)(
7780
+ outputRoot,
7781
+ _ClaudecodeMcp.LEGACY_GLOBAL_DIR,
7782
+ _ClaudecodeMcp.LEGACY_GLOBAL_FILE
7783
+ );
7784
+ if (await fileExists(legacyPath)) {
7785
+ logger?.warn(
7786
+ `Warning: using deprecated path "${legacyPath}". Please migrate to "${recommendedPath}"`
7787
+ );
7788
+ const fileContent = await readFileContent(legacyPath);
7789
+ const json = JSON.parse(fileContent);
7790
+ const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
7791
+ return new _ClaudecodeMcp({
7792
+ outputRoot,
7793
+ relativeDirPath: _ClaudecodeMcp.LEGACY_GLOBAL_DIR,
7794
+ relativeFilePath: _ClaudecodeMcp.LEGACY_GLOBAL_FILE,
7795
+ fileContent: JSON.stringify(newJson, null, 2),
7796
+ validate,
7797
+ global
7798
+ });
7799
+ }
7800
+ }
7757
7801
  return new _ClaudecodeMcp({
7758
7802
  outputRoot,
7759
7803
  relativeDirPath: paths.relativeDirPath,
7760
7804
  relativeFilePath: paths.relativeFilePath,
7761
- fileContent: JSON.stringify(newJson, null, 2),
7805
+ fileContent: JSON.stringify({ mcpServers: {} }, null, 2),
7762
7806
  validate,
7763
7807
  global
7764
7808
  });
@@ -7787,7 +7831,7 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
7787
7831
  }
7788
7832
  toRulesyncMcp() {
7789
7833
  return this.toRulesyncMcpDefault({
7790
- fileContent: JSON.stringify({ mcpServers: this.json.mcpServers }, null, 2)
7834
+ fileContent: JSON.stringify({ mcpServers: this.json.mcpServers ?? {} }, null, 2)
7791
7835
  });
7792
7836
  }
7793
7837
  validate() {
@@ -7891,11 +7935,6 @@ var import_node_path54 = require("path");
7891
7935
  var smolToml3 = __toESM(require("smol-toml"), 1);
7892
7936
  var MAX_REMOVE_EMPTY_ENTRIES_DEPTH = 32;
7893
7937
  var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
7894
- function isPlainObject2(value) {
7895
- if (!isRecord(value)) return false;
7896
- const proto = Object.getPrototypeOf(value);
7897
- return proto === null || proto === Object.prototype;
7898
- }
7899
7938
  function convertFromCodexFormat(codexMcp) {
7900
7939
  const result = {};
7901
7940
  for (const [name, config] of Object.entries(codexMcp)) {
@@ -8051,7 +8090,7 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
8051
8090
  for (const [key, value] of Object.entries(obj)) {
8052
8091
  if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
8053
8092
  if (value === null) continue;
8054
- if (isPlainObject2(value)) {
8093
+ if (isPlainObject(value)) {
8055
8094
  const cleaned = this.removeEmptyEntries(value, depth + 1);
8056
8095
  if (Object.keys(cleaned).length === 0) continue;
8057
8096
  filtered[key] = cleaned;
@@ -9897,7 +9936,8 @@ var McpProcessor = class extends FeatureProcessor {
9897
9936
  await factory.class.fromFile({
9898
9937
  outputRoot: this.outputRoot,
9899
9938
  validate: true,
9900
- global: this.global
9939
+ global: this.global,
9940
+ logger: this.logger
9901
9941
  })
9902
9942
  ];
9903
9943
  this.logger.debug(`Successfully loaded ${toolMcps.length} ${this.toolTarget} MCP files`);
@@ -19053,15 +19093,52 @@ var OpenCodeStyleSubagent = class extends ToolSubagent {
19053
19093
  // src/features/subagents/kilo-subagent.ts
19054
19094
  var KiloSubagentFrontmatterSchema = import_mini71.z.looseObject({
19055
19095
  description: import_mini71.z.optional(import_mini71.z.string()),
19056
- // Kilo's documented default for user-defined agents is "all":
19057
- // available both as a top-level pick and as a subagent.
19058
19096
  mode: import_mini71.z._default(import_mini71.z.string(), "all"),
19059
- name: import_mini71.z.optional(import_mini71.z.string())
19097
+ name: import_mini71.z.optional(import_mini71.z.string()),
19098
+ displayName: import_mini71.z.optional(import_mini71.z.string()),
19099
+ deprecated: import_mini71.z.optional(import_mini71.z.boolean()),
19100
+ native: import_mini71.z.optional(import_mini71.z.boolean()),
19101
+ hidden: import_mini71.z.optional(import_mini71.z.boolean()),
19102
+ top_p: import_mini71.z.optional(import_mini71.z.number()),
19103
+ temperature: import_mini71.z.optional(import_mini71.z.number()),
19104
+ color: import_mini71.z.optional(import_mini71.z.string()),
19105
+ permission: import_mini71.z.optional(import_mini71.z.string()),
19106
+ model: import_mini71.z.optional(import_mini71.z.string()),
19107
+ variant: import_mini71.z.optional(import_mini71.z.string()),
19108
+ prompt: import_mini71.z.optional(import_mini71.z.string()),
19109
+ options: import_mini71.z.optional(import_mini71.z.looseObject({})),
19110
+ steps: import_mini71.z.optional(import_mini71.z.array(import_mini71.z.looseObject({}))),
19111
+ disable: import_mini71.z.optional(import_mini71.z.boolean())
19060
19112
  });
19061
19113
  var KiloSubagent = class _KiloSubagent extends OpenCodeStyleSubagent {
19114
+ constructor(params) {
19115
+ super(params);
19116
+ if (params.validate !== false) {
19117
+ const result = this.validate();
19118
+ if (!result.success) {
19119
+ throw result.error;
19120
+ }
19121
+ }
19122
+ }
19062
19123
  getToolTarget() {
19063
19124
  return "kilo";
19064
19125
  }
19126
+ getFrontmatter() {
19127
+ return this.frontmatter;
19128
+ }
19129
+ validate() {
19130
+ const result = KiloSubagentFrontmatterSchema.safeParse(this.frontmatter);
19131
+ if (result.success) {
19132
+ this.frontmatter = result.data;
19133
+ return { success: true, error: null };
19134
+ }
19135
+ return {
19136
+ success: false,
19137
+ error: new Error(
19138
+ `Invalid frontmatter in ${(0, import_node_path121.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
19139
+ )
19140
+ };
19141
+ }
19065
19142
  static getSettablePaths({
19066
19143
  global = false
19067
19144
  } = {}) {
@@ -19077,11 +19154,17 @@ var KiloSubagent = class _KiloSubagent extends OpenCodeStyleSubagent {
19077
19154
  }) {
19078
19155
  const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
19079
19156
  const kiloSection = rulesyncFrontmatter.kilo ?? {};
19080
- const kiloFrontmatter = KiloSubagentFrontmatterSchema.parse({
19157
+ const parseResult = KiloSubagentFrontmatterSchema.safeParse({
19081
19158
  ...kiloSection,
19082
19159
  description: rulesyncFrontmatter.description,
19083
19160
  ...rulesyncFrontmatter.name && { name: rulesyncFrontmatter.name }
19084
19161
  });
19162
+ if (!parseResult.success) {
19163
+ throw new Error(
19164
+ `Invalid frontmatter in ${rulesyncSubagent.getRelativeFilePath()}: ${formatError(parseResult.error)}`
19165
+ );
19166
+ }
19167
+ const kiloFrontmatter = parseResult.data;
19085
19168
  const body = rulesyncSubagent.getBody();
19086
19169
  const fileContent = stringifyFrontmatter(body, kiloFrontmatter);
19087
19170
  const paths = this.getSettablePaths({ global });
@@ -19392,7 +19475,8 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends OpenCodeStyleSubagent {
19392
19475
  static forDeletion({
19393
19476
  outputRoot = process.cwd(),
19394
19477
  relativeDirPath,
19395
- relativeFilePath
19478
+ relativeFilePath,
19479
+ global = false
19396
19480
  }) {
19397
19481
  return new _OpenCodeSubagent({
19398
19482
  outputRoot,
@@ -19401,7 +19485,8 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends OpenCodeStyleSubagent {
19401
19485
  frontmatter: { description: "", mode: "subagent" },
19402
19486
  body: "",
19403
19487
  fileContent: "",
19404
- validate: false
19488
+ validate: false,
19489
+ global
19405
19490
  });
19406
19491
  }
19407
19492
  };
@@ -21205,8 +21290,8 @@ var CopilotRuleFrontmatterSchema = import_mini78.z.object({
21205
21290
  applyTo: import_mini78.z.optional(import_mini78.z.string()),
21206
21291
  excludeAgent: import_mini78.z.optional(import_mini78.z.union([import_mini78.z.literal("code-review"), import_mini78.z.literal("coding-agent")]))
21207
21292
  });
21208
- var normalizeRelativePath = (path4) => path4.replace(/\\/g, "/").replace(/\/+/g, "/");
21209
- var sameRelativePath = (leftDir, leftFile, rightDir, rightFile) => normalizeRelativePath((0, import_node_path136.join)(leftDir, leftFile)) === normalizeRelativePath((0, import_node_path136.join)(rightDir, rightFile));
21293
+ var normalizeRelativePath = (p) => toPosixPath(p).replace(/\/+/g, "/");
21294
+ var sameRelativePath = (left, right) => normalizeRelativePath((0, import_node_path136.join)(left.dir, left.file)) === normalizeRelativePath((0, import_node_path136.join)(right.dir, right.file));
21210
21295
  var CopilotRule = class _CopilotRule extends ToolRule {
21211
21296
  frontmatter;
21212
21297
  body;
@@ -21325,10 +21410,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
21325
21410
  }) {
21326
21411
  const paths = this.getSettablePaths({ global });
21327
21412
  const isRoot = relativeDirPath ? sameRelativePath(
21328
- relativeDirPath,
21329
- relativeFilePath,
21330
- paths.root.relativeDirPath,
21331
- paths.root.relativeFilePath
21413
+ { dir: relativeDirPath, file: relativeFilePath },
21414
+ { dir: paths.root.relativeDirPath, file: paths.root.relativeFilePath }
21332
21415
  ) : relativeFilePath === paths.root.relativeFilePath;
21333
21416
  const resolvedRelativeDirPath = relativeDirPath ?? (isRoot ? paths.root.relativeDirPath : paths.nonRoot?.relativeDirPath ?? paths.root.relativeDirPath);
21334
21417
  if (isRoot) {
@@ -21374,10 +21457,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
21374
21457
  }) {
21375
21458
  const paths = this.getSettablePaths({ global });
21376
21459
  const isRoot = sameRelativePath(
21377
- relativeDirPath,
21378
- relativeFilePath,
21379
- paths.root.relativeDirPath,
21380
- paths.root.relativeFilePath
21460
+ { dir: relativeDirPath, file: relativeFilePath },
21461
+ { dir: paths.root.relativeDirPath, file: paths.root.relativeFilePath }
21381
21462
  );
21382
21463
  return new _CopilotRule({
21383
21464
  outputRoot,
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  convertFromTool,
8
8
  generate,
9
9
  importFromTool
10
- } from "./chunk-KDGHMXTY.js";
10
+ } from "./chunk-66SPWRYP.js";
11
11
 
12
12
  // src/index.ts
13
13
  async function generate2(options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "8.18.0",
3
+ "version": "8.19.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",