Skip to content
docs
Arxo ↗

Versioning

For LLMs5 sections

An answer from the deadline example is reproducible only under the pins that produced it. This page names the four version axes, the checklist for moving any of them, and the rule for old captures: replay under old pins, recompute under new ones, never overwrite.

Output
docs/build/examples/deadline-app
AxisPinned whereCurrent value
SDK packagepackage.json@arxo/law 0.3.3, arxo 0.2.0 (Python)
Canon packagepackage.json@arxo/canon-bgb-fristen 0.1.5
Canon model versionopenModel in src/runtime.tsde.bgb.fristen@0.1.0
Adapter and capture formatsrc/to-case.ts, src/capture.tsADAPTER_VERSION 1.0.0, deadline-app.capture/1

Each axis moves for its own reason:

  • SDK package. New engine or facade behavior. Answers keep their statuses and values across compatible SDK releases, but bytes may move: replays stay within one SDK.
  • Canon package. New canon build: regenerated bindings, corrected metadata, repackaged engine files. The model version it carries may or may not move with it — check the package notes against the model pin.
  • Canon model version. New formalization: changed rules, changed questions. A model move can change values and statuses, not just bytes.
  • Adapter and capture format. New mapping from form fields to facts (toFacts, toCaseInput) or a new capture layout. The adapter version is stamped into every capture so a replay knows which mapping produced it.

The worked case pins all four: the packages above, the model de.bgb.fristen@0.1.0, the adapter 1.0.0, the capture format deadline-app.capture/1, the time zone Europe/Berlin, and the policy urn:de:corpus:clir:bgb-fristen#BGB_FRISTEN_TAG.

A capture under CAPTURE_FORMAT deadline-app.capture/1 carries its pins with the answer, so a replay later still knows its terms:

  • the form: eventDate, durationDays, candidateEnd, legalTime;
  • the adapter version ADAPTER_VERSION 1.0.0;
  • the SDK and canon package versions;
  • the model version de.bgb.fristen@0.1.0, the time zone, and the policy;
  • the answer: statuses, proof identifiers, the three hashes, and the canonical document as documentBase64 with its sha256.

verifyCaptureIntegrity checks the bytes against the recorded hash before replayCapture trusts them; either step fails closed.

  1. Change one axis at a time and note the old and new values.
  2. Reinstall from the lockfile (npm ci) so the tree matches the pins.
  3. Run the full suite: npm test, the typecheck, and the Python checks. Read every failure as a behavior statement before touching code.
  4. Compare the worked case: collect must still compute 2026-03-20 with COMPUTED, truth must still answer TRUE_ONLY, the wrong-date and partial cases must still answer NEITHER, and whyNot must still return 2 blockers — unless the upgrade note says otherwise, in which case the note is the new expectation and the suite is updated first.
  5. If bytes moved but values did not, refresh the snapshots from runs you have read, one SDK at a time.
  6. If the adapter moved, bump ADAPTER_VERSION, keep the old mapping readable for old captures, and add a regression case for the changed mapping.
  7. If the capture format moved, bump CAPTURE_FORMAT, keep verifyCaptureIntegrity strict on both formats, and never rewrite old files into the new layout in place.
  • Replay old. To reproduce an old answer, restore its pins — SDK, canon package, model version, adapter — and run replayCapture (the replay command or the replay endpoint). Replay re-runs the stored query and compares the result hash; the checksum step separately verifies the stored document bytes. Neither step establishes byte-equality of the old and new documents, and neither checks the capture’s metadata: restoring the recorded pins is the operator’s job, because the code does not verify the installed environment against them.
  • Recompute new. To answer under new pins, run evaluate again and store a new capture file. Never overwrite the old file: the old capture remains the record of what the old pins answered.
Output
old pins + old capture -> replayCapture (must match)
new pins + same form -> evaluate (new file in captures/)

Cross-SDK replay is out of scope in both directions: a capture saved by TypeScript is replayed by TypeScript, and a capture saved by Python is replayed by Python. The statuses and values agree; the bytes do not. Keep the old pins installed next to the new ones (separate checkouts or separate machines) while old answers must stay reproducible during an upgrade window.

Documentation for Arxo. Writings — blog.arxo.io.

Anonymous visit counts on stats.arxo.io, no cookies.