@erichll/pi-auto-review 0.21.0 → 0.22.1

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
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.22.1 - 2026-10-01
4
+
5
+ - Fix permission-policy auditing being disabled on Bun with
6
+ `No such built-in module: node:sqlite`. Bun, including Bun-compiled Pi, now
7
+ uses its built-in `bun:sqlite`; Node continues to use `node:sqlite`.
8
+ - Preserve audit statistics and request deduplication when switching between
9
+ Node and Bun by sharing the existing database schema and HMAC key.
10
+ - Finalize Bun's cached SQLite statements when closing the database so the
11
+ last WAL connection can checkpoint and release its resources.
12
+ - Add regression coverage for database migration, redaction, retention,
13
+ failure handling, concurrent Node/Bun writers, and persistent audit reports
14
+ in a real Bun-compiled Pi process.
15
+ - Update the permission-system example for current MCP tool names, including
16
+ `codemode`, `tool_search`, `mcp__atlassian__*`, and `mcp__pencil__*`.
17
+
18
+ ## 0.22.0 - 2026-09-30
19
+
20
+ - Raise the `@earendil-works/pi-ai` and `@earendil-works/pi-coding-agent` peer
21
+ floor to `^0.99.1` and the development baseline to `^0.99.1`. Validated
22
+ against Pi 0.99.1 with `tsc --noEmit` and the full test suite: the extension
23
+ adopts the 0.99 extension surface without code changes.
24
+ - Raise the `@gotgenes/pi-permission-system` peer floor to `>=36.0.0` and the
25
+ development baseline to `^36.0.0`. Versions 35.0.3 and 36.0.0 reclassify
26
+ `sed` and `awk` readers and withdraw `find`, `fd`, and `sort` read claims for
27
+ computed and quoted arguments; the broker's evidence normalization and audit
28
+ classification were validated against 36.0.0.
29
+ - Sync `examples/pi-permission-system.config.example.json` with the current tool
30
+ set: allow `web_enable`, `subagents_enable`, `contact_supervisor`, and
31
+ `bg_wait`, following the earlier skill/MCP regrouping, the `subagent` and
32
+ `source_check` allowances, the `goal_block` to `goal_blocked` correction, and
33
+ the `fetch_content` promotion from `ask` to `allow`.
34
+ - Bump the development `typescript` baseline to `^7.0.2` and migrate the test
35
+ external-ts loader from `ts.transpileModule` (removed in TypeScript 7's new JS
36
+ API) to Node's built-in `stripTypeScriptTypes`.
37
+
3
38
  ## 0.21.0 - 2026-09-25
4
39
 
5
40
  - Raise the `@gotgenes/pi-permission-system` peer floor to `>=34.0.0` and update
