Next steps (as of 2026-10-30)
Where the work stands, what comes next in order, what needs a decision
from the user, and the working rules that kept parallel agents safe. Every
claim here is recorded in more detail in compiler/CONFORMANCE.md
(D388-D419) and the linked design notes. No em dashes.
1 Where it stands
- Memory: GC-free reference counting is on by default (
design/reclamation.md, D389-D411). Header word, smallNat/Intimmediates, the tag in the header, pointer maps, iterative drop, Perceus insertion with every parameter owned, mark-on-spawn atomic counts, a leak check and a use-after-free debug mode. Peak memory fell 30-90x on the measured programs, and they end with zero live blocks.CINCH_RECLAIM=0turns it off for baselines. - Faults: a well-typed program does not fault (
design/no-faults.md, D401, D407-D417). Pattern coverage counts no guarded row; division takes aNonZerodivisor;Natsubtraction needsb <= a; exhaustion is one definedExhaustedexit (73), with stack overflow caught by guard bands; byte indexing is proven in bounds; conversions carry their ranges. Evidence comes from everycasebranch (if, guards,&&,||are case forms), and obligations discharge by difference logic, then Fourier-Motzkin, each proof with a re-checked certificate. - One known test failure on
main(merged at the user’s direction, 2026-10-30, to circle back to): the full suite is 1081 passed, 1 failed; see section 2.0. - Design directions recorded and decided: representation option C with
demand-driven specialization, compiler-chosen default layouts,
expanding-edge boxing, representations as instances of
Represent t cselected withvia(design/layouts-and-specialization.md, D392-D394); allocators (design/allocators.md, D397-D398); floats as one unboxed type with proofs in refinements and unsafe, non-implicit IEEE instances (design/float-refinements.md, D414); verified primitives and proof automation (design/verified-primitives.md,design/proof-automation.md, D395). - The bootstrap ladder (the compiler written in Cinch) was paused until reclamation landed. It has landed, so the ladder can resume when the user says so.
2 Next, in order
2.0 Fix the one failing test
NF3b and NF5 (D418-D419) were merged with one failure outstanding:
surface::bytes_literal_folds_and_map_literal_round_trips. A bytes list
literal (buf :: Bytes; buf = [1, 2, 3]) no longer folds to a constant
buffer at compile time; the program still runs correctly. FromList Bytes
now takes U8 elements (Data/Bytes.cinch bytes-from-u8s, through
byte-of-u8: byte-word then nat-from-i64), and fold_constant
(check.rs) returns None because the compile-time evaluator
(eval_core) fails somewhere on that path [INFERENCE: most likely a
widening intrinsic or the refined-result plumbing it does not evaluate].
Fix the evaluator (or the instance) so the literal folds again, and run
the full suite with no time limit. The same merge also changed one
diagnostic: a refinement flow that no fact discharges now
reports “the obligation v > 5 …” instead of “does not flow to”
(tests/lattice.rs), which names the failing obligation but no longer
names both types; restore the type names in the message if that is
preferred.
2.1 Close the remaining reachable faults
The current list is in design/no-faults-inventory.md (“Runtime exits
classified”, reachable rows):
sym-intern-byteson non-UTF-8 bytes: give it anOptionfront door or a UTF-8 evidence obligation (the documentedintern :: String -> Symis already total).OutputFailed(the OS refusing a stdout write) and the IO buffer paths: surface them asResultin the IO API rather than an exit.- The cooperative scheduler’s deadlock check (
coop.rs): decide whether a deadlock is a typed outcome or ruled out statically for the structured concurrency the language admits. f64-from-decimalon untrusted text: anOptionfront door (belongs with the float slice).- Foreign code: stays behind contracts and the manifest. Bring it to the user if it ever needs more than that (D407: anything unprovable comes back for discussion).
2.2 Replace quiet fallbacks with proofs
These sites are total today, but rest on an invariant the checker cannot
see, so on a broken invariant they now do something quiet instead of
faulting. Each should become a proof, an own using obligation, or a
visible Option/Result:
Data.Rational.normalise(zero gcd; needs the positive-denominator invariant in theRatconstructor or a product-of-non-zeros rule).Text.Builderoverflow,Text.Zlibwriting past the end andout-backat distance 0,Text.Regexprogram counters and repeat bounds,Text.Yamloffsets clamped to the length,Data.Datecivil-fieldnegatives,Text.Lexlengths above 2^63,Bootstrap.Interfacebytes-spliceandnat-to-u64residues,Bootstrap.*string-stop,key-anchored,slice-src.- Behavior choices the user may veto (D417, D419): durations clamp at zero,
reversed byte ranges are empty,
BigDecimal.divandEnum’spred/to-enumreturnOption, the bootstrap evaluator reports a zero divisor as a diagnostic. - The
NonZero IntSemigroup/Monoidpreservation law is sample-checked, not proved.
2.3 Floats (design/float-refinements.md)
Tier 1 (the predicates, decide, IEEE-correct facts) and tier 2 (refined
operation signatures, lawful instances on NotNaN F64, total
float-to-integer conversion from InRange), then the unsafe instance
mechanism for the IEEE instances. Needs the user’s answer in section 4.
2.4 Reclamation follow-ons (design/reclamation.md section 10)
- S6b: borrow inference (skip dup/drop pairs around calls) and drop specialization.
- S7: reuse of uniquely held cells (count exactly +1; a marked block at -1 must not be reused, D409) and static dictionaries for instances without sub-dictionaries.
- S8: cycle teardown per D396 (region-scoped
letrecknots, enforced memo regions); the knot test leaks exactly 3 blocks until then. - Conservative
Rawslots that leak and are not marked for atomic counts: memo and knot values, dictionary value slots, joins wider than four, packed and boxed-out boundary words, builtin index-family constructors, compile-time constants built without type arguments. Give each its real class. - S10: wasm headers and frees. Linux verification of the stack guard and thread paths (written from each ABI, run only on macOS arm64).
- Allocators A1-A4 (
design/allocators.mdsection 6): the in-house small-object allocator, the user-supplied allocator interface and the static pool, theHeap rcapability with arenas, then#[fip]and#[alloc "bounded(n)"]for thejplprofile.
2.5 Proof automation and the kernel
- The difference-logic and Farkas certificates (
DiffCert, the Fourier-Motzkin certificates) are re-checked in Rust today. Move the check into the dependent kernel by reflection (design/proof-automation.mdsection 5). - The bootstrap parser does not model
usingpredicates,refinedresults orInRangeindex parameters;bootstrap_parse’s coverage table records them as unmodeled (Data.Machine52 and others). Model them. row_resultsubstitution in nested local definitions may pick the wrong names (rare; noted by the NF3b slice).
2.6 Representation and layouts (design/layouts-and-specialization.md section 8)
Value types and field unpacking, demand-driven multi-word layouts with
expanding-edge boxing, specialize bodies, representation instances
(Represent t c, via), the justification rule.
2.7 Older follow-ups still open
A list literal of 300 or more elements overflowed the CLI stack (recheck:
it should now be the Exhausted exit); top-level values are re-evaluated
per use (CAF); Mode::Run reports a signal-killed process as exit 1;
Text.Builder copies twice; Eq_Bytes could use bytes-compare;
Text.Parse.render-errors is quadratic; Text.Json’s duplicate-key check
is O(k^2); Bootstrap.Ir’s signature search is O(decls^2);
Bootstrap.Driver copies per byte.
3 Working rules that kept the agent waves safe
- Memory. Never run a compiled program without
CINCH_HEAP_LIMIT(2G or less;compiler/.cargo/config.tomlsets it forcargo test). Never raise a cap. - Cargo. Never pipe cargo output through
heador anything that exits early: SIGPIPE kills the build and leaves the old binary in place, which looks like a stale cache. - The full suite takes about 70 minutes on this machine (over 110 test binaries, longer when agents run tests at the same time). Run it with no time limit, and after every wave, because slices verify only their own target lists: four waves in a row, the full suite caught a regression no slice had run (a test program using a now-refused form, or a typing change in a target outside the slice’s list).
- Gate a snapshot, not a moving tree. When agents keep editing during a
gate, stage the tree,
git write-tree, commit that tree to a branch withgit commit-tree, and run the suite in a worktree of that branch (mwt new <branch>); fast-forwardmainonly if it is green. - Shared tree. Agents never commit, branch, stash or reset; each owns a named region and messages the owner before touching another region; a slice blocked by another’s in-flight edit closes out with deferred checks instead of waiting or fixing it.
- Embedded and non-embedded prelude. 55 prelude modules are embedded in
the compiler and 38 are not; the 38 compile only through a
Mainthat imports them (or theirlib_*test). Programs embedded incompiler/tests/*.rsare separate again. A migration must check all three;rgovercompiler/testsfor the changed functions. - Agent budgets. A slice agent stops at about 200-300 requests. Large migrations should delegate disjoint module sets to sub-agents from the start; a stopped agent can be resumed with a precise list of what remains.
4 Decisions waiting for the user
- Float equality: should the lawful instances on
NotNaN F64(totalOrderequality, so-0 /= +0) be implicit, or must every float equality be selected explicitly? Also the unsafe module’s name and theReal64alias names (design/float-refinements.mdsection 8). - The behavior choices in section 2.2.
- Resuming the bootstrap ladder now that reclamation has landed.
- Representation details still open in
design/layouts-and-specialization.mdsection 9 (value type spelling,Copy-only represented element types, specialized body spelling).
