@erichll/pi-sandbox 0.25.0 → 0.26.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,47 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.26.1 - 2026-10-13
4
+
5
+ - Upgrade the Pi 1.2.0 development baseline (`pi-coding-agent`, `pi-ai`,
6
+ typebox `>=1.3.37`) and drop the unused
7
+ `@earendil-works/pi-server` development dependency: nothing in this package
8
+ imports it and pi-subagents 0.77.0 no longer references it, while upstream
9
+ removed the package in 1.2.0.
10
+ - Revalidate the compatibility gate against pi-subagents 0.78.0 on Pi 1.2.0.
11
+ pi-subagents 0.77.0 required chord for every host from Pi 0.85 onward,
12
+ which broke background children on Pi 1.2.0 (chord removed upstream);
13
+ 0.78.0 requires chord only when the host manifest declares it, so the
14
+ package needs no workaround. The deterministic gate and the model-backed
15
+ native baseline / protected child acceptance pass. Raise the pi-subagents
16
+ peer floor to `>=0.78.0` because 0.77.x background children fail on
17
+ Pi 1.2.0; 0.78.0 also works on Pi 1.1.0.
18
+ - Keep the pi-coding-agent peer floor at `>=1.1.0`: both 1.1.0 and 1.2.0 are
19
+ verified, so 1.1.0 users are not forced onto the newer Pi.
20
+
21
+ ## 0.26.0 - 2026-10-08
22
+
23
+ - Require `@erichll/pi-auto-review ^0.26.0` so sandbox approvals use the
24
+ coordinated Pi 1.1.0 reviewer and cancellation fixes.
25
+ - Upgrade Pi development dependencies and the coding-agent peer floor to
26
+ `^1.1.0`; move pi-subagents to development `^0.76.1` / peer `>=0.76.1` and
27
+ typebox to development `^1.3.36` / peer `>=1.3.36`. Keep pi-subagents optional
28
+ and leave the sandbox-runtime and jiti dependency declarations unchanged.
29
+ - Revalidate the deterministic 0.76.1 compatibility gate and isolated Node,
30
+ Bun, and compiled-Bun host-peer loading on Pi 1.1.0. Fix the copied-package
31
+ test for dependencies that do not export package.json, including the new
32
+ Temporal polyfill. Revalidate model-backed acceptance with the native host
33
+ read baseline and the protected child blocking that read, including the
34
+ required sandbox runtime acknowledgement.
35
+ - Reject settlement waiters for RPC runs cancelled with Pi 1.1.0
36
+ `agent_settled.aborted: true`
37
+ ([#10607](https://github.com/earendil-works/pi/issues/10607)), including
38
+ waiters registered after the event or after subsequent successful runs.
39
+ Keep the persistent child idle and available for follow-up instead of
40
+ reporting a successful result or terminating the session. Legacy events
41
+ without the field retain their existing behavior.
42
+ - Ignore buffered lifecycle events after an RPC session stops or fails so
43
+ cancellation and shutdown cannot resurrect a terminal session.
44
+
3
45
  ## 0.25.0 - 2026-10-07
4
46
 
5
47
  - Align the `@erichll/pi-auto-review` dependency with `^0.25.0` so the
package/README.md CHANGED
@@ -91,14 +91,14 @@ Supported modes:
91
91
 
92
92
  - `builtin` (default): register the process-backed `subagent` tool and sandbox
93
93
  each complete worker process tree.
94
- - `pi-subagents`: let `pi-subagents >=0.66.0` own orchestration under the required
94
+ - `pi-subagents`: let `pi-subagents >=0.76.1` own orchestration under the required
95
95
  native-background tool boundary described below.
96
96
  - `off`: protect Bash only.
97
97
 
98
98
  ### `pi-subagents` native-background tool boundary
99
99
 
100
- This provider supports the `pi-subagents >=0.66.0` line (validated through
101
- 0.75.0) and fails closed if its public ceiling API, module layout, or internal
100
+ This provider requires `pi-subagents >=0.76.1` (deterministically validated on
101
+ 0.76.1) and fails closed if its public ceiling API, module layout, or internal
102
102
  discovery layout drifts. The peer dependency is a floor with no upper pin; the
103
103
  loader's explicit export and layout checks are the real gate. On Node, the
104
104
  loader aliases the `@earendil-works/pi-tui` host peer to the running Pi package.
@@ -342,9 +342,10 @@ discovery behavior,
342
342
  capability ceiling, and protected launch policy in an isolated temporary agent
343
343
  directory. It never reads or updates production Pi configuration. Model-backed
344
344
  acceptance requires `PI_SUBAGENTS_GATE_MODEL` and an already-exported matching
345
- credential; missing prerequisites are reported as `SKIP`. Protected mode with
346
- pi-subagents 0.68.0 or newer needs Pi 0.86.0 or newer. The development
347
- baseline is validated against Pi 1.0.0.
345
+ credential; missing prerequisites are reported as `SKIP`. The current peer
346
+ floor and development baseline are Pi 1.1.0, with pi-subagents 0.76.1 and
347
+ `typebox >=1.3.36`. The deterministic and model-backed native-baseline /
348
+ protected-child gates pass on this baseline.
348
349
 
349
350
  The test suite covers real Linux Sandbox Runtime enforcement when its native
350
351
  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.25.0",
3
+ "version": "0.26.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,13 +51,13 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@anthropic-ai/sandbox-runtime": "^0.0.78",
54
- "@erichll/pi-auto-review": "^0.25.0",
54
+ "@erichll/pi-auto-review": "^0.26.0",
55
55
  "jiti": "2.7.0"
56
56
  },
57
57
  "peerDependencies": {
58
- "@earendil-works/pi-coding-agent": "^1.0.0",
59
- "pi-subagents": ">=0.66.0",
60
- "typebox": ">=1.0.0"
58
+ "@earendil-works/pi-coding-agent": ">=1.1.0",
59
+ "pi-subagents": ">=0.78.0",
60
+ "typebox": ">=1.3.37"
61
61
  },
62
62
  "peerDependenciesMeta": {
63
63
  "pi-subagents": {
@@ -65,12 +65,11 @@
65
65
  }
66
66
  },
67
67
  "devDependencies": {
68
- "@earendil-works/pi-ai": "^1.0.0",
69
- "@earendil-works/pi-coding-agent": "^1.0.0",
70
- "@earendil-works/pi-server": "^1.0.0",
71
- "@types/node": "^26.6.4",
72
- "pi-subagents": "^0.75.0",
73
- "typebox": "^1.3.34",
68
+ "@earendil-works/pi-ai": "^1.2.0",
69
+ "@earendil-works/pi-coding-agent": "^1.2.0",
70
+ "@types/node": "^26.6.5",
71
+ "pi-subagents": "^0.78.0",
72
+ "typebox": "^1.3.37",
74
73
  "typescript": "^7.0.2"
75
74
  }
76
75
  }
