Vocabulary first
Task and place
Section titled “Task and place”The vocabulary is everything a package declares before the first rule: object types, relation signatures, closed lists, named values, and visibility. Without a declared name there is nothing to write a rule about: any literal outside the vocabulary is a rejection at check time. This stage sits between inventory and construct choice. Inventory says which content units to formalize, vocabulary says what the model talks about, and only then do rules say what follows.
Inputs
Section titled “Inputs”- The included inventory rows with their content units; the filled EAI inventory carries them for the running example.
- The scope card boundary; the filled EAI scope card carries it for the running example.
- The scope card template and the source inventory template when starting a fresh package.
Actions
Section titled “Actions”- Name one object type per durable thing the act reasons about, not per mention in the text. The running example needs three: employer, employee, and insurance contract.
- Separate four things the act text blurs: the object, its stable id, its human name, and the record about it. Two people may share a name, and one person may own several records. Identity is the reference, never the text.
- Give each claim its record: one relation tuple per claim, with the parameter order fixed once in the signature.
- Put roles where they belong: a capacity inside a relationship is a relation parameter, while a standing party kind may deserve its own object type.
- Close what is closed: statuses and classes with a fixed membership become enumerations; open sets stay relations with a parameter.
- Date the events: occurrences that happen at a time take a date argument. The four modeled articles of the running example carry no time parameters, so no date column appears there.
- Mark the kind of every relation: observed case facts are empirical, statuses the law establishes are institutional, rule-head conclusions are derived. Kind is metadata and never changes truth, but a wrong kind misleads every later reader.
- State reuse up front: export shared names, require explicit local imports, and declare dependencies. The running example declares explicit local imports and no dependencies.
Decisions
Section titled “Decisions”- Object type versus relation: anything that changes over time, is contested, or arrives as a case fact is a relation, never a built-in field.
- Closed list versus open relation: fixed membership goes in an enumeration, whose members refuse comparison with another enumeration; open sets stay relations.
- Key or silent duplicates: a key turns two tuples under one projection into an explicit conflict the reader must resolve, instead of a silent pick.
- Named individual versus bare name: an individual gets its name only through a declared constant; a bare name that resolves to nothing is a rejection.
- Empirical versus institutional for each relation, decided by meaning: observed versus established by law.
Artifact
Section titled “Artifact”The artifact is a vocabulary review: every declared object type and relation with its shape and a verdict. The table below is the review for the running example at the source snapshot; a fresh package writes the same table for its own names before drafting rules. (The accepted candidate adds the insured-sum and minimum-wage inputs plus the premium-base and R1 relations — see the worked example below.)
| Name | Shape | Verdict |
|---|---|---|
| Employer, Employee | object types | keep: the parties of every modeled article |
| InsuranceContract | object type | keep with a note: declared, but no relation or rule in the four modeled articles touches it |
| employer_has_employee | empirical link, employer and employee | keep: the duty condition reads it |
| professional_risk_class | empirical, employer and integer class, key on employer | keep: one class per employer, enforced by the key |
| annual_payroll | empirical, employer and money amount, key on employer | keep: one payroll figure per employer |
| employment_accident_contract_concluded | empirical flag on employer | keep with a note: declared, but no rule in the four modeled articles reads it |
| capacity_loss_percent | empirical, worker and integer percent, key on worker | keep: the payout condition reads it |
| insurance_payment_overdue | empirical, worker with unpaid amount and day count | keep: the penalty rule reads it |
| employer_must_insure_employees | institutional duty on employer | keep: derived by the Article Eight rule |
| insurance_tariff | institutional rate on employer | keep: derived by the tariff rules |
| insurance_premium_due | institutional amount on employer | keep: derived by the premium rule |
| insurance_payout_due | institutional flag on worker | keep: derived by the payout rule |
| insurance_payout_barred | institutional flag on worker | keep with a note: declared, but no rule produces it; the act states who is paid, and silence stays silence |
| late_payment_penalty_due | institutional amount on worker | keep: derived by the penalty rule |
Worked example
Section titled “Worked example”[Source snapshot]: the employer accident insurance package, version 0.1.0, language 0.2, with zero dependencies and explicit local imports. Source EAI_EDITION, materialization PINNED_UNOFFICIAL_COPY (Adilet API copy retrieved 2026-09-13, sha256 pinned, local copy in pkg). Three object types carry the parties; six empirical relations carry the case facts with keys on the employer and the worker where duplicates would be ambiguous; six institutional relations carry what the law establishes. Article Eight derives the employer duty from the employment link. Article Seventeen derives the tariff from the risk class and the premium from payroll times rate. Article Nineteen derives payout from the loss percent. Article Nine derives the penalty from the overdue amount and the day count. Three declarations stay unread or unproduced by any rule; each is noted in the review rather than silently kept.
[Accepted candidate]: eight empirical relations (adding the insured sum and the minimum wage as case inputs) and eight institutional relations (adding the premium base amount and the R1 reimbursement conclusion). The premium base reads the insured sum, not payroll — and annual_payroll becomes the fourth rule-unread declaration: cases still assert it, but no premium rule touches it since finding EAI-R3.
Pitfall
Section titled “Pitfall”Two classic failures open this stage. Merging distinct objects that share a name lets one person’s record speak for another; matching names never carry a conclusion across. A wrong-typed literal written into the package — a number where a rule head needs text — fails the static check with LDC-E2104, before any question is asked. A wrong-typed fact fed with a case fails one layer later, at case input validation, not at package check. The subtler failure is trusting types too far: a typo is still text, and a wrong but well-typed link still reasons. Types check form, never truth — and each layer catches only its own mistakes, as the calculations page states for the runtime layer.
Verification
Section titled “Verification”The stage is done when the package check passes with no warnings and every case literal resolves against the vocabulary. Observed run with tool version law 0.1.0, semantics law.core/0.2:
law engine check corpus/laws/kz/laws/employee-accident-insurancecheck OK: corpus/laws/kz/laws/employee-accident-insuranceCriterion: the check line reads OK, and re-running it after any vocabulary edit keeps it so. An undeclared name must fail here, never at question time; a mistyped case value fails at input validation, and a mistyped runtime operation fails when the question runs — the three layers are named on the calculations page. The suite for the running example passes seven of seven; its full output is shown in the next stage.
Limits
Section titled “Limits”Vocabulary fixes form, not truth or completeness. Unused declarations warn nobody by themselves, which is why the review notes them explicitly. A missing relation is found only when a rule or a question needs it, so the review is re-read at every later stage.
Next step
Section titled “Next step”Continue with Choosing a construct, which picks the rule shape for each vocabulary item.
Sources
Section titled “Sources”- What we talk about — object, name, and record, with the two-person drill.
- Definitions and friends — which shapes derive and which only check.
- Language reference — syntax and semantics of every declaration form.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.