# Effect v4 for extension internals

Apnea’s Pi extension mixed `ToolResult` returns with thrown errors, hand-rolled JSON validation, and hard-to-test `fs`/herdr/vcs side effects inside tool functions. We adopt **Effect v4** (pinned beta) for workflow programs and IO services only: pure domain (state machine, paths, front-matter line parse, round keys) stays plain TypeScript; Pi tool params stay TypeBox; adapters map Effect exits to `ToolResult`. Services are custom and thin (FileSystem, RunStore, Config, Vcs, Herdr, Clock) — not `@effect/platform-node`. Each tool call runs with a fresh `AppLive` provide (no process-global runtime). Config/state decode via Effect Schema as runtime source of truth; repo `schemas/*.json` remain human protocol docs, kept honest with fixture tests. Protocol, artifact layout, and config trust are unchanged (ADRs 0001–0007).
