rulesync 9.6.1 → 9.6.3

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.
@@ -12617,6 +12617,13 @@ function mapOauthFromCodex(oauth) {
12617
12617
  }
12618
12618
  return result;
12619
12619
  }
12620
+ const CODEX_MCP_SERVER_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
12621
+ function normalizeCodexMcpServerName(name) {
12622
+ if (PROTOTYPE_POLLUTION_KEYS.has(name)) return null;
12623
+ if (CODEX_MCP_SERVER_NAME_PATTERN.test(name)) return name;
12624
+ const normalizedName = name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
12625
+ return normalizedName && !PROTOTYPE_POLLUTION_KEYS.has(normalizedName) ? normalizedName : null;
12626
+ }
12620
12627
  function convertFromCodexFormat(codexMcp) {
12621
12628
  const result = {};
12622
12629
  for (const [name, config] of Object.entries(codexMcp)) {
@@ -12639,8 +12646,13 @@ function convertFromCodexFormat(codexMcp) {
12639
12646
  }
12640
12647
  function convertToCodexFormat(mcpServers) {
12641
12648
  const result = {};
12649
+ const originalNames = /* @__PURE__ */ new Map();
12642
12650
  for (const [name, config] of Object.entries(mcpServers)) {
12643
- if (PROTOTYPE_POLLUTION_KEYS.has(name)) continue;
12651
+ const codexName = normalizeCodexMcpServerName(name);
12652
+ if (codexName === null) {
12653
+ warnWithFallback(void 0, `MCP server "${name}" could not be normalized to a valid Codex MCP server name and was skipped.`);
12654
+ continue;
12655
+ }
12644
12656
  if (!isRecord(config)) continue;
12645
12657
  const converted = {};
12646
12658
  for (const [key, value] of Object.entries(config)) {
@@ -12654,7 +12666,10 @@ function convertToCodexFormat(mcpServers) {
12654
12666
  else warnWithFallback(void 0, `[CodexCliMcp] Skipping invalid value type for mapped key '${key}': expected string array, got ${typeof value}`);
12655
12667
  } else converted[key] = value;
12656
12668
  }
12657
- result[name] = converted;
12669
+ const previousName = originalNames.get(codexName);
12670
+ if (previousName !== void 0) warnWithFallback(void 0, `Codex MCP server name collision: "${previousName}" and "${name}" both normalize to "${codexName}". Only the last processed server will be used.`);
12671
+ originalNames.set(codexName, name);
12672
+ result[codexName] = converted;
12658
12673
  }
12659
12674
  return result;
12660
12675
  }
@@ -36610,30 +36625,31 @@ var RovodevRule = class RovodevRule extends ToolRule {
36610
36625
  });
36611
36626
  }
36612
36627
  /**
36613
- * Mirror the primary `.rovodev/AGENTS.md` root rule to `./AGENTS.md` so project
36614
- * memory stays discoverable at the repo root. Empty when `rootRule` is not the primary root.
36628
+ * Root-mirror contract: rovodev mirrors its primary `.rovodev/AGENTS.md` root
36629
+ * rule to `./AGENTS.md` so project memory stays discoverable at the repo root.
36630
+ * Generation (`getMirrorFiles`) and deletion (`getMirrorDeletionGlobs`) are
36631
+ * bundled in one object so they cannot drift out of symmetry. The processor
36632
+ * keys off this method's mere presence to decide the tool mirrors at all.
36615
36633
  */
36616
- static getRootMirrorFiles({ outputRoot, rootRule, content }) {
36617
- if (!(rootRule instanceof RovodevRule)) return [];
36618
- const primary = this.getSettablePaths({ global: false }).root;
36619
- if (rootRule.getRelativeDirPath() !== primary.relativeDirPath || rootRule.getRelativeFilePath() !== primary.relativeFilePath) return [];
36620
- return [new RovodevRule({
36621
- outputRoot,
36622
- relativeDirPath: ".",
36623
- relativeFilePath: ROVODEV_RULE_FILE_NAME,
36624
- fileContent: content,
36625
- validate: true,
36626
- root: true
36627
- })];
36628
- }
36629
- /**
36630
- * Globs for mirror deletion: the `./AGENTS.md` mirror (`mirrorGlob`) is deleted
36631
- * only when the primary `.rovodev/AGENTS.md` (`primaryGlob`) still exists.
36632
- */
36633
- static getRootMirrorDeletionGlobs({ outputRoot }) {
36634
+ static getRootMirror() {
36634
36635
  return {
36635
- primaryGlob: join(outputRoot, ROVODEV_DIR, ROVODEV_RULE_FILE_NAME),
36636
- mirrorGlob: join(outputRoot, ROVODEV_RULE_FILE_NAME)
36636
+ getMirrorFiles: ({ outputRoot, rootRule, content }) => {
36637
+ if (!(rootRule instanceof RovodevRule)) return [];
36638
+ const primary = RovodevRule.getSettablePaths({ global: false }).root;
36639
+ if (rootRule.getRelativeDirPath() !== primary.relativeDirPath || rootRule.getRelativeFilePath() !== primary.relativeFilePath) return [];
36640
+ return [new RovodevRule({
36641
+ outputRoot,
36642
+ relativeDirPath: ".",
36643
+ relativeFilePath: ROVODEV_RULE_FILE_NAME,
36644
+ fileContent: content,
36645
+ validate: true,
36646
+ root: true
36647
+ })];
36648
+ },
36649
+ getMirrorDeletionGlobs: ({ outputRoot }) => ({
36650
+ primaryGlob: join(outputRoot, ROVODEV_DIR, ROVODEV_RULE_FILE_NAME),
36651
+ mirrorGlob: join(outputRoot, ROVODEV_RULE_FILE_NAME)
36652
+ })
36637
36653
  };
36638
36654
  }
36639
36655
  /** Glob for the `separate-local-file` deletion; rovodev writes it at project root, not under `.rovodev/`. */
@@ -37256,8 +37272,7 @@ const toolRuleFactories = /* @__PURE__ */ new Map([
37256
37272
  skills: { skillClass: RovodevSkill }
37257
37273
  },
37258
37274
  localRootMode: "separate-local-file",
37259
- localRootFileName: "AGENTS.local.md",
37260
- mirrorsRootToAgentsMd: true
37275
+ localRootFileName: "AGENTS.local.md"
37261
37276
  }
37262
37277
  }],
