# Modeling vocabulary: entities, relations, enums, constants Vocabulary is the shared language a package speaks: the kinds of things it talks about, the statements it can make, and the fixed values it reuses. Rules, norms, and cases all sit on top of this layer, so getting the vocabulary right is the first modeling step. Everything on this page works with the public release of `law`, and no input files are needed. Each claim carries a status in words with a letter mark; the full legend is on the [topic index](/corpus/#how-this-topic-marks-confidence). Every claim here is **available in the public release** (S). ## The four constructs Four declaration forms carry all vocabulary (**S**): - `entity` declares a kind of thing, with `entity A : B` for subtyping. - `relation` declares a predicate with typed parameters, plus `kind` and `key` annotations where the model needs them. - `enum` declares a closed set of named members. - `const` declares a fixed value for reuse. Visibility is explicit: `pub` marks what other packages may use, `internal` keeps a declaration inside its package (**S**). The companion page on [local and shared vocabulary](/corpus/vocabulary/local-and-shared/) explains when to choose each. ```law entity Parcel; entity Owner; relation owns(owner: Owner, parcel: Parcel); enum ParcelKind { residential, commercial, garden } const registry_name : Text = "Parcel Registry"; ``` The parcel example above is a trimmed retelling of the lab fixtures that accompany this guide: package `labparcels.iface` contributes the `Parcel` and `Owner` entities, the `owns` relation, and the `ParcelKind` enum with exactly these three members, with no rules and no sources — vocabulary only. The fixture spells each declaration in full, adding labels, the `institutional` kind, and the key; the [lab tour](/corpus/lab/) shows the complete text. ## What the engine checks Declarations are not free text. The compiler rejects unknown types, dangling references, and malformed keys with structured diagnostics, and scenario runs exercise the vocabulary against facts (**S**): - `law engine check` reports declaration problems before anything runs. - `law test` runs a package's declared scenarios over its locked world. - A key conflict at evaluation time keeps both values true and reports `KEY_CONFLICT` rather than silently picking one (**S**). ## Which form to reach for The four constructs above plus aliases, roles, definitions, and mappings cover every modeling need. Pick by what you are saying, not by how it reads in prose: | Reach for | When | Not when | |---|---|---| | `type` alias | Same type under a shorter local name; the import stays pinned | Two dictionaries describe one idea — an alias cannot join them; import both and write an explicit mapping | | New `entity` | A new kind of thing with its own identity, such as a parcel or an owner | Members of a closed set — the three parcel kinds are enum members, not entities | | `role` | A capacity a subject acts in, shared across rules | A one-off rule variable or a parameter position — roles are shared vocabulary, not local shorthand | | `relation` | A statement with parameters that a case submits or rules derive, with a kind saying which | A fixed reusable value — that is a `const`, not a relation | | `definition` | The source states what a term means, as necessary conditions or an exact equivalence | An evaluative standard such as "reasonable", whose content arrives from case submissions or a named body — that is a relation fed through the judgment channel | | Mapping | Correspondence between two existing vocabularies — see [bridges](/corpus/vocabulary/bridges/) | Both acts need the same concept — share one dictionary import instead of mapping two copies | The forms in the table that are not among the four constructs, in one line each: - `type` alias — a second, local name for an existing type, for example a short name for an imported dictionary type. - `role` — a named capacity attached to an entity type, declared as `pub role Servicer for Lender;`: the same lender can act as seller and as servicer. - `definition` — a declaration that states what a term means, either as necessary conditions or as an exact equivalence; see [Definition](/constructs/definition/). - Mapping — an ordinary package of hand-written rules that relates concepts of two vocabularies; see [bridges](/corpus/vocabulary/bridges/). - Judgment channel — an `external judgment relation`: a decision input whose value is supplied by a named authority, such as a court, instead of being computed; see [Judgment channel](/constructs/judgment-channel/) and the [contracts page](/corpus/vocabulary/contracts/#relation-kinds). ## Reproduction details
Toolchain, hashes, and full transcripts All commands on the vocabulary pages were run against this toolchain, observed 2026-10-03: ``` $ law version law 0.1.1 semantics: law.core/0.2 std for language 0.2: 0.2.0 lawql: lawql/1 (queryResult 0.1) binary hash: sha256:cfa7c17232f2dc594e665dbbf2ad3c154675797ef4be07ef7d758c9abfb80a28 ```
## Where to go next - The companion page on [local and shared vocabulary](/corpus/vocabulary/local-and-shared/) covers visibility and shared dictionaries. - The companion page on [stable identity](/corpus/vocabulary/identifiers/) explains how nodes keep their identity across edits. - The companion page on [contracts](/corpus/vocabulary/contracts/) covers relation kinds, keys, and predicate templates. - For a hands-on introduction, see [What we talk about](/tutorials/vocabulary/). - For construct-level detail with corpus forms, see [the Vocabulary construct reference](/constructs/vocabulary/).