rulesync 11.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 +39 -39
- package/dist/cli/index.cjs +251 -12
- package/dist/cli/index.js +251 -12
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-AKytnIKl.js → import-CMSHVMqU.js} +1767 -469
- package/dist/import-CMSHVMqU.js.map +1 -0
- package/dist/{import-ESr9cSFw.cjs → import-nbmxtKYi.cjs} +1809 -481
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +7 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/import-AKytnIKl.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as isSymlink, A as CLAUDECODE_SETTINGS_LOCAL_FILE_NAME, At as RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH, B as findControlCharacter, C as CommandsProcessor, Ct as RULESYNC_MCP_FILE_NAME, D as CLAUDECODE_DIR, Dt as RULESYNC_OVERVIEW_FILE_NAME, E as CODEXCLI_DIR, Et as RULESYNC_MCP_SCHEMA_URL, F as RulesyncCheck, Ft as RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH, G as checkPathTraversal, H as JsonLogger, I as RulesyncCheckFrontmatterSchema, It as RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, J as ensureDir, K as createTempDirectory, L as stringifyFrontmatter, Lt as formatError, M as RulesyncCommand, Mt as RULESYNC_RELATIVE_DIR_PATH, N as RulesyncCommandFrontmatterSchema, Nt as RULESYNC_RULES_RELATIVE_DIR_PATH, O as CLAUDECODE_LOCAL_RULE_FILE_NAME, Ot as RULESYNC_PERMISSIONS_FILE_NAME, P as ChecksProcessor, Pt as RULESYNC_SKILLS_RELATIVE_DIR_PATH, Q as getHomeDirectory, R as loadYaml, Rt as ALL_FEATURES, S as RulesyncHooks, St as RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH, T as CODEXCLI_BASH_RULES_FILE_NAME, Tt as RULESYNC_MCP_RELATIVE_FILE_PATH, U as CLIError, V as ConsoleLogger, W as ErrorCodes, X as findFilesByGlobs, Y as fileExists, Z as getFileSize, _ as McpProcessor, _t as RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH, a as convertFromTool, at as toPosixPath, b as RulesyncIgnore, bt as RULESYNC_HOOKS_RELATIVE_FILE_PATH, c as RulesyncRuleFrontmatterSchema, ct as ALL_TOOL_TARGETS_WITH_WILDCARD, d as RulesyncSubagentFrontmatterSchema, dt as RULESYNC_AIIGNORE_FILE_NAME, et as listDirectoryFiles, f as SkillsProcessor, ft as RULESYNC_AIIGNORE_RELATIVE_FILE_PATH, g as RulesyncPermissions, gt as RULESYNC_CONFIG_SCHEMA_URL, h as RulesyncSkillFrontmatterSchema, ht as RULESYNC_CONFIG_RELATIVE_FILE_PATH, i as getProcessorRegistryEntry, it as removeTempDirectory, j as CLAUDECODE_SKILLS_DIR_PATH, jt as RULESYNC_PERMISSIONS_SCHEMA_URL, k as CLAUDECODE_MEMORIES_DIR_NAME, kt as RULESYNC_PERMISSIONS_JSONC_FILE_NAME, l as SubagentsProcessor, lt as ToolTargetSchema, m as RulesyncSkill, mt as RULESYNC_COMMANDS_RELATIVE_DIR_PATH, n as checkRulesyncDirExists, nt as removeDirectory, o as RulesProcessor, ot as writeFileContent, p as getLocalSkillDirNames, pt as RULESYNC_CHECKS_RELATIVE_DIR_PATH, q as directoryExists, r as generate, rt as removeFile, s as RulesyncRule, st as ALL_TOOL_TARGETS, t as importFromTool, tt as readFileContent, u as RulesyncSubagent, ut as MAX_FILE_SIZE, v as RulesyncMcp, vt as RULESYNC_HOOKS_FILE_NAME, w as SKILL_FILE_NAME$1, wt as RULESYNC_MCP_JSONC_FILE_NAME, x as HooksProcessor, xt as RULESYNC_IGNORE_RELATIVE_FILE_PATH, y as IgnoreProcessor, yt as RULESYNC_HOOKS_JSONC_FILE_NAME, z as ConfigResolver, zt as ALL_FEATURES_WITH_WILDCARD } from "../import-CMSHVMqU.js";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import { nonnegative, optional, refine, z } from "zod/mini";
|
|
5
5
|
import * as path$1 from "node:path";
|
|
@@ -7,11 +7,11 @@ import { basename, dirname, isAbsolute, join, posix, relative, resolve, sep } fr
|
|
|
7
7
|
import * as os$1 from "node:os";
|
|
8
8
|
import { promisify } from "node:util";
|
|
9
9
|
import { dump } from "js-yaml";
|
|
10
|
+
import * as crypto from "node:crypto";
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
10
12
|
import { Semaphore } from "es-toolkit/promise";
|
|
11
13
|
import { RequestError } from "@octokit/request-error";
|
|
12
14
|
import { Octokit } from "@octokit/rest";
|
|
13
|
-
import * as crypto from "node:crypto";
|
|
14
|
-
import { createHash } from "node:crypto";
|
|
15
15
|
import { execFile } from "node:child_process";
|
|
16
16
|
import { FastMCP } from "fastmcp";
|
|
17
17
|
import * as fs from "node:fs";
|
|
@@ -34,7 +34,7 @@ const parseCommaSeparatedList = (value) => value.split(",").map((s) => s.trim())
|
|
|
34
34
|
* Calculate the total count from a result object
|
|
35
35
|
*/
|
|
36
36
|
function calculateTotalCount(result) {
|
|
37
|
-
return result.rulesCount + result.ignoreCount + result.mcpCount + result.commandsCount + result.subagentsCount + result.skillsCount + result.hooksCount + result.permissionsCount;
|
|
37
|
+
return result.rulesCount + result.ignoreCount + result.mcpCount + result.commandsCount + result.subagentsCount + result.skillsCount + result.hooksCount + result.permissionsCount + result.checksCount;
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region src/cli/commands/convert.ts
|
|
@@ -80,7 +80,8 @@ async function convertCommand(logger, options) {
|
|
|
80
80
|
subagents: { count: result.subagentsCount },
|
|
81
81
|
skills: { count: result.skillsCount },
|
|
82
82
|
hooks: { count: result.hooksCount },
|
|
83
|
-
permissions: { count: result.permissionsCount }
|
|
83
|
+
permissions: { count: result.permissionsCount },
|
|
84
|
+
checks: { count: result.checksCount }
|
|
84
85
|
});
|
|
85
86
|
logger.captureData("totalFiles", totalConverted);
|
|
86
87
|
}
|
|
@@ -93,6 +94,7 @@ async function convertCommand(logger, options) {
|
|
|
93
94
|
if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
|
|
94
95
|
if (result.hooksCount > 0) parts.push(`${result.hooksCount} hooks`);
|
|
95
96
|
if (result.permissionsCount > 0) parts.push(`${result.permissionsCount} permissions`);
|
|
97
|
+
if (result.checksCount > 0) parts.push(`${result.checksCount} checks`);
|
|
96
98
|
const summary = `${modePrefix}${isPreview ? "Would convert" : "Converted"} ${totalConverted} file(s) total from ${fromTool} to ${toTools.join(", ")} (${parts.join(" + ")})`;
|
|
97
99
|
if (isPreview) logger.info(summary);
|
|
98
100
|
else logger.success(summary);
|
|
@@ -539,6 +541,7 @@ const FEATURE_PATHS = {
|
|
|
539
541
|
commands: ["commands"],
|
|
540
542
|
subagents: ["subagents"],
|
|
541
543
|
skills: ["skills"],
|
|
544
|
+
checks: ["checks"],
|
|
542
545
|
ignore: [RULESYNC_AIIGNORE_FILE_NAME],
|
|
543
546
|
mcp: [RULESYNC_MCP_FILE_NAME, RULESYNC_MCP_JSONC_FILE_NAME],
|
|
544
547
|
hooks: [RULESYNC_HOOKS_FILE_NAME, RULESYNC_HOOKS_JSONC_FILE_NAME],
|
|
@@ -624,6 +627,16 @@ async function convertFetchedFilesToRulesync(params) {
|
|
|
624
627
|
logger
|
|
625
628
|
})
|
|
626
629
|
},
|
|
630
|
+
{
|
|
631
|
+
feature: "checks",
|
|
632
|
+
getTargets: () => ChecksProcessor.getToolTargets({ global: false }),
|
|
633
|
+
createProcessor: () => new ChecksProcessor({
|
|
634
|
+
outputRoot: tempDir,
|
|
635
|
+
toolTarget: target,
|
|
636
|
+
global: false,
|
|
637
|
+
logger
|
|
638
|
+
})
|
|
639
|
+
},
|
|
627
640
|
{
|
|
628
641
|
feature: "ignore",
|
|
629
642
|
getTargets: () => IgnoreProcessor.getToolTargets(),
|
|
@@ -947,6 +960,10 @@ function getToolPathMapping(target) {
|
|
|
947
960
|
const factory = SkillsProcessor.getFactory(target);
|
|
948
961
|
if (factory) mapping.skills = factory.class.getSettablePaths({ global: false }).relativeDirPath;
|
|
949
962
|
}
|
|
963
|
+
if (ChecksProcessor.getToolTargets({ global: false }).includes(target)) {
|
|
964
|
+
const factory = ChecksProcessor.getFactory(target);
|
|
965
|
+
if (factory) mapping.checks = factory.class.getSettablePaths({ global: false }).relativeDirPath;
|
|
966
|
+
}
|
|
950
967
|
return mapping;
|
|
951
968
|
}
|
|
952
969
|
/**
|
|
@@ -970,6 +987,10 @@ function mapToToolPath(relativePath, toolPaths) {
|
|
|
970
987
|
const restPath = relativePath.substring(7);
|
|
971
988
|
if (toolPaths.skills) return join(toolPaths.skills, restPath);
|
|
972
989
|
}
|
|
990
|
+
if (relativePath.startsWith("checks/")) {
|
|
991
|
+
const restPath = relativePath.substring(7);
|
|
992
|
+
if (toolPaths.checks) return join(toolPaths.checks, restPath);
|
|
993
|
+
}
|
|
973
994
|
return relativePath;
|
|
974
995
|
}
|
|
975
996
|
/**
|
|
@@ -1045,6 +1066,7 @@ const FEATURE_DEBUG_MESSAGES = {
|
|
|
1045
1066
|
subagents: "Generating subagent files...",
|
|
1046
1067
|
skills: "Generating skill files...",
|
|
1047
1068
|
hooks: "Generating hooks...",
|
|
1069
|
+
checks: "Generating check files...",
|
|
1048
1070
|
rules: "Generating rule files..."
|
|
1049
1071
|
};
|
|
1050
1072
|
const FEATURE_DEBUG_ORDER = [
|
|
@@ -1054,6 +1076,7 @@ const FEATURE_DEBUG_ORDER = [
|
|
|
1054
1076
|
"subagents",
|
|
1055
1077
|
"skills",
|
|
1056
1078
|
"hooks",
|
|
1079
|
+
"checks",
|
|
1057
1080
|
"rules"
|
|
1058
1081
|
];
|
|
1059
1082
|
function logFeatureDebugMessages(logger, features) {
|
|
@@ -1097,6 +1120,10 @@ function buildSummaryParts(result) {
|
|
|
1097
1120
|
{
|
|
1098
1121
|
count: result.permissionsCount,
|
|
1099
1122
|
label: "permissions"
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
count: result.checksCount,
|
|
1126
|
+
label: "checks"
|
|
1100
1127
|
}
|
|
1101
1128
|
];
|
|
1102
1129
|
const parts = [];
|
|
@@ -1147,6 +1174,10 @@ async function generateCommand(logger, options) {
|
|
|
1147
1174
|
count: result.permissionsCount,
|
|
1148
1175
|
paths: result.permissionsPaths
|
|
1149
1176
|
},
|
|
1177
|
+
checks: {
|
|
1178
|
+
count: result.checksCount,
|
|
1179
|
+
paths: result.checksPaths
|
|
1180
|
+
},
|
|
1150
1181
|
rules: {
|
|
1151
1182
|
count: result.rulesCount,
|
|
1152
1183
|
paths: result.rulesPaths
|
|
@@ -1160,7 +1191,8 @@ async function generateCommand(logger, options) {
|
|
|
1160
1191
|
subagents: (count) => `${count === 1 ? "subagent" : "subagents"}`,
|
|
1161
1192
|
skills: (count) => `${count === 1 ? "skill" : "skills"}`,
|
|
1162
1193
|
hooks: (count) => `${count === 1 ? "hooks file" : "hooks files"}`,
|
|
1163
|
-
permissions: (count) => `${count === 1 ? "permissions file" : "permissions files"}
|
|
1194
|
+
permissions: (count) => `${count === 1 ? "permissions file" : "permissions files"}`,
|
|
1195
|
+
checks: (count) => `${count === 1 ? "check" : "checks"}`
|
|
1164
1196
|
};
|
|
1165
1197
|
for (const [feature, data] of Object.entries(featureResults)) logFeatureResult(logger, {
|
|
1166
1198
|
count: data.count,
|
|
@@ -1261,13 +1293,16 @@ const deriveRulesEntries = () => {
|
|
|
1261
1293
|
for (const root of [paths.root, ...paths.alternativeRoots ?? []]) if (root) pushEntry(entries, target, "rules", fileToGlob(root.relativeDirPath, root.relativeFilePath));
|
|
1262
1294
|
const nonRootDir = paths.nonRoot?.relativeDirPath;
|
|
1263
1295
|
if (nonRootDir && nonRootDir !== ".") pushEntry(entries, target, "rules", dirToGlob(nonRootDir));
|
|
1296
|
+
const classWithExtraFiles = factory.class;
|
|
1297
|
+
if (classWithExtraFiles.getExtraFixedFiles) for (const file of classWithExtraFiles.getExtraFixedFiles({ global: false })) pushEntry(entries, target, "rules", fileToGlob(file.relativeDirPath, file.relativeFilePath));
|
|
1264
1298
|
}
|
|
1265
1299
|
return entries;
|
|
1266
1300
|
};
|
|
1267
1301
|
const DIR_FEATURES = /* @__PURE__ */ new Set([
|
|
1268
1302
|
"commands",
|
|
1269
1303
|
"skills",
|
|
1270
|
-
"subagents"
|
|
1304
|
+
"subagents",
|
|
1305
|
+
"checks"
|
|
1271
1306
|
]);
|
|
1272
1307
|
const FILE_FEATURES = /* @__PURE__ */ new Set([
|
|
1273
1308
|
"mcp",
|
|
@@ -1290,7 +1325,8 @@ const DERIVED_FEATURES = [
|
|
|
1290
1325
|
"mcp",
|
|
1291
1326
|
"hooks",
|
|
1292
1327
|
"permissions",
|
|
1293
|
-
"ignore"
|
|
1328
|
+
"ignore",
|
|
1329
|
+
"checks"
|
|
1294
1330
|
];
|
|
1295
1331
|
const deriveAllGitignoreEntriesUnfiltered = () => DERIVED_FEATURES.flatMap((feature) => deriveFeatureGitignoreEntries(feature));
|
|
1296
1332
|
const deriveAllGitignoreEntries = () => deriveAllGitignoreEntriesUnfiltered().filter((tag) => !DERIVED_PATHS_NOT_GITIGNORED.has(tag.entry));
|
|
@@ -1381,6 +1417,16 @@ const GITIGNORE_ENTRY_REGISTRY = [
|
|
|
1381
1417
|
feature: "rules",
|
|
1382
1418
|
entry: "**/.augment-guidelines"
|
|
1383
1419
|
},
|
|
1420
|
+
{
|
|
1421
|
+
target: "devin",
|
|
1422
|
+
feature: "commands",
|
|
1423
|
+
entry: "**/.devin/workflows/"
|
|
1424
|
+
},
|
|
1425
|
+
{
|
|
1426
|
+
target: "junie",
|
|
1427
|
+
feature: "rules",
|
|
1428
|
+
entry: "**/.junie/memories/"
|
|
1429
|
+
},
|
|
1384
1430
|
{
|
|
1385
1431
|
target: "rovodev",
|
|
1386
1432
|
feature: "skills",
|
|
@@ -1429,7 +1475,7 @@ const GITIGNORE_ENTRY_REGISTRY = [
|
|
|
1429
1475
|
{
|
|
1430
1476
|
target: "codexcli",
|
|
1431
1477
|
feature: "permissions",
|
|
1432
|
-
entry: `**/${CODEXCLI_DIR}/rules
|
|
1478
|
+
entry: `**/${CODEXCLI_DIR}/rules/${CODEXCLI_BASH_RULES_FILE_NAME}`
|
|
1433
1479
|
}
|
|
1434
1480
|
],
|
|
1435
1481
|
...deriveAllGitignoreEntries(),
|
|
@@ -1738,7 +1784,8 @@ async function importCommand(logger, options) {
|
|
|
1738
1784
|
subagents: { count: result.subagentsCount },
|
|
1739
1785
|
skills: { count: result.skillsCount },
|
|
1740
1786
|
hooks: { count: result.hooksCount },
|
|
1741
|
-
permissions: { count: result.permissionsCount }
|
|
1787
|
+
permissions: { count: result.permissionsCount },
|
|
1788
|
+
checks: { count: result.checksCount }
|
|
1742
1789
|
});
|
|
1743
1790
|
logger.captureData("totalFiles", totalImported);
|
|
1744
1791
|
}
|
|
@@ -1751,6 +1798,7 @@ async function importCommand(logger, options) {
|
|
|
1751
1798
|
if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
|
|
1752
1799
|
if (result.hooksCount > 0) parts.push(`${result.hooksCount} hooks`);
|
|
1753
1800
|
if (result.permissionsCount > 0) parts.push(`${result.permissionsCount} permissions`);
|
|
1801
|
+
if (result.checksCount > 0) parts.push(`${result.checksCount} checks`);
|
|
1754
1802
|
logger.success(`Imported ${totalImported} file(s) total (${parts.join(" + ")})`);
|
|
1755
1803
|
}
|
|
1756
1804
|
//#endregion
|
|
@@ -4422,6 +4470,172 @@ async function runGhInstall(logger, options) {
|
|
|
4422
4470
|
else logger.success(`All gh sources up to date (${result.sourcesProcessed} checked).`);
|
|
4423
4471
|
}
|
|
4424
4472
|
//#endregion
|
|
4473
|
+
//#region src/mcp/checks.ts
|
|
4474
|
+
const logger$4 = new ConsoleLogger({
|
|
4475
|
+
verbose: false,
|
|
4476
|
+
silent: true
|
|
4477
|
+
});
|
|
4478
|
+
const maxCheckSizeBytes = 1024 * 1024;
|
|
4479
|
+
const maxChecksCount = 1e3;
|
|
4480
|
+
/**
|
|
4481
|
+
* Tool to list all checks from .rulesync/checks/*.md
|
|
4482
|
+
*/
|
|
4483
|
+
async function listChecks() {
|
|
4484
|
+
const checksDir = join(process.cwd(), RULESYNC_CHECKS_RELATIVE_DIR_PATH);
|
|
4485
|
+
try {
|
|
4486
|
+
const mdFiles = (await listDirectoryFiles(checksDir)).filter((file) => file.endsWith(".md"));
|
|
4487
|
+
return (await Promise.all(mdFiles.map(async (file) => {
|
|
4488
|
+
try {
|
|
4489
|
+
const check = await RulesyncCheck.fromFile({
|
|
4490
|
+
relativeFilePath: file,
|
|
4491
|
+
validate: true
|
|
4492
|
+
});
|
|
4493
|
+
return {
|
|
4494
|
+
relativePathFromCwd: join(RULESYNC_CHECKS_RELATIVE_DIR_PATH, file),
|
|
4495
|
+
frontmatter: check.getFrontmatter()
|
|
4496
|
+
};
|
|
4497
|
+
} catch (error) {
|
|
4498
|
+
logger$4.error(`Failed to read check file ${file}: ${formatError(error)}`);
|
|
4499
|
+
return null;
|
|
4500
|
+
}
|
|
4501
|
+
}))).filter((check) => check !== null);
|
|
4502
|
+
} catch (error) {
|
|
4503
|
+
logger$4.error(`Failed to read checks directory (${RULESYNC_CHECKS_RELATIVE_DIR_PATH}): ${formatError(error)}`);
|
|
4504
|
+
return [];
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
/**
|
|
4508
|
+
* Tool to get detailed information about a specific check
|
|
4509
|
+
*/
|
|
4510
|
+
async function getCheck({ relativePathFromCwd }) {
|
|
4511
|
+
checkPathTraversal({
|
|
4512
|
+
relativePath: relativePathFromCwd,
|
|
4513
|
+
intendedRootDir: process.cwd()
|
|
4514
|
+
});
|
|
4515
|
+
const filename = basename(relativePathFromCwd);
|
|
4516
|
+
try {
|
|
4517
|
+
const check = await RulesyncCheck.fromFile({
|
|
4518
|
+
relativeFilePath: filename,
|
|
4519
|
+
validate: true
|
|
4520
|
+
});
|
|
4521
|
+
return {
|
|
4522
|
+
relativePathFromCwd: join(RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename),
|
|
4523
|
+
frontmatter: check.getFrontmatter(),
|
|
4524
|
+
body: check.getBody()
|
|
4525
|
+
};
|
|
4526
|
+
} catch (error) {
|
|
4527
|
+
throw new Error(`Failed to read check file ${relativePathFromCwd}: ${formatError(error)}`, { cause: error });
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
/**
|
|
4531
|
+
* Tool to create or update a check (upsert operation)
|
|
4532
|
+
*/
|
|
4533
|
+
async function putCheck({ relativePathFromCwd, frontmatter, body }) {
|
|
4534
|
+
checkPathTraversal({
|
|
4535
|
+
relativePath: relativePathFromCwd,
|
|
4536
|
+
intendedRootDir: process.cwd()
|
|
4537
|
+
});
|
|
4538
|
+
const filename = basename(relativePathFromCwd);
|
|
4539
|
+
const estimatedSize = JSON.stringify(frontmatter).length + body.length;
|
|
4540
|
+
if (estimatedSize > maxCheckSizeBytes) throw new Error(`Check size ${estimatedSize} bytes exceeds maximum ${maxCheckSizeBytes} bytes (1MB) for ${relativePathFromCwd}`);
|
|
4541
|
+
try {
|
|
4542
|
+
const existingChecks = await listChecks();
|
|
4543
|
+
if (!existingChecks.some((check) => check.relativePathFromCwd === join(RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename)) && existingChecks.length >= maxChecksCount) throw new Error(`Maximum number of checks (${maxChecksCount}) reached in ${RULESYNC_CHECKS_RELATIVE_DIR_PATH}`);
|
|
4544
|
+
const check = new RulesyncCheck({
|
|
4545
|
+
outputRoot: process.cwd(),
|
|
4546
|
+
relativeDirPath: RULESYNC_CHECKS_RELATIVE_DIR_PATH,
|
|
4547
|
+
relativeFilePath: filename,
|
|
4548
|
+
frontmatter,
|
|
4549
|
+
body,
|
|
4550
|
+
validate: true
|
|
4551
|
+
});
|
|
4552
|
+
await ensureDir(join(process.cwd(), RULESYNC_CHECKS_RELATIVE_DIR_PATH));
|
|
4553
|
+
await writeFileContent(check.getFilePath(), check.getFileContent());
|
|
4554
|
+
return {
|
|
4555
|
+
relativePathFromCwd: join(RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename),
|
|
4556
|
+
frontmatter: check.getFrontmatter(),
|
|
4557
|
+
body: check.getBody()
|
|
4558
|
+
};
|
|
4559
|
+
} catch (error) {
|
|
4560
|
+
throw new Error(`Failed to write check file ${relativePathFromCwd}: ${formatError(error)}`, { cause: error });
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
/**
|
|
4564
|
+
* Tool to delete a check
|
|
4565
|
+
*/
|
|
4566
|
+
async function deleteCheck({ relativePathFromCwd }) {
|
|
4567
|
+
checkPathTraversal({
|
|
4568
|
+
relativePath: relativePathFromCwd,
|
|
4569
|
+
intendedRootDir: process.cwd()
|
|
4570
|
+
});
|
|
4571
|
+
const filename = basename(relativePathFromCwd);
|
|
4572
|
+
const fullPath = join(process.cwd(), RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename);
|
|
4573
|
+
try {
|
|
4574
|
+
await removeFile(fullPath);
|
|
4575
|
+
return { relativePathFromCwd: join(RULESYNC_CHECKS_RELATIVE_DIR_PATH, filename) };
|
|
4576
|
+
} catch (error) {
|
|
4577
|
+
throw new Error(`Failed to delete check file ${relativePathFromCwd}: ${formatError(error)}`, { cause: error });
|
|
4578
|
+
}
|
|
4579
|
+
}
|
|
4580
|
+
/**
|
|
4581
|
+
* Schema for check-related tool parameters
|
|
4582
|
+
*/
|
|
4583
|
+
const checkToolSchemas = {
|
|
4584
|
+
listChecks: z.object({}),
|
|
4585
|
+
getCheck: z.object({ relativePathFromCwd: z.string() }),
|
|
4586
|
+
putCheck: z.object({
|
|
4587
|
+
relativePathFromCwd: z.string(),
|
|
4588
|
+
frontmatter: RulesyncCheckFrontmatterSchema,
|
|
4589
|
+
body: z.string()
|
|
4590
|
+
}),
|
|
4591
|
+
deleteCheck: z.object({ relativePathFromCwd: z.string() })
|
|
4592
|
+
};
|
|
4593
|
+
/**
|
|
4594
|
+
* Tool definitions for check-related operations
|
|
4595
|
+
*/
|
|
4596
|
+
const checkTools = {
|
|
4597
|
+
listChecks: {
|
|
4598
|
+
name: "listChecks",
|
|
4599
|
+
description: `List all checks from ${join(RULESYNC_CHECKS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
4600
|
+
parameters: checkToolSchemas.listChecks,
|
|
4601
|
+
execute: async () => {
|
|
4602
|
+
const output = { checks: await listChecks() };
|
|
4603
|
+
return JSON.stringify(output, null, 2);
|
|
4604
|
+
}
|
|
4605
|
+
},
|
|
4606
|
+
getCheck: {
|
|
4607
|
+
name: "getCheck",
|
|
4608
|
+
description: "Get detailed information about a specific check. relativePathFromCwd parameter is required.",
|
|
4609
|
+
parameters: checkToolSchemas.getCheck,
|
|
4610
|
+
execute: async (args) => {
|
|
4611
|
+
const result = await getCheck({ relativePathFromCwd: args.relativePathFromCwd });
|
|
4612
|
+
return JSON.stringify(result, null, 2);
|
|
4613
|
+
}
|
|
4614
|
+
},
|
|
4615
|
+
putCheck: {
|
|
4616
|
+
name: "putCheck",
|
|
4617
|
+
description: "Create or update a check (upsert operation). relativePathFromCwd, frontmatter, and body parameters are required.",
|
|
4618
|
+
parameters: checkToolSchemas.putCheck,
|
|
4619
|
+
execute: async (args) => {
|
|
4620
|
+
const result = await putCheck({
|
|
4621
|
+
relativePathFromCwd: args.relativePathFromCwd,
|
|
4622
|
+
frontmatter: args.frontmatter,
|
|
4623
|
+
body: args.body
|
|
4624
|
+
});
|
|
4625
|
+
return JSON.stringify(result, null, 2);
|
|
4626
|
+
}
|
|
4627
|
+
},
|
|
4628
|
+
deleteCheck: {
|
|
4629
|
+
name: "deleteCheck",
|
|
4630
|
+
description: "Delete a check file. relativePathFromCwd parameter is required.",
|
|
4631
|
+
parameters: checkToolSchemas.deleteCheck,
|
|
4632
|
+
execute: async (args) => {
|
|
4633
|
+
const result = await deleteCheck({ relativePathFromCwd: args.relativePathFromCwd });
|
|
4634
|
+
return JSON.stringify(result, null, 2);
|
|
4635
|
+
}
|
|
4636
|
+
}
|
|
4637
|
+
};
|
|
4638
|
+
//#endregion
|
|
4425
4639
|
//#region src/mcp/commands.ts
|
|
4426
4640
|
const logger$3 = new ConsoleLogger({
|
|
4427
4641
|
verbose: false,
|
|
@@ -4673,6 +4887,7 @@ function buildSuccessResponse$2(params) {
|
|
|
4673
4887
|
skillsCount: convertResult.skillsCount,
|
|
4674
4888
|
hooksCount: convertResult.hooksCount,
|
|
4675
4889
|
permissionsCount: convertResult.permissionsCount,
|
|
4890
|
+
checksCount: convertResult.checksCount,
|
|
4676
4891
|
totalCount
|
|
4677
4892
|
},
|
|
4678
4893
|
config: {
|
|
@@ -4783,6 +4998,7 @@ function buildSuccessResponse$1(params) {
|
|
|
4783
4998
|
skillsCount: generateResult.skillsCount,
|
|
4784
4999
|
hooksCount: generateResult.hooksCount,
|
|
4785
5000
|
permissionsCount: generateResult.permissionsCount,
|
|
5001
|
+
checksCount: generateResult.checksCount,
|
|
4786
5002
|
totalCount
|
|
4787
5003
|
},
|
|
4788
5004
|
config: {
|
|
@@ -5068,6 +5284,7 @@ function buildSuccessResponse(params) {
|
|
|
5068
5284
|
skillsCount: importResult.skillsCount,
|
|
5069
5285
|
hooksCount: importResult.hooksCount,
|
|
5070
5286
|
permissionsCount: importResult.permissionsCount,
|
|
5287
|
+
checksCount: importResult.checksCount,
|
|
5071
5288
|
totalCount
|
|
5072
5289
|
},
|
|
5073
5290
|
config: {
|
|
@@ -5853,6 +6070,7 @@ const rulesyncFeatureSchema = z.enum([
|
|
|
5853
6070
|
"command",
|
|
5854
6071
|
"subagent",
|
|
5855
6072
|
"skill",
|
|
6073
|
+
"check",
|
|
5856
6074
|
"ignore",
|
|
5857
6075
|
"mcp",
|
|
5858
6076
|
"permissions",
|
|
@@ -5909,6 +6127,12 @@ const supportedOperationsByFeature = {
|
|
|
5909
6127
|
"put",
|
|
5910
6128
|
"delete"
|
|
5911
6129
|
],
|
|
6130
|
+
check: [
|
|
6131
|
+
"list",
|
|
6132
|
+
"get",
|
|
6133
|
+
"put",
|
|
6134
|
+
"delete"
|
|
6135
|
+
],
|
|
5912
6136
|
ignore: [
|
|
5913
6137
|
"get",
|
|
5914
6138
|
"put",
|
|
@@ -5947,6 +6171,7 @@ function parseFrontmatter({ feature, frontmatter }) {
|
|
|
5947
6171
|
case "command": return RulesyncCommandFrontmatterSchema.parse(frontmatter);
|
|
5948
6172
|
case "subagent": return RulesyncSubagentFrontmatterSchema.parse(frontmatter);
|
|
5949
6173
|
case "skill": return RulesyncSkillFrontmatterSchema.parse(frontmatter);
|
|
6174
|
+
case "check": return RulesyncCheckFrontmatterSchema.parse(frontmatter);
|
|
5950
6175
|
}
|
|
5951
6176
|
}
|
|
5952
6177
|
function ensureBody({ body, feature, operation }) {
|
|
@@ -6010,6 +6235,19 @@ function executeSkill(parsed) {
|
|
|
6010
6235
|
});
|
|
6011
6236
|
return skillTools.deleteSkill.execute({ relativeDirPathFromCwd: requireTargetPath(parsed) });
|
|
6012
6237
|
}
|
|
6238
|
+
function executeCheck(parsed) {
|
|
6239
|
+
if (parsed.operation === "list") return checkTools.listChecks.execute();
|
|
6240
|
+
if (parsed.operation === "get") return checkTools.getCheck.execute({ relativePathFromCwd: requireTargetPath(parsed) });
|
|
6241
|
+
if (parsed.operation === "put") return checkTools.putCheck.execute({
|
|
6242
|
+
relativePathFromCwd: requireTargetPath(parsed),
|
|
6243
|
+
frontmatter: parseFrontmatter({
|
|
6244
|
+
feature: "check",
|
|
6245
|
+
frontmatter: parsed.frontmatter ?? {}
|
|
6246
|
+
}),
|
|
6247
|
+
body: ensureBody(parsed)
|
|
6248
|
+
});
|
|
6249
|
+
return checkTools.deleteCheck.execute({ relativePathFromCwd: requireTargetPath(parsed) });
|
|
6250
|
+
}
|
|
6013
6251
|
function executeIgnore(parsed) {
|
|
6014
6252
|
if (parsed.operation === "get") return ignoreTools.getIgnoreFile.execute();
|
|
6015
6253
|
if (parsed.operation === "put") return ignoreTools.putIgnoreFile.execute({ content: requireContent({
|
|
@@ -6058,6 +6296,7 @@ const featureExecutors = {
|
|
|
6058
6296
|
command: executeCommand,
|
|
6059
6297
|
subagent: executeSubagent,
|
|
6060
6298
|
skill: executeSkill,
|
|
6299
|
+
check: executeCheck,
|
|
6061
6300
|
ignore: executeIgnore,
|
|
6062
6301
|
mcp: executeMcp,
|
|
6063
6302
|
permissions: executePermissions,
|
|
@@ -6068,7 +6307,7 @@ const featureExecutors = {
|
|
|
6068
6307
|
};
|
|
6069
6308
|
const rulesyncTool = {
|
|
6070
6309
|
name: "rulesyncTool",
|
|
6071
|
-
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.",
|
|
6310
|
+
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.",
|
|
6072
6311
|
parameters: rulesyncToolSchema,
|
|
6073
6312
|
execute: async (args) => {
|
|
6074
6313
|
const parsed = rulesyncToolSchema.parse(args);
|
|
@@ -6554,7 +6793,7 @@ function wrapCommand$1({ name, errorCode, handler, getVersion, loggerFactory = c
|
|
|
6554
6793
|
}
|
|
6555
6794
|
//#endregion
|
|
6556
6795
|
//#region src/cli/index.ts
|
|
6557
|
-
const getVersion = () => "
|
|
6796
|
+
const getVersion = () => "13.0.0";
|
|
6558
6797
|
function wrapCommand(name, errorCode, handler) {
|
|
6559
6798
|
return wrapCommand$1({
|
|
6560
6799
|
name,
|