Acceptance

Full standalone host acceptance

Validated on 2026-07-14 with Node >=22.19, Pi SDK 0.80.6, ACP SDK 1.2.0, and the clean npm/Nix package definitions.

Credential-free end-to-end host

test/full-host-acceptance.test.mjs starts one real in-process Pi Daemon host on IPv6 loopback with a bearer-authenticated API and a deterministic local OpenAI-compatible streaming model. It uses the production PiSessionFactory, AgentSessionRuntime, durability/catalog/ticket stores, HTTP/WebSocket server, Pi RPC controller, ACP adapter, and stdio bridge—not a transport-only fake.

The test proves in one lifecycle:

The test patches every Node child-process entry point before dynamically loading Pi or Pi Daemon. Session creation, wakes, RPC, ACP, restart, and bridge work all complete with zero child-process calls. (The installed CLI subprocess smoke is a separate packaging test and intentionally launches the package executable.)

Adversarial matrix

The normal npm test suite additionally proves:

npm test is the deterministic credential-free Node gate. nix flake check builds the pinned dependency closure, runs that suite in the package check, and verifies the package/app/install surface. Package install checks execute only the deterministic installed pi-daemon version and pi-daemon-rpc --version commands.

The dedicated macOS lane first records the current system, signature policy, credential-redacted substituter identities, trusted key names, and offline store presence for both the job-unique package and npm dependency cache. A nonsecret GitHub run-attempt nonce changes only the package derivation identity, making its output absent even on a warm self-hosted store while leaving every dependency reusable. The lane then performs an ordinary nix build under a 75-minute bound and roots its result only through a job-private symlink below RUNNER_TEMP; it never uses --rebuild, deletes a shared-store path, or removes a live/global GC root. The complete flake and installed app assertion use the same nonce, so they reuse that exact package while Pages, Home Manager, generated contracts, and workflow syntax still contribute to the final verdict. The whole job remains bounded at 80 minutes. Nix builder logs emit start/end timestamps and durations for build, check, install, fixup, and install-check; the workflow retains those logs for 14 days. The package ceiling is based on the measured PR 26 cold tail (12m08s install and 29m27s fixup inside a run that exceeded 50 minutes), not the former warm-cache range. A manual deliberate_test_failure dispatch runs a known-failing Node test through the same phase wrapper and must make the workflow red; ordinary push and pull-request runs never enable that diagnostic. macOS runs are serialized by ref and are not cancelled by later commits.

The service-launch/process-tree consumer proof is deliberately separate because it depends on scheduler timing and observing a live descendant tree. Run it explicitly with npm run test:consumer-acceptance; the scheduled and manually dispatchable .github/workflows/consumer-acceptance.yml builds the exact x86_64-linux Nix package, points the client at its installed wrapper, retains logs, and reports a stable broken-on-main triage payload through the configured feedback webhook when it fails. It is not triggered by pushes or pull requests, so a load-sensitive consumer observation cannot make an ordinary source build, package build, or install red. On the constrained macOS host, continuous acceptance uses ::1 for loopback tests to avoid unrelated Tailscale IPv4 CLOSE_WAIT exhaustion.

Optional live-provider proof

scripts/live-sdk-smoke.mjs remains an optional credentialed parity check. It patches child-process entry points before loading Pi, opens two independent no-tools sessions, runs exact A and B prompts concurrently, verifies isolated results/events, and reports timing and the empty child-process call list.

PI_DAEMON_LIVE_MODEL=github-copilot/gpt-5-mini npm run test:live

Crash guarantee

Pi Daemon does not claim exactly-once provider execution across a crash in the narrow window between provider completion and terminal journal fsync. That state is explicitly indeterminate; it is queryable/reconcilable and never blindly replayed.