Skip to content
docs
Arxo ↗

What we talk about: object, name, and record

For LLMs6 sections

Aigerim opens the registry Dana sent. In it, two researchers are recorded identically: “Ivanova A. S.”. The first one has two accreditation records: an old one, whose validity has expired, and a new one. About the second there is no such evidence. How can the accreditation of each be answered without attributing one person’s evidence to the other?

Let us start by telling apart the person, her name, and the record about her. Two people may share a name, and one person may correspond to several records. These distinctions must be kept in the model. For that we will compose a vocabulary: declare the object types and the relations with which we will describe people and their accreditation.

The Archive of Veliky Ustin, its registry, and the people in the story are fictional. The whole example is given on this page. If you want to run it right away, go to the “Run” section.

Question: how does a person differ from a record about her?

Section titled “Question: how does a person differ from a record about her?”

In this lesson we will treat accreditation as established when a valid accreditation record corresponds to the person. We will check two cases: first two Ivanovas, then two records of one of them. In both cases we need to see which object each piece of evidence concerns.

First, let us write down the expected answers in plain words. We add an error check to them: what happens if a number is given instead of a name?

EvidenceExpected answer
Two Ivanovas; only the first has a valid recordThe second one’s accreditation is neither established nor refuted
One Ivanova; the old record has expired, the new one is validAccreditation established
A number given instead of a nameType error when checking the package

Matching names give no grounds to treat the second Ivanova as accredited. The old record does not cancel the new one. And a number instead of a name breaks the record form we are about to set in the vocabulary.

The first chapter needed the Person type, denoting people. Now we add a Record type for accreditation records. A record also becomes an object in its own right: it can be given a status and linked to a particular person.

For statuses we introduce a RecordStatus enumeration with two values: Active — the record is valid, Expired — its validity has lapsed. A parameter of this type takes one of the listed values. The enumeration itself, however, does not forbid several statements about one record’s status. Such a restriction would need a separate entry in the model.

Arxo Law
language "law.core" version "0.2";
package tutorial.archive version "0.1.1";
namespace "urn:law:tutorial:archive";
entity Person;
entity Record;
enum RecordStatus { Active; Expired }
relation person_name(p: Person, name: Text) kind empirical;
relation accreditation_record(r: Record, p: Person) kind institutional;
relation record_status(r: Record, s: RecordStatus) kind institutional;
relation accredited(p: Person) kind institutional;

After each relation name, its parameters are listed in parentheses: what we pass, in which order, and what type each value must be. This description is called a signature.

The person_name relation links a person to her name. The first parameter has type Person, the second Text, the built-in type for text. There is an Integer type for whole numbers and a Date type for dates. The accreditation_record relation links a record to a person, and record_status a record to its status. The order matters: in accreditation_record the record comes first, then the person.

The empirical marker on person_name means we describe observed evidence: which name stands in the registry. The institutional marker on the other relations points to their link with institutional decisions and statuses. These markers characterise the meaning of relations; the concrete source of each piece of evidence must be stated separately.

Now let us write the rule. The variable p denotes the person, r the record. They are declared by the for p: Person and for r: Record lines. After when stand two conditions: the record belongs to this person and has the Active status. When both hold, the rule allows her accreditation to be established.

Arxo Law
rule AccreditedByActiveRecord strict {
for p: Person;
for r: Record;
when accreditation_record(r, p) and record_status(r, Active);
then accredited(p);
}

Note: there is no person_name relation in the rule. Deriving the conclusion needs the record-to-person link and the record’s status. That is why matching names alone do not carry accreditation from one Ivanova to the other.

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 further commands in the same window: it will keep the paths you set. As in the first chapter, check will verify the package, and lower will prepare the program and save it into a temporary directory.

Terminal
cd engines/lawc
tutorial_dir=../../docs/tutorials
tutorial_page="$tutorial_dir/01-vocabulary.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 first test describes two Ivanovas. Each person is matched with her own entity_ref: urn:tutorial:ivanova and urn:tutorial:ivanova-2. Their names are identical, their references differ. By these references the model tells people apart.

The accreditation record has a reference of its own: urn:tutorial:rec-2026. We link it only to the first Ivanova and state the Active status. In the evaluate line we ask about the accreditation of the second. The expected NEITHER answer means the accreditation is neither established nor refuted.

Arxo 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 person_name(
entity_ref("urn:tutorial:ivanova"),
"Иванова А. С.") {
id "name-1";
origin case_input;
}
assert person_name(
entity_ref("urn:tutorial:ivanova-2"),
"Иванова А. С.") {
id "name-2";
origin case_input;
}
assert accreditation_record(
entity_ref("urn:tutorial:rec-2026"),
entity_ref("urn:tutorial:ivanova")) {
id "rec-new";
origin case_input;
}
assert record_status(entity_ref("urn:tutorial:rec-2026"), Active) {
id "status-new";
origin case_input;
}
}
evaluate truth(accredited(entity_ref("urn:tutorial:ivanova-2")));
expect truth_status == NEITHER;
}

The test name reads: “Two Ivanovas: a shared name does not merge people.”

