# Vocabulary **In one sentence:** the vocabulary is everything a package declares before the first rule: individual types (`entity`), assertion signatures (`relation`), closed lists (`enum`), named values (`const`), and visibility (`pub`). The author always takes the vocabulary first: without a declared name any literal is a `check` rejection, and there is nothing to write a rule about. The language specification treats the vocabulary as the package header: entities, relations, enumerations, constants, and visibility are declared before the first rule, and every literal is checked against them. The judgment channel (relations answered by an organ, not by facts) lives on the [judgment-channel page](/constructs/judgment-channel/). ## 1. When to use and when not to | Instead | Selection rule | |---|---| | `relation` vs an entity field | An `entity { field: Type; }` body holds only internal immutable fields. Everything that changes over time, is contested, or is established by a case is a relation. Criterion: the value arrives as a fact — therefore `relation` | | `kind empirical` vs `kind institutional` | An observable case fact (measurement, event) is `empirical`; a status or qualification established by law is `institutional`; rule-head-inferred is `derived`. `kind` is metadata, it does not change truth, but its lies are expensive: another’s `kind` confuses the analysis reader | | `enum` vs an open relation | A closed list (classes, ranks) is an `enum`: members are incomparable with another enumeration (`TYPE_ERROR` at runtime, `LDC-E2122` at `check`), there is no order. An open set is a relation with a parameter | | `const Name = entity_ref(…)` vs a bare name | An individual gets a name only through `const`: a bare name in term position must resolve to a declaration, otherwise `LDC-E1330`. `registered_in(c, Astana)` without `const Astana` is a rejection, not “a new individual” | | `key(c)` vs a second rule | A key is an integrity restriction: two tuples with one key projection give issue `KEY_CONFLICT`, the evaluator picks nothing and deletes nothing. The “latest/correct” of the two is not by key but by rule priority or a decision table | ## 2. Minimal example Package `research.vocabulary.company_registry`: entities, a named individual via `const`, a rate ceiling via `const Decimal`, an enumeration of classes, relations with keys, and three strict reader rules: ```law entity Company { label ru-KZ official "Компания"; } entity Region { label ru-KZ official "Регион"; } const CAPITAL: Region = entity_ref("urn:case:research:vocabulary:capital") { label ru-KZ official "столичный регион"; }; pub const MAX_RATE: Decimal = 25 percent; enum LicenceClass { first; second; third; } relation registered_in(c: Company, r: Region) kind institutional { key(c); } relation licence_class(c: Company, k: LicenceClass) kind institutional { key(c); } relation rate_applied(c: Company, r: Decimal) kind empirical { key(c); } rule CapitalCompany strict { for c: Company; when registered_in(c, CAPITAL); then capital_company(c); } rule FirstClass strict { for c: Company; for k: LicenceClass; when licence_class(c, k) and k == first; then first_class(c); } ``` Case facts: `registered_in(alpha, capital)` with `origin case_input`. Query: `evaluate truth(capital_company(alpha))`. The `CAPITAL` constant is dereferenced before evaluation, so the fact about `entity_ref("urn:case:research:vocabulary:capital")` and the rule about `CAPITAL` concern one individual. Actual engine answer: ```text law test research.vocabulary.company_registry: мир research.vocabulary.company_registry ok [research.vocabulary.company_registry#authored] tests/01-capital-company.lawtest / urn:query:research-vocabulary-01 ok [research.vocabulary.company_registry#authored] tests/02-first-class.lawtest / urn:query:research-vocabulary-02 итого: 2 проверено, 2 прошли, 0 не прошли, 0 не исполнены; код 0 ``` `law engine check` — `check OK`, no warnings. Sensitivity: `licence_class(alpha, second)` gives `first_class(alpha)` = Not established, not refuted (the second test): a different enumeration member — the rule stays silent. An enumeration member is written bare (`second`) — it is the same node as `LicenceClass.second`. Second package `research.vocabulary.subtype_key`: a subtype `entity Branch : Company` and a key. A branch fits the `Company` slot: the `BranchRegion` rule reads `registered_in(b, r)` through the supertype. Two regions of one branch give Established plus issue `KEY_CONFLICT` (`expect issue(KEY_CONFLICT)`); one region — Established without issues, `law test` — 2/2. Sensitivity: removing the second fact removes both the conflict and the second support. ## 3. Example by domain - **Standards:** package `scrum.guide` (Scrum Guide) — `pub enum DeveloperAccountability` with a label and members (see the [corpus forms](/constructs/vocabulary/corpus-forms/)): `pub enum` exports the type and every member. - **Law (sanctions):** package `us.ofac.fifty_percent` (OFAC 50% rule, US sanctions) — subtypes `entity BlockedPerson : Party` and `entity Entity : Party`: party roles as subtypes, not flags. - **Historical law:** package `eng.corpus.statutes_of_apparel_1574` (Statutes of Apparel 1574, England) — a series of `const …: Rank = entity_ref(…)` with labels: nine of the corpus’s ten constants are named individuals, not numbers. - **Finance:** package `us.fnma.selling_income` (FNMA income rules, US) — relations with `key(src)` and a comment on the honest `KEY_CONFLICT` instead of a silent pick: a model of documenting a key. ## 4. How the engine answers Table — actual runs of this section’s teaching packages: | Facts | Question | Answer | Why | |---|---|---|---| | `registered_in(alpha, capital)` | `capital_company(alpha)` | Established | `CAPITAL` dereferenced to the same `entity_ref` | | `licence_class(alpha, second)` | `first_class(alpha)` | Not established, not refuted | different enumeration member | | two regions of one branch | `branch_region` | Established + `KEY_CONFLICT` | key violated, facts not deleted | | one branch region | `branch_region` | Established, issues empty | counterfactual: the key alone declares the conflict | | `branch_office`, branch `registered_in` | `branch_region` | Established | branch is a company subtype | - Entity identity is the “nominal type, StableId” pair: one row in `Company` and in `Region` are different values; no implicit conversions. - An enumeration member is a value, and it is its identity: the guard `k == first` compares StableIds; dotted, bare, and qualified spellings are one constant reference. - A constant through a constant unfolds recursively, in one pre-pass over the program and the case. - On the rate value: `20 percent` against the `25 percent` ceiling — in the case language; the threshold is written as the guard `r <= MAX_RATE`, there are no const-percents in the corpus. On this section’s teaching packages a numeric vocabulary guard is not fixed by a run (in `company-registry` the `WithinCap` rule exists, but there is no test with `rate_applied`) — the claim of its firing is marked here as “not checked”. Additionally, further checked behaviours of the earlier edition (not fixed by a run in these teaching packages): | Facts | Question | Answer | Why | |---|---|---|---| | `registered_in(alpha, north)` | `capital_company(alpha)` | Not established, not refuted | a different individual; the rule stays silent, it does not refuse | | `rate_applied(alpha, 20 percent)` | `within_cap(alpha)` | Established | rate within `MAX_RATE` | | `rate_applied(beta, 30 percent)` | `within_cap(beta)` | Not established, not refuted | above the ceiling — the rule stays silent | | `licence_class(alpha, first)` | `first_class(alpha)` | Established | an enumeration member as a value | | `licence_class(alpha, first)` | `reliable(alpha)` | Not established, not refuted + `REQUIRES_JUDGMENT` | the judge did not answer: `good_standing` is a judgment channel (the channel itself lives on the [judgment-channel page](/constructs/judgment-channel/)) | | `risk_level(alpha, high)` | `audit_flag(alpha)` | Established | the dotted spelling `RiskLevel.high` is the same member | | `registered_in(alpha, capital)` and `(alpha, north)` | `capital_company(alpha)` | Established + `KEY_CONFLICT` | an observation expecting `KEY_CONFLICT` | ## 5. Common mistakes 1. An individual name without declaration — `LDC-E1330` (pitfalls, item 1). 2. A field in a constant’s label block — `LDC-E0201` (pitfalls, item 2). 3. A hard-keyword name (`LDC-E0203`) and arity off-declaration (`LDC-E2103`) (pitfalls, item 3). 4. A constant type not matching the initializer — `LDC-E2111`; prose-style percentage and money types are not resolved by the compiler (pitfalls, item 4). 5. A subtype the wrong way round — `LDC-E2104` (pitfalls, item 5). 6. Members of different enumerations in one guard — `LDC-E2122` (pitfalls, item 6). 7. A constant through itself — silent `check`, `CYCLIC_CONSTANT` at runtime (pitfalls, item 7). ## 6. References - Neighbour pages: [strict rules](/constructs/rule-strict/), [facts and evidence](/constructs/facts-and-evidence/). - The first-vocabulary tutorial lives in the [tutorials catalogue](/tutorials/first-package/). - The judgment channel (`external judgment relation`, `REQUIRES_JUDGMENT`) lives on the [judgment-channel page](/constructs/judgment-channel/); the syntax is in section 7 below. - The pitfalls page lists the diagnostics (`LDC-E1330`, `LDC-E0201`, `LDC-E0203`, `LDC-E2103`, `LDC-E2111`, `LDC-E2104`, `LDC-E2122`) with wrong forms and fixes. ## 7. Grammar excerpts Declaration visibility (who sees the symbol): ```ebnf top_declaration = { annotation }, [ visibility ], declaration ; visibility = "pub" | "internal" ; ``` Entity and subtype (the `entity_decl` production): ```ebnf entity_decl = "entity", identifier, [ ":", type_ref ], [ "{", { field_decl | label_item | metadata_item }, "}" ], [ ";" ] ; ``` Enumeration (the `enum_decl`, `enum_variant` productions; separators — the `= "string"` form out of slice 0.1 — `LDC-E0206`): ```ebnf enum_decl = "enum", identifier, "{", { label_item }, enum_variant, { enum_variant | label_item }, "}" ; (* Errata E-0082: разделитель вариантов необязателен и допускает запятую. Перепись корпуса: 193 варианта записаны через `;`, 98 через `,`; обе реализации принимают и смешанную запись, и вовсе бессоюзную. Форма `= string_literal` остаётся ЗАРЕЗЕРВИРОВАННОЙ (вне среза 0.1, LDC-E0206). *) enum_variant = identifier, [ "=", string_literal ], [ ";" | "," ] ; ``` Constant (the `const_decl` production; after the expression the body admits only a label): ```ebnf const_decl = "const", identifier, ":", type_ref, "=", expression, ( ";" | "{", { label_item }, "}", [ ";" ] ) ; ``` Relation and key (the `relation_decl`, `relation_item`, `relation_kind` productions): ```ebnf relation_decl = "relation", identifier, "(", parameter_list, ")", [ "kind", relation_kind ], ( ";" | "{", { relation_item }, "}" ) ; relation_item = "key", "(", identifier, { ",", identifier }, ")", ";" | label_item | metadata_item ; relation_kind = "empirical" | "institutional" | "evaluative" | "derived" | "normative_auxiliary" | "external" ; ``` Symbol parameters (the `parameter_list`, `parameter` productions): ```ebnf parameter_list = [ parameter, { ",", parameter }, [ "," ] ] ; parameter = identifier, ":", type_ref, [ "{", { label_item }, "}" ] ; ``` Judgment channel: block content (the `external_judgment_item` production; semantics and behaviour live on the [judgment-channel page](/constructs/judgment-channel/)): ```ebnf external_judgment_item = "authority", identifier, ";" | "request_schema", type_ref, ";" | label_item ; ```