docs← Back to article

Markdown for LLMs

A case package from a directory

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# A case package from a directory

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 case

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.

## What is in the directory

| Path | What it holds |
|---|---|
| `cases/delo.lawcase` | the case: context, evidence and accepted facts |
| `law.toml`, `law.lock` | the package manifest and the pinned dependencies |
| `queries/*.json` | saved 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:

```text
$ 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
```

## 1. Add the documents

`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:

```text
$ 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`.

## 2. Propose the facts

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

```text
$ 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.

## 3. Accept them

```text
$ 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:

```text
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.

## 4. Get the answers

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

```text
$ 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`.

## 5. Correct a fact

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:

```text
$ 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.

## 6. Compare the revisions

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

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

The diff names what changed and why:

| Question | Revision 1 | Revision 2 |
|---|---|---|
| `payment-due-day` | 2026-08-12 | same |
| `payment-made-late` | `TRUE_ONLY` | same |
| `late-payment-penalty-amount` | 4 020 KZT | **2 680 KZT** |
| `positions` | as above | same |

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.

## What the case knew on a date

`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:

```text
$ 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

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](/agent-engineering/case-lifecycle/).