pi-crew 0.11.50 → 0.11.52

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.
Files changed (68) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/dist/index.mjs +552 -545
  3. package/package.json +1 -1
  4. package/src/agents/agent-config.ts +58 -1
  5. package/src/config/config-validation.ts +18 -0
  6. package/src/config/env-allowlist-registry.ts +4 -0
  7. package/src/config/env-vars.ts +4 -0
  8. package/src/config/sanitize-project-config.ts +55 -0
  9. package/src/extension/management.ts +9 -0
  10. package/src/extension/registration/lifecycle-handlers.ts +28 -0
  11. package/src/extension/registration/subagent-tools.ts +5 -1
  12. package/src/extension/run-import.ts +40 -6
  13. package/src/extension/team-tool/api/agent-control.ts +49 -0
  14. package/src/extension/team-tool/api/heartbeat.ts +48 -1
  15. package/src/extension/team-tool/api/mailbox.ts +81 -2
  16. package/src/extension/team-tool/api/read.ts +22 -0
  17. package/src/extension/team-tool/api/task-claims.ts +134 -3
  18. package/src/extension/team-tool/cancel.ts +15 -1
  19. package/src/extension/team-tool/destructive-gate.ts +92 -8
  20. package/src/extension/team-tool/inspect.ts +8 -2
  21. package/src/extension/team-tool/lifecycle-actions.ts +9 -2
  22. package/src/extension/team-tool.ts +128 -27
  23. package/src/observability/exporters/otlp-exporter.ts +69 -19
  24. package/src/prompt/message-tool.ts +19 -8
  25. package/src/prompt/prompt-runtime.ts +160 -51
  26. package/src/runtime/background-runner.ts +101 -81
  27. package/src/runtime/broker/crew-broker-child.ts +32 -0
  28. package/src/runtime/broker/crew-broker-tokens.ts +24 -13
  29. package/src/runtime/broker/crew-broker.ts +12 -6
  30. package/src/runtime/broker/protocol/wait-resolve.ts +15 -1
  31. package/src/runtime/child-pi/child-pi-spawn.ts +17 -0
  32. package/src/runtime/child-pi/child-pi-steering.ts +8 -1
  33. package/src/runtime/child-pi/inference-broker.ts +41 -7
  34. package/src/runtime/child-pi/pi-version.ts +31 -3
  35. package/src/runtime/child-pi/sandbox.ts +38 -1
  36. package/src/runtime/dwf-state-store.ts +193 -7
  37. package/src/runtime/foreground-control.ts +95 -1
  38. package/src/runtime/goal-workflow/dynamic-workflow-context.ts +48 -7
  39. package/src/runtime/goal-workflow/dynamic-workflow-runner.ts +82 -6
  40. package/src/runtime/heartbeat/heartbeat-watcher.ts +32 -11
  41. package/src/runtime/live-session/live-session-runtime.ts +78 -3
  42. package/src/runtime/mcp-proxy.ts +65 -6
  43. package/src/runtime/model/pi-args.ts +16 -15
  44. package/src/runtime/plan-replan.ts +4 -1
  45. package/src/runtime/task-runner/child-executor.ts +34 -7
  46. package/src/runtime/task-runner/hybrid-tier.ts +17 -0
  47. package/src/runtime/task-runner/live-executor.ts +3 -0
  48. package/src/runtime/task-runner/post-execution.ts +5 -0
  49. package/src/runtime/task-runner/pre-execution.ts +13 -6
  50. package/src/runtime/task-runner.ts +14 -0
  51. package/src/runtime/team-runner.ts +26 -0
  52. package/src/runtime/verification/verification-worktree.ts +46 -29
  53. package/src/runtime/verification/verify-gate-memo.ts +211 -32
  54. package/src/runtime/verification/verify-gate.ts +266 -14
  55. package/src/runtime/workspace-lock.ts +95 -21
  56. package/src/schema/config-schema.ts +12 -2
  57. package/src/state/coordination/locks.ts +86 -19
  58. package/src/state/coordination/mailbox.ts +263 -22
  59. package/src/state/stores/manifest-io.ts +206 -7
  60. package/src/state/stores/state-store.ts +44 -15
  61. package/src/state/types.ts +9 -0
  62. package/src/ui/inline-panel/agent-transcript.ts +151 -11
  63. package/src/ui/settings-overlay.ts +8 -3
  64. package/src/ui/theme-discovery.ts +14 -2
  65. package/src/ui/tool-renderers/index.ts +26 -6
  66. package/src/utils/safe-terminal-text.ts +60 -0
  67. package/src/worktree/git-hardening.ts +78 -1
  68. package/src/worktree/worktree-manager.ts +34 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,148 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.11.52] — live-catch backlog: cross-session cancel reaches inline runs + heartbeat-watcher false-positive class (2026-10-30)
