feat: implement all Clojure platform features from clojure-left.md

ober

bfe296c0c0e882e9b65993e2c6931461de2c8fd6

diff --git a/docs/jerboa-for-clojure-devs.md b/docs/jerboa-for-clojure-devs.md
new file mode 100644
index 0000000..4fe7d5b
--- /dev/null
+++ b/docs/jerboa-for-clojure-devs.md
@@ -0,0 +1,606 @@
+# Jerboa for Clojure Developers
+
+Jerboa is a Chez Scheme dialect that provides a Clojure-compatible surface for developers who want fast startup, native compilation, and no JVM dependency. A single `(import (jerboa clojure))` gives you persistent data structures, atoms, lazy sequences, destructuring, `loop`/`recur`, `core.async`-style channels, and most of the Clojure core API — mapped onto Scheme's proper tail calls and hygienic macro system.
+
+## Installation
+
+```bash
+git clone https://github.com/jafourni/jerboa.git
+cd jerboa
+make build
+```
+
+You need [Chez Scheme](https://cisco.github.io/ChezScheme/) installed (`scheme` on your PATH).
+
+## Hello World
+
+Create `hello.ss`:
+
+```scheme
+(import (jerboa clojure))
+
+(println "Hello, world!")
+```
+
+Run it:
+
+```bash
+scheme --libdirs lib --script hello.ss
+```
+
+## REPL
+
+```bash
+scheme --libdirs lib
+```
+
+Then at the `>` prompt:
+
+```scheme
+> (import (jerboa clojure))
+> (def m (hash-map "name" "Alice" "age" 30))
+> (get m "name")
+"Alice"
+> (-> m (assoc "role" "dev") (dissoc "age") keys)
+("name" "role")
+```
+
+## The Import Story
+
+There is no `ns` form. A single import gives you everything:
+
+```scheme
+(import (jerboa clojure))
+```
+
+This brings in the full Jerboa prelude plus all Clojure-compatibility modules: persistent maps, sets, vectors, atoms, lazy sequences, destructuring, dynamic vars, `loop`/`recur`, `ex-info`, transients, `core.logic`, `clojure.spec`, Transit, and `clojure.string` (prefixed as `str/`).
+
+For additional modules, use the `require` macro (Clojure-style):
+
+```scheme
+(require '(std csp clj) :as async)      ;; core.async  -> async:chan, async:go, ...
+(require '(std multi) :refer (defmulti defmethod))
+(require '(std protocol) :refer (defprotocol extend-type))
+(require '(std db sqlite) :as db)
+```
+
+## Side-by-Side: 20 Common Patterns
+
+### 1. Defining Functions
+
+```clojure
+;; Clojure
+(defn greet [name]
+  (str "Hello, " name "!"))
+```
+
+```scheme
+;; Jerboa
+(def (greet name)
+  (str "Hello, " name "!"))
+```
+
+`def` with a list head defines a function. Optional args use `(def (f x (y 10)) ...)`. Multi-arity uses `def*`.
+
+### 2. Let Bindings
+
+```clojure
+;; Clojure
+(let [x 1
+      y (+ x 1)]
+  (+ x y))
+```
+
+```scheme
+;; Jerboa
+(let ([x 1]
+      [y (+ x 1)])
+  (+ x y))
+```
+
+Brackets and parens are interchangeable. Each binding is a pair `[name expr]`.
+
+### 3. if / when / cond
+
+```clojure
+;; Clojure
+(cond
+  (> x 0) "positive"
+  (< x 0) "negative"
+  :else    "zero")
+```
+
+```scheme
+;; Jerboa
+(cond
+  [(> x 0) "positive"]
+  [(< x 0) "negative"]
+  [else    "zero"])
+```
+
+`if`, `when`, and `unless` work the same as Clojure. In `cond`, use `else` instead of `:else`.
+
+### 4. Threading Macros
+
+```clojure
+;; Clojure
+(-> m (assoc :role "dev") (dissoc :age))
+(->> (range 10) (filter even?) (map inc))
+```
+
+```scheme
+;; Jerboa
+(-> m (assoc role: "dev") (dissoc age:))
+(->> (range 10) (filter even?) (map inc))
+```
+
+All threading macros are present: `->`, `->>`, `as->`, `some->`, `some->>`, `cond->`, `cond->>`.
+
+### 5. Maps
+
+```clojure
+;; Clojure
+(def m {:name "Alice" :age 30})
+(get m :name)           ;=> "Alice"
+(assoc m :role "dev")   ;=> {:name "Alice" :age 30 :role "dev"}
+(dissoc m :age)         ;=> {:name "Alice"}
+(merge m {:city "NYC"})
+(update m :age inc)
+(get-in nested [:a :b])
+(contains? m :name)     ;=> true
+(keys m)  (vals m)  (count m)
+(select-keys m [:name])
+```
+
+```scheme
+;; Jerboa
+(def m (hash-map name: "Alice" age: 30))
+(get m name:)             ;=> "Alice"
+(assoc m role: "dev")     ;=> new map with role
+(dissoc m age:)           ;=> new map without age
+(merge m (hash-map city: "NYC"))
+(update m age: inc)
+(get-in m (list name: age:))
+(contains? m name:)       ;=> #t
+(keys m)  (vals m)  (count m)
+(select-keys m (list name:))
+```
+
+`hash-map` returns a persistent (immutable) map backed by a HAMT. All ops are polymorphic across persistent maps, concurrent hash maps, and mutable hash tables.
+
+### 6. Vectors
+
+```clojure
+;; Clojure
+(def v [1 2 3])
+(conj v 4)       ;=> [1 2 3 4]
+(nth v 0)        ;=> 1
+(count v)        ;=> 3
+(first v)        ;=> 1
+(rest v)         ;=> (2 3)
+```
+
+```scheme
+;; Jerboa
+(def v (vec '(1 2 3)))     ;; or (vec 1 2 3)
+(conj v 4)                 ;=> persistent vector [1 2 3 4]
+(get v 0)                  ;=> 1
+(count v)                  ;=> 3
+(first v)                  ;=> 1
+(rest v)                   ;=> (2 3)
+```
+
+`vec` builds a persistent vector. `[1 2 3]` in Jerboa is just `(1 2 3)` — a list, not a vector.
+
+### 7. Sets
+
+```clojure
+;; Clojure
+(def s #{1 2 3})
+(conj s 4)              ;=> #{1 2 3 4}
+(disj s 2)              ;=> #{1 3}
+(contains? s 2)         ;=> true
+(clojure.set/union s #{4 5})
+(clojure.set/intersection s #{2 3 4})
+```
+
+```scheme
+;; Jerboa
+(def s (hash-set 1 2 3))
+(conj s 4)              ;=> persistent set with 1 2 3 4
+(disj s 2)              ;=> persistent set with 1 3
+(contains? s 2)         ;=> #t
+(union s (hash-set 4 5))
+(intersection s (hash-set 2 3 4))
+```
+
+`union`, `intersection`, `difference`, `subset?`, and `superset?` are all available. The full `clojure.set` relational algebra (`set-select`, `set-project`, `set-rename`, `set-index`, `set-join`, `map-invert`) is included.
+
+### 8. Atoms
+
+```clojure
+;; Clojure
+(def counter (atom 0))
+(swap! counter inc)
+(reset! counter 42)
+@counter                ;=> 42
+(add-watch counter :log (fn [k r old new] (println old "->" new)))
+```
+
+```scheme
+;; Jerboa
+(def counter (atom 0))
+(swap! counter inc)
+(reset! counter 42)
+(deref counter)          ;=> 42
+(add-watch! counter log: (lambda (k r old new) (println old "->" new)))
+```
+
+`compare-and-set!` is also available. No `@` reader macro — use `deref`.
+
+### 9. loop / recur
+
+```clojure
+;; Clojure
+(loop [i 0 acc []]
+  (if (= i 5)
+    acc
+    (recur (inc i) (conj acc i))))
+```
+
+```scheme
+;; Jerboa
+(loop ([i 0] [acc '()])
+  (if (= i 5)
+    (reverse acc)
+    (recur (+ i 1) (cons i acc))))
+```
+
+`loop`/`recur` exist for familiarity. But Chez has proper tail calls, so a plain named `let` loop is idiomatic and equally efficient:
+
+```scheme
+(let lp ([i 0] [acc '()])
+  (if (= i 5) (reverse acc) (lp (+ i 1) (cons i acc))))
+```
+
+### 10. Destructuring
+
+```clojure
+;; Clojure
+(let [{:keys [name age]} person]
+  (println name age))
+```
+
+```scheme
+;; Jerboa
+(dlet ([(keys: name age) person])
+  (println name age))
+```
+
+`dlet` supports list destructuring, `&` rest, map `keys:` lookup, `as:` binding, and `or:` defaults:
+
+```scheme
+(dlet ([(a b & rest) '(1 2 3 4 5)]
+       [(keys: x y or: ([y 99])) some-map])
+  (println a b rest x y))
+```
+
+`dfn` defines a function with destructured parameters.
+
+### 11. Pattern Matching
+
+```clojure
+;; Clojure (core.match)
+(match [x]
+  [1] "one"
+  [(:or 2 3)] "two or three"
+  :else "other")
+```
+
+```scheme
+;; Jerboa (built-in)
+(match x
+  (1 "one")
+  ((or 2 3) "two or three")
+  (_ "other"))
+```
+
+`match` is in the prelude. Supports literals, list/cons destructuring, predicates `(? number?)`, guards `(n (where (> n 0)))`, view patterns `(=> string->number n)`, and `and`/`or` combinators.
+
+### 12. Lazy Sequences
+
+```clojure
+;; Clojure
+(take 5 (iterate inc 0))      ;=> (0 1 2 3 4)
+(take 3 (cycle [1 2 3]))      ;=> (1 2 3)
+(take 3 (repeat 42))          ;=> (42 42 42)
+(->> (range) (filter even?) (take 5))
+```
+
+```scheme
+;; Jerboa
+(lazy->list (lazy-take 5 (iterate inc 0)))   ;=> (0 1 2 3 4)
+(lazy->list (lazy-take 3 (cycle '(1 2 3))))  ;=> (1 2 3)
+(lazy->list (lazy-take 3 (repeat 42)))        ;=> (42 42 42)
+(doall (lazy-take 5 (lazy-filter even? (lazy-range 0 +inf.0 1))))
+```
+
+`iterate` and `repeat` return infinite lazy sequences. `cycle`, `lazy-map`, `lazy-filter`, `lazy-take`, `lazy-drop`, `lazy-concat`, `lazy-interleave`, `lazy-mapcat`, `lazy-partition` — the full suite is available. Use `doall` to force a lazy seq into a list, or `lazy->list`.
+
+### 13. Transducers
+
+Transducers are available via `(std transducer)`:
+
+```scheme
+(require '(std transducer) :refer (sequence transduce map-xf filter-xf take-xf compose-xf))
+
+(sequence (compose-xf (filter-xf even?) (map-xf inc) (take-xf 3))
+          (range 10))
+;=> (1 3 5)
+```
+
+Channels accept transducers directly — see core.async below.
+
+### 14. core.async
+
+```clojure
+;; Clojure
+(require '[clojure.core.async :as async :refer [go chan <! >! alts! timeout]])
+(let [c (chan 10)]
+  (go (>! c 42))
+  (go (println (<! c))))
+```
+
+```scheme
+;; Jerboa
+(require '(std csp clj) :as async)
+
+(let ([c (async:chan 10)])
+  (async:go (async:>! c 42))
+  (async:go (println (async:<! c))))
+```
+
+Or import names directly:
+
+```scheme
+(require '(std csp clj) :refer (go chan <! >! alt! timeout close!))
+
+(let ([c (chan 10)])
+  (go (>! c 42))
+  (go (println (<! c))))
+```
+
+Full `core.async` surface: `go`, `go-loop`, `chan`, `<!`, `>!`, `<!!`, `>!!`, `close!`, `alt!`, `alts!`, `timeout`, `pipe`, `mult`, `tap`, `pub`, `sub`, `merge`, `split`, `pipeline`, `sliding-buffer`, `dropping-buffer`, `promise-chan`, `to-chan`, `onto-chan`. When running inside a fiber runtime, `go` spawns lightweight fibers (~4KB) instead of OS threads.
+
+### 15. Dynamic Vars
+
+```clojure
+;; Clojure
+(def ^:dynamic *indent* 0)
+(binding [*indent* 2]
+  (println *indent*))
+```
+
+```scheme
+;; Jerboa
+(def-dynamic *indent* 0)
+(binding ([*indent* 2])
+  (println (*indent*)))
+```
+
+`def-dynamic` creates a Chez parameter. Access the value by calling it: `(*indent*)`. Dynamic bindings propagate to `clj-future` and `bound-fn` automatically.
+
+### 16. Protocols
+
+```clojure
+;; Clojure
+(defprotocol Shape
+  (area [this])
+  (perimeter [this]))
+
+(defrecord Circle [r])
+(extend-type Circle Shape
+  (area [c] (* Math/PI (.r c) (.r c)))
+  (perimeter [c] (* 2 Math/PI (.r c))))
+```
+
+```scheme
+;; Jerboa
+(require '(std protocol) :refer (defprotocol extend-type))
+
+(defprotocol Shape
+  (area     (self))
+  (perimeter (self)))
+
+(defstruct circle (r))
+(extend-type circle::t Shape
+  (area     (c) (* 3.14159 (circle-r c) (circle-r c)))
+  (perimeter (c) (* 2 3.14159 (circle-r c))))
+
+(area (make-circle 3))  ;=> 28.27...
+```
+
+Protocols dispatch on Chez record types (use `name::t`) or symbols for builtins (`'string`, `'pair`, `'number`, etc.).
+
+### 17. Multimethods
+
+```clojure
+;; Clojure
+(defmulti area :shape)
+(defmethod area :circle [{:keys [r]}] (* Math/PI r r))
+(defmethod area :default [s] (throw (ex-info "Unknown" {:shape s})))
+```
+
+```scheme
+;; Jerboa
+(require '(std multi) :refer (defmulti defmethod))
+
+(defmulti area (lambda (shape) (get shape shape:)))
+(defmethod area 'circle (s) (* 3.14159 (get s r:) (get s r:)))
+(defmethod area 'default (s) (raise (ex-info "Unknown" (hash-map shape: s))))
+```
+
+Dispatch values are compared with `equal?` — any value works: symbols, strings, numbers, lists.
+
+### 18. Error Handling
+
+```clojure
+;; Clojure
+(try
+  (throw (ex-info "bad input" {:code 400}))
+  (catch Exception e
+    (println (ex-message e))
+    (println (ex-data e))))
+```
+
+```scheme
+;; Jerboa
+(try
+  (raise (ex-info "bad input" (hash-map code: 400)))
+  (catch (e)
+    (println (ex-message e))
+    (println (ex-data e))))
+```
+
+`ex-info`, `ex-data`, `ex-message`, and `ex-cause` work as expected. The `try`/`catch`/`finally` form catches any raised condition.
+
+### 19. Futures / Promises / Delays
+
+```clojure
+;; Clojure
+(def d (delay (expensive-computation)))
+(def f (future (long-running-task)))
+(def p (promise))
+(deliver p 42)
+@d  @f  @p
+```
+
+```scheme
+;; Jerboa
+(def d (clj-delay (expensive-computation)))
+(def f (clj-future (long-running-task)))
+(def p (clj-promise))
+(deliver p 42)
+(deref d)  (deref f)  (deref p)
+```
+
+`deref` is polymorphic: works on atoms, delays, futures, promises, and volatiles. `realized?` checks if a lazy seq, delay, future, or promise has been computed.
+
+### 20. Testing
+
+```clojure
+;; Clojure
+(deftest math-test
+  (is (= 4 (+ 2 2)))
+  (is (thrown? Exception (/ 1 0))))
+```
+
+```scheme
+;; Jerboa
+(import (std test))
+
+(def math-tests
+  (test-suite "math"
+    (test-case "addition"
+      (check (+ 2 2) => 4))
+    (test-case "division by zero"
+      (check-exception (/ 1 0)))))
+
+(run-tests! math-tests)
+```
+
+Uses `check` with `=>` for equality, `check-predicate` for predicates, and `check-exception` for expected errors.
+
+## What's Different and Why
+
+### Brackets are just parens
+`[1 2 3]` is the same as `(1 2 3)` — a list, not a vector. Use `(vec '(1 2 3))` or `(vec 1 2 3)` for persistent vectors.
+
+### Keywords end with a colon
+Jerboa: `name:`, `age:`. Clojure: `:name`, `:age`. The trailing colon is consistent with Gerbil Scheme.
+
+### No Java interop
+There is no `.method` syntax and no `import` for Java classes. Jerboa compiles to native code via Chez Scheme. For system interop, use FFI to C or Rust.
+
+### `#t` / `#f` instead of `true` / `false`
+Scheme booleans. `true?` and `false?` predicates exist. Everything except `#f` is truthy (including `0`, `""`, and `'()`).
+
+### `nil` is `#f`
+Clojure's `nil` maps to `#f`. `nil?` checks for `#f`. `seq` returns `#f` for empty collections, not `nil`.
+
+### Proper tail calls replace `recur`
+Every function in Jerboa has proper tail calls. You don't need `recur` to avoid stack overflow — any self-call in tail position is optimized. `loop`/`recur` exist for readability and familiarity.
+
+### No literal syntax for data structures
+No `{}`, `#{}`, or `[]` literals. Use `hash-map`, `hash-set`, `vec`, `list`.
+
+### `assoc` means different things
+Chez Scheme's built-in `assoc` does alist lookup. The `(jerboa clojure)` import shadows it with Clojure's `assoc` (map update). If you need alist lookup, use `aget` or `agetv`.
+
+## What to Reach For Instead of Java Interop
+
+| Java / Clojure Library | Jerboa Module | Import |
+|---|---|---|
+| HTTP client | `(std net request)` | `(require '(std net request) :as http)` |
+| HTTP server | `(std net httpd)` | `(require '(std net httpd) :as httpd)` |
+| JSON | Built-in | `read-json`, `write-json`, `string->json-object` |
+| SQLite | `(std db sqlite)` | `(require '(std db sqlite) :as db)` |
+| PostgreSQL | `(std db postgres)` | `(require '(std db postgres) :as pg)` |
+| Crypto / hashing | `(std crypto digest)` | `(require '(std crypto digest) :as crypto)` |
+| Regex | Built-in | `re`, `re-match?`, `re-find-all`, `re-replace` |
+| File I/O (slurp/spit) | `(std clojure io)` | `(require '(std clojure io) :refer (slurp spit))` |
+| clojure.string | Built-in (prefixed) | `str/trim`, `str/split`, `str/join`, etc. |
+| Logging | `(std logger)` | `(require '(std logger) :as log)` |
+| core.async | `(std csp clj)` | `(require '(std csp clj) :refer (go chan <! >!))` |
+| core.logic | Built-in | `run*`, `fresh`, `conde`, `==` |
+| clojure.spec | Built-in | `s-def`, `s-valid?`, `s-conform`, `s-explain` |
+| Transit | Built-in | `transit-write`, `transit-read` |
+| Datafy/Nav | Built-in | `datafy`, `nav` |
+| test.check (property) | `(std proptest)` | `(require '(std proptest) :as pt)` |
+
+## Project Structure
+
+```
+my-project/
+  lib/              ;; your modules go here
+    my/
+      app.sls       ;; (library (my app) ...)
+      util.sls
+  main.ss           ;; entry point: (import (jerboa clojure)) ...
+  tests/
+    test-app.ss     ;; (import (std test)) ...
+  Makefile
+```
+
+A minimal `Makefile`:
+
+```makefile
+SCHEME = scheme
+LIBDIRS = lib:path/to/jerboa/lib
+
+run:
+	$(SCHEME) --libdirs $(LIBDIRS) --script main.ss
+
+test:
+	$(SCHEME) --libdirs $(LIBDIRS) --script tests/test-app.ss
+```
+
+## Known Gotchas
+
+**Forgetting the import.** There is no `ns` form. Every `.ss` file needs `(import (jerboa clojure))` at the top. Without it, nothing works.
+
+**Using `:keyword` instead of `keyword:`.** Jerboa keywords trail: `name:` not `:name`. The reader converts `name:` to a keyword object.
+
+**Expecting `[1 2 3]` to be a vector.** Brackets are just parentheses. `[1 2 3]` evaluates `1` as a procedure applied to `2` and `3`. Use `(vec '(1 2 3))`.
+
+**`nil` is `#f`.** There is no separate nil value. Empty list `'()` is *not* nil/falsy. `(if '() "truthy" "falsy")` returns `"truthy"`. Test emptiness with `(empty? coll)` or `(seq coll)`.
+
+**`assoc` shadows Chez's `assoc`.** If you import `(jerboa clojure)`, `assoc` means "update a map key" (Clojure semantics), not "lookup in an alist" (Chez semantics). For alist lookup, use `aget`.
+
+**`deref` instead of `@`.** There is no `@` reader macro. Use `(deref atom-or-future)` or call `(*my-dynamic-var*)` for dynamic vars.
+
+**`clj-delay` / `clj-future` / `clj-promise` instead of `delay` / `future` / `promise`.** The `clj-` prefix avoids conflict with Chez Scheme builtins. The `deref` and `realized?` functions are not prefixed.
+
+**Keywords as function arguments.** The `require` macro uses `:as` and `:refer` with a leading colon (matching Clojure syntax). But in data, keywords trail: `name:`, not `:name`. This is the one place where Jerboa deliberately uses Clojure-style leading-colon keywords.
+
+**No implicit `str` on `println` args.** `(println 1 "hello" 'sym)` works — it calls `display` on each arg. But if you need string interpolation, use `(str "count: " n)` explicitly.
diff --git a/lib/jerboa/clojure.sls b/lib/jerboa/clojure.sls
new file mode 100644
index 0000000..f16cc7b
--- /dev/null
+++ b/lib/jerboa/clojure.sls
@@ -0,0 +1,478 @@
+#!chezscheme
+;;; (jerboa clojure) — Single-import Clojure experience
+;;;
+;;; (import (jerboa clojure)) gives you the ENTIRE Jerboa API plus
+;;; every Clojure-compatibility module:
+;;;
+;;;   - The full (jerboa prelude) — macros, runtime, iterators, etc.
+;;;   - (std clojure) — polymorphic collections, persistent data, atoms,
+;;;     lazy seqs, loop/recur, destructuring, dynamic vars, etc.
+;;;   - (std datafy) — datafy/nav protocols
+;;;   - (std logic) — miniKanren (core.logic)
+;;;   - (std spec) — composable validation (clojure.spec)
+;;;   - (std transit) — Transit wire format
+;;;   - (std clojure seq) — unified seq-* operations
+;;;   - (std clojure string) — clojure.string (prefixed str/)
+;;;   - (std clojure reducers) — parallel reducers
+;;;
+;;; Conflict resolution: when the prelude and (std clojure) export the
+;;; same name, the (std clojure) version wins (it re-exports from the
+;;; same underlying modules, so semantics are identical).
+
+(library (jerboa clojure)
+  (export
+    ;; ================================================================
+    ;; (jerboa prelude) — everything EXCEPT names also in (std clojure)
+    ;; ================================================================
+
+    ;; ---- Core macros ----
+    def def* defrule defrules
+    defstruct defclass defmethod
+    match match/strict
+    define-match-type define-sealed-hierarchy define-active-pattern
+    try catch finally
+    while until
+
+    ;; hash constructors
+    hash-literal hash-eq-literal
+    let-hash
+
+    ;; ---- Runtime ----
+    ~ bind-method! call-method
+    make-hash-table make-hash-table-eq
+    hash-ref hash-get hash-put! hash-update! hash-remove!
+    hash-key? hash->list hash->plist hash-for-each hash-map hash-fold
+    hash-find hash-keys hash-values hash-copy hash-clear!
+    hash-merge hash-merge! hash-length hash-table?
+    list->hash-table plist->hash-table
+    keyword? keyword->string string->keyword make-keyword
+    error-message error-irritants error-trace
+    displayln 1+ 1-
+    iota last-pair
+    *method-tables*
+    register-struct-type! *struct-types*
+    struct-predicate struct-field-ref struct-field-set!
+    struct-type-info
+
+    ;; ---- std/sort ----
+    sort sort! stable-sort stable-sort!
+
+    ;; ---- std/format ----
+    format printf fprintf eprintf
+
+    ;; ---- std/error ----
+    Error ContractViolation
+
+    ;; ---- std/sugar ----
+    chain chain-and assert!
+    unwind-protect with-id with-lock with-catch
+    cut cute <> <...>
+    awhen aif when-let if-let
+    -> ->> as-> some-> some->> cond-> cond->>
+    ->? ->>?
+    with-resource str alist defn defrecord
+    let-alist define-enum capture dotimes define-values
+
+    ;; ---- std/text/json ----
+    read-json write-json json-object->string string->json-object
+
+    ;; ---- std/os/path ----
+    path-expand path-normalize path-directory path-strip-directory
+    path-extension path-strip-extension
+    path-join path-absolute?
+
+    ;; ---- std/regex ----
+    re re?
+    re-match? re-search
+    re-find-all re-groups
+    re-replace re-replace-all
+    re-split re-fold
+    re-match-full re-match-group re-match-groups
+    re-match-start re-match-end re-match-named
+
+    ;; ---- std/rx ----
+    rx define-rx
+
+    ;; ---- std/misc/string ----
+    string-split string-join string-trim
+    string-prefix? string-suffix?
+    string-contains string-index
+    string-empty?
+    string-match? string-find string-find-all
+
+    ;; ---- std/misc/list ----
+    flatten unique snoc
+    take drop
+    every any
+    filter-map
+    group-by
+    zip
+    frequencies
+    partition partition-all partition-by
+    interleave interpose
+    mapcat
+    distinct
+    keep
+    some
+    iterate-n
+    reductions
+    take-last drop-last
+    split-at split-with
+    ;; Gerbil v0.19 compat
+    append-map append1 flatten1
+    push! pop!
+    for-each!
+    take-while take-until drop-while drop-until
+    butlast slice split
+    length=? length<? length<=? length>? length>=?
+    length=n? length<n? length<=n? length>n? length>=n?
+    group-consecutive group-n-consecutive group-same
+    rassoc every-consecutive?
+    map/car first-and-only when/list
+    with-list-builder call-with-list-builder
+    duplicates delete-duplicates/hash
+
+    ;; ---- std/misc/alist ----
+    agetq agetv aget
+    asetq! asetv! aset!
+    pgetq pgetv pget
+    alist->hash-table
+    ;; Gerbil v0.19 compat
+    alist? acons
+    asetq asetv aset
+    aremq aremv arem
+    aremq! aremv! arem!
+    psetq psetv pset
+    psetq! psetv! pset!
+    premq premv prem
+    premq! premv! prem!
+    plist->alist* alist->plist*
+
+    ;; ---- std/misc/ports ----
+    read-all-as-string read-all-as-lines
+    read-file-string read-file-lines
+    write-file-string
+    with-input-from-string with-output-to-string
+
+    ;; ---- std/misc/func (only names NOT in (std clojure)) ----
+    compose compose1 identity constantly flip
+    curry curryn negate conjoin disjoin
+    memo-proc juxt
+    partial complement comp
+
+    ;; ---- std/iter ----
+    for for/collect for/fold for/or for/and
+    in-list in-vector in-range in-string
+    in-hash-keys in-hash-values in-hash-pairs
+    in-naturals in-indexed
+    in-port in-lines in-chars in-bytes in-producer
+
+    ;; ---- std/result ----
+    ok err
+    ok? err? result?
+    unwrap unwrap-err unwrap-or unwrap-or-else
+    map-ok map-err
+    and-then or-else
+    flatten-result
+    result->values
+    try-result try-result*
+    result->option
+    results-partition
+    map-results
+    filter-ok filter-err
+    sequence-results
+    ok->list err->list
+
+    ;; ---- std/datetime ----
+    make-datetime datetime?
+    make-date make-time
+    datetime-now datetime-utc-now
+    datetime-year datetime-month datetime-day
+    datetime-hour datetime-minute datetime-second
+    datetime-nanosecond datetime-offset
+    parse-datetime parse-date parse-time
+    datetime->string date->string time->string
+    datetime->iso8601
+    datetime->epoch epoch->datetime
+    datetime->julian julian->datetime
+    datetime-add datetime-subtract
+    datetime-diff
+    duration duration? duration-seconds duration-nanoseconds
+    make-duration
+    datetime<? datetime>? datetime=? datetime<=? datetime>=?
+    datetime-min datetime-max datetime-clamp
+    day-of-week day-of-year days-in-month leap-year?
+    datetime->alist
+    datetime-truncate
+    datetime-floor-hour datetime-floor-day datetime-floor-month
+
+    ;; ---- std/debug/pp ----
+    pp pp-to-string pprint
+    ppd ppd-to-string
+
+    ;; ---- std/csv ----
+    read-csv read-csv-file csv-port->rows
+    write-csv write-csv-file rows->csv-string
+    csv->alists alists->csv
+
+    ;; ---- FFI ----
+    c-lambda define-c-lambda
+    begin-ffi c-declare
+
+    ;; ---- std/ergo ----
+    using : maybe list-of?
+
+    ;; ---- std/misc/shared ----
+    make-shared shared? shared-ref shared-set!
+    shared-update! shared-cas! shared-swap!
+
+    ;; ---- AI compatibility aliases ----
+    hash-has-key? hash-table-set!
+    directory-exists?
+    eql?
+    random-integer
+    read-line
+    force-output
+    string-map
+    regex-match regex-search regex-replace regex-replace-all
+
+    ;; ================================================================
+    ;; (std clojure) — Clojure compatibility layer (wins on conflicts)
+    ;; ================================================================
+
+    ;; ---- Polymorphic collection ops ----
+    get assoc dissoc contains? count keys vals
+    merge merge-with update select-keys
+    zipmap reduce-kv min-key max-key
+    first rest next last
+    conj cons* empty?
+    peek pop
+    reduce into range
+    seq =? hash
+    inc dec
+    nil? some? true? false?
+
+    ;; ---- Functional combinators (re-exports + Clojure additions) ----
+    memoize iterate repeatedly fnil
+    every-pred some-fn
+
+    ;; ---- Sugar macros ----
+    doto
+    loop recur
+    require
+
+    ;; ---- Destructuring (Clojure-style) ----
+    dlet dfn
+
+    ;; ---- Dynamic vars (Clojure-style binding) ----
+    def-dynamic binding
+    bound-fn capture-dynamic-bindings apply-dynamic-bindings
+
+    ;; ---- Structured exceptions (ex-info / ex-data) ----
+    ex-info ex-info? ex-data ex-message ex-cause
+
+    ;; ---- Transients ----
+    transient persistent! transient?
+    assoc! dissoc! conj!
+
+    ;; ---- Sets ----
+    hash-set set set?
+    disj
+    union intersection difference subset? superset?
+    ;; Set relational ops
+    set-select set-project set-rename set-index set-join
+    map-invert
+
+    ;; ---- Constructors ----
+    hash-map vec list* vector*
+    make-hash-set
+
+    ;; ---- Printing ----
+    println prn pr pr-str prn-str
+
+    ;; ---- Re-exports from (std immutable) ----
+    imap imap? imap-set imap-ref imap-has?
+    imap=? imap-hash
+    in-imap in-imap-pairs in-imap-keys in-imap-values
+    ivec ivec-set ivec-ref ivec-length
+    ;; ---- Re-exports from (std pmap) ----
+    persistent-map?
+    ;; ---- Re-exports from (std pset) ----
+    persistent-set persistent-set?
+    persistent-set-contains? persistent-set->list
+    persistent-set-hash in-pset
+
+    ;; ---- Re-exports from (std misc atom) ----
+    atom atom? reset! swap! compare-and-set!
+    add-watch! remove-watch!
+    volatile! volatile? vreset! vswap! vderef
+
+    ;; ---- Delay / Future / Promise ----
+    clj-delay delay? clj-force
+    clj-future future? future-cancel future-cancelled? future-done?
+    clj-promise promise? deliver
+    deref
+
+    ;; ---- Re-exports from (std misc meta) ----
+    with-meta meta vary-meta meta-wrapped? strip-meta
+
+    ;; ---- Re-exports from (std misc nested) ----
+    get-in assoc-in update-in
+
+    ;; ---- Re-exports from (std pqueue) ----
+    persistent-queue pqueue-empty pqueue?
+    pqueue-conj pqueue-peek pqueue-pop
+    pqueue-count pqueue->list
+    pqueue-empty? list->pqueue
+
+    ;; ---- Re-exports from (std sorted-set) ----
+    sorted-set sorted-set-by sorted-set?
+    sorted-set-empty
+    sorted-set-add sorted-set-remove
+    sorted-set-contains? sorted-set-size
+    sorted-set-min sorted-set-max
+    sorted-set-range sorted-set->list
+    sorted-set-fold
+
+    ;; ---- Lazy sequences ----
+    lazy-cons lazy-first lazy-rest lazy-nil lazy-nil? lazy-seq? lazy-force
+    lazy-map lazy-filter lazy-take lazy-drop lazy-take-while lazy-drop-while
+    lazy-zip lazy-append lazy-flatten lazy-range lazy-iterate lazy-repeat
+    lazy-cycle lazy->list list->lazy lazy-for-each lazy-fold lazy-count
+    lazy-any? lazy-all? lazy-nth lazy-concat lazy-interleave lazy-mapcat
+    lazy-interpose lazy-realize lazy-realized? lazy-partition lazy-chunk
+    ;; Clojure-named wrappers
+    cycle repeat doall dorun realized?
+
+    ;; ---- Prelude extras not in (std clojure) ----
+    ;; assoc-in! and update-in! are mutable variants from prelude's
+    ;; (std misc nested) re-export that (std clojure) does not provide.
+    assoc-in! update-in!
+    nested-get nested-empty-like
+
+    ;; ================================================================
+    ;; (std datafy) — datafy/nav protocols
+    ;; ================================================================
+    Datafiable Navigable
+    datafy nav
+
+    ;; ================================================================
+    ;; (std logic) — miniKanren core.logic
+    ;; ================================================================
+    == run run* fresh conde conda condu
+    succeed fail
+    conso caro cdro nullo pairo
+    appendo membero
+    absento
+    lvar lvar? reify
+
+    ;; ================================================================
+    ;; (std spec) — composable validation
+    ;; ================================================================
+    s-def s-get-spec
+    s-pred s-and s-or s-keys s-keys-opt
+    s-cat s-coll-of s-map-of
+    s-nilable s-tuple s-enum
+    s-int-in s-double-in
+    s-valid? s-conform s-explain s-explain-str s-assert
+    s-fdef s-check-fn
+    s-exercise
+
+    ;; ================================================================
+    ;; (std transit) — Transit wire format
+    ;; ================================================================
+    transit-write transit-read
+    transit->string string->transit
+    transit-encode transit-decode
+    transit-keyword transit-keyword?
+    transit-symbol transit-symbol?
+    transit-uuid transit-uuid?