dsh-rules 0.1.0 → 0.1.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.
- package/lib/index.js +33 -5
- package/package.json +22 -6
package/lib/index.js
CHANGED
|
@@ -68,6 +68,7 @@ const Config = z.object({
|
|
|
68
68
|
*/
|
|
69
69
|
function apply(ctx, config = {}) {
|
|
70
70
|
const resolved = resolveConfig(config);
|
|
71
|
+
reportIgnoredPathEntries(ctx, config, resolved);
|
|
71
72
|
const state = new RulesState(ctx, resolved);
|
|
72
73
|
ctx.on("fs/observed", (target, observation, actor) => {
|
|
73
74
|
if (observation === void 0 || observation.kind === "absent") return;
|
|
@@ -106,19 +107,46 @@ function resolveConfig(config) {
|
|
|
106
107
|
return {
|
|
107
108
|
dshHome: resolveDshHome(config.dshHome),
|
|
108
109
|
projectRootMarkers: config.projectRootMarkers ?? [...DEFAULT_PROJECT_ROOT_MARKERS],
|
|
109
|
-
ruleDirNames:
|
|
110
|
+
ruleDirNames: cleanRelativePaths(config.ruleDirNames, DEFAULT_RULE_DIR_NAMES),
|
|
110
111
|
includeUserRules: config.includeUserRules ?? true,
|
|
111
112
|
includeClaudeSections: config.includeClaudeSections ?? false,
|
|
112
|
-
instructionFileCandidates:
|
|
113
|
-
localInstructionFileCandidates:
|
|
113
|
+
instructionFileCandidates: cleanRelativePaths(config.instructionFileCandidates, DEFAULT_INSTRUCTION_FILE_CANDIDATES),
|
|
114
|
+
localInstructionFileCandidates: cleanRelativePaths(config.localInstructionFileCandidates, DEFAULT_LOCAL_INSTRUCTION_FILE_CANDIDATES),
|
|
114
115
|
maxBytes: config.maxBytes ?? DEFAULT_MAX_BYTES,
|
|
115
116
|
maxSourceBytes: config.maxSourceBytes ?? DEFAULT_MAX_SOURCE_BYTES,
|
|
116
117
|
maxTouchedPaths: config.maxTouchedPaths ?? DEFAULT_MAX_TOUCHED_PATHS
|
|
117
118
|
};
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Whether one configured path entry can be safely joined under a known
|
|
123
|
+
* directory: every separator-delimited segment must be non-empty and none of
|
|
124
|
+
* "", ".", "..". Multi-segment relative paths such as the default
|
|
125
|
+
* ".dsh/rules" are expected; absolute paths and Windows drive prefixes are
|
|
126
|
+
* rejected.
|
|
127
|
+
*/
|
|
128
|
+
function isSafeRelativePath(candidate) {
|
|
129
|
+
if (typeof candidate !== "string" || candidate.length === 0) return false;
|
|
130
|
+
if (/^[A-Za-z]:/.test(candidate)) return false;
|
|
131
|
+
return candidate.split(/[\\/]/).every((segment) => !RESERVED_PATH_SEGMENTS.has(segment));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function cleanRelativePaths(candidates, fallback) {
|
|
135
|
+
return (candidates ?? [...fallback]).filter(isSafeRelativePath);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Config fields holding relative path entry lists (see {@link cleanRelativePaths}). */
|
|
139
|
+
const PATH_LIST_FIELDS = ["ruleDirNames", "instructionFileCandidates", "localInstructionFileCandidates"];
|
|
140
|
+
|
|
141
|
+
/** Warn when configured path entries were dropped as unsafe, instead of failing silently. */
|
|
142
|
+
function reportIgnoredPathEntries(ctx, config, resolved) {
|
|
143
|
+
for (const field of PATH_LIST_FIELDS) {
|
|
144
|
+
const configured = config[field];
|
|
145
|
+
if (!Array.isArray(configured)) continue;
|
|
146
|
+
const dropped = configured.length - resolved[field].length;
|
|
147
|
+
if (dropped <= 0) continue;
|
|
148
|
+
ctx.logger.warn(`dsh-rules: config.${field}: ignored ${dropped} unsafe ${dropped === 1 ? "entry" : "entries"} (expected project-relative paths such as ".dsh/rules"; ".", "..", empty, or absolute paths are ignored)`);
|
|
149
|
+
}
|
|
122
150
|
}
|
|
123
151
|
|
|
124
152
|
/** Per-process rules state: versioned rule caches and per-session touch sets. */
|
package/package.json
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-rules",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "DSH rules plugin: activate rule prompts / markdown documents by glob-matching the files an agent reads or edits (Claude Code rules.md style).",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"dsh",
|
|
7
|
+
"dsh-plugin",
|
|
8
|
+
"deepseek-harness",
|
|
9
|
+
"rules",
|
|
10
|
+
"claude-code",
|
|
11
|
+
"agents",
|
|
12
|
+
"prompt"
|
|
13
|
+
],
|
|
5
14
|
"license": "MIT",
|
|
6
15
|
"type": "module",
|
|
7
16
|
"main": "lib/index.js",
|
|
@@ -29,12 +38,14 @@
|
|
|
29
38
|
}
|
|
30
39
|
},
|
|
31
40
|
"dependencies": {
|
|
41
|
+
"picomatch": "^4.0.2",
|
|
42
|
+
"yaml": "^2.9.0"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
32
45
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
33
46
|
"@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6",
|
|
34
47
|
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
35
|
-
"@deepseek-ai/schemastery": "^3.18.1"
|
|
36
|
-
"picomatch": "^4.0.2",
|
|
37
|
-
"yaml": "^2.9.0"
|
|
48
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
38
49
|
},
|
|
39
50
|
"devDependencies": {
|
|
40
51
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
@@ -45,9 +56,14 @@
|
|
|
45
56
|
"yaml": "^2.9.0"
|
|
46
57
|
},
|
|
47
58
|
"scripts": {
|
|
48
|
-
"test": "node --test"
|
|
59
|
+
"test": "node --test",
|
|
60
|
+
"prepublishOnly": "pnpm test"
|
|
61
|
+
},
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public"
|
|
49
64
|
},
|
|
50
65
|
"engines": {
|
|
51
66
|
"node": "^22.19.0 || >=24.0.0"
|
|
52
|
-
}
|
|
67
|
+
},
|
|
68
|
+
"packageManager": "pnpm@11.7.0"
|
|
53
69
|
}
|