@@ -7,7 +7,8 @@ import * as hostPiTui from "@earendil-works/pi-tui";
7
7
  import * as hostTypebox from "typebox";
8
8
 
9
9
  /**
10
- * Compatible pi-subagents line: 0.66.0 and above (no upper pin). Any new minor
10
+ * Structural loader compatibility: 0.66.0 and above; the package peer floor
11
+ * is >=0.76.1 (no upper pin). Any new minor
11
12
  * is accepted, so the exports/ceiling checks below are the real compatibility
12
13
  * gate; this range only rejects old lines and guards against blind
13
14
  * accept-on-drift. Revalidated against 0.70.0: ceiling registry
@@ -35,7 +36,21 @@ import * as hostTypebox from "typebox";
35
36
  * mode needs Pi 0.86.0 or newer
36
37
  * (the pi-subagents 0.68.0+ floor): 0.85.0 does not ship
37
38
  * `@earendil-works/pi-server`, so background children fail to launch there.
38
- * This package's own peer floor is Pi 1.0.0 (validated 2026-10-02).
39
+ * Revalidated 2026-10-08 against 0.76.1 / Pi 1.1.0: capability-ceiling and
40
+ * config modules are byte-identical to 0.75.0; discovery changes add settings
41
+ * write leases without changing the loader seams. The deterministic gate and
42
+ * isolated Node/Bun/compiled-Bun host-peer tests pass. Model-backed native
43
+ * baseline / protected child acceptance also passes, with the host read
44
+ * blocked by sandboxed Bash and the runtime acknowledgement verified. This
45
+ * package's own peer floor is Pi 1.1.0.
46
+ * Revalidated 2026-10-13 against 0.78.0 / Pi 1.2.0: pi-subagents 0.77.0
47
+ * required chord aliases for every host from Pi 0.85 onward, which broke
48
+ * background children on Pi 1.2.0 (chord removed upstream); 0.78.0 requires
49
+ * chord only when the host manifest declares it, so no host-side workaround
50
+ * is needed. The subagent tool schema moved management fields into `options`
51
+ * in 0.77.0 (top-level aliases keep working) and the loader seams are
52
+ * unchanged. The deterministic gate and model-backed native baseline /
53
+ * protected child acceptance pass.
39
54
  */
