rulesync 16.28.1 → 16.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/cli/index.cjs +10 -5
- package/dist/cli/index.js +10 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/{import-CwS7XtJP.js → import-BDlmyTcr.js} +746 -104
- package/dist/import-BDlmyTcr.js.map +1 -0
- package/dist/{import-hiWvR9cE.cjs → import-WJZi59fO.cjs} +762 -120
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/import-CwS7XtJP.js.map +0 -1
|
@@ -505,7 +505,8 @@ const rulesProcessorToolTargetTuple = [
|
|
|
505
505
|
"zcode",
|
|
506
506
|
"zed",
|
|
507
507
|
"zoocode",
|
|
508
|
-
"pool"
|
|
508
|
+
"pool",
|
|
509
|
+
"dsh"
|
|
509
510
|
];
|
|
510
511
|
const ignoreProcessorToolTargetTuple = [
|
|
511
512
|
"aiassistant",
|
|
@@ -683,7 +684,8 @@ const skillsProcessorToolTargetTuple = [
|
|
|
683
684
|
"devin",
|
|
684
685
|
"zcode",
|
|
685
686
|
"zed",
|
|
686
|
-
"zoocode"
|
|
687
|
+
"zoocode",
|
|
688
|
+
"dsh"
|
|
687
689
|
];
|
|
688
690
|
const hooksProcessorToolTargetTuple = [
|
|
689
691
|
"amp",
|
|
@@ -4211,10 +4213,12 @@ const PI_HOOK_EVENTS = [
|
|
|
4211
4213
|
"sessionEnd",
|
|
4212
4214
|
"preToolUse",
|
|
4213
4215
|
"postToolUse",
|
|
4216
|
+
"postToolUseFailure",
|
|
4214
4217
|
"preModelInvocation",
|
|
4215
4218
|
"postModelInvocation",
|
|
4216
4219
|
"beforeSubmitPrompt",
|
|
4217
4220
|
"stop",
|
|
4221
|
+
"notification",
|
|
4218
4222
|
"preCompact",
|
|
4219
4223
|
"postCompact"
|
|
4220
4224
|
];
|
|
@@ -4393,6 +4397,7 @@ const CODEXCLI_HOOK_EVENTS = [
|
|
|
4393
4397
|
"postToolUse",
|
|
4394
4398
|
"beforeSubmitPrompt",
|
|
4395
4399
|
"stop",
|
|
4400
|
+
"stopCancelled",
|
|
4396
4401
|
"permissionRequest",
|
|
4397
4402
|
"subagentStart",
|
|
4398
4403
|
"subagentStop",
|
|
@@ -4639,9 +4644,14 @@ const GROKCLI_HOOK_EVENTS = [
|
|
|
4639
4644
|
*
|
|
4640
4645
|
* Kimi Code also exposes `PermissionResult`, `Interrupt`, and the four events
|
|
4641
4646
|
* added in 0.32.0 (`TurnStarted`, `UserPromptQueued`, `TaskStarted`,
|
|
4642
|
-
* `SessionHeartbeat`), none of which
|
|
4643
|
-
*
|
|
4644
|
-
*
|
|
4647
|
+
* `SessionHeartbeat`), none of which is mapped onto a canonical rulesync event
|
|
4648
|
+
* here. `Interrupt` (fires instead of `Stop` when the user interrupts a turn)
|
|
4649
|
+
* does have a canonical shape — `stopCancelled`, which Grok CLI and Codex CLI
|
|
4650
|
+
* map — but Kimi keeps it native-only for now, since an existing `kimi-code`
|
|
4651
|
+
* override addressing it by name would otherwise double up with a canonical
|
|
4652
|
+
* `stopCancelled` block; folding it in is a follow-up. All six are listed in
|
|
4653
|
+
* `KIMI_CODE_NATIVE_HOOK_EVENTS` so a per-tool `kimi-code` override can
|
|
4654
|
+
* address them by their native name.
|
|
4645
4655
|
*
|
|
4646
4656
|
* @see https://moonshotai.github.io/kimi-code/en/customization/hooks.html
|
|
4647
4657
|
*/
|
|
@@ -5080,7 +5090,7 @@ const CANONICAL_TO_KILO_EVENT_NAMES = CANONICAL_TO_OPENCODE_EVENT_NAMES;
|
|
|
5080
5090
|
* Stop, this also fires before Pi auto-retries or auto-compacts —
|
|
5081
5091
|
* `agent_settled` would skip queued follow-ups instead, a pure trade-off).
|
|
5082
5092
|
* Pi events without a faithful canonical counterpart (e.g. `turn_start`,
|
|
5083
|
-
* `agent_settled`) are intentionally unmapped.
|
|
5093
|
+
* `agent_settled`, `ui_prompt_end`) are intentionally unmapped.
|
|
5084
5094
|
*
|
|
5085
5095
|
* @see https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md
|
|
5086
5096
|
*/
|
|
@@ -5089,10 +5099,12 @@ const CANONICAL_TO_PI_EVENT_NAMES = {
|
|
|
5089
5099
|
sessionEnd: "session_shutdown",
|
|
5090
5100
|
preToolUse: "tool_call",
|
|
5091
5101
|
postToolUse: "tool_result",
|
|
5102
|
+
postToolUseFailure: "tool_result",
|
|
5092
5103
|
preModelInvocation: "context",
|
|
5093
5104
|
postModelInvocation: "message_end",
|
|
5094
5105
|
beforeSubmitPrompt: "input",
|
|
5095
5106
|
stop: "agent_end",
|
|
5107
|
+
notification: "ui_prompt_start",
|
|
5096
5108
|
preCompact: "session_before_compact",
|
|
5097
5109
|
postCompact: "session_compact"
|
|
5098
5110
|
};
|
|
@@ -5174,6 +5186,7 @@ const CANONICAL_TO_CODEXCLI_EVENT_NAMES = {
|
|
|
5174
5186
|
postToolUse: "PostToolUse",
|
|
5175
5187
|
beforeSubmitPrompt: "UserPromptSubmit",
|
|
5176
5188
|
stop: "Stop",
|
|
5189
|
+
stopCancelled: "Interrupt",
|
|
5177
5190
|
permissionRequest: "PermissionRequest",
|
|
5178
5191
|
subagentStart: "SubagentStart",
|
|
5179
5192
|
subagentStop: "SubagentStop",
|
|
@@ -7975,7 +7988,7 @@ const RulesyncRuleFrontmatterSchema = z.object({
|
|
|
7975
7988
|
extends: z.optional(z.string()),
|
|
7976
7989
|
facet: z.optional(z.enum(["policies", "output-contracts"]))
|
|
7977
7990
|
})),
|
|
7978
|
-
factorydroid: z.optional(z.looseObject({ channel: z.optional(z.enum(["design"])) }))
|
|
7991
|
+
factorydroid: z.optional(z.looseObject({ channel: z.optional(z.enum(["design", "threat-model"])) }))
|
|
7979
7992
|
});
|
|
7980
7993
|
/**
|
|
7981
7994
|
* The `agentsmd.subprojectPath` every consumer should act on, resolved once so
|
|
@@ -9189,6 +9202,12 @@ const RulesyncSkillFrontmatterSchema = z.looseObject({
|
|
|
9189
9202
|
"disable-model-invocation": z.optional(z.boolean()),
|
|
9190
9203
|
"user-invocable": z.optional(z.boolean())
|
|
9191
9204
|
})),
|
|
9205
|
+
dsh: z.optional(z.looseObject({
|
|
9206
|
+
whenToUse: z.optional(z.string()),
|
|
9207
|
+
metadata: z.optional(z.looseObject({})),
|
|
9208
|
+
"disable-model-invocation": z.optional(z.boolean()),
|
|
9209
|
+
"user-invocable": z.optional(z.boolean())
|
|
9210
|
+
})),
|
|
9192
9211
|
"kimi-code": z.optional(z.looseObject({
|
|
9193
9212
|
type: z.optional(z.enum([
|
|
9194
9213
|
"prompt",
|
|
@@ -9453,7 +9472,7 @@ async function getLocalSkillDirNames(sourceTree) {
|
|
|
9453
9472
|
*
|
|
9454
9473
|
* The rulesync skill frontmatter exposes a root-level `disable-model-invocation`
|
|
9455
9474
|
* default that applies to every tool supporting the flag (claudecode, copilot,
|
|
9456
|
-
* copilotcli, crush, cursor, zed, pi, qwencode, grokcli, factorydroid). Each tool's own section may override that
|
|
9475
|
+
* copilotcli, crush, cursor, zed, pi, qwencode, grokcli, factorydroid, dsh). Each tool's own section may override that
|
|
9457
9476
|
* default with a per-target value. A defined section value (including `false`)
|
|
9458
9477
|
* always wins over the root default.
|
|
9459
9478
|
*
|
|
@@ -9472,7 +9491,7 @@ function resolveDisableModelInvocation({ rootFrontmatter, section }) {
|
|
|
9472
9491
|
*
|
|
9473
9492
|
* The rulesync skill frontmatter exposes a root-level `user-invocable` default
|
|
9474
9493
|
* that applies to every tool supporting the flag (claudecode, copilot,
|
|
9475
|
-
* copilotcli, crush, cursor, qwencode, vibe, grokcli, factorydroid). Each tool's own section may override that default with a
|
|
9494
|
+
* copilotcli, crush, cursor, qwencode, vibe, grokcli, factorydroid, dsh). Each tool's own section may override that default with a
|
|
9476
9495
|
* per-target value. A defined section value (including `false`) always wins
|
|
9477
9496
|
* over the root default.
|
|
9478
9497
|
*
|
|
@@ -11074,6 +11093,13 @@ const FACTORYDROID_RULE_FILE_NAME = "AGENTS.md";
|
|
|
11074
11093
|
* @see https://docs.factory.ai/cli/configuration/agents-md
|
|
11075
11094
|
*/
|
|
11076
11095
|
const FACTORYDROID_DESIGN_FILE_NAME = "DESIGN.md";
|
|
11096
|
+
/**
|
|
11097
|
+
* Factory's Security Review threat model, kept inside the tool directory:
|
|
11098
|
+
* "if `.factory/threat-model.md` exists, Droid uses it as the attack-surface
|
|
11099
|
+
* map". Documented only as a repository file, so project scope only.
|
|
11100
|
+
* @see https://docs.factory.ai/software-factory/security-review
|
|
11101
|
+
*/
|
|
11102
|
+
const FACTORYDROID_THREAT_MODEL_FILE_NAME = "threat-model.md";
|
|
11077
11103
|
const FACTORYDROID_MCP_FILE_NAME = "mcp.json";
|
|
11078
11104
|
const FACTORYDROID_SETTINGS_FILE_NAME = "settings.json";
|
|
11079
11105
|
const FACTORYDROID_HOOKS_FILE_NAME = "hooks.json";
|
|
@@ -11715,7 +11741,10 @@ function parseSharedConfig({ format, fileContent, filePath, invalidRootPolicy =
|
|
|
11715
11741
|
throw new Error(`Failed to parse shared config${at}: ${formatError(error)}`, { cause: error });
|
|
11716
11742
|
}
|
|
11717
11743
|
if (!isPlainObject$1(sanitized)) {
|
|
11718
|
-
if (invalidRootPolicy === "error")
|
|
11744
|
+
if (invalidRootPolicy === "error") {
|
|
11745
|
+
const reason = /* @__PURE__ */ new Error("expected a mapping at the root");
|
|
11746
|
+
throw new Error(`Failed to parse shared config${at}: ${reason.message}`, { cause: reason });
|
|
11747
|
+
}
|
|
11719
11748
|
return {};
|
|
11720
11749
|
}
|
|
11721
11750
|
return sanitized;
|
|
@@ -12717,7 +12746,9 @@ const SHARED_CONFIG_OWNERSHIP = {
|
|
|
12717
12746
|
}
|
|
12718
12747
|
},
|
|
12719
12748
|
".augment/settings.json": {
|
|
12720
|
-
format: "
|
|
12749
|
+
format: "jsonc",
|
|
12750
|
+
invalidRootPolicy: "error",
|
|
12751
|
+
jsoncParseErrors: "error",
|
|
12721
12752
|
features: {
|
|
12722
12753
|
mcp: {
|
|
12723
12754
|
kind: "replace-owned-keys",
|
|
@@ -13311,7 +13342,9 @@ function slugForGate({ gate, index, scope }) {
|
|
|
13311
13342
|
* agent step prompt as a completion directive;
|
|
13312
13343
|
* - with `command` in the check's `takt` frontmatter block, a **command
|
|
13313
13344
|
* gate** (`{type: command, name, command, cwd, timeout_ms}`), which Takt
|
|
13314
|
-
* runs after the step
|
|
13345
|
+
* runs after the step (since 0.62.0: after rule resolution and before the
|
|
13346
|
+
* transition, unless the selected rule sets `command_gates: skip`) and
|
|
13347
|
+
* fails on a non-zero exit code.
|
|
13315
13348
|
*
|
|
13316
13349
|
* `steps` / `personas` in that block scope a gate to named workflow steps or
|
|
13317
13350
|
* personas (`workflow_overrides.steps.<step>.quality_gates`); an unscoped gate
|
|
@@ -20573,14 +20606,14 @@ var AntigravityPluginHooks = class extends AntigravityIdeHooks {
|
|
|
20573
20606
|
* Returns `null` when neither file exists and no `baseFallbackContent` is
|
|
20574
20607
|
* given, so callers can tell "no settings at this scope" apart from empty ones.
|
|
20575
20608
|
*/
|
|
20576
|
-
async function readSettingsWithLocalOverlay({ outputRoot, relativeDirPath, baseFileName, localFileName, toolLabel, baseFallbackContent, sensitiveKeys = [], quiet = false, merge, logger }) {
|
|
20609
|
+
async function readSettingsWithLocalOverlay({ outputRoot, relativeDirPath, baseFileName, localFileName, toolLabel, baseFallbackContent, sensitiveKeys = [], quiet = false, parse = JSON.parse, merge, logger }) {
|
|
20577
20610
|
const baseContent = await readFileContentOrNull(join(outputRoot, relativeDirPath, baseFileName)) ?? baseFallbackContent ?? null;
|
|
20578
20611
|
const localContent = await readFileContentOrNull(join(outputRoot, relativeDirPath, localFileName));
|
|
20579
20612
|
if (localContent === null) return baseContent;
|
|
20580
20613
|
const configPath = join(relativeDirPath, localFileName);
|
|
20581
20614
|
let localParsed;
|
|
20582
20615
|
try {
|
|
20583
|
-
localParsed =
|
|
20616
|
+
localParsed = parse(localContent);
|
|
20584
20617
|
} catch (error) {
|
|
20585
20618
|
throw new Error(`Failed to parse ${toolLabel} settings at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
20586
20619
|
}
|
|
@@ -20589,7 +20622,7 @@ async function readSettingsWithLocalOverlay({ outputRoot, relativeDirPath, baseF
|
|
|
20589
20622
|
if (baseContent !== null) {
|
|
20590
20623
|
let parsed;
|
|
20591
20624
|
try {
|
|
20592
|
-
parsed =
|
|
20625
|
+
parsed = parse(baseContent);
|
|
20593
20626
|
} catch {
|
|
20594
20627
|
return baseContent;
|
|
20595
20628
|
}
|
|
@@ -20648,6 +20681,51 @@ function warnAboutLocalKeys({ localParsed, configPath, toolLabel, sensitiveKeys,
|
|
|
20648
20681
|
//#endregion
|
|
20649
20682
|
//#region src/utils/augmentcode-settings.ts
|
|
20650
20683
|
/**
|
|
20684
|
+
* The one place that spells out how an AugmentCode settings file is parsed.
|
|
20685
|
+
*
|
|
20686
|
+
* Auggie reads `settings.json` / `settings.local.json` as JSON with Comments —
|
|
20687
|
+
* "The files support JSON with Comments (JSONC), allowing comments and trailing
|
|
20688
|
+
* commas for better documentation." (https://docs.augmentcode.com/cli/config) —
|
|
20689
|
+
* so a bare `JSON.parse` rejects a hand-written file the CLI itself accepts. The
|
|
20690
|
+
* parse is fail-closed: a syntax error or a non-object root throws instead of
|
|
20691
|
+
* yielding a partial document, because every caller either merges its own keys
|
|
20692
|
+
* back into this file or imports permissions from it, and neither may proceed
|
|
20693
|
+
* on a file it could not read in full. An empty file parses as `{}`.
|
|
20694
|
+
*
|
|
20695
|
+
* The generate direction registers the same file as `jsonc` in
|
|
20696
|
+
* `SHARED_CONFIG_OWNERSHIP`, so the in-place patch reads it the same way.
|
|
20697
|
+
*
|
|
20698
|
+
* Throws the bare reason (the parser's own error), without naming the file;
|
|
20699
|
+
* `parseAugmentcodeSettingsDocument` adds that, and so does
|
|
20700
|
+
* `readSettingsWithLocalOverlay` when this is handed over as its `parse`.
|
|
20701
|
+
*/
|
|
20702
|
+
function parseAugmentcodeSettingsContent(fileContent) {
|
|
20703
|
+
try {
|
|
20704
|
+
return parseSharedConfig({
|
|
20705
|
+
format: "jsonc",
|
|
20706
|
+
fileContent,
|
|
20707
|
+
invalidRootPolicy: "error",
|
|
20708
|
+
jsoncParseErrors: "error"
|
|
20709
|
+
});
|
|
20710
|
+
} catch (error) {
|
|
20711
|
+
if (error instanceof Error && error.cause !== void 0) throw error.cause;
|
|
20712
|
+
throw error;
|
|
20713
|
+
}
|
|
20714
|
+
}
|
|
20715
|
+
/**
|
|
20716
|
+
* Parse an AugmentCode settings file (`settings.json` / `settings.local.json`)
|
|
20717
|
+
* into a plain object, naming `configPath` in the error when it cannot be read.
|
|
20718
|
+
* See `parseAugmentcodeSettingsContent` for the format and the fail-closed
|
|
20719
|
+
* policy.
|
|
20720
|
+
*/
|
|
20721
|
+
function parseAugmentcodeSettingsDocument({ fileContent, configPath }) {
|
|
20722
|
+
try {
|
|
20723
|
+
return parseAugmentcodeSettingsContent(fileContent);
|
|
20724
|
+
} catch (error) {
|
|
20725
|
+
throw new Error(`Failed to parse AugmentCode settings at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
20726
|
+
}
|
|
20727
|
+
}
|
|
20728
|
+
/**
|
|
20651
20729
|
* Top-level keys AugmentCode *replaces* (higher-precedence wins wholesale)
|
|
20652
20730
|
* rather than combining across tiers. Everything else combines.
|
|
20653
20731
|
*
|
|
@@ -20722,6 +20800,7 @@ async function readAugmentcodeSettingsWithLocalOverlay({ outputRoot, relativeDir
|
|
|
20722
20800
|
localFileName: "settings.local.json",
|
|
20723
20801
|
toolLabel: "AugmentCode",
|
|
20724
20802
|
sensitiveKeys: AUGMENTCODE_GUARDRAIL_KEYS,
|
|
20803
|
+
parse: parseAugmentcodeSettingsContent,
|
|
20725
20804
|
baseFallbackContent,
|
|
20726
20805
|
merge: combineAugmentSettings,
|
|
20727
20806
|
logger
|
|
@@ -20801,8 +20880,10 @@ var AugmentcodeHooks = class AugmentcodeHooks extends ToolHooks {
|
|
|
20801
20880
|
const existingContent = await readFileContentOrNull(filePath) ?? JSON.stringify({}, null, 2);
|
|
20802
20881
|
let existingHooks = {};
|
|
20803
20882
|
try {
|
|
20804
|
-
const
|
|
20805
|
-
|
|
20883
|
+
const candidate = parseAugmentcodeSettingsDocument({
|
|
20884
|
+
fileContent: existingContent,
|
|
20885
|
+
configPath: join(paths.relativeDirPath, paths.relativeFilePath)
|
|
20886
|
+
}).hooks;
|
|
20806
20887
|
if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) existingHooks = candidate;
|
|
20807
20888
|
} catch {
|
|
20808
20889
|
existingHooks = {};
|
|
@@ -20824,7 +20905,8 @@ var AugmentcodeHooks = class AugmentcodeHooks extends ToolHooks {
|
|
|
20824
20905
|
...preservedHooks,
|
|
20825
20906
|
...augmentHooks
|
|
20826
20907
|
} },
|
|
20827
|
-
filePath
|
|
20908
|
+
filePath,
|
|
20909
|
+
logger
|
|
20828
20910
|
});
|
|
20829
20911
|
return new AugmentcodeHooks({
|
|
20830
20912
|
outputRoot,
|
|
@@ -20837,7 +20919,10 @@ var AugmentcodeHooks = class AugmentcodeHooks extends ToolHooks {
|
|
|
20837
20919
|
toRulesyncHooks({ logger } = {}) {
|
|
20838
20920
|
let settings;
|
|
20839
20921
|
try {
|
|
20840
|
-
settings =
|
|
20922
|
+
settings = parseAugmentcodeSettingsDocument({
|
|
20923
|
+
fileContent: this.getFileContent(),
|
|
20924
|
+
configPath: join(this.getRelativeDirPath(), this.getRelativeFilePath())
|
|
20925
|
+
});
|
|
20841
20926
|
} catch (error) {
|
|
20842
20927
|
throw new Error(`Failed to parse AugmentCode hooks content in ${join(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`, { cause: error });
|
|
20843
20928
|
}
|
|
@@ -24152,9 +24237,10 @@ function stripTrustedDirectoryWrapper(command) {
|
|
|
24152
24237
|
* to filter on in the first place.
|
|
24153
24238
|
*
|
|
24154
24239
|
* Keyed on native names because the check runs after the canonical → native
|
|
24155
|
-
* mapping: `SessionHeartbeat` and `Interrupt`
|
|
24156
|
-
*
|
|
24157
|
-
*
|
|
24240
|
+
* mapping: `SessionHeartbeat` and `Interrupt` are not mapped from a canonical
|
|
24241
|
+
* event for Kimi (`Interrupt` is the shape of canonical `stopCancelled`, which
|
|
24242
|
+
* other tools map, but stays native-only here) and are only reachable through
|
|
24243
|
+
* a per-tool `kimi-code` override naming them directly.
|
|
24158
24244
|
*
|
|
24159
24245
|
* Deliberately narrower than Claude Code's equivalent set: Kimi Code's
|
|
24160
24246
|
* `UserPromptSubmit` matches the submitted prompt text, and `PermissionResult`
|
|
@@ -24885,6 +24971,15 @@ const PI_TOOL_EVENTS = /* @__PURE__ */ new Set(["tool_call", "tool_result"]);
|
|
|
24885
24971
|
*/
|
|
24886
24972
|
const PI_ASSISTANT_MESSAGE_EVENTS = /* @__PURE__ */ new Set(["message_end"]);
|
|
24887
24973
|
/**
|
|
24974
|
+
* Canonical events whose Pi event also fires when nothing went wrong. Pi's
|
|
24975
|
+
* `tool_result` fires for every finished tool call and exposes `event.isError`,
|
|
24976
|
+
* so a `postToolUseFailure` handler is gated on that flag while a `postToolUse`
|
|
24977
|
+
* handler on the same Pi event runs regardless.
|
|
24978
|
+
*
|
|
24979
|
+
* @see https://github.com/earendil-works/pi/blob/v0.85.1/packages/coding-agent/docs/extensions.md#tool_result
|
|
24980
|
+
*/
|
|
24981
|
+
const PI_ERROR_GATED_CANONICAL_EVENTS = /* @__PURE__ */ new Set(["postToolUseFailure"]);
|
|
24982
|
+
/**
|
|
24888
24983
|
* `tool_call` is Pi's tool gate. Its return contract is
|
|
24889
24984
|
* `{ block: true, reason?: string, terminate?: boolean }`.
|
|
24890
24985
|
*
|
|
@@ -25030,7 +25125,8 @@ function collectPiHandlers({ effectiveHooks, eventMap }) {
|
|
|
25030
25125
|
if (!def.command) continue;
|
|
25031
25126
|
handlers.push({
|
|
25032
25127
|
command: def.command,
|
|
25033
|
-
matcher: def.matcher ? def.matcher : void 0
|
|
25128
|
+
matcher: def.matcher ? def.matcher : void 0,
|
|
25129
|
+
onlyOnError: PI_ERROR_GATED_CANONICAL_EVENTS.has(canonicalEvent)
|
|
25034
25130
|
});
|
|
25035
25131
|
}
|
|
25036
25132
|
if (handlers.length > 0) {
|
|
@@ -25043,10 +25139,13 @@ function collectPiHandlers({ effectiveHooks, eventMap }) {
|
|
|
25043
25139
|
}
|
|
25044
25140
|
function buildCommandLines({ handler, usesToolName, blocking }) {
|
|
25045
25141
|
const lines = [];
|
|
25046
|
-
const
|
|
25142
|
+
const conditions = [];
|
|
25143
|
+
if (handler.onlyOnError) conditions.push("event.isError");
|
|
25144
|
+
if (usesToolName && handler.matcher) conditions.push(`new RegExp(${matcherToEmbeddedLiteral(handler.matcher)}).test(event.toolName)`);
|
|
25145
|
+
const gated = conditions.length > 0;
|
|
25047
25146
|
const indent = gated ? " " : " ";
|
|
25048
25147
|
const embeddedCommand = JSON.stringify(handler.command);
|
|
25049
|
-
if (gated
|
|
25148
|
+
if (gated) lines.push(` if (${conditions.join(" && ")}) {`);
|
|
25050
25149
|
const onFailure = FAILURE_LINES_BY_MODE[blocking];
|
|
25051
25150
|
if (onFailure.length > 0) {
|
|
25052
25151
|
lines.push(`${indent}try {`);
|
|
@@ -25064,8 +25163,9 @@ function buildSubscriptionLines(handlerGroups) {
|
|
|
25064
25163
|
const blocking = PI_BLOCKING_MODE_BY_EVENT[piEvent] ?? "none";
|
|
25065
25164
|
const isPromptGate = blocking === "prompt";
|
|
25066
25165
|
const usesToolName = PI_TOOL_EVENTS.has(piEvent) && handlers.some((h) => h.matcher);
|
|
25166
|
+
const usesErrorFlag = handlers.some((h) => h.onlyOnError);
|
|
25067
25167
|
const gatesOnAssistant = PI_ASSISTANT_MESSAGE_EVENTS.has(piEvent);
|
|
25068
|
-
const params = isPromptGate ? "event, ctx" : usesToolName || gatesOnAssistant || isPromptGate ? "event" : "";
|
|
25168
|
+
const params = isPromptGate ? "event, ctx" : usesToolName || usesErrorFlag || gatesOnAssistant || isPromptGate ? "event" : "";
|
|
25069
25169
|
lines.push(` pi.on(${JSON.stringify(piEvent)}, async (${params}) => {`);
|
|
25070
25170
|
if (gatesOnAssistant) lines.push(` if (event.message.role !== "assistant") return;`);
|
|
25071
25171
|
if (isPromptGate) lines.push(` if (event.source === "extension") return { action: "continue" };`);
|
|
@@ -25087,6 +25187,8 @@ function buildSubscriptionLines(handlerGroups) {
|
|
|
25087
25187
|
* gate — where a hook command that exits non-zero denies the call with
|
|
25088
25188
|
* `{ block: true, reason }`, and on `input` — Pi's prompt-submission gate —
|
|
25089
25189
|
* where a non-zero exit cancels the prompt with `{ action: "handled" }`.
|
|
25190
|
+
* `postToolUse` and `postToolUseFailure` share Pi's `tool_result` event; the
|
|
25191
|
+
* latter's commands run only when `event.isError` is set.
|
|
25090
25192
|
*
|
|
25091
25193
|
* @see https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md
|
|
25092
25194
|
*/
|
|
@@ -25655,12 +25757,29 @@ const VIBE_HOOKS_FILE_NAME = "hooks.toml";
|
|
|
25655
25757
|
const VIBE_TOOL_EVENTS = /* @__PURE__ */ new Set(["pre_tool", "post_tool"]);
|
|
25656
25758
|
const SUPPORTED_VIBE_EVENTS = new Set(VIBE_HOOK_EVENTS);
|
|
25657
25759
|
/**
|
|
25760
|
+
* Vibe drops a hook whose `command` contains a backslash when it loads
|
|
25761
|
+
* `hooks.toml` (since v2.25.1; `load_hooks_config` at v2.25.3: "Hook '<name>' skipped:
|
|
25762
|
+
* backslash paths are not supported in hook commands. Use forward slashes
|
|
25763
|
+
* instead."), because its exec-based executor tokenizes the command with
|
|
25764
|
+
* `shlex.split`, which eats the backslash. The hook is still written — the
|
|
25765
|
+
* command is the user's to fix — but it is worth a warning, since Vibe itself
|
|
25766
|
+
* only reports the skip as a config issue rather than failing the run.
|
|
25767
|
+
* @see https://github.com/mistralai/mistral-vibe/blob/v2.25.3/vibe/core/hooks/config.py
|
|
25768
|
+
*/
|
|
25769
|
+
function warnAboutBackslashCommand({ name, command, logger }) {
|
|
25770
|
+
if (!command.includes("\\")) return;
|
|
25771
|
+
logger?.warn(`the command of hook ${quoteValueForWarning(name)} contains a backslash, which Vibe rejects when it loads hooks.toml — the hook is skipped with "backslash paths are not supported in hook commands". Use forward slashes and avoid backslash escapes so the hook runs.`);
|
|
25772
|
+
}
|
|
25773
|
+
/**
|
|
25658
25774
|
* Build the flat `[[hooks]]` array for `.vibe/hooks.toml` from a canonical
|
|
25659
25775
|
* hooks config. Vibe uses a flat array where each entry carries its own event
|
|
25660
25776
|
* `type`, tool-name `match` glob/regex, and `command`. Only `type: "command"`
|
|
25661
|
-
* canonical hooks are emitted
|
|
25777
|
+
* canonical hooks are emitted: a Vibe hook is a command line, which the legacy
|
|
25778
|
+
* backend hands to a shell and the unified harness tokenizes with `shlex.split`
|
|
25779
|
+
* and executes directly (v2.25.1: "Hook commands run without a shell to
|
|
25780
|
+
* prevent injection via hooks.toml").
|
|
25662
25781
|
*/
|
|
25663
|
-
function canonicalToVibeHooks(config, toolOverride) {
|
|
25782
|
+
function canonicalToVibeHooks({ config, toolOverride, logger }) {
|
|
25664
25783
|
const shared = {};
|
|
25665
25784
|
for (const [event, defs] of Object.entries(config.hooks)) if (SUPPORTED_VIBE_EVENTS.has(event)) shared[event] = defs;
|
|
25666
25785
|
const effective = {
|
|
@@ -25679,6 +25798,11 @@ function canonicalToVibeHooks(config, toolOverride) {
|
|
|
25679
25798
|
if ((def.type ?? "command") !== "command") continue;
|
|
25680
25799
|
if (typeof def.command !== "string") continue;
|
|
25681
25800
|
const name = typeof def.name === "string" ? def.name : `${vibeEvent}-${index}`;
|
|
25801
|
+
warnAboutBackslashCommand({
|
|
25802
|
+
name,
|
|
25803
|
+
command: def.command,
|
|
25804
|
+
logger
|
|
25805
|
+
});
|
|
25682
25806
|
const isToolEvent = VIBE_TOOL_EVENTS.has(vibeEvent);
|
|
25683
25807
|
const entry = {
|
|
25684
25808
|
name,
|
|
@@ -25779,10 +25903,14 @@ var VibeHooks = class VibeHooks extends ToolHooks {
|
|
|
25779
25903
|
validate
|
|
25780
25904
|
});
|
|
25781
25905
|
}
|
|
25782
|
-
static async fromRulesyncHooks({ outputRoot = process.cwd(), rulesyncHooks, validate = true, global = false }) {
|
|
25906
|
+
static async fromRulesyncHooks({ outputRoot = process.cwd(), rulesyncHooks, validate = true, global = false, logger }) {
|
|
25783
25907
|
const paths = VibeHooks.getSettablePaths({ global });
|
|
25784
25908
|
const config = rulesyncHooks.getJson();
|
|
25785
|
-
const vibeHooks = canonicalToVibeHooks(
|
|
25909
|
+
const vibeHooks = canonicalToVibeHooks({
|
|
25910
|
+
config,
|
|
25911
|
+
toolOverride: config.vibe?.hooks,
|
|
25912
|
+
logger
|
|
25913
|
+
});
|
|
25786
25914
|
const fileContent = smolToml.stringify(vibeHooks);
|
|
25787
25915
|
return new VibeHooks({
|
|
25788
25916
|
outputRoot,
|
|
@@ -28715,15 +28843,10 @@ var AntigravityPluginMcp = class extends AntigravityIdeMcp {
|
|
|
28715
28843
|
//#endregion
|
|
28716
28844
|
//#region src/features/mcp/augmentcode-mcp.ts
|
|
28717
28845
|
function parseAugmentcodeSettings(fileContent, relativeDirPath, relativeFilePath) {
|
|
28718
|
-
|
|
28719
|
-
|
|
28720
|
-
|
|
28721
|
-
|
|
28722
|
-
} catch (error) {
|
|
28723
|
-
throw new Error(`Failed to parse AugmentCode settings at ${configPath}: ${formatError(error)}`, { cause: error });
|
|
28724
|
-
}
|
|
28725
|
-
if (!isPlainObject$1(parsed)) throw new Error(`Failed to parse AugmentCode settings at ${configPath}: expected a JSON object`);
|
|
28726
|
-
return parsed;
|
|
28846
|
+
return parseAugmentcodeSettingsDocument({
|
|
28847
|
+
fileContent,
|
|
28848
|
+
configPath: join(relativeDirPath, relativeFilePath)
|
|
28849
|
+
});
|
|
28727
28850
|
}
|
|
28728
28851
|
/**
|
|
28729
28852
|
* AugmentCode (Auggie CLI) MCP servers.
|
|
@@ -28780,7 +28903,7 @@ var AugmentcodeMcp = class AugmentcodeMcp extends ToolMcp {
|
|
|
28780
28903
|
global
|
|
28781
28904
|
});
|
|
28782
28905
|
}
|
|
28783
|
-
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false }) {
|
|
28906
|
+
static async fromRulesyncMcp({ outputRoot = process.cwd(), rulesyncMcp, validate = true, global = false, logger }) {
|
|
28784
28907
|
const paths = this.getSettablePaths({ global });
|
|
28785
28908
|
const filePath = join(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
|
|
28786
28909
|
const existingContent = await readFileContentOrNull(filePath) ?? JSON.stringify({}, null, 2);
|
|
@@ -28793,7 +28916,8 @@ var AugmentcodeMcp = class AugmentcodeMcp extends ToolMcp {
|
|
|
28793
28916
|
feature: "mcp",
|
|
28794
28917
|
existingContent,
|
|
28795
28918
|
patch: { mcpServers: rulesyncMcp.getMcpServers() },
|
|
28796
|
-
filePath
|
|
28919
|
+
filePath,
|
|
28920
|
+
logger
|
|
28797
28921
|
}),
|
|
28798
28922
|
validate,
|
|
28799
28923
|
global
|
|
@@ -36966,7 +37090,10 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
|
|
|
36966
37090
|
const existingContent = await readFileContentOrNull(filePath) ?? "{}";
|
|
36967
37091
|
let settings;
|
|
36968
37092
|
try {
|
|
36969
|
-
const parsed =
|
|
37093
|
+
const parsed = parseAugmentcodeSettingsDocument({
|
|
37094
|
+
fileContent: existingContent,
|
|
37095
|
+
configPath: join(paths.relativeDirPath, paths.relativeFilePath)
|
|
37096
|
+
});
|
|
36970
37097
|
const result = AugmentSettingsSchema.safeParse(parsed);
|
|
36971
37098
|
if (!result.success) throw new Error(formatError(result.error));
|
|
36972
37099
|
settings = result.data;
|
|
@@ -37006,7 +37133,8 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
|
|
|
37006
37133
|
feature: "permissions",
|
|
37007
37134
|
existingContent,
|
|
37008
37135
|
patch: { toolPermissions: [...specialEntries, ...sortedBasic] },
|
|
37009
|
-
filePath
|
|
37136
|
+
filePath,
|
|
37137
|
+
logger
|
|
37010
37138
|
});
|
|
37011
37139
|
return new AugmentcodePermissions({
|
|
37012
37140
|
outputRoot,
|
|
@@ -37019,7 +37147,10 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
|
|
|
37019
37147
|
toRulesyncPermissions() {
|
|
37020
37148
|
let settings;
|
|
37021
37149
|
try {
|
|
37022
|
-
const parsed =
|
|
37150
|
+
const parsed = parseAugmentcodeSettingsDocument({
|
|
37151
|
+
fileContent: this.getFileContent(),
|
|
37152
|
+
configPath: join(this.getRelativeDirPath(), this.getRelativeFilePath())
|
|
37153
|
+
});
|
|
37023
37154
|
const result = AugmentSettingsSchema.safeParse(parsed);
|
|
37024
37155
|
if (!result.success) throw new Error(formatError(result.error));
|
|
37025
37156
|
settings = result.data;
|
|
@@ -37037,7 +37168,10 @@ var AugmentcodePermissions = class AugmentcodePermissions extends ToolPermission
|
|
|
37037
37168
|
}
|
|
37038
37169
|
validate() {
|
|
37039
37170
|
try {
|
|
37040
|
-
const parsed =
|
|
37171
|
+
const parsed = parseAugmentcodeSettingsDocument({
|
|
37172
|
+
fileContent: this.fileContent || "{}",
|
|
37173
|
+
configPath: join(this.getRelativeDirPath(), this.getRelativeFilePath())
|
|
37174
|
+
});
|
|
37041
37175
|
const result = AugmentSettingsSchema.safeParse(parsed);
|
|
37042
37176
|
if (!result.success) return {
|
|
37043
37177
|
success: false,
|
|
@@ -41387,19 +41521,27 @@ const CATEGORY_TO_GROK_TOOL = {
|
|
|
41387
41521
|
edit: "Edit",
|
|
41388
41522
|
write: "Edit",
|
|
41389
41523
|
grep: "Grep",
|
|
41524
|
+
glob: "Glob",
|
|
41390
41525
|
webfetch: "WebFetch",
|
|
41391
|
-
websearch: "WebSearch"
|
|
41526
|
+
websearch: "WebSearch",
|
|
41527
|
+
agent: "AgentMessage"
|
|
41392
41528
|
};
|
|
41393
41529
|
const GROK_TOOL_TO_CATEGORY = {
|
|
41394
41530
|
Bash: "bash",
|
|
41395
41531
|
Read: "read",
|
|
41396
41532
|
Edit: "edit",
|
|
41397
41533
|
Grep: "grep",
|
|
41534
|
+
Glob: "glob",
|
|
41398
41535
|
WebFetch: "webfetch",
|
|
41399
|
-
WebSearch: "websearch"
|
|
41536
|
+
WebSearch: "websearch",
|
|
41537
|
+
AgentMessage: "agent",
|
|
41538
|
+
...Object.fromEntries(["SendSubagentMessage", "SendAgentMessage"].map((tool) => [tool, "agent"]))
|
|
41400
41539
|
};
|
|
41401
41540
|
const GROK_MCP_TOOL = "MCPTool";
|
|
41402
|
-
const GROK_TOOL_TO_CATEGORY_LOWER =
|
|
41541
|
+
const GROK_TOOL_TO_CATEGORY_LOWER = {
|
|
41542
|
+
...Object.fromEntries(Object.entries(GROK_TOOL_TO_CATEGORY).map(([tool, category]) => [tool.toLowerCase(), category])),
|
|
41543
|
+
agent_message: "agent"
|
|
41544
|
+
};
|
|
41403
41545
|
const GROK_MCP_TOOL_ALIASES = /* @__PURE__ */ new Set(["mcp", GROK_MCP_TOOL.toLowerCase()]);
|
|
41404
41546
|
const GROKCLI_PERMISSION_RULES_KEY = "rules";
|
|
41405
41547
|
/**
|
|
@@ -41502,13 +41644,16 @@ function parseGrokRule(rule) {
|
|
|
41502
41644
|
* per-category, per-pattern model maps almost 1:1:
|
|
41503
41645
|
* - Generate: each `permission.<category>.<pattern> = allow|ask|deny` becomes
|
|
41504
41646
|
* the matching Grok entry and is bucketed into the `[permission]` array for
|
|
41505
|
-
* that action. `bash|read|edit|grep|webfetch|websearch` map to
|
|
41506
|
-
* tool; `write` collapses onto `Edit` (Grok has no `Write`
|
|
41507
|
-
* maps to `
|
|
41508
|
-
*
|
|
41509
|
-
*
|
|
41510
|
-
*
|
|
41511
|
-
*
|
|
41647
|
+
* that action. `bash|read|edit|grep|glob|webfetch|websearch|agent` map to
|
|
41648
|
+
* their Grok tool; `write` collapses onto `Edit` (Grok has no `Write`
|
|
41649
|
+
* tool); `glob` maps to `Glob` (an upstream alias of the `Grep` filter);
|
|
41650
|
+
* `agent` maps to `AgentMessage` (which gates messages to a running
|
|
41651
|
+
* subagent rather than its launch, and whose pattern is a subagent id
|
|
41652
|
+
* rather than a subagent type); `mcp__*` maps to `MCPTool(...)` (a scoped
|
|
41653
|
+
* MCP category folds its address into the parentheses, so a non-`*`
|
|
41654
|
+
* argument pattern on it is not represented). The one category with no Grok tool (`notebookedit`) is
|
|
41655
|
+
* skipped (with a warning when it carries a `deny` rule, to surface the
|
|
41656
|
+
* gap). When two canonical rules collapse onto the same Grok
|
|
41512
41657
|
* entry with different actions (e.g. `edit` allow + `write` deny → `Edit`),
|
|
41513
41658
|
* the strictest wins (`deny > ask > allow`) and a warning is logged, so the
|
|
41514
41659
|
* entry never lands contradictorily in two arrays.
|
|
@@ -42620,6 +42765,32 @@ function mergeKimiCodeToolsSection({ existingContent, patch }) {
|
|
|
42620
42765
|
return merged;
|
|
42621
42766
|
}
|
|
42622
42767
|
/**
|
|
42768
|
+
* Carry the existing `[permission]` siblings of `rules` over onto the generated
|
|
42769
|
+
* table. The gateway replaces the owned `permission` key wholesale and rulesync
|
|
42770
|
+
* only ever authors `rules`, so a hand-written sibling such as
|
|
42771
|
+
* `dangerous_command_guard = false` (Kimi Code 0.40.0) would otherwise be
|
|
42772
|
+
* deleted on every generate. Rulesync does not model these keys; they pass
|
|
42773
|
+
* through verbatim and `rules` always comes from the patch.
|
|
42774
|
+
*
|
|
42775
|
+
* @see https://moonshotai.github.io/kimi-code/en/configuration/config-files.html#permission
|
|
42776
|
+
*/
|
|
42777
|
+
function mergeKimiCodePermissionSection({ existingContent, patch }) {
|
|
42778
|
+
let existing;
|
|
42779
|
+
try {
|
|
42780
|
+
existing = parseSharedConfig({
|
|
42781
|
+
format: "toml",
|
|
42782
|
+
fileContent: existingContent
|
|
42783
|
+
}).permission;
|
|
42784
|
+
} catch {
|
|
42785
|
+
existing = void 0;
|
|
42786
|
+
}
|
|
42787
|
+
const { rules: _existingRules, ...siblings } = isRecord$1(existing) ? existing : {};
|
|
42788
|
+
return {
|
|
42789
|
+
...siblings,
|
|
42790
|
+
...isRecord$1(patch.permission) ? patch.permission : {}
|
|
42791
|
+
};
|
|
42792
|
+
}
|
|
42793
|
+
/**
|
|
42623
42794
|
* Build Kimi's `[tools]` section from a rulesync override, or read one back on
|
|
42624
42795
|
* import. Entries pass through verbatim: the section uses agent-file tool syntax
|
|
42625
42796
|
* (exact built-in names, `mcp__server__*` globs), not the canonical
|
|
@@ -42799,12 +42970,17 @@ var KimiCodePermissions = class KimiCodePermissions extends ToolPermissions {
|
|
|
42799
42970
|
existingContent: fileContent,
|
|
42800
42971
|
patch
|
|
42801
42972
|
});
|
|
42973
|
+
const mergedPermission = mergeKimiCodePermissionSection({
|
|
42974
|
+
existingContent: fileContent,
|
|
42975
|
+
patch
|
|
42976
|
+
});
|
|
42802
42977
|
this.fileContent = applySharedConfigPatch({
|
|
42803
42978
|
fileKey: getKimiCodeConfigSharedFileKey({ global: this.global }),
|
|
42804
42979
|
feature: "permissions",
|
|
42805
42980
|
existingContent: fileContent,
|
|
42806
42981
|
patch: {
|
|
42807
42982
|
...patch,
|
|
42983
|
+
permission: mergedPermission,
|
|
42808
42984
|
...mergedTools && { tools: mergedTools }
|
|
42809
42985
|
},
|
|
42810
42986
|
filePath: join(paths.relativeDirPath, paths.relativeFilePath)
|
|
@@ -52210,6 +52386,207 @@ var DevinSkill = class DevinSkill extends ToolSkill {
|
|
|
52210
52386
|
}
|
|
52211
52387
|
};
|
|
52212
52388
|
//#endregion
|
|
52389
|
+
//#region src/constants/dsh-paths.ts
|
|
52390
|
+
/**
|
|
52391
|
+
* DeepSeek Harness (`dsh`) configuration-layout conventions.
|
|
52392
|
+
*
|
|
52393
|
+
* The harness home is `$DSH_HOME`, which defaults to `~/.dsh`; rulesync writes
|
|
52394
|
+
* only the default location. Project-scoped assets live under a `.dsh/`
|
|
52395
|
+
* directory at the project root.
|
|
52396
|
+
*
|
|
52397
|
+
* Rules: `dsh-agent-instructions` loads the user-global `$DSH_HOME/AGENTS.md`
|
|
52398
|
+
* (root file only — the user-global file has no `.local.md` overlay), then the
|
|
52399
|
+
* project chain of `AGENTS.md` / `CLAUDE.md` files from the project root (the
|
|
52400
|
+
* nearest ancestor holding `.git`) down to the session cwd, broad to specific.
|
|
52401
|
+
* Rulesync emits `AGENTS.md` only; `CLAUDE.md` is the `claudecode` target's
|
|
52402
|
+
* file, and a `CLAUDE.md` duplicating its sibling `AGENTS.md` renders once.
|
|
52403
|
+
*
|
|
52404
|
+
* Skills: `dsh-skill-filesystem` scans `<projectRoot>/.dsh/skills` (rank 100),
|
|
52405
|
+
* `<projectRoot>/.agents/skills` (200), `<dshHome>/skills` (400) and
|
|
52406
|
+
* `<agentsHome>/skills` (500), each holding top-level `<name>/SKILL.md`
|
|
52407
|
+
* bundles or flat `<name>.md` files; nested `SKILL.md` files are deliberately
|
|
52408
|
+
* not discovered. Rulesync writes only the `dsh`-specific roots — the
|
|
52409
|
+
* `.agents/skills` roots are the `agentsskills` target's output.
|
|
52410
|
+
*
|
|
52411
|
+
* @see https://github.com/deepseek-ai/deepseek-harness
|
|
52412
|
+
* @see https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/context/agent-instructions/README.md
|
|
52413
|
+
* @see https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill-filesystem/README.md
|
|
52414
|
+
*/
|
|
52415
|
+
/**
|
|
52416
|
+
* Project-scoped `.dsh/` directory, and the harness home relative to the home
|
|
52417
|
+
* directory (`$DSH_HOME` default).
|
|
52418
|
+
*/
|
|
52419
|
+
const DSH_DIR = ".dsh";
|
|
52420
|
+
/** Skills root, relative to the project root or the harness home. */
|
|
52421
|
+
const DSH_SKILLS_DIR_PATH = join(DSH_DIR, "skills");
|
|
52422
|
+
//#endregion
|
|
52423
|
+
//#region src/features/skills/dsh-skill.ts
|
|
52424
|
+
const DshSkillFrontmatterSchema = z.looseObject({
|
|
52425
|
+
name: z.string(),
|
|
52426
|
+
description: z.string(),
|
|
52427
|
+
whenToUse: z.optional(z.string()),
|
|
52428
|
+
metadata: z.optional(z.looseObject({})),
|
|
52429
|
+
"disable-model-invocation": z.optional(z.boolean()),
|
|
52430
|
+
"user-invocable": z.optional(z.boolean())
|
|
52431
|
+
});
|
|
52432
|
+
/**
|
|
52433
|
+
* Represents a DeepSeek Harness skill directory.
|
|
52434
|
+
*
|
|
52435
|
+
* The harness scans `<projectRoot>/.dsh/skills` (project) and
|
|
52436
|
+
* `~/.dsh/skills` (global, the `$DSH_HOME` default) — plus the `.agents/skills`
|
|
52437
|
+
* roots the `agentsskills` target already writes — and discovers only the
|
|
52438
|
+
* top-level entries of each root: a `<name>/SKILL.md` bundle or a flat
|
|
52439
|
+
* `<name>.md` file. Nested `SKILL.md` files below a bundle are deliberately
|
|
52440
|
+
* not discovered, which matches what rulesync emits: one top-level bundle per
|
|
52441
|
+
* skill, supporting files carried inside it as plain files.
|
|
52442
|
+
*
|
|
52443
|
+
* @see https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill-filesystem/README.md
|
|
52444
|
+
*/
|
|
52445
|
+
var DshSkill = class DshSkill extends ToolSkill {
|
|
52446
|
+
constructor({ outputRoot = process.cwd(), relativeDirPath = DSH_SKILLS_DIR_PATH, dirName, frontmatter, body, otherFiles = [], validate = true, global = false }) {
|
|
52447
|
+
super({
|
|
52448
|
+
outputRoot,
|
|
52449
|
+
relativeDirPath,
|
|
52450
|
+
dirName,
|
|
52451
|
+
mainFile: {
|
|
52452
|
+
name: SKILL_FILE_NAME,
|
|
52453
|
+
body,
|
|
52454
|
+
frontmatter: { ...frontmatter }
|
|
52455
|
+
},
|
|
52456
|
+
otherFiles,
|
|
52457
|
+
global
|
|
52458
|
+
});
|
|
52459
|
+
if (validate) {
|
|
52460
|
+
const result = this.validate();
|
|
52461
|
+
if (!result.success) throw result.error;
|
|
52462
|
+
}
|
|
52463
|
+
}
|
|
52464
|
+
static getSettablePaths({ global: _global = false } = {}) {
|
|
52465
|
+
return { relativeDirPath: DSH_SKILLS_DIR_PATH };
|
|
52466
|
+
}
|
|
52467
|
+
getFrontmatter() {
|
|
52468
|
+
return DshSkillFrontmatterSchema.parse(this.requireMainFileFrontmatter());
|
|
52469
|
+
}
|
|
52470
|
+
getBody() {
|
|
52471
|
+
return this.mainFile?.body ?? "";
|
|
52472
|
+
}
|
|
52473
|
+
validate() {
|
|
52474
|
+
if (this.mainFile === void 0) return {
|
|
52475
|
+
success: false,
|
|
52476
|
+
error: /* @__PURE__ */ new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
|
|
52477
|
+
};
|
|
52478
|
+
const result = DshSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
|
|
52479
|
+
if (!result.success) return {
|
|
52480
|
+
success: false,
|
|
52481
|
+
error: /* @__PURE__ */ new Error(`Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`)
|
|
52482
|
+
};
|
|
52483
|
+
return {
|
|
52484
|
+
success: true,
|
|
52485
|
+
error: null
|
|
52486
|
+
};
|
|
52487
|
+
}
|
|
52488
|
+
toRulesyncSkill() {
|
|
52489
|
+
const frontmatter = this.getFrontmatter();
|
|
52490
|
+
const dshSection = {
|
|
52491
|
+
...frontmatter.whenToUse !== void 0 && { whenToUse: frontmatter.whenToUse },
|
|
52492
|
+
...frontmatter.metadata !== void 0 && { metadata: frontmatter.metadata },
|
|
52493
|
+
...frontmatter["disable-model-invocation"] !== void 0 && { "disable-model-invocation": frontmatter["disable-model-invocation"] },
|
|
52494
|
+
...frontmatter["user-invocable"] !== void 0 && { "user-invocable": frontmatter["user-invocable"] }
|
|
52495
|
+
};
|
|
52496
|
+
const rulesyncFrontmatter = {
|
|
52497
|
+
name: frontmatter.name,
|
|
52498
|
+
description: frontmatter.description,
|
|
52499
|
+
targets: ["*"],
|
|
52500
|
+
...Object.keys(dshSection).length > 0 && { dsh: dshSection }
|
|
52501
|
+
};
|
|
52502
|
+
return new RulesyncSkill({
|
|
52503
|
+
outputRoot: this.outputRoot,
|
|
52504
|
+
relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH,
|
|
52505
|
+
dirName: this.getDirName(),
|
|
52506
|
+
frontmatter: rulesyncFrontmatter,
|
|
52507
|
+
body: this.getBody(),
|
|
52508
|
+
otherFiles: this.getOtherFiles(),
|
|
52509
|
+
validate: true,
|
|
52510
|
+
global: this.global
|
|
52511
|
+
});
|
|
52512
|
+
}
|
|
52513
|
+
static fromRulesyncSkill({ outputRoot = process.cwd(), rulesyncSkill, validate = true, global = false }) {
|
|
52514
|
+
const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
|
|
52515
|
+
const dshSection = rulesyncFrontmatter.dsh;
|
|
52516
|
+
const disableModelInvocation = resolveDisableModelInvocation({
|
|
52517
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
52518
|
+
section: dshSection
|
|
52519
|
+
});
|
|
52520
|
+
const userInvocable = resolveUserInvocable({
|
|
52521
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
52522
|
+
section: dshSection
|
|
52523
|
+
});
|
|
52524
|
+
const metadata = resolveMetadata({
|
|
52525
|
+
rootFrontmatter: rulesyncFrontmatter,
|
|
52526
|
+
section: dshSection
|
|
52527
|
+
});
|
|
52528
|
+
const dshFrontmatter = {
|
|
52529
|
+
name: rulesyncFrontmatter.name,
|
|
52530
|
+
description: rulesyncFrontmatter.description,
|
|
52531
|
+
...dshSection?.whenToUse !== void 0 && { whenToUse: dshSection.whenToUse },
|
|
52532
|
+
...metadata !== void 0 && { metadata },
|
|
52533
|
+
...disableModelInvocation !== void 0 && { "disable-model-invocation": disableModelInvocation },
|
|
52534
|
+
...userInvocable !== void 0 && { "user-invocable": userInvocable }
|
|
52535
|
+
};
|
|
52536
|
+
const settablePaths = DshSkill.getSettablePaths({ global });
|
|
52537
|
+
return new DshSkill({
|
|
52538
|
+
outputRoot,
|
|
52539
|
+
relativeDirPath: settablePaths.relativeDirPath,
|
|
52540
|
+
dirName: rulesyncSkill.getDirName(),
|
|
52541
|
+
frontmatter: dshFrontmatter,
|
|
52542
|
+
body: rulesyncSkill.getBody(),
|
|
52543
|
+
otherFiles: rulesyncSkill.getOtherFiles(),
|
|
52544
|
+
validate,
|
|
52545
|
+
global
|
|
52546
|
+
});
|
|
52547
|
+
}
|
|
52548
|
+
static isTargetedByRulesyncSkill(rulesyncSkill) {
|
|
52549
|
+
const targets = rulesyncSkill.getFrontmatter().targets;
|
|
52550
|
+
return targets.includes("*") || targets.includes("dsh");
|
|
52551
|
+
}
|
|
52552
|
+
static async fromDir(params) {
|
|
52553
|
+
const loaded = await this.loadSkillDirContent({
|
|
52554
|
+
...params,
|
|
52555
|
+
getSettablePaths: DshSkill.getSettablePaths
|
|
52556
|
+
});
|
|
52557
|
+
const result = DshSkillFrontmatterSchema.safeParse(loaded.frontmatter);
|
|
52558
|
+
if (!result.success) {
|
|
52559
|
+
const skillDirPath = join(loaded.outputRoot, loaded.relativeDirPath, loaded.dirName);
|
|
52560
|
+
throw new Error(`Invalid frontmatter in ${join(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`);
|
|
52561
|
+
}
|
|
52562
|
+
return new DshSkill({
|
|
52563
|
+
outputRoot: loaded.outputRoot,
|
|
52564
|
+
relativeDirPath: loaded.relativeDirPath,
|
|
52565
|
+
dirName: loaded.dirName,
|
|
52566
|
+
frontmatter: result.data,
|
|
52567
|
+
body: loaded.body,
|
|
52568
|
+
otherFiles: loaded.otherFiles,
|
|
52569
|
+
validate: true,
|
|
52570
|
+
global: loaded.global
|
|
52571
|
+
});
|
|
52572
|
+
}
|
|
52573
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, dirName, global = false }) {
|
|
52574
|
+
return new DshSkill({
|
|
52575
|
+
outputRoot,
|
|
52576
|
+
relativeDirPath,
|
|
52577
|
+
dirName,
|
|
52578
|
+
frontmatter: {
|
|
52579
|
+
name: "",
|
|
52580
|
+
description: ""
|
|
52581
|
+
},
|
|
52582
|
+
body: "",
|
|
52583
|
+
otherFiles: [],
|
|
52584
|
+
validate: false,
|
|
52585
|
+
global
|
|
52586
|
+
});
|
|
52587
|
+
}
|
|
52588
|
+
};
|
|
52589
|
+
//#endregion
|
|
52213
52590
|
//#region src/features/skills/factorydroid-skill.ts
|
|
52214
52591
|
const FactorydroidSkillFrontmatterSchema = z.looseObject({
|
|
52215
52592
|
name: z.string(),
|
|
@@ -54765,6 +55142,19 @@ const VibeSkillFrontmatterSchema = z.looseObject({
|
|
|
54765
55142
|
"allowed-tools": z.optional(z.union([z.string(), z.array(z.string())]))
|
|
54766
55143
|
});
|
|
54767
55144
|
/**
|
|
55145
|
+
* Skill names Vibe's built-in skills occupy. `SkillManager` treats them as
|
|
55146
|
+
* reserved: a project or user skill whose frontmatter `name` matches one is
|
|
55147
|
+
* skipped at load time with only a debug log ("Skipping skill '<name>' ...
|
|
55148
|
+
* because builtin skill names are reserved"), so a generated skill by that
|
|
55149
|
+
* name is silently never offered. That is the legacy backend, still the
|
|
55150
|
+
* default; the unified harness constructs the manager with
|
|
55151
|
+
* `include_builtins=False` because its built-ins arrive as skills of the
|
|
55152
|
+
* shipped `vibe` plugin under namespaced names, so it reserves nothing.
|
|
55153
|
+
* @see https://github.com/mistralai/mistral-vibe/blob/v2.25.3/vibe/core/skills/builtins/__init__.py
|
|
55154
|
+
* @see https://github.com/mistralai/mistral-vibe/blob/v2.25.3/vibe/core/skills/manager.py
|
|
55155
|
+
*/
|
|
55156
|
+
const VIBE_RESERVED_SKILL_NAMES = /* @__PURE__ */ new Set(["vibe", "skill-creator"]);
|
|
55157
|
+
/**
|
|
54768
55158
|
* Build the Vibe frontmatter from a rulesync skill frontmatter, preferring the
|
|
54769
55159
|
* dedicated `vibe` section over the shared root-level fields.
|
|
54770
55160
|
*/
|
|
@@ -54796,6 +55186,15 @@ function buildVibeFrontmatter(rulesyncFrontmatter) {
|
|
|
54796
55186
|
...vibeSection?.["allowed-tools"] !== void 0 && { "allowed-tools": vibeSection["allowed-tools"] }
|
|
54797
55187
|
};
|
|
54798
55188
|
}
|
|
55189
|
+
/**
|
|
55190
|
+
* The skill is still generated under the reserved name — the name is the
|
|
55191
|
+
* user's to change, and a rename here would make it diverge from the other
|
|
55192
|
+
* targets — but Vibe would drop it without a visible word, so say so now.
|
|
55193
|
+
*/
|
|
55194
|
+
function warnAboutReservedSkillName({ name, logger }) {
|
|
55195
|
+
if (!VIBE_RESERVED_SKILL_NAMES.has(name)) return;
|
|
55196
|
+
logger?.warn(`Vibe skills: the skill name ${quoteValueForWarning(name)} is reserved for a Vibe built-in skill, so Vibe skips a project or user skill by that name when it loads skills. Rename the skill for it to be available in Vibe.`);
|
|
55197
|
+
}
|
|
54799
55198
|
var VibeSkill = class VibeSkill extends ToolSkill {
|
|
54800
55199
|
constructor({ outputRoot = process.cwd(), relativeDirPath = VibeSkill.getSettablePaths().relativeDirPath, dirName, frontmatter, body, otherFiles = [], validate = true, global = false }) {
|
|
54801
55200
|
super({
|
|
@@ -54868,9 +55267,13 @@ var VibeSkill = class VibeSkill extends ToolSkill {
|
|
|
54868
55267
|
global: this.global
|
|
54869
55268
|
});
|
|
54870
55269
|
}
|
|
54871
|
-
static fromRulesyncSkill({ outputRoot = process.cwd(), rulesyncSkill, validate = true, global = false }) {
|
|
55270
|
+
static fromRulesyncSkill({ outputRoot = process.cwd(), rulesyncSkill, validate = true, global = false, logger }) {
|
|
54872
55271
|
const settablePaths = VibeSkill.getSettablePaths({ global });
|
|
54873
55272
|
const vibeFrontmatter = buildVibeFrontmatter(rulesyncSkill.getFrontmatter());
|
|
55273
|
+
warnAboutReservedSkillName({
|
|
55274
|
+
name: vibeFrontmatter.name,
|
|
55275
|
+
logger
|
|
55276
|
+
});
|
|
54874
55277
|
return new VibeSkill({
|
|
54875
55278
|
outputRoot,
|
|
54876
55279
|
relativeDirPath: settablePaths.relativeDirPath,
|
|
@@ -55750,6 +56153,14 @@ const toolSkillFactories = /* @__PURE__ */ new Map([
|
|
|
55750
56153
|
supportsSimulated: false,
|
|
55751
56154
|
supportsGlobal: true
|
|
55752
56155
|
}
|
|
56156
|
+
}],
|
|
56157
|
+
["dsh", {
|
|
56158
|
+
class: DshSkill,
|
|
56159
|
+
meta: {
|
|
56160
|
+
supportsProject: true,
|
|
56161
|
+
supportsSimulated: false,
|
|
56162
|
+
supportsGlobal: true
|
|
56163
|
+
}
|
|
55753
56164
|
}]
|
|
55754
56165
|
]);
|
|
55755
56166
|
const defaultGetFactory$2 = (target) => {
|
|
@@ -55789,9 +56200,14 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
55789
56200
|
const rulesyncSkills = rulesyncDirs.filter((dir) => dir instanceof RulesyncSkill);
|
|
55790
56201
|
const factory = this.getFactory(this.toolTarget);
|
|
55791
56202
|
return (await Promise.all(rulesyncSkills.map(async (rulesyncSkill) => {
|
|
55792
|
-
|
|
56203
|
+
const isClaudecodeScheduledTask = rulesyncSkill.getFrontmatter().claudecode?.["scheduled-task"] === true;
|
|
56204
|
+
if (isClaudecodeScheduledTask && this.toolTarget !== "claudecode" && this.toolTarget !== "claudecode-legacy") return null;
|
|
55793
56205
|
if (!factory.class.isTargetedByRulesyncSkill(rulesyncSkill)) return null;
|
|
55794
56206
|
const dirName = rulesyncSkill.getDirName();
|
|
56207
|
+
if (isClaudecodeScheduledTask && !this.global) {
|
|
56208
|
+
this.logger.warn(`Skipping skill ${quoteForLog(dirName)} for '${this.toolTarget}': 'claudecode.scheduled-task' skills are only read from the user config directory (~/.claude/scheduled-tasks/), so nothing is written at project scope. Generate it with --global instead; a stale copy an earlier generate left under .claude/scheduled-tasks/ is removed by a generate with --delete.`);
|
|
56209
|
+
return null;
|
|
56210
|
+
}
|
|
55795
56211
|
const dirWriteBlockReason = await factory.class.getDirWriteBlockReason?.({
|
|
55796
56212
|
outputRoot: this.outputRoot,
|
|
55797
56213
|
relativeDirPath: factory.class.getSettablePaths({ global: this.global }).relativeDirPath,
|
|
@@ -56932,13 +57348,26 @@ var AntigravityPluginSubagent = class extends AntigravitySharedSubagent {
|
|
|
56932
57348
|
};
|
|
56933
57349
|
//#endregion
|
|
56934
57350
|
//#region src/features/subagents/augmentcode-subagent.ts
|
|
57351
|
+
const AugmentcodeToolListSchema = z.union([z.array(z.string()), z.string()]);
|
|
57352
|
+
/**
|
|
57353
|
+
* Normalize a documented tool-list value to the list form: a string is split on
|
|
57354
|
+
* commas, trimmed, and emptied of blank entries; a list is returned as is. A
|
|
57355
|
+
* string that names no tool (`""`, `", ,"`) is treated as unset rather than as
|
|
57356
|
+
* an empty allowlist — the author left the value blank, not the tool set — so
|
|
57357
|
+
* it yields `undefined`; an authored empty list is kept as written.
|
|
57358
|
+
*/
|
|
57359
|
+
function normalizeAugmentcodeToolList(value) {
|
|
57360
|
+
if (Array.isArray(value)) return value;
|
|
57361
|
+
const tools = value.split(",").map((tool) => tool.trim()).filter((tool) => tool.length > 0);
|
|
57362
|
+
return tools.length > 0 ? tools : void 0;
|
|
57363
|
+
}
|
|
56935
57364
|
const AugmentcodeSubagentFrontmatterSchema = z.looseObject({
|
|
56936
57365
|
name: z.string(),
|
|
56937
57366
|
description: z.optional(z.string()),
|
|
56938
57367
|
color: z.optional(z.string()),
|
|
56939
57368
|
model: z.optional(z.string()),
|
|
56940
|
-
tools: z.optional(
|
|
56941
|
-
disabled_tools: z.optional(
|
|
57369
|
+
tools: z.optional(AugmentcodeToolListSchema),
|
|
57370
|
+
disabled_tools: z.optional(AugmentcodeToolListSchema)
|
|
56942
57371
|
});
|
|
56943
57372
|
/**
|
|
56944
57373
|
* AugmentCode (Auggie CLI) subagents.
|
|
@@ -56977,14 +57406,24 @@ var AugmentcodeSubagent = class AugmentcodeSubagent extends ToolSubagent {
|
|
|
56977
57406
|
return this.body;
|
|
56978
57407
|
}
|
|
56979
57408
|
toRulesyncSubagent() {
|
|
56980
|
-
const { name, description, ...rest } = this.frontmatter;
|
|
57409
|
+
const { name, description, tools, disabled_tools, ...rest } = this.frontmatter;
|
|
57410
|
+
const normalizedTools = tools === void 0 ? void 0 : normalizeAugmentcodeToolList(tools);
|
|
57411
|
+
const normalizedDisabledTools = disabled_tools === void 0 ? void 0 : normalizeAugmentcodeToolList(disabled_tools);
|
|
57412
|
+
const toolLists = {
|
|
57413
|
+
...normalizedTools !== void 0 && { tools: normalizedTools },
|
|
57414
|
+
...normalizedDisabledTools !== void 0 && { disabled_tools: normalizedDisabledTools }
|
|
57415
|
+
};
|
|
57416
|
+
const augmentcodeSection = {
|
|
57417
|
+
...rest,
|
|
57418
|
+
...toolLists
|
|
57419
|
+
};
|
|
56981
57420
|
return new RulesyncSubagent({
|
|
56982
57421
|
outputRoot: ".",
|
|
56983
57422
|
frontmatter: {
|
|
56984
57423
|
targets: ["*"],
|
|
56985
57424
|
name,
|
|
56986
57425
|
description,
|
|
56987
|
-
...Object.keys(
|
|
57426
|
+
...Object.keys(augmentcodeSection).length > 0 && { augmentcode: augmentcodeSection }
|
|
56988
57427
|
},
|
|
56989
57428
|
body: this.body,
|
|
56990
57429
|
relativeDirPath: RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH,
|
|
@@ -63297,13 +63736,40 @@ const CodebuddyRuleFrontmatterSchema = z.object({
|
|
|
63297
63736
|
enabled: z.optional(z.boolean())
|
|
63298
63737
|
});
|
|
63299
63738
|
/**
|
|
63739
|
+
* Splits a scalar `paths` value on the commas that separate patterns, leaving
|
|
63740
|
+
* the commas inside a brace group alone: CodeBuddy's memory docs say "You can
|
|
63741
|
+
* also combine multiple patterns with commas" and give
|
|
63742
|
+
* `paths: {src,lib}/**\/*.ts, tests/**\/*.test.ts` as the example, where the
|
|
63743
|
+
* first comma belongs to the brace expansion and the second separates the two
|
|
63744
|
+
* globs. Only a scalar is split — the docs describe the comma form for the
|
|
63745
|
+
* string shape, and a list already separates its patterns.
|
|
63746
|
+
*/
|
|
63747
|
+
function splitCodebuddyPathsScalar(paths) {
|
|
63748
|
+
const patterns = [];
|
|
63749
|
+
let current = "";
|
|
63750
|
+
let braceDepth = 0;
|
|
63751
|
+
for (const char of paths) {
|
|
63752
|
+
if (char === "{") braceDepth += 1;
|
|
63753
|
+
else if (char === "}" && braceDepth > 0) braceDepth -= 1;
|
|
63754
|
+
else if (char === "," && braceDepth === 0) {
|
|
63755
|
+
patterns.push(current);
|
|
63756
|
+
current = "";
|
|
63757
|
+
continue;
|
|
63758
|
+
}
|
|
63759
|
+
current += char;
|
|
63760
|
+
}
|
|
63761
|
+
patterns.push(current);
|
|
63762
|
+
return patterns.map((pattern) => pattern.trim());
|
|
63763
|
+
}
|
|
63764
|
+
/**
|
|
63300
63765
|
* Normalizes the documented `string` / `string[]` shapes of `paths` to the
|
|
63301
|
-
* list form the rest of the adapter works with
|
|
63302
|
-
*
|
|
63766
|
+
* list form the rest of the adapter works with, splitting a comma-separated
|
|
63767
|
+
* scalar into its patterns (see `splitCodebuddyPathsScalar`). An empty list
|
|
63768
|
+
* and an empty string both mean "no paths".
|
|
63303
63769
|
*/
|
|
63304
63770
|
function normalizeCodebuddyPaths(paths) {
|
|
63305
63771
|
if (paths === void 0) return;
|
|
63306
|
-
const list = (typeof paths === "string" ?
|
|
63772
|
+
const list = (typeof paths === "string" ? splitCodebuddyPathsScalar(paths) : paths).filter((path) => path.trim() !== "");
|
|
63307
63773
|
return list.length > 0 ? list : void 0;
|
|
63308
63774
|
}
|
|
63309
63775
|
/**
|
|
@@ -64537,6 +65003,125 @@ var DevinRule = class DevinRule extends ToolRule {
|
|
|
64537
65003
|
}
|
|
64538
65004
|
};
|
|
64539
65005
|
//#endregion
|
|
65006
|
+
//#region src/features/rules/dsh-rule.ts
|
|
65007
|
+
/**
|
|
65008
|
+
* DeepSeek Harness (`dsh`) rules.
|
|
65009
|
+
*
|
|
65010
|
+
* Project scope writes the root `AGENTS.md` plus nested `<dir>/AGENTS.md`
|
|
65011
|
+
* files — the project chain `dsh-agent-instructions` loads from the `.git`
|
|
65012
|
+
* root down to the session cwd. Global scope writes the user-global
|
|
65013
|
+
* `~/.dsh/AGENTS.md` (`$DSH_HOME` default), which the harness reads as a
|
|
65014
|
+
* single root file with no local overlay, so non-root rules fold into it.
|
|
65015
|
+
*
|
|
65016
|
+
* @see https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/context/agent-instructions/README.md
|
|
65017
|
+
*/
|
|
65018
|
+
var DshRule = class DshRule extends ToolRule {
|
|
65019
|
+
static getSettablePaths({ global = false } = {}) {
|
|
65020
|
+
if (global) return { root: {
|
|
65021
|
+
relativeDirPath: DSH_DIR,
|
|
65022
|
+
relativeFilePath: AGENTSMD_RULE_FILE_NAME
|
|
65023
|
+
} };
|
|
65024
|
+
return { root: {
|
|
65025
|
+
relativeDirPath: ".",
|
|
65026
|
+
relativeFilePath: AGENTSMD_RULE_FILE_NAME
|
|
65027
|
+
} };
|
|
65028
|
+
}
|
|
65029
|
+
/**
|
|
65030
|
+
* DeepSeek Harness loads the project chain of `AGENTS.md` files from the
|
|
65031
|
+
* project root (the nearest ancestor holding `.git`) down through the session
|
|
65032
|
+
* cwd, broad to specific, so a per-directory file applies only while working
|
|
65033
|
+
* under that directory. Nested files are therefore a real scoping surface,
|
|
65034
|
+
* not just the root file's overflow.
|
|
65035
|
+
*
|
|
65036
|
+
* The scan mirrors the AGENTS.md standard's nested discovery — same file
|
|
65037
|
+
* name, same exclusions, import-only, project scope — because it discovers
|
|
65038
|
+
* literally the same files.
|
|
65039
|
+
* @see https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/context/agent-instructions/README.md
|
|
65040
|
+
*/
|
|
65041
|
+
static getNestedFilePatterns() {
|
|
65042
|
+
return this.buildNestedFilePatterns({ fileName: AGENTSMD_RULE_FILE_NAME });
|
|
65043
|
+
}
|
|
65044
|
+
/**
|
|
65045
|
+
* The subproject directory this rule scopes, or `undefined` for the root file
|
|
65046
|
+
* (project or global).
|
|
65047
|
+
*/
|
|
65048
|
+
getSubprojectPath() {
|
|
65049
|
+
return this.getNestedSubprojectPath({ fileName: AGENTSMD_RULE_FILE_NAME });
|
|
65050
|
+
}
|
|
65051
|
+
static async fromFile({ outputRoot = process.cwd(), relativeFilePath: _relativeFilePath, relativeDirPath: overrideDirPath, validate = true, global = false }) {
|
|
65052
|
+
const { root } = this.getSettablePaths({ global });
|
|
65053
|
+
if (overrideDirPath !== void 0 && overrideDirPath !== root.relativeDirPath && overrideDirPath !== ".") {
|
|
65054
|
+
const fileContent = await readFileContent(join(outputRoot, overrideDirPath, AGENTSMD_RULE_FILE_NAME));
|
|
65055
|
+
return new DshRule({
|
|
65056
|
+
outputRoot,
|
|
65057
|
+
relativeDirPath: overrideDirPath,
|
|
65058
|
+
relativeFilePath: AGENTSMD_RULE_FILE_NAME,
|
|
65059
|
+
fileContent,
|
|
65060
|
+
validate,
|
|
65061
|
+
root: false
|
|
65062
|
+
});
|
|
65063
|
+
}
|
|
65064
|
+
const fileContent = await readFileContent(join(outputRoot, root.relativeDirPath, root.relativeFilePath));
|
|
65065
|
+
return new DshRule({
|
|
65066
|
+
outputRoot,
|
|
65067
|
+
relativeDirPath: root.relativeDirPath,
|
|
65068
|
+
relativeFilePath: root.relativeFilePath,
|
|
65069
|
+
fileContent,
|
|
65070
|
+
validate,
|
|
65071
|
+
root: true
|
|
65072
|
+
});
|
|
65073
|
+
}
|
|
65074
|
+
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
|
|
65075
|
+
const { root } = this.getSettablePaths({ global });
|
|
65076
|
+
const frontmatter = rulesyncRule.getFrontmatter();
|
|
65077
|
+
const isRoot = frontmatter.root ?? false;
|
|
65078
|
+
const subprojectPath = frontmatter.agentsmd?.subprojectPath;
|
|
65079
|
+
if (!global && !isRoot && subprojectPath) return new DshRule({
|
|
65080
|
+
outputRoot,
|
|
65081
|
+
relativeDirPath: join(subprojectPath),
|
|
65082
|
+
relativeFilePath: AGENTSMD_RULE_FILE_NAME,
|
|
65083
|
+
fileContent: rulesyncRule.getBody(),
|
|
65084
|
+
validate,
|
|
65085
|
+
root: false
|
|
65086
|
+
});
|
|
65087
|
+
return new DshRule({
|
|
65088
|
+
outputRoot,
|
|
65089
|
+
relativeDirPath: root.relativeDirPath,
|
|
65090
|
+
relativeFilePath: root.relativeFilePath,
|
|
65091
|
+
fileContent: rulesyncRule.getBody(),
|
|
65092
|
+
validate,
|
|
65093
|
+
root: isRoot
|
|
65094
|
+
});
|
|
65095
|
+
}
|
|
65096
|
+
toRulesyncRule() {
|
|
65097
|
+
const subprojectPath = this.getSubprojectPath();
|
|
65098
|
+
if (subprojectPath === void 0) return this.toRulesyncRuleDefault();
|
|
65099
|
+
return this.toRulesyncRuleNestedAgentsmd({ subprojectPath });
|
|
65100
|
+
}
|
|
65101
|
+
validate() {
|
|
65102
|
+
return {
|
|
65103
|
+
success: true,
|
|
65104
|
+
error: null
|
|
65105
|
+
};
|
|
65106
|
+
}
|
|
65107
|
+
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath }) {
|
|
65108
|
+
return new DshRule({
|
|
65109
|
+
outputRoot,
|
|
65110
|
+
relativeDirPath,
|
|
65111
|
+
relativeFilePath,
|
|
65112
|
+
fileContent: "",
|
|
65113
|
+
validate: false,
|
|
65114
|
+
root: relativeFilePath === "AGENTS.md" && (relativeDirPath === "." || relativeDirPath === ".dsh")
|
|
65115
|
+
});
|
|
65116
|
+
}
|
|
65117
|
+
static isTargetedByRulesyncRule(rulesyncRule) {
|
|
65118
|
+
return this.isTargetedByRulesyncRuleDefault({
|
|
65119
|
+
rulesyncRule,
|
|
65120
|
+
toolTarget: "dsh"
|
|
65121
|
+
});
|
|
65122
|
+
}
|
|
65123
|
+
};
|
|
65124
|
+
//#endregion
|
|
64540
65125
|
//#region src/features/rules/factorydroid-rule.ts
|
|
64541
65126
|
/**
|
|
64542
65127
|
* Rule generator for Factory Droid.
|
|
@@ -64545,27 +65130,36 @@ var DevinRule = class DevinRule extends ToolRule {
|
|
|
64545
65130
|
* (global) as coding guidelines, plus non-root rules referenced from it via
|
|
64546
65131
|
* `.factory/rules/*.md`.
|
|
64547
65132
|
*
|
|
64548
|
-
* Factory Droid also loads
|
|
64549
|
-
* independent instruction
|
|
64550
|
-
*
|
|
64551
|
-
*
|
|
64552
|
-
* `
|
|
64553
|
-
*
|
|
64554
|
-
*
|
|
64555
|
-
* `DESIGN.md
|
|
64556
|
-
* `AGENTS.md
|
|
64557
|
-
*
|
|
65133
|
+
* Factory Droid also loads two further fixed files (project only) as
|
|
65134
|
+
* independent instruction surfaces, which rulesync emits from any non-root
|
|
65135
|
+
* rule that opts in via a `factorydroid.channel` frontmatter key. Opted-in
|
|
65136
|
+
* rule bodies are routed to the channel's file instead of
|
|
65137
|
+
* `AGENTS.md`/`.factory/rules/*.md`, and multiple opted-in rules concatenate
|
|
65138
|
+
* in source order:
|
|
65139
|
+
*
|
|
65140
|
+
* - `design` → `DESIGN.md`: "Always-on design-system, UX, visual, and
|
|
65141
|
+
* interaction guidance", loaded separately from `AGENTS.md`'s coding
|
|
65142
|
+
* guidelines. Factory's docs describe `DESIGN.md` at the repository root and
|
|
65143
|
+
* in nested subdirectories, like `AGENTS.md`, but document no
|
|
65144
|
+
* personal/global home-directory equivalent.
|
|
65145
|
+
* - `threat-model` → `.factory/threat-model.md`: the attack-surface map
|
|
65146
|
+
* Factory's Security Review reads — "if `.factory/threat-model.md` exists,
|
|
65147
|
+
* Droid uses it as the attack-surface map". It is documented only as a
|
|
65148
|
+
* repository file, so it has no global scope either.
|
|
65149
|
+
*
|
|
65150
|
+
* Both channels are therefore project scope only.
|
|
64558
65151
|
* @see https://docs.factory.ai/cli/configuration/agents-md
|
|
65152
|
+
* @see https://docs.factory.ai/software-factory/security-review
|
|
64559
65153
|
*/
|
|
64560
65154
|
var FactorydroidRule = class FactorydroidRule extends ToolRule {
|
|
64561
|
-
|
|
64562
|
-
constructor({ fileContent, root,
|
|
65155
|
+
channel;
|
|
65156
|
+
constructor({ fileContent, root, channel, ...rest }) {
|
|
64563
65157
|
super({
|
|
64564
65158
|
...rest,
|
|
64565
65159
|
fileContent,
|
|
64566
65160
|
root: root ?? false
|
|
64567
65161
|
});
|
|
64568
|
-
this.
|
|
65162
|
+
this.channel = channel;
|
|
64569
65163
|
}
|
|
64570
65164
|
static getSettablePaths({ global, excludeToolDir } = {}) {
|
|
64571
65165
|
if (global) return { root: {
|
|
@@ -64581,41 +65175,75 @@ var FactorydroidRule = class FactorydroidRule extends ToolRule {
|
|
|
64581
65175
|
design: {
|
|
64582
65176
|
relativeDirPath: ".",
|
|
64583
65177
|
relativeFilePath: FACTORYDROID_DESIGN_FILE_NAME
|
|
65178
|
+
},
|
|
65179
|
+
threatModel: {
|
|
65180
|
+
relativeDirPath: buildToolPath(FACTORYDROID_DIR, ".", excludeToolDir),
|
|
65181
|
+
relativeFilePath: FACTORYDROID_THREAT_MODEL_FILE_NAME
|
|
64584
65182
|
}
|
|
64585
65183
|
};
|
|
64586
65184
|
}
|
|
64587
65185
|
/**
|
|
65186
|
+
* The channel files in a fixed order, so that `getExtraFixedFiles` and the
|
|
65187
|
+
* channel lookups below agree on which paths are channels. Empty in global
|
|
65188
|
+
* mode, where neither file has a documented home-directory equivalent.
|
|
65189
|
+
*/
|
|
65190
|
+
static getChannelPaths({ global }) {
|
|
65191
|
+
if (global) return [];
|
|
65192
|
+
const paths = this.getSettablePaths({ global });
|
|
65193
|
+
return [{
|
|
65194
|
+
channel: "design",
|
|
65195
|
+
path: paths.design
|
|
65196
|
+
}, {
|
|
65197
|
+
channel: "threat-model",
|
|
65198
|
+
path: paths.threatModel
|
|
65199
|
+
}];
|
|
65200
|
+
}
|
|
65201
|
+
/**
|
|
65202
|
+
* Which channel, if any, owns the given output path. Matching on
|
|
65203
|
+
* `relativeDirPath` too (not just the basename) keeps a non-root rule that
|
|
65204
|
+
* happens to be named `DESIGN.md` or `threat-model.md` under
|
|
65205
|
+
* `.factory/rules/` from being routed to a channel by mistake.
|
|
65206
|
+
*/
|
|
65207
|
+
static findChannelByPath({ relativeDirPath, relativeFilePath, global }) {
|
|
65208
|
+
return this.getChannelPaths({ global }).find(({ path }) => relativeDirPath === path.relativeDirPath && relativeFilePath === path.relativeFilePath);
|
|
65209
|
+
}
|
|
65210
|
+
/**
|
|
64588
65211
|
* Extra fixed files this tool manages beyond the root/non-root rules. The
|
|
64589
65212
|
* RulesProcessor enumerates these for import and deletion so a stale
|
|
64590
|
-
* `DESIGN.md` is cleaned up once no rule opts
|
|
64591
|
-
* mode:
|
|
65213
|
+
* `DESIGN.md` or `.factory/threat-model.md` is cleaned up once no rule opts
|
|
65214
|
+
* in anymore. Empty in global mode: neither file has a documented
|
|
65215
|
+
* home-directory equivalent.
|
|
64592
65216
|
*/
|
|
64593
65217
|
static getExtraFixedFiles({ global = false } = {}) {
|
|
64594
|
-
|
|
64595
|
-
return [this.getSettablePaths({ global }).design];
|
|
65218
|
+
return this.getChannelPaths({ global }).map(({ path }) => path);
|
|
64596
65219
|
}
|
|
64597
65220
|
/**
|
|
64598
|
-
* Factory Droid loads
|
|
64599
|
-
* TOON reference section would double-load the content (and
|
|
64600
|
-
* as a rule the model must remember to open).
|
|
65221
|
+
* Factory Droid loads the channel files itself, so listing one in the root
|
|
65222
|
+
* rule's TOON reference section would double-load the content (and
|
|
65223
|
+
* misrepresent it as a rule the model must remember to open).
|
|
64601
65224
|
*/
|
|
64602
65225
|
isExcludedFromRootReferences() {
|
|
64603
|
-
return this.
|
|
65226
|
+
return this.channel !== void 0;
|
|
64604
65227
|
}
|
|
64605
65228
|
static async fromFile({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, validate = true, global = false }) {
|
|
64606
65229
|
const paths = this.getSettablePaths({ global });
|
|
64607
|
-
const
|
|
64608
|
-
|
|
64609
|
-
|
|
65230
|
+
const channelMatch = this.findChannelByPath({
|
|
65231
|
+
relativeDirPath,
|
|
65232
|
+
relativeFilePath,
|
|
65233
|
+
global
|
|
65234
|
+
});
|
|
65235
|
+
if (channelMatch) {
|
|
65236
|
+
const { channel, path } = channelMatch;
|
|
65237
|
+
const relativePath = join(path.relativeDirPath, path.relativeFilePath);
|
|
64610
65238
|
const fileContent = await readFileContent(join(outputRoot, relativePath));
|
|
64611
65239
|
return new FactorydroidRule({
|
|
64612
65240
|
outputRoot,
|
|
64613
|
-
relativeDirPath:
|
|
64614
|
-
relativeFilePath:
|
|
65241
|
+
relativeDirPath: path.relativeDirPath,
|
|
65242
|
+
relativeFilePath: path.relativeFilePath,
|
|
64615
65243
|
fileContent,
|
|
64616
65244
|
validate,
|
|
64617
65245
|
root: false,
|
|
64618
|
-
|
|
65246
|
+
channel
|
|
64619
65247
|
});
|
|
64620
65248
|
}
|
|
64621
65249
|
if (relativeFilePath === paths.root.relativeFilePath) {
|
|
@@ -64644,9 +65272,12 @@ var FactorydroidRule = class FactorydroidRule extends ToolRule {
|
|
|
64644
65272
|
}
|
|
64645
65273
|
static forDeletion({ outputRoot = process.cwd(), relativeDirPath, relativeFilePath, global = false }) {
|
|
64646
65274
|
const paths = this.getSettablePaths({ global });
|
|
64647
|
-
const
|
|
64648
|
-
|
|
64649
|
-
|
|
65275
|
+
const channel = this.findChannelByPath({
|
|
65276
|
+
relativeDirPath,
|
|
65277
|
+
relativeFilePath,
|
|
65278
|
+
global
|
|
65279
|
+
})?.channel;
|
|
65280
|
+
const isRoot = channel === void 0 && relativeFilePath === paths.root.relativeFilePath && relativeDirPath === paths.root.relativeDirPath;
|
|
64650
65281
|
return new FactorydroidRule({
|
|
64651
65282
|
outputRoot,
|
|
64652
65283
|
relativeDirPath,
|
|
@@ -64654,22 +65285,24 @@ var FactorydroidRule = class FactorydroidRule extends ToolRule {
|
|
|
64654
65285
|
fileContent: "",
|
|
64655
65286
|
validate: false,
|
|
64656
65287
|
root: isRoot,
|
|
64657
|
-
|
|
65288
|
+
channel
|
|
64658
65289
|
});
|
|
64659
65290
|
}
|
|
64660
65291
|
static fromRulesyncRule({ outputRoot = process.cwd(), rulesyncRule, validate = true, global = false }) {
|
|
64661
65292
|
const frontmatter = rulesyncRule.getFrontmatter();
|
|
64662
65293
|
const paths = this.getSettablePaths({ global });
|
|
64663
|
-
|
|
64664
|
-
|
|
65294
|
+
const requestedChannel = frontmatter.factorydroid?.channel;
|
|
65295
|
+
const channelMatch = !global && !frontmatter.root && requestedChannel !== void 0 ? this.getChannelPaths({ global }).find(({ channel }) => channel === requestedChannel) : void 0;
|
|
65296
|
+
if (channelMatch) {
|
|
65297
|
+
const { channel, path } = channelMatch;
|
|
64665
65298
|
return new FactorydroidRule({
|
|
64666
65299
|
outputRoot,
|
|
64667
|
-
relativeDirPath:
|
|
64668
|
-
relativeFilePath:
|
|
65300
|
+
relativeDirPath: path.relativeDirPath,
|
|
65301
|
+
relativeFilePath: path.relativeFilePath,
|
|
64669
65302
|
fileContent: rulesyncRule.getBody(),
|
|
64670
65303
|
validate,
|
|
64671
65304
|
root: false,
|
|
64672
|
-
|
|
65305
|
+
channel
|
|
64673
65306
|
});
|
|
64674
65307
|
}
|
|
64675
65308
|
return new FactorydroidRule(this.buildToolRuleParamsAgentsmd({
|
|
@@ -64681,14 +65314,14 @@ var FactorydroidRule = class FactorydroidRule extends ToolRule {
|
|
|
64681
65314
|
}));
|
|
64682
65315
|
}
|
|
64683
65316
|
toRulesyncRule() {
|
|
64684
|
-
if (this.
|
|
65317
|
+
if (this.channel !== void 0) return new RulesyncRule({
|
|
64685
65318
|
outputRoot: process.cwd(),
|
|
64686
65319
|
relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
|
|
64687
|
-
relativeFilePath:
|
|
65320
|
+
relativeFilePath: this.getRelativeFilePath(),
|
|
64688
65321
|
frontmatter: {
|
|
64689
65322
|
root: false,
|
|
64690
65323
|
targets: ["factorydroid"],
|
|
64691
|
-
factorydroid: { channel:
|
|
65324
|
+
factorydroid: { channel: this.channel }
|
|
64692
65325
|
},
|
|
64693
65326
|
body: this.getFileContent()
|
|
64694
65327
|
});
|
|
@@ -67655,6 +68288,15 @@ const toolRuleFactories = /* @__PURE__ */ new Map([
|
|
|
67655
68288
|
ruleDiscoveryMode: "auto",
|
|
67656
68289
|
collisionPolicy: "fold"
|
|
67657
68290
|
}
|
|
68291
|
+
}],
|
|
68292
|
+
["dsh", {
|
|
68293
|
+
class: DshRule,
|
|
68294
|
+
meta: {
|
|
68295
|
+
extension: "md",
|
|
68296
|
+
supportsGlobal: true,
|
|
68297
|
+
ruleDiscoveryMode: "auto",
|
|
68298
|
+
collisionPolicy: "fold"
|
|
68299
|
+
}
|
|
67658
68300
|
}]
|
|
67659
68301
|
]);
|
|
67660
68302
|
const allToolTargetKeys = [...toolRuleFactories.keys()];
|
|
@@ -70754,4 +71396,4 @@ async function importChecksCore(params) {
|
|
|
70754
71396
|
//#endregion
|
|
70755
71397
|
export { RulesyncCheck as $, ALL_TOOL_TARGETS as $t, CLAUDECODE_SKILLS_DIR_PATH as A, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH as An, ensureDir as At, RulesyncSkill as B, quoteForLog as Bn, pathEscapesRoot as Bt, ChecksProcessor as C, RULESYNC_PERMISSIONS_FILE_NAME as Cn, applyFileMode as Ct, CLAUDECODE_LOCAL_RULE_FILE_NAME as D, RULESYNC_RELATIVE_DIR_PATH as Dn, checkPathTraversal as Dt, CLAUDECODE_DIR as E, RULESYNC_PERMISSIONS_SCHEMA_URL as En, assertWritablePathInsideRoot as Et, AUGMENTCODE_DIR as F, DEPRECATED_FEATURE_REPLACEMENTS as Fn, isFileSystemError as Ft, RulesyncMcp as G, removeFile as Gt, RulesyncRule as H, stripControlCharactersKeepingLineFeeds as Hn, readFileContentOrNull as Ht, AUGMENTCODE_SETTINGS_LOCAL_FILE_NAME as I, formatError as In, isSymlink as It, getRulesyncSourceCandidates as J, resolvePath as Jt, RulesyncIgnore as K, removeFileStrict as Kt, getLocalSkillDirNames as L, truncateText as Ln, listDirectoryEntryNames as Lt, FACTORYDROID_SETTINGS_LOCAL_FILE_NAME as M, parseCommaSeparatedList as Mn, getFileSize as Mt, caseFoldIdentity as N, ALL_FEATURES as Nn, getHomeDirectory as Nt, CLAUDECODE_MEMORIES_DIR_NAME as O, RULESYNC_RULES_RELATIVE_DIR_PATH as On, createTempDirectory as Ot, groupSpellingsByCaseFoldedIdentity as P, ALL_FEATURES_WITH_WILDCARD as Pn, isFileNotFoundError as Pt, RulesyncCommandFrontmatterSchema as Q, writeFileContent as Qt, RulesyncSubagent as R, hasDeceptiveHiddenCharacters as Rn, listFilePathsRecursively as Rt, QWENCODE_LOCAL_RULE_FILE_NAME as S, RULESYNC_NPM_SOURCES_LOCK_RELATIVE_FILE_PATH as Sn, ErrorCodes as St, CODEXCLI_DIR as T, RULESYNC_PERMISSIONS_RELATIVE_FILE_PATH as Tn, assertTreeContainsNoSymlinks as Tt, RulesyncRuleFrontmatterSchema as U, stripHiddenCharacters as Un, removeDirectory as Ut, RulesyncSkillFrontmatterSchema as V, stripControlCharacters as Vn, readFileContent as Vt, RulesyncPermissions as W, removeDirectoryStrict as Wt, parseJsonc as X, toPosixPath as Xt, resolveRulesyncSourceWritePath as Y, runWithDirectoryRollback as Yt, RulesyncCommand as Z, writeFileBuffer as Zt, IgnoreProcessor as _, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH as _n, warnOnConflictingFlags as _t, getProcessorRegistryEntry as a, RULESYNC_AIIGNORE_FILE_NAME as an, ConfigResolver as at, CommandsProcessor as b, RULESYNC_MCP_RELATIVE_FILE_PATH as bn, withWarnOnceScope as bt, RulesProcessor as c, RULESYNC_COMMANDS_RELATIVE_DIR_PATH as cn, CONFLICTING_TARGET_PAIRS as ct, CODEBUDDY_DIR as d, RULESYNC_CURATED_RULES_RELATIVE_DIR_PATH as dn, SourceEntrySchema as dt, ALL_TOOL_TARGETS_WITH_WILDCARD as en, RulesyncCheckFrontmatterSchema as et, CODEBUDDY_LOCAL_RULE_FILE_NAME as f, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH as fn, findControlCharacter as ft, McpProcessor as g, RULESYNC_IGNORE_RELATIVE_FILE_PATH as gn, fallbackLogger as gt, shortenToWidth as h, RULESYNC_HOOKS_RELATIVE_FILE_PATH as hn, WarningCollectingLogger as ht, inspectInputRoots as i, MAX_FILE_SIZE as in, SKILL_FILE_NAME as it, FACTORYDROID_DIR as j, RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH as jn, fileExists as jt, CLAUDECODE_SETTINGS_LOCAL_FILE_NAME as k, RULESYNC_SKILLS_RELATIVE_DIR_PATH as kn, directoryExists as kt, SubagentsProcessor as l, RULESYNC_CONFIG_RELATIVE_FILE_PATH as ln, ConfigFileSchema as lt, displayWidthOf as m, RULESYNC_HOOKS_LEGACY_FILE_NAME as mn, JsonLogger as mt, formatSourceLoadFailure as n, ToolTargetSchema as nn, loadYaml as nt, convertFromTool as o, RULESYNC_AIIGNORE_RELATIVE_FILE_PATH as on, mergeInputRootConfigs as ot, ELLIPSIS_WIDTH as p, RULESYNC_HOOKS_FILE_NAME as pn, ConsoleLogger as pt, RulesyncHooks as q, removeTempDirectory as qt, generate as r, CURATED_RULES_FEATURE_SUBDIR as rn, SHARED_USER_MANAGED_CONFIG_PATHS as rt, isPackagingToolTarget as s, RULESYNC_CHECKS_RELATIVE_DIR_PATH as sn, resolveEffectiveInputRoots as st, importFromTool as t, PACKAGING_TOOL_TARGETS as tn, stringifyFrontmatter as tt, SkillsProcessor as u, RULESYNC_CONFIG_SCHEMA_URL as un, GITIGNORE_DESTINATION_KEY as ut, CRUSH_LOCAL_RULE_FILE_NAME as v, RULESYNC_MCP_FILE_NAME as vn, withFallbackLoggerTarget as vt, CODEXCLI_BASH_RULES_FILE_NAME as w, RULESYNC_PERMISSIONS_LEGACY_FILE_NAME as wn, assertDirectoryIfExists as wt, QWENCODE_DIR as x, RULESYNC_MCP_SCHEMA_URL as xn, CLIError as xt, HooksProcessor as y, RULESYNC_MCP_LEGACY_FILE_NAME as yn, resetRunWarningState as yt, RulesyncSubagentFrontmatterSchema as z, hasEnclosingMarkOutsideKeycap as zn, listSubdirectoryNames as zt };
|
|
70756
71398
|
|
|
70757
|
-
//# sourceMappingURL=import-
|
|
71399
|
+
//# sourceMappingURL=import-BDlmyTcr.js.map
|