Tracking issue to scope the next cut after v1.12.2 (2026-07-20), modeled on #275 / #545 . About 55 commits have landed on main since that tag (through #628 , f3ca5f9b, 2026-08-11), with another ~20 open PRs in flight. Freeze scope here, draft the upgrade notes, run the pre-release checks, and list blockers before we tag.
#545 still tracks the v1.12.0 cut that already shipped (v1.12.0–v1.12.2). Close or retarget it so release tracking has one live home.
Scope snapshot
Range v1.12.2..main @ f3ca5f9b: 55 merged PRs (~54k insertions / ~8k deletions across ~237 files). Headline arcs:
VM / call path. Explicit frame chain for direct bytecode calls (vm: make direct bytecode calls non-recursive with an explicit frame chain #645 ): stack-safe deep lg→lg recursion (vm: Frame.Run is Go-recursive — deep lg→lg recursion aborts the process #644 ), with a measured per-invoke cost tracked in vm: bytecode invoke is ~1.7x costlier since #645 (explicit frame chain) #700 . Follow-ups: vm: drop leaveFrame's unused *Frame parameter to unpin f from memory #706 , Design: constant-space tail calls on the explicit-frame VM (closures, multi-arity, apply) #620 , perf(vm): re-evaluate static self-call shortcut after shared frame transitions #646 .
Native / registrar surface. Hot clojure.core direct-call natives (perf(rt): direct-call natives for the hot clojure.core surface #613 ); hoist of 222 primitives to //lg:native (feat(rt): hoist 222 clojure.core primitives to named //lg:native decls #639 ); per-package registrar (feat: per-package //lg:native registrar surface (migrate corefns) #640 ). Shadowed reduce registration fixed in perf(rt): restore reduce's ArrayVector and Range fast paths #686 ; remaining guard gaps in Three generated-primitive guards pass when their premise breaks #704 / Retire the twelve hand registrations the generated registrar shadows #696 / Drain the remaining hand registrations in pkg/rt onto //lg:native #697 .
IR / AOT. Catalog-driven op and form-head dispatch (perf(ir): catalog-driven op dispatch — generated OpByKeyword string switch (§1/§2/§2b) #612 , refactor(ir): catalog-driven form-head dispatch with load-time coherence check #667 ); strict-mode census (feat(ir): *ir-compile-strict* + a bytecode-path coverage census (70.7% vs the 99.5% we were measuring) #580 ); lower correctness (fix(ir/lower): block-junk agreement + RPO block order + deferrable-branch guards #648 , fix(ir): give function-level recur its own op and lower it to OP_RECUR_FN #642 , fix(ir): treat a return-hinted arity vector as one arity (#598) #661 ); typed-return override registration (fix(aot): register a boxed override for typed-return fns (#554) #653 ); self-recursive typed seed (feat(ir): seed self-recursive calls from a declared return type (#599) #662 ); native-entry Go frame via lg-compile --entry-frame (feat(aot): generate native-entry Go frame from main/-main (#425 Item 1) #628 , closes AOT native-entry: generate the Go entry frame, self-contain gogen, and stop the silent perf-cliff #425 Item 1 / AOT entry frame: recover the lowered signature from gogen as data, not by string-matching rendered Go #657 ). Silent fallback and strict Tier-2 fixtures: Lowering falls back to bytecode silently, and only the bench harness notices #660 , strict-mode AOT: 6/16 gold-aot fixtures only run via silent fallback — binding conveyance, @f deref rot, closure capture untracked #678 ; parity gate PR test(parity): gate complete-corpus strict capability and engine output #681 .
WASM / host. SPSC ring + held-key coalesce for SAB key input (feat(wasm): SPSC ring buffer + held-key coalesce for SAB key input #595 ); RGBA surface capability (feat(rt): surface host capability — RGBA frame sink (graphics, #255) #572 ); TinyGo lane (feat: TinyGo support: small-footprint WASM and native builds #522 ) with CI follow-ups (ci(tinygo): failed wasmtime install passes and breaks the boot step #682 , ci(tinygo): pin wasmtime and verify it landed on PATH #685 ).
Toolchain / bundles. go.mod toolchain go1.26.5 (build: single-source Go toolchain via go.mod toolchain directive #677 ); named capability rejects (feat(bytecode): actionable hint on capability-mask reject #608 , feat(bytecode): name capabilities in reject errors and lg -v #622 ); Var metadata bundle round-trip + clojure.repl / clojure.pprint (feat(clojure): add clojure.repl / clojure.pprint, fix Var metadata bundle round-trip #668 ); lg_no_http build tag (build: add lg_no_http to drop net/http from the runtime (#652) #658 ).
Embedder API. lg.IsIncomplete (feat(api): IsIncomplete — sanctioned incomplete-input check for REPL loops #602 ); lg.NS / Def / DefShadowing (feat(api): namespace facade — lg.NS with Def/DefShadowing #603 ).
Behavior changes to note for the release
Consumer- and embedder-facing; confirm wording before the tag:
Known open items that touch the cut
Already filed; decide accept / fix / defer before tagging:
Issue
Why it matters for the cut
#700
Bytecode invoke ~1.7× costlier since #645 ; explains residual reduce / some / etc. cost after #686
#663
Startup ~5 ms → ~9 ms unnoticed; ratchet not in the everyday loop
#705
Perf gate can report green through a regression (budget, filter, soft-else)
#704
Generated-primitive guards can pass when their premise breaks
#660 / #678
Silent AOT fallback; 6/16 gold-aot fixtures Tier-2 under strict
#607
lower-vm embedded fallback rejected (capability mask 0x1 vs 0x0); Gloat regression
#636
Self tail call lowers to a Go call (stack growth once AOT), constant-space on VM
#681 (PR)
Phase-1 backend parity / strict-mode audit: makes the #660 /#678 frontier visible in CI
In-flight PRs worth naming in scope freeze (not a full queue): #681 , #706 , #649 , #675 , #692 , #501 /#502 , #624 , #641 , #683 , #713 .
Downstream dependencies
Pre-release checklist
Scope frozen — list squeeze-ins still allowed vs deferred to the next tag
Close or retarget Gather requirements for release v1.12.0 #545 so this issue is the live release home
Size + perf audit vs v1.12.2 : startup (lg -e '(+ 1 1)'), reduce / invoke micros (vm: bytecode invoke is ~1.7x costlier since #645 (explicit frame chain) #700 ), WASM, make bench-ratchet / interleaved A/B where relevant
Confirm Three gaps that let the perf gate report green through a regression #705 holes are either fixed or explicitly accepted for this cut
AOT matrix: default lg-compile, --entry-frame, lower-vm (AOT lower-vm: embedded VM-fallback bundle rejected by its own runtime — unsupported capability mask 0x1 (supported: 0x0) #607 ), strict Tier-1 vs Tier-2 (strict-mode AOT: 6/16 gold-aot fixtures only run via silent fallback — binding conveyance, @f deref rot, closure capture untracked #678 / test(parity): gate complete-corpus strict capability and engine output #681 )
Release hook green — go test -short path that tag-push runs
Upgrade notes: breaking chore(rt): drop 34 unreferenced per-file core embeds superseded by coreFS #604 , toolchain build: single-source Go toolchain via go.mod toolchain directive #677 , #595 host input, #628 RunExecUnit / --entry-frame
Draft release + announcement; attribution pass
Tag (version TBD below)
Open questions
Add other release-worthy items or blockers below.
Tracking issue to scope the next cut after v1.12.2 (2026-07-20), modeled on #275 / #545. About 55 commits have landed on
mainsince that tag (through #628,f3ca5f9b, 2026-08-11), with another ~20 open PRs in flight. Freeze scope here, draft the upgrade notes, run the pre-release checks, and list blockers before we tag.#545 still tracks the v1.12.0 cut that already shipped (v1.12.0–v1.12.2). Close or retarget it so release tracking has one live home.
Scope snapshot
Range
v1.12.2..main@f3ca5f9b: 55 merged PRs (~54k insertions / ~8k deletions across ~237 files). Headline arcs:Frame.Runis Go-recursive — deep lg→lg recursion aborts the process #644), with a measured per-invoke cost tracked in vm: bytecode invoke is ~1.7x costlier since #645 (explicit frame chain) #700. Follow-ups: vm: drop leaveFrame's unused *Frame parameter to unpin f from memory #706, Design: constant-space tail calls on the explicit-frame VM (closures, multi-arity, apply) #620, perf(vm): re-evaluate static self-call shortcut after shared frame transitions #646.clojure.coredirect-call natives (perf(rt): direct-call natives for the hot clojure.core surface #613); hoist of 222 primitives to//lg:native(feat(rt): hoist 222 clojure.core primitives to named //lg:native decls #639); per-package registrar (feat: per-package //lg:native registrar surface (migrate corefns) #640). Shadowedreduceregistration fixed in perf(rt): restore reduce's ArrayVector and Range fast paths #686; remaining guard gaps in Three generated-primitive guards pass when their premise breaks #704 / Retire the twelve hand registrations the generated registrar shadows #696 / Drain the remaining hand registrations in pkg/rt onto //lg:native #697.lg-compile --entry-frame(feat(aot): generate native-entry Go frame from main/-main (#425 Item 1) #628, closes AOT native-entry: generate the Go entry frame, self-containgogen, and stop the silent perf-cliff #425 Item 1 / AOT entry frame: recover the lowered signature from gogen as data, not by string-matching rendered Go #657). Silent fallback and strict Tier-2 fixtures: Lowering falls back to bytecode silently, and only the bench harness notices #660, strict-mode AOT: 6/16 gold-aot fixtures only run via silent fallback — binding conveyance, @f deref rot, closure capture untracked #678; parity gate PR test(parity): gate complete-corpus strict capability and engine output #681.go.modtoolchain go1.26.5(build: single-source Go toolchain via go.mod toolchain directive #677); named capability rejects (feat(bytecode): actionable hint on capability-mask reject #608, feat(bytecode): name capabilities in reject errors and lg -v #622); Var metadata bundle round-trip +clojure.repl/clojure.pprint(feat(clojure): add clojure.repl / clojure.pprint, fix Var metadata bundle round-trip #668);lg_no_httpbuild tag (build: addlg_no_httpto dropnet/httpfrom the runtime (#652) #658).lg.IsIncomplete(feat(api): IsIncomplete — sanctioned incomplete-input check for REPL loops #602);lg.NS/Def/DefShadowing(feat(api): namespace facade — lg.NS with Def/DefShadowing #603).Behavior changes to note for the release
Consumer- and embedder-facing; confirm wording before the tag:
rt.SetSrc,rt.TestSrc, …) superseded bycoreFS. No known public callers found at review time; still name it in the upgrade notes.toolchaindirective (build: single-source Go toolchain via go.mod toolchain directive #677).RunExecUnitload path (feat(aot): generate native-entry Go frame from main/-main (#425 Item 1) #628): even without--entry-frame,RunExecUnitnow loads viaLoadProgramNamespaces(NSOrder replay +ApplyGoOverridesdrain) andRunProgramMainChunk. Orchestrators that assumed the old MainChunk-skip loop should re-check (Gloat lower-vm; see also AOT lower-vm: embedded VM-fallback bundle rejected by its own runtime —unsupported capability mask 0x1 (supported: 0x0)#607).--entry-frame: opt-in native-entrymain.go; defaultlg-compileremains package-only for orchestrators that own their own frame..lgb/ Var metadata (feat(clojure): add clojure.repl / clojure.pprint, fix Var metadata bundle round-trip #668)::arglists/ source location metadata round-trips through the bundle; core bundle regenerated.lg -vnaming; mask compatibility rules unchanged in intent. Verify against AOT lower-vm: embedded VM-fallback bundle rejected by its own runtime —unsupported capability mask 0x1 (supported: 0x0)#607 before advertising lower-vm.Known open items that touch the cut
Already filed; decide accept / fix / defer before tagging:
reduce/some/ etc. cost after #686capability mask 0x1vs0x0); Gloat regressionIn-flight PRs worth naming in scope freeze (not a full queue): #681, #706, #649, #675, #692, #501/#502, #624, #641, #683, #713.
Downstream dependencies
RunExecUnitor lower-vm consumers should exercise tip with and without--entry-frame, and confirm AOT lower-vm: embedded VM-fallback bundle rejected by its own runtime —unsupported capability mask 0x1 (supported: 0x0)#607 status.Pre-release checklist
lg -e '(+ 1 1)'),reduce/ invoke micros (vm: bytecode invoke is ~1.7x costlier since #645 (explicit frame chain) #700), WASM,make bench-ratchet/ interleaved A/B where relevantlg-compile,--entry-frame, lower-vm (AOT lower-vm: embedded VM-fallback bundle rejected by its own runtime —unsupported capability mask 0x1 (supported: 0x0)#607), strict Tier-1 vs Tier-2 (strict-mode AOT: 6/16 gold-aot fixtures only run via silent fallback — binding conveyance, @f deref rot, closure capture untracked #678 / test(parity): gate complete-corpus strict capability and engine output #681)go test -shortpath that tag-push runs#595host input,#628RunExecUnit/--entry-frameOpen questions
unsupported capability mask 0x1 (supported: 0x0)#607 a release blocker for advertising AOT / lower-vm, or a known-limitation note?Add other release-worthy items or blockers below.