All notable changes to this project are documented here. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- 🎯 Byte-exact zlib round-trip in safe Rust (the moonshot). Alchemist
translated zlib — compressor and decompressor — from C into pure safe Rust,
proven by a full byte-exact round-trip:
Rust deflate → Rust inflate → original bytes, identical to the reference C library.deflateis byte-exact at levels 1–9 (greedydeflate_fast, lazydeflate_slow) plusZ_HUFFMAN_ONLYandZ_RLE;inflateis byte-exact on stored, dynamic, and fixed Huffman streams with LZ77 back-references; the round-trip is 21/21 across levels 1/6/9 × {empty, tiny, text, repetitive, random, low-alphabet, periodic}. Zerounsafe— the ~30-stateinflate()decode machine,goto-based control flow (as labeled breaks),unionfields, pointer aliasing (s->dyn_ltree↔l_desc.dyn_tree), and bit-level manipulation all re-expressed in safe Rust's ownership model. The differential oracle earned its keep: it caught ~9 real integration bugs that every isolated unit test passed clean over (a whole-stateinit_blockwipe, a1<<ioverflow indetect_data_type, a missingscan_treeinitialmax_count, thebuild_tree/dyn_ltreealiasing gap, stale local state indeflate_slow, and the 32-vs-30 fixed distance table). Also new: a stream/window-snapshot differential oracle class, the durability backbone (restore_hardports: hydrate a fresh skeleton from the git-tracked hardport store — proven by a clean regen+restore of 320 verified tests from git alone), and a field- addition mechanism for extractor-missed struct fields. See docs/zlib_case_study.md for the full write-up with honest limitations. Remaining polish:deflate_stored(L0), zlib/gzip wrappers,inflate_fast(perf only — slow path already byte-exact). - All five Huffman tree-builders verified end-to-end (Phase 2 complete).
pqdownheap,gen_codes,gen_bitlen,build_tree, andbuild_bl_treeare model-written (Gemma 4 31B Dense) and byte-exact against the compiled-C state oracle — 10/10 differential vectors each — in the real coherentzlib-treescrate (122 tests passing, 0 failing; snapshot inreferences/impls/zlib_trees_verified/).build_treeis the keystone: it calls the other three, so its green transitively exercises the whole tree-construction pipeline.build_bl_treerequired reconciling zlib's aliasing ofbl_desc.dyn_treetos.bl_tree(which the coherent types separate) viastd::mem::take. The oracle hierarchy proved itself —build_treeexposed apqdownheaptie-break bug (<vs zlib's<=) thatpqdownheap's own vectors never hit. Each of the harder functions went green by injecting the C source and iterating on the differential oracle's exact discrepancies (unsigned wrap, counter semantics, tie-break). zlib's static Huffman tables are now emitted as Rust consts (zlib-trees/src/static_tables.rs), unblocking_tr_align(correct EOB code) and the descriptor tier. Getting a 220KB filled module through the model surfaced and fixed three general scaling bugs: stale module locks from killed runs, and two context-overflow sources in the fill prompt (whole test module inlined; largerust_bodyvectors dumped) — the prompt went from ~20k to ~1.3k tokens.compress_block/send_all_trees(bitstream emission) remain — the moonshot. - State-mutator oracle proven on a Huffman tree-builder (Phase 2). The
first stateful function verified end-to-end:
pqdownheap(zlib's heap sift) is model-written by Gemma 4 31B and byte-exact against a compiled-C state oracle across 12 fuzzed vectors. The path: the shim exposes the Huffman heap state (shim_set/get_heap,heap_len,depth) and ashim_run_pqdownheaprunner (verified 200/200 against a Python reference);fuzz_pqdownheapdrives it with valid fuzzed heaps and renders the tree as aVec<TreeElement>literal; the state-mutator test emitter borrows the Vec so it coerces to thetree: &[TreeElement]slice the function takes. This works only because the tree types are now coherent (below) and because the fill feeds the model the Csmallermacro the function references (the SipHash lesson). Proof-of-life for the whole Huffman tree-builder family. - Whole-workspace type coherence (
architect/type_unifier.py). The extractor infers a Rust type per parameter/field independently, so one C type fractures into several incompatible Rust types across the workspace — zlib'sct_data(a Huffman tree node) becameTreeElement,HuffmanNode, ANDVec<(u16,u16)>, and the three descriptor members collapsed tou32. A function taking&[TreeElement]then cannot be handed a state field of typeVec<(u16,u16)>, so the crate cannot compile coherently — a type-generation defect underneath every Huffman tree-builder (Phase 2) and the deflate state machine (Phase 3). The unifier canonicalizes registered C types across params,TypeFields, and rawrust_definitionstrings: correlating spec params with C base types fromanalysis.json, folding element aliases (the(u16,u16)stand-in, theHuffmanNodeduplicate), dropping duplicate structs, materializing the canonical struct with its complete field set (TreeElementregains the droppeddad), and applying explicit field overrides for scalar-collapsed state members (l_desc/d_desc/bl_desc→TreeDesc). It is registry-only: Cint,void*, andz_streamplegitimately map to different Rust types by context (z_streampis both a deflate and an inflate stream), so a conflict heuristic would corrupt them — a type earns canonicalization only by being registered. Wired intorun_architect_stage(runs before architecture design and skeleton emission, persists the rewritten specs) and a no-op on subjects with no registered types. Verified on real zlib: all three tree arrays becomeVec<TreeElement>, all three descriptorsTreeDesc,HuffmanNodedropped, and the resulting type graph compiles underrustcwith no leaks. - A real external cryptographic library, translated end-to-end.
alchemist translate subjects/siphash— the genuine veorq/SipHash-2-4 reference (CC0, not authored here) — reaches OVERALL: PASS with Gemma 4 31B Dense in the loop: byte-exact against the compiled reference (canonical vector and thousands of fuzzed messages), zero hand-edits. Receipt:docs/receipts/siphash-2026-07-04.json. Getting there taught the pipeline to handle a keyed byte-digest hash with an out-param (a whole hash family: SipHash/SHA/HMAC/BLAKE) and — the decisive fix — to feed the model the C#definemacros a function references (SIPROUND,ROTL), which is why the model finally produced the exact ARX rounds instead of guessing them. It also surfaced eleven general pipeline fixes (below), none SipHash-specific. - Generalization proven on a second, independent subject.
alchemist translate subjects/hashkit— FNV-1a (u32), CRC-16/CCITT-FALSE (u16) and the BSD rotate-add sum (u16), algorithms and widths distinct from tinychk — runs end-to-end with Gemma 4 31B Dense and prints OVERALL: PASS, all three functions model-written on the first iteration and byte-exact against a compiled hashkit oracle. Getting there fixed three general pipeline bugs (below), none tinychk- or hashkit-specific. Receipt:docs/receipts/hashkit-2026-07-04.json. - First complete automated C→Rust translation (ROADMAP M09).
alchemist translate subjects/tinychkruns all six stages with the local model (Gemma 4 31B Dense) in the loop and prints OVERALL: PASS — zero hand-edits to generated code. adler32, crc32, and fletcher16 are model-written and byte-exact against a freshly compiled tinychk oracle across 5000 random inputs each (21 differential tests, receipt sealed); crc32's lazy static table became a locally-computed table and its initializer a no-op. This is the first birth-to-receipt run in the project's history, and it is subject-generic — no tinychk-specific code. - First all-gates-green crate.
alchemist verify subjects/zlib -p zlib-checksumprintsOVERALL: PASS— compile, anti-stub, no-unsafe, semantic, test (177/0) and differential (19/19) all green through the automated pipeline. The six remaining table-generation skeletons (make_crc_table,get_crc_table,braid,write_table,write_table64, and the MAKEFIXED/inffixed generator with a fullinflate_tableport) are now verified ports anchored byte-for-byte against zlib's shippedcrc32.handinffixed.h; hardports stored inalchemist/references/impls/zlib_hardports/. - Checksum shim oracle (
zlib_checksum_shim.dll): zlib'slocalstatics (crc_word,crc_word_big,multmodp,x2nmodp) now have a compiled-C FFI oracle with W=8/N=5 compile-time pins.crosscheck_checksum_shimenforces shim-vs-pure-reference agreement before any vector is minted — an oracle disagreement halts generation. Independently confirms the crc_word_big W=8 fix against real compiled zlib (crc_word_big(1) == 0x9630077700000000). - Verification receipts (
verifier/receipt.py): every differential run writesverify_gen/receipt.json— gate results, harness bindings, case counts, boundary lengths, and the oracle's identity (gcc version, C source and DLL sha256) — content-addressed with an integrity hash and an optional HMAC (ALCHEMIST_RECEIPT_KEY). - Compression adapters with full effect footprint:
rust_compress/c_compresswrappers return(status, bytes)— no asserts inside wrappers — and the harness checks status parity, both roundtrips, and cross-interop. The zlib deflate harness now resolves (3/3 adapted) and fails honestly on the stub implementations instead of being unresolvable. - Boundary-length differential tests: deterministic LCG-content tests at algorithmic fold edges (Adler NMAX 5551/5552/5553, CRC word/braid/batch alignments) that random sampling almost never hits.
- Oracle-tagged vector persistence: fuzz vectors are stamped with their
oracle's content hash (
[oracle:shim:zlib_checksum_shim.dll:<sha16>]) and persisted into the spec checkpoints. Tagged vectors always regenerate on the next run — a persisted vector can never outlive a fix to its oracle — while authored vectors are never touched. - Automated differential adapter (
verifier/adapter_gen.py): the Stage-5 gate now discovers the generated crates' realpub fnsignatures, emitsc_*/rust_*wrapper code and path-deps automatically, and turns any harness it cannot adapt into a failing test. First genuine automated differential green: zlib-checksum, adler32 + crc32, 5000 random cases each vs the compiled C reference, zero hand-editing. - Semantic-lint verify gate:
semantic_lints.scan_workspace_semanticssweeps every generated function against its spec at verify time;VerificationReportgains asemanticgate that fails closed on errors. Newlint_crc32_braidcatches the big-endian word-braid variant confusion (the #1 named failure mode) — proven with negative tests. --packagescoping foralchemist verifyandDifferentialConfig.packagesso a completed crate can be verified while sibling crates are still skeletons.zlib_checksum_diff_config()— checksum-crate-scoped differential config.docs/PATH_TO_FLAWLESS.md— the assurance roadmap: per-function verification levels (L0–L6), the oracle-integrity/fuzzing/proof gap program, and the "flawless-or-refused" end-state with signed receipts.- Initial CHANGELOG.md — establishes Keep-a-Changelog format
- Architecture module placement: the LLM architect sometimes listed function
names (or scattered one source module's functions) in crate
moduleslists, so the module matched no crate and the skeleton emitted empty crates — nothing to fill, nothing to differentially adapt._reconcile_module_placementnow guarantees every spec module is claimed by exactly one crate and drops crates left empty. - Standards-catalog false oracle: a boundary-blind prefix match handed
CRC-32 (32-bit) vectors to
crc16_ccitt(a 16-bit function), failing a correct implementation every iteration. Catalog matching now respects word boundaries —crc32_z/adler32_implstill resolve,crc16_ccittmatches nothing. - Scalar-hash fuzzing: hash-category functions were always routed to the byte-digest fuzzer, which rejected FNV-1a's scalar u32 and left it unverifiable. A scalar-integer return is now fuzzed as a checksum.
- FFI oracle library naming and loader path: the differential oracle was
built with a hardcoded Windows
.dllname and no runtime library path, so on Linux the diff crate failed to link (-lc_*_refnot found) and, once linked, failed to load the.so. Names are now platform-correct (.dll/.so/.dylib) with a build.rs rpath and the oracle directory prepended to the loader-path variable for the test subprocess. - The lazy-static-table idiom (a C function that fills a file-scope static on first use) now translates: the initializer becomes a no-op and consumers compute their own table, driven by a fill prompt that lists the module-level constants actually in scope.
- crc_word_big translation and its pure-Python fuzz reference implemented a
chimera of zlib's W=4 and W=8 braid configurations (32-bit-swapped table
entries in the low half driving a 64-bit loop). Both now implement the real
W=8 variant —
crc_big_table[i] = byte_swap64(crc_table[i]), entries in the high 32 bits, anchored against zlib's shipped crc32.h. The 17 previously-failingtest_crc_word_bigvectors now pass (183/183 in zlib-checksum). - Differential harness generation no longer falls through to a smoke-only
check for unhandled algorithm categories:
transform/protocol/scheduler/othernow emit an UNVERIFIABLE harness that fails, so the weakest check is never the default. - Test emitter renders expected values against the function's actual Rust
return type:
Option/Resultconstructors pass through (Some(18usize)no longer mangled intob"Some(18usize)"), byte-string fallback only for byte-like returns, and unrenderable values emit a failing test instead of uncompilable code. The zlib-compression test module compiles and runs again (and honestly fails on the stub implementations). alchemist verifyCLI updated to the currentDifferentialTesterAPI (was calling a long-removed constructor shape and dict-style report).- Removed the orphaned
zlib_config.WRAPPERS_RSdead code, replaced by adapter_gen. - FFI import libraries are now named
lib<name>.dll.a(MinGW convention, matches the proven hand-written layout).