rulesync 9.5.0 → 9.6.1

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.
@@ -7,9 +7,9 @@ import os from "node:os";
7
7
  import { intersection, kebabCase, uniq } from "es-toolkit";
8
8
  import { globbySync } from "globby";
9
9
  import { isDeepStrictEqual } from "node:util";
10
- import { dump, load } from "js-yaml";
11
10
  import * as smolToml from "smol-toml";
12
11
  import matter from "gray-matter";
12
+ import { YAMLException, dump, load } from "js-yaml";
13
13
  import { omit } from "es-toolkit/object";
14
14
  import { encode } from "@toon-format/toon";
15
15
  //#region src/types/features.ts
@@ -141,6 +141,7 @@ const rulesProcessorToolTargetTuple = [
141
141
  "opencode",
142
142
  "pi",
143
143
  "qwencode",
144
+ "reasonix",
144
145
  "replit",
145
146
  "roo",
146
147
  "rovodev",
@@ -288,6 +289,7 @@ const skillsProcessorToolTargetTuple = [
288
289
  "opencode",
289
290
  "pi",
290
291
  "qwencode",
292
+ "reasonix",
291
293
  "replit",
292
294
  "roo",
293
295
  "rovodev",
@@ -1291,7 +1293,8 @@ var ConfigResolver = class {
1291
1293
  const validatedConfigPath = resolvePath(configPath, resolve(inputRoot ?? cwd));
1292
1294
  const baseConfig = await loadConfigFromFile(validatedConfigPath);
1293
1295
  const localConfigPath = join(dirname(validatedConfigPath), RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH);
1294
- const configByFile = mergeConfigs(baseConfig, await loadConfigFromFile(localConfigPath));
1296
+ const localConfig = await loadConfigFromFile(localConfigPath);
1297
+ const configByFile = mergeConfigs(baseConfig, localConfig);
1295
1298
  if (inputRoot === void 0 && configByFile.inputRoot !== void 0) validateOutputRoot(configByFile.inputRoot);
1296
1299
  assertMergedTargetsFeaturesExclusive({
1297
1300
  configByFile,
@@ -1424,7 +1427,7 @@ function isRecord(value) {
1424
1427
  * conversion, etc.) should reject inputs whose prototype could carry
1425
1428
  * malicious accessor descriptors.
1426
1429
  */
1427
- function isPlainObject(value) {
1430
+ function isPlainObject$1(value) {
1428
1431
  if (!isRecord(value)) return false;
1429
1432
  const proto = Object.getPrototypeOf(value);
1430
1433
  return proto === null || proto === Object.prototype;
@@ -1436,11 +1439,43 @@ function isStringArray(value) {
1436
1439
  return Array.isArray(value) && value.every((item) => typeof item === "string");
1437
1440
  }
1438
1441
  //#endregion
1442
+ //#region src/utils/yaml.ts
1443
+ /**
1444
+ * js-yaml v5's `reason` for an empty document. `load("")` — and any
1445
+ * whitespace/comment-only input — throws a `YAMLException` with this reason
1446
+ * instead of returning `undefined` the way v4 did.
1447
+ */
1448
+ const EMPTY_INPUT_REASON = "expected a document, but the input is empty";
1449
+ /**
1450
+ * Load YAML content while preserving js-yaml v4's behavior of returning
1451
+ * `undefined` for empty documents (empty, whitespace-only, or comment-only
1452
+ * input).
1453
+ *
1454
+ * js-yaml v5 changed `load("")` to **throw** ("expected a document, but the
1455
+ * input is empty") instead of returning `undefined`. Many call sites here parse
1456
+ * config/lock/frontmatter files that can legitimately be empty and rely on the
1457
+ * old `undefined` sentinel (`load(input) ?? {}`, `if (loaded === undefined)`,
1458
+ * "an empty file parses to undefined/null"). Routing every load through this
1459
+ * wrapper keeps that contract in one place so a future js-yaml bump cannot
1460
+ * reintroduce the empty-input regression. Genuine parse errors still propagate.
1461
+ *
1462
+ * @see https://github.com/nodeca/js-yaml/blob/master/docs/migrate_v4_to_v5.md#empty-input-throws
1463
+ */
1464
+ function loadYaml(content) {
1465
+ if (content.trim() === "") return;
1466
+ try {
1467
+ return load(content);
1468
+ } catch (error) {
1469
+ if (error instanceof YAMLException && error.reason === EMPTY_INPUT_REASON) return;
1470
+ throw error;
1471
+ }
1472
+ }
1473
+ //#endregion
1439
1474
  //#region src/utils/frontmatter.ts
1440
1475
  function deepRemoveNullishValue(value) {
1441
1476
  if (value === null || value === void 0) return;
1442
1477
  if (Array.isArray(value)) return value.map((item) => deepRemoveNullishValue(item)).filter((item) => item !== void 0);
1443
- if (isPlainObject(value)) {
1478
+ if (isPlainObject$1(value)) {
1444
1479
  const result = {};
1445
1480
  for (const [key, val] of Object.entries(value)) {
1446
1481
  const cleaned = deepRemoveNullishValue(val);
@@ -1463,7 +1498,7 @@ function deepFlattenStringsValue(value) {
1463
1498
  if (value === null || value === void 0) return;
1464
1499
  if (typeof value === "string") return value.replace(/\n+/g, " ").trim();
1465
1500
  if (Array.isArray(value)) return value.map((item) => deepFlattenStringsValue(item)).filter((item) => item !== void 0);
1466
- if (isPlainObject(value)) {
1501
+ if (isPlainObject$1(value)) {
1467
1502
  const result = {};
1468
1503
  for (const [key, val] of Object.entries(value)) {
1469
1504
  const cleaned = deepFlattenStringsValue(val);
@@ -1486,7 +1521,7 @@ function stringifyFrontmatter(body, frontmatter, options) {
1486
1521
  const { avoidBlockScalars = false } = options ?? {};
1487
1522
  const cleanFrontmatter = avoidBlockScalars ? deepFlattenStringsObject(frontmatter) : deepRemoveNullishObject(frontmatter);
1488
1523
  if (avoidBlockScalars) return matter.stringify(body, cleanFrontmatter, { engines: { yaml: {
1489
- parse: (input) => load(input) ?? {},
1524
+ parse: (input) => loadYaml(input) ?? {},
1490
1525
  stringify: (data) => dump(data, { lineWidth: -1 })
1491
1526
  } } });
1492
1527
  return matter.stringify(body, cleanFrontmatter);
@@ -1525,7 +1560,7 @@ function tryJsonEquivalent(a, b) {
1525
1560
  }
1526
1561
  function tryYamlEquivalent(a, b) {
1527
1562
  try {
1528
- return isDeepStrictEqual(load(a), load(b));
1563
+ return isDeepStrictEqual(loadYaml(a), loadYaml(b));
1529
1564
  } catch {
1530
1565
  return;
1531
1566
  }
@@ -2347,14 +2382,17 @@ var AugmentcodeCommand = class AugmentcodeCommand extends ToolCommand {
2347
2382
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
2348
2383
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
2349
2384
  const augmentcodeFields = rulesyncFrontmatter.augmentcode ?? {};
2385
+ const augmentcodeFrontmatter = {
2386
+ description: rulesyncFrontmatter.description,
2387
+ ...augmentcodeFields
2388
+ };
2389
+ const body = rulesyncCommand.getBody();
2390
+ const paths = this.getSettablePaths({ global });
2350
2391
  return new AugmentcodeCommand({
2351
2392
  outputRoot,
2352
- frontmatter: {
2353
- description: rulesyncFrontmatter.description,
2354
- ...augmentcodeFields
2355
- },
2356
- body: rulesyncCommand.getBody(),
2357
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
2393
+ frontmatter: augmentcodeFrontmatter,
2394
+ body,
2395
+ relativeDirPath: paths.relativeDirPath,
2358
2396
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
2359
2397
  validate
2360
2398
  });
@@ -2488,14 +2526,17 @@ var ClaudecodeCommand = class ClaudecodeCommand extends ToolCommand {
2488
2526
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
2489
2527
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
2490
2528
  const claudecodeFields = rulesyncFrontmatter.claudecode ?? {};
2529
+ const claudecodeFrontmatter = {
2530
+ description: rulesyncFrontmatter.description,
2531
+ ...claudecodeFields
2532
+ };
2533
+ const body = rulesyncCommand.getBody();
2534
+ const paths = this.getSettablePaths({ global });
2491
2535
  return new ClaudecodeCommand({
2492
2536
  outputRoot,
2493
- frontmatter: {
2494
- description: rulesyncFrontmatter.description,
2495
- ...claudecodeFields
2496
- },
2497
- body: rulesyncCommand.getBody(),
2498
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
2537
+ frontmatter: claudecodeFrontmatter,
2538
+ body,
2539
+ relativeDirPath: paths.relativeDirPath,
2499
2540
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
2500
2541
  validate
2501
2542
  });
@@ -2696,12 +2737,13 @@ var CodexcliCommand = class CodexcliCommand extends ToolCommand {
2696
2737
  const paths = this.getSettablePaths({ global });
2697
2738
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
2698
2739
  const codexcliFields = rulesyncFrontmatter.codexcli ?? {};
2740
+ const codexcliFrontmatter = {
2741
+ ...rulesyncFrontmatter.description !== void 0 && { description: rulesyncFrontmatter.description },
2742
+ ...codexcliFields
2743
+ };
2699
2744
  return new CodexcliCommand({
2700
2745
  outputRoot,
2701
- frontmatter: {
2702
- ...rulesyncFrontmatter.description !== void 0 && { description: rulesyncFrontmatter.description },
2703
- ...codexcliFields
2704
- },
2746
+ frontmatter: codexcliFrontmatter,
2705
2747
  body: rulesyncCommand.getBody(),
2706
2748
  relativeDirPath: paths.relativeDirPath,
2707
2749
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
@@ -2963,14 +3005,17 @@ var CursorCommand = class CursorCommand extends ToolCommand {
2963
3005
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
2964
3006
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
2965
3007
  const cursorFields = rulesyncFrontmatter.cursor ?? {};
3008
+ const cursorFrontmatter = {
3009
+ ...rulesyncFrontmatter.description && { description: rulesyncFrontmatter.description },
3010
+ ...cursorFields
3011
+ };
3012
+ const body = rulesyncCommand.getBody();
3013
+ const paths = this.getSettablePaths({ global });
2966
3014
  return new CursorCommand({
2967
3015
  outputRoot,
2968
- frontmatter: {
2969
- ...rulesyncFrontmatter.description && { description: rulesyncFrontmatter.description },
2970
- ...cursorFields
2971
- },
2972
- body: rulesyncCommand.getBody(),
2973
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
3016
+ frontmatter: cursorFrontmatter,
3017
+ body,
3018
+ relativeDirPath: paths.relativeDirPath,
2974
3019
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
2975
3020
  validate
2976
3021
  });
@@ -3094,14 +3139,17 @@ var DevinCommand = class DevinCommand extends ToolCommand {
3094
3139
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
3095
3140
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
3096
3141
  const devinFields = rulesyncFrontmatter.devin ?? {};
3142
+ const devinFrontmatter = {
3143
+ description: rulesyncFrontmatter.description,
3144
+ ...devinFields
3145
+ };
3146
+ const body = rulesyncCommand.getBody();
3147
+ const paths = this.getSettablePaths({ global });
3097
3148
  return new DevinCommand({
3098
3149
  outputRoot,
3099
- frontmatter: {
3100
- description: rulesyncFrontmatter.description,
3101
- ...devinFields
3102
- },
3103
- body: rulesyncCommand.getBody(),
3104
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
3150
+ frontmatter: devinFrontmatter,
3151
+ body,
3152
+ relativeDirPath: paths.relativeDirPath,
3105
3153
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
3106
3154
  validate
3107
3155
  });
@@ -3215,14 +3263,17 @@ var FactorydroidCommand = class FactorydroidCommand extends ToolCommand {
3215
3263
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
3216
3264
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
3217
3265
  const factorydroidFields = rulesyncFrontmatter.factorydroid ?? {};
3266
+ const factorydroidFrontmatter = {
3267
+ description: rulesyncFrontmatter.description,
3268
+ ...factorydroidFields
3269
+ };
3270
+ const body = rulesyncCommand.getBody();
3271
+ const paths = this.getSettablePaths({ global });
3218
3272
  return new FactorydroidCommand({
3219
3273
  outputRoot,
3220
- frontmatter: {
3221
- description: rulesyncFrontmatter.description,
3222
- ...factorydroidFields
3223
- },
3224
- body: rulesyncCommand.getBody(),
3225
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
3274
+ frontmatter: factorydroidFrontmatter,
3275
+ body,
3276
+ relativeDirPath: paths.relativeDirPath,
3226
3277
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
3227
3278
  validate
3228
3279
  });
@@ -3332,7 +3383,7 @@ var GooseCommand = class GooseCommand extends ToolCommand {
3332
3383
  const where = join(this.relativeDirPath, this.relativeFilePath);
3333
3384
  let parsed;
3334
3385
  try {
3335
- parsed = load(content);
3386
+ parsed = loadYaml(content);
3336
3387
  } catch (error) {
3337
3388
  throw new Error(`Failed to parse Goose recipe (${where}): ${formatError(error)}`, { cause: error });
3338
3389
  }
@@ -3383,9 +3434,10 @@ var GooseCommand = class GooseCommand extends ToolCommand {
3383
3434
  prompt,
3384
3435
  ...extraFields
3385
3436
  };
3437
+ const paths = this.getSettablePaths({ global });
3386
3438
  return new GooseCommand({
3387
3439
  outputRoot,
3388
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
3440
+ relativeDirPath: paths.relativeDirPath,
3389
3441
  relativeFilePath,
3390
3442
  fileContent: dump(recipe, {
3391
3443
  lineWidth: -1,
@@ -3426,19 +3478,20 @@ var GooseCommand = class GooseCommand extends ToolCommand {
3426
3478
  });
3427
3479
  }
3428
3480
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
3481
+ const placeholder = dump({
3482
+ version: RECIPE_VERSION$1,
3483
+ title: "",
3484
+ description: "",
3485
+ prompt: ""
3486
+ }, {
3487
+ lineWidth: -1,
3488
+ noRefs: true
3489
+ });
3429
3490
  return new GooseCommand({
3430
3491
  outputRoot,
3431
3492
  relativeDirPath,
3432
3493
  relativeFilePath,
3433
- fileContent: dump({
3434
- version: RECIPE_VERSION$1,
3435
- title: "",
3436
- description: "",
3437
- prompt: ""
3438
- }, {
3439
- lineWidth: -1,
3440
- noRefs: true
3441
- }),
3494
+ fileContent: placeholder,
3442
3495
  validate: false
3443
3496
  });
3444
3497
  }
@@ -3595,14 +3648,17 @@ var JunieCommand = class JunieCommand extends ToolCommand {
3595
3648
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
3596
3649
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
3597
3650
  const junieFields = rulesyncFrontmatter.junie ?? {};
3651
+ const junieFrontmatter = {
3652
+ description: rulesyncFrontmatter.description,
3653
+ ...junieFields
3654
+ };
3655
+ const body = rulesyncCommand.getBody();
3656
+ const paths = this.getSettablePaths({ global });
3598
3657
  return new JunieCommand({
3599
3658
  outputRoot,
3600
- frontmatter: {
3601
- description: rulesyncFrontmatter.description,
3602
- ...junieFields
3603
- },
3604
- body: rulesyncCommand.getBody(),
3605
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
3659
+ frontmatter: junieFrontmatter,
3660
+ body,
3661
+ relativeDirPath: paths.relativeDirPath,
3606
3662
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
3607
3663
  validate
3608
3664
  });
@@ -3726,14 +3782,17 @@ var KiloCommand = class KiloCommand extends ToolCommand {
3726
3782
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
3727
3783
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
3728
3784
  const kiloFields = rulesyncFrontmatter.kilo ?? {};
3785
+ const kiloFrontmatter = {
3786
+ description: rulesyncFrontmatter.description,
3787
+ ...kiloFields
3788
+ };
3789
+ const body = rulesyncCommand.getBody();
3790
+ const paths = this.getSettablePaths({ global });
3729
3791
  return new KiloCommand({
3730
3792
  outputRoot,
3731
- frontmatter: {
3732
- description: rulesyncFrontmatter.description,
3733
- ...kiloFields
3734
- },
3735
- body: rulesyncCommand.getBody(),
3736
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
3793
+ frontmatter: kiloFrontmatter,
3794
+ body,
3795
+ relativeDirPath: paths.relativeDirPath,
3737
3796
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
3738
3797
  validate
3739
3798
  });
@@ -3985,7 +4044,7 @@ function omitPrototypePollutionKeys(record) {
3985
4044
  //#region src/features/shared/shared-config-gateway.ts
3986
4045
  function sanitizeSharedConfigValue(value) {
3987
4046
  if (Array.isArray(value)) return value.map(sanitizeSharedConfigValue);
3988
- if (!isPlainObject(value)) return value;
4047
+ if (!isPlainObject$1(value)) return value;
3989
4048
  const result = {};
3990
4049
  for (const [key, nested] of Object.entries(omitPrototypePollutionKeys(value))) result[key] = sanitizeSharedConfigValue(nested);
3991
4050
  return result;
@@ -4001,14 +4060,14 @@ function parseSharedConfig({ format, fileContent, filePath, invalidRootPolicy =
4001
4060
  const at = filePath === void 0 ? "" : ` at ${filePath}`;
4002
4061
  let parsed;
4003
4062
  try {
4004
- if (format === "yaml") parsed = load(fileContent);
4063
+ if (format === "yaml") parsed = loadYaml(fileContent);
4005
4064
  else if (format === "json") parsed = JSON.parse(fileContent);
4006
4065
  else parsed = parse(fileContent);
4007
4066
  } catch (error) {
4008
4067
  throw new Error(`Failed to parse shared config${at}: ${formatError(error)}`, { cause: error });
4009
4068
  }
4010
4069
  if (parsed === void 0 || parsed === null) return {};
4011
- if (!isPlainObject(parsed)) {
4070
+ if (!isPlainObject$1(parsed)) {
4012
4071
  if (invalidRootPolicy === "error") throw new Error(`Failed to parse shared config${at}: expected a mapping at the root`);
4013
4072
  return {};
4014
4073
  }
@@ -4051,7 +4110,7 @@ function mergeSharedConfigDeep({ base, patch }) {
4051
4110
  for (const [key, patchValue] of Object.entries(patch)) {
4052
4111
  if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
4053
4112
  const baseValue = result[key];
4054
- if (isPlainObject(baseValue) && isPlainObject(patchValue)) result[key] = mergeSharedConfigDeep({
4113
+ if (isPlainObject$1(baseValue) && isPlainObject$1(patchValue)) result[key] = mergeSharedConfigDeep({
4055
4114
  base: baseValue,
4056
4115
  patch: patchValue
4057
4116
  });
@@ -4321,14 +4380,17 @@ var OpenCodeCommand = class OpenCodeCommand extends ToolCommand {
4321
4380
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
4322
4381
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
4323
4382
  const opencodeFields = rulesyncFrontmatter.opencode ?? {};
4383
+ const opencodeFrontmatter = {
4384
+ description: rulesyncFrontmatter.description,
4385
+ ...opencodeFields
4386
+ };
4387
+ const body = rulesyncCommand.getBody();
4388
+ const paths = this.getSettablePaths({ global });
4324
4389
  return new OpenCodeCommand({
4325
4390
  outputRoot,
4326
- frontmatter: {
4327
- description: rulesyncFrontmatter.description,
4328
- ...opencodeFields
4329
- },
4330
- body: rulesyncCommand.getBody(),
4331
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
4391
+ frontmatter: opencodeFrontmatter,
4392
+ body,
4393
+ relativeDirPath: paths.relativeDirPath,
4332
4394
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
4333
4395
  validate
4334
4396
  });
@@ -4616,14 +4678,17 @@ var QwencodeCommand = class QwencodeCommand extends ToolCommand {
4616
4678
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
4617
4679
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
4618
4680
  const qwencodeFields = rulesyncFrontmatter.qwencode ?? {};
4681
+ const qwencodeFrontmatter = {
4682
+ description: rulesyncFrontmatter.description,
4683
+ ...qwencodeFields
4684
+ };
4685
+ const body = rulesyncCommand.getBody();
4686
+ const paths = this.getSettablePaths({ global });
4619
4687
  return new QwencodeCommand({
4620
4688
  outputRoot,
4621
- frontmatter: {
4622
- description: rulesyncFrontmatter.description,
4623
- ...qwencodeFields
4624
- },
4625
- body: rulesyncCommand.getBody(),
4626
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
4689
+ frontmatter: qwencodeFrontmatter,
4690
+ body,
4691
+ relativeDirPath: paths.relativeDirPath,
4627
4692
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
4628
4693
  validate
4629
4694
  });
@@ -4685,6 +4750,8 @@ const REASONIX_GLOBAL_PERMISSIONS_FILE_NAME = REASONIX_GLOBAL_MCP_FILE_NAME;
4685
4750
  const REASONIX_DIR = REASONIX_GLOBAL_DIR;
4686
4751
  const REASONIX_SETTINGS_FILE_NAME = "settings.json";
4687
4752
  const REASONIX_COMMANDS_DIR_PATH = join(REASONIX_DIR, "commands");
4753
+ const REASONIX_RULE_FILE_NAME = "REASONIX.md";
4754
+ const REASONIX_SKILLS_DIR_PATH = join(REASONIX_DIR, "skills");
4688
4755
  //#endregion
4689
4756
  //#region src/features/commands/reasonix-command.ts
4690
4757
  /**
@@ -4745,14 +4812,17 @@ var ReasonixCommand = class ReasonixCommand extends ToolCommand {
4745
4812
  static fromRulesyncCommand({ outputRoot = process.cwd(), rulesyncCommand, validate = true, global = false }) {
4746
4813
  const rulesyncFrontmatter = rulesyncCommand.getFrontmatter();
4747
4814
  const reasonixFields = rulesyncFrontmatter.reasonix ?? {};
4815
+ const reasonixFrontmatter = {
4816
+ description: rulesyncFrontmatter.description,
4817
+ ...reasonixFields
4818
+ };
4819
+ const body = rulesyncCommand.getBody();
4820
+ const paths = this.getSettablePaths({ global });
4748
4821
  return new ReasonixCommand({
4749
4822
  outputRoot,
4750
- frontmatter: {
4751
- description: rulesyncFrontmatter.description,
4752
- ...reasonixFields
4753
- },
4754
- body: rulesyncCommand.getBody(),
4755
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
4823
+ frontmatter: reasonixFrontmatter,
4824
+ body,
4825
+ relativeDirPath: paths.relativeDirPath,
4756
4826
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
4757
4827
  validate
4758
4828
  });
@@ -5050,14 +5120,15 @@ var RovodevCommand = class RovodevCommand extends ToolCommand {
5050
5120
  const paths = this.getSettablePaths({ global });
5051
5121
  const body = (await readFileContent(join(outputRoot, paths.relativeDirPath, relativeFilePath))).trim();
5052
5122
  const name = basename(relativeFilePath, ".md");
5123
+ const description = await lookupPromptDescription({
5124
+ outputRoot,
5125
+ relativeFilePath,
5126
+ name
5127
+ });
5053
5128
  return new RovodevCommand({
5054
5129
  outputRoot,
5055
5130
  name,
5056
- description: await lookupPromptDescription({
5057
- outputRoot,
5058
- relativeFilePath,
5059
- name
5060
- }),
5131
+ description,
5061
5132
  body,
5062
5133
  relativeDirPath: paths.relativeDirPath,
5063
5134
  relativeFilePath,
@@ -5090,8 +5161,8 @@ var RovodevCommand = class RovodevCommand extends ToolCommand {
5090
5161
  const existingContent = await readFileContentOrNull(join(outputRoot, ROVODEV_DIR, ROVODEV_PROMPTS_FILE_NAME));
5091
5162
  let existing = {};
5092
5163
  if (existingContent) try {
5093
- const parsed = load(existingContent);
5094
- if (isPlainObject(parsed)) existing = parsed;
5164
+ const parsed = loadYaml(existingContent);
5165
+ if (isPlainObject$1(parsed)) existing = parsed;
5095
5166
  } catch {}
5096
5167
  const prompts = rovodevCommands.map((command) => ({
5097
5168
  name: command.getName(),
@@ -5121,11 +5192,11 @@ async function lookupPromptDescription({ outputRoot, relativeFilePath, name }) {
5121
5192
  if (!manifestContent) return "";
5122
5193
  let parsed;
5123
5194
  try {
5124
- parsed = load(manifestContent);
5195
+ parsed = loadYaml(manifestContent);
5125
5196
  } catch {
5126
5197
  return "";
5127
5198
  }
5128
- if (!isPlainObject(parsed) || !Array.isArray(parsed.prompts)) return "";
5199
+ if (!isPlainObject$1(parsed) || !Array.isArray(parsed.prompts)) return "";
5129
5200
  const expectedContentFile = toPosixPath(join("prompts", relativeFilePath));
5130
5201
  const entry = parsed.prompts.find((candidate) => isRecord(candidate) && (candidate.content_file === expectedContentFile || candidate.name === name));
5131
5202
  return isRecord(entry) && typeof entry.description === "string" ? entry.description : "";
@@ -5256,14 +5327,15 @@ var TaktCommand = class TaktCommand extends ToolCommand {
5256
5327
  });
5257
5328
  const relativeFilePath = `${stem}.md`;
5258
5329
  const paths = this.getSettablePaths({ global });
5330
+ const body = prependTaktExtends({
5331
+ extendsName: typeof taktSection?.extends === "string" ? taktSection.extends : void 0,
5332
+ body: rulesyncCommand.getBody(),
5333
+ featureLabel: "command",
5334
+ sourceLabel
5335
+ });
5259
5336
  return new TaktCommand({
5260
5337
  outputRoot,
5261
- body: prependTaktExtends({
5262
- extendsName: typeof taktSection?.extends === "string" ? taktSection.extends : void 0,
5263
- body: rulesyncCommand.getBody(),
5264
- featureLabel: "command",
5265
- sourceLabel
5266
- }),
5338
+ body,
5267
5339
  relativeDirPath: paths.relativeDirPath,
5268
5340
  relativeFilePath,
5269
5341
  validate
@@ -6163,18 +6235,25 @@ const QWENCODE_HOOK_EVENTS = [
6163
6235
  * Reasonix's `.reasonix/settings.json` (project) / `~/.reasonix/settings.json`
6164
6236
  * (global) documents a ten-event surface (`PreToolUse`, `PostToolUse`,
6165
6237
  * `UserPromptSubmit`, `Stop`, `PostLLMCall`, `SessionStart`, `SessionEnd`,
6166
- * `SubagentStop`, `Notification`, `PreCompact`), but only the four events the
6167
- * upstream issue scoped in are mapped here: `PreToolUse`, `PostToolUse`,
6168
- * `UserPromptSubmit` ← `beforeSubmitPrompt`, and `Stop`. `match` (Reasonix's
6169
- * matcher field name) is honored only on `PreToolUse`/`PostToolUse`, matching
6170
- * the canonical `matcher` field's tool-event scoping used by other adapters.
6238
+ * `SubagentStop`, `Notification`, `PreCompact`). The eight events with a clean
6239
+ * canonical equivalent are mapped: `PreToolUse`, `PostToolUse`,
6240
+ * `UserPromptSubmit` ← `beforeSubmitPrompt`, `Stop`, `SessionStart`,
6241
+ * `SessionEnd`, `SubagentStop`, and `PostLLMCall` `postModelInvocation`.
6242
+ * (`Notification` and `PreCompact` have no canonical event and are left out.)
6243
+ * `match` (Reasonix's matcher field name) is honored only on
6244
+ * `PreToolUse`/`PostToolUse`, matching the canonical `matcher` field's
6245
+ * tool-event scoping used by other adapters.
6171
6246
  * @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/DESKTOP_HOOKS.zh-CN.md
6172
6247
  */
6173
6248
  const REASONIX_HOOK_EVENTS = [
6174
6249
  "preToolUse",
6175
6250
  "postToolUse",
6176
6251
  "beforeSubmitPrompt",
6177
- "stop"
6252
+ "stop",
6253
+ "sessionStart",
6254
+ "sessionEnd",
6255
+ "subagentStop",
6256
+ "postModelInvocation"
6178
6257
  ];
6179
6258
  /**
6180
6259
  * Hook events supported by Hermes Agent's native Shell Hooks system.
@@ -6610,14 +6689,18 @@ const QWENCODE_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(Object.entries(CANO
6610
6689
  /**
6611
6690
  * Map canonical camelCase event names to Reasonix PascalCase.
6612
6691
  * Reasonix explicitly mirrors Claude Code's hooks model, so it reuses the same
6613
- * PascalCase names for the four events rulesync maps.
6692
+ * PascalCase names for the events rulesync maps.
6614
6693
  * @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/DESKTOP_HOOKS.zh-CN.md
6615
6694
  */
6616
6695
  const CANONICAL_TO_REASONIX_EVENT_NAMES = {
6617
6696
  preToolUse: "PreToolUse",
6618
6697
  postToolUse: "PostToolUse",
6619
6698
  beforeSubmitPrompt: "UserPromptSubmit",
6620
- stop: "Stop"
6699
+ stop: "Stop",
6700
+ sessionStart: "SessionStart",
6701
+ sessionEnd: "SessionEnd",
6702
+ subagentStop: "SubagentStop",
6703
+ postModelInvocation: "PostLLMCall"
6621
6704
  };
6622
6705
  /**
6623
6706
  * Map Reasonix PascalCase event names to canonical camelCase.
@@ -6666,6 +6749,21 @@ function applyCommandPrefix({ def, converterConfig }) {
6666
6749
  return converterConfig.projectDirVar !== "" && typeof trimmedCommand === "string" && !trimmedCommand.startsWith("$") && (!converterConfig.prefixDotRelativeCommandsOnly || trimmedCommand.startsWith(".")) && typeof trimmedCommand === "string" ? `"${converterConfig.projectDirVar}"/${trimmedCommand.replace(/^\.\//, "")}` : def.command;
6667
6750
  }
6668
6751
  /**
6752
+ * Emit the configured boolean passthrough fields on the tool side, mapping each
6753
+ * canonical field name to its (possibly renamed) tool field name. Only boolean
6754
+ * values are carried through.
6755
+ */
6756
+ function emitBooleanPassthroughFields({ def, converterConfig }) {
6757
+ return Object.fromEntries((converterConfig.booleanPassthroughFields ?? []).filter(({ canonical }) => typeof def[canonical] === "boolean").map(({ canonical, tool }) => [tool, def[canonical]]));
6758
+ }
6759
+ /**
6760
+ * Import the configured boolean passthrough fields back into canonical fields,
6761
+ * reversing {@link emitBooleanPassthroughFields}. Only boolean values are read.
6762
+ */
6763
+ function importBooleanPassthroughFields({ h, converterConfig }) {
6764
+ return Object.fromEntries((converterConfig.booleanPassthroughFields ?? []).filter(({ tool }) => typeof h[tool] === "boolean").map(({ canonical, tool }) => [canonical, h[tool]]));
6765
+ }
6766
+ /**
6669
6767
  * Convert the definitions of a single matcher group into tool hook entries,
6670
6768
  * honoring supported hook types and passthrough fields.
6671
6769
  */
@@ -6679,6 +6777,10 @@ function buildToolHooks({ defs, converterConfig }) {
6679
6777
  converterConfig
6680
6778
  });
6681
6779
  hooks.push({
6780
+ ...emitBooleanPassthroughFields({
6781
+ def,
6782
+ converterConfig
6783
+ }),
6682
6784
  type: hookType,
6683
6785
  ...command !== void 0 && command !== null && { command },
6684
6786
  ...def.timeout !== void 0 && def.timeout !== null && { timeout: def.timeout },
@@ -6766,6 +6868,10 @@ function toolHookToCanonical({ h, rawEntry, converterConfig }) {
6766
6868
  ...prompt !== void 0 && prompt !== null && { prompt },
6767
6869
  ...converterConfig.passthroughFields?.includes("name") && typeof h.name === "string" && { name: h.name },
6768
6870
  ...converterConfig.passthroughFields?.includes("description") && typeof h.description === "string" && { description: h.description },
6871
+ ...importBooleanPassthroughFields({
6872
+ h,
6873
+ converterConfig
6874
+ }),
6769
6875
  ...rawEntry.matcher !== void 0 && rawEntry.matcher !== null && rawEntry.matcher !== "" && { matcher: rawEntry.matcher }
6770
6876
  };
6771
6877
  }
@@ -7060,7 +7166,7 @@ function combineAugmentSettings(base, local) {
7060
7166
  const baseValue = result[key];
7061
7167
  if (AUGMENTCODE_REPLACE_KEYS.has(key)) result[key] = localValue;
7062
7168
  else if (Array.isArray(localValue) && Array.isArray(baseValue)) result[key] = [...localValue, ...baseValue];
7063
- else if (isPlainObject(localValue) && isPlainObject(baseValue)) result[key] = combineAugmentSettings(baseValue, localValue);
7169
+ else if (isPlainObject$1(localValue) && isPlainObject$1(baseValue)) result[key] = combineAugmentSettings(baseValue, localValue);
7064
7170
  else result[key] = localValue;
7065
7171
  }
7066
7172
  return result;
@@ -7104,14 +7210,14 @@ async function readAugmentcodeSettingsWithLocalOverlay({ outputRoot, relativeDir
7104
7210
  } catch (error) {
7105
7211
  throw new Error(`Failed to parse AugmentCode settings at ${configPath}: ${formatError(error)}`, { cause: error });
7106
7212
  }
7107
- if (!isPlainObject(localParsed)) throw new Error(`Failed to parse AugmentCode settings at ${configPath}: expected a JSON object`);
7213
+ if (!isPlainObject$1(localParsed)) throw new Error(`Failed to parse AugmentCode settings at ${configPath}: expected a JSON object`);
7108
7214
  let baseParsed;
7109
7215
  try {
7110
7216
  baseParsed = JSON.parse(baseContent);
7111
7217
  } catch {
7112
7218
  return baseContent;
7113
7219
  }
7114
- const merged = combineAugmentSettings(isPlainObject(baseParsed) ? baseParsed : {}, localParsed);
7220
+ const merged = combineAugmentSettings(isPlainObject$1(baseParsed) ? baseParsed : {}, localParsed);
7115
7221
  return JSON.stringify(merged, null, 2);
7116
7222
  }
7117
7223
  //#endregion
@@ -7380,11 +7486,12 @@ var CodexcliConfigToml = class CodexcliConfigToml extends ToolFile {
7380
7486
  };
7381
7487
  }
7382
7488
  static async fromOutputRoot({ outputRoot }) {
7489
+ const fileContent = await buildCodexConfigTomlContent({ outputRoot });
7383
7490
  return new CodexcliConfigToml({
7384
7491
  outputRoot,
7385
7492
  relativeDirPath: CODEXCLI_DIR,
7386
7493
  relativeFilePath: CODEXCLI_MCP_FILE_NAME,
7387
- fileContent: await buildCodexConfigTomlContent({ outputRoot })
7494
+ fileContent
7388
7495
  });
7389
7496
  }
7390
7497
  };
@@ -8675,15 +8782,16 @@ var HermesagentHooks = class HermesagentHooks extends ToolHooks {
8675
8782
  }
8676
8783
  static fromRulesyncHooks({ outputRoot, rulesyncHooks, logger }) {
8677
8784
  const config = rulesyncHooks.getJson();
8785
+ const hermesHooks = canonicalToHermesHooks({
8786
+ config,
8787
+ toolOverrideHooks: config.hermesagent?.hooks,
8788
+ logger
8789
+ });
8678
8790
  return new HermesagentHooks({
8679
8791
  outputRoot,
8680
8792
  fileContent: stringifySharedConfig({
8681
8793
  format: "yaml",
8682
- document: { hooks: canonicalToHermesHooks({
8683
- config,
8684
- toolOverrideHooks: config.hermesagent?.hooks,
8685
- logger
8686
- }) }
8794
+ document: { hooks: hermesHooks }
8687
8795
  })
8688
8796
  });
8689
8797
  }
@@ -8696,7 +8804,14 @@ const JUNIE_CONVERTER_CONFIG = {
8696
8804
  toolToCanonicalEventNames: JUNIE_TO_CANONICAL_EVENT_NAMES,
8697
8805
  projectDirVar: "",
8698
8806
  supportedHookTypes: /* @__PURE__ */ new Set(["command"]),
8699
- noMatcherEvents: /* @__PURE__ */ new Set(["beforeSubmitPrompt", "stop"])
8807
+ noMatcherEvents: /* @__PURE__ */ new Set(["beforeSubmitPrompt", "stop"]),
8808
+ booleanPassthroughFields: [{
8809
+ canonical: "failClosed",
8810
+ tool: "blockOnError"
8811
+ }, {
8812
+ canonical: "async",
8813
+ tool: "async"
8814
+ }]
8700
8815
  };
8701
8816
  var JunieHooks = class JunieHooks extends ToolHooks {
8702
8817
  constructor(params) {
@@ -9732,8 +9847,9 @@ function reasonixHooksToCanonical(hooks) {
9732
9847
  * Reasonix hooks live in a Claude-Code-style but standalone JSON file —
9733
9848
  * `.reasonix/settings.json` (project) or `~/.reasonix/settings.json`
9734
9849
  * (global) — separate from the `[permissions]`/`[[plugins]]` TOML config.
9735
- * Only the four events documented in the upstream issue are mapped:
9736
- * PreToolUse/PostToolUse/UserPromptSubmit/Stop (see REASONIX_HOOK_EVENTS).
9850
+ * The eight upstream events with a clean canonical equivalent are mapped:
9851
+ * PreToolUse/PostToolUse/UserPromptSubmit/Stop plus SessionStart/SessionEnd/
9852
+ * SubagentStop/PostLLMCall (see REASONIX_HOOK_EVENTS).
9737
9853
  * @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/DESKTOP_HOOKS.zh-CN.md
9738
9854
  */
9739
9855
  var ReasonixHooks = class ReasonixHooks extends ToolHooks {
@@ -9950,11 +10066,12 @@ var VibeConfigToml = class VibeConfigToml extends ToolFile {
9950
10066
  };
9951
10067
  }
9952
10068
  static async fromOutputRoot({ outputRoot }) {
10069
+ const fileContent = await buildVibeConfigTomlContent({ outputRoot });
9953
10070
  return new VibeConfigToml({
9954
10071
  outputRoot,
9955
10072
  relativeDirPath: VIBE_DIR,
9956
10073
  relativeFilePath: VIBE_CONFIG_FILE_NAME,
9957
- fileContent: await buildVibeConfigTomlContent({ outputRoot })
10074
+ fileContent
9958
10075
  });
9959
10076
  }
9960
10077
  };
@@ -10731,9 +10848,10 @@ var ClaudecodeIgnore = class ClaudecodeIgnore extends ToolIgnore {
10731
10848
  this.patterns = jsonValue.permissions?.deny ?? [];
10732
10849
  }
10733
10850
  static getSettablePaths(params) {
10851
+ const fileMode = resolveFileMode(params?.options);
10734
10852
  return {
10735
10853
  relativeDirPath: CLAUDECODE_DIR,
10736
- relativeFilePath: fileNameForMode(resolveFileMode(params?.options))
10854
+ relativeFilePath: fileNameForMode(fileMode)
10737
10855
  };
10738
10856
  }
10739
10857
  /**
@@ -10966,11 +11084,12 @@ var DevinIgnore = class DevinIgnore extends ToolIgnore {
10966
11084
  const primaryPath = join(outputRoot, relativeDirPath, relativeFilePath);
10967
11085
  const legacyPath = join(outputRoot, relativeDirPath, DEVIN_LEGACY_IGNORE_FILE_NAME);
10968
11086
  const resolvedFilePath = !await fileExists(primaryPath) && await fileExists(legacyPath) ? DEVIN_LEGACY_IGNORE_FILE_NAME : relativeFilePath;
11087
+ const fileContent = await readFileContent(join(outputRoot, relativeDirPath, resolvedFilePath));
10969
11088
  return new DevinIgnore({
10970
11089
  outputRoot,
10971
11090
  relativeDirPath,
10972
11091
  relativeFilePath: resolvedFilePath,
10973
- fileContent: await readFileContent(join(outputRoot, relativeDirPath, resolvedFilePath)),
11092
+ fileContent,
10974
11093
  validate
10975
11094
  });
10976
11095
  }
@@ -11812,7 +11931,7 @@ function parseAmpSettingsJsonc(fileContent) {
11812
11931
  const details = errors.map((error) => `${printParseErrorCode(error.error)} at offset ${error.offset}`).join(", ");
11813
11932
  throw new Error(`Failed to parse Amp settings: ${details}`);
11814
11933
  }
11815
- if (!isPlainObject(parsed)) throw new Error("Amp settings must be a JSON object");
11934
+ if (!isPlainObject$1(parsed)) throw new Error("Amp settings must be a JSON object");
11816
11935
  return parsed;
11817
11936
  }
11818
11937
  function filterMcpServers(mcpServers) {
@@ -12134,7 +12253,7 @@ function parseAugmentcodeSettings(fileContent, relativeDirPath, relativeFilePath
12134
12253
  } catch (error) {
12135
12254
  throw new Error(`Failed to parse AugmentCode settings at ${configPath}: ${formatError(error)}`, { cause: error });
12136
12255
  }
12137
- if (!isPlainObject(parsed)) throw new Error(`Failed to parse AugmentCode settings at ${configPath}: expected a JSON object`);
12256
+ if (!isPlainObject$1(parsed)) throw new Error(`Failed to parse AugmentCode settings at ${configPath}: expected a JSON object`);
12138
12257
  return parsed;
12139
12258
  }
12140
12259
  /**
@@ -12360,7 +12479,7 @@ function parseClineSettings(fileContent, relativeDirPath, relativeFilePath) {
12360
12479
  } catch (error) {
12361
12480
  throw new Error(`Failed to parse Cline MCP settings at ${configPath}: ${formatError(error)}`, { cause: error });
12362
12481
  }
12363
- if (!isPlainObject(parsed)) throw new Error(`Failed to parse Cline MCP settings at ${configPath}: expected a JSON object`);
12482
+ if (!isPlainObject$1(parsed)) throw new Error(`Failed to parse Cline MCP settings at ${configPath}: expected a JSON object`);
12364
12483
  return parsed;
12365
12484
  }
12366
12485
  /**
@@ -12631,7 +12750,7 @@ var CodexcliMcp = class CodexcliMcp extends ToolMcp {
12631
12750
  for (const [key, value] of Object.entries(obj)) {
12632
12751
  if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
12633
12752
  if (value === null) continue;
12634
- if (isPlainObject(value)) {
12753
+ if (isPlainObject$1(value)) {
12635
12754
  const cleaned = this.removeEmptyEntries(value, depth + 1);
12636
12755
  if (Object.keys(cleaned).length === 0) continue;
12637
12756
  filtered[key] = cleaned;
@@ -13272,12 +13391,12 @@ function parseGooseConfig(fileContent, relativeDirPath, relativeFilePath) {
13272
13391
  const configPath = join(relativeDirPath, relativeFilePath);
13273
13392
  let parsed;
13274
13393
  try {
13275
- parsed = load(fileContent);
13394
+ parsed = loadYaml(fileContent);
13276
13395
  } catch (error) {
13277
13396
  throw new Error(`Failed to parse Goose config at ${configPath}: ${formatError(error)}`, { cause: error });
13278
13397
  }
13279
13398
  if (parsed === void 0 || parsed === null) return {};
13280
- if (!isPlainObject(parsed)) throw new Error(`Failed to parse Goose config at ${configPath}: expected a YAML mapping`);
13399
+ if (!isPlainObject$1(parsed)) throw new Error(`Failed to parse Goose config at ${configPath}: expected a YAML mapping`);
13281
13400
  return parsed;
13282
13401
  }
13283
13402
  /**
@@ -13322,7 +13441,7 @@ function applyGooseStdioFields(ext, config) {
13322
13441
  ext.cmd = command;
13323
13442
  if (isStringArray(config.args)) ext.args = config.args;
13324
13443
  }
13325
- if (isPlainObject(config.env)) ext.envs = omitPrototypePollutionKeys(config.env);
13444
+ if (isPlainObject$1(config.env)) ext.envs = omitPrototypePollutionKeys(config.env);
13326
13445
  }
13327
13446
  /**
13328
13447
  * Converts a single rulesync canonical MCP server into a Goose `extensions:` entry.
@@ -13337,7 +13456,7 @@ function convertServerToGooseExtension(name, config) {
13337
13456
  if (gooseType === "stdio") applyGooseStdioFields(ext, config);
13338
13457
  else if (gooseType === "sse" || gooseType === "streamable_http") {
13339
13458
  if (url !== void 0) ext.uri = url;
13340
- if (isPlainObject(config.headers)) ext.headers = omitPrototypePollutionKeys(config.headers);
13459
+ if (isPlainObject$1(config.headers)) ext.headers = omitPrototypePollutionKeys(config.headers);
13341
13460
  }
13342
13461
  ext.enabled = config.disabled !== true;
13343
13462
  const timeout = resolveGooseTimeout(config);
@@ -13379,9 +13498,9 @@ function convertFromGooseFormat(extensions) {
13379
13498
  else if (type === "stdio") server.type = "stdio";
13380
13499
  if (typeof ext.cmd === "string") server.command = ext.cmd;
13381
13500
  if (isStringArray(ext.args)) server.args = ext.args;
13382
- if (isPlainObject(ext.envs)) server.env = omitPrototypePollutionKeys(ext.envs);
13501
+ if (isPlainObject$1(ext.envs)) server.env = omitPrototypePollutionKeys(ext.envs);
13383
13502
  if (typeof ext.uri === "string") server.url = ext.uri;
13384
- if (isPlainObject(ext.headers)) server.headers = omitPrototypePollutionKeys(ext.headers);
13503
+ if (isPlainObject$1(ext.headers)) server.headers = omitPrototypePollutionKeys(ext.headers);
13385
13504
  if (ext.enabled === false) server.disabled = true;
13386
13505
  if (typeof ext.timeout === "number") server.timeout = ext.timeout;
13387
13506
  result[name] = server;
@@ -13404,7 +13523,7 @@ function buildGoosePluginStdioServer(config) {
13404
13523
  server.command = command;
13405
13524
  if (isStringArray(config.args)) server.args = config.args;
13406
13525
  }
13407
- if (isPlainObject(config.env)) server.env = omitPrototypePollutionKeys(config.env);
13526
+ if (isPlainObject$1(config.env)) server.env = omitPrototypePollutionKeys(config.env);
13408
13527
  if (typeof config.cwd === "string") server.cwd = config.cwd;
13409
13528
  return server;
13410
13529
  }
@@ -13704,7 +13823,7 @@ var GrokcliMcp = class GrokcliMcp extends ToolMcp {
13704
13823
  for (const [key, value] of Object.entries(obj)) {
13705
13824
  if (PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
13706
13825
  if (value === null) continue;
13707
- if (isPlainObject(value)) {
13826
+ if (isPlainObject$1(value)) {
13708
13827
  const cleaned = this.removeEmptyEntries(value, depth + 1);
13709
13828
  if (Object.keys(cleaned).length === 0) continue;
13710
13829
  filtered[key] = cleaned;
@@ -13766,10 +13885,10 @@ function convertServerToHermes(config) {
13766
13885
  out.command = command;
13767
13886
  if (isStringArray(config.args)) out.args = config.args;
13768
13887
  }
13769
- if (isPlainObject(config.env)) out.env = omitPrototypePollutionKeys(config.env);
13888
+ if (isPlainObject$1(config.env)) out.env = omitPrototypePollutionKeys(config.env);
13770
13889
  } else if (url !== void 0) {
13771
13890
  out.url = url;
13772
- if (isPlainObject(config.headers)) out.headers = omitPrototypePollutionKeys(config.headers);
13891
+ if (isPlainObject$1(config.headers)) out.headers = omitPrototypePollutionKeys(config.headers);
13773
13892
  }
13774
13893
  if (config.disabled === true) out.enabled = false;
13775
13894
  const timeout = resolveHermesTimeout(config);
@@ -13814,9 +13933,9 @@ function convertFromHermesFormat(mcpServers) {
13814
13933
  const server = {};
13815
13934
  if (typeof config.command === "string") server.command = config.command;
13816
13935
  if (isStringArray(config.args)) server.args = config.args;
13817
- if (isPlainObject(config.env)) server.env = omitPrototypePollutionKeys(config.env);
13936
+ if (isPlainObject$1(config.env)) server.env = omitPrototypePollutionKeys(config.env);
13818
13937
  if (typeof config.url === "string") server.url = config.url;
13819
- if (isPlainObject(config.headers)) server.headers = omitPrototypePollutionKeys(config.headers);
13938
+ if (isPlainObject$1(config.headers)) server.headers = omitPrototypePollutionKeys(config.headers);
13820
13939
  if (config.enabled === false) server.disabled = true;
13821
13940
  if (typeof config.timeout === "number") server.networkTimeout = config.timeout;
13822
13941
  if (isRecord(config.tools)) {
@@ -14753,7 +14872,9 @@ const REASONIX_PLUGIN_FIELDS = [
14753
14872
  "env",
14754
14873
  "url",
14755
14874
  "headers",
14756
- "trusted_read_only_tools"
14875
+ "trusted_read_only_tools",
14876
+ "call_timeout_seconds",
14877
+ "tool_timeout_seconds"
14757
14878
  ];
14758
14879
  var ReasonixMcp = class ReasonixMcp extends ToolMcp {
14759
14880
  toml;
@@ -14985,7 +15106,7 @@ function parseRovodevMcpJson(fileContent, relativeDirPath, relativeFilePath) {
14985
15106
  } catch (error) {
14986
15107
  throw new Error(`Failed to parse Rovodev MCP config at ${configPath}: ${formatError(error)}`, { cause: error });
14987
15108
  }
14988
- if (!isPlainObject(parsed)) throw new Error(`Failed to parse Rovodev MCP config at ${configPath}: expected a JSON object`);
15109
+ if (!isPlainObject$1(parsed)) throw new Error(`Failed to parse Rovodev MCP config at ${configPath}: expected a JSON object`);
14989
15110
  return parsed;
14990
15111
  }
14991
15112
  /**
@@ -16256,15 +16377,123 @@ const AntigravityCliPermissionsOverrideSchema = z.looseObject({
16256
16377
  enableTerminalSandbox: z.optional(z.boolean())
16257
16378
  });
16258
16379
  /**
16380
+ * Tool-scoped override block for AugmentCode. AugmentCode's `toolPermissions[]`
16381
+ * array supports "custom policy" entries the canonical allow/ask/deny model
16382
+ * cannot express: `permission.type` of `webhook-policy` / `script-policy`
16383
+ * (delegating the decision to a `webhookUrl` / `script`) and an `eventType` of
16384
+ * `tool-response` (a post-execution check rather than the default pre-execution
16385
+ * `tool-call`). These are authored here as verbatim `toolPermissions` entries
16386
+ * and prepended — ahead of the canonical-generated basic rules — into the shared
16387
+ * `.augment/settings.json`, so a webhook/script gate or tool-response check is
16388
+ * never shadowed by a regenerated allow/deny/ask entry under AugmentCode's
16389
+ * first-match-wins evaluation. The shared `permission` block continues to drive
16390
+ * the basic `allow` / `deny` / `ask-user` entries. Kept `looseObject` (verbatim
16391
+ * passthrough) so `shellInputRegex`, `eventType`, `webhookUrl`, `script`, and
16392
+ * any future policy field survive untouched. Both project and global scope are
16393
+ * supported.
16394
+ *
16395
+ * @example
16396
+ * { "toolPermissions": [
16397
+ * { "toolName": "github-api",
16398
+ * "permission": { "type": "webhook-policy", "webhookUrl": "https://api.example.com/validate" } },
16399
+ * { "toolName": "view", "eventType": "tool-response", "permission": { "type": "allow" } } ] }
16400
+ */
16401
+ const AugmentcodePermissionsOverrideSchema = z.looseObject({ toolPermissions: z.optional(z.array(z.looseObject({
16402
+ toolName: z.string(),
16403
+ permission: z.looseObject({ type: z.string() })
16404
+ }))) });
16405
+ /**
16406
+ * Tool-scoped override block for Kiro. Kiro's agent config (`.kiro/agents/<name>.json`)
16407
+ * exposes per-tool `toolsSettings` knobs with no canonical allow/ask/deny
16408
+ * category: the shell auto-trust flags `shell.autoAllowReadonly` /
16409
+ * `shell.denyByDefault`, the `aws` built-in tool's `allowedServices` /
16410
+ * `deniedServices` (+ `autoAllowReadonly`), and the `web_fetch` domain trust
16411
+ * arrays `trusted` / `blocked` (regex host patterns; documented for `web_fetch`
16412
+ * only — `web_search` has no such surface). Fields placed here are deep-merged
16413
+ * (per `toolsSettings` key, override wins at the leaf) into the shared agent
16414
+ * config, while the canonical `permission` block continues to drive
16415
+ * `shell.{allowed,denied}Commands`, `read`/`write`/`grep`/`glob` paths, and the
16416
+ * `web_fetch`/`web_search` `allowedTools` toggles. Kept `looseObject` at every
16417
+ * level (verbatim passthrough) so future Kiro `toolsSettings` fields survive.
16418
+ *
16419
+ * Kiro's MCP `autoApprove` / `disabledTools` lists are intentionally NOT modeled
16420
+ * here: they live in a SEPARATE file (`.kiro/settings/mcp.json`, under
16421
+ * `mcpServers.<name>`), not the agent config this permissions translator writes,
16422
+ * and reconciling them with the canonical `mcp__*` model is a distinct design
16423
+ * question left out of scope.
16424
+ *
16425
+ * @example
16426
+ * { "toolsSettings": { "shell": { "autoAllowReadonly": true },
16427
+ * "aws": { "allowedServices": ["s3"], "deniedServices": ["eks"] },
16428
+ * "web_fetch": { "trusted": [".*github\\.com.*"] } } }
16429
+ */
16430
+ const KiroPermissionsOverrideSchema = z.looseObject({ toolsSettings: z.optional(z.looseObject({
16431
+ shell: z.optional(z.looseObject({
16432
+ autoAllowReadonly: z.optional(z.boolean()),
16433
+ denyByDefault: z.optional(z.boolean())
16434
+ })),
16435
+ aws: z.optional(z.looseObject({
16436
+ allowedServices: z.optional(z.array(z.string())),
16437
+ deniedServices: z.optional(z.array(z.string())),
16438
+ autoAllowReadonly: z.optional(z.boolean())
16439
+ })),
16440
+ web_fetch: z.optional(z.looseObject({
16441
+ trusted: z.optional(z.array(z.string())),
16442
+ blocked: z.optional(z.array(z.string()))
16443
+ }))
16444
+ })) });
16445
+ /**
16446
+ * Codex CLI-scoped permission override.
16447
+ *
16448
+ * Codex CLI's permission surface is richer than the canonical allow/ask/deny
16449
+ * model: its approval workflow, classic sandbox system, and per-app tool gating
16450
+ * have no canonical category. Author them through a tool-scoped `codexcli`
16451
+ * override whose fields are written verbatim as top-level `.codex/config.toml`
16452
+ * keys (the override wins per key; existing sibling keys the user set directly
16453
+ * are preserved):
16454
+ * - `approval_policy` — `untrusted` | `on-request` | `never`, or a
16455
+ * `{ granular = { … } }` table (kept verbatim; the granular schema has
16456
+ * required fields that are brittle to model as typed keys).
16457
+ * - `sandbox_mode` — `read-only` | `workspace-write` | `danger-full-access`,
16458
+ * with the sibling `sandbox_workspace_write` table (`network_access`,
16459
+ * `writable_roots`, …).
16460
+ * - `apps` — per-app tool gating (`apps.<id>.tools.<tool>.approval_mode` /
16461
+ * `.enabled`, `apps.<id>.default_tools_approval_mode`).
16462
+ * - `approvals_reviewer` — the reviewer-approval surface.
16463
+ *
16464
+ * Two surfaces are deliberately NOT authorable here so the override can never
16465
+ * clobber a feature-owned key: `mcp_servers.*` per-MCP gating is owned by the
16466
+ * MCP feature (`codexcli-mcp.ts` already writes the `mcp_servers` tables in the
16467
+ * same `config.toml`), and `permissions` / `default_permissions` are owned by
16468
+ * the canonical model. Any such key placed in the override is skipped with a
16469
+ * warning. Kept `looseObject` (verbatim passthrough) so future top-level Codex
16470
+ * config keys can be authored without Rulesync modeling each one.
16471
+ *
16472
+ * @see https://developers.openai.com/codex/config-reference
16473
+ * @see https://developers.openai.com/codex/permissions
16474
+ *
16475
+ * @example
16476
+ * { "approval_policy": "on-request", "sandbox_mode": "workspace-write",
16477
+ * "sandbox_workspace_write": { "network_access": true } }
16478
+ */
16479
+ const CodexcliPermissionsOverrideSchema = z.looseObject({
16480
+ approval_policy: z.optional(z.union([z.string(), z.looseObject({})])),
16481
+ sandbox_mode: z.optional(z.string()),
16482
+ sandbox_workspace_write: z.optional(z.looseObject({})),
16483
+ apps: z.optional(z.looseObject({})),
16484
+ approvals_reviewer: z.optional(z.union([z.string(), z.looseObject({})]))
16485
+ });
16486
+ /**
16259
16487
  * Permissions configuration.
16260
16488
  * Keys are tool category names (e.g., "bash", "edit", "read", "webfetch").
16261
16489
  * Values are pattern-to-action mappings for that tool category.
16262
16490
  *
16263
16491
  * The optional `opencode`/`hermes`/`cline`/`kilo`/`claudecode`/`vibe`/`cursor`/
16264
16492
  * `qwencode`/`reasonix`/`factorydroid`/`warp`/`junie`/`takt`/`amp`/
16265
- * `antigravity-cli` keys are tool-scoped overrides consumed only by their
16266
- * respective translator (see the matching `*PermissionsOverrideSchema`); every
16267
- * other tool reads the shared `permission` block and ignores them.
16493
+ * `antigravity-cli`/`augmentcode`/`kiro`/`codexcli` keys are tool-scoped
16494
+ * overrides consumed only by their respective translator (see the matching
16495
+ * `*PermissionsOverrideSchema`); every other tool reads the shared `permission`
16496
+ * block and ignores them.
16268
16497
  *
16269
16498
  * @example
16270
16499
  * {
@@ -16288,7 +16517,10 @@ const PermissionsConfigSchema = z.looseObject({
16288
16517
  junie: z.optional(JuniePermissionsOverrideSchema),
16289
16518
  takt: z.optional(TaktPermissionsOverrideSchema),
16290
16519
  amp: z.optional(AmpPermissionsOverrideSchema),
16291
- "antigravity-cli": z.optional(AntigravityCliPermissionsOverrideSchema)
16520
+ "antigravity-cli": z.optional(AntigravityCliPermissionsOverrideSchema),
16521
+ augmentcode: z.optional(AugmentcodePermissionsOverrideSchema),
16522
+ kiro: z.optional(KiroPermissionsOverrideSchema),
16523
+ codexcli: z.optional(CodexcliPermissionsOverrideSchema)
16292
16524
  });
16293
16525
  /**
16294
16526
  * Full permissions file schema including optional $schema field.
@@ -16440,7 +16672,7 @@ function parseAmpSettings(fileContent) {
16440
16672
  const details = errors.map((error) => `${printParseErrorCode(error.error)} at offset ${error.offset}`).join(", ");
16441
16673
  throw new Error(`Failed to parse Amp settings: ${details}`);
16442
16674
  }
16443
- if (!isPlainObject(parsed)) throw new Error("Amp settings must be a JSON object");
16675
+ if (!isPlainObject$1(parsed)) throw new Error("Amp settings must be a JSON object");
16444
16676
  return parsed;
16445
16677
  }
16446
16678
  function toDisableList(value) {
@@ -16467,7 +16699,7 @@ function toPermissionsList(value) {
16467
16699
  if (!Array.isArray(value)) return [];
16468
16700
  const entries = [];
16469
16701
  for (const raw of value) {
16470
- if (!isPlainObject(raw)) continue;
16702
+ if (!isPlainObject$1(raw)) continue;
16471
16703
  const { tool, action } = raw;
16472
16704
  if (typeof tool !== "string" || typeof action !== "string") continue;
16473
16705
  if (action !== "allow" && action !== "reject" && action !== "ask" && action !== "delegate") continue;
@@ -16475,7 +16707,7 @@ function toPermissionsList(value) {
16475
16707
  ...raw,
16476
16708
  tool,
16477
16709
  action,
16478
- ...isPlainObject(raw.matches) ? { matches: raw.matches } : {}
16710
+ ...isPlainObject$1(raw.matches) ? { matches: raw.matches } : {}
16479
16711
  });
16480
16712
  }
16481
16713
  return entries;
@@ -17335,6 +17567,55 @@ function isSpecialEntry(entry) {
17335
17567
  return false;
17336
17568
  }
17337
17569
  /**
17570
+ * A composite identity for a special entry, used to de-duplicate authored
17571
+ * (`augmentcode` override) and preserved (existing-file) special entries so the
17572
+ * same policy is not emitted twice into `toolPermissions`. Every field that can
17573
+ * distinguish two special entries is included.
17574
+ */
17575
+ function specialEntryKey(entry) {
17576
+ return JSON.stringify([
17577
+ entry.toolName,
17578
+ entry.shellInputRegex ?? "",
17579
+ entry.eventType ?? "",
17580
+ entry.permission.type,
17581
+ entry.permission.webhookUrl ?? "",
17582
+ entry.permission.script ?? ""
17583
+ ]);
17584
+ }
17585
+ /**
17586
+ * Stable de-duplication of special entries by {@link specialEntryKey}, keeping
17587
+ * the first occurrence (authored entries lead, so an authored policy wins over
17588
+ * an identical preserved one).
17589
+ */
17590
+ function dedupeSpecialEntries(entries) {
17591
+ const seen = /* @__PURE__ */ new Set();
17592
+ const out = [];
17593
+ for (const entry of entries) {
17594
+ const key = specialEntryKey(entry);
17595
+ if (seen.has(key)) continue;
17596
+ seen.add(key);
17597
+ out.push(entry);
17598
+ }
17599
+ return out;
17600
+ }
17601
+ /**
17602
+ * Validate/normalize the `augmentcode` override's `toolPermissions` array into
17603
+ * typed `AugmentToolPermission` entries, dropping any malformed item (with a
17604
+ * warning so a typo is not lost silently). The override schema is intentionally
17605
+ * loose (verbatim passthrough), so entries are re-parsed through the full entry
17606
+ * schema here to guarantee shape before they are written into the shared
17607
+ * settings file.
17608
+ */
17609
+ function coerceAuthoredEntries(entries, logger) {
17610
+ const out = [];
17611
+ for (const item of entries) {
17612
+ const parsed = AugmentToolPermissionSchema.safeParse(item);
17613
+ if (parsed.success) out.push(parsed.data);
17614
+ else logger?.warn(`AugmentCode permissions: dropping malformed 'augmentcode.toolPermissions' override entry: ${formatError(parsed.error)}.`);
17615
+ }
17616
+ return out;
17617
+ }
17618
+ /**
17338
17619
  * Convert a glob-like pattern into a regex string for AugmentCode's `shellInputRegex`.
17339
17620
  * Maps glob `*` to `.*`, `?` to `.`, escapes other regex metacharacters, and anchors at both ends.
17340
17621
  */
@@ -17465,12 +17746,18 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
17465
17746
  } catch (error) {
17466
17747
  throw new Error(`Failed to parse existing AugmentCode settings at ${filePath}: ${formatError(error)}`, { cause: error });
17467
17748
  }
17749
+ const config = rulesyncPermissions.getJson();
17468
17750
  const generated = convertRulesyncToAugmentEntries({
17469
- config: rulesyncPermissions.getJson(),
17751
+ config,
17470
17752
  logger
17471
17753
  });
17472
17754
  const existingEntries = settings.toolPermissions ?? [];
17473
- const specialEntries = existingEntries.filter((entry) => isSpecialEntry(entry));
17755
+ const override = config.augmentcode;
17756
+ const authoredEntries = override?.toolPermissions ? coerceAuthoredEntries(override.toolPermissions, logger) : [];
17757
+ const authoredSpecials = authoredEntries.filter((entry) => isSpecialEntry(entry));
17758
+ const authoredBasics = authoredEntries.filter((entry) => !isSpecialEntry(entry));
17759
+ const preservedSpecials = override?.toolPermissions ? [] : existingEntries.filter((entry) => isSpecialEntry(entry));
17760
+ const specialEntries = dedupeSpecialEntries([...authoredSpecials, ...preservedSpecials]);
17474
17761
  const basicExistingEntries = existingEntries.filter((entry) => !isSpecialEntry(entry));
17475
17762
  const generatedKeys = new Set(generated.map((e) => `${e.toolName}|${e.shellInputRegex ?? ""}|${e.permission.type}`));
17476
17763
  const preservedBasicEntries = basicExistingEntries.filter((entry) => {
@@ -17481,7 +17768,11 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
17481
17768
  }
17482
17769
  return false;
17483
17770
  });
17484
- const sortedBasic = sortAugmentEntries([...generated, ...preservedBasicEntries]);
17771
+ const sortedBasic = sortAugmentEntries([
17772
+ ...generated,
17773
+ ...preservedBasicEntries,
17774
+ ...authoredBasics
17775
+ ]);
17485
17776
  const merged = {
17486
17777
  ...settings,
17487
17778
  toolPermissions: [...specialEntries, ...sortedBasic]
@@ -17505,11 +17796,14 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
17505
17796
  } catch (error) {
17506
17797
  throw new Error(`Failed to parse AugmentCode permissions content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
17507
17798
  }
17508
- const config = convertAugmentToRulesyncPermissions({
17509
- entries: settings.toolPermissions ?? [],
17799
+ const allEntries = settings.toolPermissions ?? [];
17800
+ const specialEntries = allEntries.filter((entry) => isSpecialEntry(entry));
17801
+ const result = { ...convertAugmentToRulesyncPermissions({
17802
+ entries: allEntries.filter((entry) => !isSpecialEntry(entry)),
17510
17803
  logger: moduleLogger$1
17511
- });
17512
- return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(config, null, 2) });
17804
+ }) };
17805
+ if (specialEntries.length > 0) result.augmentcode = { toolPermissions: specialEntries };
17806
+ return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(result, null, 2) });
17513
17807
  }
17514
17808
  validate() {
17515
17809
  try {
@@ -17643,10 +17937,7 @@ function convertAugmentToRulesyncPermissions({ entries, logger }) {
17643
17937
  ]);
17644
17938
  const permission = {};
17645
17939
  for (const entry of entries) {
17646
- if (isSpecialEntry(entry)) {
17647
- logger?.warn(`AugmentCode permissions: skipping advanced entry for tool '${entry.toolName}' (type '${entry.permission.type}'${entry.eventType !== void 0 ? `, eventType '${entry.eventType}'` : ""}) on import; rulesync's permission model cannot represent custom policies, eventType, webhookUrl, or script. Such entries are preserved on generate but not imported.`);
17648
- continue;
17649
- }
17940
+ if (isSpecialEntry(entry)) continue;
17650
17941
  const type = entry.permission.type;
17651
17942
  if (!isBasicAugmentType(type)) continue;
17652
17943
  const canonical = toCanonicalToolName$5(entry.toolName);
@@ -18078,6 +18369,13 @@ const WORKSPACE_WIDE_WRITE_PATTERNS = /* @__PURE__ */ new Set([
18078
18369
  ]);
18079
18370
  const CODEX_MINIMAL_KEY = ":minimal";
18080
18371
  const GLOBAL_WILDCARD_DOMAIN = "*";
18372
+ const CODEXCLI_OVERRIDE_KEYS = [
18373
+ "approval_policy",
18374
+ "sandbox_mode",
18375
+ "sandbox_workspace_write",
18376
+ "apps",
18377
+ "approvals_reviewer"
18378
+ ];
18081
18379
  var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
18082
18380
  static getSettablePaths(_options = {}) {
18083
18381
  return {
@@ -18119,6 +18417,11 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
18119
18417
  });
18120
18418
  parsed.permissions = permissionsTable;
18121
18419
  parsed.default_permissions = RULESYNC_PROFILE_NAME;
18420
+ applyCodexcliOverride({
18421
+ parsed,
18422
+ override: rulesyncPermissions.getJson().codexcli,
18423
+ logger
18424
+ });
18122
18425
  return new CodexcliPermissions({
18123
18426
  outputRoot,
18124
18427
  relativeDirPath: paths.relativeDirPath,
@@ -18143,7 +18446,12 @@ var CodexcliPermissions = class CodexcliPermissions extends ToolPermissions {
18143
18446
  profile,
18144
18447
  domainsHadUnknown
18145
18448
  });
18146
- return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(config, null, 2) });
18449
+ const override = extractCodexcliOverride(table);
18450
+ const result = Object.keys(override).length > 0 ? {
18451
+ ...config,
18452
+ codexcli: override
18453
+ } : config;
18454
+ return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(result, null, 2) });
18147
18455
  }
18148
18456
  validate() {
18149
18457
  return {
@@ -18335,6 +18643,30 @@ function toMutableTable(value) {
18335
18643
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
18336
18644
  return { ...value };
18337
18645
  }
18646
+ function isPlainObject(value) {
18647
+ return value !== null && typeof value === "object" && !Array.isArray(value);
18648
+ }
18649
+ function applyCodexcliOverride({ parsed, override, logger }) {
18650
+ if (!override) return;
18651
+ const allowed = new Set(CODEXCLI_OVERRIDE_KEYS);
18652
+ for (const [key, value] of Object.entries(override)) {
18653
+ if (!allowed.has(key)) {
18654
+ logger?.warn(`Codex CLI permission override key "${key}" is not managed and was skipped. "permissions"/"default_permissions" are owned by the canonical permission model and "mcp_servers" gating by the MCP feature.`);
18655
+ continue;
18656
+ }
18657
+ if (value === void 0) continue;
18658
+ const existing = parsed[key];
18659
+ parsed[key] = isPlainObject(existing) && isPlainObject(value) ? {
18660
+ ...existing,
18661
+ ...value
18662
+ } : value;
18663
+ }
18664
+ }
18665
+ function extractCodexcliOverride(table) {
18666
+ const override = {};
18667
+ for (const key of CODEXCLI_OVERRIDE_KEYS) if (table[key] !== void 0) override[key] = table[key];
18668
+ return override;
18669
+ }
18338
18670
  function toFilesystemRecord(value) {
18339
18671
  if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
18340
18672
  const result = {};
@@ -18502,7 +18834,11 @@ function toCursorPattern(canonical, pattern) {
18502
18834
  function toCanonicalCategory$1(cursorType, pattern) {
18503
18835
  if (cursorType === "Mcp") {
18504
18836
  const match = pattern.match(/^([^:()]+):([^:()]+)$/);
18505
- if (match) return `${MCP_CANONICAL_PREFIX$1}${match[1] ?? "*"}__${match[2] ?? "*"}`;
18837
+ if (match) {
18838
+ const server = match[1] ?? "*";
18839
+ const tool = match[2] ?? "*";
18840
+ return `${MCP_CANONICAL_PREFIX$1}${server}__${tool}`;
18841
+ }
18506
18842
  return CURSOR_TYPE_TO_CANONICAL[cursorType] ?? cursorType.toLowerCase();
18507
18843
  }
18508
18844
  return CURSOR_TYPE_TO_CANONICAL[cursorType] ?? cursorType.toLowerCase();
@@ -19249,7 +19585,7 @@ var GoosePermissions = class GoosePermissions extends ToolPermissions {
19249
19585
  const existingContent = await readFileContentOrNull(filePath) ?? "";
19250
19586
  let parsed;
19251
19587
  try {
19252
- parsed = existingContent.trim() === "" ? {} : load(existingContent);
19588
+ parsed = existingContent.trim() === "" ? {} : loadYaml(existingContent);
19253
19589
  } catch (error) {
19254
19590
  throw new Error(`Failed to parse existing Goose permission.yaml at ${filePath}: ${formatError(error)}`, { cause: error });
19255
19591
  }
@@ -19271,7 +19607,7 @@ var GoosePermissions = class GoosePermissions extends ToolPermissions {
19271
19607
  let parsed;
19272
19608
  try {
19273
19609
  const content = this.getFileContent();
19274
- parsed = content.trim() === "" ? {} : load(content);
19610
+ parsed = content.trim() === "" ? {} : loadYaml(content);
19275
19611
  } catch (error) {
19276
19612
  throw new Error(`Failed to parse Goose permissions content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
19277
19613
  }
@@ -20178,6 +20514,13 @@ const KiroAgentSchema = z.looseObject({
20178
20514
  toolsSettings: z.optional(z.record(z.string(), z.unknown()))
20179
20515
  });
20180
20516
  const UnknownRecordSchema = z.record(z.string(), z.unknown());
20517
+ const CANONICAL_SHELL_KEYS = /* @__PURE__ */ new Set(["allowedCommands", "deniedCommands"]);
20518
+ const CANONICAL_TOOL_SETTINGS_KEYS = /* @__PURE__ */ new Set([
20519
+ "read",
20520
+ "write",
20521
+ "grep",
20522
+ "glob"
20523
+ ]);
20181
20524
  var KiroPermissions = class KiroPermissions extends ToolPermissions {
20182
20525
  static getSettablePaths(_options = {}) {
20183
20526
  return {
@@ -20241,7 +20584,10 @@ var KiroPermissions = class KiroPermissions extends ToolPermissions {
20241
20584
  const allowedTools = new Set(parsed.allowedTools ?? []);
20242
20585
  if (allowedTools.has("web_fetch")) permission.webfetch = { "*": "allow" };
20243
20586
  if (allowedTools.has("web_search")) permission.websearch = { "*": "allow" };
20244
- return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify({ permission }, null, 2) });
20587
+ const kiroOverride = extractKiroOverride(toolsSettings);
20588
+ const result = { permission };
20589
+ if (kiroOverride !== void 0) result.kiro = kiroOverride;
20590
+ return this.toRulesyncPermissionsDefault({ fileContent: JSON.stringify(result, null, 2) });
20245
20591
  }
20246
20592
  validate() {
20247
20593
  return {
@@ -20291,19 +20637,71 @@ function buildKiroPermissionsFromRulesync({ config, logger, existing }) {
20291
20637
  });
20292
20638
  else logger?.warn(`Kiro permissions do not support category: ${category}. Skipping.`);
20293
20639
  }
20294
- nextToolsSettings.shell = shell;
20640
+ nextToolsSettings.shell = {
20641
+ ...preservedShellFlags(existing),
20642
+ ...shell
20643
+ };
20295
20644
  nextToolsSettings.read = pathTable(pathBuckets.read);
20296
20645
  nextToolsSettings.write = pathTable(pathBuckets.write);
20297
20646
  for (const key of ["grep", "glob"]) {
20298
20647
  const bucket = pathBuckets[key];
20299
20648
  if (bucket && (bucket.allow.length > 0 || bucket.deny.length > 0)) nextToolsSettings[key] = pathTable(bucket);
20300
20649
  }
20650
+ applyKiroOverride({
20651
+ override: config.kiro,
20652
+ nextToolsSettings,
20653
+ logger
20654
+ });
20301
20655
  return {
20302
20656
  ...existing,
20303
20657
  allowedTools: [...nextAllowedTools].toSorted(),
20304
20658
  toolsSettings: nextToolsSettings
20305
20659
  };
20306
20660
  }
20661
+ /**
20662
+ * Non-canonical `toolsSettings.shell` keys already present in the existing agent
20663
+ * config (everything except the canonical `allowed`/`deniedCommands`), so a
20664
+ * regenerate does not silently drop a hand-set `autoAllowReadonly` /
20665
+ * `denyByDefault` when no `kiro` override re-authors it.
20666
+ */
20667
+ function preservedShellFlags(existing) {
20668
+ const existingShell = asRecord$1(asRecord$1(existing.toolsSettings).shell);
20669
+ const flags = {};
20670
+ for (const [key, value] of Object.entries(existingShell)) if (!CANONICAL_SHELL_KEYS.has(key)) flags[key] = value;
20671
+ return flags;
20672
+ }
20673
+ /**
20674
+ * Deep-merge the `kiro` override's `toolsSettings` block into the generated
20675
+ * settings, one `toolsSettings` key at a time so the override's leaf fields win
20676
+ * without clobbering canonical-generated siblings.
20677
+ *
20678
+ * Guards, so the override can only author the non-canonical surfaces it is meant
20679
+ * for and can never weaken a canonical-generated deny:
20680
+ * - prototype-pollution keys are skipped before being used as object keys;
20681
+ * - fully-canonical `toolsSettings` keys (`read`/`write`/`grep`/`glob`) are
20682
+ * rejected outright with a warning (their paths are owned by the canonical
20683
+ * `permission` block);
20684
+ * - for `shell` (partly canonical), the canonical command-list leaves
20685
+ * (`allowed`/`deniedCommands`) are stripped from the override value so only the
20686
+ * auto-trust flags merge.
20687
+ */
20688
+ function applyKiroOverride({ override, nextToolsSettings, logger }) {
20689
+ const overrideToolsSettings = override?.toolsSettings;
20690
+ if (!isPlainObject$1(overrideToolsSettings)) return;
20691
+ for (const [key, value] of Object.entries(overrideToolsSettings)) {
20692
+ if (isPrototypePollutionKey(key)) continue;
20693
+ if (!isPlainObject$1(value)) continue;
20694
+ if (CANONICAL_TOOL_SETTINGS_KEYS.has(key)) {
20695
+ logger?.warn(`Kiro permissions: ignoring 'kiro.toolsSettings.${key}' override; '${key}' paths are driven by the canonical permission block.`);
20696
+ continue;
20697
+ }
20698
+ const mergeValue = key === "shell" ? Object.fromEntries(Object.entries(value).filter(([leaf]) => !CANONICAL_SHELL_KEYS.has(leaf))) : value;
20699
+ nextToolsSettings[key] = {
20700
+ ...asRecord$1(nextToolsSettings[key]),
20701
+ ...mergeValue
20702
+ };
20703
+ }
20704
+ }
20307
20705
  function pathTable(bucket) {
20308
20706
  return {
20309
20707
  allowedPaths: bucket?.allow ?? [],
@@ -20323,6 +20721,31 @@ function asRecord$1(value) {
20323
20721
  const result = UnknownRecordSchema.safeParse(value);
20324
20722
  return result.success ? result.data : {};
20325
20723
  }
20724
+ /**
20725
+ * Build the `kiro` permissions override from a parsed agent config's
20726
+ * `toolsSettings`, lifting the Kiro-specific knobs with no canonical category:
20727
+ * - `shell.*` flags other than the canonical `allowed`/`deniedCommands`
20728
+ * (e.g. `autoAllowReadonly`, `denyByDefault`), verbatim.
20729
+ * - the whole `aws` object (`allowedServices` / `deniedServices` / …), verbatim.
20730
+ * - the whole `web_fetch` object (`trusted` / `blocked`), verbatim.
20731
+ *
20732
+ * Returns `undefined` when none are present so the override key is omitted.
20733
+ */
20734
+ function extractKiroOverride(toolsSettings) {
20735
+ const overrideToolsSettings = {};
20736
+ const shellFlags = {};
20737
+ for (const [key, value] of Object.entries(asRecord$1(toolsSettings.shell))) {
20738
+ if (isPrototypePollutionKey(key)) continue;
20739
+ if (!CANONICAL_SHELL_KEYS.has(key)) shellFlags[key] = value;
20740
+ }
20741
+ if (Object.keys(shellFlags).length > 0) overrideToolsSettings.shell = shellFlags;
20742
+ const aws = asRecord$1(toolsSettings.aws);
20743
+ if (Object.keys(aws).length > 0) overrideToolsSettings.aws = aws;
20744
+ const webFetch = asRecord$1(toolsSettings.web_fetch);
20745
+ if (Object.keys(webFetch).length > 0) overrideToolsSettings.web_fetch = webFetch;
20746
+ if (Object.keys(overrideToolsSettings).length === 0) return void 0;
20747
+ return { toolsSettings: overrideToolsSettings };
20748
+ }
20326
20749
  function asStringArray(value) {
20327
20750
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
20328
20751
  }
@@ -21135,7 +21558,7 @@ var RovodevPermissions = class RovodevPermissions extends ToolPermissions {
21135
21558
  const existingContent = await readFileContentOrNull(filePath) ?? "";
21136
21559
  let parsed;
21137
21560
  try {
21138
- parsed = existingContent.trim() === "" ? {} : load(existingContent);
21561
+ parsed = existingContent.trim() === "" ? {} : loadYaml(existingContent);
21139
21562
  } catch (error) {
21140
21563
  throw new Error(`Failed to parse existing Rovodev config at ${filePath}: ${formatError(error)}`, { cause: error });
21141
21564
  }
@@ -21161,7 +21584,7 @@ var RovodevPermissions = class RovodevPermissions extends ToolPermissions {
21161
21584
  let parsed;
21162
21585
  try {
21163
21586
  const content = this.getFileContent();
21164
- parsed = content.trim() === "" ? {} : load(content);
21587
+ parsed = content.trim() === "" ? {} : loadYaml(content);
21165
21588
  } catch (error) {
21166
21589
  throw new Error(`Failed to parse Rovodev permissions content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
21167
21590
  }
@@ -21356,9 +21779,9 @@ var TaktPermissions = class TaktPermissions extends ToolPermissions {
21356
21779
  const rulesyncJson = rulesyncPermissions.getJson();
21357
21780
  const provider = resolveActiveProvider(config);
21358
21781
  const mode = deriveTaktPermissionMode(rulesyncJson);
21359
- const override = isPlainObject(rulesyncJson.takt) ? rulesyncJson.takt : void 0;
21360
- const stepOverrides = isPlainObject(override?.[TAKT_STEP_PERMISSION_OVERRIDES_KEY]) ? override[TAKT_STEP_PERMISSION_OVERRIDES_KEY] : void 0;
21361
- const overrideProviderOptions = isPlainObject(override?.[TAKT_PROVIDER_OPTIONS_KEY]) ? override[TAKT_PROVIDER_OPTIONS_KEY] : void 0;
21782
+ const override = isPlainObject$1(rulesyncJson.takt) ? rulesyncJson.takt : void 0;
21783
+ const stepOverrides = isPlainObject$1(override?.[TAKT_STEP_PERMISSION_OVERRIDES_KEY]) ? override[TAKT_STEP_PERMISSION_OVERRIDES_KEY] : void 0;
21784
+ const overrideProviderOptions = isPlainObject$1(override?.[TAKT_PROVIDER_OPTIONS_KEY]) ? override[TAKT_PROVIDER_OPTIONS_KEY] : void 0;
21362
21785
  const patch = {
21363
21786
  [TAKT_PROVIDER_PROFILES_KEY]: { [provider]: {
21364
21787
  [TAKT_DEFAULT_PERMISSION_MODE_KEY]: mode,
@@ -21389,12 +21812,12 @@ var TaktPermissions = class TaktPermissions extends ToolPermissions {
21389
21812
  invalidRootPolicy: "error"
21390
21813
  });
21391
21814
  const provider = resolveActiveProvider(config);
21392
- const profiles = isPlainObject(config[TAKT_PROVIDER_PROFILES_KEY]) ? config[TAKT_PROVIDER_PROFILES_KEY] : {};
21393
- const profile = isPlainObject(profiles[provider]) ? profiles[provider] : {};
21815
+ const profiles = isPlainObject$1(config[TAKT_PROVIDER_PROFILES_KEY]) ? config[TAKT_PROVIDER_PROFILES_KEY] : {};
21816
+ const profile = isPlainObject$1(profiles[provider]) ? profiles[provider] : {};
21394
21817
  const mode = profile[TAKT_DEFAULT_PERMISSION_MODE_KEY];
21395
21818
  const rulesyncConfig = taktModeToRulesyncConfig(mode);
21396
- const stepOverrides = isPlainObject(profile[TAKT_STEP_PERMISSION_OVERRIDES_KEY]) ? profile[TAKT_STEP_PERMISSION_OVERRIDES_KEY] : void 0;
21397
- const providerOptions = isPlainObject(config[TAKT_PROVIDER_OPTIONS_KEY]) ? config[TAKT_PROVIDER_OPTIONS_KEY] : void 0;
21819
+ const stepOverrides = isPlainObject$1(profile[TAKT_STEP_PERMISSION_OVERRIDES_KEY]) ? profile[TAKT_STEP_PERMISSION_OVERRIDES_KEY] : void 0;
21820
+ const providerOptions = isPlainObject$1(config[TAKT_PROVIDER_OPTIONS_KEY]) ? config[TAKT_PROVIDER_OPTIONS_KEY] : void 0;
21398
21821
  const taktOverride = {};
21399
21822
  if (stepOverrides && Object.keys(stepOverrides).length > 0) taktOverride[TAKT_STEP_PERMISSION_OVERRIDES_KEY] = stepOverrides;
21400
21823
  if (providerOptions && Object.keys(providerOptions).length > 0) taktOverride[TAKT_PROVIDER_OPTIONS_KEY] = providerOptions;
@@ -21426,7 +21849,7 @@ var TaktPermissions = class TaktPermissions extends ToolPermissions {
21426
21849
  function resolveActiveProvider(config) {
21427
21850
  if (typeof config[TAKT_PROVIDER_KEY] === "string" && config[TAKT_PROVIDER_KEY].trim() !== "") return config[TAKT_PROVIDER_KEY];
21428
21851
  const profiles = config[TAKT_PROVIDER_PROFILES_KEY];
21429
- if (isPlainObject(profiles)) {
21852
+ if (isPlainObject$1(profiles)) {
21430
21853
  const keys = Object.keys(profiles);
21431
21854
  if (keys.length === 1) return keys[0];
21432
21855
  }
@@ -22758,13 +23181,15 @@ var AgentsmdSkill = class AgentsmdSkill extends SimulatedSkill {
22758
23181
  return { relativeDirPath: AGENTSMD_SKILLS_DIR_PATH };
22759
23182
  }
22760
23183
  static async fromDir(params) {
22761
- return new AgentsmdSkill(await this.fromDirDefault(params));
23184
+ const baseParams = await this.fromDirDefault(params);
23185
+ return new AgentsmdSkill(baseParams);
22762
23186
  }
22763
23187
  static fromRulesyncSkill(params) {
22764
- return new AgentsmdSkill({
23188
+ const baseParams = {
22765
23189
  ...this.fromRulesyncSkillDefault(params),
22766
23190
  relativeDirPath: this.getSettablePaths().relativeDirPath
22767
- });
23191
+ };
23192
+ return new AgentsmdSkill(baseParams);
22768
23193
  }
22769
23194
  static isTargetedByRulesyncSkill(rulesyncSkill) {
22770
23195
  return this.isTargetedByRulesyncSkillDefault({
@@ -22773,7 +23198,8 @@ var AgentsmdSkill = class AgentsmdSkill extends SimulatedSkill {
22773
23198
  });
22774
23199
  }
22775
23200
  static forDeletion(params) {
22776
- return new AgentsmdSkill(this.forDeletionDefault(params));
23201
+ const baseParams = this.forDeletionDefault(params);
23202
+ return new AgentsmdSkill(baseParams);
22777
23203
  }
22778
23204
  };
22779
23205
  const RulesyncSkillFrontmatterSchema = z.looseObject({
@@ -24180,9 +24606,10 @@ var ClaudecodeSkill = class ClaudecodeSkill extends ToolSkill {
24180
24606
  })
24181
24607
  });
24182
24608
  const settablePaths = ClaudecodeSkill.getSettablePaths({ global });
24609
+ const relativeDirPath = rulesyncFrontmatter.claudecode?.["scheduled-task"] ? CLAUDECODE_SCHEDULED_TASKS_DIR_PATH : settablePaths.relativeDirPath;
24183
24610
  return new ClaudecodeSkill({
24184
24611
  outputRoot,
24185
- relativeDirPath: rulesyncFrontmatter.claudecode?.["scheduled-task"] ? CLAUDECODE_SCHEDULED_TASKS_DIR_PATH : settablePaths.relativeDirPath,
24612
+ relativeDirPath,
24186
24613
  dirName: rulesyncSkill.getDirName(),
24187
24614
  frontmatter: claudecodeFrontmatter,
24188
24615
  body: rulesyncSkill.getBody(),
@@ -24415,7 +24842,7 @@ function extractOpenaiYamlFile(otherFiles) {
24415
24842
  const rest = [];
24416
24843
  for (const file of otherFiles) {
24417
24844
  if (toPosixPath(file.relativeFilePathToDirPath) === target) try {
24418
- const loaded = load(file.fileBuffer.toString("utf-8"));
24845
+ const loaded = loadYaml(file.fileBuffer.toString("utf-8"));
24419
24846
  if (loaded !== null && typeof loaded === "object" && !Array.isArray(loaded)) {
24420
24847
  parsed = loaded;
24421
24848
  continue;
@@ -25971,9 +26398,10 @@ var KiloSkill = class KiloSkill extends ToolSkill {
25971
26398
  ...kiloSection?.compatibility !== void 0 && { compatibility: kiloSection.compatibility },
25972
26399
  ...kiloSection?.metadata !== void 0 && { metadata: kiloSection.metadata }
25973
26400
  };
26401
+ const settablePaths = KiloSkill.getSettablePaths({ global });
25974
26402
  return new KiloSkill({
25975
26403
  outputRoot,
25976
- relativeDirPath: KiloSkill.getSettablePaths({ global }).relativeDirPath,
26404
+ relativeDirPath: settablePaths.relativeDirPath,
25977
26405
  dirName: rulesyncSkill.getDirName(),
25978
26406
  frontmatter: kiloFrontmatter,
25979
26407
  body: rulesyncSkill.getBody(),
@@ -26296,9 +26724,10 @@ var OpenCodeSkill = class OpenCodeSkill extends ToolSkill {
26296
26724
  ...metadata !== void 0 && { metadata },
26297
26725
  ...opencodeSection?.["allowed-tools"] !== void 0 && { "allowed-tools": opencodeSection["allowed-tools"] }
26298
26726
  };
26727
+ const settablePaths = OpenCodeSkill.getSettablePaths({ global });
26299
26728
  return new OpenCodeSkill({
26300
26729
  outputRoot,
26301
- relativeDirPath: OpenCodeSkill.getSettablePaths({ global }).relativeDirPath,
26730
+ relativeDirPath: settablePaths.relativeDirPath,
26302
26731
  dirName: rulesyncSkill.getDirName(),
26303
26732
  frontmatter: opencodeFrontmatter,
26304
26733
  body: rulesyncSkill.getBody(),
@@ -26613,9 +27042,10 @@ var QwencodeSkill = class QwencodeSkill extends ToolSkill {
26613
27042
  ...resolvedUserInvocable !== void 0 && { "user-invocable": resolvedUserInvocable },
26614
27043
  ...resolvedDisableModelInvocation !== void 0 && { "disable-model-invocation": resolvedDisableModelInvocation }
26615
27044
  };
27045
+ const settablePaths = QwencodeSkill.getSettablePaths({ global });
26616
27046
  return new QwencodeSkill({
26617
27047
  outputRoot,
26618
- relativeDirPath: QwencodeSkill.getSettablePaths({ global }).relativeDirPath,
27048
+ relativeDirPath: settablePaths.relativeDirPath,
26619
27049
  dirName: rulesyncSkill.getDirName(),
26620
27050
  frontmatter: qwencodeFrontmatter,
26621
27051
  body: rulesyncSkill.getBody(),
@@ -26666,6 +27096,140 @@ var QwencodeSkill = class QwencodeSkill extends ToolSkill {
26666
27096
  }
26667
27097
  };
26668
27098
  //#endregion
27099
+ //#region src/features/skills/reasonix-skill.ts
27100
+ const ReasonixSkillFrontmatterSchema = z.looseObject({
27101
+ name: z.string(),
27102
+ description: z.string()
27103
+ });
27104
+ /**
27105
+ * Represents a DeepSeek-Reasonix skill directory.
27106
+ *
27107
+ * Reasonix discovers directory-layout skills (`<name>/SKILL.md`) under
27108
+ * `.reasonix/skills/` (project) and `~/.reasonix/skills/` (global); the global
27109
+ * scope is served by the processor supplying the home directory as outputRoot.
27110
+ * @see https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/GUIDE.md
27111
+ */
27112
+ var ReasonixSkill = class ReasonixSkill extends ToolSkill {
27113
+ constructor({ outputRoot = process.cwd(), relativeDirPath = REASONIX_SKILLS_DIR_PATH, dirName, frontmatter, body, otherFiles = [], validate = true, global = false }) {
27114
+ super({
27115
+ outputRoot,
27116
+ relativeDirPath,
27117
+ dirName,
27118
+ mainFile: {
27119
+ name: SKILL_FILE_NAME,
27120
+ body,
27121
+ frontmatter: { ...frontmatter }
27122
+ },
27123
+ otherFiles,
27124
+ global
27125
+ });
27126
+ if (validate) {
27127
+ const result = this.validate();
27128
+ if (!result.success) throw result.error;
27129
+ }
27130
+ }
27131
+ static getSettablePaths({ global: _global = false } = {}) {
27132
+ return { relativeDirPath: REASONIX_SKILLS_DIR_PATH };
27133
+ }
27134
+ getFrontmatter() {
27135
+ return ReasonixSkillFrontmatterSchema.parse(this.requireMainFileFrontmatter());
27136
+ }
27137
+ getBody() {
27138
+ return this.mainFile?.body ?? "";
27139
+ }
27140
+ validate() {
27141
+ if (this.mainFile === void 0) return {
27142
+ success: false,
27143
+ error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
27144
+ };
27145
+ const result = ReasonixSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
27146
+ if (!result.success) return {
27147
+ success: false,
27148
+ error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`)
27149
+ };
27150
+ return {
27151
+ success: true,
27152
+ error: null
27153
+ };
27154
+ }
27155
+ toRulesyncSkill() {
27156
+ const frontmatter = this.getFrontmatter();
27157
+ const rulesyncFrontmatter = {
27158
+ name: frontmatter.name,
27159
+ description: frontmatter.description,
27160
+ targets: ["*"]
27161
+ };
27162
+ return new RulesyncSkill({
27163
+ outputRoot: this.outputRoot,
27164
+ relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH,
27165
+ dirName: this.getDirName(),
27166
+ frontmatter: rulesyncFrontmatter,
27167
+ body: this.getBody(),
27168
+ otherFiles: this.getOtherFiles(),
27169
+ validate: true,
27170
+ global: this.global
27171
+ });
27172
+ }
27173
+ static fromRulesyncSkill({ outputRoot = process.cwd(), rulesyncSkill, validate = true, global = false }) {
27174
+ const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
27175
+ const reasonixFrontmatter = {
27176
+ name: rulesyncFrontmatter.name,
27177
+ description: rulesyncFrontmatter.description
27178
+ };
27179
+ const settablePaths = ReasonixSkill.getSettablePaths({ global });
27180
+ return new ReasonixSkill({
27181
+ outputRoot,
27182
+ relativeDirPath: settablePaths.relativeDirPath,
27183
+ dirName: rulesyncSkill.getDirName(),
27184
+ frontmatter: reasonixFrontmatter,
27185
+ body: rulesyncSkill.getBody(),
27186
+ otherFiles: rulesyncSkill.getOtherFiles(),
27187
+ validate,
27188
+ global
27189
+ });
27190
+ }
27191
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
27192
+ const targets = rulesyncSkill.getFrontmatter().targets;
27193
+ return targets.includes("*") || targets.includes("reasonix");
27194
+ }
27195
+ static async fromDir(params) {
27196
+ const loaded = await this.loadSkillDirContent({
27197
+ ...params,
27198
+ getSettablePaths: ReasonixSkill.getSettablePaths
27199
+ });
27200
+ const result = ReasonixSkillFrontmatterSchema.safeParse(loaded.frontmatter);
27201
+ if (!result.success) {
27202
+ const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
27203
+ throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
27204
+ }
27205
+ return new ReasonixSkill({
27206
+ outputRoot: loaded.outputRoot,
27207
+ relativeDirPath: loaded.relativeDirPath,
27208
+ dirName: loaded.dirName,
27209
+ frontmatter: result.data,
27210
+ body: loaded.body,
27211
+ otherFiles: loaded.otherFiles,
27212
+ validate: true,
27213
+ global: loaded.global
27214
+ });
27215
+ }
27216
+ static forDeletion({ outputRoot = process.cwd(), relativeDirPath, dirName, global = false }) {
27217
+ return new ReasonixSkill({
27218
+ outputRoot,
27219
+ relativeDirPath,
27220
+ dirName,
27221
+ frontmatter: {
27222
+ name: "",
27223
+ description: ""
27224
+ },
27225
+ body: "",
27226
+ otherFiles: [],
27227
+ validate: false,
27228
+ global
27229
+ });
27230
+ }
27231
+ };
27232
+ //#endregion
26669
27233
  //#region src/constants/replit-paths.ts
26670
27234
  const REPLIT_RULE_FILE_NAME = "replit.md";
26671
27235
  const REPLIT_SKILLS_DIR_PATH = join(".agents", "skills");
@@ -27034,17 +27598,20 @@ var TaktSkill = class TaktSkill extends ToolSkill {
27034
27598
  featureLabel: "skill",
27035
27599
  sourceLabel
27036
27600
  });
27601
+ const fileName = `${stem}.md`;
27602
+ const relativeDirPath = TAKT_SKILLS_DIR_PATH;
27603
+ const body = prependTaktExtends({
27604
+ extendsName: typeof taktSection?.extends === "string" ? taktSection.extends : void 0,
27605
+ body: rulesyncSkill.getBody(),
27606
+ featureLabel: "skill",
27607
+ sourceLabel
27608
+ });
27037
27609
  return new TaktSkill({
27038
27610
  outputRoot,
27039
- relativeDirPath: TAKT_SKILLS_DIR_PATH,
27611
+ relativeDirPath,
27040
27612
  dirName: stem,
27041
- fileName: `${stem}.md`,
27042
- body: prependTaktExtends({
27043
- extendsName: typeof taktSection?.extends === "string" ? taktSection.extends : void 0,
27044
- body: rulesyncSkill.getBody(),
27045
- featureLabel: "skill",
27046
- sourceLabel
27047
- }),
27613
+ fileName,
27614
+ body,
27048
27615
  otherFiles: rulesyncSkill.getOtherFiles(),
27049
27616
  validate,
27050
27617
  global
@@ -27342,9 +27909,10 @@ var WarpSkill = class WarpSkill extends ToolSkill {
27342
27909
  name: rulesyncFrontmatter.name,
27343
27910
  description: rulesyncFrontmatter.description
27344
27911
  };
27912
+ const settablePaths = WarpSkill.getSettablePaths({ global });
27345
27913
  return new WarpSkill({
27346
27914
  outputRoot,
27347
- relativeDirPath: WarpSkill.getSettablePaths({ global }).relativeDirPath,
27915
+ relativeDirPath: settablePaths.relativeDirPath,
27348
27916
  dirName: rulesyncSkill.getDirName(),
27349
27917
  frontmatter: warpFrontmatter,
27350
27918
  body: rulesyncSkill.getBody(),
@@ -27760,6 +28328,14 @@ const toolSkillFactories = /* @__PURE__ */ new Map([
27760
28328
  supportsGlobal: true
27761
28329
  }
27762
28330
  }],
28331
+ ["reasonix", {
28332
+ class: ReasonixSkill,
28333
+ meta: {
28334
+ supportsProject: true,
28335
+ supportsSimulated: false,
28336
+ supportsGlobal: true
28337
+ }
28338
+ }],
27763
28339
  ["replit", {
27764
28340
  class: ReplitSkill,
27765
28341
  meta: {
@@ -28153,10 +28729,12 @@ var AgentsmdSubagent = class AgentsmdSubagent extends SimulatedSubagent {
28153
28729
  return { relativeDirPath: AGENTSMD_SUBAGENTS_DIR_PATH };
28154
28730
  }
28155
28731
  static async fromFile(params) {
28156
- return new AgentsmdSubagent(await this.fromFileDefault(params));
28732
+ const baseParams = await this.fromFileDefault(params);
28733
+ return new AgentsmdSubagent(baseParams);
28157
28734
  }
28158
28735
  static fromRulesyncSubagent(params) {
28159
- return new AgentsmdSubagent(this.fromRulesyncSubagentDefault(params));
28736
+ const baseParams = this.fromRulesyncSubagentDefault(params);
28737
+ return new AgentsmdSubagent(baseParams);
28160
28738
  }
28161
28739
  static isTargetedByRulesyncSubagent(rulesyncSubagent) {
28162
28740
  return this.isTargetedByRulesyncSubagentDefault({
@@ -28321,11 +28899,12 @@ var QwencodeSubagent = class QwencodeSubagent extends ToolSubagent {
28321
28899
  };
28322
28900
  const body = rulesyncSubagent.getBody();
28323
28901
  const fileContent = stringifyFrontmatter(body, qwencodeSubagentFrontmatter, { avoidBlockScalars: true });
28902
+ const paths = this.getSettablePaths({ global });
28324
28903
  return new QwencodeSubagent({
28325
28904
  outputRoot,
28326
28905
  frontmatter: qwencodeSubagentFrontmatter,
28327
28906
  body,
28328
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
28907
+ relativeDirPath: paths.relativeDirPath,
28329
28908
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
28330
28909
  fileContent,
28331
28910
  validate,
@@ -28449,11 +29028,12 @@ var RovodevSubagent = class RovodevSubagent extends ToolSubagent {
28449
29028
  };
28450
29029
  const body = rulesyncSubagent.getBody();
28451
29030
  const fileContent = stringifyFrontmatter(body, rovodevFrontmatter, { avoidBlockScalars: true });
29031
+ const paths = this.getSettablePaths({ global });
28452
29032
  return new RovodevSubagent({
28453
29033
  outputRoot,
28454
29034
  frontmatter: rovodevFrontmatter,
28455
29035
  body,
28456
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
29036
+ relativeDirPath: paths.relativeDirPath,
28457
29037
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
28458
29038
  fileContent,
28459
29039
  validate,
@@ -28584,11 +29164,12 @@ var AugmentcodeSubagent = class AugmentcodeSubagent extends ToolSubagent {
28584
29164
  };
28585
29165
  const body = rulesyncSubagent.getBody();
28586
29166
  const fileContent = stringifyFrontmatter(body, augmentcodeFrontmatter, { avoidBlockScalars: true });
29167
+ const paths = this.getSettablePaths({ global });
28587
29168
  return new AugmentcodeSubagent({
28588
29169
  outputRoot,
28589
29170
  frontmatter: augmentcodeFrontmatter,
28590
29171
  body,
28591
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
29172
+ relativeDirPath: paths.relativeDirPath,
28592
29173
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
28593
29174
  fileContent,
28594
29175
  validate,
@@ -28723,11 +29304,12 @@ var ClaudecodeSubagent = class ClaudecodeSubagent extends ToolSubagent {
28723
29304
  const claudecodeFrontmatter = result.data;
28724
29305
  const body = rulesyncSubagent.getBody();
28725
29306
  const fileContent = stringifyFrontmatter(body, claudecodeFrontmatter);
29307
+ const paths = this.getSettablePaths({ global });
28726
29308
  return new ClaudecodeSubagent({
28727
29309
  outputRoot,
28728
29310
  frontmatter: claudecodeFrontmatter,
28729
29311
  body,
28730
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
29312
+ relativeDirPath: paths.relativeDirPath,
28731
29313
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
28732
29314
  fileContent,
28733
29315
  validate
@@ -28853,11 +29435,12 @@ var ClineSubagent = class ClineSubagent extends ToolSubagent {
28853
29435
  };
28854
29436
  const body = rulesyncSubagent.getBody();
28855
29437
  const fileContent = stringifyFrontmatter(body, clineFrontmatter, { avoidBlockScalars: true });
29438
+ const paths = this.getSettablePaths({ global });
28856
29439
  return new ClineSubagent({
28857
29440
  outputRoot,
28858
29441
  frontmatter: clineFrontmatter,
28859
29442
  body,
28860
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
29443
+ relativeDirPath: paths.relativeDirPath,
28861
29444
  relativeFilePath: rulesyncSubagent.getRelativeFilePath().replace(/\.md$/, ".yaml"),
28862
29445
  fileContent,
28863
29446
  validate,
@@ -29123,7 +29706,8 @@ var CopilotSubagent = class CopilotSubagent extends ToolSubagent {
29123
29706
  const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
29124
29707
  const copilotSection = rulesyncFrontmatter.copilot ?? {};
29125
29708
  const toolsField = copilotSection.tools;
29126
- const mergedTools = ensureRequiredTool(normalizeTools(Array.isArray(toolsField) || typeof toolsField === "string" ? toolsField : void 0));
29709
+ const userTools = normalizeTools(Array.isArray(toolsField) || typeof toolsField === "string" ? toolsField : void 0);
29710
+ const mergedTools = ensureRequiredTool(userTools);
29127
29711
  const copilotFrontmatter = {
29128
29712
  name: rulesyncFrontmatter.name,
29129
29713
  description: rulesyncFrontmatter.description,
@@ -29132,11 +29716,12 @@ var CopilotSubagent = class CopilotSubagent extends ToolSubagent {
29132
29716
  };
29133
29717
  const body = rulesyncSubagent.getBody();
29134
29718
  const fileContent = stringifyFrontmatter(body, copilotFrontmatter);
29719
+ const paths = this.getSettablePaths({ global });
29135
29720
  return new CopilotSubagent({
29136
29721
  outputRoot,
29137
29722
  frontmatter: copilotFrontmatter,
29138
29723
  body,
29139
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
29724
+ relativeDirPath: paths.relativeDirPath,
29140
29725
  relativeFilePath: toCopilotAgentFilePath(rulesyncSubagent.getRelativeFilePath()),
29141
29726
  fileContent,
29142
29727
  validate,
@@ -29309,11 +29894,12 @@ var CopilotcliSubagent = class CopilotcliSubagent extends ToolSubagent {
29309
29894
  const copilotCliFrontmatter = result.data;
29310
29895
  const body = rulesyncSubagent.getBody();
29311
29896
  const fileContent = stringifyFrontmatter(body, copilotCliFrontmatter);
29897
+ const paths = this.getSettablePaths({ global });
29312
29898
  return new CopilotcliSubagent({
29313
29899
  outputRoot,
29314
29900
  frontmatter: copilotCliFrontmatter,
29315
29901
  body,
29316
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
29902
+ relativeDirPath: paths.relativeDirPath,
29317
29903
  relativeFilePath: toCopilotCliAgentFilePath(rulesyncSubagent.getRelativeFilePath()),
29318
29904
  fileContent,
29319
29905
  validate,
@@ -29427,11 +30013,12 @@ var CursorSubagent = class CursorSubagent extends ToolSubagent {
29427
30013
  };
29428
30014
  const body = rulesyncSubagent.getBody();
29429
30015
  const fileContent = stringifyFrontmatter(body, cursorFrontmatter, { avoidBlockScalars: true });
30016
+ const paths = this.getSettablePaths({ global });
29430
30017
  return new CursorSubagent({
29431
30018
  outputRoot,
29432
30019
  frontmatter: cursorFrontmatter,
29433
30020
  body,
29434
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
30021
+ relativeDirPath: paths.relativeDirPath,
29435
30022
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
29436
30023
  fileContent,
29437
30024
  validate,
@@ -29865,11 +30452,12 @@ var FactorydroidSubagent = class FactorydroidSubagent extends ToolSubagent {
29865
30452
  const factorydroidFrontmatter = result.data;
29866
30453
  const body = rulesyncSubagent.getBody();
29867
30454
  const fileContent = stringifyFrontmatter(body, factorydroidFrontmatter);
30455
+ const paths = this.getSettablePaths({ global });
29868
30456
  return new FactorydroidSubagent({
29869
30457
  outputRoot,
29870
30458
  frontmatter: factorydroidFrontmatter,
29871
30459
  body,
29872
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
30460
+ relativeDirPath: paths.relativeDirPath,
29873
30461
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
29874
30462
  fileContent,
29875
30463
  validate,
@@ -30007,10 +30595,11 @@ var GooseSubagent = class GooseSubagent extends ToolSubagent {
30007
30595
  instructions,
30008
30596
  ...extraFields
30009
30597
  };
30598
+ const paths = this.getSettablePaths({ global });
30010
30599
  return new GooseSubagent({
30011
30600
  outputRoot,
30012
30601
  recipe,
30013
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
30602
+ relativeDirPath: paths.relativeDirPath,
30014
30603
  relativeFilePath,
30015
30604
  fileContent: dump(recipe, {
30016
30605
  lineWidth: -1,
@@ -30043,7 +30632,7 @@ var GooseSubagent = class GooseSubagent extends ToolSubagent {
30043
30632
  const fileContent = await readFileContent(filePath);
30044
30633
  let parsed;
30045
30634
  try {
30046
- parsed = load(fileContent);
30635
+ parsed = loadYaml(fileContent);
30047
30636
  } catch (error) {
30048
30637
  throw new Error(`Failed to parse Goose recipe (${filePath}): ${formatError(error)}`, { cause: error });
30049
30638
  }
@@ -30145,11 +30734,12 @@ var GrokcliSubagent = class GrokcliSubagent extends ToolSubagent {
30145
30734
  };
30146
30735
  const body = rulesyncSubagent.getBody();
30147
30736
  const fileContent = stringifyFrontmatter(body, grokcliSubagentFrontmatter, { avoidBlockScalars: true });
30737
+ const paths = this.getSettablePaths({ global });
30148
30738
  return new GrokcliSubagent({
30149
30739
  outputRoot,
30150
30740
  frontmatter: grokcliSubagentFrontmatter,
30151
30741
  body,
30152
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
30742
+ relativeDirPath: paths.relativeDirPath,
30153
30743
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
30154
30744
  fileContent,
30155
30745
  validate,
@@ -30385,9 +30975,10 @@ var HermesagentSubagent = class HermesagentSubagent extends ToolSubagent {
30385
30975
  }
30386
30976
  static fromRulesyncSubagent({ rulesyncSubagent, outputRoot }) {
30387
30977
  const spec = getSubagentSpec(rulesyncSubagent);
30978
+ const slug = String(spec.slug);
30388
30979
  return new HermesagentSubagent({
30389
30980
  relativeDirPath: HERMESAGENT_RULESYNC_SUBAGENTS_DIR_PATH,
30390
- relativeFilePath: `${String(spec.slug)}.json`,
30981
+ relativeFilePath: `${slug}.json`,
30391
30982
  fileContent: `${JSON.stringify(spec, null, 2)}\n`,
30392
30983
  outputRoot
30393
30984
  });
@@ -30521,11 +31112,12 @@ var JunieSubagent = class JunieSubagent extends ToolSubagent {
30521
31112
  const junieFrontmatter = result.data;
30522
31113
  const body = rulesyncSubagent.getBody();
30523
31114
  const fileContent = stringifyFrontmatter(body, junieFrontmatter);
31115
+ const paths = this.getSettablePaths({ global });
30524
31116
  return new JunieSubagent({
30525
31117
  outputRoot,
30526
31118
  frontmatter: junieFrontmatter,
30527
31119
  body,
30528
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
31120
+ relativeDirPath: paths.relativeDirPath,
30529
31121
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
30530
31122
  fileContent,
30531
31123
  validate,
@@ -30716,11 +31308,12 @@ var KiloSubagent = class KiloSubagent extends OpenCodeStyleSubagent {
30716
31308
  const kiloFrontmatter = parseResult.data;
30717
31309
  const body = rulesyncSubagent.getBody();
30718
31310
  const fileContent = stringifyFrontmatter(body, kiloFrontmatter);
31311
+ const paths = this.getSettablePaths({ global });
30719
31312
  return new KiloSubagent({
30720
31313
  outputRoot,
30721
31314
  frontmatter: kiloFrontmatter,
30722
31315
  body,
30723
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
31316
+ relativeDirPath: paths.relativeDirPath,
30724
31317
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
30725
31318
  fileContent,
30726
31319
  validate,
@@ -30992,11 +31585,12 @@ var KiroIdeSubagent = class KiroIdeSubagent extends ToolSubagent {
30992
31585
  const frontmatter = result.data;
30993
31586
  const body = rulesyncSubagent.getBody();
30994
31587
  const fileContent = stringifyFrontmatter(body, frontmatter);
31588
+ const paths = this.getSettablePaths({ global });
30995
31589
  return new KiroIdeSubagent({
30996
31590
  outputRoot,
30997
31591
  frontmatter,
30998
31592
  body,
30999
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
31593
+ relativeDirPath: paths.relativeDirPath,
31000
31594
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
31001
31595
  fileContent,
31002
31596
  validate,
@@ -31140,11 +31734,12 @@ var OpenCodeSubagent = class OpenCodeSubagent extends OpenCodeStyleSubagent {
31140
31734
  const opencodeFrontmatter = parseResult.data;
31141
31735
  const body = rulesyncSubagent.getBody();
31142
31736
  const fileContent = stringifyFrontmatter(body, opencodeFrontmatter);
31737
+ const paths = this.getSettablePaths({ global });
31143
31738
  return new OpenCodeSubagent({
31144
31739
  outputRoot,
31145
31740
  frontmatter: opencodeFrontmatter,
31146
31741
  body,
31147
- relativeDirPath: this.getSettablePaths({ global }).relativeDirPath,
31742
+ relativeDirPath: paths.relativeDirPath,
31148
31743
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
31149
31744
  fileContent,
31150
31745
  validate,
@@ -31431,7 +32026,7 @@ var RooSubagent = class RooSubagent extends ToolSubagent {
31431
32026
  const fileContent = await readFileContent(filePath);
31432
32027
  let parsed;
31433
32028
  try {
31434
- parsed = load(fileContent);
32029
+ parsed = loadYaml(fileContent);
31435
32030
  } catch (error) {
31436
32031
  throw new Error(`Failed to parse .roomodes (${filePath}): ${formatError(error)}`, { cause: error });
31437
32032
  }
@@ -32433,11 +33028,12 @@ var AiassistantRule = class AiassistantRule extends ToolRule {
32433
33028
  }
32434
33029
  static async fromFile({ outputRoot = process.cwd(), relativeFilePath, validate = true }) {
32435
33030
  const relativeDirPath = this.getSettablePaths().nonRoot.relativeDirPath;
33031
+ const fileContent = await readFileContent(join(outputRoot, relativeDirPath, relativeFilePath));
32436
33032
  return new AiassistantRule({
32437
33033
  outputRoot,
32438
33034
  relativeDirPath,
32439
33035
  relativeFilePath,
32440
- fileContent: (await readFileContent(join(outputRoot, relativeDirPath, relativeFilePath))).trim(),
33036
+ fileContent: fileContent.trim(),
32441
33037
  validate,
32442
33038
  root: false
32443
33039
  });
@@ -32538,13 +33134,14 @@ var AmpRule = class AmpRule extends ToolRule {
32538
33134
  };
32539
33135
  }
32540
33136
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
33137
+ const isRoot = relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath;
32541
33138
  return new AmpRule({
32542
33139
  outputRoot,
32543
33140
  relativeDirPath,
32544
33141
  relativeFilePath,
32545
33142
  fileContent: "",
32546
33143
  validate: false,
32547
- root: relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath
33144
+ root: isRoot
32548
33145
  });
32549
33146
  }
32550
33147
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -32627,13 +33224,14 @@ var AntigravityCliRule = class AntigravityCliRule extends ToolRule {
32627
33224
  };
32628
33225
  }
32629
33226
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
33227
+ const isRoot = relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath;
32630
33228
  return new AntigravityCliRule({
32631
33229
  outputRoot,
32632
33230
  relativeDirPath,
32633
33231
  relativeFilePath,
32634
33232
  fileContent: "",
32635
33233
  validate: false,
32636
- root: relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath
33234
+ root: isRoot
32637
33235
  });
32638
33236
  }
32639
33237
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -33047,13 +33645,14 @@ var AugmentcodeLegacyRule = class AugmentcodeLegacyRule extends ToolRule {
33047
33645
  });
33048
33646
  }
33049
33647
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
33648
+ const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
33050
33649
  return new AugmentcodeLegacyRule({
33051
33650
  outputRoot,
33052
33651
  relativeDirPath,
33053
33652
  relativeFilePath,
33054
33653
  fileContent: "",
33055
33654
  validate: false,
33056
- root: relativeFilePath === this.getSettablePaths().root.relativeFilePath
33655
+ root: isRoot
33057
33656
  });
33058
33657
  }
33059
33658
  };
@@ -33289,13 +33888,14 @@ var ClaudecodeLegacyRule = class ClaudecodeLegacyRule extends ToolRule {
33289
33888
  };
33290
33889
  }
33291
33890
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
33891
+ const isRoot = relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath;
33292
33892
  return new ClaudecodeLegacyRule({
33293
33893
  outputRoot,
33294
33894
  relativeDirPath,
33295
33895
  relativeFilePath,
33296
33896
  fileContent: "",
33297
33897
  validate: false,
33298
- root: relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath
33898
+ root: isRoot
33299
33899
  });
33300
33900
  }
33301
33901
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -33394,6 +33994,7 @@ var ClaudecodeRule = class ClaudecodeRule extends ToolRule {
33394
33994
  });
33395
33995
  }
33396
33996
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
33997
+ const isRoot = relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath;
33397
33998
  return new ClaudecodeRule({
33398
33999
  outputRoot,
33399
34000
  relativeDirPath,
@@ -33401,7 +34002,7 @@ var ClaudecodeRule = class ClaudecodeRule extends ToolRule {
33401
34002
  frontmatter: {},
33402
34003
  body: "",
33403
34004
  validate: false,
33404
- root: relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath
34005
+ root: isRoot
33405
34006
  });
33406
34007
  }
33407
34008
  static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
@@ -33917,6 +34518,13 @@ var CopilotRule = class CopilotRule extends ToolRule {
33917
34518
  }
33918
34519
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
33919
34520
  const paths = this.getSettablePaths({ global });
34521
+ const isRoot = sameRelativePath({
34522
+ dir: relativeDirPath,
34523
+ file: relativeFilePath
34524
+ }, {
34525
+ dir: paths.root.relativeDirPath,
34526
+ file: paths.root.relativeFilePath
34527
+ });
33920
34528
  return new CopilotRule({
33921
34529
  outputRoot,
33922
34530
  relativeDirPath,
@@ -33924,13 +34532,7 @@ var CopilotRule = class CopilotRule extends ToolRule {
33924
34532
  frontmatter: {},
33925
34533
  body: "",
33926
34534
  validate: false,
33927
- root: sameRelativePath({
33928
- dir: relativeDirPath,
33929
- file: relativeFilePath
33930
- }, {
33931
- dir: paths.root.relativeDirPath,
33932
- file: paths.root.relativeFilePath
33933
- })
34535
+ root: isRoot
33934
34536
  });
33935
34537
  }
33936
34538
  validate() {
@@ -34594,13 +35196,14 @@ var FactorydroidRule = class FactorydroidRule extends ToolRule {
34594
35196
  }
34595
35197
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
34596
35198
  const paths = this.getSettablePaths({ global });
35199
+ const isRoot = relativeFilePath === paths.root.relativeFilePath && relativeDirPath === paths.root.relativeDirPath;
34597
35200
  return new FactorydroidRule({
34598
35201
  outputRoot,
34599
35202
  relativeDirPath,
34600
35203
  relativeFilePath,
34601
35204
  fileContent: "",
34602
35205
  validate: false,
34603
- root: relativeFilePath === paths.root.relativeFilePath && relativeDirPath === paths.root.relativeDirPath
35206
+ root: isRoot
34604
35207
  });
34605
35208
  }
34606
35209
  static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
@@ -34696,13 +35299,14 @@ var GooseRule = class GooseRule extends ToolRule {
34696
35299
  }
34697
35300
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
34698
35301
  const paths = this.getSettablePaths({ global });
35302
+ const isRoot = relativeFilePath === paths.root.relativeFilePath && (relativeDirPath === "." || relativeDirPath === paths.root.relativeDirPath);
34699
35303
  return new GooseRule({
34700
35304
  outputRoot,
34701
35305
  relativeDirPath,
34702
35306
  relativeFilePath,
34703
35307
  fileContent: "",
34704
35308
  validate: false,
34705
- root: relativeFilePath === paths.root.relativeFilePath && (relativeDirPath === "." || relativeDirPath === paths.root.relativeDirPath)
35309
+ root: isRoot
34706
35310
  });
34707
35311
  }
34708
35312
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -34906,11 +35510,12 @@ var JunieRule = class JunieRule extends ToolRule {
34906
35510
  const settablePaths = this.getSettablePaths();
34907
35511
  if (!settablePaths.nonRoot) throw new Error("JunieRule project settable paths must include a nonRoot path");
34908
35512
  const relativeDirPath = isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath;
35513
+ const fileContent = await readFileContent(join(outputRoot, join(relativeDirPath, relativeFilePath)));
34909
35514
  return new JunieRule({
34910
35515
  outputRoot,
34911
35516
  relativeDirPath,
34912
35517
  relativeFilePath,
34913
- fileContent: await readFileContent(join(outputRoot, join(relativeDirPath, relativeFilePath))),
35518
+ fileContent,
34914
35519
  validate,
34915
35520
  root: isRoot
34916
35521
  });
@@ -34945,13 +35550,14 @@ var JunieRule = class JunieRule extends ToolRule {
34945
35550
  };
34946
35551
  }
34947
35552
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
35553
+ const isRoot = JunieRule.isRootRelativeFilePath(relativeFilePath);
34948
35554
  return new JunieRule({
34949
35555
  outputRoot,
34950
35556
  relativeDirPath,
34951
35557
  relativeFilePath,
34952
35558
  fileContent: "",
34953
35559
  validate: false,
34954
- root: JunieRule.isRootRelativeFilePath(relativeFilePath)
35560
+ root: isRoot
34955
35561
  });
34956
35562
  }
34957
35563
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -35025,13 +35631,14 @@ var KiloRule = class KiloRule extends ToolRule {
35025
35631
  };
35026
35632
  }
35027
35633
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
35634
+ const isRoot = relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath;
35028
35635
  return new KiloRule({
35029
35636
  outputRoot,
35030
35637
  relativeDirPath,
35031
35638
  relativeFilePath,
35032
35639
  fileContent: "",
35033
35640
  validate: false,
35034
- root: relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath
35641
+ root: isRoot
35035
35642
  });
35036
35643
  }
35037
35644
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -35120,11 +35727,12 @@ var KiroRule = class KiroRule extends ToolRule {
35120
35727
  const paths = this.getSettablePaths({ global });
35121
35728
  const isRoot = "root" in paths && relativeFilePath === paths.root.relativeFilePath;
35122
35729
  const relativeDirPath = paths.nonRoot?.relativeDirPath ?? buildToolPath(".kiro", "steering");
35730
+ const fileContent = await readFileContent(join(outputRoot, relativeDirPath, relativeFilePath));
35123
35731
  return new KiroRule({
35124
35732
  outputRoot,
35125
35733
  relativeDirPath,
35126
35734
  relativeFilePath,
35127
- fileContent: await readFileContent(join(outputRoot, relativeDirPath, relativeFilePath)),
35735
+ fileContent,
35128
35736
  validate,
35129
35737
  root: isRoot
35130
35738
  });
@@ -35299,13 +35907,14 @@ var OpenCodeRule = class OpenCodeRule extends ToolRule {
35299
35907
  };
35300
35908
  }
35301
35909
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
35910
+ const isRoot = relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath;
35302
35911
  return new OpenCodeRule({
35303
35912
  outputRoot,
35304
35913
  relativeDirPath,
35305
35914
  relativeFilePath,
35306
35915
  fileContent: "",
35307
35916
  validate: false,
35308
- root: relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath
35917
+ root: isRoot
35309
35918
  });
35310
35919
  }
35311
35920
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -35390,13 +35999,14 @@ var PiRule = class PiRule extends ToolRule {
35390
35999
  }
35391
36000
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
35392
36001
  const { root } = this.getSettablePaths({ global });
36002
+ const isRoot = relativeFilePath === "AGENTS.md" && (relativeDirPath === "." || relativeDirPath === root.relativeDirPath);
35393
36003
  return new PiRule({
35394
36004
  outputRoot,
35395
36005
  relativeDirPath,
35396
36006
  relativeFilePath,
35397
36007
  fileContent: "",
35398
36008
  validate: false,
35399
- root: relativeFilePath === "AGENTS.md" && (relativeDirPath === "." || relativeDirPath === root.relativeDirPath)
36009
+ root: isRoot
35400
36010
  });
35401
36011
  }
35402
36012
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -35624,6 +36234,72 @@ var QwencodeRule = class QwencodeRule extends ToolRule {
35624
36234
  }
35625
36235
  };
35626
36236
  //#endregion
36237
+ //#region src/features/rules/reasonix-rule.ts
36238
+ var ReasonixRule = class ReasonixRule extends ToolRule {
36239
+ constructor({ fileContent, root, ...rest }) {
36240
+ super({
36241
+ ...rest,
36242
+ fileContent,
36243
+ root: root ?? false
36244
+ });
36245
+ }
36246
+ static getSettablePaths({ global = false } = {}) {
36247
+ return { root: {
36248
+ relativeDirPath: global ? REASONIX_GLOBAL_DIR : ".",
36249
+ relativeFilePath: REASONIX_RULE_FILE_NAME
36250
+ } };
36251
+ }
36252
+ static async fromFile({ outputRoot = process.cwd(), relativeFilePath: _relativeFilePath, validate = true, global = false }) {
36253
+ const { root } = this.getSettablePaths({ global });
36254
+ const fileContent = await readFileContent(join(outputRoot, join(root.relativeDirPath, root.relativeFilePath)));
36255
+ return new ReasonixRule({
36256
+ outputRoot,
36257
+ relativeDirPath: root.relativeDirPath,
36258
+ relativeFilePath: root.relativeFilePath,
36259
+ fileContent,
36260
+ validate,
36261
+ root: true
36262
+ });
36263
+ }
36264
+ static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
36265
+ const { root } = this.getSettablePaths({ global });
36266
+ const isRoot = rulesyncRule.getFrontmatter().root ?? false;
36267
+ return new ReasonixRule({
36268
+ outputRoot,
36269
+ relativeDirPath: root.relativeDirPath,
36270
+ relativeFilePath: root.relativeFilePath,
36271
+ fileContent: rulesyncRule.getBody(),
36272
+ validate,
36273
+ root: isRoot
36274
+ });
36275
+ }
36276
+ toRulesyncRule() {
36277
+ return this.toRulesyncRuleDefault();
36278
+ }
36279
+ validate() {
36280
+ return {
36281
+ success: true,
36282
+ error: null
36283
+ };
36284
+ }
36285
+ static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
36286
+ return new ReasonixRule({
36287
+ outputRoot,
36288
+ relativeDirPath,
36289
+ relativeFilePath,
36290
+ fileContent: "",
36291
+ validate: false,
36292
+ root: relativeFilePath === "REASONIX.md" && (relativeDirPath === "." || relativeDirPath === ".reasonix")
36293
+ });
36294
+ }
36295
+ static isTargetedByRulesyncRule(rulesyncRule) {
36296
+ return this.isTargetedByRulesyncRuleDefault({
36297
+ rulesyncRule,
36298
+ toolTarget: "reasonix"
36299
+ });
36300
+ }
36301
+ };
36302
+ //#endregion
35627
36303
  //#region src/features/rules/replit-rule.ts
35628
36304
  /**
35629
36305
  * Rule generator for Replit Agent
@@ -35674,13 +36350,14 @@ var ReplitRule = class ReplitRule extends ToolRule {
35674
36350
  };
35675
36351
  }
35676
36352
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
36353
+ const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
35677
36354
  return new ReplitRule({
35678
36355
  outputRoot,
35679
36356
  relativeDirPath,
35680
36357
  relativeFilePath,
35681
36358
  fileContent: "",
35682
36359
  validate: false,
35683
- root: relativeFilePath === this.getSettablePaths().root.relativeFilePath
36360
+ root: isRoot
35684
36361
  });
35685
36362
  }
35686
36363
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -35831,11 +36508,12 @@ var RovodevRule = class RovodevRule extends ToolRule {
35831
36508
  }
35832
36509
  static async fromModularFile({ outputRoot, relativeFilePath, relativeDirPath, validate, global }) {
35833
36510
  if (!this.isAllowedModularRulesRelativePath(relativeFilePath)) throw new Error(`Reserved Rovodev memory basename under modular-rules (not a modular rule): ${join(relativeDirPath, relativeFilePath)}`);
36511
+ const fileContent = await readFileContent(join(outputRoot, relativeDirPath, relativeFilePath));
35834
36512
  return new RovodevRule({
35835
36513
  outputRoot,
35836
36514
  relativeDirPath,
35837
36515
  relativeFilePath,
35838
- fileContent: await readFileContent(join(outputRoot, relativeDirPath, relativeFilePath)),
36516
+ fileContent,
35839
36517
  validate,
35840
36518
  global,
35841
36519
  root: false
@@ -35846,11 +36524,12 @@ var RovodevRule = class RovodevRule extends ToolRule {
35846
36524
  const agentsMdExpectedLocationsDescription = "alternativeRoots" in paths && paths.alternativeRoots && paths.alternativeRoots.length > 0 ? `${join(paths.root.relativeDirPath, paths.root.relativeFilePath)} or project root` : join(paths.root.relativeDirPath, paths.root.relativeFilePath);
35847
36525
  if (relativeFilePath !== "AGENTS.md") throw new Error(`Rovodev rules support only AGENTS.md at ${agentsMdExpectedLocationsDescription}, got: ${join(relativeDirPath, relativeFilePath)}`);
35848
36526
  if (!(relativeDirPath === paths.root.relativeDirPath || "alternativeRoots" in paths && paths.alternativeRoots?.some((alt) => alt.relativeDirPath === relativeDirPath && alt.relativeFilePath === relativeFilePath))) throw new Error(`Rovodev AGENTS.md must be at ${agentsMdExpectedLocationsDescription}, got: ${join(relativeDirPath, relativeFilePath)}`);
36527
+ const fileContent = await readFileContent(join(outputRoot, relativeDirPath, relativeFilePath));
35849
36528
  return new RovodevRule({
35850
36529
  outputRoot,
35851
36530
  relativeDirPath,
35852
36531
  relativeFilePath,
35853
- fileContent: await readFileContent(join(outputRoot, relativeDirPath, relativeFilePath)),
36532
+ fileContent,
35854
36533
  validate,
35855
36534
  global,
35856
36535
  root: true
@@ -36041,16 +36720,18 @@ var TaktRule = class TaktRule extends ToolRule {
36041
36720
  sourceLabel
36042
36721
  });
36043
36722
  const relativeFilePath = `${stem}.md`;
36723
+ const relativeDirPath = resolveTaktRuleFacet(taktSection?.facet) === "output-contracts" ? TAKT_OUTPUT_CONTRACTS_DIR_PATH : TAKT_RULES_DIR_PATH;
36724
+ const body = prependTaktExtends({
36725
+ extendsName: typeof taktSection?.extends === "string" ? taktSection.extends : void 0,
36726
+ body: rulesyncRule.getBody(),
36727
+ featureLabel: "rule",
36728
+ sourceLabel
36729
+ });
36044
36730
  return new TaktRule({
36045
36731
  outputRoot,
36046
- relativeDirPath: resolveTaktRuleFacet(taktSection?.facet) === "output-contracts" ? TAKT_OUTPUT_CONTRACTS_DIR_PATH : TAKT_RULES_DIR_PATH,
36732
+ relativeDirPath,
36047
36733
  relativeFilePath,
36048
- body: prependTaktExtends({
36049
- extendsName: typeof taktSection?.extends === "string" ? taktSection.extends : void 0,
36050
- body: rulesyncRule.getBody(),
36051
- featureLabel: "rule",
36052
- sourceLabel
36053
- }),
36734
+ body,
36054
36735
  validate,
36055
36736
  root: false
36056
36737
  });
@@ -36118,13 +36799,14 @@ var VibeRule = class VibeRule extends ToolRule {
36118
36799
  };
36119
36800
  }
36120
36801
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
36802
+ const isRoot = relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath;
36121
36803
  return new VibeRule({
36122
36804
  outputRoot,
36123
36805
  relativeDirPath,
36124
36806
  relativeFilePath,
36125
36807
  fileContent: "",
36126
36808
  validate: false,
36127
- root: relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath
36809
+ root: isRoot
36128
36810
  });
36129
36811
  }
36130
36812
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -36186,13 +36868,14 @@ var WarpRule = class WarpRule extends ToolRule {
36186
36868
  }
36187
36869
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
36188
36870
  const { root } = this.getSettablePaths();
36871
+ const isRoot = relativeFilePath === root.relativeFilePath && relativeDirPath === root.relativeDirPath;
36189
36872
  return new WarpRule({
36190
36873
  outputRoot,
36191
36874
  relativeDirPath,
36192
36875
  relativeFilePath,
36193
36876
  fileContent: "",
36194
36877
  validate: false,
36195
- root: relativeFilePath === root.relativeFilePath && relativeDirPath === root.relativeDirPath
36878
+ root: isRoot
36196
36879
  });
36197
36880
  }
36198
36881
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -36257,13 +36940,14 @@ var ZedRule = class ZedRule extends ToolRule {
36257
36940
  };
36258
36941
  }
36259
36942
  static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
36943
+ const isRoot = relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath;
36260
36944
  return new ZedRule({
36261
36945
  outputRoot,
36262
36946
  relativeDirPath,
36263
36947
  relativeFilePath,
36264
36948
  fileContent: "",
36265
36949
  validate: false,
36266
- root: relativeFilePath === this.getSettablePaths({ global }).root.relativeFilePath
36950
+ root: isRoot
36267
36951
  });
36268
36952
  }
36269
36953
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -36536,6 +37220,15 @@ const toolRuleFactories = /* @__PURE__ */ new Map([
36536
37220
  additionalConventions: { subagents: { subagentClass: QwencodeSubagent } }
36537
37221
  }
36538
37222
  }],
37223
+ ["reasonix", {
37224
+ class: ReasonixRule,
37225
+ meta: {
37226
+ extension: "md",
37227
+ supportsGlobal: true,
37228
+ ruleDiscoveryMode: "auto",
37229
+ foldsNonRootIntoRoot: true
37230
+ }
37231
+ }],
36539
37232
  ["replit", {
36540
37233
  class: ReplitRule,
36541
37234
  meta: {
@@ -36980,19 +37673,24 @@ As this project's AI coding tool, you must follow the additional conventions bel
36980
37673
  const localRootToolRules = await (async () => {
36981
37674
  if (!forDeletion || this.global || factory.meta.localRootMode !== "separate-local-file" || !factory.meta.localRootFileName) return [];
36982
37675
  const fileName = factory.meta.localRootFileName;
36983
- if (factory.class.getLocalRootDeletionGlob) return buildDeletionRulesFromPaths(await findFilesByGlobs(factory.class.getLocalRootDeletionGlob({
36984
- outputRoot: this.outputRoot,
36985
- fileName
36986
- })));
37676
+ if (factory.class.getLocalRootDeletionGlob) {
37677
+ const filePaths = await findFilesByGlobs(factory.class.getLocalRootDeletionGlob({
37678
+ outputRoot: this.outputRoot,
37679
+ fileName
37680
+ }));
37681
+ return buildDeletionRulesFromPaths(filePaths);
37682
+ }
36987
37683
  if (!settablePaths.root) return [];
36988
- return buildDeletionRulesFromPaths(await findFilesWithFallback(join(this.outputRoot, settablePaths.root.relativeDirPath ?? ".", fileName), settablePaths.alternativeRoots, (alt) => join(this.outputRoot, alt.relativeDirPath, fileName)));
37684
+ const filePaths = await findFilesWithFallback(join(this.outputRoot, settablePaths.root.relativeDirPath ?? ".", fileName), settablePaths.alternativeRoots, (alt) => join(this.outputRoot, alt.relativeDirPath, fileName));
37685
+ return buildDeletionRulesFromPaths(filePaths);
36989
37686
  })();
36990
37687
  this.logger.debug(`Found ${localRootToolRules.length} local root tool rule files for deletion`);
36991
37688
  const rootMirrorDeletionRules = await (async () => {
36992
37689
  if (!forDeletion || this.global || !factory.meta.mirrorsRootToAgentsMd || !factory.class.getRootMirrorDeletionGlobs) return [];
36993
37690
  const { primaryGlob, mirrorGlob } = factory.class.getRootMirrorDeletionGlobs({ outputRoot: this.outputRoot });
36994
37691
  if ((await findFilesByGlobs(primaryGlob)).length === 0) return [];
36995
- return buildDeletionRulesFromPaths(await findFilesByGlobs(mirrorGlob));
37692
+ const mirrorPaths = await findFilesByGlobs(mirrorGlob);
37693
+ return buildDeletionRulesFromPaths(mirrorPaths);
36996
37694
  })();
36997
37695
  const nonRootToolRules = await (async () => {
36998
37696
  if (!settablePaths.nonRoot) return [];
@@ -37421,7 +38119,6 @@ const SHARED_WRITE_FEATURE_ORDER = [
37421
38119
  "permissions",
37422
38120
  "rules"
37423
38121
  ];
37424
- const SHARED_WRITE_FEATURES = new Set(SHARED_WRITE_FEATURE_ORDER);
37425
38122
  const TARGETS_NOT_DERIVED = /* @__PURE__ */ new Set(["augmentcode-legacy", "claudecode-legacy"]);
37426
38123
  const sharedFileKey = (path) => {
37427
38124
  const dir = path.relativeDirPath.replace(/\\/g, "/").replace(/\/$/, "");
@@ -37444,7 +38141,13 @@ const settablePathsForScope = (cls, global) => {
37444
38141
  paths.push(settable.root);
37445
38142
  for (const alt of settable.alternativeRoots ?? []) paths.push(alt);
37446
38143
  }
37447
- for (const path of cls.getExtraSharedWritePaths?.({ global }) ?? []) if (path.relativeFilePath) paths.push(path);
38144
+ let extra;
38145
+ try {
38146
+ extra = cls.getExtraSharedWritePaths?.({ global }) ?? [];
38147
+ } catch {
38148
+ return paths;
38149
+ }
38150
+ for (const path of extra) if (path.relativeFilePath) paths.push(path);
37448
38151
  return paths;
37449
38152
  };
37450
38153
  const collectFactoryPaths = (factory) => [...settablePathsForScope(factory.class, false), ...settablePathsForScope(factory.class, true)];
@@ -37457,7 +38160,6 @@ const deriveSharedFileWriters = () => {
37457
38160
  const byKey = /* @__PURE__ */ new Map();
37458
38161
  const pathByKey = /* @__PURE__ */ new Map();
37459
38162
  for (const entry of PROCESSOR_REGISTRY) {
37460
- if (!SHARED_WRITE_FEATURES.has(entry.feature)) continue;
37461
38163
  const factories = entry.factory;
37462
38164
  for (const [tool, factory] of factories) {
37463
38165
  if (TARGETS_NOT_DERIVED.has(tool)) continue;
@@ -38423,6 +39125,6 @@ async function importPermissionsCore(params) {
38423
39125
  return writtenCount;
38424
39126
  }
38425
39127
  //#endregion
38426
- export { toPosixPath as $, RulesyncCommand as A, createTempDirectory as B, RulesyncHooks as C, RULESYNC_SKILLS_RELATIVE_DIR_PATH as Ct, CLAUDECODE_MEMORIES_DIR_NAME as D, ALL_FEATURES as Dt, CLAUDECODE_LOCAL_RULE_FILE_NAME as E, formatError as Et, ConsoleLogger as F, getFileSize as G, ensureDir as H, JsonLogger as I, listDirectoryFiles as J, getHomeDirectory as K, CLIError as L, stringifyFrontmatter as M, ConfigResolver as N, CLAUDECODE_SETTINGS_LOCAL_FILE_NAME as O, ALL_FEATURES_WITH_WILDCARD as Ot, findControlCharacter as P, removeTempDirectory as Q, ErrorCodes as R, HooksProcessor as S, RULESYNC_RULES_RELATIVE_DIR_PATH as St, CLAUDECODE_DIR as T, RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH as Tt, fileExists as U, directoryExists as V, findFilesByGlobs as W, removeDirectory as X, readFileContent as Y, removeFile as Z, RulesyncPermissions as _, RULESYNC_MCP_SCHEMA_URL as _t, convertFromTool as a, RULESYNC_AIIGNORE_FILE_NAME as at, IgnoreProcessor as b, RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH as bt, RulesyncRuleFrontmatterSchema as c, RULESYNC_CONFIG_RELATIVE_FILE_PATH as ct, RulesyncSubagentFrontmatterSchema as d, RULESYNC_HOOKS_FILE_NAME as dt, writeFileContent as et, SkillsProcessor as f, RULESYNC_HOOKS_RELATIVE_FILE_PATH as ft, SKILL_FILE_NAME as g, RULESYNC_MCP_RELATIVE_FILE_PATH as gt, RulesyncSkillFrontmatterSchema as h, RULESYNC_MCP_FILE_NAME as ht, getProcessorRegistryEntry as i, MAX_FILE_SIZE as it, RulesyncCommandFrontmatterSchema as j, CLAUDECODE_SKILLS_DIR_PATH as k, SubagentsProcessor as l, RULESYNC_CONFIG_SCHEMA_URL as lt, RulesyncSkill as m, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH as mt, checkRulesyncDirExists as n, ALL_TOOL_TARGETS_WITH_WILDCARD as nt, RulesProcessor as o, RULESYNC_AIIGNORE_RELATIVE_FILE_PATH as ot, getLocalSkillDirNames as p, RULESYNC_IGNORE_RELATIVE_FILE_PATH as pt, isSymlink as q, generate as r, ToolTargetSchema as rt, RulesyncRule as s, RULESYNC_COMMANDS_RELATIVE_DIR_PATH as st, importFromTool as t, ALL_TOOL_TARGETS as tt, RulesyncSubagent as u, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH as ut, McpProcessor as v, RULESYNC_OVERVIEW_FILE_NAME as vt, CommandsProcessor as w, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH as wt, RulesyncIgnore as x, RULESYNC_RELATIVE_DIR_PATH as xt, RulesyncMcp as y, RULESYNC_PERMISSIONS_FILE_NAME as yt, checkPathTraversal as z };
39128
+ 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 };
38427
39129
 
38428
- //# sourceMappingURL=import-BdJG1fyb.js.map
39130
+ //# sourceMappingURL=import-tTMN0WRi.js.map