37263
37278
  ["takt", {
@@ -37444,7 +37459,8 @@ var RulesProcessor = class extends FeatureProcessor {
37444
37459
  if (!rootRule) return;
37445
37460
  const newContent = this.generateReferenceSectionFromMeta(meta, toolRules) + (!meta.createsSeparateConventionsRule && meta.additionalConventions ? this.generateAdditionalConventionsSectionFromMeta(meta) : "") + rootRule.getFileContent();
37446
37461
  rootRule.setFileContent(newContent);
37447
- if (meta.mirrorsRootToAgentsMd && !this.global && factory.class.getRootMirrorFiles) toolRules.push(...factory.class.getRootMirrorFiles({
37462
+ const rootMirror = factory.class.getRootMirror?.();
37463
+ if (rootMirror && !this.global) toolRules.push(...rootMirror.getMirrorFiles({
37448
37464
  outputRoot: this.outputRoot,
37449
37465
  rootRule,
37450
37466
  content: newContent
@@ -37686,8 +37702,9 @@ As this project's AI coding tool, you must follow the additional conventions bel
37686
37702
  })();
37687
37703
  this.logger.debug(`Found ${localRootToolRules.length} local root tool rule files for deletion`);
37688
37704
  const rootMirrorDeletionRules = await (async () => {
37689
- if (!forDeletion || this.global || !factory.meta.mirrorsRootToAgentsMd || !factory.class.getRootMirrorDeletionGlobs) return [];
37690
- const { primaryGlob, mirrorGlob } = factory.class.getRootMirrorDeletionGlobs({ outputRoot: this.outputRoot });
37705
+ const rootMirror = factory.class.getRootMirror?.();
37706
+ if (!forDeletion || this.global || !rootMirror) return [];
37707
+ const { primaryGlob, mirrorGlob } = rootMirror.getMirrorDeletionGlobs({ outputRoot: this.outputRoot });
37691
37708
  if ((await findFilesByGlobs(primaryGlob)).length === 0) return [];
37692
37709
  const mirrorPaths = await findFilesByGlobs(mirrorGlob);
37693
37710
  return buildDeletionRulesFromPaths(mirrorPaths);
@@ -38125,13 +38142,13 @@ const sharedFileKey = (path) => {
38125
38142
  const file = path.relativeFilePath.replace(/\\/g, "/");
38126
38143
  return dir === "" || dir === "." ? file : `${dir}/${file}`;
38127
38144
  };
38128
- const settablePathsForScope = (cls, global) => {
38145
+ const settablePathsForScope = ({ cls, global }) => {
38129
38146
  const paths = [];
38130
38147
  let settable;
38131
38148
  try {
38132
38149
  settable = cls.getSettablePaths?.({ global });
38133
38150
  } catch {
38134
- return paths;
38151
+ settable = void 0;
38135
38152
  }
38136
38153
  if (settable?.relativeFilePath) paths.push({
38137
38154
  relativeDirPath: settable.relativeDirPath ?? ".",
@@ -38141,16 +38158,22 @@ const settablePathsForScope = (cls, global) => {
38141
38158
  paths.push(settable.root);
38142
38159
  for (const alt of settable.alternativeRoots ?? []) paths.push(alt);
38143
38160
  }
38144
- let extra;
38161
+ let extra = [];
38145
38162
  try {
38146
38163
  extra = cls.getExtraSharedWritePaths?.({ global }) ?? [];
38147
38164
  } catch {
38148
- return paths;
38165
+ extra = [];
38149
38166
  }
38150
38167
  for (const path of extra) if (path.relativeFilePath) paths.push(path);
38151
38168
  return paths;
38152
38169
  };
38153
- const collectFactoryPaths = (factory) => [...settablePathsForScope(factory.class, false), ...settablePathsForScope(factory.class, true)];
38170
+ const collectFactoryPaths = (factory) => [...settablePathsForScope({
38171
+ cls: factory.class,
38172
+ global: false
38173
+ }), ...settablePathsForScope({
38174
+ cls: factory.class,
38175
+ global: true
38176
+ })];
38154
38177
  /**
38155
38178
  * Derive, from the processor registry, every on-disk file that two or more
38156
38179
  * features read-modify-write. Source of truth the generation step graph's
@@ -38526,7 +38549,7 @@ function computeRootFileOwnership(params) {
38526
38549
  const paths = factory.class.getSettablePaths({ global: params.global });
38527
38550
  if ("root" in paths && paths.root) register(paths.root.relativeDirPath, paths.root.relativeFilePath, target);
38528
38551
  if ("alternativeRoots" in paths && paths.alternativeRoots) for (const alt of paths.alternativeRoots) register(alt.relativeDirPath, alt.relativeFilePath, target);
38529
- if (!params.global && factory.meta.mirrorsRootToAgentsMd) register(".", AGENTSMD_RULE_FILE_NAME, target);
38552
+ if (!params.global && factory.class.getRootMirror) register(".", AGENTSMD_RULE_FILE_NAME, target);
38530
38553
  }
38531
38554
  return ownerByPath;
38532
38555
  }
@@ -39127,4 +39150,4 @@ async function importPermissionsCore(params) {
39127
39150
  //#endregion
39128
39151
  export { removeTempDirectory as $, RulesyncCommand as A, checkPathTraversal as B, RulesyncHooks as C, RULESYNC_RULES_RELATIVE_DIR_PATH as Ct, CLAUDECODE_MEMORIES_DIR_NAME as D, formatError as Dt, CLAUDECODE_LOCAL_RULE_FILE_NAME as E, RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH as Et, findControlCharacter as F, findFilesByGlobs as G, directoryExists as H, ConsoleLogger as I, isSymlink as J, getFileSize as K, JsonLogger as L, stringifyFrontmatter as M, loadYaml as N, CLAUDECODE_SETTINGS_LOCAL_FILE_NAME as O, ALL_FEATURES as Ot, ConfigResolver as P, removeFile as Q, CLIError as R, HooksProcessor as S, RULESYNC_RELATIVE_DIR_PATH as St, CLAUDECODE_DIR as T, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH as Tt, ensureDir as U, createTempDirectory as V, fileExists as W, readFileContent as X, listDirectoryFiles as Y, removeDirectory as Z, RulesyncPermissions as _, RULESYNC_MCP_RELATIVE_FILE_PATH as _t, convertFromTool as a, MAX_FILE_SIZE as at, IgnoreProcessor as b, RULESYNC_PERMISSIONS_FILE_NAME as bt, RulesyncRuleFrontmatterSchema as c, RULESYNC_COMMANDS_RELATIVE_DIR_PATH as ct, RulesyncSubagentFrontmatterSchema as d, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH as dt, toPosixPath as et, SkillsProcessor as f, RULESYNC_HOOKS_FILE_NAME as ft, SKILL_FILE_NAME as g, RULESYNC_MCP_FILE_NAME as gt, RulesyncSkillFrontmatterSchema as h, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH as ht, getProcessorRegistryEntry as i, ToolTargetSchema as it, RulesyncCommandFrontmatterSchema as j, CLAUDECODE_SKILLS_DIR_PATH as k, ALL_FEATURES_WITH_WILDCARD as kt, SubagentsProcessor as l, RULESYNC_CONFIG_RELATIVE_FILE_PATH as lt, RulesyncSkill as m, RULESYNC_IGNORE_RELATIVE_FILE_PATH as mt, checkRulesyncDirExists as n, ALL_TOOL_TARGETS as nt, RulesProcessor as o, RULESYNC_AIIGNORE_FILE_NAME as ot, getLocalSkillDirNames as p, RULESYNC_HOOKS_RELATIVE_FILE_PATH as pt, getHomeDirectory as q, generate as r, ALL_TOOL_TARGETS_WITH_WILDCARD as rt, RulesyncRule as s, RULESYNC_AIIGNORE_RELATIVE_FILE_PATH as st, importFromTool as t, writeFileContent as tt, RulesyncSubagent as u, RULESYNC_CONFIG_SCHEMA_URL as ut, McpProcessor as v, RULESYNC_MCP_SCHEMA_URL as vt, CommandsProcessor as w, RULESYNC_SKILLS_RELATIVE_DIR_PATH as wt, RulesyncIgnore as x, RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH as xt, RulesyncMcp as y, RULESYNC_OVERVIEW_FILE_NAME as yt, ErrorCodes as z };
39129
39152
 
39130
- //# sourceMappingURL=import-tTMN0WRi.js.map
39153
+ //# sourceMappingURL=import-A1yGuzwv.js.map