@czottmann/pi-automode 1.10.0 → 1.11.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 CHANGED
@@ -90,7 +90,7 @@ Set a global default classifier model in `~/.pi/agent/automode.json`; override i
90
90
 
91
91
  `classifierReasoningLevel` optionally requests `low`, `medium`, `high`, `xhigh`, or `max` reasoning for both classifier stages. If the key is absent, pi-automode sends no reasoning preference and leaves the choice to the server. Pi AI clamps unsupported values to the nearest level supported by the selected model; a non-reasoning model resolves to `off`. `low` matches Codex Auto Review's reasoning effort and the practical default when an explicit value is needed. Higher levels can consume the existing 512/1200-token stage limits before producing visible output, which causes the classifier to fail closed. Raise `fastClassifierMaxTokens` (default 512, integer ≥ 16) if you run a reasoning model whose fast-stage budget is truncated before it emits the required `0`/`1` digit.
92
92
 
93
- `allowInsideWorkingDirectory` (default `false`) adds a deterministic silent-allow tier for the file tools (`read`, `write`, `edit`, `grep`, `find`, `ls`): when `true`, a call whose resolved path is inside the working directory is allowed without any classifier call, and file access outside the working directory is routed to the classifier (including reads, which would otherwise take the read-only fast path). This matches the Codex/Claude Code "inside the sandbox = silent, outside = review" model. The tier takes precedence over `classifyReadOnlyTools`: with both enabled, in-tree file access is still allowed without a classifier call, and out-of-tree file access is classified. `classifyReadOnlyTools: true` only routes in-tree reads to the classifier when `allowInsideWorkingDirectory` is `false`.
93
+ `allowInsideWorkingDirectory` (default `false`) adds a deterministic silent-allow tier for the file tools (`read`, `write`, `edit`, `grep`, `find`, `ls`): when `true`, a call whose resolved path is inside the working directory is allowed without any classifier call, and file access outside the working directory is routed to the classifier (including reads, which would otherwise take the read-only fast path). This matches the Codex/Claude Code "inside the sandbox = silent, outside = review" model. The tier takes precedence over `classifyReadOnlyTools`: with both enabled, in-tree file access is still allowed without a classifier call, and out-of-tree file access is classified. `classifyReadOnlyTools: true` only routes in-tree reads to the classifier when `allowInsideWorkingDirectory` is `false`. Writes and edits to protected in-tree paths (`.git/hooks`, `.pi` controls, shell profiles, config files) are exempt from the silent-allow tier and still go to the classifier.
94
94
 
95
95
  `deniedPaths` (default `[]`) is a list of path glob patterns that are hard-denied before the classifier and before the inside-working-directory tier — the file-tool equivalent of a secret/system deny list. Patterns support `~`, `$HOME`, and `${HOME}` expansion and `*` (which matches any characters, including `/`, so `**/id_rsa` matches a private key at any depth). Matching checks both the path as typed and its symlink-resolved form, so a `~/.ssh/*` rule still matches when `~/.ssh` is a symlink. A matching path blocks the call unconditionally (no classifier, no override). The deny list applies to file tools only; `bash` path access is governed by the classifier. Both keys follow the normal scalar/array precedence.
96
96
 
@@ -177,7 +177,7 @@ The extension blocks these before any allow or classifier decision:
177
177
  - root, home, and system-path destructive deletes
178
178
  - edits to `.pi/automode*`, `.pi` auto-mode files, and this extension's safety-control files
179
179
 
180
- Read-only Pi tools (`read`, `grep`, `find`, `ls`) are allowed after those checks. Every side-effecting action goes to the classifier, including all `write` and `edit` calls, `bash`, MCP, subagent, network-capable tools, and unknown tools. This keeps classifier hard-deny rules unconditional; direct file writes cannot bypass them. Set `classifyReadOnlyTools: true` to route read-only tools through the classifier as well, so reads outside the trusted working tree can be denied by policy. With it enabled, every `read`, `grep`, `find`, and `ls` call runs the two-stage classifier, which raises the number of model calls, the latency, and the cost per session.
180
+ Read-only Pi tools (`read`, `grep`, `find`, `ls`) are allowed after those checks. Every side-effecting action goes to the classifier, including all `write` and `edit` calls, `bash`, MCP, subagent, network-capable tools, and unknown tools. This keeps classifier hard-deny rules unconditional; direct file writes cannot bypass them. Set `classifyReadOnlyTools: true` (default `false`) to route read-only tools through the classifier as well, so reads outside the trusted working tree can be denied by policy. With it enabled, every `read`, `grep`, `find`, and `ls` call runs the two-stage classifier, which raises the number of model calls, the latency, and the cost per session.
181
181
 
