Your first rule
The task: the town of Northbridge issues residential parking permits. An applicant is eligible when two things hold — they are a resident, and they have a vehicle registered at their address. We will write that rule, give it one applicant, and ask whether she is eligible.
This page is a complete package. Every law block below is compiled by the
checks that publish this site, so the code you see is the code that ran.
Open this package in the playground → — edit the rules and the scenarios of this page and run them in your browser.
The package
Section titled “The package”A package starts with three lines: the language line, the package name with its version, and a namespace that makes every name in the package globally addressable.
language "law.core" version "0.2";package demo.parking version "0.1.0";namespace "urn:law:demo:parking";Then the vocabulary. An entity is a kind of thing the rules talk about; a
relation is a statement about such things. kind institutional says the
statement exists because some rule or record says so, as opposed to a
measured fact.
entity Applicant;
relation resident(a: Applicant) kind institutional;relation vehicle_registered(a: Applicant) kind institutional;relation permit_eligible(a: Applicant) kind institutional;The rule. for introduces a typed variable; when lists what must be
established; then is what follows. strict means the rule has no
exceptions — nothing can defeat its conclusion.
rule PermitEligibility strict { for a: Applicant; when resident(a) and vehicle_registered(a); then permit_eligible(a);}The scenario
Section titled “The scenario”A scenario lives in a separate file with the extension .lawtest. It
repeats the same three header lines, then states what is given, what is
asked, and what is expected. The context block fixes the dates the
question is asked at; the two assert lines are the facts of the case.
test "a resident with a registered vehicle is eligible" { given { context { legal_time @2026-03-01; decision_time @2026-03-01T09:00:00Z; knowledge_time @2026-03-01T09:00:00Z; timezone "UTC"; } assert resident(entity_ref("urn:demo:parking:ann")) { id "ann-resident"; origin case_input; } assert vehicle_registered(entity_ref("urn:demo:parking:ann")) { id "ann-vehicle"; origin case_input; } } evaluate truth(permit_eligible(entity_ref("urn:demo:parking:ann"))); expect truth_status == TRUE_ONLY; expect evaluation_status == COMPUTED;}evaluate truth(…) asks whether a statement is established. The answer has
two parts: evaluation_status says whether the engine could compute at all
(COMPUTED), and truth_status is the answer itself — here TRUE_ONLY:
established, with nothing against it.
Run it
Section titled “Run it”Save the law blocks above as two files: the package as parking.law, and
the test block, preceded by the same three header lines, as
tests/eligibility.lawtest. Then check the package and run the scenario
against it (law is the Arxo command-line tool; inside a checkout of the
repository it is ./law):
law engine check parking.lawlaw engine test tests/eligibility.lawtest --program parking.lawExpected output:
check OK: parking.lawtest PASS: a resident with a registered vehicle is eligiblefollowed by a summary line with the count of scenarios that passed.
Try one change
Section titled “Try one change”Delete the vehicle_registered line from given and run the scenario
again. The rule no longer fires, and the test fails:
test FAIL: a resident with a registered vehicle is eligible truth_status == TRUE_ONLY: в документе NEITHERThe answer is NEITHER — neither established nor refuted. Nothing in the
case says Ann has no registered vehicle; the case is silent, and Arxo says
so instead of guessing. The next page, Facts and questions, shows the other
kinds of questions you can ask; Missing and conflicting facts explains the four possible answers.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.