host: fix serving-JIT host miscompile — install IO resolver for http-listen
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 33s

The serving-JIT perform-in-HO-callback miscompile (map/rest/drop wrong
CALL_PRIM args → blank pages, empty picker) is now fully fixed, so the host
runs 100% serving JIT with NO jit-exclude.

sx-vm-extensions 81177d0e resolves a suspended HO-callback's IO inline
(instead of unwinding the native map/filter loop and corrupting the stack),
but ONLY when a synchronous resolver is installed (!_cek_io_resolver = Some).
The host serves via the http-listen primitive, whose handler drove durable IO
through cek_run_with_io with the resolver = None — so it hit the unwinding
path the fix doesn't cover. (The vm-ext repro installed a resolver, so it
never exercised the host's real no-resolver path.)

Fix: extract cek_run_with_io's IO resolution into resolve_io_request, and have
http-listen install _cek_io_resolver := Some (fun req _ -> resolve_io_request
req) — byte-identical resolution, so the inline path resolves durable reads
exactly as the CEK loop would.

Verified: host conformance 271/271; ephemeral durable server at 100% JIT (no
exclude) zero fallbacks + real content + related shown + picker 12 candidates;
live blog.rose-ash.com home/post/tags 200 with related posts, zero error-log
lines; relate-picker Playwright 4/4 (infinite-scroll + filter + relate).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-28 20:13:24 +00:00
parent 8104aadc2b
commit d8d7663565
3 changed files with 102 additions and 59 deletions

View File

@@ -99,19 +99,14 @@ EPOCH=1
for M in "${MODULES[@]}"; do
echo "(epoch $EPOCH)"; echo "(load \"$M\")"; EPOCH=$((EPOCH+1))
done
# Serving-mode JIT: exclude the request-path SX (host app + Dream framework). The
# 100%-JIT experiment surfaced the key finding — the kernel miscompile isn't just
# 500s, it SILENTLY returns wrong results (the `drop` in host/blog-relate-options
# yielded an empty candidate list → broken relate picker, NO error logged). Silent
# corruption is worse than a crash, so these run on CEK (they're IO-bound — no perf
# loss) while the kernel bug is fixed upstream (sx-vm-extensions, OP_PERFORM resume
# — see plans/HANDOFF-jit-miscompile.md). The Datalog/relations JIT (the real win)
# stays on. Drop this exclude once the resume bug lands, then go 100% JIT again.
if [ "${SX_SERVING_JIT:-}" = "1" ]; then
echo "(epoch $EPOCH)"
echo "(eval \"(jit-exclude! \\\"host/*\\\" \\\"dream-*\\\" \\\"dr/*\\\")\")"
EPOCH=$((EPOCH+1))
fi
# 100% serving JIT — NO host exclude. The serving-JIT perform-in-HO-callback
# miscompile (map/rest/drop wrong args → blank pages, empty picker) is fixed by
# two composing pieces: sx-vm-extensions 81177d0e resolves a callback's IO
# inline (instead of unwinding the native HO loop) WHEN a synchronous resolver
# is installed, and sx_server.ml's http-listen now installs that resolver (it
# mirrors cek_run_with_io exactly). So the whole request path — host app +
# Dream + Datalog — runs under JIT with no exclude. Verified: ephemeral durable
# server, 100% JIT, zero fallbacks, real content, picker lists candidates.
# Point the blog at the DURABLE file backend (persists under $SX_PERSIST_DIR),
# then idempotently seed a welcome post (sx_content = SX element markup, the
# editor's content model). Re-seeding is a no-op if the slug already exists.