rulesync 12.0.0 → 13.0.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/README.md CHANGED
@@ -86,41 +86,41 @@ The tables below show whether each tool supports a given feature (✅ = supporte
86
86
 
87
87
  <!-- SUPPORTED_TOOLS_AI:BEGIN -->
88
88
 
89
- | Tool | rules | ignore | mcp | commands | subagents | skills | hooks | permissions |
90
- | ---------------------- | :---: | :----: | :-: | :------: | :-------: | :----: | :---: | :---------: |
91
- | Amp | ✅ | | ✅ | | | ✅ | | ✅ |
92
- | Claude Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
93
- | Codex CLI | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
94
- | GitHub Copilot | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | |
95
- | GitHub Copilot CLI | ✅ | | ✅ | | ✅ | ✅ | ✅ | |
96
- | Goose | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
97
- | Hermes Agent | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
98
- | Grok CLI | ✅ | | ✅ | | ✅ | ✅ | ✅ | ✅ |
99
- | Cursor | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
100
- | deepagents-cli | ✅ | | ✅ | | ✅ | ✅ | ✅ | |
101
- | Factory Droid | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
102
- | OpenCode | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
103
- | Cline | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅ |
104
- | Kilo Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
105
- | Roo Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | |
106
- | Rovodev (Atlassian) | ✅ | | ✅ | ✅ | ✅ | ✅ | | ✅ |
107
- | Takt | ✅ | | ✅ | ✅ | ✅ | ✅ | | ✅ |
108
- | Vibe Code | ✅ | ✅ | ✅ | | ✅ | ✅ | ✅ | ✅ |
109
- | Qwen Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
110
- | Reasonix | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
111
- | Kiro ⚠️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
112
- | Kiro CLI | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
113
- | Kiro IDE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
114
- | Google Antigravity IDE | ✅ | | ✅ | ✅ | | ✅ | ✅ | ✅ |
115
- | Google Antigravity CLI | ✅ | ✅ | ✅ | ✅ | | ✅ | ✅ | ✅ |
116
- | JetBrains AI Assistant | ✅ | ✅ | | | | ✅ | | |
117
- | JetBrains Junie | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
118
- | AugmentCode | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
119
- | Devin Desktop | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
120
- | Warp | ✅ | ✅ | ✅ | | | ✅ | | ✅ |
121
- | Replit | ✅ | | | | | ✅ | | |
122
- | Pi Coding Agent | ✅ | | | ✅ | | ✅ | | |
123
- | Zed | ✅ | ✅ | ✅ | | | ✅ | | ✅ |
89
+ | Tool | rules | ignore | mcp | commands | subagents | skills | hooks | permissions | checks |
90
+ | ---------------------- | :---: | :----: | :-: | :------: | :-------: | :----: | :---: | :---------: | :----: |
91
+ | Amp | ✅ | | ✅ | | | ✅ | | ✅ | ✅ |
92
+ | Claude Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
93
+ | Codex CLI | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
94
+ | GitHub Copilot | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | | |
95
+ | GitHub Copilot CLI | ✅ | | ✅ | | ✅ | ✅ | ✅ | | |
96
+ | Goose | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
97
+ | Hermes Agent | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
98
+ | Grok CLI | ✅ | | ✅ | | ✅ | ✅ | ✅ | ✅ | |
99
+ | Cursor | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
100
+ | deepagents-cli | ✅ | | ✅ | | ✅ | ✅ | ✅ | | |
101
+ | Factory Droid | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
102
+ | OpenCode | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
103
+ | Cline | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅ | |
104
+ | Kilo Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
105
+ | Roo Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | |
106
+ | Rovodev (Atlassian) | ✅ | | ✅ | ✅ | ✅ | ✅ | | ✅ | |
107
+ | Takt | ✅ | | ✅ | ✅ | ✅ | ✅ | | ✅ | |
108
+ | Vibe Code | ✅ | ✅ | ✅ | | ✅ | ✅ | ✅ | ✅ | |
109
+ | Qwen Code | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
110
+ | Reasonix | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
111
+ | Kiro ⚠️ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
112
+ | Kiro CLI | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
113
+ | Kiro IDE | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
114
+ | Google Antigravity IDE | ✅ | | ✅ | ✅ | | ✅ | ✅ | ✅ | |
115
+ | Google Antigravity CLI | ✅ | ✅ | ✅ | ✅ | | ✅ | ✅ | ✅ | |
116
+ | JetBrains AI Assistant | ✅ | ✅ | | | | ✅ | | | |
117
+ | JetBrains Junie | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
118
+ | AugmentCode | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
119
+ | Devin Desktop | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
120
+ | Warp | ✅ | ✅ | ✅ | | | ✅ | | ✅ | |
121
+ | Replit | ✅ | | | | | ✅ | | | |
122
+ | Pi Coding Agent | ✅ | | | ✅ | | ✅ | | | |
123
+ | Zed | ✅ | ✅ | ✅ | | | ✅ | | ✅ | |
124
124
 
125
125
  <!-- SUPPORTED_TOOLS_AI:END -->
126
126
 
@@ -128,10 +128,10 @@ The tables below show whether each tool supports a given feature (✅ = supporte
128
128
 
129
129
  <!-- SUPPORTED_TOOLS_STANDARD:BEGIN -->
130
130
 
131
- | Tool | rules | ignore | mcp | commands | subagents | skills | hooks | permissions |
132
- | ------------ | :---: | :----: | :-: | :------: | :-------: | :----: | :---: | :---------: |
133
- | AGENTS.md | ✅ | | | ✅ | ✅ | ✅ | | |
134
- | AgentsSkills | | | | | | ✅ | | |
131
+ | Tool | rules | ignore | mcp | commands | subagents | skills | hooks | permissions | checks |
132
+ | ------------ | :---: | :----: | :-: | :------: | :-------: | :----: | :---: | :---------: | :----: |
133
+ | AGENTS.md | ✅ | | | ✅ | ✅ | ✅ | | | |
134
+ | AgentsSkills | | | | | | ✅ | | | |
135
135
 
136
136
  <!-- SUPPORTED_TOOLS_STANDARD:END -->
137
137
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_import = require("../import-C0N0Lo_F.cjs");
2
+ const require_import = require("../import-nbmxtKYi.cjs");
3
3
  let commander = require("commander");
4
4
  let zod_mini = require("zod/mini");
5
5
  let node_path = require("node:path");
@@ -8,11 +8,11 @@ let node_os = require("node:os");
8
8
  node_os = require_import.__toESM(node_os, 1);
9
9
  let node_util = require("node:util");
10
10
  let js_yaml = require("js-yaml");
11
+ let node_crypto = require("node:crypto");
12
+ node_crypto = require_import.__toESM(node_crypto, 1);
11
13
  let es_toolkit_promise = require("es-toolkit/promise");
12
14
  let _octokit_request_error = require("@octokit/request-error");
13
15
  let _octokit_rest = require("@octokit/rest");
14
- let node_crypto = require("node:crypto");
15
- node_crypto = require_import.__toESM(node_crypto, 1);
16
16
  let node_child_process = require("node:child_process");
17
17
  let fastmcp = require("fastmcp");
18
18
  let node_fs = require("node:fs");
@@ -36,7 +36,7 @@ const parseCommaSeparatedList = (value) => value.split(",").map((s) => s.trim())
36
36
  * Calculate the total count from a result object
37
37
  */
38
38
  function calculateTotalCount(result) {
39
- return result.rulesCount + result.ignoreCount + result.mcpCount + result.commandsCount + result.subagentsCount + result.skillsCount + result.hooksCount + result.permissionsCount;
39
+ return result.rulesCount + result.ignoreCount + result.mcpCount + result.commandsCount + result.subagentsCount + result.skillsCount + result.hooksCount + result.permissionsCount + result.checksCount;
40
40
  }
41
41
  //#endregion
42
42
  //#region src/cli/commands/convert.ts
@@ -82,7 +82,8 @@ async function convertCommand(logger, options) {
82
82
  subagents: { count: result.subagentsCount },
83
83
  skills: { count: result.skillsCount },
84
84
  hooks: { count: result.hooksCount },
85
- permissions: { count: result.permissionsCount }
85
+ permissions: { count: result.permissionsCount },
86
+ checks: { count: result.checksCount }
86
87
  });
87
88
  logger.captureData("totalFiles", totalConverted);
88
89
  }
