# What we talk about: object, name, and record 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"](#run-get-the-answer) section. ## 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? | Evidence | Expected answer | |---|---| | Two Ivanovas; only the first has a valid record | The second one's accreditation is neither established nor refuted | | One Ivanova; the old record has expired, the new one is valid | Accreditation established | | A number given instead of a name | Type 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. ## Record: 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. ```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. ```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. ## Run: get the answer 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. ```bash 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. ```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." ```bash 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. ```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." ```bash 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. ## Practice: mix up and catch 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. ## Acceptance: what you can check yourself 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. ## Boundary: what types do not check 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](/constructs/vocabulary/). 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"](/tutorials/four-states/).