feat(host): capture HostEnvironment once at entry points
Summary
This branch is the whole HostEnvironment adoption: #3775 (root src/ and the remaining packages) and #3777 (platform and capture packages) are merged into it, on top of this PR's own foundation.
HostEnvironment = { env, cwd } now has one owner. Entry points capture it once, and the daemon runtime, request scope and command spawning receive it instead of reading process. About 260 files change, most of them test call sites.
- Type and capture:
HostEnvironmentis in@agent-device/kernel/source-value.captureHostEnvironment(process)is in@agent-device/host-kit/process. It copies the environment. - Entry points:
src/bin.ts,src/cli.ts(runCli(argv, deps, host)),src/daemon.tsandcreateAgentDeviceClient(config, { host })capture once. A client built without a host capturesprocessand then reads only that host: its default transport, daemon launch, state dir andstateDir()all resolve from it. - Daemon:
startDaemonRuntimerequireshost.DaemonRuntimeDepsInput.hostreplacesenv.RequestRouterDeps.hostandRequestExecutionScope.hostcarry it. Request handlers, claim writers, lease admission and the reapers inpackages/daemonread configuration from that host explicitly (throughRequestHandlerChainParams.hostor the env their constructor receives), not from the ambient scope. - Command spawning:
withCommandHost({ host, requestEnv }, fn)replaceswithRequestCommandEnv. Spawned commands start fromhost.env.commandHostEnvironment()still gives platform and root code that host and throws outside one; it is meant for command execution only, and their owners (#3750, #3751) convert the remaining readers to explicit hosts. - Explicit inputs:
whichCmd,resolveUserPath,expandSessionPath, the device-claim functions,loadDaemonPolicy,launchDaemonProcessand kernel allowlist and simulator-set resolvers take env or cwd as parameters. - Done when: host-kit, kernel and daemon-contracts non-test sources have no
process.envorprocess.cwd().
Behavior changes: a relative state dir without a cwd is refused (relative_state_dir_without_cwd; callers now pass one), and a relative AGENT_DEVICE_CLAIMS_DIR is refused (relative_claims_dir; the store is shared by every daemon on the host, so it used to depend on where one of them started). Suites that reach host-reading code outside a daemon request or the CLI bind a host with bindTestCommandHost() from test-kit; there is no global test setup.
The root src/ readers (#3775) and the platform and capture packages (#3777) now read host settings from HostEnvironment, merged into this branch. commandHostEnvironment() remains the ambient host for command execution and for a number of platform-side readers that still call it; narrowing it further is a follow-up.
Validation
pnpm check:affected --run --head fab82cc123 (exactCommit) passed, with current main, #3775 and #3777 merged.
Behavior note (PNG worker): packages/capture-kit/src/png-worker-client.ts no longer calls process.emitWarning when the worker is unavailable and starts with env {}; the reason is reported once through the png_worker_unavailable diagnostic (also in CHANGELOG).
🤖 Generated with Claude Code