@@ -95,6 +96,7 @@ async function convertCommand(logger, options) {
95
96
  if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
96
97
  if (result.hooksCount > 0) parts.push(`${result.hooksCount} hooks`);
97
98
  if (result.permissionsCount > 0) parts.push(`${result.permissionsCount} permissions`);
99
+ if (result.checksCount > 0) parts.push(`${result.checksCount} checks`);
98
100
  const summary = `${modePrefix}${isPreview ? "Would convert" : "Converted"} ${totalConverted} file(s) total from ${fromTool} to ${toTools.join(", ")} (${parts.join(" + ")})`;
99
101
  if (isPreview) logger.info(summary);
100
102
  else logger.success(summary);
@@ -541,6 +543,7 @@ const FEATURE_PATHS = {
541
543
  commands: ["commands"],
542
544
  subagents: ["subagents"],
543
545
  skills: ["skills"],
546
+ checks: ["checks"],
544
547
  ignore: [require_import.RULESYNC_AIIGNORE_FILE_NAME],
545
548
  mcp: [require_import.RULESYNC_MCP_FILE_NAME, require_import.RULESYNC_MCP_JSONC_FILE_NAME],
546
549
  hooks: [require_import.RULESYNC_HOOKS_FILE_NAME, require_import.RULESYNC_HOOKS_JSONC_FILE_NAME],
@@ -626,6 +629,16 @@ async function convertFetchedFilesToRulesync(params) {
626
629
  logger
627
630
  })
628
631
  },
