@erichll/pi-sandbox 0.18.2 → 0.19.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,44 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.1 - 2026-09-20
4
+
5
+ - Pin the development `pi-subagents` baseline to `^0.70.0`. The runtime peer
6
+ stays `>=0.66.0`.
7
+ - Accept the compiled module layout introduced in 0.70.0: the npm package now
8
+ ships `src/**/*.js` plus `.d.ts` and publishes `./capability-ceiling` as a
9
+ `{ types, default }` condition map instead of the 0.69.0 bare
10
+ `./src/api/capability-ceiling.ts` string. The loader derives the module
11
+ extension and internal module paths from that export, so the source
12
+ (0.66.0-0.69.0) and compiled (0.70.0+) layouts share one validated code path;
13
+ unknown export targets still fail closed.
14
+ - Revalidated protected native mode against published pi-subagents 0.70.0:
15
+ `SUBAGENT_CAPABILITY_CEILING_VERSION` 1, `registerSubagentCapabilityCeiling`,
16
+ discovery/canonical resolution, and the config loader with `scheduledRuns`
17
+ are unchanged. The package test suite passes (89 pass, 1 skipped) and the
18
+ deterministic `gate:pi-subagents` preflight passes with
19
+ `piSubagentsModuleExtension: ".js"`. The model-backed gate phase was skipped
20
+ locally because no model credential was exported.
21
+ - Record in `docs/compat-notes.md` that 0.70.0 makes the root
22
+ `PI_SUBAGENT_PARENT_SESSION` marker self-deleting while detached runners keep
23
+ receiving it from their exact launch. Protected mode requires `async: true`
24
+ children, so forwarded-permission routing is unaffected; the gate's
25
+ parent-forwarding adapter is now a no-op shim for 0.69.0 and earlier.
26
+
27
+ ## 0.19.0 - 2026-09-20
28
+
29
+ - Require Pi `^0.86.0` for both the development and peer dependency of
30
+ `@earendil-works/pi-coding-agent`, and depend on `@erichll/pi-auto-review`
31
+ `^0.19.0` so the pair shares the same Pi floor. The `pi-subagents` runtime
32
+ peer stays `>=0.66.0`.
33
+ - Revalidated against Pi 0.86.0: the package test suite passes (88 pass, 1
34
+ skipped), the deterministic `gate:pi-subagents` preflight passes, and the
35
+ model-backed gate passes both phases (native baseline host-readable,
36
+ protected sandboxed Bash blocked from the host read) with native
37
+ acknowledgement `@erichll:pi-sandbox`.
38
+ - Recorded the Pi 0.86.0 floor in `README.md`, `docs/compat-notes.md`, and the
39
+ `pi-subagents-native.ts` compatibility notes: protected mode with
40
+ pi-subagents 0.68.0+ needs Pi 0.86.0 or newer.
41
+
3
42
  ## 0.18.2 - 2026-09-20
4
43
 
5
44
  - Pin the development `pi-subagents` baseline to `^0.69.0` and Pi to
package/README.md CHANGED
@@ -97,9 +97,9 @@ Supported modes:
97
97
  ### `pi-subagents` native-background tool boundary
98
98
 
99
99
  This provider supports the `pi-subagents >=0.66.0` line (validated through
100
- 0.69.0) and fails closed if its public ceiling API or internal discovery layout
101
- drifts. The peer dependency is a floor with no upper pin; the loader's explicit
102
- export and layout checks are the real gate.
100
+ 0.70.0) and fails closed if its public ceiling API, module layout, or internal
101
+ discovery layout drifts. The peer dependency is a floor with no upper pin; the
102
+ loader's explicit export and layout checks are the real gate.
103
103
  Configure both the protection mode and a non-empty canonical whitelist:
104
104
 
