@herbertgao/pi-extensions 2026.9.5 → 2026.9.6
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 +3 -15
- package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +1 -1
- package/node_modules/@herbertgao/sol-pi/package.json +1 -1
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +0 -5
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +3 -1
- package/package.json +2 -7
- package/examples/pi-footer.json +0 -275
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +0 -70
- package/node_modules/@czottmann/pi-automode/LICENSE.md +0 -21
- package/node_modules/@czottmann/pi-automode/README.md +0 -215
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +0 -39
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +0 -46
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-002-global-config-in-extension-data-directory.md +0 -60
- package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +0 -6
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +0 -428
- package/node_modules/@czottmann/pi-automode/docs/configuration.md +0 -171
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +0 -178
- package/node_modules/@czottmann/pi-automode/docs/diagnostics.md +0 -90
- package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +0 -160
- package/node_modules/@czottmann/pi-automode/examples/automode.local.json +0 -44
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/bash.ts +0 -692
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +0 -852
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +0 -904
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +0 -228
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +0 -954
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +0 -429
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/log.ts +0 -173
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/model-selector.ts +0 -113
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/model.ts +0 -13
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +0 -297
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +0 -623
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/state.ts +0 -102
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/transcript.ts +0 -236
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +0 -205
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/utils.ts +0 -54
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode.ts +0 -26
- package/node_modules/@czottmann/pi-automode/package.json +0 -61
- package/node_modules/@czottmann/pi-automode/skills/automode-diagnostics/SKILL.md +0 -63
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
# Defaults and rule-list behavior
|
|
2
|
-
|
|
3
|
-
## `$defaults`
|
|
4
|
-
|
|
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
|
-
|
|
7
|
-
### `environment`
|
|
8
|
-
|
|
9
|
-
`$defaults` expands to:
|
|
10
|
-
|
|
11
|
-
- trusted repo: the repository Pi started in and its configured git remotes
|
|
12
|
-
- source control: the trusted repo and its configured remotes only
|
|
13
|
-
- trusted internal domains: none configured
|
|
14
|
-
- trusted cloud buckets: none configured
|
|
15
|
-
- key internal services: none configured
|
|
16
|
-
|
|
17
|
-
If the classifier needs information about trusted company infrastructure, add entries such as these:
|
|
18
|
-
|
|
19
|
-
```json
|
|
20
|
-
{
|
|
21
|
-
"autoMode": {
|
|
22
|
-
"environment": [
|
|
23
|
-
"$defaults",
|
|
24
|
-
"Trusted internal domains: *.corp.example.com, git.example.com",
|
|
25
|
-
"Trusted cloud buckets: s3://acme-dev-artifacts, gs://acme-ci-cache",
|
|
26
|
-
"Key internal services: staging deploy API at deploy.corp.example.com"
|
|
27
|
-
]
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
These entries give the classifier context. They do not bypass `hard_deny` or automatically allow every action involving those services.
|
|
33
|
-
|
|
34
|
-
### `allow`
|
|
35
|
-
|
|
36
|
-
`$defaults` expands to allow exceptions for:
|
|
37
|
-
|
|
38
|
-
- read-only operations: inspecting files, listing directories, searching, GET requests, and state queries that do not expose secrets
|
|
39
|
-
- local development inside the working tree: creating, editing, building, testing, linting, formatting, and deleting files created during the current task
|
|
40
|
-
- modifying or deleting pre-existing local files with bounded direct user authorization
|
|
41
|
-
- installing dependencies already declared in package manifests or lockfiles
|
|
42
|
-
- using standard credentials only with their intended configured providers
|
|
43
|
-
- pushing to the current non-default working branch or a new branch created for the task
|
|
44
|
-
- bootstrapping language/toolchain installers from official sources
|
|
45
|
-
|
|
46
|
-
These are exceptions to `soft_deny`, not to `hard_deny`.
|
|
47
|
-
|
|
48
|
-
### `protectedPaths`
|
|
49
|
-
|
|
50
|
-
`$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.
|
|
51
|
-
|
|
52
|
-
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.
|
|
53
|
-
|
|
54
|
-
Protected directories: `.git`, `.config/git`, `.vscode`, `.idea`, `.husky`, `.cargo`, `.devcontainer`, `.yarn`, `.mvn`, `.pi`.
|
|
55
|
-
|
|
56
|
-
Protected files include:
|
|
57
|
-
|
|
58
|
-
- Git files: `.gitconfig`, `.gitmodules`, `.gitignore`, and `.gitattributes`
|
|
59
|
-
- Bash files: `.bashrc`, `.bash_profile`, `.bash_login`, `.bash_aliases`, and `.bash_logout`
|
|
60
|
-
- Zsh files: `.zshrc`, `.zprofile`, `.zshenv`, `.zlogin`, and `.zlogout`
|
|
61
|
-
- other shell files: `.profile` and `.envrc`
|
|
62
|
-
- package-manager files: `.npmrc`, `.yarnrc`, `.yarnrc.yml`, `.pnp.cjs`, `.pnp.loader.mjs`, and `.pnpmfile.cjs`
|
|
63
|
-
- Bun files: `bunfig.toml` and `.bunfig.toml`
|
|
64
|
-
- Bazel files: `.bazelrc`, `.bazelversion`, and `.bazeliskrc`
|
|
65
|
-
- hook files: `.pre-commit-config.yaml`, `lefthook.yml`, `lefthook.yaml`, `.lefthook.yml`, and `.lefthook.yaml`
|
|
66
|
-
- wrapper files: `gradle-wrapper.properties` and `maven-wrapper.properties`
|
|
67
|
-
- other control files: `.devcontainer.json`, `.ripgreprc`, `pyrightconfig.json`, and `.mcp.json`
|
|
68
|
-
|
|
69
|
-
Read-only tools remain locally allowed after permission and deterministic checks. These tools are `read`, `grep`, `find`, and `ls`.
|
|
70
|
-
|
|
71
|
-
In the default configuration, all writes and edits require classification. The value `allowInsideWorkingDirectory: true` allows non-protected in-tree access locally.
|
|
72
|
-
|
|
73
|
-
Protected in-tree writes and edits still require classification. All out-of-tree file access also requires classification.
|
|
74
|
-
|
|
75
|
-
### `deniedPaths`
|
|
76
|
-
|
|
77
|
-
`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.
|
|
78
|
-
|
|
79
|
-
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`.
|
|
80
|
-
|
|
81
|
-
Use this list for secrets and system paths that file tools must not send to the model. The classifier continues to govern `bash` access.
|
|
82
|
-
|
|
83
|
-
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.
|
|
84
|
-
|
|
85
|
-
### `soft_deny`
|
|
86
|
-
|
|
87
|
-
`$defaults` expands to soft blocks for:
|
|
88
|
-
|
|
89
|
-
- force push, remote branch deletion, remote history rewrite, or direct push to `main`, `master`, or the default branch
|
|
90
|
-
- downloading and executing external code, including `curl | bash` and `wget | sh`
|
|
91
|
-
- production deploys, production database migrations, or production infrastructure changes
|
|
92
|
-
- deleting, truncating, or overwriting local files that existed before session start without a bounded user authorization
|
|
93
|
-
- mass modification/deletion in cloud storage, ticketing systems, collaboration tools, or external APIs
|
|
94
|
-
- writing through remote shells such as `ssh`, `kubectl exec`, or `docker exec` on shared or production hosts
|
|
95
|
-
- changing shared or live infrastructure without its normal preview, plan, dry run, or review
|
|
96
|
-
- killing other users' processes, cancelling shared jobs, or disrupting shared infrastructure
|
|
97
|
-
- exposing local files, sockets, credentials, or internal services through a network service
|
|
98
|
-
- outbound messages, purchases, bookings, subscriptions, or other real-world transactions
|
|
99
|
-
|
|
100
|
-
Soft blocks can be overridden by a matching `allow` exception or direct user intent. For a pre-existing local file, direct user intent must name the task, one repository or worktree, permitted path scopes, and an allowed operation. The action must stay inside those bounds. Other soft blocks need direct user intent but do not require these file bounds. A later user instruction that narrows or revokes authorization controls.
|
|
101
|
-
|
|
102
|
-
### `hard_deny`
|
|
103
|
-
|
|
104
|
-
`$defaults` expands to unconditional blocks for:
|
|
105
|
-
|
|
106
|
-
- weakening TLS, certificate validation, authentication, authorization, audit logging, or other security controls
|
|
107
|
-
- adding persistence such as SSH keys, shell profile edits, cron jobs, launch agents, login items, or background agents
|
|
108
|
-
- granting admin, owner, IAM, RBAC, repository, or production access
|
|
109
|
-
- exfiltrating repository contents, secrets, credentials, private keys, tokens, or internal data to untrusted places
|
|
110
|
-
- scanning for credentials, tokens, private keys, or secrets beyond what the task requires
|
|
111
|
-
- tampering with logs, audit trails, security monitoring, permission rules, auto-mode configuration, or safety-control files
|
|
112
|
-
- creating services, endpoints, workflows, or autonomous agents that execute arbitrary code without meaningful approval
|
|
113
|
-
- posting or updating public/external content that is fabricated, misleading, impersonating a user, or claiming approval/action that did not happen
|
|
114
|
-
|
|
115
|
-
Hard-deny rules cannot be overridden by `allow` or by user intent.
|
|
116
|
-
|
|
117
|
-
### Classifier transcript budgets
|
|
118
|
-
|
|
119
|
-
Classifier evidence has separate approximate-token budgets for user messages and assistant tool-call payloads:
|
|
120
|
-
|
|
121
|
-
- `maxUserTranscriptTokens`: 4000
|
|
122
|
-
- `maxToolTranscriptTokens`: 4000
|
|
123
|
-
|
|
124
|
-
The selector keeps the first and latest user messages as intent anchors. It fills the remaining space from the newest eligible entries.
|
|
125
|
-
|
|
126
|
-
The selector limits individual entries. It marks omitted or truncated evidence in the classifier transcript. It excludes assistant prose and tool results.
|
|
127
|
-
|
|
128
|
-
These limits use approximate character counts. They do not guarantee the same result as a provider tokenizer.
|
|
129
|
-
|
|
130
|
-
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.
|
|
131
|
-
|
|
132
|
-
### Classifier request timeout
|
|
133
|
-
|
|
134
|
-
`classifierTimeoutMs` limits each classifier request in milliseconds. The fast and detailed stages have separate budgets. The default is 20000.
|
|
135
|
-
|
|
136
|
-
If a request exceeds its budget, pi-automode aborts the attempt. Then auto mode fails closed and blocks the action.
|
|
137
|
-
|
|
138
|
-
To change the timeout, set an integer of at least 1000 in a Pi-owned `autoMode` configuration source.
|
|
139
|
-
|
|
140
|
-
### Replacement behavior
|
|
141
|
-
|
|
142
|
-
If you want to keep the built-ins and add entries, use `$defaults`:
|
|
143
|
-
|
|
144
|
-
```json
|
|
145
|
-
{
|
|
146
|
-
"autoMode": {
|
|
147
|
-
"allow": [
|
|
148
|
-
"$defaults",
|
|
149
|
-
"Running the staging deploy script is allowed."
|
|
150
|
-
]
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
This configuration uses all built-in `allow` entries and the staging rule.
|
|
156
|
-
|
|
157
|
-
If you omit `$defaults`, you replace the built-ins for that section:
|
|
158
|
-
|
|
159
|
-
```json
|
|
160
|
-
{
|
|
161
|
-
"autoMode": {
|
|
162
|
-
"allow": [
|
|
163
|
-
"Running the staging deploy script is allowed."
|
|
164
|
-
]
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
This configuration uses only the staging rule. It does not use the built-in `allow` entries.
|
|
170
|
-
|
|
171
|
-
Replacing `allow` does not replace `soft_deny`, `hard_deny`, `protectedPaths`, or `environment`.
|
|
172
|
-
|
|
173
|
-
`permissions.deny`, `permissions.ask`, and `permissions.allow` do not support `$defaults`. These lists contain only explicit Pi tool patterns. All three lists default to `[]`.
|
|
174
|
-
|
|
175
|
-
Global, project-local, and inline configuration can add all three permission lists. Shared project configuration can add only deny and ask rules.
|
|
176
|
-
|
|
177
|
-
`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.
|
|
178
|
-
|
|
@@ -1,90 +0,0 @@
|
|
|
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,160 +0,0 @@
|
|
|
1
|
-
# Observability logging
|
|
2
|
-
|
|
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.
|
|
6
|
-
|
|
7
|
-
## Enabling
|
|
8
|
-
|
|
9
|
-
Set `autoMode.log` in a Pi-owned configuration source. These sources include `~/.pi/agent/extensions/pi-automode/config.json`, trusted `.pi/automode.local.json`, and `PI_AUTOMODE_SETTINGS_JSON`.
|
|
10
|
-
|
|
11
|
-
```json
|
|
12
|
-
{
|
|
13
|
-
"autoMode": {
|
|
14
|
-
"log": {
|
|
15
|
-
"enabled": true,
|
|
16
|
-
"classifierIo": false
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
- `enabled` — write one `decision` line per tool-call decision and one ccusage-compatible `message` line per classifier model response.
|
|
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.
|
|
26
|
-
|
|
27
|
-
Shared project `.pi/automode.json` cannot set `log`. The shared file cannot set any `autoMode` field. `/automode config` reports an invalid shape.
|
|
28
|
-
|
|
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.
|
|
30
|
-
|
|
31
|
-
## Log file location
|
|
32
|
-
|
|
33
|
-
Pi-automode stores the log next to the current Pi session file. It inserts `-pi-automode` before the extension:
|
|
34
|
-
|
|
35
|
-
```text
|
|
36
|
-
<session-file> → <dir>/<id>.jsonl
|
|
37
|
-
<session-file>-pi-automode.jsonl → <dir>/<id>-pi-automode.jsonl
|
|
38
|
-
```
|
|
39
|
-
|
|
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.
|
|
53
|
-
|
|
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.
|
|
59
|
-
|
|
60
|
-
## Entry types
|
|
61
|
-
|
|
62
|
-
### `decision`
|
|
63
|
-
|
|
64
|
-
Pi-automode writes one `decision` entry for each tool-call decision. Each allowed or blocked call has exactly one entry.
|
|
65
|
-
|
|
66
|
-
| field | meaning |
|
|
67
|
-
| --- | --- |
|
|
68
|
-
| `ts` | ISO timestamp |
|
|
69
|
-
| `decisionId` | links to the related `classifier` entry. Local decisions have no related entry. |
|
|
70
|
-
| `sessionId` | Pi session id |
|
|
71
|
-
| `cwd` | working directory |
|
|
72
|
-
| `tool` | tool name, for example `bash` or `write` |
|
|
73
|
-
| `summary` | `actionSummary` — tool name + input JSON (truncated) |
|
|
74
|
-
| `kind` | enforcement path: `permissions.deny`, `permissions.ask`, `deterministic-hard-deny`, `deterministic-path-deny`, `permissions.allow`, `inside-working-directory`, `classifier`, `read-only`, or `setup` |
|
|
75
|
-
| `outcome` | `allow` or `block` |
|
|
76
|
-
| `reason` | the reason string (classifier reason, or the deterministic/permission reason) |
|
|
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. |
|
|
79
|
-
|
|
80
|
-
The reasoning field records either server-default mode:
|
|
81
|
-
|
|
82
|
-
```json
|
|
83
|
-
{"mode":"server-default"}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
or an explicit request after model-level clamping:
|
|
87
|
-
|
|
88
|
-
```json
|
|
89
|
-
{"mode":"explicit","requestedLevel":"max","effectiveLevel":"xhigh"}
|
|
90
|
-
```
|
|
91
|
-
|
|
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.
|
|
97
|
-
|
|
98
|
-
### `message` (classifier usage)
|
|
99
|
-
|
|
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`:
|
|
103
|
-
|
|
104
|
-
| field | meaning |
|
|
105
|
-
| --- | --- |
|
|
106
|
-
| `timestamp` | ISO timestamp from the classifier response |
|
|
107
|
-
| `message.role` | always `assistant` |
|
|
108
|
-
| `message.model` | model ID returned by the classifier provider |
|
|
109
|
-
| `message.usage` | provider-reported input, output, cache, total-token, and cost fields |
|
|
110
|
-
|
|
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.
|
|
112
|
-
|
|
113
|
-
### `classifier`
|
|
114
|
-
|
|
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.
|
|
118
|
-
|
|
119
|
-
| field | meaning |
|
|
120
|
-
| --- | --- |
|
|
121
|
-
| `ts` | ISO timestamp |
|
|
122
|
-
| `decisionId` | matches the `decision` entry for the same call |
|
|
123
|
-
| `model` | classifier model, for example `anthropic/claude-haiku-4` |
|
|
124
|
-
| `reasoning` | `server-default`, or the explicit requested and effective model-supported level |
|
|
125
|
-
| `prompt.system` | the full system policy with `environment`/`allow`/`soft_deny`/`hard_deny` rules interpolated |
|
|
126
|
-
| `prompt.context` | the shared context message: loaded project instructions + classifier transcript |
|
|
127
|
-
| `prompt.action` | the complete, untruncated current tool action JSON |
|
|
128
|
-
| `prompt.fastInstruction` | the exact one-token filter instruction |
|
|
129
|
-
| `prompt.detailedInstruction` | the exact structured-review instruction |
|
|
130
|
-
| `attempts` | one entry per classifier model call (see below) |
|
|
131
|
-
| `durationMs` | total classifier time |
|
|
132
|
-
| `parsed` | the final decision that was acted on (`{ decision, tier, reason }`) |
|
|
133
|
-
|
|
134
|
-
Each `attempts[]` entry is `{ stage, attempt, response?, parsed?, error?, durationMs }`:
|
|
135
|
-
|
|
136
|
-
- `stage` — `fast` for the one-token filter or `detailed` for structured review.
|
|
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.
|
|
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.
|
|
140
|
-
|
|
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.
|
|
142
|
-
|
|
143
|
-
## Privacy
|
|
144
|
-
|
|
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.
|
|
148
|
-
|
|
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.
|
|
152
|
-
|
|
153
|
-
## Sizing
|
|
154
|
-
|
|
155
|
-
- `decision` line: ~0.4–2 KB (driven by `summary`, which carries the tool input, capped at 6 KB).
|
|
156
|
-
- `classifier` line: ~5 KB fixed policy plus loaded project instructions, selected transcript evidence, stage instructions, and recorded responses.
|
|
157
|
-
|
|
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,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"autoMode": {
|
|
3
|
-
"classifierReasoningLevel": "low",
|
|
4
|
-
"classifierTimeoutMs": 20000,
|
|
5
|
-
"allowInsideWorkingDirectory": false,
|
|
6
|
-
"deniedPaths": [
|
|
7
|
-
"*.env",
|
|
8
|
-
"~/.ssh/*",
|
|
9
|
-
"/etc/*"
|
|
10
|
-
],
|
|
11
|
-
"environment": [
|
|
12
|
-
"$defaults",
|
|
13
|
-
"Source control: github.example.com/acme-corp and all repos under it",
|
|
14
|
-
"Trusted internal domains: *.corp.example.com, api.internal.example.com",
|
|
15
|
-
"Trusted cloud buckets: s3://acme-build-artifacts, gs://acme-dev-scratch"
|
|
16
|
-
],
|
|
17
|
-
"allow": [
|
|
18
|
-
"$defaults",
|
|
19
|
-
"Deploying to the staging namespace is allowed when the command names staging explicitly."
|
|
20
|
-
],
|
|
21
|
-
"soft_deny": [
|
|
22
|
-
"$defaults",
|
|
23
|
-
"Never run database migrations except through the project's migrations CLI."
|
|
24
|
-
],
|
|
25
|
-
"hard_deny": [
|
|
26
|
-
"$defaults",
|
|
27
|
-
"Never send repository contents to third-party code-review APIs."
|
|
28
|
-
]
|
|
29
|
-
},
|
|
30
|
-
"permissions": {
|
|
31
|
-
"allow": [
|
|
32
|
-
"bash(git status*)",
|
|
33
|
-
"example-extension-tool"
|
|
34
|
-
],
|
|
35
|
-
"ask": [
|
|
36
|
-
"bash(git push *)"
|
|
37
|
-
],
|
|
38
|
-
"deny": [
|
|
39
|
-
"bash(git push --force*)",
|
|
40
|
-
"edit(.env*)",
|
|
41
|
-
"write(.env*)"
|
|
42
|
-
]
|
|
43
|
-
}
|
|
44
|
-
}
|