Skip to content
docs
Arxo ↗

A case package from a directory

For LLMs10 sections

A case package is a directory that holds one case together with everything needed to recompute it: the case file, the documents, the proposed and accepted facts, the saved questions and the pinned canon. After this page you can follow one case from a document to an answer, correct a fact, and show what the correction changed.

The rule to keep in mind from the start: a document in the package does not assert anything by itself. A fact enters the case only when someone proposes it and someone accepts it, and both steps are recorded.

The example is the worked case dva-dokumenta-i-zamena-vyplaty (“two documents and a replaced payment”) that ships with the canon of the Kazakhstan law on compulsory motor third-party insurance. A claim with a complete set of documents reached the insurer on 22 July 2026. The law gives the insurer fifteen working days to pay, so on the official calendar the payment was due by 12 August 2026. A late payment owes a penalty, counted from the next day at 16.75 % a year on 730 000 KZT.

The payment document says the insurer paid on 24 August: twelve days late, a penalty of 4 020 KZT. Later the operator learns the actual date was 20 August: eight days late, 2 680 KZT. The package records both revisions. The predicate and entity names are the canon’s own, in transliterated Russian; the commands below run from the package directory.

PathWhat it holds
cases/delo.lawcasethe case: context, evidence and accepted facts
law.toml, law.lockthe package manifest and the pinned dependencies
queries/*.jsonsaved questions
resources/documents/copies of the documents, pinned by hash
analysis/proposals/proposed facts and their history
revisions/saved answers, one archive per revision

The case is called Delo, and it has four saved questions:

Output
$ law case questions
SOURCE ID KIND PARAMETERS
saved late-payment-penalty-amount collect
saved payment-due-day collect
saved payment-made-late truth
saved positions positions

law case document add copies a file into resources/documents/, records its hash in the case and in law.lock, and names it as evidence:

Output
$ law case document add resources/payment.txt --case Delo --as PaymentDoc \
--type kz.corpus.ogpo_documents::PaymentDocument \
--observed 2026-08-24T12:00:00+05:00 --recorded 2026-08-24T12:00:00+05:00
{"case":"Delo","contentHash":"sha256:5da879ea…","evidence":"PaymentDoc","id":"Delo-PaymentDoc","path":"resources/documents/payment.txt"}

The claim is added the same way, as ClaimDoc. The case file now has two evidence entries and no new facts: asking the questions at this point still gives NEITHER for payment-made-late.

A proposal is a typed fact that waits for acceptance. Submit a file of facts with --from, naming who proposes and when:

Output
$ law case facts propose --case Delo --from analysis/facts-r1.json \
--by urn:example:operator --at 2026-09-15T12:00:00+05:00
{"added":["p-0001",…,"p-0008"],"case":"Delo","package":"examples.ogpovts.dva_dokumenta_i_zamena_vyplaty","path":"analysis/proposals/Delo.json"}

Eight proposals land in analysis/proposals/Delo.json, among them p-0005, “the payment was made on 24 August”, linked to PaymentDoc. The case file is unchanged: proposals do not count.

To enter one fact by hand, name the predicate and its declared parameters: --predicate den_ispolneniya_denezhnogo_obyazatelstva --arg demand=… --arg day=2026-08-19. --document PaymentDoc --quote "…" links such a fact to the passage it was read from.

Output
$ law case facts accept p-0005 --case Delo --by urn:example:operator --at 2026-09-15T12:00:00+05:00
{"case":"Delo","id":"p-0005","newId":null,"status":"accepted"}

Accepting p-0005 writes an assertion into cases/delo.lawcase, with the document it rests on:

Output
assert "p-0005": kz.corpus.ogpovts::strakhovaya_vyplata_osushchestvlena(trebovanie, @2026-08-24) { origin case_input; evidence PaymentDoc; }

The proposal store keeps an accepted event with the time, the person and the proposal’s hash. The other seven proposals are accepted the same way.

law case check asks every saved question; law ask --out saves the same answers as a revision archive:

Output
$ law ask --all-cases --query-json queries/payment-due-day.json --query-json queries/payment-made-late.json \
--query-json queries/late-payment-penalty-amount.json --query-json queries/positions.json \
--out revisions/r1.arxo

Revision 1 says: the payment was due on 2026-08-12; payment-made-late is TRUE_ONLY; the penalty is 4 020 KZT; the duty to pay within the term is SATISFIED and the duty to pay the penalty is ACTIVE.

The operator learns that the money arrived on 20 August. A fact is not edited in place: the old proposal is replaced by a new one, with a reason, and the new one must be accepted like any other:

Output
$ law case facts replace p-0005 --case Delo --from analysis/facts-r2-payment.json \
--by urn:example:operator --at 2026-09-16T12:00:00+05:00 --reason "уточнена дата фактического исполнения"
{"case":"Delo","id":"p-0005","newId":"p-0009","status":"replaced"}
$ law case facts accept p-0009 --case Delo --by urn:example:operator --at 2026-09-16T12:00:00+05:00
{"case":"Delo","id":"p-0009","newId":null,"status":"accepted"}

The reason reads “actual payment date clarified”. The same is done for the day the money obligation was performed (p-0007 → p-0010). Between replace and accept, the case has no payment date at all, and payment-made-late answers NEITHER: the new date is only proposed. The replaced assertion leaves the case file, but its history stays in the proposal store. facts revoke removes an assertion without a replacement, also keeping the history.

Save the answers again as revisions/r2.arxo and compare:

Output
$ law case diff revisions/r1.arxo revisions/r2.arxo --json

The diff names what changed and why:

QuestionRevision 1Revision 2
payment-due-day2026-08-12same
payment-made-lateTRUE_ONLYsame
late-payment-penalty-amount4 020 KZT2 680 KZT
positionsas abovesame

Its inputs.assertions lists the cause: p-0005 and p-0007 removed, p-0009 and p-0010 added, each with its literal and evidence — p-0005 rested on PaymentDoc, p-0009 on no document. The pinned dependencies are equal on both sides, so the change comes from the facts, not from the law.

The walk ends here. You have taken one case from documents to an answer, corrected a fact the recorded way, and shown what the correction changed.

law case check --as-of TIME recomputes the answers from the facts accepted by that time, in a temporary copy; the package itself is not changed:

Output
$ law case check --as-of 2026-09-15T18:00:00+05:00
SNAPSHOT AT 2026-09-15T18:00:00+05:00: excluded assertions ["p-0009","p-0010"], documents []; restored ["p-0005","p-0007"]

On 15 September the case still held the 24 August date, so this snapshot gives revision 1’s answers.

The same operations from code and from an agent

Section titled “The same operations from code and from an agent”

Every step above has the same transaction behind the CLI, the SDKs and MCP; for the same input the bytes match.

  • Node: openCasePackage(dir) from @arxo/law/case-package, with addDocument, proposeFacts, acceptFact, revokeFact, replaceFact and check.
  • Python: arxo.open_case_package(dir), with add_document, propose_facts and the rest under the same names.
  • Both ask through the engine’s wasm ask operation, and run edits through the law binary. The binary comes from the law option or ARXO_LAW_BINARY, in Node also from @arxo/cli, otherwise law on PATH.
  • Local MCP: law_case_ask takes a saved queryId, or a card with args. Edits are the editing facet of the local profile only: law_case_document, law_case_propose, law_case_facts, law_case_decide, law_case_check; asOf is the date snapshot.

Building an agent around these operations — proposing, accepting, retracting, and replacing facts, recomputing dependents, resuming after a pause — is the topic of Correct, resume and recheck a case.

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

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