105
105
  ```json
@@ -284,7 +284,7 @@ capability ceiling, and protected launch policy in an isolated temporary agent
284
284
  directory. It never reads or updates production Pi configuration. Model-backed
285
285
  acceptance requires `PI_SUBAGENTS_GATE_MODEL` and an already-exported matching
286
286
  credential; missing prerequisites are reported as `SKIP`. Protected mode with
287
- pi-subagents 0.68.0 or newer needs Pi 0.85.1 or newer.
287
+ pi-subagents 0.68.0 or newer needs Pi 0.86.0 or newer.
288
288
 
289
289
  The test suite covers real Linux Sandbox Runtime enforcement when its native
290
290
  dependencies are installed, plus deterministic broker, network approval,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erichll/pi-sandbox",
3
- "version": "0.18.2",
3
+ "version": "0.19.1",
4
4
  "description": "Linux (bubblewrap) and macOS (Seatbelt) process sandbox for Pi backed by Anthropic's @anthropic-ai/sandbox-runtime. Fail-closed static filesystem policy plus per-connection network approval from pi-auto-review; sandboxes main-agent Bash and built-in subagent process trees.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -51,11 +51,11 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@anthropic-ai/sandbox-runtime": "0.0.75",
54
- "@erichll/pi-auto-review": "^0.18.0",
54
+ "@erichll/pi-auto-review": "^0.19.0",
55
55
  "jiti": "2.7.0"
56
56
  },
57
57
  "peerDependencies": {
58
- "@earendil-works/pi-coding-agent": "^0.85.0",
58
+ "@earendil-works/pi-coding-agent": "^0.86.0",
59
59
  "pi-subagents": ">=0.66.0",
60
60
  "typebox": ">=1.0.0"
61
61
  },
@@ -65,10 +65,10 @@
65
65
  }
66
66
  },
67
67
  "devDependencies": {
68
- "@earendil-works/pi-coding-agent": "^0.85.1",
69
- "@earendil-works/pi-server": "^0.85.1",
68
+ "@earendil-works/pi-coding-agent": "^0.86.0",
69
+ "@earendil-works/pi-server": "^0.86.0",
70
70
  "@types/node": "^26.2.0",
71
- "pi-subagents": "^0.69.0",
71
+ "pi-subagents": "^0.70.0",
72
72
  "typescript": "^6.0.3"
73
73
  }
74
74
  }
@@ -7,18 +7,28 @@ import { createJiti } from "jiti";
7
7
  * Compatible pi-subagents line: 0.66.0 and above (no upper pin). Any new minor
8
8
  * is accepted, so the exports/ceiling checks below are the real compatibility
9
9
  * gate; this range only rejects old lines and guards against blind
10
- * accept-on-drift. Revalidated against 0.69.0: ceiling registry
11
- * (`SUBAGENT_CAPABILITY_CEILING_VERSION` 1), the `./capability-ceiling` export
12
- * path, discovery/canonical resolution, and the config loader with
13
- * `scheduledRuns` are unchanged since 0.66.0 (verified 2026-09-19 against the
14
- * published 0.69.0 package). Protected mode needs Pi 0.85.1 or newer with
15
- * pi-subagents 0.68.0+: 0.85.0 does not ship `@earendil-works/pi-server`, so
16
- * background children fail to launch there.
10
+ * accept-on-drift. Revalidated against 0.70.0: ceiling registry
11
+ * (`SUBAGENT_CAPABILITY_CEILING_VERSION` 1), the `./capability-ceiling` export,
12
+ * discovery/canonical resolution, and the config loader with `scheduledRuns`
13
+ * are unchanged since 0.66.0, and the published package now ships compiled
14
+ * `.js`/`.d.ts` modules instead of the TypeScript source layout (verified
15
+ * 2026-09-20 against the published 0.70.0 package). Protected mode needs Pi
16
+ * 0.86.0 or newer (the package peer floor) with pi-subagents 0.68.0+: 0.85.0
17
+ * does not ship `@earendil-works/pi-server`, so background children fail to
18
+ * launch there.
17
19
  */
18
20
  export const PI_SUBAGENTS_COMPAT_RANGE = ">=0.66.0";
19
21
  export const NATIVE_CHILD_TOOLS = ["bash", "read", "grep", "find", "ls"] as const;
20
22
  export const PI_SANDBOX_ACKNOWLEDGEMENT = "@erichll:pi-sandbox";
21
23
 
24
+ /**
25
+ * Module extension of the installed pi-subagents layout. Source checkouts (and
26
+ * the 0.66.0-0.69.0 npm line) ship `.ts` modules that need a TypeScript loader;
27
+ * the 0.70.0+ npm package ships compiled `.js` plus `.d.ts` declarations. Both
28
+ * layouts keep the same package-relative module paths.
29
+ */
30
+ export type PiSubagentsModuleExtension = ".ts" | ".js";
31
+
22
32
  type Agent = {
23
33
  name: string;
24
34
  localName?: string;
@@ -85,6 +95,50 @@ export function isCompatiblePiSubagentsVersion(version: unknown): boolean {
85
95
  return Number(match[1] ?? "") === 0 && Number(match[2] ?? "") >= 66;
86
96
  }
87
97
 
98
+ function capabilityCeilingExportTarget(value: unknown): string | undefined {
99
+ if (typeof value === "string") return value;
100
+ if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
101
+ const conditions = value as Record<string, unknown>;
102
+ for (const condition of ["default", "import", "require", "types"]) {
103
+ const candidate = conditions[condition];
104
+ if (typeof candidate === "string") return candidate;
105
+ }
106
+ return undefined;
107
+ }
108
+
109
+ /**
110
+ * Resolve the installed module extension from the `./capability-ceiling`
111
+ * export, which every supported line publishes: a bare `.ts`/`.js` path before
112
+ * 0.70.0, a `{ types, default }` condition map from 0.70.0 on. Only the known
113
+ * `./src/api/capability-ceiling.<ext>` target is accepted; anything else fails
114
+ * closed instead of guessing a layout.
115
+ */
116
+ export function resolvePiSubagentsModuleExtension(
117
+ exportsField: Record<string, unknown> | undefined,
118
+ ): PiSubagentsModuleExtension {
119
+ const target = capabilityCeilingExportTarget(exportsField?.["./capability-ceiling"]);
120
+ const match = typeof target === "string"
121
+ ? /^\.\/src\/api\/capability-ceiling(?:\.d)?\.(ts|js)$/u.exec(target)
122
+ : null;
123
+ if (!match) {
124
+ throw new Error(
125
+ "pi-subagents compatibility failure: capability-ceiling export changed",
126
+ );
127
+ }
128
+ return match[1] === "js" ? ".js" : ".ts";
129
+ }
130
+
131
+ /**
132
+ * Resolve a package-relative internal module path for the installed layout,
133
+ * for example `src/agents/agents` on the compiled 0.70.0 line.
134
+ */
135
+ export function piSubagentsInternalModulePath(
136
+ relativePath: string,
137
+ extension: PiSubagentsModuleExtension,
138
+ ): string {
139
+ return `${relativePath.replace(/\.(?:ts|js)$/u, "")}${extension}`;
140
+ }
141
+
88
142
  /** Load the public ceiling API and the discovery/config internals.
89
143
  * This intentionally fails closed on package version, export, or layout drift.
90
144
  */
@@ -101,20 +155,18 @@ export async function loadPiSubagentsNativeRuntime(
101
155
  `pi-subagents protected mode requires ${PI_SUBAGENTS_COMPAT_RANGE}; found ${String(packageJson.version)}`,
102
156
  );
103
157
  }
104
- if (packageJson.exports?.["./capability-ceiling"] !== "./src/api/capability-ceiling.ts") {
105
- throw new Error(
106
- "pi-subagents compatibility failure: capability-ceiling export changed",
107
- );
108
- }
158
+ const extension = resolvePiSubagentsModuleExtension(packageJson.exports);
109
159
 
110
160
  const jiti = createJiti(import.meta.url, {
111
161
  interopDefault: false,
112
162
  fsCache: false,
113
163
  });
164
+ const internal = (relative: string): string =>
165
+ pathToFileURL(join(root, piSubagentsInternalModulePath(relative, extension))).href;
114
166
  const [ceiling, discovery, config] = await Promise.all([
115
- jiti.import(pathToFileURL(join(root, "src/api/capability-ceiling.ts")).href) as Promise<CeilingModule>,
116
- jiti.import(pathToFileURL(join(root, "src/agents/agents.ts")).href) as Promise<DiscoveryModule>,
117
- jiti.import(pathToFileURL(join(root, "src/extension/config.ts")).href) as Promise<ConfigModule>,
167
+ jiti.import(internal("src/api/capability-ceiling")) as Promise<CeilingModule>,
168
+ jiti.import(internal("src/agents/agents")) as Promise<DiscoveryModule>,
169
+ jiti.import(internal("src/extension/config")) as Promise<ConfigModule>,
118
170
  ]).catch((error) => {
119
171
  throw new Error(
120
172
  `pi-subagents compatibility failure: ${error instanceof Error ? error.message : String(error)}`,