632
+ {
633
+ feature: "checks",
634
+ getTargets: () => require_import.ChecksProcessor.getToolTargets({ global: false }),
635
+ createProcessor: () => new require_import.ChecksProcessor({
636
+ outputRoot: tempDir,
637
+ toolTarget: target,
638
+ global: false,
639
+ logger
640
+ })
641
+ },
629
642
  {
630
643
  feature: "ignore",
631
644
  getTargets: () => require_import.IgnoreProcessor.getToolTargets(),
@@ -949,6 +962,10 @@ function getToolPathMapping(target) {
949
962
  const factory = require_import.SkillsProcessor.getFactory(target);
950
963
  if (factory) mapping.skills = factory.class.getSettablePaths({ global: false }).relativeDirPath;
951
964
  }
965
+ if (require_import.ChecksProcessor.getToolTargets({ global: false }).includes(target)) {
966
+ const factory = require_import.ChecksProcessor.getFactory(target);
967
+ if (factory) mapping.checks = factory.class.getSettablePaths({ global: false }).relativeDirPath;
968
+ }
952
969
  return mapping;
953
970
  }
954
971
  /**
@@ -972,6 +989,10 @@ function mapToToolPath(relativePath, toolPaths) {
972
989
  const restPath = relativePath.substring(7);
973
990
  if (toolPaths.skills) return (0, node_path.join)(toolPaths.skills, restPath);
974
991
  }
992
+ if (relativePath.startsWith("checks/")) {
993
+ const restPath = relativePath.substring(7);
994
+ if (toolPaths.checks) return (0, node_path.join)(toolPaths.checks, restPath);
995
+ }
975
996
  return relativePath;
976
997
  }
977
998
  /**
@@ -1047,6 +1068,7 @@ const FEATURE_DEBUG_MESSAGES = {
1047
1068
  subagents: "Generating subagent files...",
1048
1069
  skills: "Generating skill files...",
1049
1070
  hooks: "Generating hooks...",
1071
+ checks: "Generating check files...",
1050
1072
  rules: "Generating rule files..."
1051
1073
  };
1052
1074
  const FEATURE_DEBUG_ORDER = [
@@ -1056,6 +1078,7 @@ const FEATURE_DEBUG_ORDER = [
1056
1078
  "subagents",
1057
1079
  "skills",
1058
1080
  "hooks",
1081
+ "checks",
1059
1082
  "rules"
1060
1083
  ];
1061
1084
  function logFeatureDebugMessages(logger, features) {
@@ -1099,6 +1122,10 @@ function buildSummaryParts(result) {
1099
1122
  {
1100
1123
  count: result.permissionsCount,
1101
1124
  label: "permissions"
1125
+ },
1126
+ {
1127
+ count: result.checksCount,
1128
+ label: "checks"
1102
1129
  }
1103
1130
  ];
1104
1131
  const parts = [];
@@ -1149,6 +1176,10 @@ async function generateCommand(logger, options) {
1149
1176
  count: result.permissionsCount,
1150
1177
  paths: result.permissionsPaths
1151
1178
  },
1179
+ checks: {
1180
+ count: result.checksCount,
1181
+ paths: result.checksPaths
1182
+ },
1152
1183
  rules: {
1153
1184
  count: result.rulesCount,
1154
1185
  paths: result.rulesPaths
@@ -1162,7 +1193,8 @@ async function generateCommand(logger, options) {
1162
1193
  subagents: (count) => `${count === 1 ? "subagent" : "subagents"}`,
1163
1194
  skills: (count) => `${count === 1 ? "skill" : "skills"}`,
1164
1195
  hooks: (count) => `${count === 1 ? "hooks file" : "hooks files"}`,
1165
- permissions: (count) => `${count === 1 ? "permissions file" : "permissions files"}`
1196
+ permissions: (count) => `${count === 1 ? "permissions file" : "permissions files"}`,
1197
+ checks: (count) => `${count === 1 ? "check" : "checks"}`
1166
1198
  };
1167
1199
  for (const [feature, data] of Object.entries(featureResults)) logFeatureResult(logger, {
1168
1200
  count: data.count,
@@ -1263,13 +1295,16 @@ const deriveRulesEntries = () => {
1263
1295
  for (const root of [paths.root, ...paths.alternativeRoots ?? []]) if (root) pushEntry(entries, target, "rules", fileToGlob(root.relativeDirPath, root.relativeFilePath));
1264
1296
  const nonRootDir = paths.nonRoot?.relativeDirPath;
1265
1297
  if (nonRootDir && nonRootDir !== ".") pushEntry(entries, target, "rules", dirToGlob(nonRootDir));
1298
+ const classWithExtraFiles = factory.class;
1299
+ if (classWithExtraFiles.getExtraFixedFiles) for (const file of classWithExtraFiles.getExtraFixedFiles({ global: false })) pushEntry(entries, target, "rules", fileToGlob(file.relativeDirPath, file.relativeFilePath));
1266
1300
  }
1267
1301
  return entries;
1268
1302
  };
1269
1303
  const DIR_FEATURES = /* @__PURE__ */ new Set([
1270
1304
  "commands",
1271
1305
  "skills",
1272
- "subagents"
1306
+ "subagents",
1307
+ "checks"
1273
1308
  ]);
