docs← Back to article

Markdown for LLMs

First package: from rule to answer

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

Download this articlePlain text ↗
# First package: from rule to answer

Dana sent Aigerim a model of access to the rare collections and an example
of its application. Researcher Ivanova is listed in the registry, and her
accreditation is valid. Under the archive rule she may enter the room.
Aigerim wants to check how this conclusion follows from the record Dana
prepared.

First she will repeat the example unchanged. Then she will remove the
accreditation evidence and ask the same question. If access can no longer
be established, will that mean Ivanova was refused?

We will carry out both checks together with her. The Archive of Veliky
Ustin, its rules, and the people in the story are fictional; the example
is given in full on this page. If you want to run it right away, go to
the ["Run"](#run-get-the-answer) section.

## Question: does access follow from this evidence?

The archive rule requires two conditions: the reader must be listed in
the researcher registry and hold a valid accreditation. About Ivanova we
know both. That should be enough to conclude access. We do not add the
conclusion itself to the input evidence: the check has to derive it
by the rule.

First, let us write down the expected answers in plain words:

| Evidence about Ivanova | Expected answer about access |
|---|---|
| Registry entry and a valid accreditation | Established |
| Registry entry; no accreditation evidence | Neither established nor refuted |

In the second row, evidence of accreditation is missing for the
conclusion. At the same time, nothing in our example states that Ivanova
was refused. We cannot yet justify either access or its denial. Below we
will see how Arxo denotes these answers.

## Record: the rule

This page can be passed to the compiler as a package source file.
It reads together all blocks marked `law` and skips the explanations
between them. So there is no need to move the code into a separate file
to check the example.

Let us start with the rule itself. The variable `p` denotes the person
in question; `Person` states its type. After `when` come two conditions
joined by `and`. After `then` stands the conclusion that follows
when they hold.

```law
@source(ARCHIVE_RULES_P4)
rule RareRoomAccess strict {
    for p: Person;
    when in_researcher_registry(p) and accredited(p);
    then may_enter_rare_room(p);
}
```

`RareRoomAccess` is the rule name: by it we will recognise this rule in
the explanation of the answer. The `strict` marker sets a strict rule.
There are no exceptions or priorities in our example yet.

The names `in_researcher_registry`, `accredited`, and `may_enter_rare_room`
denote three relations: a person is listed in the registry, is accredited,
and is admitted to the room. Their full declarations are in the "Record,
continued" section below. First we will get the answer, then return to
the structure of the package.

The `@source(ARCHIVE_RULES_P4)` reference points to the fragment of the
archive rules, which is also given at the end of the page. Compare the
record after `when` with the Russian phrase: both must keep the two
conditions required at the same time.

## Run: get the answer

To run it you will need a copy of the repository and Rust with Cargo
installed. Open a terminal at the repository root and run the commands
below. Run all later commands in the same terminal window:
it will keep the directory and file names we are about to set.
The first run may take some time to build.

```bash
cd engines/lawc
tutorial_dir=../../docs/tutorials
tutorial_page="$tutorial_dir/01-first-package.en.law.md"
cargo run -q --profile gate -p law-cli -- check \
    "$tutorial_page"
tutorial_work=$(mktemp -d)
cargo run -q --profile gate -p law-cli -- lower \
    "$tutorial_page" > "$tutorial_work/program.lawir.json"
```

The `check` command verifies that the package is written correctly:
whether the names used are declared, whether the types agree, and whether
the source text matches the pinned hash. The `lower` command prepares
the program for running and saves it into a temporary directory.

Warning `LDC-E1314` means that tests are not part of the program itself.
Their evidence and expectations are used only when checking concrete
cases. That is why below we will pass the program and the test as separate
command arguments.

Now let us state the evidence about Ivanova and the question of her
access. For this we use a test. The `given` section lists what is given;
the `evaluate` line states the question; the `expect` line states the
expected answer. The first row of our table corresponds to the designation
`TRUE_ONLY`: the statement is established, with no grounds to deny it.

```law
test "Иванова: реестр и аккредитация дают допуск" {
    given {
        context {
            decision_time @2026-03-01T09:00:00+05:00;
            knowledge_time @2026-03-01T09:00:00+05:00;
            legal_time @2026-03-01;
            timezone "Asia/Almaty";
        }
        assert in_researcher_registry(entity_ref("urn:tutorial:ivanova")) {
            id "assert-reg";
            origin case_input;
        }
        assert accredited(entity_ref("urn:tutorial:ivanova")) {
            id "assert-acc";
            origin case_input;
        }
    }
    evaluate truth(may_enter_rare_room(entity_ref("urn:tutorial:ivanova")));
    expect truth_status == TRUE_ONLY;
}
```

The test name reads: "Ivanova: registry and accreditation grant access."

Two `assert` records state that Ivanova is listed in the registry and
holds an accreditation. Both use the same reference
`entity_ref("urn:tutorial:ivanova")`, so they speak about one person.
Each record has its own `id` name; the `origin case_input` marker means
the evidence is entered as input data of this case.

The `context` section fixes the date on which we ask the question, the
moment of decision, the moment bounding our evidence, and the time zone.
We will examine these distinctions in detail in the chapter on time. For
now we keep the context the same in both experiments, so that only one
change is tested.

A ready-made test for this case ships with the tutorial.
The first command runs the check, and the second shows the explanation
of the answer:

```bash
cargo run -q --profile gate -p law-cli -- test \
    "$tutorial_dir/tests/01-with-accreditation.lawtest" \
    --lawtest --program "$tutorial_work/program.lawir.json"
cargo run -q --profile gate -p law-cli -- explain \
    "$tutorial_dir/tests/01-with-accreditation.lawtest" \
    --program "$tutorial_work/program.lawir.json"
```

A `test PASS` message means the answer obtained matched the expected
`TRUE_ONLY`. In the explanation, find the `RareRoomAccess` rule and the
two records: Ivanova's registry entry and her accreditation. Together
they allow the access conclusion to be derived.

The `expect` line is there to compare the result with our expectation.
It adds no facts and does not affect the derivation. Had we entered
the access itself into the input evidence in advance, such an example
would not show whether the rule can derive it from the two conditions.

## Practice: change one ground

Now prepare the second case yourself. Copy the first test
into a temporary directory:

```bash
tutorial_try=$(mktemp -d)
cp "$tutorial_dir/tests/01-with-accreditation.lawtest" \
    "$tutorial_try/try.lawtest"
```

Open the `try.lawtest` file in the created directory. Delete from it
the whole `assert accredited(...) { … }` block, including the `id` and
`origin` lines inside the braces. Keep the registry record, the question,
and the `TRUE_ONLY` expectation unchanged. Before running the test,
explain why the previous answer should no longer be obtained.

```bash
cargo run -q --profile gate -p law-cli -- test \
    "$tutorial_try/try.lawtest" \
    --lawtest --program "$tutorial_work/program.lawir.json"
```

The check should finish with a `FAIL` message: we expected `TRUE_ONLY`
but got `NEITHER`. The second designation means "neither established
nor refuted". The accreditation evidence is gone, so the rule no longer
allows access to be derived. No grounds for a negative conclusion
appeared in our example either.

Now correct the expectation to `NEITHER` and repeat the command. The test
should pass. We changed the expectation for a clear reason: one of the
necessary conditions is no longer confirmed. In other tasks, an unexpected
result likewise needs to be explained first; simply replacing the
expectation with the obtained answer would drain the test of meaning.

A ready-made solution ships with the tutorial. Compare your
record with it. Then try adding a rule yourself
in [the two-reading-rooms exercise](/tutorials/exercise-first-package/).

## Record, continued: vocabulary and source

Let us return to those parts of the package that were needed for the run
but have so far been left without a detailed explanation.

At the start of the record come the language and its version, the package
name and version, and the `namespace`. It lets same-named designations
from different packages be told apart. The language version and the version
of the particular package are stated separately.

```law
language "law.core" version "0.2";
package tutorial.archive version "0.1.0";
namespace "urn:law:tutorial:archive";

entity Person;

relation in_researcher_registry(p: Person) kind institutional;
relation accredited(p: Person) kind institutional;
relation may_enter_rare_room(p: Person) kind institutional;
```

The `entity Person` line declares the type of objects — people. Each
`relation` line introduces a relation that can be used in statements
and rules. The `p: Person` parameter states that this relation concerns
a person.

The `institutional` marker means the relation is tied to an institutional
status or decision. In this example `accredited` reports a valid
accreditation on the date of the question. We do not yet compute its
period of validity: the needed evidence is already given in the setup.
More about objects and ways of describing them can be read
on [the vocabulary page](/constructs/vocabulary/).

It remains to state the source of the rule. This takes three declarations:
`source` names the document, `edition` its edition, `fragment` the
fragment we used. The `@source` reference before the `RareRoomAccess`
rule leads exactly to this fragment.

```law
source ARCHIVE_RULES {
    kind municipal_act;
    jurisdiction VELIKY_USTIN;
    number "2026-14";
}

edition ARCHIVE_RULES_2026_RU of ARCHIVE_RULES {
    language ru;
    officiality official;
    adopted @2026-01-15;
    in_force [@2026-02-01, infinity);
}

fragment ARCHIVE_RULES_P4 in ARCHIVE_RULES_2026_RU {
    kind paragraph;
    locator "paragraph/4";
    text ru official """Читатель допускается в зал редких фондов, если он состоит в реестре
исследователей и имеет действующую аккредитацию.
""";
    content_hash "sha256:7f76a4311e52b9af58fcf3175f613794316583ae19c4f0767d0570774a456688";
}
```

The quoted act text reads: "A reader is admitted to the rare-collections room if listed in the researcher registry and holding a valid accreditation."

Here the edition was adopted on 15 January 2026 and is in force from
1 February inclusive. No end date is set. These dates, like the `official`
marker, belong to the fictional rules of the teaching archive.

The `content_hash` field holds the hash of the text. During checking it
is recomputed and compared with the recorded value. Exact bytes count,
including line breaks. This is how a changed fragment can be detected.
The hash does not confirm that we read it correctly: the meaning of the
Russian phrase and of the recorded rule must be compared separately. We
will return to working with documents and editions in the lesson
about [the real source](/tutorials/real-article-source/).

## Acceptance: what you can check yourself

Before moving on, make sure you can repeat the experiment
and explain its result.

- With both pieces of input evidence present, access is established: the answer is `TRUE_ONLY`.
- After removing the accreditation evidence, the answer changes to `NEITHER`.
- If the previous expectation is kept, the test fails.
- In the explanation of the first answer, the rule and both of its premises are visible.
- The access statement itself is absent from the input evidence.

Also check how a change of the source is detected. Make a copy of the
page and replace in the fragment text «зал редких фондов» ("rare-collections
room") with «зал редкого фонда», keeping the same `content_hash`. Run the
`check` command for that copy. It should report an `LDC-E5201` error: the
hash of the changed text does not match the recorded one. After the
experiment, restore the original phrase.

## Boundary: what this answer does not yet establish

Aigerim managed to repeat Dana's result and found out which evidence it
needs. But in this experiment we did not check the authenticity of the
pass, the completeness of the registry, or the actual visit to the
archive. Established access alone does not mean Ivanova has already
entered the room. Such questions will need other evidence and rules.

We also saw that removing the accreditation evidence changes the answer
about access but does not turn it into a refusal. **If there are not
enough grounds for a conclusion, that does not yet give grounds for
its denial.**

So far we have needed two designations: `TRUE_ONLY` and `NEITHER`.
What happens with a negative statement or a contradiction is covered
in the lesson
["Four states of support"](/tutorials/four-states/).