Compatibility
Four matrices: which released versions work together, which operations each facade ships, where each facade runs, and what touches the network. Every matrix names its sources, so a version bump becomes a list of fields and declarations to re-check.
Version matrix
Section titled “Version matrix”All four packages below are published versions; the SDK versions match the repository manifests, and the canon version matches the canon manifest inside each package.
| SDK | Canon package | Canon (model) |
|---|---|---|
@arxo/law 0.3.3 (TypeScript) | @arxo/canon-bgb-fristen 0.1.5 | de.bgb.fristen 0.1.0 |
arxo 0.2.0 (Python) | arxo-canon-bgb-fristen 0.1.1 | de.bgb.fristen 0.1.0 |
@arxo/law 0.3.3 facade manifest: name and version fields@arxo/canon-bgb-fristen 0.1.5 canon manifest: name and version fieldsarxo 0.2.0 pyproject: version field; needs-python >= 3.12arxo-canon-bgb-fristen 0.1.1 pyproject: version fieldde.bgb.fristen 0.1.0 canon package-meta: name and version fieldsThe canon manifest pins the linked world by hash (contentHash over
world.lawir.json, the package hash over package.lawir.json), and
the lock file pins the de.bgb.core dependency, the calendar
resource, and the resolution hash. The loading chapter shows both
documents. One limit: the two facades do not produce byte-identical
documents for the same question — replay with the facade that
recorded the answer.
Capability matrix
Section titled “Capability matrix”“Yes” means the operation exists in the shipped API quoted on the facade pages; “no” means it is absent, with the workaround beside it.
| Operation | TypeScript | Python |
|---|---|---|
open(spec, options) | Yes | Yes, dict options |
truth | Yes | Yes |
focused_truth | focusedTruth | No — ask truth |
why_not | whyNot | why_not / whyNot |
collect | Yes, ?name or {args, free} | Yes, ?name or {args, free, comprehension} |
deadline (calendar_op) | Yes | Yes |
calc (term) | Yes | Yes |
positions | Yes | Yes |
unfold | Yes, sync, no case needed | No — read at author time |
questions manifest | Yes | No — read at author time |
passport / inModel | Yes | Yes, in_model / inModel |
explain | Yes, needs the host | Yes, needs the host |
verbalize | Yes, needs engine and pack | No |
ask (uniform request) | Yes, 7 kinds | Yes, 6 kinds (no focused_truth) |
parseSpec | Yes | Yes, parse_spec |
TS LawPackage surface canonical declarations: class LawPackage blockTS AskRequest kinds canonical declarations: AskRequest typePython LawPackage package module: LawPackage methods ask/truth/why_not/collect/deadline/calc/positionsPython ask kinds package module: ask dispatch (truth/why_not/collect/calendar_op/term/positions)Environment matrix
Section titled “Environment matrix”| Facade | Runs on | Engine | Notes |
|---|---|---|---|
| TypeScript, Node | Node 20 minimum, 24 LTS recommended | Packaged law_wasm_core.wasm | Full surface; checkout trees, cache, registry |
| TypeScript, browser | Modern browsers | wasm bytes passed in | No Node-only imports; canons from the bundle, pins for Cache Storage |
| TypeScript, serve mode | Any with fetch | None local — the server | open with serve returns ServePackage |
| Python | Any OS with Python 3.12+ | Bundled law_wasm_core.wasm via wasmtime | No registry, remote, or router in this release |
Node floor facade manifest engines field; quickstart asks for Node 20+Browser entry browser declarations: BrowserOpenOptions with wasm/canons/pinsPython floor pyproject requires-python >= 3.12Python engine engine module: bundled wasm path via wasmtimeServe mode facade declarations: ServePackage and connectServeNetwork matrix
Section titled “Network matrix”After install, the default path is offline: installed canons answer from local bytes checked against their manifest hashes.
| Path | Network? | Notes |
|---|---|---|
TS open, installed canon | No | Bytes checked against contentHash, then parsed |
TS open, checkout tree | No | local root/map/packages |
TS open, disk cache | No | Keyed by content hash |
TS open, registry | Yes | Skipped with offline: true |
TS explain | Yes | Host law_explain over the carried document |
TS verbalize | No | Local; needs the full engine and a pack |
| TS serve mode | Yes | Every question goes to the server |
| TS router | Yes | Routes over HTTP |
Python open | No | Installed canon, checkout tree, or cache only |
Python explain | Yes | MCP client on first use; offline refuses |
| Python queries | No | Local engine always |
TS sources open module: installed/tree/cache sources offline, registry unless offlineTS canon check canon source module: digest-then-parse against package-meta contentHashTS explain LawPackage: host law_explain over the carried documentPython sources open module: canon/tree/cache; registry fetch not in this releasePython explain package module: host client on first use; offline raises TransportErrorProbe record
Section titled “Probe record”The examples on these pages are one probed scenario, run on the
versions above: event on 6 March 2026, a duration of 14 calendar days,
candidate end 20 March 2026, legal time 17 September 2026, time zone
Europe/Berlin, counting policy BGB_FRISTEN_TAG.
collect frist_ende(frist, ?end) COMPUTED 2026-03-20truth frist_ende(frist, 2026-03-20) COMPUTED TRUE_ONLYtruth frist_ende(frist, <wrong date>) COMPUTED NEITHERtruth frist_ende(frist, 2026-03-20), partial case COMPUTED NEITHERwhy_not over the partial case 2 blockers, one per candidate rulesources on every answer above []hashes on every answer above program, semantic, resultThe partial case removes the duration fact; the two blockers name the premises each candidate rule was waiting for. Re-run this probe after any version move: the verdicts must match, and the program hash names the new build.
How to read a cell
Section titled “How to read a cell”Each matrix row ends in a pointer: a manifest field, a declaration block, or a module. When a version moves, open the pointer first and update the cell from what it says. For the worked case behind these pages, see the quickstart and the deadline app.
Verification record
Section titled “Verification record”The example, the pins, the commands, and their observed results for the versions above:
example deadline-app 0.1.0 (29 files, sha256 in the Start chapter)pins @arxo/law 0.3.3, @arxo/canon-bgb-fristen 0.1.5, arxo 0.2.0, arxo-canon-bgb-fristen 0.1.1, model de.bgb.fristen@0.1.0, adapter 1.0.0checked 2026-10-03, Node v20.20.2 and v24.21.0 (63/63 + typecheck clean on both; v24 reporter prints `ℹ` summaries), Python 3.13$ cd docs/build/examples/deadline-app && npm test# tests 63, # pass 63, # fail 0$ npm run typecheck # tsc --noEmit, clean$ python3 python/test_deadline.py10/10 passed$ node docs/build/tools/check-fences.mjsfences checked: 53, verbatim: 39, allowlisted: 14, failures: 0The site build enforces the documentation half of this record:
content:strict runs the prose and link gates, and
deadline-app:archive:check fails the build when the published
zip, sidecar, or release manifest drifts from the example sources.
Before publishing, one more check compares the pages with a fresh run:
$ node docs/build/tools/check-release.mjsrelease: 10 passed, 0 failedIt re-runs the suite and asserts the archive, the manifest, the
Start checksum and file count, every quoted test count, the
fences, and the typecheck. Published bytes are immutable
under their name: changed sources ship as a new package version
with a new archive name, never as a silent rewrite. The strict
HTTP run (npm run test:http:strict in the unpacked archive,
where sockets listen) belongs to the same pre-publish pass.
Re-run the probe above and these commands after any version move;
if a verdict changes, the matrices on this page change with it.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.