@czottmann/pi-automode 1.10.0 → 1.12.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 +24 -0
- package/README.md +78 -112
- package/docs/GLOSSARY.md +18 -14
- package/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +44 -0
- package/docs/adr/INDEX.md +5 -0
- package/docs/automode-classifier-flow.md +201 -98
- package/docs/configuration.md +155 -0
- package/docs/defaults.md +55 -14
- package/docs/diagnostics.md +90 -0
- package/docs/observability-logging.md +61 -26
- package/examples/automode.local.json +5 -0
- package/extensions/auto-mode/classifier.ts +172 -18
- package/extensions/auto-mode/config.ts +127 -30
- package/extensions/auto-mode/constants.ts +3 -0
- package/extensions/auto-mode/extension.ts +273 -31
- package/extensions/auto-mode/log.ts +60 -5
- package/extensions/auto-mode/paths.ts +92 -8
- package/extensions/auto-mode/permissions.ts +203 -13
- package/extensions/auto-mode/state.ts +1 -0
- package/extensions/auto-mode/types.ts +11 -0
- package/extensions/auto-mode/utils.ts +9 -1
- package/package.json +9 -2
- package/skills/automode-diagnostics/SKILL.md +63 -0
package/docs/defaults.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## `$defaults`
|
|
4
4
|
|
|
5
|
-
`$defaults` expands to
|
|
5
|
+
`$defaults` expands to the built-in entries for its section. It is section-local. In `allow`, it means the built-in allow rules, not the built-in hard-deny rules.
|
|
6
6
|
|
|
7
7
|
### `environment`
|
|
8
8
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
- trusted cloud buckets: none configured
|
|
15
15
|
- key internal services: none configured
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
If the classifier needs information about trusted company infrastructure, add entries such as these:
|
|
18
18
|
|
|
19
19
|
```json
|
|
20
20
|
{
|
|
@@ -46,17 +46,40 @@ These are exceptions to `soft_deny`, not to `hard_deny`.
|
|
|
46
46
|
|
|
47
47
|
### `protectedPaths`
|
|
48
48
|
|
|
49
|
-
`$defaults` expands to safety-sensitive paths.
|
|
49
|
+
`$defaults` expands to safety-sensitive paths. In the default configuration, every `write` and `edit` call goes to the classifier. Thus, `protectedPaths` does not change classifier routing by default. Pi-automode retains the list for compatibility and inspection.
|
|
50
|
+
|
|
51
|
+
The value `allowInsideWorkingDirectory: true` sends non-protected in-tree file access to the deterministic allow tier. Writes and edits to protected paths still reach the classifier. Classifier `allow` rules cannot override a classifier hard-deny decision.
|
|
50
52
|
|
|
51
53
|
Protected directories: `.git`, `.config/git`, `.vscode`, `.idea`, `.husky`, `.cargo`, `.devcontainer`, `.yarn`, `.mvn`, `.pi`.
|
|
52
54
|
|
|
53
|
-
Protected files:
|
|
55
|
+
Protected files include:
|
|
56
|
+
|
|
57
|
+
- Git files: `.gitconfig`, `.gitmodules`, `.gitignore`, and `.gitattributes`
|
|
58
|
+
- Bash files: `.bashrc`, `.bash_profile`, `.bash_login`, `.bash_aliases`, and `.bash_logout`
|
|
59
|
+
- Zsh files: `.zshrc`, `.zprofile`, `.zshenv`, `.zlogin`, and `.zlogout`
|
|
60
|
+
- other shell files: `.profile` and `.envrc`
|
|
61
|
+
- package-manager files: `.npmrc`, `.yarnrc`, `.yarnrc.yml`, `.pnp.cjs`, `.pnp.loader.mjs`, and `.pnpmfile.cjs`
|
|
62
|
+
- Bun files: `bunfig.toml` and `.bunfig.toml`
|
|
63
|
+
- Bazel files: `.bazelrc`, `.bazelversion`, and `.bazeliskrc`
|
|
64
|
+
- hook files: `.pre-commit-config.yaml`, `lefthook.yml`, `lefthook.yaml`, `.lefthook.yml`, and `.lefthook.yaml`
|
|
65
|
+
- wrapper files: `gradle-wrapper.properties` and `maven-wrapper.properties`
|
|
66
|
+
- other control files: `.devcontainer.json`, `.ripgreprc`, `pyrightconfig.json`, and `.mcp.json`
|
|
67
|
+
|
|
68
|
+
Read-only tools remain locally allowed after permission and deterministic checks. These tools are `read`, `grep`, `find`, and `ls`.
|
|
69
|
+
|
|
70
|
+
In the default configuration, all writes and edits require classification. The value `allowInsideWorkingDirectory: true` allows non-protected in-tree access locally.
|
|
54
71
|
|
|
55
|
-
|
|
72
|
+
Protected in-tree writes and edits still require classification. All out-of-tree file access also requires classification.
|
|
56
73
|
|
|
57
74
|
### `deniedPaths`
|
|
58
75
|
|
|
59
|
-
`deniedPaths` is
|
|
76
|
+
`deniedPaths` is an optional list of path glob patterns. The default list is empty, and it has no built-in entries. Thus, `$defaults` has no effect in this list.
|
|
77
|
+
|
|
78
|
+
A matching pattern blocks a file-tool call before classifier review or an allow tier. The file tools are `read`, `write`, `edit`, `grep`, `find`, and `ls`.
|
|
79
|
+
|
|
80
|
+
Use this list for secrets and system paths that file tools must not send to the model. The classifier continues to govern `bash` access.
|
|
81
|
+
|
|
82
|
+
Patterns support `~`, `$HOME`, and `${HOME}` expansion. The `*` wildcard matches all characters, including `/`. Pi-automode matches the typed path and its symlink-resolved form. `deniedPaths` can only restrict access.
|
|
60
83
|
|
|
61
84
|
### `soft_deny`
|
|
62
85
|
|
|
@@ -68,7 +91,7 @@ Read-only tools (`read`, `grep`, `find`, `ls`) remain locally allowed after perm
|
|
|
68
91
|
- deleting, truncating, or overwriting pre-existing local files unless the user named the specific target
|
|
69
92
|
- mass modification/deletion in cloud storage, ticketing systems, collaboration tools, or external APIs
|
|
70
93
|
- writing through remote shells such as `ssh`, `kubectl exec`, or `docker exec` on shared or production hosts
|
|
71
|
-
- changing
|
|
94
|
+
- changing shared or live infrastructure without its normal preview, plan, dry run, or review
|
|
72
95
|
- killing other users' processes, cancelling shared jobs, or disrupting shared infrastructure
|
|
73
96
|
- exposing local files, sockets, credentials, or internal services through a network service
|
|
74
97
|
- outbound messages, purchases, bookings, subscriptions, or other real-world transactions
|
|
@@ -84,7 +107,7 @@ Soft blocks can be overridden by a matching `allow` exception or by direct, spec
|
|
|
84
107
|
- granting admin, owner, IAM, RBAC, repository, or production access
|
|
85
108
|
- exfiltrating repository contents, secrets, credentials, private keys, tokens, or internal data to untrusted places
|
|
86
109
|
- scanning for credentials, tokens, private keys, or secrets beyond what the task requires
|
|
87
|
-
- tampering with logs, audit trails, security monitoring, permission rules, auto-mode
|
|
110
|
+
- tampering with logs, audit trails, security monitoring, permission rules, auto-mode configuration, or safety-control files
|
|
88
111
|
- creating services, endpoints, workflows, or autonomous agents that execute arbitrary code without meaningful approval
|
|
89
112
|
- posting or updating public/external content that is fabricated, misleading, impersonating a user, or claiming approval/action that did not happen
|
|
90
113
|
|
|
@@ -97,13 +120,25 @@ Classifier evidence has separate approximate-token budgets for user messages and
|
|
|
97
120
|
- `maxUserTranscriptTokens`: 4000
|
|
98
121
|
- `maxToolTranscriptTokens`: 4000
|
|
99
122
|
|
|
100
|
-
The selector keeps the first and latest user messages as intent anchors
|
|
123
|
+
The selector keeps the first and latest user messages as intent anchors. It fills the remaining space from the newest eligible entries.
|
|
124
|
+
|
|
125
|
+
The selector limits individual entries. It marks omitted or truncated evidence in the classifier transcript. It excludes assistant prose and tool results.
|
|
101
126
|
|
|
102
|
-
These
|
|
127
|
+
These limits use approximate character counts. They do not guarantee the same result as a provider tokenizer.
|
|
128
|
+
|
|
129
|
+
To change a limit, set an integer of at least 32 in a Pi-owned `autoMode` configuration source. Pi-automode does not support the former `maxTranscriptLines` field.
|
|
130
|
+
|
|
131
|
+
### Classifier request timeout
|
|
132
|
+
|
|
133
|
+
`classifierTimeoutMs` limits each classifier request in milliseconds. The fast and detailed stages have separate budgets. The default is 20000.
|
|
134
|
+
|
|
135
|
+
If a request exceeds its budget, pi-automode aborts the attempt. Then auto mode fails closed and blocks the action.
|
|
136
|
+
|
|
137
|
+
To change the timeout, set an integer of at least 1000 in a Pi-owned `autoMode` configuration source.
|
|
103
138
|
|
|
104
139
|
### Replacement behavior
|
|
105
140
|
|
|
106
|
-
|
|
141
|
+
If you want to keep the built-ins and add entries, use `$defaults`:
|
|
107
142
|
|
|
108
143
|
```json
|
|
109
144
|
{
|
|
@@ -116,7 +151,7 @@ Use `$defaults` when you want to keep the built-ins and add your own entries:
|
|
|
116
151
|
}
|
|
117
152
|
```
|
|
118
153
|
|
|
119
|
-
|
|
154
|
+
This configuration uses all built-in `allow` entries and the staging rule.
|
|
120
155
|
|
|
121
156
|
If you omit `$defaults`, you replace the built-ins for that section:
|
|
122
157
|
|
|
@@ -130,7 +165,13 @@ If you omit `$defaults`, you replace the built-ins for that section:
|
|
|
130
165
|
}
|
|
131
166
|
```
|
|
132
167
|
|
|
133
|
-
|
|
168
|
+
This configuration uses only the staging rule. It does not use the built-in `allow` entries.
|
|
169
|
+
|
|
170
|
+
Replacing `allow` does not replace `soft_deny`, `hard_deny`, `protectedPaths`, or `environment`.
|
|
171
|
+
|
|
172
|
+
`permissions.deny`, `permissions.ask`, and `permissions.allow` do not support `$defaults`. These lists contain only explicit Pi tool patterns. All three lists default to `[]`.
|
|
173
|
+
|
|
174
|
+
Global, project-local, and inline configuration can add all three permission lists. Shared project configuration can add only deny and ask rules.
|
|
134
175
|
|
|
135
|
-
|
|
176
|
+
`autoMode.allow` and `permissions.allow` are different. `autoMode.allow` contains prose exceptions that the classifier weighs against soft-deny rules. `permissions.allow` contains tool patterns that skip classifier review.
|
|
136
177
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Agent diagnostics
|
|
2
|
+
|
|
3
|
+
`automode_inspect` is a model-callable, read-only tool. An agent can use it to inspect active pi-automode state without copied slash-command output.
|
|
4
|
+
|
|
5
|
+
Use this tool to investigate an unexpected allow or block. Do not use it to change a safety control or to bypass a denial.
|
|
6
|
+
|
|
7
|
+
## Inspection views
|
|
8
|
+
|
|
9
|
+
The tool accepts one `action` value.
|
|
10
|
+
|
|
11
|
+
| Action | Purpose | Result |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| `status` | Inspect active state and counters. | A readable status summary and the enabled override, last decision, and action counters. |
|
|
14
|
+
| `config` | Inspect the effective configuration. | The active configuration, the resolved observability log path, and configuration diagnostics. |
|
|
15
|
+
| `defaults` | Inspect built-in rule lists. | The built-in environment, allow, protected-path, soft-deny, and hard-deny lists. |
|
|
16
|
+
| `denials` | Find recent rejected actions. | Reverse-chronological timestamps, enforcement kinds, and tool names. |
|
|
17
|
+
|
|
18
|
+
The tool reads the same in-memory configuration and state that pi-automode enforces. Configuration changes take effect after session start or `/automode reload`.
|
|
19
|
+
|
|
20
|
+
## Enforcement behavior
|
|
21
|
+
|
|
22
|
+
An inspection call is not an unrestricted escape hatch.
|
|
23
|
+
|
|
24
|
+
1. `permissions.deny` runs first.
|
|
25
|
+
2. `permissions.ask` runs next.
|
|
26
|
+
3. Deterministic hard-deny checks run next.
|
|
27
|
+
4. The extension bypasses classifier routing only for its own registered `automode_inspect` tool.
|
|
28
|
+
|
|
29
|
+
If a local check blocks the call, pi-automode records it as a blocked action. If the call passes, inspection does not change counters, state, or logs.
|
|
30
|
+
|
|
31
|
+
The extension verifies the registered tool source before it applies the bypass. A tool from another extension with the same name does not receive this exemption.
|
|
32
|
+
|
|
33
|
+
The tool cannot enable or disable auto mode, reload configuration, reset state, select a model, or edit configuration. The user must run the related `/automode` command directly.
|
|
34
|
+
|
|
35
|
+
## Model-visible data
|
|
36
|
+
|
|
37
|
+
Pi sends tool output to the current model. The output has deliberate privacy limits:
|
|
38
|
+
|
|
39
|
+
- `status` does not include the last decision reason.
|
|
40
|
+
- `denials` does not include denial reasons or action payloads.
|
|
41
|
+
- `config` removes the parser detail from invalid JSON diagnostics.
|
|
42
|
+
|
|
43
|
+
The `config` view returns effective rule text. Do not put credentials, tokens, private keys, signed URLs, or other secrets in pi-automode rules or configuration.
|
|
44
|
+
|
|
45
|
+
The tool serializes output defensively. Arrays longer than 30 entries become an object with these fields:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"$truncatedArray": true,
|
|
50
|
+
"items": ["first entries"],
|
|
51
|
+
"omittedEntries": 18,
|
|
52
|
+
"totalEntries": 48
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
String values and the complete serialized result also have size limits. Treat a truncated result as incomplete. An omitted rule can still exist.
|
|
57
|
+
|
|
58
|
+
## Observability log path
|
|
59
|
+
|
|
60
|
+
Use the `config` view to get the log path for the current session. Its `logFile` value uses the same resolution as observability logging:
|
|
61
|
+
|
|
62
|
+
- A persisted session uses a sidecar beside its Pi session file.
|
|
63
|
+
- An in-memory session uses the application-owned log directory for the effective session working directory.
|
|
64
|
+
|
|
65
|
+
For in-memory sessions, pi-automode uses this default location:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
~/.pi/agent/extensions/pi-automode/logs/<encoded-session-cwd>/YYYY-MM-DD/<session-id>-pi-automode.jsonl
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This includes `--no-session` runs and non-persisted subagents. The path does not use the launching process working directory.
|
|
72
|
+
|
|
73
|
+
See [Observability logging](observability-logging.md) for log configuration and entry schemas.
|
|
74
|
+
|
|
75
|
+
## Diagnosis workflow
|
|
76
|
+
|
|
77
|
+
Classifier rules cannot override permission or deterministic denials.
|
|
78
|
+
|
|
79
|
+
1. Call `automode_inspect` with `status`, `config`, and `denials`.
|
|
80
|
+
2. If observability logging is enabled, use the reported log path.
|
|
81
|
+
3. Read a matching decision entry before you propose a rule change.
|
|
82
|
+
4. Identify the enforcement layer before you change a rule.
|
|
83
|
+
5. If a configuration change is necessary, explain the change.
|
|
84
|
+
6. Ask the user to run `/automode off`.
|
|
85
|
+
7. Make only the requested configuration change during that maintenance window.
|
|
86
|
+
8. Ask the user to run `/automode reload` and `/automode on`.
|
|
87
|
+
9. Use `automode_inspect` to make sure that auto mode is enabled.
|
|
88
|
+
10. Retry only an action that you know is safe.
|
|
89
|
+
|
|
90
|
+
Do not replay an unsafe action because auto mode is off. Do not print sensitive tool input or log content in a diagnosis report.
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Observability logging
|
|
2
2
|
|
|
3
|
-
Auto mode can write a JSONL observability log
|
|
3
|
+
Auto mode can write a JSONL observability log for decisions and classifier usage. Persisted sessions use a sidecar next to the Pi session file. In-memory sessions use a global application directory.
|
|
4
|
+
|
|
5
|
+
Logging is off by default. Logging fails open, so a write error never changes an allow or block decision.
|
|
4
6
|
|
|
5
7
|
## Enabling
|
|
6
8
|
|
|
7
|
-
Set `autoMode.log` in
|
|
9
|
+
Set `autoMode.log` in a Pi-owned configuration source. These sources include `~/.pi/agent/automode.json`, trusted `.pi/automode.local.json`, and `PI_AUTOMODE_SETTINGS_JSON`.
|
|
8
10
|
|
|
9
11
|
```json
|
|
10
12
|
{
|
|
@@ -18,44 +20,62 @@ Set `autoMode.log` in any Pi-owned config source (`~/.pi/agent/automode.json`, `
|
|
|
18
20
|
```
|
|
19
21
|
|
|
20
22
|
- `enabled` — write one `decision` line per tool-call decision and one ccusage-compatible `message` line per classifier model response.
|
|
21
|
-
- `classifierIo` — also write the classifier
|
|
23
|
+
- `classifierIo` — also write the classifier prompt, raw responses, and parsed decision for classifier-routed actions. The default is `false`. See [Privacy](#privacy).
|
|
24
|
+
|
|
25
|
+
Fields merge independently across configuration sources. For example, set `enabled` globally and set `classifierIo` for a trusted project.
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
Shared project `.pi/automode.json` cannot set `log`. The shared file cannot set any `autoMode` field. `/automode config` reports an invalid shape.
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
Pi-automode writes log entries only while auto mode is **enabled**. With auto mode off, no tool calls reach the hook. Thus, pi-automode writes no entries.
|
|
26
30
|
|
|
27
31
|
## Log file location
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
Pi-automode stores the log next to the current Pi session file. It inserts `-pi-automode` before the extension:
|
|
30
34
|
|
|
31
35
|
```text
|
|
32
36
|
<session-file> → <dir>/<id>.jsonl
|
|
33
37
|
<session-file>-pi-automode.jsonl → <dir>/<id>-pi-automode.jsonl
|
|
34
38
|
```
|
|
35
39
|
|
|
36
|
-
For example
|
|
40
|
+
For example, pi-automode can use `~/.pi/agent/sessions/<slug>/<id>-pi-automode.jsonl`.
|
|
41
|
+
|
|
42
|
+
If a custom session manager provides an absolute session directory without a session file, pi-automode uses `<sessionDir>/<sessionId>-pi-automode.jsonl`.
|
|
43
|
+
|
|
44
|
+
Pi in-memory sessions have no session file or session directory. These sessions include `--no-session` and non-persisted subagents. Their logs use this absolute application path:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
~/.pi/agent/extensions/pi-automode/logs/<encoded-session-cwd>/YYYY-MM-DD/<session-id>-pi-automode.jsonl
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The project directory uses the same `--path-with-dashes--` encoding as normal Pi session directories. The date partition uses UTC.
|
|
51
|
+
|
|
52
|
+
A custom session manager can supply an absolute `sessionDir` without a session file. In this case, pi-automode continues to use that directory. Run `/automode config` to see the resolved path.
|
|
37
53
|
|
|
38
|
-
|
|
54
|
+
Persisted sessions use one combined file per session. In-memory sessions use one file for each session ID and UTC day.
|
|
55
|
+
|
|
56
|
+
If a session crosses midnight, pi-automode continues in the file for the next day. Each line contains one JSON object with a `type` discriminator. Entries for the same tool call share a `decisionId`.
|
|
57
|
+
|
|
58
|
+
For persisted sessions, `ccusage pi` reports the sidecar as a separate `-pi-automode` session. Inspect in-memory logs directly because they are outside the normal Pi session tree.
|
|
39
59
|
|
|
40
60
|
## Entry types
|
|
41
61
|
|
|
42
62
|
### `decision`
|
|
43
63
|
|
|
44
|
-
|
|
64
|
+
Pi-automode writes one `decision` entry for each tool-call decision. Each allowed or blocked call has exactly one entry.
|
|
45
65
|
|
|
46
66
|
| field | meaning |
|
|
47
67
|
| --- | --- |
|
|
48
68
|
| `ts` | ISO timestamp |
|
|
49
|
-
| `decisionId` | links to the `classifier` entry
|
|
69
|
+
| `decisionId` | links to the related `classifier` entry. Local decisions have no related entry. |
|
|
50
70
|
| `sessionId` | Pi session id |
|
|
51
71
|
| `cwd` | working directory |
|
|
52
|
-
| `tool` | tool name,
|
|
72
|
+
| `tool` | tool name, for example `bash` or `write` |
|
|
53
73
|
| `summary` | `actionSummary` — tool name + input JSON (truncated) |
|
|
54
|
-
| `kind` | enforcement path: `permissions.deny`, `permissions.ask`, `deterministic-hard-deny`, `
|
|
74
|
+
| `kind` | enforcement path: `permissions.deny`, `permissions.ask`, `deterministic-hard-deny`, `deterministic-path-deny`, `permissions.allow`, `inside-working-directory`, `classifier`, `read-only`, or `setup` |
|
|
55
75
|
| `outcome` | `allow` or `block` |
|
|
56
76
|
| `reason` | the reason string (classifier reason, or the deterministic/permission reason) |
|
|
57
|
-
| `classifierModel` | the configured classifier model
|
|
58
|
-
| `reasoning` | classifier reasoning mode and requested
|
|
77
|
+
| `classifierModel` | the configured classifier model for a classifier-routed decision |
|
|
78
|
+
| `reasoning` | classifier reasoning mode and requested or effective level. See the examples below. |
|
|
59
79
|
|
|
60
80
|
The reasoning field records either server-default mode:
|
|
61
81
|
|
|
@@ -69,11 +89,17 @@ or an explicit request after model-level clamping:
|
|
|
69
89
|
{"mode":"explicit","requestedLevel":"max","effectiveLevel":"xhigh"}
|
|
70
90
|
```
|
|
71
91
|
|
|
72
|
-
Classifier-routed decisions contain the effective level
|
|
92
|
+
Classifier-routed decisions contain the effective level after model resolution. If `classifierIo` is off or authentication fails later, this field still exists.
|
|
93
|
+
|
|
94
|
+
If pi-automode cannot resolve the model, the entry contains `requestedLevel` without `effectiveLevel`. In this case, no model-supported level exists.
|
|
95
|
+
|
|
96
|
+
Local permission, deterministic, `permissions.allow`, and read-only decisions do not run the classifier. These decisions can omit `effectiveLevel`. Pi-automode cannot observe or infer the server-selected level in `server-default` mode.
|
|
73
97
|
|
|
74
98
|
### `message` (classifier usage)
|
|
75
99
|
|
|
76
|
-
|
|
100
|
+
Pi-automode writes one `message` entry for each classifier response. This includes a malformed response that causes a retry.
|
|
101
|
+
|
|
102
|
+
When logging is enabled, pi-automode writes this entry before the matching `decision` line. The entry shape is compatible with `ccusage pi`:
|
|
77
103
|
|
|
78
104
|
| field | meaning |
|
|
79
105
|
| --- | --- |
|
|
@@ -82,20 +108,23 @@ One per classifier model response, including malformed responses that trigger a
|
|
|
82
108
|
| `message.model` | model ID returned by the classifier provider |
|
|
83
109
|
| `message.usage` | provider-reported input, output, cache, total-token, and cost fields |
|
|
84
110
|
|
|
85
|
-
`ccusage` reports this sidecar as a separate `-pi-automode` session. This entry contains no prompt or response text
|
|
111
|
+
For persisted sessions, `ccusage` reports this sidecar as a separate `-pi-automode` session. This entry contains no prompt or response text. When `classifierIo` is off, pi-automode still writes it.
|
|
86
112
|
|
|
87
113
|
### `classifier`
|
|
88
114
|
|
|
89
|
-
|
|
115
|
+
If `classifierIo: true`, pi-automode writes a `classifier` entry. It writes this entry only for classifier-routed actions.
|
|
116
|
+
|
|
117
|
+
The entry follows all related classifier-usage `message` entries. It precedes the matching `decision` entry.
|
|
90
118
|
|
|
91
119
|
| field | meaning |
|
|
92
120
|
| --- | --- |
|
|
93
121
|
| `ts` | ISO timestamp |
|
|
94
122
|
| `decisionId` | matches the `decision` entry for the same call |
|
|
95
|
-
| `model` | classifier model
|
|
123
|
+
| `model` | classifier model, for example `anthropic/claude-haiku-4` |
|
|
96
124
|
| `reasoning` | `server-default`, or the explicit requested and effective model-supported level |
|
|
97
125
|
| `prompt.system` | the full system policy with `environment`/`allow`/`soft_deny`/`hard_deny` rules interpolated |
|
|
98
|
-
| `prompt.context` | the shared context message: loaded project instructions + classifier transcript
|
|
126
|
+
| `prompt.context` | the shared context message: loaded project instructions + classifier transcript |
|
|
127
|
+
| `prompt.action` | the complete, untruncated current tool action JSON |
|
|
99
128
|
| `prompt.fastInstruction` | the exact one-token filter instruction |
|
|
100
129
|
| `prompt.detailedInstruction` | the exact structured-review instruction |
|
|
101
130
|
| `attempts` | one entry per classifier model call (see below) |
|
|
@@ -106,20 +135,26 @@ Each `attempts[]` entry is `{ stage, attempt, response?, parsed?, error?, durati
|
|
|
106
135
|
|
|
107
136
|
- `stage` — `fast` for the one-token filter or `detailed` for structured review.
|
|
108
137
|
- `response` — `{ stopReason, text, model, timestamp, usage, errorMessage? }`, the raw model output and provider-reported usage for that call, including provider-reported errors and aborted requests.
|
|
109
|
-
- `parsed` — the decision parsed from the response, or absent
|
|
110
|
-
- `error` — present
|
|
138
|
+
- `parsed` — the decision parsed from the response, or absent after a parse failure.
|
|
139
|
+
- `error` — present after a network or authentication error. In this case, `response` is absent.
|
|
111
140
|
|
|
112
|
-
|
|
141
|
+
The array records both stages, retries, and fail-closed cases. A fast allow has one entry. A review with one successful retry has three entries.
|
|
113
142
|
|
|
114
143
|
## Privacy
|
|
115
144
|
|
|
116
|
-
`prompt.context`
|
|
145
|
+
`prompt.context` contains project instructions and transcript evidence for both classifier stages. `prompt.action` contains the separate, untruncated current action. Pi-automode logs the final stage instructions separately.
|
|
146
|
+
|
|
147
|
+
See [Auto-mode classifier flow → What is sent to the classifier](automode-classifier-flow.md#what-is-sent-to-the-classifier) for the evidence assembly rules.
|
|
117
148
|
|
|
118
|
-
The log records this payload locally
|
|
149
|
+
The log records this payload locally. Pi-automode also sends the same data to the classifier endpoint for each classifier-routed call.
|
|
150
|
+
|
|
151
|
+
If `classifierModel` uses a cloud provider, the payload leaves the machine. Enable `classifierIo` only for classifier diagnosis or rule tuning. Leave it off for routine outcome logging.
|
|
119
152
|
|
|
120
153
|
## Sizing
|
|
121
154
|
|
|
122
155
|
- `decision` line: ~0.4–2 KB (driven by `summary`, which carries the tool input, capped at 6 KB).
|
|
123
156
|
- `classifier` line: ~5 KB fixed policy plus loaded project instructions, selected transcript evidence, stage instructions, and recorded responses.
|
|
124
157
|
|
|
125
|
-
|
|
158
|
+
`autoMode.maxUserTranscriptTokens` and `autoMode.maxToolTranscriptTokens` limit transcript evidence separately. Both fields default to approximately 4000 tokens.
|
|
159
|
+
|
|
160
|
+
Pi-automode excludes assistant prose and tool results. Provider cache hits can reduce processed or billed input. The log still records the full classifier payload.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"autoMode": {
|
|
3
3
|
"classifierReasoningLevel": "low",
|
|
4
|
+
"classifierTimeoutMs": 20000,
|
|
4
5
|
"allowInsideWorkingDirectory": false,
|
|
5
6
|
"deniedPaths": [
|
|
6
7
|
"*.env",
|
|
@@ -27,6 +28,10 @@
|
|
|
27
28
|
]
|
|
28
29
|
},
|
|
29
30
|
"permissions": {
|
|
31
|
+
"allow": [
|
|
32
|
+
"bash(git status*)",
|
|
33
|
+
"example-extension-tool"
|
|
34
|
+
],
|
|
30
35
|
"ask": [
|
|
31
36
|
"bash(git push *)"
|
|
32
37
|
],
|