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.
- package/CHANGELOG.md +143 -0
- package/dist/index.mjs +552 -545
- package/package.json +1 -1
- package/src/agents/agent-config.ts +58 -1
- package/src/config/config-validation.ts +18 -0
- package/src/config/env-allowlist-registry.ts +4 -0
- package/src/config/env-vars.ts +4 -0
- package/src/config/sanitize-project-config.ts +55 -0
- package/src/extension/management.ts +9 -0
- package/src/extension/registration/lifecycle-handlers.ts +28 -0
- package/src/extension/registration/subagent-tools.ts +5 -1
- package/src/extension/run-import.ts +40 -6
- package/src/extension/team-tool/api/agent-control.ts +49 -0
- package/src/extension/team-tool/api/heartbeat.ts +48 -1
- package/src/extension/team-tool/api/mailbox.ts +81 -2
- package/src/extension/team-tool/api/read.ts +22 -0
- package/src/extension/team-tool/api/task-claims.ts +134 -3
- package/src/extension/team-tool/cancel.ts +15 -1
- package/src/extension/team-tool/destructive-gate.ts +92 -8
- package/src/extension/team-tool/inspect.ts +8 -2
- package/src/extension/team-tool/lifecycle-actions.ts +9 -2
- package/src/extension/team-tool.ts +128 -27
- package/src/observability/exporters/otlp-exporter.ts +69 -19
- package/src/prompt/message-tool.ts +19 -8
- package/src/prompt/prompt-runtime.ts +160 -51
- package/src/runtime/background-runner.ts +101 -81
- package/src/runtime/broker/crew-broker-child.ts +32 -0
- package/src/runtime/broker/crew-broker-tokens.ts +24 -13
- package/src/runtime/broker/crew-broker.ts +12 -6
- package/src/runtime/broker/protocol/wait-resolve.ts +15 -1
- package/src/runtime/child-pi/child-pi-spawn.ts +17 -0
- package/src/runtime/child-pi/child-pi-steering.ts +8 -1
- package/src/runtime/child-pi/inference-broker.ts +41 -7
- package/src/runtime/child-pi/pi-version.ts +31 -3
- package/src/runtime/child-pi/sandbox.ts +38 -1
- package/src/runtime/dwf-state-store.ts +193 -7
- package/src/runtime/foreground-control.ts +95 -1
- package/src/runtime/goal-workflow/dynamic-workflow-context.ts +48 -7
- package/src/runtime/goal-workflow/dynamic-workflow-runner.ts +82 -6
- package/src/runtime/heartbeat/heartbeat-watcher.ts +32 -11
- package/src/runtime/live-session/live-session-runtime.ts +78 -3
- package/src/runtime/mcp-proxy.ts +65 -6
- package/src/runtime/model/pi-args.ts +16 -15
- package/src/runtime/plan-replan.ts +4 -1
- package/src/runtime/task-runner/child-executor.ts +34 -7
- package/src/runtime/task-runner/hybrid-tier.ts +17 -0
- package/src/runtime/task-runner/live-executor.ts +3 -0
- package/src/runtime/task-runner/post-execution.ts +5 -0
- package/src/runtime/task-runner/pre-execution.ts +13 -6
- package/src/runtime/task-runner.ts +14 -0
- package/src/runtime/team-runner.ts +26 -0
- package/src/runtime/verification/verification-worktree.ts +46 -29
- package/src/runtime/verification/verify-gate-memo.ts +211 -32
- package/src/runtime/verification/verify-gate.ts +266 -14
- package/src/runtime/workspace-lock.ts +95 -21
- package/src/schema/config-schema.ts +12 -2
- package/src/state/coordination/locks.ts +86 -19
- package/src/state/coordination/mailbox.ts +263 -22
- package/src/state/stores/manifest-io.ts +206 -7
- package/src/state/stores/state-store.ts +44 -15
- package/src/state/types.ts +9 -0
- package/src/ui/inline-panel/agent-transcript.ts +151 -11
- package/src/ui/settings-overlay.ts +8 -3
- package/src/ui/theme-discovery.ts +14 -2
- package/src/ui/tool-renderers/index.ts +26 -6
- package/src/utils/safe-terminal-text.ts +60 -0
- package/src/worktree/git-hardening.ts +78 -1
- 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
|