dsh-permission-rules 0.3.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to dsh-permission-rules are recorded here, newest first.
4
4
 
5
+ ## v0.4.0 — 2026-08-15
6
+
7
+ ### Hot reload and workspace identity
8
+
9
+ - **Mid-session rule-file creation is adopted automatically.** Expected-but-absent rule files (the project file when it is not in effect, a fallback deleted after mount) are now watched through their deepest existing ancestor directory (chokidar cannot reliably watch a missing path whose parent is also missing), so creating `.dsh/rules.yaml` — or recreating it after a fallback took over — takes effect without a manual `/rules reload`. Under `searchUp`, only the immediate cwd-level candidate is watched; deeper ancestors still need a reload.
10
+ - The per-workspace cache key is now the resolved cwd, case-folded on Windows: differently-spelled paths to the same workspace share one cache entry and one watcher set instead of doubling both.
11
+
12
+ ### Commands and observability
13
+
14
+ - `/rules test` accepts `--platform <name>` (one of the closed platform list): the `when.platform` match dimension is now dry-testable on any host, completing the flag coverage of every match dimension.
15
+ - `/rules` lists each rule with its own source file in multi-file chains (`searchUp`), via a localized `src:` attribution token; `/rules list` is an explicit alias for the bare listing.
16
+ - All five output languages carry the new `testBadPlatform` message, the updated usage strings, and the `src` token.
17
+
18
+ ### Engineering
19
+
20
+ - 133 tests across 8 suites (new coverage: creation-adoption watch paths, fallback recreation, cache-key dedup, `--platform`, `list`, source attribution); coverage gate held. Five-language READMEs, both rules-format references, AGENTS.md, and the `/rules` command hint updated.
21
+
5
22
  ## v0.3.0 — 2026-08-14
6
23
 
7
24
  ### Rules vocabulary
package/README.es.md CHANGED
@@ -55,8 +55,8 @@ Un segundo modelo responde *"¿es segura ESTA llamada?"* con criterio, pero cues
55
55
  - ✅ **Seam de aprobación oficial** — `ask` fluye por `ctx.approval`; nunca reimplementado, nunca eludido
56
56
  - ✅ **Auditoría completa** — los eventos `permissionRules/decision` llevan la acción de la regla, el cwd del workspace Y el resultado final de cada llamada; `/rules decisions` reproduce el rastro en la sesión
57
57
  - ✅ **Despliegue en simulación** — `enforce: false` audita lo que la política *haría* (acción hipotética + resultado real posterior, marcado `dryRun`) mientras deja pasar todas las llamadas; prueba segura de políticas en producción
58
- - ✅ **Prueba en seco** — `/rules test <tool> <json-args>` evalúa las reglas activas sin ejecutar nada, con sobrescrituras `--cwd`, `--env` y `--agent` para cada dimensión
59
- - ✅ **Recarga en caliente** — vigilancia Chokidar con debounce; una edición rota conserva las reglas previas, nunca falla
58
+ - ✅ **Prueba en seco** — `/rules test <tool> <json-args>` evalúa las reglas activas sin ejecutar nada, con sobrescrituras `--cwd`, `--env`, `--agent` y `--platform` para cada dimensión
59
+ - ✅ **Recarga en caliente** — vigilancia Chokidar con debounce; una edición rota conserva las reglas previas, nunca falla; un archivo de reglas creado a mitad de sesión (el del proyecto o el fallback) se adopta automáticamente, sin recarga manual
60
60
  - ✅ **Fallo ruidoso** — YAML inválido, acciones/campos desconocidos, globs/regex incorrectos, patrones propensos a backtracking o > `maxRules` hacen fallar la carga
61
61
  - ✅ **Ruta caliente acotada** — matchers precompilados, O(reglas × patrones), limitado por `maxRules`; el grado de backtracking de glob limitado por `maxGlobStars`
62
62
 
@@ -68,7 +68,7 @@ dsh plugin --profile web add "github:PerryLink/dsh-permission-rules#main"
68
68
 
69
69
  # o desde un tarball empaquetado (artefactos compilados, sin permiso de build)
70
70
  pnpm pack
