Orca v0.2.19
Orca v0.2.19
Patch release: prevent macOS sandboxed test runners from leaving child worker
processes behind when their cleanup signal is denied.
Incident And Root Cause
During a persistent Goal, a sandboxed pnpm ... vitest run reached Tinypool's
worker cleanup path. Node's ChildProcess.kill failed with EPERM, and macOS
unified logging recorded the matching policy denial:
Sandbox: node(31412) deny(1) signal children [node(31426)] signum:15
Both Orca macOS Seatbelt profiles allowed a process to signal itself, but not
its own children. Vitest stopped after the failed cleanup operation while its
worker processes remained alive.
System Evidence
The macOS Jetsam snapshot taken during the freeze showed:
- 10 leftover Node workers using 3.90-4.16 GiB each, 40.51 GiB in total
- the Orca native process using about 30.2 MiB
- the npm Node wrapper using about 11.8 MiB
nodeas the largest process class while the system was under compressor
pressure
This was not an Orca transcript-heap leak. The saved Orca session was about
608 KiB, and the native process remained small in the system snapshot. The
evidence does not establish why each abandoned worker grew to roughly 4 GiB;
it establishes that the sandbox denied the parent's cleanup signal and that
the workers remained active afterward.
Changes
- Descendant cleanup: workspace-write and read-only Seatbelt profiles now
include(allow signal (target children)). - Real behavior coverage: both profiles execute a child process, send it
SIGTERM, and wait for it to exit. - Security contract: tests reject broad signal grants and the
target others/target same-sandboxscopes. - Goal documentation: the Goal guide now explains that Goal turns use the
normal shell sandbox and the same child-process cleanup boundary.
Security Boundary
The new permission is lineage-scoped. A sandboxed command can signal itself
and its own descendants, which is the minimum required for worker-pool process
managers. It still cannot signal an unrelated process or a process that merely
shares the same sandbox.
Regression Boundary
The v0.2.17..v0.2.18 production diff did not change Seatbelt or shell process
handling, and the incident session did not use the unknown-tool recovery added
in v0.2.18. This was a pre-existing macOS sandbox policy defect exposed by a
long Goal workload, not a regression in v0.2.18's DeepSeek tool correction.
Compatibility
No changes to CLI flags, slash commands, approval modes, Goal records, history
formats, provider configuration, MCP configuration, npm package layout, Linux
behavior, or public APIs.
Verification
Focused validation:
cargo test -p orca-tools child_process -- --nocapture
cargo test -p orca-tools -- --test-threads=1
cargo clippy -p orca-tools --all-targets
cargo fmt --all -- --check
git diff --checkA controlled Node smoke also spawned a child Node process inside the repaired
profile, called ChildProcess.kill("SIGTERM"), and observed the child exit with
SIGTERM. A separately owned process remained protected with EPERM.
Full release gate before tagging:
cargo check --workspace --all-targets
cargo test --workspace --all-targets -- --test-threads=1
cargo clippy --workspace --all-targets
npm --prefix site run build
npm --prefix site run check:seo
node scripts/release/test-stage-npm.mjs
node scripts/release/test-verify-published.mjsPost-publish verification:
node scripts/release/verify-published.mjs --version 0.2.19 --repo echoVic/blade-deepseek --package @blade-ai/orca --bin orcaUpgrade
Install or pin the release with:
npm install -g @blade-ai/orca@0.2.19or:
curl -fsSL https://orcaagent.dev/install.sh | \
INSTALL_DIR=/usr/local/bin ORCA_VERSION=0.2.19 sh