package/README.md CHANGED
@@ -31,11 +31,13 @@ that dependency is a hard prerequisite (see [Install and enable](#install-and-en
31
31
  > **Prerequisite:** pi-auto-review is an authorizer inside
32
32
  > `@gotgenes/pi-permission-system`. Pi does not auto-install peer packages, so
33
33
  > install the permission system separately (once per machine) before this
34
- > extension. This release line supports permission-system 34.0.0 and later:
34
+ > extension. This release line requires Pi 0.99.1 or later and supports
35
+ > permission-system 36.0.0 and later:
35
36
 
36
- Node.js 22.13.0 or newer is required. Permission auditing uses Node's built-in
37
- `node:sqlite`; it does not require a SQLite CLI, system SQLite library, or npm
38
- SQLite package.
37
+ Node-based Pi requires Node.js 22.13.0 or newer. Permission auditing uses the
38
+ host runtime's built-in SQLite: `node:sqlite` on Node and `bun:sqlite` on Bun,
39
+ including Bun-compiled Pi (verified with Bun 1.3.14). It does not require a
40
+ SQLite CLI, system SQLite library, or npm SQLite package.
39
41
 
40
42
  ```bash
41
43
  pi install npm:@gotgenes/pi-permission-system
@@ -373,7 +375,9 @@ project-specific labels; inspect suggestions before copying them.
373
375
 
374
376
  Data lives at
375
377
  `~/.pi/agent/extensions/pi-auto-review/policy-audit.sqlite`, beside an
376
- owner-only HMAC key. The directory is mode `0700`; the key, database, WAL, and
378
+ owner-only HMAC key. Node and Bun use the same database schema and key, so
379
+ switching runtimes preserves statistics and request deduplication.
380
+ The directory is mode `0700`; the key, database, WAL, and
377
381
  SHM are mode `0600`. Initialization, lock, write, or corruption failures disable
378
382
  auditing and warn once without changing any permission result. A corrupt
379
383
  database is not deleted or rebuilt automatically. Disable new collection with:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erichll/pi-auto-review",
3
- "version": "0.21.0",
3
+ "version": "0.22.1",
4
4
  "description": "Fail-closed, model-backed approval broker for Pi: deterministically hard-denies dangerous operations, reviews dangerous boundaries with a reviewer model, and issues one-shot expiring grants that OS sandbox adapters must consume before retrying.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -47,16 +47,16 @@
47
47
  "test": "node --disable-warning=ExperimentalWarning --experimental-transform-types --import ./test/register-external-ts.mjs --test test/*.test.ts"
48
48
  },
49
49
  "peerDependencies": {
50
- "@earendil-works/pi-ai": "^0.87.1",
51
- "@earendil-works/pi-coding-agent": "^0.87.1",
52
- "@gotgenes/pi-permission-system": ">=34.0.0"
50
+ "@earendil-works/pi-ai": "^0.99.1",
51
+ "@earendil-works/pi-coding-agent": "^0.99.1",
52
+ "@gotgenes/pi-permission-system": ">=36.0.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@earendil-works/pi-ai": "^0.87.1",
56
- "@earendil-works/pi-coding-agent": "^0.87.1",
57
- "@earendil-works/pi-server": "^0.87.1",
58
- "@gotgenes/pi-permission-system": "^34.0.0",
55
+ "@earendil-works/pi-ai": "^0.99.1",
56
+ "@earendil-works/pi-coding-agent": "^0.99.1",
57
+ "@earendil-works/pi-server": "^0.99.1",
58
+ "@gotgenes/pi-permission-system": "^36.0.0",
59
59
  "@types/node": "^26.6.2",
60
- "typescript": "^6.0.3"
60
+ "typescript": "^7.0.2"
61
61
  }
62
62
  }
@@ -0,0 +1,55 @@
1
+ type Statement = {
2
+ run(...params: unknown[]): { changes: number | bigint };
3
+ // Node returns undefined for a missing row; Bun returns null.
4
+ get(...params: unknown[]): Record<string, unknown> | null | undefined;
5
+ all(...params: unknown[]): Record<string, unknown>[];
6
+ };
7
+
8
+ export type SqliteDatabase = {
9
+ exec(sql: string): void;
10
+ prepare(sql: string): Statement;
11
+ close(): void;
12
+ };
13
+
14
+ export type SqliteModule = {
15
+ DatabaseSync: new (path: string, options?: Record<string, unknown>) => SqliteDatabase;
16
+ };
17
+
18
+ type BunDatabase = Omit<SqliteDatabase, "prepare"> & {
19
+ query(sql: string): Statement;
20
+ };
21
+
22
+ /** Load the host's built-in SQLite lazily, including inside Bun-compiled Pi. */
23
+ export async function loadSqlite(): Promise<SqliteModule> {
24
+ if (process.versions.bun) {
25
+ // A runtime specifier avoids requiring Bun's ambient types in Node builds.
26
+ const specifier = "bun:sqlite";
27
+ const sqlite = await import(specifier) as {
28
+ Database: new (path: string, options?: Record<string, unknown>) => BunDatabase;
29
+ };
30
+ return {
31
+ DatabaseSync: class implements SqliteDatabase {
32
+ private readonly database: BunDatabase;
33
+
34
+ constructor(path: string, options?: Record<string, unknown>) {
35
+ this.database = new sqlite.Database(path, options);
36
+ }
37
+
38
+ exec(sql: string): void {
39
+ this.database.exec(sql);
40
+ }
41
+
42
+ prepare(sql: string): Statement {
43
+ // Bun finalizes cached queries on close. Uncached prepare() statements
44
+ // can outlive the connection, retaining locks and delaying checkpoints.
45
+ return this.database.query(sql);
46
+ }
47
+
48
+ close(): void {
49
+ this.database.close();
50
+ }
51
+ },
52
+ };
53
+ }
54
+ return import("node:sqlite") as Promise<SqliteModule>;
55
+ }
@@ -11,24 +11,12 @@ import {
11
11
  } from "node:fs";
12
12
  import { dirname, join, resolve } from "node:path";
13
13
  import type { ClassifiedPermission } from "./classifier.ts";
14
+ import { loadSqlite, type SqliteDatabase, type SqliteModule } from "./sqlite.ts";
14
15
 
15
16
  export const POLICY_AUDIT_SCHEMA_VERSION = 2;
16
17
  export const POLICY_AUDIT_DATABASE_NAME = "policy-audit.sqlite";
17
18
  export const POLICY_AUDIT_KEY_NAME = "policy-audit.key";
18
19
 
19
- type RunResult = { changes: number | bigint };
20
- type Statement = {
21
- run(...params: unknown[]): RunResult;
22
- get(...params: unknown[]): Record<string, unknown> | undefined;
23
- all(...params: unknown[]): Record<string, unknown>[];
24
- };
25
- type Database = {
26
- exec(sql: string): void;
27
- prepare(sql: string): Statement;
28
- close(): void;
29
- };
30
- type SqliteModule = { DatabaseSync: new (path: string, options?: Record<string, unknown>) => Database };
31
-
32
20
  export type SanitizedPermissionDecision = ClassifiedPermission & {
33
21
  requestId: string;
34
22
  result: "allow" | "deny";
@@ -124,7 +112,7 @@ export class PolicyAuditStore {
124
112
  mkdirSync(options.directory, { recursive: true, mode: 0o700 });
125
113
  chmodSync(options.directory, 0o700);
126
114
  const key = loadOrCreateKey(options.directory);
127
- const sqlite = await (options.sqliteLoader ?? (() => import("node:sqlite") as Promise<SqliteModule>))();
115
+ const sqlite = await (options.sqliteLoader ?? loadSqlite)();
128
116
  const databasePath = join(options.directory, POLICY_AUDIT_DATABASE_NAME);
129
117
  const db = new sqlite.DatabaseSync(databasePath);
130
118
  chmodSync(databasePath, 0o600);
@@ -139,7 +127,7 @@ export class PolicyAuditStore {
139
127
  }
140
128
 
141
129
  private constructor(
142
- private readonly db: Database,
130
+ private readonly db: SqliteDatabase,
143
131
  private readonly key: Buffer,
144
132
  private readonly databasePath: string,
145
133
  private readonly retentionDays: number,