@czottmann/pi-automode 1.4.0 → 1.5.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
@@ -141,6 +141,12 @@ GitHub Actions publishes the package to npm when a GitHub Release is published.
141
141
 
142
142
  The workflow uses npm Trusted Publishing, so it does not need an npm token secret. Configure this package on npm with this repository and workflow file (`.github/workflows/publish.yml`). The workflow builds the package, runs `npm run check`, and publishes with npm provenance.
143
143
 
144
+ ### Release tag must point at the version bump
145
+
146
+ The publish workflow checks out the commit the release tag points at and compares `package.json` against the tag name. **The tag must point at a commit where `package.json` already carries the new version.** Concretely: commit the version bump (`chore: release X.Y.Z`), push `main`, then create the GitHub release targeting that pushed commit. Creating the release before pushing the version bump — or targeting a commit that still has the old version — fails the `Check release tag` step with `Release tag (vX.Y.Z) does not match package.json version (x.y.z)`.
147
+
148
+ If the tag was cut against the wrong commit, fix it by force-moving it to the version-bump commit and pushing, then trigger the workflow via `gh workflow run publish.yml --ref vX.Y.Z` (the `release` event fires on tag creation; re-running a failed `release`-triggered run reuses the original ref and won't pick up the moved tag).
149
+
144
150
  ## Author
145
151
 
146
152
  Carlo Zottmann, <carlo@zottmann.dev>
@@ -69,6 +69,7 @@ export function createPiAutomode(options: PiAutomodeOptions = {}) {
69
69
  let state: AutoModeState = {
70
70
  checkedActions: 0,
71
71
  blockedActions: 0,
72
+ classifierChecks: 0,
72
73
  recentDenials: [],
73
74
  };
74
75
  let loadedContext = "";
@@ -215,6 +216,7 @@ export function createPiAutomode(options: PiAutomodeOptions = {}) {
215
216
  if (event.toolName === "write" || event.toolName === "edit") {
216
217
  const path = resolveInputPath(ctx.cwd, input.path);
217
218
  if (path && isProtectedPath(path, ctx.cwd, cfg.protectedPaths)) {
219
+ state.classifierChecks += 1;
218
220
  const decision = await classify(ctx, cfg, summary, loadedContext);
219
221
  if (decision.decision === "allow") {
220
222
  state.lastDecision = "allow";
@@ -233,6 +235,7 @@ export function createPiAutomode(options: PiAutomodeOptions = {}) {
233
235
  }
234
236
  }
235
237
 
238
+ state.classifierChecks += 1;
236
239
  const decision = await classify(ctx, cfg, summary, loadedContext);
237
240
  if (decision.decision === "allow") {
238
241
  state.lastDecision = "allow";
@@ -295,6 +298,7 @@ export function createPiAutomode(options: PiAutomodeOptions = {}) {
295
298
  state = {
296
299
  checkedActions: 0,
297
300
  blockedActions: 0,
301
+ classifierChecks: 0,
298
302
  recentDenials: [],
299
303
  enabledOverride: state.enabledOverride,
300
304
  };
@@ -15,15 +15,12 @@ export function statusLine(
15
15
  state: AutoModeState,
16
16
  ): string {
17
17
  const enabled = state.enabledOverride ?? config.enabled;
18
- if (!enabled) return "Auto-mode off";
19
- let line = `Auto-mode on • checked: ${state.checkedActions}`;
20
- if (state.blockedActions > 0) {
21
- line =
22
- `Auto-mode on · blocked: ${state.blockedActions}/${state.checkedActions}`;
23
- const last = state.recentDenials.at(-1);
24
- if (last) line += ` · last: ${truncateMiddle(last.reason, 60)}`;
25
- }
26
- return line;
18
+ const circle = enabled ? "●" : "○";
19
+ const allowed = state.checkedActions - state.blockedActions;
20
+ const classifier = state.classifierChecks > 0
21
+ ? ` c:${state.classifierChecks}`
22
+ : "";
23
+ return `AM${circle} a:${allowed} d:${state.blockedActions}${classifier}`;
27
24
  }
28
25
 
29
26
  export function statusText(
@@ -35,6 +32,7 @@ export function statusText(
35
32
  `classifier: ${config.classifierModel ?? "current session model"}`,
36
33
  `checked actions: ${state.checkedActions}`,
37
34
  `blocked actions: ${state.blockedActions}`,
35
+ `classifier checks: ${state.classifierChecks}`,
38
36
  `permissions.deny rules: ${config.permissionDeny.length}`,
39
37
  `permissions.ask rules: ${config.permissionAsk.length}`,
40
38
  `environment entries: ${config.environment.length}`,
@@ -90,10 +88,11 @@ export function restoreState(ctx: ExtensionContext): AutoModeState {
90
88
  lastReason: entry.data.lastReason,
91
89
  checkedActions: entry.data.checkedActions ?? 0,
92
90
  blockedActions: entry.data.blockedActions ?? 0,
91
+ classifierChecks: entry.data.classifierChecks ?? 0,
93
92
  recentDenials: Array.isArray(entry.data.recentDenials)
94
93
  ? entry.data.recentDenials.slice(-DENIAL_HISTORY_LIMIT)
95
94
  : [],
96
95
  };
97
96
  }
98
- return { checkedActions: 0, blockedActions: 0, recentDenials: [] };
97
+ return { checkedActions: 0, blockedActions: 0, classifierChecks: 0, recentDenials: [] };
99
98
  }
@@ -52,6 +52,7 @@ export type AutoModeState = {
52
52
  lastReason?: string;
53
53
  checkedActions: number;
54
54
  blockedActions: number;
55
+ classifierChecks: number;
55
56
  recentDenials: DenialRecord[];
56
57
  };
57
58
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@czottmann/pi-automode",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Claude Code-style auto mode guardrail for pi.",
5
5
  "repository": {
6
6
  "url": "https://github.com/czottmann/pi-automode"