Update Jerboa MCP knowledge data

ober

e660064e107e20659c16fdf6c8ac1ce24b63e1b9

diff --git a/data/anti-patterns.sexp b/data/anti-patterns.sexp
index f1c80c9..44e3c37 100644
--- a/data/anti-patterns.sexp
+++ b/data/anti-patterns.sexp
@@ -5283,4 +5283,573 @@
    ("tools"
      "jerboa_check_balance"
      "jerboa_security_scan"
-     "jerboa_make")))
+     "jerboa_make"))
+ (("advice"
+    .
+    "For bool storage, return #t/#f from element kernels when using storage-set!, or write raw bytes with bytevector-u8-set! directly. Add smoke coverage for both true and false rows, not only true/null rows.")
+   ("avoid"
+     .
+     "Do not assume 0 is false in Jerboa/Chez. In Scheme only #f is false, so (if 0 1 0) style values become true when routed through boolean conversion helpers.")
+   ("id" . "scheme-bool-storage-numeric-false")
+   ("kinds"
+     "kernel-generation"
+     "vector-storage"
+     "compiler-runtime")
+   ("pattern"
+     .
+     "Generated or hand-written bool-storage kernels return numeric 1/0 and pass the value to storage-set! for storage class 'bool.")
+   ("severity" . "high")
+   ("tags" "chezscheme" "truthiness" "bool" "storage-set"
+     "kernels" "bytevector")
+   ("title"
+     .
+     "Do not write numeric 0 through bool storage setters")
+   ("tools"
+     "jerboa_howto"
+     "jerboa_check_balance"
+     "jerboa_compile_check"))
+ (("advice"
+    .
+    "Thread the left/right storage classes into fallback kernels and call (storage-ref ls ld i) and (storage-ref rs rd i). Add smoke coverage for non-specialized operators, such as <=, >=, =, and <> over fxvector columns, not only the specialized < path.")
+   ("avoid"
+     .
+     "Do not write generic vector fallbacks that assume boxed backing storage after dispatch has already accepted fx, fl, or bool storage classes.")
+   ("id" . "generic-kernel-storage-class-mismatch")
+   ("kinds"
+     "kernel-generation"
+     "vector-storage"
+     "compiler-runtime")
+   ("pattern"
+     .
+     "A generic fallback kernel handles non-boxed inputs but calls (storage-ref 'boxed data i), causing vector-ref on fxvector/flvector or silently using the wrong representation.")
+   ("severity" . "high")
+   ("tags" "duckdb" "kernels" "fxvector" "flvector" "boxed"
+     "storage-ref" "fallback")
+   ("title"
+     .
+     "Generic vector kernels must read with the actual storage class")
+   ("tools"
+     "jerboa_howto"
+     "jerboa_check_balance"
+     "jerboa_compile_check"))
+ (("advice"
+    .
+    "Until Rust borrow-aware Bytes call lowering lands, keep parity fixtures' bytevector mutations directly in the function that owns the local buffer, or implement function signatures/call sites that pass mutable Bytes by borrow without cloning.")
+   ("avoid"
+     .
+     "Do not assume a Typed Jerboa function with a `Bytes` parameter and `#:effects (mut)` mutates the caller's buffer through the current Rust backend when called from another typed function.")
+   ("id" . "typed-rust-mutable-bytes-helper-clones")
+   ("kinds" "test" "debug-error")
+   ("pattern"
+     .
+     "bytevector-u8-set!.*helper|typed-llvmir-parity: rust=1 llvm=42|add_bang\\(\\(bits\\)\\.clone\\(\\)")
+   ("severity" . "medium")
+   ("tags" "typed" "rust" "Bytes" "mutation" "parity" "clone")
+   ("title"
+     .
+     "Typed Rust mutable Bytes helper calls clone instead of mutating caller")
+   ("tools"
+     "jerboa_check_balance"
+     "jerboa_make typed-llvmir-parity"
+     "typed Rust generated source inspection"))
+ (("advice"
+    .
+    "For SQL literal classification and scalar casts, check flonum? first, or preserve the token spelling to distinguish decimal/exponent literals. Convert flonums to exact integers before fxvector storage using the target engine's cast semantics.")
+   ("avoid"
+     .
+     "Do not assume integer? excludes flonums in Chez Scheme. Do not classify SQL decimal-looking literals using only integer? on the parsed number.")
+   ("id" . "chez-integer-p-before-flonum-p")
+   ("kinds" "runtime" "sql-engine" "numeric-casts")
+   ("pattern"
+     .
+     "Numeric classification branches on integer? before flonum?, then writes an integral flonum such as 2.0 into fxvector-backed storage.")
+   ("severity" . "high")
+   ("tags" "chez" "flonum" "integer" "numeric-literal"
+     "fxvector" "duckdb")
+   ("title"
+     .
+     "Checking integer? before flonum? misclassifies integral flonums")
+   ("tools" "jerboa_eval" "jerboa_verify" "jerboa_howto"))
+ (("advice"
+    .
+    "When either input storage is boxed, use boxed output for +, -, *, //, and %. Keep / as fl because DuckDB integer division with / returns DOUBLE. Rebuild compiled .so files before validating the fix.")
+   ("avoid"
+     .
+     "Do not choose flvector output only because an arithmetic operation is not fx/fx. Boxed integer, HUGEINT, DECIMAL, or aggregate values can produce exact results that must remain boxed.")
+   ("id" . "boxed-arithmetic-flvector-output")
+   ("kinds" "runtime" "sql-engine" "vector-kernels")
+   ("pattern"
+     .
+     "A generic arithmetic path with one boxed input chooses fl output storage, then writes exact integer results into an flvector.")
+   ("severity" . "high")
+   ("tags" "duckdb" "kernel" "boxed" "flvector" "aggregate"
+     "storage")
+   ("title"
+     .
+     "Boxed arithmetic results must not default to flvector output")
+   ("tools" "jerboa_verify" "jerboa_make" "jerboa_eval"))
+ (("advice"
+    .
+    "Generate a small adapter helper with the closure ABI, ignore the env pointer for top-level refs, call the direct function with only value arguments inside the adapter, and run executable LLVM/Rust parity for the fixture.")
+   ("avoid"
+     .
+     "Do not put direct typed function symbols into closure values unless the direct function already has the closure ABI `fn(ptr env, args...)`. `llvm-as` can still accept opaque-pointer indirect calls that will fail only in executable parity.")
+   ("id" . "llvm-closure-fnptr-direct-abi-mismatch")
+   ("kinds" "codegen" "debug-error" "test")
+   ("pattern"
+     .
+     "A top-level function reference stores a direct function symbol in a `{ptr, ptr}` closure value even though indirect `invoke` calls the pointer with an environment pointer first.")
+   ("severity" . "high")
+   ("tags" "typed" "llvmir" "closure" "function-ref" "ABI"
+     "opaque-ptr" "parity")
+   ("title"
+     .
+     "LLVM closure values need closure-ABI function pointers")
+   ("tools"
+     "jerboa_check_balance"
+     "jerboa_verify"
+     "jerboa_make typed-llvmir-parity"))
+ (("advice"
+    .
+    "Use parameter-aware emission: Borrow/MutBorrow become references, function values move, scalar/Copy args and temporaries pass without clone, explicit Owned non-temporaries clone, and non-scalar locals keep clone until the checker has broader move/liveness information. Always compile the generated Rust crate after emitter changes.")
+   ("avoid"
+     .
+     "Do not implement borrow-aware argument emission as a blanket no-clone rule for all non-Borrow params. Current typed move tracking only covers explicit Owned values; ordinary record/variant values may still be reused by typed code.")
+   ("id"
+     .
+     "typed-rust-nonscalar-local-move-after-clone-removal")
+   ("kinds" "codegen" "debug-error" "test")
+   ("pattern"
+     .
+     "Removing `(expr).clone()` from every Typed Rust direct-call argument makes generated Rust fail with E0382 `use of moved value` when a non-Copy record/variant local is passed by value and then reused later in the same expression.")
+   ("severity" . "high")
+   ("tags" "typed" "rust" "clone" "borrow-aware" "E0382" "move"
+     "argument-emission")
+   ("title"
+     .
+     "Rust clone removal must preserve non-scalar local reuse")
+   ("tools"
+     "jerboa_check_balance"
+     "jerboa_verify"
+     "jerboa_make test-typed-rust"
+     "cargo build in build/typed/rust"))
+ (("advice"
+    .
+    "Use a dedicated source list such as TYPED_LLVMIR_LEAK_SOURCES for whole-program checks, default it to one parity/smoke fixture, and expand it only to modules with unique exported function names or after the generated C main shim is configurable.")
+   ("avoid"
+     .
+     "Do not feed the entire typed LLVM fixture list to --whole-program when several sample modules export a zero-arg main; the emitter generates both the mangled typed entry and a C @main shim, so duplicate main definitions can stop leak-check or link harness work before it tests allocator behavior.")
+   ("id" . "typed-llvmir-whole-program-duplicate-main")
+   ("kinds" "build tooling" "typed llvmir" "test harness")
+   ("pattern"
+     .
+     "typed-llvmir\\.ss --whole-program .*TYPED_LLVMIR_SOURCES|duplicate function name across modules.*main")
+   ("severity" . "medium")
+   ("tags" "typed" "llvmir" "whole-program" "main" "fixtures"
+     "leak-check")
+   ("title"
+     .
+     "Do not whole-program link every typed LLVM sample fixture blindly")
+   ("tools"
+     "jerboa_howto"
+     "jerboa_verify"
+     "typed-llvmir-check"))
+ (("advice"
+    .
+    "When a convenience target forwards to another make target, pass all documented override variables explicitly on the recursive $(MAKE) command line, especially strict/fail-mode flags, source lists, entry symbols, and expected results. Add a negative probe for strict/fail mode after wiring the target.")
+   ("avoid"
+     .
+     "Do not assume a wrapper target that invokes recursive make will preserve every user-facing mode variable in the way the nested recipe observes it. A strict-mode probe can silently run with the nested target's default value and produce a false green report.")
+   ("id" . "recursive-make-wrapper-must-forward-mode-vars")
+   ("kinds" "build tooling" "test harness" "makefile")
+   ("pattern"
+     .
+     "\\$\\(MAKE\\).*typed-llvmir-check.*TYPED_LLVMIR_LEAK_CHECK=1|wrapper target.*recursive make.*strict")
+   ("severity" . "medium")
+   ("tags" "make" "recursive-make" "variables" "strict-mode"
+     "typed" "leak-check")
+   ("title"
+     .
+     "Recursive Make wrapper targets must forward mode variables explicitly")
+   ("tools"
+     "make typed-llvmir-leak-check TYPED_LLVMIR_LEAK_STRICT=true"
+     "git diff --check"))
+ (("advice"
+    .
+    "Free only owned Bytes with a proven lexical owner. Current safe slice: direct bytes-build or same-module Bytes-returning function-call bindings in scalar-result let/var scopes, plus builder header free after bytes-builder->bytes transfers data ownership. Add ownership-qualified parameter/result types before generic temporary cleanup.")
+   ("avoid"
+     .
+     "Do not free every temporary Bytes argument after a function call just because the argument expression returned Bytes. The current Typed Jerboa surface can express a callee that returns a Bytes parameter unchanged, so blindly freeing the argument can turn the returned value into a use-after-free.")
+   ("id"
+     .
+     "typed-llvmir-freeing-buffer-call-temporaries-is-unsound")
+   ("kinds" "codegen" "memory-management" "typed llvmir")
+   ("pattern"
+     .
+     "free.*lower-function-call.*Bytes|owned buffer temporary.*function call.*free")
+   ("severity" . "high")
+   ("tags" "typed" "llvmir" "Bytes" "ownership" "free" "UAF")
+   ("title"
+     .
+     "Do not blindly free Typed LLVM IR Bytes call temporaries")
+   ("tools"
+     "jerboa_howto"
+     "jerboa_verify"
+     "make typed-llvmir-leak-check TYPED_LLVMIR_LEAK_STRICT=1"))
+ (("advice"
+    .
+    "Free only values with a proven lexical owner and a scope exit where the result cannot retain them. Current safe slice: direct owned Bytes bindings from bytes-build or same-module Bytes-returning calls, local lambda environment bindings, and local variant boxes from constructors or same-module variant-returning calls in scalar-result let/var scopes, plus builder header free after bytes-builder->bytes transfers data ownership. Add ownership-qualified parameter/result types before generic temporary cleanup.")
+   ("avoid"
+     .
+     "Do not free every temporary Bytes, closure, or variant argument after a function call just because the argument expression appears to allocate. The current Typed Jerboa surface can express callees that return or retain a passed value unchanged, so blindly freeing the argument can turn the returned value or later use into a use-after-free.")
+   ("id"
+     .
+     "typed-llvmir-freeing-owned-call-temporaries-is-unsound")
+   ("kinds" "codegen" "memory-management" "typed llvmir")
+   ("pattern"
+     .
+     "free.*lower-function-call.*(Bytes|closure|variant)|owned (buffer|closure|variant) temporary.*function call.*free")
+   ("severity" . "high")
+   ("tags" "typed" "llvmir" "Bytes" "closure" "variant"
+     "ownership" "free" "UAF")
+   ("title"
+     .
+     "Do not blindly free Typed LLVM IR owned call temporaries")
+   ("tools"
+     "jerboa_howto"
+     "jerboa_verify"
+     "make typed-llvmir-leak-check TYPED_LLVMIR_LEAK_STRICT=1"))
+ (("advice"
+    .
+    "For typed fuzz/property tests, use parser/checker invariants for the closure corpus unless the harness is explicitly switched to the full typed Rust crate driver. Keep executable backend parity in test-typed-rust, test-typed-llvmir, typed-llvmir-parity, and fixture-specific gates.")
+   ("avoid"
+     .
+     "Do not require every closure/function-ref fuzz corpus form to pass typed-library-form->rust-string. That helper is useful for simple single-form Rust emission properties, but it does not model every newer multi-stage typed pipeline path used by function refs and full crate generation.")
+   ("id"
+     .
+     "typed-fuzz-direct-rust-string-emitter-overclaims-closure-codegen")
+   ("kinds" "testing" "typed" "codegen")
+   ("pattern"
+     .
+     "typed-library-form->rust-string.*(lambda|invoke|function-ref).*fuzz|closure fixture.*direct Rust string emitter")
+   ("severity" . "medium")
+   ("tags" "typed" "fuzz" "rust" "closure" "function-ref"
+     "emitter")
+   ("title"
+     .
+     "Do not use the direct typed Rust string emitter as the only closure codegen proof")
+   ("tools"
+     "jerboa_howto"
+     "jerboa_check_balance"
+     "make test-typed-fuzz"
+     "make typed-test"))
+ (("advice"
+    .
+    "For executable Rust/LLVM parity fixtures that need owned extracted Bytes today, use bytes-build over the selected span, then run make typed-uri-pilot or typed-llvmir-parity. Save make-bytevector/copy-based slicing for a backend-lowering slice with dedicated LLVM tests.")
+   ("avoid"
+     .
+     "Do not use make-bytevector as the first implementation path for executable Typed LLVM fixture extraction unless typed-llvmir lowering has been verified for that call kind.")
+   ("id" . "typed-llvmir-make-bytevector-extraction")
+   ("kinds" "typed" "llvmir" "fixture" "backend")
+   ("pattern"
+     .
+     "Adding a Typed LLVM fixture helper that allocates Bytes with make-bytevector and fills/copies it, then assuming it will lower through typed-llvmir because checker tests know the primitive.")
+   ("severity" . "medium")
+   ("tags" "typed" "llvmir" "bytes" "make-bytevector"
+     "bytes-build" "uri")
+   ("title"
+     .
+     "Using make-bytevector for Typed LLVM extraction before lowering exists")
+   ("tools"
+     "jerboa_howto"
+     "jerboa_function_signature"
+     "jerboa_check_balance"
+     "typed-llvmir-parity"))
+ (("advice"
+    .
+    "In parity fixtures, compute whole-record checksums or calls before binding Bytes/String fields out of the record. If whole-record reuse after field extraction is needed as language behavior, add a backend/checker slice for borrow-aware record access instead of working around it silently.")
+   ("avoid"
+     .
+     "Do not move non-Copy record fields out of a typed record before all whole-record uses have completed, unless the emitter/checker has explicit borrow or clone semantics for that access.")
+   ("id" . "typed-rust-record-field-partial-move")
+   ("kinds" "typed" "rust" "fixture" "backend")
+   ("pattern"
+     .
+     "A Typed Jerboa fixture extracts Bytes fields from a record into locals and then later passes the original record to another function. Rust lowering turns the field access into a Vec move, so rustc reports E0382 borrow of partially moved value.")
+   ("severity" . "medium")
+   ("tags" "typed" "rust" "record" "bytes" "ownership"
+     "partial-move")
+   ("title"
+     .
+     "Moving non-Copy record fields before reusing the record in generated Rust")
+   ("tools"
+     "jerboa_check_balance"
+     "typed-llvmir-parity"
+     "jerboa_failure_advisor"))
+ (("advice"
+    .
+    "For current parity fixtures, inspect owned record fields through direct record accessors when the owning record remains the cleanup owner, and run typed-uri-pilot plus typed-llvmir-leak-suite in strict mode. For language work, add borrow-aware record accessor ownership semantics before allowing accessor-returned Bytes to be separately tracked as owned.")
+   ("avoid"
+     .
+     "Do not create a second owned local from an accessor over an owning record unless the record cleanup no longer owns that field or the access is explicitly borrowed/cloned in the backend model.")
+   ("id" . "typed-llvmir-record-accessor-alias-double-free")
+   ("kinds" "typed" "llvmir" "ownership" "fixture")
+   ("pattern"
+     .
+     "A scalar-returning Typed LLVM fixture binds a local record with owned Bytes fields, then binds a Bytes result from a same-module accessor function over that record. The backend tracks the accessor call result as an owned Bytes binding while scoped record cleanup also frees the original field, causing alias double-free or aborts under executable/leak checks.")
+   ("severity" . "high")
+   ("tags" "typed" "llvmir" "bytes" "record" "accessor"
+     "ownership" "double-free")
+   ("title"
+     .
+     "Treating record accessor Bytes results as separately owned while record cleanup owns the same field")
+   ("tools"
+     "jerboa_check_balance"
+     "typed-uri-pilot"
+     "typed-llvmir-leak-suite"
+     "jerboa_failure_advisor"))
+ (("advice"
+    .
+    "Have the typed-llvmir target clear generated .ll/.bc/.opt.bc files in TYPED_LLVMIR_DIR before regenerating, or manually clean that dedicated build directory before trusting typed-llvmir-check after fixture-list edits.")
+   ("avoid"
+     .
+     "Do not assume removing a fixture from TYPED_LLVMIR_SOURCES removes its previously generated .ll/.bc artifacts. The verifier loops over build/typed/llvmir/*.ll, so stale outputs can keep passing or failing after the source list changed.")
+   ("id" . "typed-llvmir-stale-generated-ir")
+   ("kinds" "build" "verification" "typed-llvmir")
+   ("pattern"
+     .
+     "TYPED_LLVMIR_SOURCES.*removed.*build/typed/llvmir|typed-llvmir-check.*\\*.ll.*stale")
+   ("severity" . "medium")
+   ("tags" "typed" "llvmir" "stale-artifact" "Makefile"
+     "fixtures")
+   ("title"
+     .
+     "Clean generated LLVM IR before changing fixture source lists")
+   ("tools" "jerboa_make" "jerboa_stale_static"))
+ (("advice"
+    .
+    "Run make typed-uri-bench before claiming M4 performance parity. If it fails, inspect the generated Rust source for owned Bytes clones through helper calls and fix ownership/borrow-aware emission before moving the typed URI fixture into the real std/net/uri path.")
+   ("avoid"
+     .
+     "Do not treat typed-uri-pilot plus typed-uri-diff as enough evidence that the URI replacement meets the M4 performance budget.")
+   ("id" . "typed-uri-parity-without-benchmark-budget")
+   ("kinds" "typed" "performance" "replacement-pilot")
+   ("pattern"
+     .
+     "typed-uri-pilot.*PASS|typed-uri-diff.*PASS|M4.*URI.*complete")
+   ("severity" . "high")
+   ("tags" "typed" "uri" "benchmark" "rust" "clone" "M4")
+   ("title"
+     .
+     "Claiming typed URI replacement readiness without the strict benchmark")
+   ("tools"
+     "jerboa_make typed-uri-bench"
+     "typed Rust generated source inspection"))
+ (("advice"
+    .
+    "Run jerboa_check_balance first. For typed-library source, validate with the typed-specific gates such as make typed-test, make typed-uri-pilot, make typed-uri-diff, make typed-llvmir-check, or support/typecheck.ss. Use jerboa_write_file or balanced_replace for the edit, but if verify:true follows the generic verifier false path, write only after a clean balance check and immediately run typed-specific verification.")
+   ("avoid"
+     .
+     "Do not repair balanced typed-library source by hand-counting closers just because generic jerboa_verify reports an invalid context for a later def. The same generic verifier path can reject existing typed-library fixtures even when the typed backend gates accept them.")
+   ("id"
+     .
+     "typed-library-standalone-verify-false-definition-context")
+   ("kinds" "typed-jerboa" "verification" "mcp-tooling")
+   ("pattern"
+     .
+     "jerboa_verify.*typed-library.*invalid context for definition|jerboa_write_file.*verification failed.*typed-library")
+   ("severity" . "medium")
+   ("tags" "typed-library" "jerboa_verify" "invalid-context"
+     "typecheck" "balanced-write" "typed-uri")
+   ("title"
+     .
+     "Treating generic jerboa_verify failure as proof a typed-library fixture is broken")
+   ("tools"
+     "jerboa_check_balance"
+     "jerboa_make typed-test"
+     "jerboa_make typed-uri-pilot"
+     "jerboa_make typed-llvmir-check"))
+ (("advice"
+    .
+    "Use parenthesized match clauses in file-backed typed fixtures: ((Some x) body), ((None) body), ((Case a b) body). Keep square-bracket examples limited to quoted checker unit forms unless the source-file parser path has been verified.")
+   ("avoid"
+     .
+     "Do not introduce square-bracket match clauses in tests/fixtures/typed/*.ss when validating through typed-rust, typed-llvmir, or typed-uri-pilot source-file paths.")
+   ("id" . "typed-fixture-square-match-clauses")
+   ("kinds" "typed" "tests" "source-fixture")
+   ("pattern"
+     .
+     "File-backed typed-library fixtures use square-bracket match clauses such as [(Some x) ...] and typed build gates report bad-match-pattern, even if quoted in-memory checker tests accepted the shape.")
+   ("severity" . "medium")
+   ("tags" "typed" "match" "fixture" "parser"
+     "bad-match-pattern")
+   ("title"
+     .
+     "Avoid square-bracket match clauses in file-backed typed fixtures")
+   ("tools"
+     "jerboa_check_balance"
+     "jerboa_verify"
+     "jerboa_make typed-uri-pilot"
+     "jerboa_make test-typed-checker"))
+ (("advice"
+    .
+    "Use the target's default benchmark settings for pass/fail claims. Short runs are acceptable only as compile/smoke checks, and any noisy failure must be rerun with the CI-shaped defaults before treating it as a regression.")
+   ("avoid"
+     .
+     "Do not validate a performance ratio gate by shrinking iterations or samples so far that timer noise dominates the measurement.")
+   ("id" . "under-sampled-benchmark-gate")
+   ("kinds" "test" "debug-error")
+   ("pattern"
+     .
+     "benchmark.*(iters|samples).*(1|10|small)|ratio=.*max=.*")
+   ("severity" . "medium")
+   ("tags" "benchmark" "perf" "ratio" "ci-gate" "noise")
+   ("title" . "Under-sampled benchmark gate")
+   ("tools" "jerboa_make"))
+ (("advice"
+    .
+    "Keep generated invalid cases to forms proven rejected by both sides, or split the test into strict-parser expectations and incumbent-compatibility expectations. Current known permissive areas include malformed number-like forms such as `1.`/`1e` and trailing-token cases parsed as the first value.")
+   ("avoid"
+     .
+     "Do not build a generated invalid JSON corpus from generic JSON-spec invalid templates and compare it directly against `(std text json)` without first checking incumbent behavior.")
+   ("id" . "json-diff-invalid-corpus-assumes-strict-incumbent")
+   ("kinds" "test" "module")
+   ("pattern"
+     .
+     "JSON differential tests that generate arbitrary malformed numbers, trailing tokens, or unterminated strings and expect `(std text json)` to reject them")
+   ("severity" . "medium")
+   ("tags" "json" "diff" "fuzz" "std-text-json"
+     "compatibility")
+   ("title"
+     .
+     "Do not assume std/text/json rejects every malformed JSON form")
+   ("tools"
+     "jerboa_howto"
+     "jerboa_eval"
+     "jerboa_security_scan"))
+ (("advice"
+    .
+    "For `(typed-library ...)` files, use balanced write/replace tools with balance verification, then validate through the typed toolchain targets such as `typed-rust`, `typed-llvmir-parity`, `typed-llvmir-check`, and the relevant suite gate.")
+   ("avoid"
+     .
+     "Do not repair balanced typed-library source by hand or rewrite top-level forms just because the generic Jerboa compile checker rejects the typed surface form.")
+   ("id"
+     .
+     "typed-library-generic-compile-check-false-positive")
+   ("kinds" "module" "test" "debug-error")
+   ("pattern"
+     .
+     "`jerboa_write_file verify:true`, `jerboa_compile_check`, or generic source verification reports `invalid context for definition` on otherwise valid `(typed-library ...)` fixtures")
+   ("severity" . "medium")
+   ("tags" "typed-library" "verify" "compile-check" "mcp"
+     "balance")
+   ("title"
+     .
+     "Do not trust generic compile checks for typed-library forms")
+   ("tools"
+     "jerboa_check_balance"
+     "jerboa_write_file"
+     "jerboa_make"))
+ (("advice"
+    .
+    "Keep imported typed module examples behind focused smoke targets that pass both provider and consumer sources to support/typed-rust.ss. Leave TYPED_RUST_SOURCES on wrapper-safe default fixtures, or extend typed-build/wrapper import resolution first.")
+   ("avoid"
+     .
+     "Do not treat dedicated imported-module smoke fixtures as default wrapper-generation inputs until support/typed-build.ss resolves imports for wrapper checks.")
+   ("id"
+     .
+     "typed-build-default-imported-fixture-wrapper-failure")
+   ("kinds" "typed" "build" "rust" "wrappers")
+   ("pattern"
+     .
+     "Adding a typed fixture that imports another typed-library to the default TYPED_RUST_SOURCES can make make typed-build fail in typed-module->jerboa-wrapper-string with unknown-import/unknown-type, even when a dedicated typed-rust smoke with both sources succeeds.")
+   ("severity" . "medium")
+   ("tags" "typed-build" "typed-library" "imports" "wrappers"
+     "Makefile")
+   ("title"
+     .
+     "Do not add imported typed-library fixtures to default typed-build sources before wrapper support")
+   ("tools" "jerboa_make" "jerboa_verify" "jerboa_howto"))
+ (("advice"
+    .
+    "Route the zero through an Int-typed helper or existing Int-taking function, for example `(def (int-zero) : Int (negative-nat 0))`, then pass `(int-zero)` to the record constructor. Re-run the generated Rust gate, not just the Scheme balance check.")
+   ("avoid"
+     .
+     "Do not rely on record constructor field annotations to coerce bare numeric literals to Int in generated Rust.")
+   ("id" . "typed-rust-int-record-field-bare-zero-u64")
+   ("kinds" "typed-rust" "codegen" "parser")
+   ("pattern"
+     .
+     "A typed record has an Int field, but helper constructors pass bare 0 as the field value. The checker accepts it, but generated Rust can emit value: 0u64 for an i64 field and fail with expected `i64`, found `u64`.")
+   ("severity" . "medium")
+   ("tags" "typed" "rust" "Int" "record" "literal" "u64")
+   ("title"
+     .
+     "Bare zero in Int record fields can lower as u64")
+   ("tools"
+     "jerboa_check_balance"
+     "jerboa_make typed-json-value-diff"
+     "jerboa_make test-typed-rust"))
+ (("advice"
+    .
+    "Keep incumbent parity gates on cases both parsers accept. Cover broader typed Unicode decoding, including BMP non-ASCII and surrogate pairs, with typed-only smoke fixtures or a dedicated strict JSON oracle instead of the current std parser.")
+   ("avoid"
+     .
+     "Do not use the incumbent (std text json) parser as the sole oracle for typed JSON Unicode escape coverage beyond the shared subset, currently ASCII escapes such as \\u0041.")
+   ("id" . "typed-json-diff-oracle-unicode-escape-subset")
+   ("kinds" "testing" "typed" "json" "benchmark")
+   ("pattern"
+     .
+     "Adding non-ASCII \\uXXXX or surrogate-pair Unicode escape cases directly to typed-json-value-diff or generated-Rust-vs-(std text json) benchmark corpora can make the oracle report invalid while the typed parser correctly accepts and decodes the string.")
+   ("severity" . "medium")
+   ("tags" "typed-json" "std-text-json" "unicode" "surrogate"
+     "diff" "oracle")
+   ("title"
+     .
+     "Do not assume std JSON accepts every Unicode escape in typed JSON parity gates")
+   ("tools"
+     "jerboa_howto"
+     "jerboa_make typed-json-value-smoke"
+     "jerboa_make typed-json-value-diff"))
+ (("advice"
+    .
+    "When ownership is genuinely tail-position and the local is not used afterward, pass it as a temporary expression such as `(begin fields)` so the Rust emitter moves it instead of cloning it. Verify with generated Rust inspection plus executable smoke/diff/bench gates; do not use this if any later branch needs the moved local.")
+   ("avoid"
+     .
+     "Do not assume tail recursion over a mutable HashMap accumulator is cheap in the Rust backend. Passing a local accumulator directly can clone the whole map at each recursive step.")
+   ("id" . "typed-rust-tail-call-nonscalar-local-clone")
+   ("kinds" "typed" "rust" "performance" "parser")
+   ("pattern"
+     .
+     "Generated Rust for a tail-position typed call passes a non-scalar local such as a HashMap or BytesBuilder as `(fields).clone()` even when the caller never uses that local after the call.")
+   ("severity" . "medium")
+   ("tags" "typed-rust" "clone" "HashMap" "tail-call"
+     "performance" "json")
+   ("title"
+     .
+     "Typed Rust tail calls clone non-scalar locals unless passed as temporaries")
+   ("tools"
+     "jerboa_check_balance"
+     "jerboa_make typed-json-value-smoke"
+     "jerboa_make typed-json-value-bench"))
+ (("advice"
+    .
+    "Keep the benchmarked no-entry parser body inline at the exported hot function. Add a separate entry-collecting/public wrapper only for slower public bridge paths, then inspect generated Rust and rerun the strict benchmark.")
+   ("avoid"
+     .
+     "Do not put the hot typed parser entry behind a generic mode wrapper when the backend lowers the call by cloning a Bytes argument.")
+   ("id" . "typed-rust-parser-mode-wrapper-bytevector-clone")
+   ("kinds" "performance" "typed-rust" "benchmark")
+   ("pattern"
+     .
+     "A typed parser is refactored from an inline public entry point into a small mode wrapper such as (json-parse-mode data flag), and generated Rust starts calling json_parse_mode((data).clone(), ...), regressing parser benchmarks.")
+   ("severity" . "medium")
+   ("tags" "typed" "rust" "bytevector" "parser" "benchmark"
+     "clone")
+   ("title"
+     .
+     "Typed parser mode wrapper clones bytevector input")
+   ("tools"
+     "jerboa_check_balance"
+     "make typed-json-value-bench"
+     "rg generated Rust for \"clone()\"")))
diff --git a/data/api-signatures.sexp b/data/api-signatures.sexp
index d6e4c69..a17ba5f 100644
--- a/data/api-signatures.sexp
+++ b/data/api-signatures.sexp
@@ -1,4 +1,4 @@
-(("errors") ("generated" . "2026-07-16")
+(("errors") ("generated" . "2026-07-28")
   ("modules"
    ("(jerboa build musl)"
      ("exports" "build-musl-binary" "make-musl-cross-target"
@@ -326,7 +326,7 @@
      ("tier" . "core"))
    ("(jerboa prelude clean)"
      ("exports" "*method-tables*" "*struct-types*"
-      "ContractViolation" "Error" "aget" "agetq" "agetv"
+      "ContractViolation" "Error" "aget" "agetq" "agetv" "alist"
       "alist->hash-table" "any" "aset!" "asetq!" "asetv!"
       "assert!" "begin-ffi" "bind-method!" "c-declare" "c-lambda"
       "call-method" "catch" "chain" "chain-and" "def" "def*"
@@ -342,19 +342,23 @@
       "hash-put!" "hash-ref" "hash-remove!" "hash-update!"
       "hash-values" "json-object->string" "keyword->string"
       "keyword?" "last-pair" "let-hash" "list->hash-table"
-      "make-hash-table-eq" "make-keyword" "match" "match/strict"
-      "path-directory" "path-expand" "path-join" "path-normalize"
+      "make-hash-table-eq" "make-keyword" "make-rwlock"
+      "make-thread" "match" "match/strict" "path-directory"
+      "path-expand" "path-join" "path-normalize"
       "path-strip-directory" "path-strip-extension" "pget" "pgetq"
       "pgetv" "plist->hash-table" "read-all-as-lines"
       "read-all-as-string" "read-file-lines" "read-file-string"
-      "read-json" "register-struct-type!" "snoc" "stable-sort"
+      "read-json" "register-struct-type!" "rwlock-read-lock!"
+      "rwlock-read-unlock!" "rwlock-write-lock!"
+      "rwlock-write-unlock!" "rwlock?" "snoc" "stable-sort"
       "stable-sort!" "string->json-object" "string->keyword"
       "string-contains" "string-empty?" "string-index"
       "string-join" "string-prefix?" "string-split"
       "string-suffix?" "string-trim" "struct-field-ref"
       "struct-field-set!" "struct-predicate" "struct-type-info"
-      "take" "try" "unique" "until" "while" "write-file-string"
-      "write-json" "zip" "~")
+      "take" "thread-join!" "thread-start!" "try" "unique" "until"
+      "while" "with-read-lock" "with-write-lock"
+      "write-file-string" "write-json" "zip" "~")
      ("file" . "lib/jerboa/prelude/clean.ss")
      ("tier" . "core"))
    ("(jerboa prelude safe)"
@@ -366,25 +370,29 @@
       "*sandbox-timeout*" "*struct-types*" "1+" "1-"
       "ContractViolation" "Error" "aget" "agetq" "agetv"
       "alist->hash-table" "any" "aset!" "asetq!" "asetv!"
-      "assert!" "bind-method!" "call-method" "call-with-resource"
-      "call-with-safe-input-file" "call-with-safe-output-file"
-      "catch" "chain" "chain-and" "connection-refused?"
+      "assert!" "bind-method!" "call-method"
+      "call-with-input-file" "call-with-output-file"
+      "call-with-resource" "call-with-safe-input-file"
+      "call-with-safe-output-file" "catch" "chain" "chain-and"
+      "check-untainted!" "connection-refused?"
       "connection-timeout?" "db-connection-error?"
       "db-constraint-violation?" "db-error?" "db-query-error?"
       "def" "def*" "defclass" "defmethod" "defrule" "defrules"
-      "defstruct" "displayln" "drop" "eprintf" "error-irritants"
-      "error-message" "error-trace" "every" "filter-map" "finally"
-      "flatten" "format" "fprintf" "group-by" "hash->list"
-      "hash->plist" "hash-clear!" "hash-copy" "hash-eq-literal"
-      "hash-find" "hash-fold" "hash-for-each" "hash-get"
-      "hash-key?" "hash-keys" "hash-length" "hash-literal"
-      "hash-map" "hash-merge" "hash-merge!" "hash-put!" "hash-ref"
-      "hash-remove!" "hash-table?" "hash-update!" "hash-values"
-      "iota" "jerboa-condition-subsystem" "jerboa-condition?"
+      "defstruct" "delete-file" "displayln" "drop" "eprintf"
+      "error-irritants" "error-message" "error-trace" "every"
+      "filter-map" "finally" "flatten" "format" "fprintf" "getenv"
+      "group-by" "hash->list" "hash->plist" "hash-clear!"
+      "hash-copy" "hash-eq-literal" "hash-find" "hash-fold"
+      "hash-for-each" "hash-get" "hash-key?" "hash-keys"
+      "hash-length" "hash-literal" "hash-map" "hash-merge"
+      "hash-merge!" "hash-put!" "hash-ref" "hash-remove!"
+      "hash-table?" "hash-update!" "hash-values" "iota"
+      "jerboa-condition-subsystem" "jerboa-condition?"
       "json-object->string" "keyword->string" "keyword?"
       "last-pair" "let-hash" "list->hash-table" "make-hash-table"
       "make-hash-table-eq" "make-keyword" "make-sandbox-config"
-      "match" "network-error?" "open-safe-input-file"
+      "make-taint-violation" "match" "network-error?"
+      "open-input-file" "open-output-file" "open-safe-input-file"
       "open-safe-output-file" "parallel" "parse-error?"
       "path-absolute?" "path-directory" "path-expand"
       "path-extension" "path-join" "path-normalize"
@@ -402,22 +410,33 @@
       "sandbox-config-timeout" "sandbox-config?"
       "sandbox-error-detail" "sandbox-error-phase"
       "sandbox-error?" "scope-spawn" "scope-spawn-named" "snoc"
-      "sort" "sort!" "sqlite-bind" "sqlite-close" "sqlite-exec"
-      "sqlite-execute" "sqlite-finalize" "sqlite-open"
-      "sqlite-prepare" "sqlite-query" "sqlite-step" "stable-sort"
-      "stable-sort!" "string->json-object" "string->keyword"
-      "string-contains" "string-empty?" "string-index"
-      "string-join" "string-prefix?" "string-split"
-      "string-suffix?" "string-trim" "struct-field-ref"
-      "struct-field-set!" "struct-predicate" "struct-type-info"
-      "take" "task-await" "task-cancel" "task-done?" "task-name"
-      "task-result" "task?" "tcp-accept" "tcp-close" "tcp-connect"
-      "tcp-listen" "tcp-read" "tcp-write" "tcp-write-string"
-      "timeout-error?" "try" "unique"
-      "unregister-safe-record-type!" "until" "while"
-      "with-input-from-string" "with-output-to-string"
-      "with-resource" "with-resource1" "with-task-scope"
-      "with-timeout" "write-file-string" "write-json" "zip" "~")
+      "sort" "sort!" "sqlite-close" "sqlite-exec" "sqlite-execute"
+      "sqlite-open" "sqlite-query" "stable-sort" "stable-sort!"
+      "string->json-object" "string->keyword" "string-contains"
+      "string-empty?" "string-index" "string-join"
+      "string-prefix?" "string-split" "string-suffix?"
+      "string-trim" "struct-field-ref" "struct-field-set!"
+      "struct-predicate" "struct-type-info" "system" "taint"
+      "taint-class" "taint-deser" "taint-env" "taint-file"
+      "taint-http" "taint-net" "taint-value"
+      "taint-violation-class" "taint-violation-sink"
+      "taint-violation?" "tainted-bytevector-copy"
+      "tainted-bytevector-length" "tainted-bytevector-u8-ref"
+      "tainted-format" "tainted-string->number"
+      "tainted-string->utf8" "tainted-string-append"
+      "tainted-string-downcase" "tainted-string-join"
+      "tainted-string-length" "tainted-string-ref"
+      "tainted-string-split" "tainted-string-trim"
+      "tainted-string-upcase" "tainted-substring"
+      "tainted-utf8->string" "tainted?" "take" "task-await"
+      "task-cancel" "task-done?" "task-name" "task-result" "task?"
+      "tcp-accept" "tcp-close" "tcp-connect" "tcp-listen"
+      "tcp-read" "tcp-write" "tcp-write-string" "timeout-error?"
+      "try" "unique" "unregister-safe-record-type!" "untaint"
+      "until" "while" "with-input-from-string"
+      "with-output-to-string" "with-resource" "with-resource1"
+      "with-task-scope" "with-timeout" "write-file-string"
+      "write-json" "zip" "~")
      ("file" . "lib/jerboa/prelude/safe.ss")
      ("tier" . "core"))
    ("(jerboa prelude)"
@@ -594,6 +613,13 @@
        "write-safe-rust-program")
      ("file" . "lib/jerboa/rust/codegen.ss")
      ("tier" . "core"))
