jolt/docs/seed-overlay-registry.md
Yogthos 33eff7c7d8 Clean up codebase: rename stdlib layer, strip porting residue, fix tooling
Rename src/jolt -> stdlib (the runtime-loaded layer; jolt-core stays the
seed-baked layer) and update the loader / emit-image / doc paths. Drop dead
code: the spike/ experiments, the duplicate clojuredocs-export.edn (json moves
to tools/), the Janet-era jolt.http binding, and the orphaned
persistent_vector.clj whose ns/path didn't even match.

Strip porting residue from comments and docstrings across host/chez, jolt-core,
stdlib, tests, and docs: internal issue ids, "Phase N" markers, and the "vs
Janet" historical exposition, leaving present-tense descriptions and the real
JVM-Clojure semantic contrasts. Same pass over the corpus suite labels. The seed
is unchanged (docstrings/comments aren't emitted), so the self-host fixpoint and
corpus are untouched.

Port tools/spec_coverage.py off the dead janet probe to bin/joltc and regenerate
coverage.md; drop the dead :host/janet rule from certify.clj and regenerate the
conformance profile. Add docs/host-interop.md (the JVM shims and how to register
your own host class from a library) and a writing-style note in CLAUDE.md.

Stabilize the four racy concurrency corpus cases (future-cancel and agent
send/send-off): give the future a sleeping body and the agent a slow action, so
cancel reliably catches an in-flight future and deref reliably reads the
pre-update snapshot. They certify deterministically now, so drop their :flaky
allowlist entries and the orphaned legend.
2026-06-22 22:18:00 -04:00

2.3 KiB

Seed ↔ Overlay Registry

Jolt is Clojure on Chez Scheme. clojure.core is built from two tiers that both define clojure.core-facing vars, and for a handful of names both tiers carry a definition. This document records how the two tiers relate and which copy is authoritative.

The two tiers

  • Native shims (host/chez/natives-*.ss) bind a set of clojure.core vars directly to Scheme runtime values via def-var! — collection constructors, seq fns, numeric/string ops, and so on. These cover names the overlay assumes exist as bare clojure.core vars but does not define itself.
  • The Clojure overlay (jolt-core/clojure/core/NN-*.clj) defines the rest of clojure.core in dependency-ordered tiers, loaded in order: 00-syntax, 00-kernel, 10-seq, 20-coll, 25-sorted, 30-macros, 40-lazy, 50-io.

The overlay loads after the native shims. When an overlay tier (defn X …) for a name a native shim already bound, the overlay def shadows the native binding — user code sees the overlay copy. The native binding then survives only if some other native/runtime code still calls the Scheme value directly.

So a name's home is determined by two facts:

  1. is it bound by a native shim? (the Scheme value is reachable from the runtime)
  2. does an overlay tier (defn X …)? (the overlay copy is what user code sees)

The compiled seed

clojure.core is compiled ahead of time into the checked-in seed (host/chez/seed/{prelude,image}.ss) as Scheme def-var! forms. The seed's source twin is the overlay (jolt-core/clojure/core/*.clj plus the stdlib namespaces under stdlib/clojure/); host/chez/emit-image.ss re-emits the prelude from those sources on Chez. The build is a byte-fixpoint: rebuilding from an up-to-date seed reproduces it exactly.

Consistency guard

There is no separate drift-check test for the registry. The self-hosting fixpoint is the guard: after changing a seed source (a core tier, the compiler namespaces, the host contract, the reader, or emit-image.ss) you must re-mint the seed (make remint), and make selfhost fails if the checked-in seed and its sources have drifted. So if the overlay's shadowing relationship changes, the re-minted prelude changes with it, and the fixpoint check keeps source and seed in agreement.