dsh-rules 0.1.1 → 0.1.2
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/LICENSE +21 -21
- package/README.md +188 -188
- package/README.zh.md +188 -188
- package/cordis.patch.yml +20 -20
- package/lib/fs.js +195 -195
- package/lib/index.js +476 -476
- package/lib/rules.js +336 -336
- package/package.json +9 -7
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 rj-jiangyichen
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 rj-jiangyichen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,188 +1,188 @@
|
|
|
1
|
-
# dsh-rules
|
|
2
|
-
|
|
3
|
-
[](LICENSE)
|
|
4
|
-
[](https://github.com/topics/dsh-plugin)
|
|
5
|
-
|
|
6
|
-
**English** | [中文](./README.zh.md)
|
|
7
|
-
|
|
8
|
-
Glob-activated rule prompts for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) — a Claude Code `rules.md` / `# Path:`-style mechanism. Each rule declares glob patterns; when the agent **reads or edits** a matching file, the rule activates and its content (any prompt or markdown document) is injected into the conversation as a superseding `<rules>` snapshot.
|
|
9
|
-
|
|
10
|
-
> Works in **every DSH deployment**: desktop / web / tui / headless / custom profiles — nothing about this plugin is desktop-specific.
|
|
11
|
-
|
|
12
|
-
## Contents
|
|
13
|
-
|
|
14
|
-
- [Features](#features)
|
|
15
|
-
- [How it works](#how-it-works)
|
|
16
|
-
- [Installation](#installation)
|
|
17
|
-
- [Rule format](#rule-format)
|
|
18
|
-
- [Configuration](#configuration)
|
|
19
|
-
- [Discoverability](#discoverability)
|
|
20
|
-
- [Limitations](#limitations)
|
|
21
|
-
- [Development](#development)
|
|
22
|
-
- [License](#license)
|
|
23
|
-
|
|
24
|
-
## Features
|
|
25
|
-
|
|
26
|
-
- **Glob activation** — rules activate per file the agent touches: `**`, `*`, `?`, `{a,b}`, `[abc]`, and `!` negation (picomatch).
|
|
27
|
-
- **Claude Code compatible** — plain rule files (`.dsh/rules/*.md`) *and* `# Path:` sections inside `CLAUDE.md` / `AGENTS.md`.
|
|
28
|
-
- **Visible & durable** — active rules are injected as a user message the UI shows and the session log persists; each snapshot supersedes earlier ones, so the model always sees the current set.
|
|
29
|
-
- **Budget-bounded** — byte-budget rendering (32 KB default): low-priority rules are dropped first, then the last rule is truncated; content is escaped so it can never break out of the framing tags.
|
|
30
|
-
- **Resume-friendly** — on session resume the last snapshot and its matched files are restored from the log, preventing duplicate injection.
|
|
31
|
-
- **Per-session tracking** — every agent/session tracks its own touched files (subagents included); global rules (no `path:`) are always active.
|
|
32
|
-
|
|
33
|
-
## How it works
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
workspace
|
|
37
|
-
.dsh/rules/*.md ← rule definitions (frontmatter declares globs)
|
|
38
|
-
~/.dsh/rules/*.md ← user-level rules (optional)
|
|
39
|
-
CLAUDE.md ← optional: # Path: sections (Claude Code compatible)
|
|
40
|
-
|
|
41
|
-
agent reads/edits a file (fs/observed) → record per-session touched path
|
|
42
|
-
↓ every step (agent/pre-step)
|
|
43
|
-
match touched paths against globs → collect active rules → render a <rules> snapshot into the conversation
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
- **Injection point**: an `agent/pre-step` waterfall listener appends a `<rules>`-framed user message; a new message is only appended when the snapshot text changes.
|
|
47
|
-
- **Discovery & caching**: rule sources are re-probed per step with version caching (`fs.stat().version`, or `mtimeMs:size` on the Node fallback) — edits to rule files take effect on the next step.
|
|
48
|
-
- **Reads**: prefer the harness `fs` service (containment-aware); fall back to Node's filesystem when no `fs` service is mounted.
|
|
49
|
-
|
|
50
|
-
## Installation
|
|
51
|
-
|
|
52
|
-
### Any DSH deployment (generic)
|
|
53
|
-
|
|
54
|
-
Published on the npm registry — `dsh plugin` installs **and activates** the plugin in one step:
|
|
55
|
-
|
|
56
|
-
```powershell
|
|
57
|
-
# Adjust the profile name: desktop / web / tui / headless
|
|
58
|
-
dsh plugin --profile desktop add dsh-rules
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
The package declares `dsh.bundle.patch`, so the reconcile pass of `dsh plugin add` appends `dsh-rules` to the profile's `dsh.profile.bundles` layer list automatically — **no manual `cordis.patch.yml` edits are needed**. Restart DSH (restart the desktop app; restart the web/headless process) and the plugin loads with the next Cordis composition.
|
|
62
|
-
|
|
63
|
-
Updates: `dsh plugin --profile desktop update dsh-rules` (or remove + add).
|
|
64
|
-
|
|
65
|
-
Installing from a local checkout (development):
|
|
66
|
-
|
|
67
|
-
```powershell
|
|
68
|
-
# From the repo root — activates the bundle automatically, same as the registry install
|
|
69
|
-
dsh plugin --profile desktop add .
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
> ⚠️ pnpm splits `add` arguments on spaces, so a repository **path containing spaces** must be installed through a no-space junction (see below).
|
|
73
|
-
|
|
74
|
-
### DSH Desktop (Windows) one-click script
|
|
75
|
-
|
|
76
|
-
```powershell
|
|
77
|
-
# 1. Clone this repository, then from the repo root:
|
|
78
|
-
node scripts\install-desktop.mjs
|
|
79
|
-
|
|
80
|
-
# 2. Restart DSH Desktop — the plugin loads with the next Cordis composition
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
The script creates a no-space junction to the repo and runs the desktop app's own `dsh plugin add` through it (pnpm splits `add` arguments on spaces, so a repository path containing spaces must go through the junction):
|
|
84
|
-
|
|
85
|
-
```powershell
|
|
86
|
-
# 0) Create a no-space junction to the repository (needed when the path contains spaces)
|
|
87
|
-
mklink /J "C:\code_repos\dsh-rules" "C:\code_repos\dsh rules plugin"
|
|
88
|
-
|
|
89
|
-
# 1) Install via the desktop's own dsh command (through the junction path)
|
|
90
|
-
& "C:\Program Files\DSH Desktop\DSH Desktop.exe" --expose-internals `
|
|
91
|
-
"C:\Program Files\DSH Desktop\resources\app.asar.unpacked\lib\desktop-cli.js" `
|
|
92
|
-
plugin --profile desktop add "C:\code_repos\dsh-rules"
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Per-profile configuration (optional): the plugin loads with its code defaults; to customize, override the entry's `config` in `<profile>/cordis.patch.yml`:
|
|
96
|
-
|
|
97
|
-
```yaml
|
|
98
|
-
- id: dsh-rules
|
|
99
|
-
name: dsh-rules
|
|
100
|
-
config:
|
|
101
|
-
includeClaudeSections: true
|
|
102
|
-
projectRootMarkers: [".git", ".dsh"]
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
**Uninstall**: `node scripts\install-desktop.mjs --uninstall` (or `dsh plugin --profile desktop remove dsh-rules`), then restart the app. Installing/uninstalling never touches the DSH installation directory (`resources\app.asar.unpacked`) — only profile configuration, fully reversible.
|
|
106
|
-
|
|
107
|
-
## Rule format
|
|
108
|
-
|
|
109
|
-
### Source A: rule files (`.dsh/rules/*.md` and `~/.dsh/rules/*.md`)
|
|
110
|
-
|
|
111
|
-
```markdown
|
|
112
|
-
---
|
|
113
|
-
path:
|
|
114
|
-
- "src/**/*.ts"
|
|
115
|
-
- "!src/**/*.test.ts"
|
|
116
|
-
---
|
|
117
|
-
Rule body (markdown, injected verbatim when active — any prompt content works)
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
| Frontmatter field | Description |
|
|
121
|
-
| --- | --- |
|
|
122
|
-
| `path` | String or list of globs, relative to the project root, `/` separators; `!` prefixes mark exclusion patterns. **Absent or empty = always-active global rule** (active for any session in the workspace). |
|
|
123
|
-
| `name` | Optional; rule identity (used for same-name deduplication). Defaults to the file name without `.md`. |
|
|
124
|
-
|
|
125
|
-
### Source B: `# Path:` sections (requires `includeClaudeSections: true`)
|
|
126
|
-
|
|
127
|
-
Parses `# Path: <globs…>` headings out of `AGENTS.md` / `CLAUDE.md` (including `.local.md` variants and `~/.dsh/AGENTS.md`):
|
|
128
|
-
|
|
129
|
-
```markdown
|
|
130
|
-
# Project notes (content before the first heading is handled by the built-in agent-instructions baseline, not by this plugin)
|
|
131
|
-
|
|
132
|
-
# Path: src/**/*.ts, scripts/**
|
|
133
|
-
This section activates only when a file under src/**/*.ts or scripts/ is touched
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
- Each `# Path:` heading starts a rule that runs until the next heading (or end of file).
|
|
137
|
-
- Globs may be comma- or space-separated.
|
|
138
|
-
- Content before the first `# Path:` heading is intentionally **not** injected by this plugin — DSH's built-in `agent-instructions` already injects the full AGENTS.md/CLAUDE.md baseline.
|
|
139
|
-
|
|
140
|
-
### Precedence & deduplication
|
|
141
|
-
|
|
142
|
-
Project rules (rank 100) > user rules (rank 200) > `# Path:` sections (rank 300). Same-name rules keep the highest-priority entry; rendering order is (rank, name) — deterministic across steps.
|
|
143
|
-
|
|
144
|
-
## Configuration
|
|
145
|
-
|
|
146
|
-
| Option | Default | Description |
|
|
147
|
-
| --- | --- | --- |
|
|
148
|
-
| `dshHome` | `$DSH_HOME` / `~/.dsh` | Root for user rules and `~/.dsh/AGENTS.md` |
|
|
149
|
-
| `projectRootMarkers` | `[".git"]` | Marker files/dirs used to find the project root by walking up |
|
|
150
|
-
| `ruleDirNames` | `[".dsh/rules"]` | Rule directories inside the project (relative to the project root, multiple allowed) |
|
|
151
|
-
| `includeUserRules` | `true` | Enable `~/.dsh/rules/*.md` |
|
|
152
|
-
| `includeClaudeSections` | `false` | Parse `# Path:` sections |
|
|
153
|
-
| `instructionFileCandidates` | `["AGENTS.md", "CLAUDE.md"]` | Candidate file names for `# Path:` sections |
|
|
154
|
-
| `localInstructionFileCandidates` | `["AGENTS.local.md", "CLAUDE.local.md"]` | Per-directory candidate file names |
|
|
155
|
-
| `maxBytes` | `32768` | Per-injection render budget (UTF-8 bytes); `<= 0` disables the plugin |
|
|
156
|
-
| `maxSourceBytes` | `1048576` | Per-rule source size cap; larger files are skipped |
|
|
157
|
-
| `maxTouchedPaths` | `512` | Touched-path cap per session (FIFO eviction) |
|
|
158
|
-
|
|
159
|
-
## Discoverability
|
|
160
|
-
|
|
161
|
-
This plugin is discoverable through the GitHub [`dsh-plugin`](https://github.com/topics/dsh-plugin) topic — the channel recommended by the [DeepSeek Harness README](https://github.com/deepseek-ai/deepseek-harness) ("Community and support": *Add the `dsh-plugin` topic to your plugin repository for discoverability*). Community plugin lists and marketplaces (e.g. awesome-dsh-plugin, dsh-plugin-marketplace) scan that topic to pick up new plugins; the tag can be viewed/edited in the repository's About section.
|
|
162
|
-
|
|
163
|
-
## Limitations
|
|
164
|
-
|
|
165
|
-
- Only files **inside the project root** can activate rules; reads outside the root never trigger (avoids `../` false positives).
|
|
166
|
-
- The touched-path set is in-memory: after resuming a session, rules re-activate as the agent re-reads files (the previously matched list is restored from the log).
|
|
167
|
-
- Deployments with `includeRuntimeContext: false` are unaffected — this plugin injects its own message and does not depend on the runtime-context snapshot.
|
|
168
|
-
- Rules are injected as "superseding snapshot" messages; the session log retains historical snapshots, but each snapshot is the complete current set and the model follows the latest one.
|
|
169
|
-
|
|
170
|
-
## Development
|
|
171
|
-
|
|
172
|
-
```powershell
|
|
173
|
-
pnpm install
|
|
174
|
-
pnpm test # node --test: parsing / glob matching / precedence / budget / determinism / fs fallback
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Layout:
|
|
178
|
-
|
|
179
|
-
- `lib/index.js` — plugin entry (`name` / `Config` / `apply`): `fs/observed` touch tracking, `agent/pre-step` injection, `agent/disposed` cleanup.
|
|
180
|
-
- `lib/rules.js` — pure logic: frontmatter and `# Path:` parsing, glob compilation/matching, precedence merging, budget rendering.
|
|
181
|
-
- `lib/fs.js` — versioned discovery/reads: harness `fs` service first, Node fallback.
|
|
182
|
-
- `test/rules.test.mjs` — unit tests.
|
|
183
|
-
- `examples/.dsh/rules/` — sample rules (copy into your project to get started).
|
|
184
|
-
- `fixtures/demo-project/` — a ready-made project for trying the plugin out.
|
|
185
|
-
|
|
186
|
-
## License
|
|
187
|
-
|
|
188
|
-
[MIT](LICENSE)
|
|
1
|
+
# dsh-rules
|
|
2
|
+
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
[](https://github.com/topics/dsh-plugin)
|
|
5
|
+
|
|
6
|
+
**English** | [中文](./README.zh.md)
|
|
7
|
+
|
|
8
|
+
Glob-activated rule prompts for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) — a Claude Code `rules.md` / `# Path:`-style mechanism. Each rule declares glob patterns; when the agent **reads or edits** a matching file, the rule activates and its content (any prompt or markdown document) is injected into the conversation as a superseding `<rules>` snapshot.
|
|
9
|
+
|
|
10
|
+
> Works in **every DSH deployment**: desktop / web / tui / headless / custom profiles — nothing about this plugin is desktop-specific.
|
|
11
|
+
|
|
12
|
+
## Contents
|
|
13
|
+
|
|
14
|
+
- [Features](#features)
|
|
15
|
+
- [How it works](#how-it-works)
|
|
16
|
+
- [Installation](#installation)
|
|
17
|
+
- [Rule format](#rule-format)
|
|
18
|
+
- [Configuration](#configuration)
|
|
19
|
+
- [Discoverability](#discoverability)
|
|
20
|
+
- [Limitations](#limitations)
|
|
21
|
+
- [Development](#development)
|
|
22
|
+
- [License](#license)
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
- **Glob activation** — rules activate per file the agent touches: `**`, `*`, `?`, `{a,b}`, `[abc]`, and `!` negation (picomatch).
|
|
27
|
+
- **Claude Code compatible** — plain rule files (`.dsh/rules/*.md`) *and* `# Path:` sections inside `CLAUDE.md` / `AGENTS.md`.
|
|
28
|
+
- **Visible & durable** — active rules are injected as a user message the UI shows and the session log persists; each snapshot supersedes earlier ones, so the model always sees the current set.
|
|
29
|
+
- **Budget-bounded** — byte-budget rendering (32 KB default): low-priority rules are dropped first, then the last rule is truncated; content is escaped so it can never break out of the framing tags.
|
|
30
|
+
- **Resume-friendly** — on session resume the last snapshot and its matched files are restored from the log, preventing duplicate injection.
|
|
31
|
+
- **Per-session tracking** — every agent/session tracks its own touched files (subagents included); global rules (no `path:`) are always active.
|
|
32
|
+
|
|
33
|
+
## How it works
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
workspace
|
|
37
|
+
.dsh/rules/*.md ← rule definitions (frontmatter declares globs)
|
|
38
|
+
~/.dsh/rules/*.md ← user-level rules (optional)
|
|
39
|
+
CLAUDE.md ← optional: # Path: sections (Claude Code compatible)
|
|
40
|
+
|
|
41
|
+
agent reads/edits a file (fs/observed) → record per-session touched path
|
|
42
|
+
↓ every step (agent/pre-step)
|
|
43
|
+
match touched paths against globs → collect active rules → render a <rules> snapshot into the conversation
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- **Injection point**: an `agent/pre-step` waterfall listener appends a `<rules>`-framed user message; a new message is only appended when the snapshot text changes.
|
|
47
|
+
- **Discovery & caching**: rule sources are re-probed per step with version caching (`fs.stat().version`, or `mtimeMs:size` on the Node fallback) — edits to rule files take effect on the next step.
|
|
48
|
+
- **Reads**: prefer the harness `fs` service (containment-aware); fall back to Node's filesystem when no `fs` service is mounted.
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
### Any DSH deployment (generic)
|
|
53
|
+
|
|
54
|
+
Published on the npm registry — `dsh plugin` installs **and activates** the plugin in one step:
|
|
55
|
+
|
|
56
|
+
```powershell
|
|
57
|
+
# Adjust the profile name: desktop / web / tui / headless
|
|
58
|
+
dsh plugin --profile desktop add dsh-rules
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The package declares `dsh.bundle.patch`, so the reconcile pass of `dsh plugin add` appends `dsh-rules` to the profile's `dsh.profile.bundles` layer list automatically — **no manual `cordis.patch.yml` edits are needed**. Restart DSH (restart the desktop app; restart the web/headless process) and the plugin loads with the next Cordis composition.
|
|
62
|
+
|
|
63
|
+
Updates: `dsh plugin --profile desktop update dsh-rules` (or remove + add).
|
|
64
|
+
|
|
65
|
+
Installing from a local checkout (development):
|
|
66
|
+
|
|
67
|
+
```powershell
|
|
68
|
+
# From the repo root — activates the bundle automatically, same as the registry install
|
|
69
|
+
dsh plugin --profile desktop add .
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
> ⚠️ pnpm splits `add` arguments on spaces, so a repository **path containing spaces** must be installed through a no-space junction (see below).
|
|
73
|
+
|
|
74
|
+
### DSH Desktop (Windows) one-click script
|
|
75
|
+
|
|
76
|
+
```powershell
|
|
77
|
+
# 1. Clone this repository, then from the repo root:
|
|
78
|
+
node scripts\install-desktop.mjs
|
|
79
|
+
|
|
80
|
+
# 2. Restart DSH Desktop — the plugin loads with the next Cordis composition
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The script creates a no-space junction to the repo and runs the desktop app's own `dsh plugin add` through it (pnpm splits `add` arguments on spaces, so a repository path containing spaces must go through the junction):
|
|
84
|
+
|
|
85
|
+
```powershell
|
|
86
|
+
# 0) Create a no-space junction to the repository (needed when the path contains spaces)
|
|
87
|
+
mklink /J "C:\code_repos\dsh-rules" "C:\code_repos\dsh rules plugin"
|
|
88
|
+
|
|
89
|
+
# 1) Install via the desktop's own dsh command (through the junction path)
|
|
90
|
+
& "C:\Program Files\DSH Desktop\DSH Desktop.exe" --expose-internals `
|
|
91
|
+
"C:\Program Files\DSH Desktop\resources\app.asar.unpacked\lib\desktop-cli.js" `
|
|
92
|
+
plugin --profile desktop add "C:\code_repos\dsh-rules"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Per-profile configuration (optional): the plugin loads with its code defaults; to customize, override the entry's `config` in `<profile>/cordis.patch.yml`:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
- id: dsh-rules
|
|
99
|
+
name: dsh-rules
|
|
100
|
+
config:
|
|
101
|
+
includeClaudeSections: true
|
|
102
|
+
projectRootMarkers: [".git", ".dsh"]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Uninstall**: `node scripts\install-desktop.mjs --uninstall` (or `dsh plugin --profile desktop remove dsh-rules`), then restart the app. Installing/uninstalling never touches the DSH installation directory (`resources\app.asar.unpacked`) — only profile configuration, fully reversible.
|
|
106
|
+
|
|
107
|
+
## Rule format
|
|
108
|
+
|
|
109
|
+
### Source A: rule files (`.dsh/rules/*.md` and `~/.dsh/rules/*.md`)
|
|
110
|
+
|
|
111
|
+
```markdown
|
|
112
|
+
---
|
|
113
|
+
path:
|
|
114
|
+
- "src/**/*.ts"
|
|
115
|
+
- "!src/**/*.test.ts"
|
|
116
|
+
---
|
|
117
|
+
Rule body (markdown, injected verbatim when active — any prompt content works)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
| Frontmatter field | Description |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `path` | String or list of globs, relative to the project root, `/` separators; `!` prefixes mark exclusion patterns. **Absent or empty = always-active global rule** (active for any session in the workspace). |
|
|
123
|
+
| `name` | Optional; rule identity (used for same-name deduplication). Defaults to the file name without `.md`. |
|
|
124
|
+
|
|
125
|
+
### Source B: `# Path:` sections (requires `includeClaudeSections: true`)
|
|
126
|
+
|
|
127
|
+
Parses `# Path: <globs…>` headings out of `AGENTS.md` / `CLAUDE.md` (including `.local.md` variants and `~/.dsh/AGENTS.md`):
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
# Project notes (content before the first heading is handled by the built-in agent-instructions baseline, not by this plugin)
|
|
131
|
+
|
|
132
|
+
# Path: src/**/*.ts, scripts/**
|
|
133
|
+
This section activates only when a file under src/**/*.ts or scripts/ is touched
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- Each `# Path:` heading starts a rule that runs until the next heading (or end of file).
|
|
137
|
+
- Globs may be comma- or space-separated.
|
|
138
|
+
- Content before the first `# Path:` heading is intentionally **not** injected by this plugin — DSH's built-in `agent-instructions` already injects the full AGENTS.md/CLAUDE.md baseline.
|
|
139
|
+
|
|
140
|
+
### Precedence & deduplication
|
|
141
|
+
|
|
142
|
+
Project rules (rank 100) > user rules (rank 200) > `# Path:` sections (rank 300). Same-name rules keep the highest-priority entry; rendering order is (rank, name) — deterministic across steps.
|
|
143
|
+
|
|
144
|
+
## Configuration
|
|
145
|
+
|
|
146
|
+
| Option | Default | Description |
|
|
147
|
+
| --- | --- | --- |
|
|
148
|
+
| `dshHome` | `$DSH_HOME` / `~/.dsh` | Root for user rules and `~/.dsh/AGENTS.md` |
|
|
149
|
+
| `projectRootMarkers` | `[".git"]` | Marker files/dirs used to find the project root by walking up |
|
|
150
|
+
| `ruleDirNames` | `[".dsh/rules"]` | Rule directories inside the project (relative to the project root, multiple allowed) |
|
|
151
|
+
| `includeUserRules` | `true` | Enable `~/.dsh/rules/*.md` |
|
|
152
|
+
| `includeClaudeSections` | `false` | Parse `# Path:` sections |
|
|
153
|
+
| `instructionFileCandidates` | `["AGENTS.md", "CLAUDE.md"]` | Candidate file names for `# Path:` sections |
|
|
154
|
+
| `localInstructionFileCandidates` | `["AGENTS.local.md", "CLAUDE.local.md"]` | Per-directory candidate file names |
|
|
155
|
+
| `maxBytes` | `32768` | Per-injection render budget (UTF-8 bytes); `<= 0` disables the plugin |
|
|
156
|
+
| `maxSourceBytes` | `1048576` | Per-rule source size cap; larger files are skipped |
|
|
157
|
+
| `maxTouchedPaths` | `512` | Touched-path cap per session (FIFO eviction) |
|
|
158
|
+
|
|
159
|
+
## Discoverability
|
|
160
|
+
|
|
161
|
+
This plugin is discoverable through the GitHub [`dsh-plugin`](https://github.com/topics/dsh-plugin) topic — the channel recommended by the [DeepSeek Harness README](https://github.com/deepseek-ai/deepseek-harness) ("Community and support": *Add the `dsh-plugin` topic to your plugin repository for discoverability*). Community plugin lists and marketplaces (e.g. awesome-dsh-plugin, dsh-plugin-marketplace) scan that topic to pick up new plugins; the tag can be viewed/edited in the repository's About section.
|
|
162
|
+
|
|
163
|
+
## Limitations
|
|
164
|
+
|
|
165
|
+
- Only files **inside the project root** can activate rules; reads outside the root never trigger (avoids `../` false positives).
|
|
166
|
+
- The touched-path set is in-memory: after resuming a session, rules re-activate as the agent re-reads files (the previously matched list is restored from the log).
|
|
167
|
+
- Deployments with `includeRuntimeContext: false` are unaffected — this plugin injects its own message and does not depend on the runtime-context snapshot.
|
|
168
|
+
- Rules are injected as "superseding snapshot" messages; the session log retains historical snapshots, but each snapshot is the complete current set and the model follows the latest one.
|
|
169
|
+
|
|
170
|
+
## Development
|
|
171
|
+
|
|
172
|
+
```powershell
|
|
173
|
+
pnpm install
|
|
174
|
+
pnpm test # node --test: parsing / glob matching / precedence / budget / determinism / fs fallback
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Layout:
|
|
178
|
+
|
|
179
|
+
- `lib/index.js` — plugin entry (`name` / `Config` / `apply`): `fs/observed` touch tracking, `agent/pre-step` injection, `agent/disposed` cleanup.
|
|
180
|
+
- `lib/rules.js` — pure logic: frontmatter and `# Path:` parsing, glob compilation/matching, precedence merging, budget rendering.
|
|
181
|
+
- `lib/fs.js` — versioned discovery/reads: harness `fs` service first, Node fallback.
|
|
182
|
+
- `test/rules.test.mjs` — unit tests.
|
|
183
|
+
- `examples/.dsh/rules/` — sample rules (copy into your project to get started).
|
|
184
|
+
- `fixtures/demo-project/` — a ready-made project for trying the plugin out.
|
|
185
|
+
|
|
186
|
+
## License
|
|
187
|
+
|
|
188
|
+
[MIT](LICENSE)
|