Queries: truth, collect, positions, why_not and neighbours
In one sentence: these constructs answer the question “what to
ask the law and in which shape the answer arrives”, without changing the law
itself: take them when the case is already described by facts and a
question must be put — check a proposition (truth), gather values
(collect), take a norm-position slice (positions, duties, …), explain a
non-firing (why_not) — and read the answer as a document with result kinds
and statuses.
A case is questioned in four shapes — check a proposition, collect values, slice norm positions, explain a non-firing — each answered as a typed document. The nearest pages are lifecycle statuses (what the positional kinds ask) and expressions and quantities (terms and collect generators).
1. When to take it and when not to
Section titled “1. When to take it and when not to”| Instead of | Selection rule |
|---|---|
truth(P) vs why_not(P) | truth asks “does it hold” and answers with a status (PROPOSITION); why_not asks “why not concluded” and answers with a blocker graph (GRAPH). An unfired rule is taken apart via why_not, not a second truth: the status is one, but there is no explanation |
truth(P) vs positions() | truth is a point question about one proposition; positions() is a slice of all the case’s norm positions (no literal). Duty/prohibition states are taken with positions(), a fact with truth |
collect v: T where G vs truth with a concrete value | collect lists ALL values the generator concludes (COLLECTION); truth checks one presented value. “Which books are overdue” is collect, “is this one overdue” is truth |
focused_truth vs truth | In 0.2 focused_truth does NOT execute: refusal FOCUS_UNSUPPORTED_SEMANTICS without a result. The question cone is a later-semantics feature. In 0.2 always truth |
query declaration vs standard kind | A named query with let/return is computation over the law (COMPLIANCE, DATA); the standard kinds are questions to the law itself. query adds no support to the legal state |
2. Minimal example
Section titled “2. Minimal example”Package research.queries.truth_why_not: a reader is admitted to book issue when
registered and no debt is established (not_known).
entity Reader { label ru-KZ official "Читатель";}relation registered(r: Reader) kind empirical { label ru-KZ official "зарегистрирован в библиотеке";}relation has_debt(r: Reader) kind empirical { label ru-KZ official "имеет задолженность";}relation may_borrow(r: Reader) kind institutional { label ru-KZ official "допускается к выдаче книг";}rule BorrowAllowed strict { label ru-KZ official "Зарегистрированный читатель без задолженности допускается к выдаче книг"; for r: Reader; when registered(r); when not_known(has_debt(r)); then may_borrow(r);}Case-01 facts: registered(urn:case:research:queries:anna).
Query: evaluate truth(may_borrow(...)).
Case-02 facts: plus has_debt(...) of the same reader.
Queries: evaluate truth(...), then evaluate why_not(...).
Observed engine answer (installed law, semantics law.core/0.2):
law test research.queries.truth_why_not: мир research.queries.truth_why_not ok [research.queries.truth_why_not#authored] tests/01-borrow-granted.lawtest / urn:query:research-queries-01 ok [research.queries.truth_why_not#authored] tests/02-borrow-blocked.lawtest / urn:query:research-queries-02итого: 2 проверено, 2 прошли, 0 не прошли, 0 не исполнены; код 0law engine check — check OK, no warnings. Case-02 expectations:
truth — PROPOSITION / NEITHER / COMPUTED; why_not — GRAPH /
NEITHER / COMPUTED plus the blocked_by(BorrowAllowed) observation.
Sensitivity: cases 01 and 02 differ by exactly one has_debt fact —
it flips truth from TRUE_ONLY to NEITHER and lights the rule blocker in
why_not. The example is not vacuous: removing registered from case 01 also
gives NEITHER (premise not established).
Nearest wrong outcome (caught during this research before the fix):
a when not has_debt(r) premise instead of when not_known(has_debt(r))
gives NEITHER even in case 01 — strict not requires a refutation,
and a missing fact is not a refutation. The “unless otherwise established”
form is only not_known.
3. Example by domain
Section titled “3. Example by domain”- Law: Kazakh Civil Code art. 10 (package
kz.corpus.civilcode, Kazakhstan) —evaluate positions()expectingposition(ObjedinenieVObshchestvennyeOrganizatsiiPotrebiteley, ACTIVE)(seecorpus-forms.md). - Law: Uzbek Civil Code (package
uz.civil_code, Uzbekistan) — atruthTRUE_ONLY/NEITHERpair on one predicate (positive/negative with one line ofresult_kind/truth_status/evaluation_statusexpectations). - Duty and collection:
research.queries.collect_positions— the same device in miniature:collect t: Text where overdue_title(...)(COLLECTION,collected_count(2)vscollected_count(0)) andpositions()(NORM_POSITION,position(ReturnOnTime, ACTIVE)vsposition_count(ReturnOnTime, ACTIVE, 0)). Observed engine answer:
law test research.queries.collect_positions: мир research.queries.collect_positions ok [research.queries.collect_positions#authored] tests/01-overdue-collected.lawtest / urn:query:research-queries-c1 ok [research.queries.collect_positions#authored] tests/02-nothing-overdue.lawtest / urn:query:research-queries-c2 ok [research.queries.collect_positions#authored] tests/03-duty-active.lawtest / urn:query:research-queries-c3 ok [research.queries.collect_positions#authored] tests/04-no-member.lawtest / urn:query:research-queries-c4итого: 4 проверено, 4 прошли, 0 не прошли, 0 не исполнены; код 0law engine check — check OK. Double sensitivity: overdue_title facts flip
collected_count(2) to collected_count(0) (cases c1/c2), the
member_enrolled fact flips position(ReturnOnTime, ACTIVE) to the 0 counter
(cases c3/c4).
- Non-firing explanation: the blocked-borrow scenario test —
why_notwithblocked_by(BorrowAllowed); a conformance scenario with the sameGRAPH/NEITHER/COMPUTEDshape.
4. Writing questions in .lawtest
Section titled “4. Writing questions in .lawtest”A question is written as evaluate <kind>(…);, followed by expect expectations
on the nearest preceding query: one test may hold several “question —
expectations” pairs (the specimen is case 02 of the truth-why-not
example, where truth with three expect is followed by why_not with four).
The test program is presented as a [[tests]] set via world; the case inside
a test is the given body: a context with time axes and assert facts
with origin.
The observation dictionary is closed and grows additively: result_kind, truth_status, evaluation_status,
applicability_status, normative_status, applied(R) / any_applied(R),
blocked_by(R) (on a transition blocker — with the step reason: attempt,
from, on, guard, requires, join), position(T, S),
position_count(T, S, n), collected_count(n), collected(…) /
collected_exactly(…), judgment_requests(n), conflicts(n) with the
conflict_* family, certificate(…), refused(CODE) (on a refusal the other
expectations of the same step are unsatisfiable by construction).
A standalone question to a case package outside a test carries an explicit queryId in the case-package namespace
(<namespace>#case/<Case>/query/<name>); a missing ID, another namespace
or an explicit-ID vs completed mismatch is a preparation refusal LDC-E1356.
In .lawtest the ID derives from the test header, so two forms of one
question (JSON and the evaluate string) give one canonical query.
5. How the engine answers
Section titled “5. How the engine answers”Table — observed runs of this directory’s examples (installed law,
semantics law.core/0.2):
| Facts | Question | Answer | Why |
|---|---|---|---|
registered | truth(may_borrow) | PROPOSITION / TRUE_ONLY / COMPUTED | the not_known rule fired |
registered + has_debt | truth(may_borrow) | PROPOSITION / NEITHER / COMPUTED | not_known false, the rule stays silent |
| same | why_not(may_borrow) | GRAPH / NEITHER / COMPUTED, blocked_by(BorrowAllowed) | root classified as truth, the blocker is the rule |
2 overdue_title facts | collect t: Text where … | COLLECTION / COMPUTED, collected_count(2) | the generator listed both values |
no overdue_title facts | same collect | COLLECTION / COMPUTED, collected_count(0) | an empty collection is also an answer, not a refusal |
member_enrolled | positions() | NORM_POSITION / COMPUTED, position(ReturnOnTime, ACTIVE) | the duty concluded by a rule |
| no facts | positions() | NORM_POSITION / COMPUTED, 0 counter | no positions, same result kind |
| no facts (pure computation) | evaluate -7 mod 3 | DATA / COMPUTED, value == 2 | a term asked directly, with no case (earlier “euclidean remainder” scenario) |
why_notclassifies the goal the same astruthon the same case: the sametruthStatus, status,judgmentRequests,missingInputs; next toblockerson a candidate term error liestermErrors.- A candidate-rule term error with
NEITHERontruth/why_notraisesevaluation_statusup the status ladder (MISSING_INPUT,MISSING_POLICY,NON_EXECUTABLE, …, otherwiseRUNTIME_ERROR);positions/collectdo not carry a term error in their status — a named but unclosed boundary. - A missing dimension is absent, not filled with a fictitious
NEITHER. A runtime result mismatching thequery-declaration contract is a conformance error. - Term-computation refusals use the
issue(CODE)observation:1000 KZT + 5 USD→issue(CURRENCY_MISMATCH),7 mod 0→issue(DIVISION_BY_ZERO), a sum over an empty collection →RUNTIME_ERROR(EMPTY_AGGREGATE: an empty sum is not zero). - A question outside the question schema and a wrong-arity question are
rejected BEFORE computation with a
QUERY_INVALIDerror object; literal values are read by the value reader, refusal — the sameQUERY_INVALID.
6. Common mistakes
Section titled “6. Common mistakes”when not Pinstead ofwhen not_known(P)for “unless established” — silentNEITHERinstead of a conclusion (in detail —pitfalls.md, item 1; caught by run).- Wrong-arity question — refusal
QUERY_INVALID, notNEITHER(pitfalls.md, item 2). focused_truthin 0.2 — refusalFOCUS_UNSUPPORTED_SEMANTICSwithout a result (pitfalls.md, item 3;boundaries.md).- Two-argument
position_count—LDC-E1316, three needed (pitfalls.md, item 4; caught by run). - Expecting
truth_statusonpositions()/collect— these kinds have none (pitfalls.md, item 5). - Uppercase
bearer/holder— the examples use only lowercase keywords (pitfalls.md, item 6).
7. References
Section titled “7. References”- Tutorial: writing tests.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.