Sky auto-testing — Phase 3: the deterministic effect-mock harness

Progress (2026-09-12): 3a (determinism kernels), 3c (mock-by-default outbound HTTP), the 3a offline/determinism DECOUPLE, and opt-in ACTIVATION via .env.test are DONE + verified (runtime-go/rt/test_mode.go, test_http.go; rust/crates/testrunner). Remaining: 3b ephemeral-DB automation, 3e temp cluster, 3d webhook helper, auto-derived happy mock from a typed Codec, Log capture. The flagship webhook scenario PIV is proven at shop-app/tests/CheckoutWebhookTest.sky.

Status: DESIGN (Architecture-Consult PROCEED, 2026-09-12). The enabler for mode B (scenario e2e), whose flagship is the shop-app (DS) Stripe checkout -> webhook -> finalize flow run OFFLINE. Phase 2 (the differential split fuzzer, mode A) is DONE + Judge-verified. See docs/design/auto-testing.md.

Headline: there is NO runtime effect-dispatch table to swap

Ffi.kernel "X" is a build-time sentinel — rt.Ffi_kernel panics if reached at runtime (runtime-go/rt/rt.go:4295). Stage-4 rewrites every Ffi.kernel "Name" call-site to a Can.VarKernel lowering to a DIRECT Go symbol via a static compile-time table (rust/crates/lower/src/kernel.rs:99 table()). So "swap the interpreter" is not a registry swap — the seam is INSIDE each Go kernel, keyed on a runtime-global test flag. The determinism-relevant kernels are few and funnel through two shared helpers (skyGetenv for the DB DSN, skyHTTPClient for outbound HTTP), so the surface is small and mostly closeable.

Test-mode activation

The existing sky test runner (rust/crates/testrunner/src/lib.rs:52 run_test) synthesises main = Test.runMain Suite.tests, builds, and SPAWNS the compiled binary with inherited stdio (:175). The runner sets env (SKY_TEST_MODE, seed, fixed-clock ms, DATABASE_URL) BEFORE spawn — same app code, swapped interpreter, app never knows. Matches the ENV/SKY_* convention. Env-before-main is also REQUIRED by the CAF connect footgun: db = Task.run (Db.connect …) memoises the pool handle (lower.rs:919-923), so the DSN must be set before the first DB force.

The seams (file:line)

Phased plan (smallest-surface-first, each shippable + verifiable)

Hazards (guard against)

Verdict

PROCEED. No floor blocker needing user auth — every seam is runtime-owned; the DB is the user's already-running local PG (:5433) for 3a-3b and the shipped embedded bundle for 3e; no credentials, no network.