Read inapplicability separately from truth
Intent
Section titled “Intent”I want to read inapplicability separately from truth.
Wrong form and why it stays silent
Section titled “Wrong form and why it stays silent”NOT_APPLICABLE is not part of truth_status. In why_not, applicability belongs to the candidate, not automatically to the root answer.
expect truth_status == NOT_APPLICABLE;Correct form
Section titled “Correct form”language "law.core" version "0.2";package recipe.m09 version "1.0.0";namespace "urn:recipe:m-queries:09";entity Person;relation eligible(p: Person);relation accepted(p: Person);rule Accept strict { for p: Person; effective [@2026-09-01, @2026-10-01); when eligible(p); then accepted(p); }Frozen execution scene
Section titled “Frozen execution scene”| Input / variant | Question | Expectation |
|---|---|---|
| 1. outside the window | truth(accepted(entity_ref("urn:recipe:m-queries:p"))) | truth_status == NEITHER; evaluation_status == COMPUTED; |
| 2. explanation outside the window | why_not(accepted(entity_ref("urn:recipe:m-queries:p"))) | evaluation_status == COMPUTED; blocked_by(Accept); |
| 3. applicable, but the body refuted | why_not(accepted(entity_ref("urn:recipe:m-queries:p"))) | evaluation_status == COMPUTED; blocked_by(Accept); |
| 4. applicable and fired | truth(accepted(entity_ref("urn:recipe:m-queries:p"))) | truth_status == TRUE_ONLY; evaluation_status == COMPUTED; |
outside window answers neither
test "outside window answers neither" { given { context { legal_time @2026-10-01; decision_time @2026-09-13T09:00:00Z; knowledge_time @2026-09-13T09:00:00Z; timezone "UTC"; } assert eligible(entity_ref("urn:recipe:m-queries:p")); } evaluate truth(accepted(entity_ref("urn:recipe:m-queries:p"))); expect truth_status == NEITHER; expect evaluation_status == COMPUTED;}explanation outside window names rule
test "explanation outside window names rule" { given { context { legal_time @2026-10-01; decision_time @2026-09-13T09:00:00Z; knowledge_time @2026-09-13T09:00:00Z; timezone "UTC"; } assert eligible(entity_ref("urn:recipe:m-queries:p")); } evaluate why_not(accepted(entity_ref("urn:recipe:m-queries:p"))); expect evaluation_status == COMPUTED; expect blocked_by(Accept);}refuted body names rule
test "refuted body names rule" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00Z; knowledge_time @2026-09-13T09:00:00Z; timezone "UTC"; } assert not eligible(entity_ref("urn:recipe:m-queries:p")); } evaluate why_not(accepted(entity_ref("urn:recipe:m-queries:p"))); expect evaluation_status == COMPUTED; expect blocked_by(Accept);}applicable rule fires
test "applicable rule fires" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00Z; knowledge_time @2026-09-13T09:00:00Z; timezone "UTC"; } assert eligible(entity_ref("urn:recipe:m-queries:p")); } evaluate truth(accepted(entity_ref("urn:recipe:m-queries:p"))); expect truth_status == TRUE_ONLY; expect evaluation_status == COMPUTED;}In scene 2 the path results[0].value.value.blockers[0].applicability
equals NOT_APPLICABLE, the conjunct list is empty: the rule is outside effective.
In scene 3 applicability is APPLICABLE, but trigger is NOT_SATISFIED.
Both questions return truthStatus NEITHER. The root GRAPH result
has no applicabilityStatus field; a candidate field must not be attributed to it.
Check of result fields and extra inputs:
>>> import runpy>>> checks = runpy.run_path("docs/recipes/m-queries/resources/check.py")>>> checks["applicability"](https://github.com/arxohq/law/blob/master/docs/recipes/m-queries/9)TrueCounterfactual
Section titled “Counterfactual”The sidecar mutation reproduces LDC-E1319. Counterfactual table variants are executed separately; input errors are not passed off as NEITHER.
Boundary
Section titled “Boundary”APPLICABLE and SATISFIED are different axes. Absence of a rule’s application does not create negative support for its head.
Pitfall
Section titled “Pitfall”A closed anchor or window lifts application but does not refute the head — see Move a rule onto the edition in force.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.