71
- dsh plugin --profile web add ./dsh-permission-rules-0.3.0.tgz
71
+ dsh plugin --profile web add ./dsh-permission-rules-0.4.0.tgz
72
72
 
73
73
  # 2. reinicia
74
74
  dsh --profile web
@@ -119,12 +119,13 @@ Todos los ajustes son campos `Config` de Schemastery (modificables desde cordis.
119
119
 
120
120
  ```
121
121
  /rules lista las reglas activas, sus archivos fuente y cualquier error de la última recarga
122
+ /rules list alias explícito del listado simple
122
123
  /rules reload relee la cadena de archivos de reglas de este workspace
123
124
  /rules decisions [n] muestra las últimas n decisiones de permisos de esta sesión (por defecto 10)
124
125
  /rules test <tool> <json> evalúa en seco las reglas contra una llamada hipotética, p. ej. /rules test bash {"command":"git push origin main"}
125
126
  ```
126
127
 
127
- `/rules test` también acepta banderas iniciales: `--cwd <dir>` evalúa contra otro workspace, `--env CLAVE=VALOR` (repetible) sobrescribe el entorno para `when.env`, y `--agent <selector>` (repetible) suministra candidatos de identidad para la dimensión `agents`.
128
+ `/rules test` también acepta banderas iniciales: `--cwd <dir>` evalúa contra otro workspace, `--env CLAVE=VALOR` (repetible) sobrescribe el entorno para `when.env`, `--agent <selector>` (repetible) suministra candidatos de identidad para la dimensión `agents`, y `--platform <nombre>` sobrescribe la plataforma para `when.platform`. En cadenas de varios archivos (p. ej. `searchUp`), cada línea de regla se atribuye a su propio archivo fuente.
128
129
 
129
130
  La salida de los comandos es solo UI: el modelo aprende las reglas únicamente a través de los resultados de herramienta que producen. `language` elige el idioma de salida. Un JSON Schema del archivo de reglas se distribuye en [docs/rules-format.schema.json](docs/rules-format.schema.json) (conéctalo con `# yaml-language-server: $schema=...` para autocompletado en el editor).
130
131
 
@@ -172,7 +173,7 @@ node scripts/repair-session-logs.mjs repair [--home DIR] [--dry-run]
172
173
  pnpm install # node ^22.19 || >=24
173
174
  pnpm run typecheck # tsc, src + tests
174
175
  pnpm run lint # eslint, src + tests + scripts
175
- pnpm test # vitest: 106 tests, 8 suites
176
+ pnpm test # vitest: 133 tests, 8 suites
176
177
  pnpm run test:coverage # puerta de cobertura (90/80/90/90)
177
178
  pnpm run build # declaraciones tsc + bundles tsdown (lib/)
178
179
  pnpm run pack:check # build + pack (el artefacto publicado)
package/README.hi.md CHANGED
@@ -55,8 +55,8 @@ tools/pre-execute waterfall approval/request waterfall (answ
55
55
  - ✅ **आधिकारिक approval seam** — `ask` `ctx.approval` से होकर जाता है; कभी पुनः-कार्यान्वित नहीं, कभी बायपास नहीं
56
56
  - ✅ **पूर्ण ऑडिट** — `permissionRules/decision` इवेंट हर कॉल के लिए नियम क्रिया, workspace cwd और अंतिम परिणाम रखते हैं; `/rules decisions` सत्र में रास्ता फिर चलाता है
57
57
  - ✅ **dry-run रोलआउट** — `enforce: false` केवल ऑडिट करता है कि नीति *क्या करती* (काल्पनिक क्रिया + वास्तविक डाउनस्ट्रीम परिणाम, `dryRun` चिह्नित) और हर कॉल को पास करता है; उत्पादन में नई नीति का सुरक्षित परीक्षण
58
- - ✅ **dry-run परीक्षण** — `/rules test <tool> <json-args>` कुछ भी निष्पादित किए बिना सक्रिय नियमों का मूल्यांकन करता है, हर मिलान आयाम के लिए `--cwd`, `--env`, और `--agent` ओवरराइड के साथ
59
- - ✅ **हॉट रीलोड** — debounce सहित Chokidar निगरानी; टूटा हुआ संपादन पिछले नियम रखता है, कभी क्रैश नहीं करता
58
+ - ✅ **dry-run परीक्षण** — `/rules test <tool> <json-args>` कुछ भी निष्पादित किए बिना सक्रिय नियमों का मूल्यांकन करता है, हर मिलान आयाम के लिए `--cwd`, `--env`, `--agent` और `--platform` ओवरराइड के साथ
59
+ - ✅ **हॉट रीलोड** — debounce सहित Chokidar निगरानी; टूटा हुआ संपादन पिछले नियम रखता है, कभी क्रैश नहीं करता; सत्र के बीच बनाई गई नियम फ़ाइल (प्रोजेक्ट की या fallback) स्वतः अपनाई जाती है, मैनुअल रीलोड की आवश्यकता नहीं
60
60
  - ✅ **ज़ोरदार विफलता** — अमान्य YAML, अज्ञात action/फ़ील्ड, ख़राब globs/regex, बैकट्रैकिंग-प्रवण पैटर्न, या `maxRules` से अधिक → लोड विफल
61
61
  - ✅ **सीमित हॉट पथ** — पूर्व-संकलित matchers, O(नियम × पैटर्न), `maxRules` द्वारा सीमित; glob बैकट्रैकिंग डिग्री `maxGlobStars` द्वारा सीमित
62
62
 
@@ -68,7 +68,7 @@ dsh plugin --profile web add "github:PerryLink/dsh-permission-rules#main"
68
68
 
69
69
  # या पैक किए गए tarball से (बिल्ट आर्टिफ़ैक्ट, build अनुमति की ज़रूरत नहीं)
70
70
  pnpm pack
71
- dsh plugin --profile web add ./dsh-permission-rules-0.3.0.tgz
71
+ dsh plugin --profile web add ./dsh-permission-rules-0.4.0.tgz
72
72
 
73
73
  # 2. पुनः आरंभ करें
74
74
  dsh --profile web
@@ -119,12 +119,13 @@ dsh --profile web --dump-config | grep -A4 'id: permission-rules' # पंक
119
119
 
120
120
  ```
121
121
  /rules सक्रिय नियम, उनकी स्रोत फ़ाइलें और अंतिम रीलोड त्रुटि दिखाता है
122
+ /rules list सामान्य सूची का स्पष्ट उपनाम
122
123
  /rules reload इस workspace की नियम-फ़ाइल शृंखला दोबारा पढ़ता है
123
124
  /rules decisions [n] इस सत्र की अंतिम n अनुमति निर्णय दिखाता है (डिफ़ॉल्ट 10)
124
125
  /rules test <tool> <json> काल्पनिक कॉल के विरुद्ध नियमों का dry-मूल्यांकन, जैसे /rules test bash {"command":"git push origin main"}
125
126
  ```
126
127
 
127
- `/rules test` शुरुआती फ़्लैग भी स्वीकार करता है: `--cwd <dir>` दूसरे workspace के विरुद्ध मूल्यांकन करता है, `--env KEY=मान` (दोहराने योग्य) `when.env` के लिए होस्ट env ओवरराइड करता है, और `--agent <चयनकर्ता>` (दोहराने योग्य) `agents` आयाम के लिए पहचान उम्मीदवार देता है।
128
+ `/rules test` शुरुआती फ़्लैग भी स्वीकार करता है: `--cwd <dir>` दूसरे workspace के विरुद्ध मूल्यांकन करता है, `--env KEY=मान` (दोहराने योग्य) `when.env` के लिए होस्ट env ओवरराइड करता है, `--agent <चयनकर्ता>` (दोहराने योग्य) `agents` आयाम के लिए पहचान उम्मीदवार देता है, और `--platform <नाम>` `when.platform` के लिए होस्ट प्लेटफ़ॉर्म ओवरराइड करता है। बहु-फ़ाइल शृंखलाओं (जैसे `searchUp`) में हर नियम पंक्ति अपनी स्रोत फ़ाइल के साथ चिह्नित होती है।
128
129
 
129
130
  कमांड आउटपुट केवल UI के लिए है — मॉडल नियमों को केवल उनके उत्पन्न टूल परिणामों से ही सीखता है। `language` आउटपुट भाषा चुनता है। नियम फ़ाइल का JSON Schema [docs/rules-format.schema.json](docs/rules-format.schema.json) पर साथ आता है (संपादक पूर्णता के लिए `# yaml-language-server: $schema=...` से जोड़ें)।
130
131
 
@@ -172,7 +173,7 @@ node scripts/repair-session-logs.mjs repair [--home DIR] [--dry-run]
172
173
  pnpm install # node ^22.19 || >=24
173
174
  pnpm run typecheck # tsc, src + tests
174
175
  pnpm run lint # eslint, src + tests + scripts
175
- pnpm test # vitest: 106 tests, 8 suites
176
+ pnpm test # vitest: 133 tests, 8 suites
176
177
  pnpm run test:coverage # कवरेज द्वार (90/80/90/90)
177
178
  pnpm run build # tsc डिक्लेरेशन + tsdown bundles (lib/)
178
179
  pnpm run pack:check # build + pack (प्रकाशित आर्टिफ़ैक्ट)
package/README.md CHANGED
@@ -55,8 +55,8 @@ A second model answers *"is THIS call okay?"* with judgment, but costs a round-t
55
55
  - ✅ **Official approval seam** — `ask` flows through `ctx.approval`; never re-implemented, never bypassed
56
56
  - ✅ **Full audit** — `permissionRules/decision` events carry the rule action, the workspace cwd, AND the final outcome for every call; `/rules decisions` replays the trail in-session
57
57
  - ✅ **Dry-run rollout** — `enforce: false` audits what the policy *would* do (would-be action + real downstream outcome, `dryRun`-marked) while passing every call through; safe policy trialing in production
58
- - ✅ **Dry-run testing** — `/rules test <tool> <json-args>` evaluates the active rules without executing anything, with `--cwd`, `--env`, and `--agent` overrides for every match dimension
59
- - ✅ **Hot reload** — Chokidar watch with debounce; a broken edit keeps the previous rules, never crashes
58
+ - ✅ **Dry-run testing** — `/rules test <tool> <json-args>` evaluates the active rules without executing anything, with `--cwd`, `--env`, `--agent`, and `--platform` overrides for every match dimension
59
+ - ✅ **Hot reload** — Chokidar watch with debounce; a broken edit keeps the previous rules, never crashes; a rule file created mid-session (the project file or the fallback) is adopted automatically, no manual reload
60
60
  - ✅ **Fail loud** — invalid YAML, unknown actions/fields, bad globs/regexes, backtracking-prone patterns, or > `maxRules` fail the load
61
61
  - ✅ **Bounded hot path** — precompiled matchers, O(rules × patterns), capped by `maxRules`; glob backtracking degree capped by `maxGlobStars`
62
62
 
@@ -68,7 +68,7 @@ dsh plugin --profile web add "github:PerryLink/dsh-permission-rules#main"
68
68
 
69
69
  # or from a packed tarball (built artifacts, no build permission needed)
70
70
  pnpm pack
71
- dsh plugin --profile web add ./dsh-permission-rules-0.3.0.tgz
71
+ dsh plugin --profile web add ./dsh-permission-rules-0.4.0.tgz
72
72
 
73
73
  # 2. restart
74
74
  dsh --profile web
@@ -119,12 +119,13 @@ All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id
119
119
 
120
120
  ```
121
121
  /rules list the active rules, their source files, and any last-reload error
122
+ /rules list explicit alias for the bare listing
122
123
  /rules reload re-read the rule-file chain for this workspace
123
124
  /rules decisions [n] show the last n permission decisions of this session (default 10)
124
125
  /rules test <tool> <json> dry-evaluate the rules against a hypothetical call, e.g. /rules test bash {"command":"git push origin main"}
125
126
  ```
126
127
 
127
- `/rules test` also accepts leading flags: `--cwd <dir>` evaluates against another workspace, `--env KEY=VALUE` (repeatable) overrides host env for `when.env`, and `--agent <selector>` (repeatable) supplies identity candidates for the `agents` dimension.
128
+ `/rules test` also accepts leading flags: `--cwd <dir>` evaluates against another workspace, `--env KEY=VALUE` (repeatable) overrides host env for `when.env`, `--agent <selector>` (repeatable) supplies identity candidates for the `agents` dimension, and `--platform <name>` overrides the host platform for `when.platform`. In multi-file chains (e.g. `searchUp`), every listed rule line is attributed to its own source file.
128
129
 
129
130
  Command output is UI-only — the model learns the rules only through the tool results they produce. `language` picks the output language. A JSON Schema for the rule file ships at [docs/rules-format.schema.json](docs/rules-format.schema.json) (wire it up with `# yaml-language-server: $schema=...` for editor completion).
130
131
 
@@ -172,7 +173,7 @@ node scripts/repair-session-logs.mjs repair [--home DIR] [--dry-run]
172
173
  pnpm install # node ^22.19 || >=24
173
174
  pnpm run typecheck # tsc, src + tests
174
175
  pnpm run lint # eslint, src + tests + scripts
175
- pnpm test # vitest: 106 tests, 8 suites
176
+ pnpm test # vitest: 133 tests, 8 suites
176
177
  pnpm run test:coverage # coverage gate (90/80/90/90)
177
178
  pnpm run build # tsc declarations + tsdown bundles (lib/)
178
179
  pnpm run pack:check # build + pack (the published artifact)
package/README.pt.md CHANGED
@@ -55,8 +55,8 @@ Um segundo modelo responde *"ESTA chamada é segura?"* com julgamento, mas custa
55
55
  - ✅ **Seam de aprovação oficial** — `ask` flui por `ctx.approval`; nunca reimplementado, nunca contornado
56
56
  - ✅ **Auditoria completa** — os eventos `permissionRules/decision` carregam a ação da regra, o cwd do workspace E o resultado final de cada chamada; `/rules decisions` reproduz o rastro na sessão
57
57
  - ✅ **Implantação em simulação** — `enforce: false` audita o que a política *faria* (ação hipotética + resultado real posterior, marcado com `dryRun`) enquanto deixa todas as chamadas passarem; teste seguro de políticas em produção
58
- - ✅ **Teste em seco** — `/rules test <tool> <json-args>` avalia as regras ativas sem executar nada, com sobrescritas `--cwd`, `--env` e `--agent` para cada dimensão
59
- - ✅ **Recarga a quente** — vigilância Chokidar com debounce; uma edição quebrada mantém as regras anteriores, nunca quebra
58
+ - ✅ **Teste em seco** — `/rules test <tool> <json-args>` avalia as regras ativas sem executar nada, com sobrescritas `--cwd`, `--env`, `--agent` e `--platform` para cada dimensão
59
+ - ✅ **Recarga a quente** — vigilância Chokidar com debounce; uma edição quebrada mantém as regras anteriores, nunca quebra; um arquivo de regras criado no meio da sessão (o do projeto ou o fallback) é adotado automaticamente, sem recarga manual
60
60
  - ✅ **Falha ruidosa** — YAML inválido, ações/campos desconhecidos, globs/regex ruins, padrões propensos a backtracking ou > `maxRules` fazem a carga falhar
61
61
  - ✅ **Caminho quente limitado** — matchers pré-compilados, O(regras × padrões), limitado por `maxRules`; o grau de backtracking de glob limitado por `maxGlobStars`
62
62
 
@@ -68,7 +68,7 @@ dsh plugin --profile web add "github:PerryLink/dsh-permission-rules#main"
68
68
 
69
69
  # ou a partir de um tarball empacotado (artefatos compilados, sem permissão de build)
70
70
  pnpm pack
71
- dsh plugin --profile web add ./dsh-permission-rules-0.3.0.tgz
71
+ dsh plugin --profile web add ./dsh-permission-rules-0.4.0.tgz
72
72
 
73
73
  # 2. reinicie
74
74
  dsh --profile web
@@ -119,12 +119,13 @@ Todos os ajustes são campos `Config` do Schemastery (alteráveis no cordis.yml)
119
119
 
120
120
  ```
121
121
  /rules lista as regras ativas, seus arquivos de origem e qualquer erro da última recarga
122
+ /rules list alias explícito da listagem simples
122
123
  /rules reload relê a cadeia de arquivos de regras deste workspace
123
124
  /rules decisions [n] mostra as últimas n decisões de permissão desta sessão (padrão 10)
124
125
  /rules test <tool> <json> avalia em seco as regras contra uma chamada hipotética, ex.: /rules test bash {"command":"git push origin main"}
125
126
  ```
126
127
 
127
- `/rules test` também aceita sinalizadores iniciais: `--cwd <dir>` avalia contra outro workspace, `--env CHAVE=VALOR` (repetível) sobrescreve o ambiente para `when.env`, e `--agent <seletor>` (repetível) fornece candidatos de identidade para a dimensão `agents`.
128
+ `/rules test` também aceita sinalizadores iniciais: `--cwd <dir>` avalia contra outro workspace, `--env CHAVE=VALOR` (repetível) sobrescreve o ambiente para `when.env`, `--agent <seletor>` (repetível) fornece candidatos de identidade para a dimensão `agents`, e `--platform <nome>` sobrescreve a plataforma para `when.platform`. Em cadeias de vários arquivos (ex.: `searchUp`), cada linha de regra é atribuída ao seu próprio arquivo de origem.
128
129
 
129
130
  A saída dos comandos é somente UI — o modelo aprende as regras apenas pelos resultados de ferramenta que elas produzem. `language` escolhe o idioma da saída. Um JSON Schema do arquivo de regras é distribuído em [docs/rules-format.schema.json](docs/rules-format.schema.json) (conecte-o com `# yaml-language-server: $schema=...` para autocompletar no editor).
130
131
 
@@ -172,7 +173,7 @@ node scripts/repair-session-logs.mjs repair [--home DIR] [--dry-run]
172
173
  pnpm install # node ^22.19 || >=24
173
174
  pnpm run typecheck # tsc, src + tests
174
175
  pnpm run lint # eslint, src + tests + scripts
175
- pnpm test # vitest: 106 tests, 8 suites
176
+ pnpm test # vitest: 133 tests, 8 suites
176
177
  pnpm run test:coverage # portão de cobertura (90/80/90/90)
177
178
  pnpm run build # declarações tsc + bundles tsdown (lib/)
178
179
  pnpm run pack:check # build + pack (o artefato publicado)
package/README.zh.md CHANGED
@@ -55,8 +55,8 @@ tools/pre-execute waterfall approval/request waterfall(ans
55
55
  - ✅ **官方审批 seam** — `ask` 走 `ctx.approval`;不重复实现、绝不绕过
56
56
  - ✅ **完整审计** — `permissionRules/decision` 事件记录规则动作、工作区 cwd 与最终裁决;`/rules decisions` 可在会话内回放审计轨迹
57
57
  - ✅ **干跑上线** — `enforce: false` 只审计策略「本会做什么」(记录本会动作 + 下游真实结果,带 `dryRun` 标记),所有调用照常透传;可在生产环境安全试跑新策略
58
- - ✅ **干跑测试** — `/rules test <工具> <json-参数>` 不执行任何东西地评估规则命中,支持 `--cwd`、`--env`、`--agent` 覆盖每个匹配维度
59
- - ✅ **热更新** — Chokidar 监视 + 去抖;改坏了保留旧规则,绝不崩溃
58
+ - ✅ **干跑测试** — `/rules test <工具> <json-参数>` 不执行任何东西地评估规则命中,支持 `--cwd`、`--env`、`--agent`、`--platform` 覆盖每个匹配维度
59
+ - ✅ **热更新** — Chokidar 监视 + 去抖;改坏了保留旧规则,绝不崩溃;会话中途创建的规则文件(项目文件或 fallback)自动生效,无需手动重载
60
60
  - ✅ **响亮失败** — 非法 YAML、未知字段/action、坏 glob/正则、易回溯灾难的模式、超过 `maxRules` 都使加载失败
61
61
  - ✅ **热路径有界** — 预编译匹配器,O(规则数 × 模式数),`maxRules` 封顶;glob 回溯度由 `maxGlobStars` 封顶
62
62
 
@@ -68,7 +68,7 @@ dsh plugin --profile web add "github:PerryLink/dsh-permission-rules#main"
68
68
 
69
69
  # 或从打包好的 tarball 安装(预构建产物,无需构建许可)
70
70
  pnpm pack
71
- dsh plugin --profile web add ./dsh-permission-rules-0.3.0.tgz
71
+ dsh plugin --profile web add ./dsh-permission-rules-0.4.0.tgz
72
72
 
73
73
  # 2. 重启
74
74
  dsh --profile web
@@ -119,12 +119,13 @@ dsh --profile web --dump-config | grep -A4 'id: permission-rules' # 验证挂
119
119
 
120
120
  ```
121
121
  /rules 列出当前生效规则、来源文件与最近一次重载错误
122
+ /rules list 裸列出的显式别名
122
123
  /rules reload 重读本工作区的规则文件链
123
124
  /rules decisions [n] 显示本会话最近 n 条权限裁决(默认 10)
124
125
  /rules test <工具> <json> 对假设调用干跑评估,如 /rules test bash {"command":"git push origin main"}
125
126
  ```
126
127
 
127
- `/rules test` 还支持前置标志:`--cwd <目录>` 换一个工作区评估,`--env 键=值`(可重复)覆盖宿主环境变量以测试 `when.env`,`--agent <选择器>`(可重复)为 `agents` 维度提供身份候选。
128
+ `/rules test` 还支持前置标志:`--cwd <目录>` 换一个工作区评估,`--env 键=值`(可重复)覆盖宿主环境变量以测试 `when.env`,`--agent <选择器>`(可重复)为 `agents` 维度提供身份候选,`--platform <平台名>` 覆盖宿主平台以测试 `when.platform`。多文件链(如 `searchUp`)下,每条规则行都会标注它自己的来源文件。
128
129
 
129
130
  命令输出只进 UI——模型只通过规则产生的工具结果感知规则。`language` 选择输出语言。规则文件的 JSON Schema 随包发布在 [docs/rules-format.schema.json](docs/rules-format.schema.json)(用 `# yaml-language-server: $schema=...` 启用编辑器补全)。
130
131
 
@@ -172,7 +173,7 @@ node scripts/repair-session-logs.mjs repair [--home DIR] [--dry-run]
172
173
  pnpm install # node ^22.19 || >=24
173
174
  pnpm run typecheck # tsc,src + tests
174
175
  pnpm run lint # eslint,src + tests + scripts
175
- pnpm test # vitest:106 测试 / 8 套件
176
+ pnpm test # vitest:133 测试 / 8 套件
176
177
  pnpm run test:coverage # 覆盖率门禁(90/80/90/90)
177
178
  pnpm run build # tsc 声明 + tsdown 打包(lib/)
178
179
  pnpm run pack:check # 构建 + pack(发布产物)
@@ -100,9 +100,11 @@ This plugin only produces `ask` decisions; the `ask` goes to the official `ctx.a
100
100
 
101
101
  ## Loading and hot reload
102
102
 
103
- - Lazily discovered per session cwd and cached on the first `tools/pre-execute` (least-recently-used eviction beyond `maxCachedWorkspaces`).
103
+ - Lazily discovered per session cwd and cached on the first `tools/pre-execute` (least-recently-used eviction beyond `maxCachedWorkspaces`); the cache key is the resolved cwd (case-folded on Windows), so differently-spelled paths share one entry.
104
104
  - Invalid YAML, unknown fields/actions, bad globs/regexes, backtracking-prone patterns, and counts over `maxRules` are load-time errors: `badFilePolicy: fail` (default) makes the first tool call in that workspace fail loudly; `ignore-with-warning` warns and degrades to an empty rule set.
105
105
  - An absolute `rulesFile` or a configured `fallbackPath` is validated at plugin mount — missing or invalid fails the mount.
106
106
  - File changes reload through Chokidar with a debounce (`watch`, `watchStabilityThresholdMs`); a failed reload keeps the previous rules and only warns — never crashes. `/rules reload` triggers the same path manually; `/rules decisions` and `/rules test` inspect the trail and dry-run the rules.
107
- - `/rules test` accepts leading flags: `--cwd <dir>` evaluates against another workspace (rule discovery AND path normalization), `--env KEY=VALUE` (repeatable) overrides host env for `when.env`, and `--agent <selector>` (repeatable) supplies identity candidates for the `agents` dimension.
107
+ - Expected-but-absent rule files (the project file when it is not in effect, a fallback after it was deleted) are watched through their deepest existing ancestor directory: creating one mid-session is adopted automatically without a manual reload. Under `searchUp` only the immediate cwd-level candidate is watched — creating a rule file in a deeper ancestor still needs `/rules reload`.
108
+ - `/rules` lists the active rules (with `list` as an explicit alias); in multi-file chains every rule line is attributed to its own source file.
109
+ - `/rules test` accepts leading flags: `--cwd <dir>` evaluates against another workspace (rule discovery AND path normalization), `--env KEY=VALUE` (repeatable) overrides host env for `when.env`, `--agent <selector>` (repeatable) supplies identity candidates for the `agents` dimension, and `--platform <name>` overrides the host platform for `when.platform`.
108
110
  - `enforce: false` puts the plugin in dry-run mode: deny/ask hits are audit-logged with a `dryRun` marker (keeping the would-be action and the real downstream outcome) and every call passes through — use it to trial a new policy in production before enforcing it. `/rules` prints a dry-run notice while the mode is active.
@@ -98,9 +98,11 @@ rules:
98
98
 
99
99
  ## 加载与热更新
100
100
 
101
- - 按会话 cwd 惰性发现,首次 `tools/pre-execute` 时加载并缓存(超出 `maxCachedWorkspaces` 逐出最久未用项)。
101
+ - 按会话 cwd 惰性发现,首次 `tools/pre-execute` 时加载并缓存(超出 `maxCachedWorkspaces` 逐出最久未用项);缓存键为解析后的 cwd(Windows 上折叠大小写),同一目录的不同拼写共享同一条目。
102
102
  - 非法 YAML / 未知字段或 action / 坏 glob 与正则 / 易回溯灾难的模式 / 超 `maxRules` 都是加载期错误:`badFilePolicy: fail`(默认)时首个使用该工作区的工具调用响亮失败;`ignore-with-warning` 时告警并降级为空规则集。
103
103
  - 绝对 `rulesFile` 或配置的 `fallbackPath` 在插件挂载时即校验,缺失/非法直接挂载失败。
104
104
  - 文件变更后经 Chokidar 去抖重读(`watch`、`watchStabilityThresholdMs`);重读失败保留旧规则、只告警,绝不崩溃。`/rules reload` 手动触发同样路径;`/rules decisions` 回放审计轨迹,`/rules test` 对假设调用干跑规则。
105
- - `/rules test` 支持前置标志:`--cwd <目录>` 换一个工作区求值(规则发现与路径归一化都切换);`--env 键=值`(可重复)覆盖宿主环境变量以测试 `when.env`;`--agent <选择器>`(可重复)为 `agents` 维度提供身份候选。
105
+ - 预期存在但缺失的规则文件(未生效的项目文件、被删除后的 fallback)会通过其最近存在祖先目录被监听:会话中途创建即自动采纳,无需手动重载。`searchUp` 下只监听 cwd 层级的候选——更上层祖先新建规则文件仍需 `/rules reload`。
106
+ - `/rules` 列出当前规则(`list` 为显式别名);多文件链中每条规则行标注自己的来源文件。
107
+ - `/rules test` 支持前置标志:`--cwd <目录>` 换一个工作区求值(规则发现与路径归一化都切换);`--env 键=值`(可重复)覆盖宿主环境变量以测试 `when.env`;`--agent <选择器>`(可重复)为 `agents` 维度提供身份候选;`--platform <平台名>` 覆盖宿主平台以测试 `when.platform`。
106
108
  - `enforce: false` 让插件进入干跑模式:deny/ask 命中只写审计(带 `dryRun` 标记,记录「本会做什么」与下游真实结果),所有调用照常透传——用于在生产环境先试跑新策略再强制执行。激活期间 `/rules` 会打印干跑提示。