Skip to content
docs
Arxo ↗

Queries: truth, collect, positions, why_not and neighbours

For LLMs7 sections

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).

Instead ofSelection 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 valuecollect 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 truthIn 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 kindA 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

Package research.queries.truth_why_not: a reader is admitted to book issue when registered and no debt is established (not_known).

Arxo Law
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):

Output
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 не исполнены; код 0

law 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.

  • Law: Kazakh Civil Code art. 10 (package kz.corpus.civilcode, Kazakhstan) — evaluate positions() expecting position(ObjedinenieVObshchestvennyeOrganizatsiiPotrebiteley, ACTIVE) (see corpus-forms.md).
  • Law: Uzbek Civil Code (package uz.civil_code, Uzbekistan) — a truth TRUE_ONLY/NEITHER pair on one predicate (positive/negative with one line of result_kind/truth_status/evaluation_status expectations).
  • Duty and collection: research.queries.collect_positions — the same device in miniature: collect t: Text where overdue_title(...) (COLLECTION, collected_count(2) vs collected_count(0)) and positions() (NORM_POSITION, position(ReturnOnTime, ACTIVE) vs position_count(ReturnOnTime, ACTIVE, 0)). Observed engine answer:
Output
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 не исполнены; код 0

law 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_not with blocked_by(BorrowAllowed); a conformance scenario with the same GRAPH/NEITHER/COMPUTED shape.

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.

Table — observed runs of this directory’s examples (installed law, semantics law.core/0.2):

FactsQuestionAnswerWhy
registeredtruth(may_borrow)PROPOSITION / TRUE_ONLY / COMPUTEDthe not_known rule fired
registered + has_debttruth(may_borrow)PROPOSITION / NEITHER / COMPUTEDnot_known false, the rule stays silent
samewhy_not(may_borrow)GRAPH / NEITHER / COMPUTED, blocked_by(BorrowAllowed)root classified as truth, the blocker is the rule
2 overdue_title factscollect t: Text where …COLLECTION / COMPUTED, collected_count(2)the generator listed both values
no overdue_title factssame collectCOLLECTION / COMPUTED, collected_count(0)an empty collection is also an answer, not a refusal
member_enrolledpositions()NORM_POSITION / COMPUTED, position(ReturnOnTime, ACTIVE)the duty concluded by a rule
no factspositions()NORM_POSITION / COMPUTED, 0 counterno positions, same result kind
no facts (pure computation)evaluate -7 mod 3DATA / COMPUTED, value == 2a term asked directly, with no case (earlier “euclidean remainder” scenario)
  • why_not classifies the goal the same as truth on the same case: the same truthStatus, status, judgmentRequests, missingInputs; next to blockers on a candidate term error lies termErrors.
  • A candidate-rule term error with NEITHER on truth/why_not raises evaluation_status up the status ladder (MISSING_INPUT, MISSING_POLICY, NON_EXECUTABLE, …, otherwise RUNTIME_ERROR); positions/collect do 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 the query-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_INVALID error object; literal values are read by the value reader, refusal — the same QUERY_INVALID.
  1. when not P instead of when not_known(P) for “unless established” — silent NEITHER instead of a conclusion (in detail — pitfalls.md, item 1; caught by run).
  2. Wrong-arity question — refusal QUERY_INVALID, not NEITHER (pitfalls.md, item 2).
  3. focused_truth in 0.2 — refusal FOCUS_UNSUPPORTED_SEMANTICS without a result (pitfalls.md, item 3; boundaries.md).
  4. Two-argument position_count — LDC-E1316, three needed (pitfalls.md, item 4; caught by run).
  5. Expecting truth_status on positions()/collect — these kinds have none (pitfalls.md, item 5).
  6. Uppercase bearer/holder — the examples use only lowercase keywords (pitfalls.md, item 6).

Documentation for Arxo. Writings — blog.arxo.io.

Anonymous visit counts on stats.arxo.io, no cookies.