182
182
  Path matches in `deniedPaths` are blocked before every classifier and fast-path decision, so secret and system paths never reach the model through the file tools. The deny list does not govern `bash`; shell access to those paths is handled by the classifier and the deterministic hard-deny checks. With `allowInsideWorkingDirectory: true`, file tools inside the working directory are allowed without a classifier call, and outside-working-directory file access (reads included) goes to the classifier.
183
183
 
@@ -12,10 +12,11 @@ For each Pi `tool_call` event, the extension does this:
12
12
  4. Check `permissions.deny` rules.
13
13
  5. Check `permissions.ask` rules and ask the user when needed.
14
14
  6. Run deterministic hard-deny checks.
15
- 7. Allow read-only built-in tools without a classifier call.
16
- 8. Send every remaining action, including all writes and edits, through a one-token conservative filter.
17
- 9. Run structured classifier review only when the filter requests it, then allow or block.
18
- 10. Persist state and update the UI status/denial history.
15
+ 7. Run the path gate: `deniedPaths` matches block locally; with `allowInsideWorkingDirectory`, in-tree non-protected file access is allowed without a classifier call.
16
+ 8. Allow read-only built-in tools without a classifier call, unless `classifyReadOnlyTools` routes them through the classifier.
17
+ 9. Send every remaining action, including all writes and edits, through a one-token conservative filter.
18
+ 10. Run structured classifier review only when the filter requests it, then allow or block.
19
+ 11. Persist state and update the UI status/denial history.
19
20
 
20
21
  The default posture is fail-closed. If the classifier cannot be resolved, has no API key, errors, or returns an invalid stage response, the action is blocked.
21
22
 
@@ -43,7 +44,11 @@ flowchart TD
43
44
 
44
45
  J --> K{Deterministic hard-deny?}
45
46
  K -- yes --> K1[Block locally]
46
- K -- no --> L{Read-only built-in tool?}
47
+ K -- no --> K2{Path gate: deniedPaths match or in-tree allow tier?}
48
+
49
+ K2 -- denied --> K1[Block locally]
50
+ K2 -- in-tree, non-protected --> L1[Allow locally]
51
+ K2 -- no match or tier off --> L{Read-only built-in tool?}
47
52
 
48
53
  L -- yes --> L1[Allow locally]
49
54
  L -- no --> N[Run one-token filter]
@@ -145,9 +150,11 @@ Current deterministic blocks include:
145
150
 
146
151
  The `bash` checks use a small shell lexer. It handles quotes, redirects, pipes, `&&`, `||`, and `;` well enough to catch common "safe prefix, risky suffix" patterns.
147
152
 
148
- ### Read-only bypass
153
+ Recursive-delete checks treat `/`, the user's home root, and top-level system roots as hard-denied, but exempt the home *subtree*: subpaths of the user's home are user data, not system paths. On distros where `HOME` lives under `/var` (e.g. Fedora Silverblue with `/var/home/<user>`), `rm -rf` on home subpaths is therefore not hard-denied as a system-path delete, while `rm -rf ~` stays blocked.
154
+
155
+ ### Read-only bypass and the path gate
149
156
 
150
- Read-only built-in tools are allowed without classifier review after the checks above pass.
157
+ Read-only built-in tools are allowed without classifier review after the checks above pass, unless `classifyReadOnlyTools: true` routes them through the classifier instead.
151
158
 
152
159
  The read-only tool set is:
153
160
 
@@ -155,11 +162,13 @@ The read-only tool set is:
155
162
  read, grep, find, ls
