Stop matching :bb in reader conditionals - #896
Open
yogthos wants to merge 5 commits into
Open
Conversation
added 3 commits
September 8, 2026 13:15
On the JVM seqable? is an instance? test over Seqable / ISeq / Iterable, plus arrays, CharSequence and Map. Jolt built it out of coll?, which a bare deftype is not, so it answered false for values seq works on perfectly well — a (reify Iterable ...), a (deftype T [] Seqable (seq [_] ...)), and clojure.core.Eduction, the one in core. The predicate reads the same per-method probes the seq arms in records-dispatch.ss read, rather than a second list of interface names, so the two answers cannot drift apart again. jrec-declares-coll-iface? is deliberately not it: that name list is the collection-behaviour set and ILookup, Counted and Associative are in it, none of which is Seqable on the JVM — the corpus has a row pinning an ILookup-only deftype as neither coll? nor seqable?. Found through malli's :every schema, which tests seqability before it walks: (m/validate [:every :int] (eduction (map identity) [1 2 3])) was false and (m/parser [:every :any]) answered ::invalid on an eduction. Claude-Session: https://claude.ai/code/session_017f4uwd9Mq3Bn6NZLzBsjCT
The feature set is {:jolt :clj :default} again. 0.7.10 added :bb on the theory
that a :bb branch solves the same non-JVM problems jolt has. It does not: a :bb
branch is written for babashka's host model, and where that model differs from
jolt's the branch is wrong here. The branch a library writes for a host with no
java.nio and no reflection is not the branch for a host that has both.
Measured against the checkouts this repo gates, matching :bb cost:
- claxon and aws-api write #?(:bb [cheshire.core] :clj [clojure.data.json]).
jolt has no cheshire, so a working library became a load failure.
- lasertag: 2 failures from :bb branches asserting sci.impl.fns class names and
babashka's class-as-symbol hierarchies. 49/9 -> 51/7.
- tick: 1 failure from a :bb branch asserting babashka's English-only locale
rendering, where jolt renders the French through jolt-lang/time. 722/1 -> 723/0.
- markdown-clj: two assertions jolt passes, gated away. 180 -> 182.
- cts: 89 assertions hidden across 13 namespaces, and two ##NaN divergences with
them. descendants goes green (its 3 failures WERE the :bb branch); eq, not-eq
and num pick up rows that are the float/integer box model and the two NaN
entries now in known-divergences.
- honeysql orders #?(:bb … :clj (.sym ^Keyword k)) with :bb first at all three
sites, so jolt never reached its own keyword-direct-emit path. Tally unchanged.
jolt.bb.fs and the loader's namespace-supplement seam existed only to fill the
babashka.fs/list-dir a :bb branch skips; babashka.fs defines it off its own :clj
branch now, which is the one jolt's java.nio shims target. vendor/process goes
back to upstream babashka/process — the fork's only patch was a :jolt arm
working around the empty :bb splice, and process-test's timed-deref row pins it.
malli's row is not re-recorded here: its :bb branch swapped m/eval's evaluator
for load-string, so the suite needs sci, and sci 0.12.51 from Maven does not
load on jolt (jolt-l7tq). It points at vendor/sci instead and gets the timeout
the full assertion set needs.
A project that wants :bb read asks for it with :jolt/features.
Reported by @markokocic in #893.
Claude-Session: https://claude.ai/code/session_017f4uwd9Mq3Bn6NZLzBsjCT
…ot carry
jolt reads #?() against {:jolt :clj :default}. A project widens that for the
whole program with
{:jolt/features [:bb]}
which is what a script ported from babashka wants now that jolt does not match
:bb itself. Additive: it can add a key, never remove one, so :clj still reads
and a :jolt clause still wins over both — a project cannot make jolt stop
reading the branches its own stdlib is written against.
The project's alone, like :jolt/replaces and :jolt/provides and for the same
reason: the feature set decides which branch EVERY library in the program is
read through, so a dependency must not change it underneath. Installed in
apply-project! ahead of the class providers, because those matter at the first
class reference and this one at the first form read.
Two smoke rows, both directions: with the key a :bb clause wins and the set has
four members; without it the same expression reads :clj and the set has three.
Claude-Session: https://claude.ai/code/session_017f4uwd9Mq3Bn6NZLzBsjCT
added 2 commits
September 8, 2026 13:46
Better on every counter, three effects and no regression: - the suite :bb-gated roughly half its assertions and jolt was reading those branches. malli.parser-test alone goes 1754 -> 8224 passing: its ensure-parser-type helper is #?(:bb nil :default …), so every call was vacuous. - sci is on the classpath now, so the 72 ::sci-not-available errors m/eval raised are gone. - seqable? answers for a declared Seqable/Iterable, so :every over an eduction validates and parses — the 104 identical? failures in parser-test and 12 in core-test. The row is the heaviest in the gate now: ~15GB RSS and ~30 CPU-minutes, which is what the 2400s timeout is for. Its comment said the suite was :bb-gated as if that were the recorded state; rewritten to say where the residue actually sits. Claude-Session: https://claude.ai/code/session_017f4uwd9Mq3Bn6NZLzBsjCT
The seed records line numbers, so the comment edits in analyzer.clj and backend_scheme.clj move it even though no behaviour changed; records-gambit.ss is generated from records-dispatch.ss among others, so iface-seqable? has to be mirrored there. Converged in 2 passes. Claude-Session: https://claude.ai/code/session_017f4uwd9Mq3Bn6NZLzBsjCT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #893.
Stacked on #894 (base
fix/wp-trace-getenv-load-order) — it re-records the sametwo libconformance rows this touches, and one of them moves again here.
The reader feature set is
{:jolt :clj :default}again. 0.7.10 added:bbonthe theory that a
:bbbranch solves the same non-JVM problems jolt has. Itdoes not. A
:bbbranch is written for babashka's host model, and the branch alibrary writes for a host with no
java.nioand no reflection is not the branchfor a host that has both.
Measured, matching
:bbcost::bbsrc)FileNotFoundException: cheshire/core— will not load:bbbranches)#?(:bb [cheshire.core] :clj [clojure.data.json]).jolt has no cheshire, so matching
:bbturned a working library into a loadfailure.
:bbbranches assertingsci.impl.fnsclass names andbabashka's class-as-symbol hierarchies; tick's was a
:bbbranch assertingbabashka's English-only locale rendering, where jolt renders the French
through jolt-lang/time.
descendantsgoes green — its 3 failures were the:bbbranch.eq,not-eqandnumpick up rows: three are the float/integer box model,and two are
##NaNdivergences:bbhad been hiding, now inknown-divergences with
:checks.#?(:bb … :clj (.sym ^Keyword k))with:bbfirst at allthree
.symsites, so jolt never reached its ownkeyword-direct-emitpath.Same tally, and
analyzer.clj/backend_scheme.cljno longer claim otherwise.jolt.bb.fsand the loader's namespace-supplement seam existed only to fill thebabashka.fs/list-dira:bbbranch skips. babashka.fs defines it off its own:cljbranch now — theDirectoryStreamimport,Files/newDirectoryStream,the
reify DirectoryStream$Filterand(with-open [s …] (vec s))all workhere, and
fs-testpasses unchanged.vendor/processgoes back to upstreambabashka/process: the fork's only patch was a
:joltarm working around theempty
:bbsplice, andprocess-test's timed-deref row pins the behaviour.seqable?(first commit, independent)seqable?was built out ofcoll?, so it answered false for a baredeftypeor
reifydeclaringSeqableorIterable— and forclojure.core.Eduction,the one in core — while
seqworked on all of them. malli's:everytestsseqability before it walks, so
(m/validate [:every :int] (eduction …))wasfalse. The predicate now reads the same per-method probes the
seqarms read,so the two answers cannot drift apart;
jrec-declares-coll-iface?isdeliberately not it, since
ILookupandCountedare in that list and neitheris
Seqableon the JVM (corpus has the row).:jolt/features{:paths ["src"] :jolt/features [:bb]}for a script ported from babashka whose
:bbbranches are the ones its authorwants. Additive — it can add a key, never remove one — and the project's alone,
like
:jolt/replaces, because the feature set decides which branch everylibrary in the program is read through. Installed ahead of the class providers,
since those matter at the first class reference and this at the first form read.
malli
6757/36/34 -> 13261/28/10 — better on every counter.
malli.sci's:bbbranch swapsm/eval's whole evaluator forload-string, so the suite's ~12k assertionswere running with
m/evalstubbed and roughly half of them gated away(
ensure-parser-typeis#?(:bb nil :default …)). Without:bbthe suiteneeds sci, and sci 0.12.51 from Maven does not load on jolt — its
copy-varsplices the dereffed value of a macro var straight into theemitted form, and a raw procedure is not a form jolt's analyzer takes. Filed as
jolt-l7tq; the recipe points at
vendor/sci(the copymake sciandmake scifunctionalalready gate), which clears all 72::sci-not-availableerrors,and takes the timeout the full assertion set needs.
Three effects, no regression on any counter: half the suite was
:bb-gated(
malli.parser-testalone goes 1754 -> 8224 passing assertions — itsensure-parser-typehelper is#?(:bb nil :default …), so every call wasvacuous), sci clears the 72 errors, and the
seqable?fix clears the 104identical?failures in parser-test plus 12 in core-test.It is now the heaviest row in the gate by a wide margin: ~15GB RSS and ~30
CPU-minutes, hence
:timeout 2400and the runner's existingJOLT_MAX_HEAP=off. Worth a look if CI machines are smaller than this one.Gates
make testgreen — 104 ci targets + selfhost byte fixpoint.make libconformanceon the seven affected rows: 3 ok, 4 better, 0 regressed.Three things only the full gate caught, all in the last commit: the seed
records line numbers, so the comment edits in
analyzer.cljandbackend_scheme.cljmove it (make remint, converged in 2 passes); andrecords-gambit.ssis generated fromrecords-dispatch.ssamong others, soiface-seqable?had to be mirrored (make gambitgen,make gambitseed).Site pages for
cljc-interop,differencesandtools-depsare injolt-lang/jolt-lang.github.io#29.
https://claude.ai/code/session_017f4uwd9Mq3Bn6NZLzBsjCT