+   ("(jerboa script-loader)"
+     ("exports"
+       "jerboa-load-script"
+       "jerboa-load-stdin"
+       "split-unsafe-prelude-flag")
+     ("file" . "lib/jerboa/script-loader.ss")
+     ("tier" . "core"))
    ("(jerboa translator)"
      ("exports" "default-transforms" "make-translator"
       "translate-brackets" "translate-define-values"
@@ -624,28 +650,43 @@
      ("tier" . "core"))
    ("(jerboa typed core)"
      ("exports" "make-typed-ir-begin" "make-typed-ir-binding"
-      "make-typed-ir-bytes-build" "make-typed-ir-call"
-      "make-typed-ir-for-fold" "make-typed-ir-if"
+      "make-typed-ir-break" "make-typed-ir-bytes-build"
+      "make-typed-ir-call" "make-typed-ir-continue"
+      "make-typed-ir-for-fold" "make-typed-ir-function-ref"
+      "make-typed-ir-if" "make-typed-ir-lambda"
       "make-typed-ir-let" "make-typed-ir-lit"
       "make-typed-ir-match" "make-typed-ir-match-clause"
-      "make-typed-ir-var" "typed-ir-begin-exprs"
+      "make-typed-ir-mutable-let" "make-typed-ir-new"
+      "make-typed-ir-object" "make-typed-ir-object-method"
+      "make-typed-ir-return" "make-typed-ir-set"
+      "make-typed-ir-throw" "make-typed-ir-try"
+      "make-typed-ir-try-finally" "make-typed-ir-var"
+      "make-typed-ir-while" "typed-ir-begin-exprs"
       "typed-ir-begin-source" "typed-ir-begin-type"
       "typed-ir-begin?" "typed-ir-binding-expr"
       "typed-ir-binding-name" "typed-ir-binding?"
-      "typed-ir-bytes-build-body" "typed-ir-bytes-build-size"
-      "typed-ir-bytes-build-source" "typed-ir-bytes-build-type"
-      "typed-ir-bytes-build-var-name" "typed-ir-bytes-build?"
-      "typed-ir-call-args" "typed-ir-call-info"
-      "typed-ir-call-kind" "typed-ir-call-kinds"
-      "typed-ir-call-operator" "typed-ir-call-source"
-      "typed-ir-call-type" "typed-ir-call?"
-      "typed-ir-for-fold-acc-init" "typed-ir-for-fold-acc-name"
-      "typed-ir-for-fold-body" "typed-ir-for-fold-range-end"
+      "typed-ir-break-source" "typed-ir-break-type"
+      "typed-ir-break?" "typed-ir-bytes-build-body"
+      "typed-ir-bytes-build-size" "typed-ir-bytes-build-source"
+      "typed-ir-bytes-build-type" "typed-ir-bytes-build-var-name"
+      "typed-ir-bytes-build?" "typed-ir-call-args"
+      "typed-ir-call-info" "typed-ir-call-kind"
+      "typed-ir-call-kinds" "typed-ir-call-operator"
+      "typed-ir-call-source" "typed-ir-call-type" "typed-ir-call?"
+      "typed-ir-continue-source" "typed-ir-continue-type"
+      "typed-ir-continue?" "typed-ir-for-fold-acc-init"
+      "typed-ir-for-fold-acc-name" "typed-ir-for-fold-body"
+      "typed-ir-for-fold-range-end"
       "typed-ir-for-fold-range-start" "typed-ir-for-fold-source"
       "typed-ir-for-fold-type" "typed-ir-for-fold-var-name"
-      "typed-ir-for-fold?" "typed-ir-if-else" "typed-ir-if-source"
-      "typed-ir-if-test" "typed-ir-if-then" "typed-ir-if-type"
-      "typed-ir-if?" "typed-ir-let-bindings" "typed-ir-let-body"
+      "typed-ir-for-fold?" "typed-ir-function-ref-name"
+      "typed-ir-function-ref-source" "typed-ir-function-ref-type"
+      "typed-ir-function-ref?" "typed-ir-if-else"
+      "typed-ir-if-source" "typed-ir-if-test" "typed-ir-if-then"
+      "typed-ir-if-type" "typed-ir-if?" "typed-ir-lambda-body"
+      "typed-ir-lambda-params" "typed-ir-lambda-source"
+      "typed-ir-lambda-type" "typed-ir-lambda?"
+      "typed-ir-let-bindings" "typed-ir-let-body"
       "typed-ir-let-source" "typed-ir-let-type" "typed-ir-let?"
       "typed-ir-lit-source" "typed-ir-lit-type"
       "typed-ir-lit-value" "typed-ir-lit?"
@@ -655,54 +696,101 @@
       "typed-ir-match-clauses" "typed-ir-match-default"
       "typed-ir-match-scrutinee" "typed-ir-match-scrutinee-type"
       "typed-ir-match-source" "typed-ir-match-type"
-      "typed-ir-match?" "typed-ir-node-source"
-      "typed-ir-node-type" "typed-ir-node?" "typed-ir-var-name"
-      "typed-ir-var-source" "typed-ir-var-type" "typed-ir-var?")
+      "typed-ir-match?" "typed-ir-mutable-let-bindings"
+      "typed-ir-mutable-let-body" "typed-ir-mutable-let-source"
+      "typed-ir-mutable-let-type" "typed-ir-mutable-let?"
+      "typed-ir-new-args" "typed-ir-new-result-type"
+      "typed-ir-new-source" "typed-ir-new-type" "typed-ir-new?"
+      "typed-ir-node-source" "typed-ir-node-type" "typed-ir-node?"
+      "typed-ir-object-method-body"
+      "typed-ir-object-method-modifiers"
+      "typed-ir-object-method-name"
+      "typed-ir-object-method-params"
+      "typed-ir-object-method-return-type"
+      "typed-ir-object-method-source" "typed-ir-object-method?"
+      "typed-ir-object-methods" "typed-ir-object-source"
+      "typed-ir-object-super-args" "typed-ir-object-super-type"
+      "typed-ir-object-type" "typed-ir-object?"
+      "typed-ir-return-expr" "typed-ir-return-source"
+      "typed-ir-return-type" "typed-ir-return?"
+      "typed-ir-set-expr" "typed-ir-set-name"
+      "typed-ir-set-source" "typed-ir-set-type" "typed-ir-set?"
+      "typed-ir-throw-exception" "typed-ir-throw-source"
+      "typed-ir-throw-type" "typed-ir-throw?" "typed-ir-try-body"
+      "typed-ir-try-catch-body" "typed-ir-try-catch-name"
+      "typed-ir-try-catch-type" "typed-ir-try-finally-body"
+      "typed-ir-try-finally-finally-body"
+      "typed-ir-try-finally-source" "typed-ir-try-finally-type"
+      "typed-ir-try-finally?" "typed-ir-try-source"
+      "typed-ir-try-type" "typed-ir-try?" "typed-ir-var-name"
+      "typed-ir-var-source" "typed-ir-var-type" "typed-ir-var?"
+      "typed-ir-while-body" "typed-ir-while-source"
+      "typed-ir-while-test" "typed-ir-while-type"
+      "typed-ir-while?")
      ("file" . "lib/jerboa/typed/core.ss")
      ("tier" . "core"))
    ("(jerboa typed kotlin ast)"
      ("exports" "kt-assign-expr" "kt-assign-target" "kt-assign?"
       "kt-binary-left" "kt-binary-op" "kt-binary-right"
       "kt-binary?" "kt-block-result" "kt-block-statements"
-      "kt-block?" "kt-call-args" "kt-call-callee" "kt-call?"
-      "kt-class-annotations" "kt-class-body" "kt-class-kind"
-      "kt-class-name" "kt-class-params" "kt-class-super-types"
-      "kt-class-visibility" "kt-class?" "kt-expr-stmt-expr"
-      "kt-expr-stmt?" "kt-file-declarations" "kt-file-imports"
-      "kt-file-package" "kt-file?" "kt-for-range-body"
-      "kt-for-range-end" "kt-for-range-start" "kt-for-range-var"
-      "kt-for-range?" "kt-function-annotations" "kt-function-body"
-      "kt-function-name" "kt-function-params"
-      "kt-function-return-type" "kt-function-visibility"
-      "kt-function?" "kt-if-else" "kt-if-test" "kt-if-then"
-      "kt-if?" "kt-import-alias" "kt-import-path" "kt-import?"
-      "kt-index-get-index" "kt-index-get-target" "kt-index-get?"
-      "kt-lambda-body" "kt-lambda-params" "kt-lambda?"
+      "kt-block?" "kt-break?" "kt-call-args" "kt-call-callee"
+      "kt-call?" "kt-cast-expr" "kt-cast-safe?" "kt-cast-type"
+      "kt-cast?" "kt-catch-body" "kt-catch-name" "kt-catch-type"
+      "kt-catch?" "kt-class-annotations" "kt-class-body"
+      "kt-class-kind" "kt-class-name" "kt-class-params"
+      "kt-class-super-types" "kt-class-visibility" "kt-class?"
+      "kt-continue?" "kt-enum-entry-args" "kt-enum-entry-name"
+      "kt-enum-entry?" "kt-expr-stmt-expr" "kt-expr-stmt?"
+      "kt-file-declarations" "kt-file-imports" "kt-file-package"
+      "kt-file?" "kt-for-range-body" "kt-for-range-end"
+      "kt-for-range-start" "kt-for-range-var" "kt-for-range?"
+      "kt-function-annotations" "kt-function-body"
+      "kt-function-modifiers" "kt-function-name"
+      "kt-function-params" "kt-function-return-type"
+      "kt-function-visibility" "kt-function?" "kt-if-else"
+      "kt-if-test" "kt-if-then" "kt-if?" "kt-import-alias"
+      "kt-import-path" "kt-import?" "kt-index-get-index"
+      "kt-index-get-target" "kt-index-get?" "kt-init-body"
+      "kt-init?" "kt-lambda-body" "kt-lambda-params" "kt-lambda?"
       "kt-lit-type" "kt-lit-value" "kt-lit?" "kt-member-call-args"
       "kt-member-call-name" "kt-member-call-target"
       "kt-member-call?" "kt-member-get-name"
       "kt-member-get-target" "kt-member-get?" "kt-name-parts"
       "kt-name?" "kt-new-args" "kt-new-type" "kt-new?"
-      "kt-param-default" "kt-param-mutable?" "kt-param-name"
-      "kt-param-property" "kt-param-type" "kt-param-visibility"
-      "kt-param?" "kt-property-annotations" "kt-property-init"
-      "kt-property-mutable?" "kt-property-name" "kt-property-type"
+      "kt-object-expr-body" "kt-object-expr-super-types"
+      "kt-object-expr?" "kt-param-default" "kt-param-modifiers"
+      "kt-param-mutable?" "kt-param-name" "kt-param-property"
+      "kt-param-type" "kt-param-visibility" "kt-param?"
+      "kt-property-annotations" "kt-property-init"
+      "kt-property-modifiers" "kt-property-mutable?"
+      "kt-property-name" "kt-property-setter"
+      "kt-property-setter-body" "kt-property-setter-param-name"
+      "kt-property-setter?" "kt-property-type"
       "kt-property-visibility" "kt-property?" "kt-return-expr"
-      "kt-return?" "kt-type-args" "kt-type-name"
-      "kt-type-nullable?" "kt-type?" "kt-unary-expr" "kt-unary-op"
-      "kt-unary?" "kt-val-init" "kt-val-mutable?" "kt-val-name"
-      "kt-val-type" "kt-val?" "kt-when-branch-body"
+      "kt-return?" "kt-throw-exception" "kt-throw?" "kt-try-body"
+      "kt-try-catch" "kt-try-finally-body"
+      "kt-try-finally-finally-body" "kt-try-finally?" "kt-try?"
+      "kt-type-args" "kt-type-name" "kt-type-nullable?"
+      "kt-type-projection-type" "kt-type-projection-variance"
+      "kt-type-projection?" "kt-type?" "kt-unary-expr"
+      "kt-unary-op" "kt-unary?" "kt-val-init" "kt-val-mutable?"
+      "kt-val-name" "kt-val-type" "kt-val?" "kt-when-branch-body"
       "kt-when-branch-pattern" "kt-when-branch?"
       "kt-when-branches" "kt-when-subject" "kt-when?"
-      "make-kt-assign" "make-kt-binary" "make-kt-block"
-      "make-kt-call" "make-kt-class" "make-kt-expr-stmt"
-      "make-kt-file" "make-kt-for-range" "make-kt-function"
-      "make-kt-if" "make-kt-import" "make-kt-index-get"
-      "make-kt-lambda" "make-kt-lit" "make-kt-member-call"
-      "make-kt-member-get" "make-kt-name" "make-kt-new"
-      "make-kt-param" "make-kt-property" "make-kt-return"
-      "make-kt-type" "make-kt-unary" "make-kt-val" "make-kt-when"
-      "make-kt-when-branch")
+      "kt-while-body" "kt-while-test" "kt-while?" "make-kt-assign"
+      "make-kt-binary" "make-kt-block" "make-kt-break"
+      "make-kt-call" "make-kt-cast" "make-kt-catch"
+      "make-kt-class" "make-kt-continue" "make-kt-enum-entry"
+      "make-kt-expr-stmt" "make-kt-file" "make-kt-for-range"
+      "make-kt-function" "make-kt-if" "make-kt-import"
+      "make-kt-index-get" "make-kt-init" "make-kt-lambda"
+      "make-kt-lit" "make-kt-member-call" "make-kt-member-get"
+      "make-kt-name" "make-kt-new" "make-kt-object-expr"
+      "make-kt-param" "make-kt-property" "make-kt-property-setter"
+      "make-kt-return" "make-kt-throw" "make-kt-try"
+      "make-kt-try-finally" "make-kt-type"
+      "make-kt-type-projection" "make-kt-unary" "make-kt-val"
+      "make-kt-when" "make-kt-when-branch" "make-kt-while")
      ("file" . "lib/jerboa/typed/kotlin/ast.ss")
      ("tier" . "core"))
    ("(jerboa typed kotlin lower)"
@@ -743,22 +831,55 @@
      ("exports" "expr->list" "expr-cadddr" "expr-caddr"
       "expr-cadr" "expr-car" "expr-cdddr" "expr-cdr" "expr-length"
       "expr-list?" "expr-map" "expr-pair?" "expr-source"
-      "expr-symbol?" "expr-value" "make-typed-def"
-      "make-typed-field" "make-typed-module" "make-typed-param"
+      "expr-symbol?" "expr-value" "make-typed-class-decl"
+      "make-typed-class-super" "make-typed-def"
+      "make-typed-enum-decl" "make-typed-enum-entry"
+      "make-typed-extern" "make-typed-field"
+      "make-typed-init-decl" "make-typed-module"
+      "make-typed-object-decl" "make-typed-param"
+      "make-typed-property" "make-typed-property-setter"
       "make-typed-record" "make-typed-resource"
       "make-typed-type-decl" "make-typed-variant"
       "make-typed-variant-case" "parse-typed-declaration"
       "parse-typed-library" "parse-typed-type"
-      "strip-source-annotations" "typed-def-body"
-      "typed-def-effects" "typed-def-name" "typed-def-params"
-      "typed-def-return-type" "typed-def-source" "typed-def?"
-      "typed-field-mutable?" "typed-field-name"
-      "typed-field-source" "typed-field-type" "typed-field?"
-      "typed-library-form?" "typed-module-declarations"
+      "strip-source-annotations" "typed-class-decl-declarations"
+      "typed-class-decl-name" "typed-class-decl-params"
+      "typed-class-decl-source" "typed-class-decl-super"
+      "typed-class-decl?" "typed-class-super-args"
+      "typed-class-super-name" "typed-class-super-source"
+      "typed-class-super?" "typed-def-body" "typed-def-effects"
+      "typed-def-kotlin-name" "typed-def-modifiers"
+      "typed-def-name" "typed-def-params" "typed-def-return-type"
+      "typed-def-source" "typed-def?" "typed-enum-decl-entries"
+      "typed-enum-decl-name" "typed-enum-decl-params"
+      "typed-enum-decl-source" "typed-enum-decl?"
+      "typed-enum-entry-args" "typed-enum-entry-name"
+      "typed-enum-entry-source" "typed-enum-entry?"
+      "typed-extern-kotlin-path" "typed-extern-name"
+      "typed-extern-params" "typed-extern-return-type"
+      "typed-extern-source" "typed-extern?" "typed-field-mutable?"
+      "typed-field-name" "typed-field-source" "typed-field-type"
+      "typed-field?" "typed-init-decl-body"
+      "typed-init-decl-source" "typed-init-decl?"
+      "typed-library-form?" "typed-module-crate-description"
+      "typed-module-crate-license" "typed-module-crate-name"
+      "typed-module-crate-repository" "typed-module-declarations"
       "typed-module-exports" "typed-module-imports"
-      "typed-module-name" "typed-module-source" "typed-module?"
-      "typed-param-name" "typed-param-source" "typed-param-type"
-      "typed-param?" "typed-record-fields" "typed-record-name"
+      "typed-module-name" "typed-module-source"
+      "typed-module-version" "typed-module?"
+      "typed-object-decl-declarations" "typed-object-decl-name"
+      "typed-object-decl-source" "typed-object-decl?"
+      "typed-param-default" "typed-param-modifiers"
+      "typed-param-mutable?" "typed-param-name"
+      "typed-param-property" "typed-param-source"
+      "typed-param-type" "typed-param-visibility" "typed-param?"
+      "typed-property-init" "typed-property-modifiers"
+      "typed-property-mutable?" "typed-property-name"
+      "typed-property-setter" "typed-property-setter-body"
+      "typed-property-setter-param" "typed-property-setter-source"
+      "typed-property-setter?" "typed-property-source"
+      "typed-property-type" "typed-property?"
+      "typed-record-fields" "typed-record-name"
       "typed-record-source" "typed-record?" "typed-resource-close"
       "typed-resource-name" "typed-resource-source"
       "typed-resource?" "typed-type-decl-name"
@@ -802,26 +923,45 @@
       "context-add-func!" "context-add-local!"
       "context-block-depth" "context-func-index"
       "context-local-index" "context-pop-block!"
-      "context-push-block!" "make-compile-context"
-      "make-wasm-export" "make-wasm-func" "make-wasm-import"
-      "make-wasm-module" "make-wasm-type" "scheme->wasm-type"
+      "context-push-block!" "encode-field-type" "encode-heaptype"
+      "encode-storage-type" "encode-valtype" "encode-wasm-type"