Repository navigation
Rete 0.3.6
Where 0.3.6 is published: every channel. crates.io (rete-core,
rete-graph, rete-cli, rete-wasm), PyPI and npm (rete-graph), the
GitHub release with its native archives, browser bundle, Blender add-on and
the Claude Desktop extension (rete-0.3.6.mcpb, and rete.mcpb behind the
releases/latest/download/rete.mcpb link), the container images on GHCR
(rete-cli, rete-relay, rete-dev), the Pyodide fallback wheel, and the
desktop File Explorer installers. The extension is no longer uploaded to the
bucket; the copies there stay at 0.3.5.
What 0.3.6 changes on top of 0.3.5:
- Behaviour change: property-path alternatives and sequences keep their
duplicates.?s (:a|:b) ?oand a sequence inside an alternative now
return one solution per matching path, as SPARQL 1.1 §18.4 defines them,
where 0.3.5 returned each pair once. Counts over such paths can go up
(DataCite: 8,897 → 8,929 for?s (dcite:cites|dcite:references) <doi>);
addDISTINCTto count nodes rather than paths.*,+,?and
negated property sets are unchanged. Details below. - SPARQL runs under a memory budget.
rete sparqlandrete sparql-url
take--memory-budget-mb(default 4096,0= unlimited), and
Rete::open_ranged_lazyapplies the same default, so the Python, R and
Java clients and the relay are bounded too.rete verifystreams the file
instead of reading it whole. - Join planning follows the data's size. Lazy opens estimate each
pattern from the tile directory and pick the join order and method from
it; DataCite queries that ran out of memory at 16 GB now answer in seconds. COUNT(DISTINCT …)is exact and bounded, spilling sorted runs to
TMPDIRpast the budget.- The Claude Desktop extension downloads from GitHub releases
(https://github.com/caviri/rete/releases/latest/download/rete.mcpb). - Security: the TLS certificate checks are patched.
rustls-webpki
0.103.16 (RUSTSEC-2026-0382) andwebpki-roots1.0.10
(RUSTSEC-2026-0381). These advisories are what kept 0.3.5 off crates.io,
which goes from 0.3.4 straight to 0.3.6. Details below.
Repository-only changes in this release, with no effect on the published
packages: the DataCite converter keeps one identity per registered DOI and
guards its build (#312), and the dataset pipelines under scripts/ moved to
a separate dataset repository (#313).
Security
rustls-webpki0.103.16 andwebpki-roots1.0.10 (were 0.103.15 and
1.0.7–1.0.9 across the workspace, Python, R and File Explorer lockfiles),
fixing RUSTSEC-2026-0382 (certificate verification could accept distrusted
intermediates) and RUSTSEC-2026-0381 (the bundled roots trusted distrusted
emSign intermediates) in the TLS stack behind remote reads over HTTPS. The
browser engine does not link either crate.
Changed
- The Claude Desktop extension downloads from GitHub releases. Every
v*
release attaches the bundle asrete-<version>.mcpband, same bytes, as
rete.mcpb, both inSHA256SUMSand both attested, so
https://github.com/caviri/rete/releases/latest/download/rete.mcpbalways
serves the Latest release's build. The README,docs/agents.mdand
clients/mcpb/README.mdlink there.clients/mcpb/publish.sh, the manual
R2 upload, is removed and is no longer a release step; the objects under
https://data.graphplaza.com/mcpb/are left in place, frozen at 0.3.5, so
existing links keep working.
Fixed
- Property-path alternatives keep SPARQL's duplicates.
?s (:a|:b) ?o
is the union of the two branches (SPARQL 1.1 §18.4), so a pair both
predicates connect is two solutions; rete evaluated every path as a set and
returned it once. A sequence nested inside an alternative ((:a/:b)|:c) was
deduplicated the same way. Both now keep their multiplicities;*,+,
?and negated property sets stay sets, as the spec defines them. On
DataCite?s (dcite:cites|dcite:references) <doi>now counts 8,929 — the
1,218citesplus 7,711referencesof the equivalentUNION— instead of
8,897 (32 records state both). UseSELECT DISTINCTto count nodes rather
than paths. COUNT(DISTINCT …)is bounded and exact. It kept every distinct value
in an ordered set (about 40 bytes each), soCOUNT(DISTINCT ?r)over the
610 M PID relations of DataCite ran out of memory at 16 GB. Distinct values
are now a sorted, deduplicated buffer of dictionary ids (8 bytes each); past
an eighth of the memory budget (512 MiB by default,Rete::spill_threshold)
it is written toTMPDIRas sorted delta-encoded runs and counted by
merging them. That query now returns 609,765,497 (the card's count of
dcite:PidRelation) in 47 s at 1.5 GB peak RSS, and the ten
COUNT(DISTINCT ?s)invariant checks drop from 3.5–5.3 GB to 1.3–1.5 GB,
with identical answers. A resident open spills at the same threshold when
the command has a budget (rete sparqlalways does); the browser engine
never spills.- Join order and join method follow the data's size. Without a resident
pyramid (every lazy open, every file built with--memory-budget-mb) the
planner ordered patterns by how many constants they had and pushed
?s a :Classto the end, so on DataCite?s a dcite:Service ; dcite:publicationYear ?ystarted from the 109 M years and ran out of memory
at 16 GB, although there are 517 services. The planner now estimates each
pattern from the tile directory (tiles routed × triples per tile; no read,
and per class), looks a pattern up per row when the rows found so far are
at least 16 times fewer than the pattern (a bound subject becomes an SPO
range read), streams the whole join when even the most selective pattern is
large (per-row lookups, small patterns hashed, two large subject-sharing
patterns merge-joined), and lands sub-select rows as dictionary ids instead
of strings. On DataCite: the class × predicate joins run in 1.1–56 s within
4.5 GB (were out of memory),?r dcite:relationSubject <doi> . ?r ?p ?oin
0.9 s (was out of memory, then 968 s), the bound-subject chainse_join_a/
e_join_bin 0.9 s (were 32 and 54 s),?s dcite:doi ?d . ?s dcite:fromSnapshot ?xin 17 s at 1.1 GB (was out of memory). Results are
unchanged, except that aLIMITwithoutORDER BYmay return a different
(equally valid) page. rete sparqland every lazily-opened file now run under a memory
budget. The dictionary chunk cache, the index tile cache and the raw block
cache of a lazy open were unbounded on every query path (onlyrete export
capped them), so a whole-graph scan kept everything it touched: on the 49 GB,
9.53 B-triple DataCite fileGROUP BY ?pwas killed at 16 GB and a
CONTAINSover every title peaked at 15.1 GB.rete sparqland
rete sparql-urltake--memory-budget-mb N(default 4096,0=
unlimited) with the same split asrete export, and
Rete::open_ranged_lazyapplies the 4096 MiB default itself, so the Python,
R and Java clients and the relay are bounded too (not the browser engine).
The per-tile group directories that point lookups build now live in the tile
cache and are evicted with their tile; they used to stay resident forever
and could outgrow the tiles. The per-query term and number memos are capped
at 64 MiB each. A local file goes to the lazy reader once it is larger than
a quarter of the budget (1 GiB at the default, as before). Answers are
unchanged (75 DataCite QA queries, 36 queries on three smaller files and
the W3C suite compared). On DataCite,GROUP BY ?pnow completes (876 s,
1.1 GB peak RSS), theCONTAINScount peaks at 4.0 GB instead of 15.1 GB,
and?r dcite:relationSubject <doi> . ?r ?p ?ocompletes in 1.1 GB, though
it still scans the whole graph until the join planner is fixed. See "Memory
budget" indocs/sparql.mdfor what the budget does not cover.rete verifystreams. It read the whole file into memory, so a 49 GB
file could not be verified in a capped container; it now hashes the sections
in 8 MiB reads (rete_core::verify_ranged).
Install, artifact list, download verification and known limitations: release guide. Full history: CHANGELOG.md.