40
55
  export const PI_SUBAGENTS_COMPAT_RANGE = ">=0.66.0";
41
56
  export const NATIVE_CHILD_TOOLS = ["bash", "read", "grep", "find", "ls"] as const;
package/src/subagent.ts CHANGED
@@ -294,6 +294,9 @@ export class ProcessBackedSubagentSession {
294
294
  private stdin: Writable | undefined;
295
295
  private rpcSequence = 0;
296
296
  private settledCount = 0;
297
+ // Keep cancellation tied to its run even when settlement beats the RPC
298
+ // response/waiter registration or later follow-ups complete successfully.
299
+ private readonly abortedSettlements = new Set<number>();
297
300
  private requestedSettlements = 0;
298
301
  private activePrompt:
299
302
  | {
@@ -421,6 +424,8 @@ export class ProcessBackedSubagentSession {
421
424
  if (this.stateValue === "stopped") {
422
425
  return Promise.reject(new Error(`subagent session ${this.id} is stopped`));
423
426
  }
427
+ const aborted = this.settlementAbortError(target);
428
+ if (aborted) return Promise.reject(aborted);
424
429
  if (this.settledCount >= target) {
425
430
  return Promise.resolve(sessionResult(this.textValue, this.rawOutput));
426
431
  }
@@ -531,12 +536,20 @@ export class ProcessBackedSubagentSession {
531
536
  this.startReady = undefined;
532
537
  }
533
538
 
539
+ private settlementAbortError(target: number): Error | undefined {
540
+ return this.abortedSettlements.has(target)
541
+ ? new Error(`subagent session ${this.id} run ${target} aborted`)
542
+ : undefined;
543
+ }
544
+
534
545
  private resolveSettledWaiters(): void {
535
546
  const result = sessionResult(this.textValue, this.rawOutput);
536
547
  for (const waiter of [...this.waiters]) {
537
548
  if (waiter.target <= this.settledCount) {
538
549
  waiter.cleanup();
539
- waiter.resolve(result);
550
+ const aborted = this.settlementAbortError(waiter.target);
551
+ if (aborted) waiter.reject(aborted);
552
+ else waiter.resolve(result);
540
553
  }
541
554
  }
542
555
  }
@@ -573,6 +586,9 @@ export class ProcessBackedSubagentSession {
573
586
  pending.resolve(event as RpcResponse);
574
587
  return;
575
588
  }
589
+ // Buffered lifecycle records after shutdown/failure must not resurrect a
590
+ // terminal session or resolve a waiter already rejected by that path.
591
+ if (this.stateValue === "stopped" || this.stateValue === "failed") return;
576
592
  const text = rpcAssistantText(event);
577
593
  if (text) {
578
594
  this.textValue = text;
@@ -584,6 +600,9 @@ export class ProcessBackedSubagentSession {
584
600
  if (event.type === "agent_settled") {
585
601
  this.stateValue = "idle";
586
602
  this.settledCount++;
603
+ // Pi 1.1.0 distinguishes an aborted run from a completed one. The child
604
+ // process is still alive/idle; cancel its result, not the whole session.
605
+ if (event.aborted === true) this.abortedSettlements.add(this.settledCount);
587
606
  if (
588
607
  this.activePrompt &&
589
608
  this.activePrompt.target <= this.settledCount