Terminal
cargo run -q --profile gate -p law-cli -- test \
"$tutorial_dir/tests/01-vocabulary-two-ivanovas.lawtest" \
--lawtest --program "$tutorial_work/program.lawir.json"

A test PASS message confirms the expected NEITHER answer. The input evidence holds no accreditation record for the second Ivanova. The first one’s name matches hers, but that is not enough to apply the rule. At the same time, the missing record does not yet mean the second Ivanova’s accreditation is refuted.

In the second test we consider one Ivanova and her two records. The old one, rec-2024, has expired; the new one, rec-2026, is valid. Each record has its own reference and status, so the rule conditions can be checked for each of them separately.

Arxo 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 accreditation_record(
entity_ref("urn:tutorial:rec-2024"),
entity_ref("urn:tutorial:ivanova")) {
id "rec-old";
origin case_input;
}
assert record_status(entity_ref("urn:tutorial:rec-2024"), Expired) {
id "status-old";
origin case_input;
}
assert accreditation_record(
entity_ref("urn:tutorial:rec-2026"),
entity_ref("urn:tutorial:ivanova")) {
id "rec-new";
origin case_input;
}
assert record_status(entity_ref("urn:tutorial:rec-2026"), Active) {
id "status-new";
origin case_input;
}
}
evaluate truth(accredited(entity_ref("urn:tutorial:ivanova")));
expect truth_status == TRUE_ONLY;
}

The test name reads: “Two records: the valid one counts.”

Terminal
cargo run -q --profile gate -p law-cli -- test \
"$tutorial_dir/tests/01-vocabulary-two-records.lawtest" \
--lawtest --program "$tutorial_work/program.lawir.json"
cargo run -q --profile gate -p law-cli -- explain \
"$tutorial_dir/tests/01-vocabulary-two-records.lawtest" \
--program "$tutorial_work/program.lawir.json"

The test should finish with a test PASS message: accreditation is established, the answer is TRUE_ONLY. In the explanation, find the AccreditedByActiveRecord rule and the evidence about the rec-2026 record: whom it belongs to and in which status it is. Together they give grounds for the conclusion.

The old rec-2024 record does not satisfy the Active condition. Moreover, our rule has no conclusion of missing accreditation from the Expired status. So the old record does not refute the result obtained via the new one. We kept both records and can explain which of them supports the answer.

Make a copy of the ready-made two-Ivanovas test file in a temporary directory. In the test command, give the path to this copy instead of the original file. The prepared program stays the same.

First change only the question: in the evaluate line replace ivanova-2 with ivanova. Now we ask about the first Ivanova, who has a valid record. Before running the test, explain why you expect TRUE_ONLY, and put that status in the expect line. The test should pass. You may also change the name in one of the person_name lines: it will not affect the answer, since the name is not among the rule conditions.

For the next experiment, again take a copy of the original test with the question about the second Ivanova and the NEITHER expectation. In the statement named rec-new, replace the urn:tutorial:ivanova reference with urn:tutorial:ivanova-2. Now the record belongs to the second Ivanova. Keep the previous expectation and run the test: it should finish with FAIL, because the obtained answer became TRUE_ONLY. The record-to-person link changed, and the conclusion followed it.

Finally, check how a wrong value type is detected. Make a copy of this page and in the first test replace the "Иванова А. С." text (“Ivanova A. S.”) with the number 42 without quotes. Run the check command for the copy. It should report an LDC-E2104 error: an Integer number was passed, while the name parameter requires Text. The compiler does not turn a number into a name automatically; such a record must be fixed before running.

Check that you can repeat both cases and explain the results:

  • Matching names do not merge two Ivanovas. In the first case the answer about the second is NEITHER, about the first TRUE_ONLY.
  • One Ivanova may have two separate records. The valid one lets accreditation be established: the answer is TRUE_ONLY.
  • If the valid record is linked to another person, the answer changes. Changing the name text does not affect the conclusion.
  • A number instead of a name gives an LDC-E2104 error when checking the package.

Package checking detects a number where text is required and compares the argument count against the relation declaration. But a typo in a name is still text. A wrong record-to-person link may also be written in a type-correct way. The model will reason over the evidence we passed to it.

Handle entity_ref references with particular care. The type of such a reference is set by the relation parameter in which it is used. The words ivanova and rec-2026 inside the reference help us read the example, but by themselves they do not declare a person or a record. If in the accreditation_record statement these references are swapped, the compiler may accept the record: the first argument is used as a Record, the second as a Person. But then the needed link to the Active record is lost. So when checking input evidence, it matters to verify both the argument order and what each reference denotes. This is examined in more detail on the vocabulary reference.

We did not compute validity periods here either. The Active and Expired statuses were given in the input evidence. Checking a status against dates would need the dates themselves and a matching rule.

Now Aigerim can tell apart two people with the same name and explain which of several records supports the conclusion. To understand the answer, you need to know which object each piece of input evidence speaks about.

In these examples we again obtained TRUE_ONLY and NEITHER. What the two remaining states mean, and how to work with contradicting statements, is covered in the lesson “Four states of support”.

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

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