4
+
5
+ **Fixed (runtime, live-caught run `team_20261030044630`).** Two gaps filed as backlog after the
6
+ 0.11.51 real-test battery, both root-caused from the incident artifacts (not hypotheses):
7
+
8
+ 1. **Cross-session cancel never reached INLINE async runs.** The foreground-control interrupt guard
9
+ lived ONLY in background-runner's detached `main()`. Runs executed inline in the owner session
10
+ process (`executeBackgroundRun` core — also the `PI_CREW_TEST_ASYNC_INLINE` seam) never polled
11
+ `foreground-control.json`: the incident run had `manifest.async === undefined`, zero `async.*`
12
+ events, and TWO interrupt requests both stuck `acknowledged:false` while worker 403288 ran ≥75s
13
+ post-cancel with fresh heartbeats. Fix: guard core extracted as `startRunInterruptGuard` (hosted in
14
+ `foreground-control.ts` with the producer — keeps the lazy-imports ratchet at 542); detached
15
+ `startInterruptGuard` is now a thin process-wide wrapper (behavior byte-identical: sweep +
16
+ stopParentGuard + exitCode 130, pinned by regression tests); `executeBackgroundRun` with no host
17
+ signal mounts a RUN-SCOPED guard — ack + event + `runController.abort()` ONLY, never
18
+ `terminateActiveChildPiProcesses()` (a global sweep would murder sibling runs' children in the same
19
+ host process; pinned by the SCOPED-KILL test with a real registered child). The team-run input now
20
+ receives the RESOLVED signal — inline runs previously had NO cancellation source at all. Guard
21
+ stops in a `finally`; ownership deduped by host-signal presence (no double guard).
22
+ 2. **heartbeat-watcher false-dead class.** `crew.task.heartbeat_dead` fired 3× for a live worker
23
+ (heartbeat silent >5min during long tool work, `task.heartbeat.pid` undefined on every task, so the
24
+ PID-liveness downgrade gate had nothing to read), and `handleRetry` re-queued tasks WITHOUT
25
+ stripping liveness fields (attempt-2 inherited attempt-1's heartbeat timestamps). Fix: (a) watcher
26
+ attempt-clamp — heartbeat/`agentProgress` evidence older than the current attempt's `startedAt` is
27
+ inadmissible; no usable evidence ⇒ elapsed from `startedAt` (a task younger than `deadMs` can never
28
+ be dead); (b) `handleRetry` strips `heartbeat` + `agentProgress` on re-queue (checkpoint untouched);
29
+ (c) child-executor pins the attempt's worker pid into `task.heartbeat` (per-attempt reset, guarded
30
+ spread) so the PID-gate actually functions.
31
+
32
+ Also: an already-ACKED interrupt no longer warns "Ignoring unknown foreground control request" every
33
+ poll tick until guard stop (verifier-flagged cosmetic, carried over from the pre-extraction guard).
34
+
35
+ Tests: 5 new `interrupt-guard.test.ts` (inline wiring, post-stop non-consumption, SCOPED-KILL,
36
+ detached regression, acked-silence), `async-runner-inline-interrupt.test.ts` (e2e via the real inline
37
+ seam: mid-run request → ack ≤3s + event + terminal run + no leaked interval), 4 watcher attempt-clamp
38
+ pins (incl. genuinely-stale-still-dead regression + no-startedAt legacy), 2 heartbeat-pid pins, +1
39
+ lifecycle retry-strip. Leader gates: full unit+integration, typecheck, biome, format:check,
40
+ lazy-imports 542, slop 41 — all green.
41
+
42
+ ## [0.11.51] — SEC-2026-11: security audit remediation (30 confirmed findings + 4 leads, 13 waves) (2026-10-30)
43
+
44
+ **Fixed (security).** Full remediation of the 2026-10-29 independent security audit (skill security-audit, full
45
+ profile, whole package @ 6063f377; 30 confirmed / 4 needs_validation / 3 rejected). Story:
46
+ `docs/stories/SEC-2026-11-audit-remediation/`. Evidence: `/home/bom/security-audit-skill/pi-crew/run-1` (report,
47
+ findings, fix-records). Wave-by-wave:
48
+
49
+ **Fixed (CI live-probed, Windows).** Hardened git env (`GIT_CONFIG_NOSYSTEM=1`) dropped the
50
+ Git-for-Windows system gitconfig — where the install-wide `core.autocrlf=true` default lives — so every
51
+ hardened `git status` reported phantom modifications on pristine CRLF worktrees (verify-gate skip refusals,
52
+ memo disabled, snapshot dirty: all fail-closed on clean trees). `buildGitSafeEnv` now re-injects ONLY the two
53
+ eol scalars (`core.autocrlf`/`core.eol`), parsed and value-domain-checked from the canonical system gitconfig
54
+ by trusted code, via git's env-config channel (`GIT_CONFIG_COUNT`, honored independently of NOSYSTEM). No
55
+ include/filter/other system key can travel the channel; attacker-supplied `GIT_CONFIG_*` stays stripped
56
+ (pinned). Diagnosed with a live windows-2025 CI probe (run 41058674711: full-env status clean vs safe-env
57
+ `M run.js`). Test suite hardening: deadline test isolates its bound (no seeded budget racing the terminal
58
+ status), O_NOFOLLOW symlink-swap pin skips documented on win32 (libuv no-op; binding control there is the
59
+ Ed25519 steering signature layer), theme-stem escape plant skips documented where the OS forbids control
60
+ chars in filenames (vector structurally absent).
61
+
62
+ **Fixed (live-caught regression, real-test battery).** Ask/delegate/message were dead in every default-config
63
+ worker session since 0.11.50: LOW-1 moved the broker token from env to the fd3 pipe, but the three tool guards
64
+ still read the env token. Workers now bridge to fd3-resolved child broker credentials (task-identity-bound,
65
+ settled-promise seam in `crew-broker-child.ts`; guards in `prompt-runtime.ts` / `message-tool.ts`). Proven live:
66
+ ask park→respond(signed)→resume, message delivery, signed steer honored; pinned unit suite 5/5
67
+ (`test/unit/prompt/low1-fd3-tool-guard.test.ts`).
68
+
69
+ - **w1a broker (HIGH×2, MEDIUM)** — spawns without a task identity no longer receive the bare per-run token
70
+ (fail closed); bare-runId fallback retired for explicit taskId hello claims; `wait.*` authenticate via
71
+ task-scoped compound tokens only; durable mailbox rows + steering lines are Ed25519-signed by the root session
72
+ (private key heap-only, children get the public verify key via `PI_CREW_MAILBOX_VERIFY_KEY`), consumers drop
73
+ unsigned/invalid rows as noise; steering poll re-validates per tick (TOCTOU); inbox fence neutralization covers
74
+ every attacker-influenced metadata field.
75
+ - **w1b bindings (MEDIUM, LOW)** — gatherReplies binds replies to (mailId → expected addressee) with broker-
76
+ authenticated `from`; api claim/release/transition gated for read_only tier + claim bound to the caller's
77
+ `PI_CREW_TASK_ID`.
78
+ - **w2 verify-gate (HIGH×3)** — gate binds the tracked working tree at dispatch (temp-index treeOid), fails on
79
+ drift, downgrades mid-gate tamper to INCONCLUSIVE; memo key = cwd + full tracked-tree oid (dirty ⇒ memo off);
80
+ dependency-worktree probes refuse skip on uncommitted work even on memoized PASS.
81
+ - **w3 dwf trust (HIGH, MEDIUM)** — user-tier `.dwf.ts`/preStepScript default-deny (`PI_CREW_TRUST_USER_DWF`);
82
+ dispatch-time `dynamicScriptPin` (path+sha256) persisted before load and verified on every resume arm;
83
+ checkpoints bound to runId with schema/clamp/verdict-allowlist hydration validation.
84
+ - **w4a child-pi (HIGH×2)** — inference-broker in-flight cap enforced (increment + exactly-once settle; over-cap
85
+ 429s); sandbox toolchain binds capped below the user trust boundary (no `$HOME`/`~/.pi/agent` overshoot —
86
+ auth.json unreachable).
87
+ - **w4b config (HIGH, MEDIUM)** — `runtime.embeddedWorkers` user-only (sensitive); embedded routing fails closed
88
+ while a sandbox posture is on; S-7 read_only execution-tool floor (bash/edit/write un-expandable by
89
+ frontmatter; D5 write-tier parity preserved); `pi-args` emits tools from the resolved policy.
90
+ - **w5a root-gate (HIGH, MEDIUM)** — dryRun carriers traverse the full R11-S1 matrix; delete/cleanup/init gated
91
+ (resolved-tier backstop in handleDelete; init scope union resolver).
92
+ - **w5b resume (MEDIUM×2, LOW)** — resume inherits budget + deadline (manifest-derived re-arm; deadline timer
93
+ armed); maxTasks admission re-enforced before any side effect; special-kind adopt performs the in-lock
94
+ liveness recheck. Plus: perf-sampler child error listener (pre-existing abort-after-exit host crash).
95
+ - **w6 locks (HIGH, MEDIUM, LOW)** — seed-path destination O_NOFOLLOW ancestor validation (pre+post mkdir);
96
+ workspace-lock refresh CAS on (dev,ino)+bytes (no clobber of a stolen lock); steal removal bound to the
97
+ verified corpse token + post-claim verification in both acquire loops.
98
+ - **w7a render (MEDIUM×2, LOW)** — shared `stripTerminalSequences`; control-char theme names refused/neutralized;
99
+ inline-panel transcript + tool-renderers + inspect sinks sanitize OSC/CSI/control chars.
100
+ - **w7b observability/import (MEDIUM, LOW×2)** — OTLP `redirect:'manual'` + 3xx refusal; userinfo endpoints
101
+ refused + origin-only error/log rendering; imported manifest fields rendered through `sanitizeImportedText`.
102
+ - **w8 ci (MEDIUM, LOW)** — battery changed-path matching decodes git C-quoted paths (quotePath pinned,
103
+ fail-closed decode) so T7 live-smoke can't be blind-triggered; ci.yml tarball smoke binds the exact pack name
104
+ with loud existence/count/version assertions (no decoy glob).
105
+
106
+ **Verification.** Per-wave regression tests (≈160 new) + sequential re-run of all 211 suite files affected by
107
+ mid-run tree churn: green. `npm run typecheck`, `npm run lint`, `biome format`, `check-env-vars`,
108
+ `check-lazy-imports`, `check-slop-rules`, `check-event-types-registry --enforce` all pass. Full-suite fresh run
109
+ on the final tree pending release gate (see story validation.md).
110
+
111
+ ## [0.11.51] — wave 9: needs_validation leads + deferred residuals
112
+
113
+ **Fixed (security hardening).** Follow-up wave closing the audit's 4 needs_validation leads (deterministic/defensive
114
+ halves) and the residuals deferred by w1b/w7a/w7b:
115
+
116
+ - **N1** legacy live-session MCP route: allowlist-shaped post-creation foreign-extension assert (typed
117
+ fail-closed `McpForeignExtensionError` + `live-session.foreign_extension_blocked` event) — a differently-named
118
+ MCP adapter can no longer silently load/connect for a read-only role when the SDK falls back to the
119
+ DefaultResourceLoader path.
120
+ - **N2** version probe: `probePiVersion` failures re-arm after a 60s TTL instead of memoizing null for the
121
+ process lifetime — one transient cold-start miss no longer permanently drops `--no-mcp` from parity spawns on
122
+ hosts that support it (the empty-frontmatter `--tools` half was already closed in the first wave).
123
+ - **N3** persisted run state: loader-level validation — per-task shape + runId binding (foreign-runId entries
124
+ dropped) + 10k DoG cap; manifest runKind allowlist (unknown → team-run + warn); non-object manifests fail
125
+ closed with quarantine. On-disk forensics preserved (in-memory drops only).
126
+ - **N4** verification subsystem git invocations: all 16 sites (verification-worktree ×6, verify-gate-memo ×9,
127
+ verify-gate dirty-probe ×1) routed through the MED-1 composition (`hardenGitArgs` + `buildGitSafeEnv` +
128
+ `assertWorktreePointerTrusted`), closing the config-reachable helper-execution sink the audit reproduced live
129
+ (core.fsmonitor at a hijacked worktree). w2 tree-OID values pinned unchanged.
130
+ - **residuals**: read_only role gates + caller audit fields on the remaining mutating api ops
131
+ (write-heartbeat, live-agent control cluster, mailbox send/ack/repair, foreground-interrupt);
132
+ `parseOtlpConfig` refuses userinfo endpoints at validation time (origin-only errors); `tool_execution_start`
133
+ `event.args` string leaves sanitized before ToolExecutionComponent render.
134
+
135
+ 42 new regression tests. Owner-observed deployment checklists for the leads' impact confirmation remain in the
136
+ audit's NEEDS-VALIDATION.md.
137
+
138
+ ## [Unreleased] — test hardening
139
+
140
+ **Fixed (test-only).** `waitForPreGateEvents` (classifier-pre-gate) now THROWS on timeout with counts + path
141
+ instead of returning silently — the silent return turned a legit wait-timeout into a far-away
142
+ `TypeError: Cannot read properties of undefined (reading 'taskId')` on `preGateEvents(...)[0]!` (the [pg-10]
143
+ CI flake: 2 Node-22 shards, run 40797688830, 2026-10-29; rerun green). A timeout now fails AT the wait site
144
+ with diagnostics (found vs expected `task.verifier_pre_gate` events, eventsPath, budget). Bug-030 RCA backlog item.
145
+
3
146
  ## [0.11.50] — LOW-1: PI_CREW_BROKER_STDIN fd3 handshake DEFAULT-ON ('0' opts out) (2026-10-28)
4
147
 
5
148
  **Changed (LOW-1 gate flip).** The broker-credential fd3 handshake route is now **DEFAULT-ON**: both gates