1274
1309
  const FILE_FEATURES = /* @__PURE__ */ new Set([
1275
1310
  "mcp",
@@ -1292,7 +1327,8 @@ const DERIVED_FEATURES = [
1292
1327
  "mcp",
1293
1328
  "hooks",
1294
1329
  "permissions",
1295
- "ignore"
1330
+ "ignore",
1331
+ "checks"
1296
1332
  ];
1297
1333
  const deriveAllGitignoreEntriesUnfiltered = () => DERIVED_FEATURES.flatMap((feature) => deriveFeatureGitignoreEntries(feature));
1298
1334
  const deriveAllGitignoreEntries = () => deriveAllGitignoreEntriesUnfiltered().filter((tag) => !DERIVED_PATHS_NOT_GITIGNORED.has(tag.entry));
@@ -1383,6 +1419,16 @@ const GITIGNORE_ENTRY_REGISTRY = [
1383
1419
  feature: "rules",
1384
1420
  entry: "**/.augment-guidelines"
1385
1421
  },
1422
+ {
1423
+ target: "devin",
1424
+ feature: "commands",
1425
+ entry: "**/.devin/workflows/"
1426
+ },
1427
+ {
1428
+ target: "junie",
1429
+ feature: "rules",
1430
+ entry: "**/.junie/memories/"
1431
+ },
1386
1432
  {
1387
1433
  target: "rovodev",
1388
1434
  feature: "skills",
@@ -1431,7 +1477,7 @@ const GITIGNORE_ENTRY_REGISTRY = [
1431
1477
  {
1432
1478
  target: "codexcli",
1433
1479
  feature: "permissions",
1434
- entry: `**/${require_import.CODEXCLI_DIR}/rules/`
1480
+ entry: `**/${require_import.CODEXCLI_DIR}/rules/${require_import.CODEXCLI_BASH_RULES_FILE_NAME}`
1435
1481
  }
1436
1482
  ],
1437
1483
  ...deriveAllGitignoreEntries(),
@@ -1740,7 +1786,8 @@ async function importCommand(logger, options) {
1740
1786
  subagents: { count: result.subagentsCount },
1741
1787
  skills: { count: result.skillsCount },
1742
1788
  hooks: { count: result.hooksCount },
1743
- permissions: { count: result.permissionsCount }
1789
+ permissions: { count: result.permissionsCount },
1790
+ checks: { count: result.checksCount }
1744
1791
  });
1745
1792
  logger.captureData("totalFiles", totalImported);
1746
1793
  }
@@ -1753,6 +1800,7 @@ async function importCommand(logger, options) {
1753
1800
  if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
1754
1801
  if (result.hooksCount > 0) parts.push(`${result.hooksCount} hooks`);
1755
1802
  if (result.permissionsCount > 0) parts.push(`${result.permissionsCount} permissions`);
1803
+ if (result.checksCount > 0) parts.push(`${result.checksCount} checks`);
1756
1804
  logger.success(`Imported ${totalImported} file(s) total (${parts.join(" + ")})`);
1757
1805
  }
1758
1806
  //#endregion
@@ -4424,6 +4472,172 @@ async function runGhInstall(logger, options) {
4424
4472
  else logger.success(`All gh sources up to date (${result.sourcesProcessed} checked).`);
4425
4473
  }
4426
4474
  //#endregion
4475
+ //#region src/mcp/checks.ts
4476
+ const logger$4 = new require_import.ConsoleLogger({
4477
+ verbose: false,
4478
+ silent: true
4479
+ });
4480
+ const maxCheckSizeBytes = 1024 * 1024;
4481
+ const maxChecksCount = 1e3;
4482
+ /**
4483
+ * Tool to list all checks from .rulesync/checks/*.md
4484
+ */
4485
+ async function listChecks() {
4486
+ const checksDir = (0, node_path.join)(process.cwd(), require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH);
4487
+ try {
4488
+ const mdFiles = (await require_import.listDirectoryFiles(checksDir)).filter((file) => file.endsWith(".md"));
4489
+ return (await Promise.all(mdFiles.map(async (file) => {
4490
+ try {
4491
+ const check = await require_import.RulesyncCheck.fromFile({
4492
+ relativeFilePath: file,
4493
+ validate: true
4494
+ });
4495
+ return {
4496
+ relativePathFromCwd: (0, node_path.join)(require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH, file),
4497
+ frontmatter: check.getFrontmatter()
4498
+ };
4499
+ } catch (error) {
4500
+ logger$4.error(`Failed to read check file ${file}: ${require_import.formatError(error)}`);
4501
+ return null;
4502
+ }
4503
+ }))).filter((check) => check !== null);
4504
+ } catch (error) {
4505
+ logger$4.error(`Failed to read checks directory (${require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH}): ${require_import.formatError(error)}`);
4506
+ return [];
4507
+ }
4508
+ }
4509
+ /**
4510
+ * Tool to get detailed information about a specific check
4511
+ */
4512
+ async function getCheck({ relativePathFromCwd }) {
4513
+ require_import.checkPathTraversal({
4514
+ relativePath: relativePathFromCwd,
4515
+ intendedRootDir: process.cwd()
4516
+ });
4517
+ const filename = (0, node_path.basename)(relativePathFromCwd);
4518
+ try {
4519
+ const check = await require_import.RulesyncCheck.fromFile({
4520
+ relativeFilePath: filename,
4521
+ validate: true
4522
+ });
4523
+ return {
4524
+ relativePathFromCwd: (0, node_path.join)(require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename),
4525
+ frontmatter: check.getFrontmatter(),
4526
+ body: check.getBody()
4527
+ };
4528
+ } catch (error) {
4529
+ throw new Error(`Failed to read check file ${relativePathFromCwd}: ${require_import.formatError(error)}`, { cause: error });
4530
+ }
4531
+ }
4532
+ /**
4533
+ * Tool to create or update a check (upsert operation)
4534
+ */
4535
+ async function putCheck({ relativePathFromCwd, frontmatter, body }) {
4536
+ require_import.checkPathTraversal({
4537
+ relativePath: relativePathFromCwd,
4538
+ intendedRootDir: process.cwd()
4539
+ });
4540
+ const filename = (0, node_path.basename)(relativePathFromCwd);
4541
+ const estimatedSize = JSON.stringify(frontmatter).length + body.length;
4542
+ if (estimatedSize > maxCheckSizeBytes) throw new Error(`Check size ${estimatedSize} bytes exceeds maximum ${maxCheckSizeBytes} bytes (1MB) for ${relativePathFromCwd}`);
4543
+ try {
4544
+ const existingChecks = await listChecks();
4545
+ if (!existingChecks.some((check) => check.relativePathFromCwd === (0, node_path.join)(require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename)) && existingChecks.length >= maxChecksCount) throw new Error(`Maximum number of checks (${maxChecksCount}) reached in ${require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH}`);
4546
+ const check = new require_import.RulesyncCheck({
4547
+ outputRoot: process.cwd(),
4548
+ relativeDirPath: require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH,
4549
+ relativeFilePath: filename,
4550
+ frontmatter,
4551
+ body,
4552
+ validate: true
4553
+ });
4554
+ await require_import.ensureDir((0, node_path.join)(process.cwd(), require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH));
4555
+ await require_import.writeFileContent(check.getFilePath(), check.getFileContent());
4556
+ return {
4557
+ relativePathFromCwd: (0, node_path.join)(require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename),
4558
+ frontmatter: check.getFrontmatter(),
4559
+ body: check.getBody()
4560
+ };
4561
+ } catch (error) {
4562
+ throw new Error(`Failed to write check file ${relativePathFromCwd}: ${require_import.formatError(error)}`, { cause: error });
4563
+ }
4564
+ }
4565
+ /**
4566
+ * Tool to delete a check
4567
+ */
4568
+ async function deleteCheck({ relativePathFromCwd }) {
4569
+ require_import.checkPathTraversal({
4570
+ relativePath: relativePathFromCwd,
4571
+ intendedRootDir: process.cwd()
4572
+ });
4573
+ const filename = (0, node_path.basename)(relativePathFromCwd);
4574
+ const fullPath = (0, node_path.join)(process.cwd(), require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename);
4575
+ try {
4576
+ await require_import.removeFile(fullPath);
4577
+ return { relativePathFromCwd: (0, node_path.join)(require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename) };
4578
+ } catch (error) {
4579
+ throw new Error(`Failed to delete check file ${relativePathFromCwd}: ${require_import.formatError(error)}`, { cause: error });
4580
+ }
4581
+ }
4582
+ /**
4583
+ * Schema for check-related tool parameters
4584
+ */
4585
+ const checkToolSchemas = {
4586
+ listChecks: zod_mini.z.object({}),
4587
+ getCheck: zod_mini.z.object({ relativePathFromCwd: zod_mini.z.string() }),
4588
+ putCheck: zod_mini.z.object({
4589
+ relativePathFromCwd: zod_mini.z.string(),
4590
+ frontmatter: require_import.RulesyncCheckFrontmatterSchema,
4591
+ body: zod_mini.z.string()
4592
+ }),
4593
+ deleteCheck: zod_mini.z.object({ relativePathFromCwd: zod_mini.z.string() })
4594
+ };
4595
+ /**
4596
+ * Tool definitions for check-related operations
4597
+ */
4598
+ const checkTools = {
4599
+ listChecks: {
4600
+ name: "listChecks",
4601
+ description: `List all checks from ${(0, node_path.join)(require_import.RULESYNC_CHECKS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
4602
+ parameters: checkToolSchemas.listChecks,
4603
+ execute: async () => {
4604
+ const output = { checks: await listChecks() };
4605
+ return JSON.stringify(output, null, 2);
4606
+ }
4607
+ },
4608
+ getCheck: {
4609
+ name: "getCheck",
4610
+ description: "Get detailed information about a specific check. relativePathFromCwd parameter is required.",
4611
+ parameters: checkToolSchemas.getCheck,
4612
+ execute: async (args) => {
4613
+ const result = await getCheck({ relativePathFromCwd: args.relativePathFromCwd });
4614
+ return JSON.stringify(result, null, 2);
4615
+ }
4616
+ },
4617
+ putCheck: {
4618
+ name: "putCheck",
4619
+ description: "Create or update a check (upsert operation). relativePathFromCwd, frontmatter, and body parameters are required.",
4620
+ parameters: checkToolSchemas.putCheck,
4621
+ execute: async (args) => {
4622
+ const result = await putCheck({
4623
+ relativePathFromCwd: args.relativePathFromCwd,
4624
+ frontmatter: args.frontmatter,
4625
+ body: args.body
4626
+ });
4627
+ return JSON.stringify(result, null, 2);
4628
+ }
4629
+ },
4630
+ deleteCheck: {
4631
+ name: "deleteCheck",
4632
+ description: "Delete a check file. relativePathFromCwd parameter is required.",
4633
+ parameters: checkToolSchemas.deleteCheck,
4634
+ execute: async (args) => {
4635
+ const result = await deleteCheck({ relativePathFromCwd: args.relativePathFromCwd });
4636
+ return JSON.stringify(result, null, 2);
4637
+ }
4638
+ }
4639
+ };
4640
+ //#endregion
4427
4641
  //#region src/mcp/commands.ts
4428
4642
  const logger$3 = new require_import.ConsoleLogger({
4429
4643
  verbose: false,
@@ -4675,6 +4889,7 @@ function buildSuccessResponse$2(params) {
4675
4889
  skillsCount: convertResult.skillsCount,
4676
4890
  hooksCount: convertResult.hooksCount,
4677
4891
  permissionsCount: convertResult.permissionsCount,
4892
+ checksCount: convertResult.checksCount,
4678
4893
  totalCount
4679
4894
  },
4680
4895
  config: {
@@ -4785,6 +5000,7 @@ function buildSuccessResponse$1(params) {
4785
5000
  skillsCount: generateResult.skillsCount,
4786
5001
  hooksCount: generateResult.hooksCount,
4787
5002
  permissionsCount: generateResult.permissionsCount,
5003
+ checksCount: generateResult.checksCount,
4788
5004
  totalCount
4789
5005
  },
4790
5006
  config: {
@@ -5070,6 +5286,7 @@ function buildSuccessResponse(params) {
5070
5286
  skillsCount: importResult.skillsCount,
5071
5287
  hooksCount: importResult.hooksCount,
5072
5288
  permissionsCount: importResult.permissionsCount,
5289
+ checksCount: importResult.checksCount,
5073
5290
  totalCount
5074
5291
  },
5075
5292
  config: {
@@ -5855,6 +6072,7 @@ const rulesyncFeatureSchema = zod_mini.z.enum([
5855
6072
  "command",
5856
6073
  "subagent",
5857
6074
  "skill",
6075
+ "check",
5858
6076
  "ignore",
5859
6077
  "mcp",
5860
6078
  "permissions",
@@ -5911,6 +6129,12 @@ const supportedOperationsByFeature = {
5911
6129
  "put",
5912
6130
  "delete"
5913
6131
  ],
6132
+ check: [
6133
+ "list",
6134
+ "get",
6135
+ "put",
6136
+ "delete"
6137
+ ],
5914
6138
  ignore: [
5915
6139
  "get",
5916
6140
  "put",
@@ -5949,6 +6173,7 @@ function parseFrontmatter({ feature, frontmatter }) {
5949
6173
  case "command": return require_import.RulesyncCommandFrontmatterSchema.parse(frontmatter);
5950
6174
  case "subagent": return require_import.RulesyncSubagentFrontmatterSchema.parse(frontmatter);
5951
6175
  case "skill": return require_import.RulesyncSkillFrontmatterSchema.parse(frontmatter);
6176
+ case "check": return require_import.RulesyncCheckFrontmatterSchema.parse(frontmatter);
5952
6177
  }
5953
6178
  }
5954
6179
  function ensureBody({ body, feature, operation }) {
@@ -6012,6 +6237,19 @@ function executeSkill(parsed) {
6012
6237
  });
6013
6238
  return skillTools.deleteSkill.execute({ relativeDirPathFromCwd: requireTargetPath(parsed) });
6014
6239
  }
6240
+ function executeCheck(parsed) {
6241
+ if (parsed.operation === "list") return checkTools.listChecks.execute();
6242
+ if (parsed.operation === "get") return checkTools.getCheck.execute({ relativePathFromCwd: requireTargetPath(parsed) });
6243
+ if (parsed.operation === "put") return checkTools.putCheck.execute({
6244
+ relativePathFromCwd: requireTargetPath(parsed),
6245
+ frontmatter: parseFrontmatter({
6246
+ feature: "check",
6247
+ frontmatter: parsed.frontmatter ?? {}
6248
+ }),
6249
+ body: ensureBody(parsed)
6250
+ });
6251
+ return checkTools.deleteCheck.execute({ relativePathFromCwd: requireTargetPath(parsed) });
6252
+ }
6015
6253
  function executeIgnore(parsed) {
6016
6254
  if (parsed.operation === "get") return ignoreTools.getIgnoreFile.execute();
6017
6255
  if (parsed.operation === "put") return ignoreTools.putIgnoreFile.execute({ content: requireContent({
@@ -6060,6 +6298,7 @@ const featureExecutors = {
6060
6298
  command: executeCommand,
6061
6299
  subagent: executeSubagent,
6062
6300
  skill: executeSkill,
6301
+ check: executeCheck,
6063
6302
  ignore: executeIgnore,
6064
6303
  mcp: executeMcp,
6065
6304
  permissions: executePermissions,
@@ -6070,7 +6309,7 @@ const featureExecutors = {
6070
6309
  };
6071
6310
  const rulesyncTool = {
6072
6311
  name: "rulesyncTool",
6073
- description: "Manage Rulesync files through a single MCP tool. Features: rule/command/subagent/skill support list/get/put/delete; ignore/mcp/permissions/hooks support get/put/delete only; generate supports run only; import supports run only; convert supports run only. Parameters: list requires no targetPathFromCwd (lists all items); get/delete require targetPathFromCwd; put requires targetPathFromCwd, frontmatter, and body (or content for ignore/mcp/permissions/hooks); generate/run uses generateOptions to configure generation; import/run uses importOptions to configure import; convert/run uses convertOptions to configure conversion.",
6312
+ description: "Manage Rulesync files through a single MCP tool. Features: rule/command/subagent/skill/check support list/get/put/delete; ignore/mcp/permissions/hooks support get/put/delete only; generate supports run only; import supports run only; convert supports run only. Parameters: list requires no targetPathFromCwd (lists all items); get/delete require targetPathFromCwd; put requires targetPathFromCwd, frontmatter, and body (or content for ignore/mcp/permissions/hooks); generate/run uses generateOptions to configure generation; import/run uses importOptions to configure import; convert/run uses convertOptions to configure conversion.",
6074
6313
  parameters: rulesyncToolSchema,
6075
6314
  execute: async (args) => {
6076
6315
  const parsed = rulesyncToolSchema.parse(args);
@@ -6556,7 +6795,7 @@ function wrapCommand$1({ name, errorCode, handler, getVersion, loggerFactory = c
6556
6795
  }
6557
6796
  //#endregion
6558
6797
  //#region src/cli/index.ts
6559
- const getVersion = () => "12.0.0";
6798
+ const getVersion = () => "13.0.0";
6560
6799
  function wrapCommand(name, errorCode, handler) {
6561
6800
  return wrapCommand$1({
6562
6801
  name,