156
163
  ```
157
164
 
158
- Reads to protected paths are still allowed. Every write and edit is classifier-reviewed, whether or not its target is protected.
165
+ Reads to protected paths are still allowed.
166
+
167
+ Two opt-in settings change the deterministic tier. `deniedPaths` blocks matching file-tool paths locally, before the classifier and any fast path. `allowInsideWorkingDirectory: true` allows file access inside the working directory without a classifier call — writes and edits included — while out-of-tree file access is routed to the classifier (reads included). Writes and edits to protected in-tree paths are exempt from the silent-allow tier and still reach the classifier. In the default configuration (both settings off), every write and edit is classifier-reviewed, whether or not its target is protected.
159
168
 
160
169
  ## Protected paths
161
170
 
162
- The protected-path configuration identifies safety-sensitive targets such as `.git`, `.pi`, editor config directories, shell profiles, package-manager config files, hook configs, and similar files. All writes and edits now go to the classifier, so there is no direct-write allow path that can bypass classifier policy for these or any other target.
171
+ The protected-path configuration identifies safety-sensitive targets such as `.git`, `.pi`, editor config directories, shell profiles, package-manager config files, hook configs, and similar files. In the default configuration every write and edit goes to the classifier, so there is no direct-write allow path that can bypass classifier policy. With `allowInsideWorkingDirectory: true`, non-protected in-tree writes take the deterministic allow tier, but protected targets still route to the classifier. `deniedPaths` can hard-deny any of these targets before the classifier.
163
172
 
164
173
  Deterministic safety-control checks still resolve paths canonically before classification. This catches writes through symlinks to auto-mode controls, shell profiles, and SSH authorization files without relying on the model.
165
174
 
package/docs/defaults.md CHANGED
@@ -46,13 +46,13 @@ These are exceptions to `soft_deny`, not to `hard_deny`.
46
46
 
47
47
  ### `protectedPaths`
48
48
 
49
- `$defaults` expands to safety-sensitive paths. Every `write` and `edit` call now goes to the classifier, so `protectedPaths` no longer changes whether a model call occurs; it remains part of the resolved configuration for compatibility and inspection. No path can be reached through a direct-write allow path, and `allow` rules cannot override a classifier hard-deny decision.
49
+ `$defaults` expands to safety-sensitive paths. In the default configuration every `write` and `edit` call goes to the classifier, so `protectedPaths` does not change whether a model call occurs; it remains part of the resolved configuration for compatibility and inspection. With `allowInsideWorkingDirectory: true`, non-protected in-tree file access takes the deterministic allow tier, but writes and edits to these protected paths still reach the classifier; `allow` rules cannot override a classifier hard-deny decision.
50
50
 
51
51
  Protected directories: `.git`, `.config/git`, `.vscode`, `.idea`, `.husky`, `.cargo`, `.devcontainer`, `.yarn`, `.mvn`, `.pi`.
52
52
 
53
53
  Protected files: `.gitconfig`, `.gitmodules`, `.gitignore`, `.gitattributes`, shell profiles (`.bashrc`, `.zshrc`, `.profile`, etc.), `.envrc`, package manager configs (`.npmrc`, `.yarnrc`, `.yarnrc.yml`, `.pnp.cjs`, `bunfig.toml`, etc.), Bazel configs (`.bazelrc`, `.bazelversion`, `.bazeliskrc`), hook configs (`.pre-commit-config.yaml`, `lefthook.yml`), Gradle/Maven wrappers, `.devcontainer.json`, `.ripgreprc`, `pyrightconfig.json`, `.mcp.json`.
54
54
 
55
- Read-only tools (`read`, `grep`, `find`, `ls`) remain locally allowed after permission and deterministic checks. Writes and edits always require classification, regardless of their target.
55
+ Read-only tools (`read`, `grep`, `find`, `ls`) remain locally allowed after permission and deterministic checks. In the default configuration writes and edits always require classification, regardless of their target; with `allowInsideWorkingDirectory` enabled, only protected targets still require it.
56
56
 
57
57
  ### `deniedPaths`
58
58
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@czottmann/pi-automode",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "Claude Code-style auto mode guardrail for pi.",
5
5
  "repository": {
6
6
  "url": "https://github.com/czottmann/pi-automode"