Skip to content
docs
Arxo ↗

Read answers

For LLMs10 sections

An answer from an executable model is a document, not a sentence: the outcome, the rules that fired, diagnostics on what blocked a derivation, source addresses, legal time and hashes. This page is the single reference for reading it, including the status table other pages link to. The Guide pages on silence and explain and doubt cover the user’s side.

Never flatten an answer to a boolean. Store the untouched response under the question that produced it, then derive views: a later step may need a field this one ignores, and reproduction needs the hashes as received.

TypeScript
type RawAnswer = {
bytes: Uint8Array; // untouched response, kept for replay
callOk: boolean; // transport and call shape accepted
evaluationStatus: string; // see the table below
truthStatus?: string; // TRUE_ONLY | FALSE_ONLY | BOTH | NEITHER
value?: unknown; // kind-specific payload
whyNot?: unknown; // absent, [] or a blocker list: three different facts
issues?: unknown[]; // engine messages, kept verbatim
provenance?: unknown; // rules, sources, hashes, legal time
};

Status: labeled pseudocode. Not executed; it defines no contract beyond the prose.

Read every answer on three axes, in order, and never merge them.

AxisFieldQuestion
Callerror flag, exception, refusaldid the call itself go through
EvaluationevaluationStatusdid the engine finish the computation, and if not, why
ResulttruthStatus, value, positionswhat the finished computation establishes
  • COMPUTED is not a positive result. It says the computation finished; a computed answer can still support neither side.
  • A refused call is not NEITHER. Fix the call (predicate name, arity, types, project) instead of reading silence into it.

Refusal shape from the local CLI, run from a directory without a case project:

Output
law: REFUSAL LPK-E0201: no law.toml here or above — pass the project via --project

Status: ran locally in an earlier authoring session (law ask); not re-run for this page.

The full set defined by the specification and the published SDK types. Read it before the truth status or values.

evaluationStatusMeaningAllowed next step
COMPUTEDthe evaluation finishedread the result axis
MISSING_INPUTa required input snapshot (for example a calendar) or function input was not supplied or is invalidsupply the named input; do not invent it
MISSING_POLICYa required policy (for example a deadline policy) is not set or is unusableask the human or the integrator which policy applies
REQUIRES_JUDGMENTthe canon routes an element to an authority’s judgmentstop; record a human judgment (see Human decisions)
INTERPRETATION_REQUIREDa disputed reading must be chosenshow the readings the canon names; a human selects one
NON_EXECUTABLEthe needed part of the model cannot run (opaque term, unknown function, non-exhaustive match, unstratifiable negation)report it; this is a model limit, not a case fact
EXTERNAL_UNAVAILABLEan external value or its snapshot is missingsupply the snapshot or report the gap
SOURCE_RESOLUTION_FAILEDa source or edition could not be resolvedcheck the pin and edition (see Pin context)
PRIORITY_CONFLICTa priority cycle arose in context; no tie-break is madereport the conflict group
UNRESOLVED_NORMATIVE_CONFLICTtwo incompatible positions stand with no priority between themshow both; never pick one
CONFLICTED_INPUTSaccepted inputs conflict and the package’s policy says halt; absent that policy this status does not arisecorrect the inputs
TYPE_ERRORa term failed on types, currency, dimension or date/instant mismatchfix the submitted values or report the model defect
RUNTIME_ERRORany other evaluation errorreport the issue verbatim
RESOURCE_LIMITa limit stopped the computationnarrow the question or raise the limit, then re-ask

Precedence and scope, as the specification states them:

  • A truth or why-not NEITHER caused by a candidate rule’s failed term names that failure. With several codes the order is MISSING_INPUT, MISSING_POLICY, NON_EXECUTABLE, EXTERNAL_UNAVAILABLE, TYPE_ERROR, RUNTIME_ERROR, RESOURCE_LIMIT. INTERPRETATION_REQUIRED, UNRESOLVED_NORMATIVE_CONFLICT and REQUIRES_JUDGMENT rank above term failures.
  • INTERPRETATION_REQUIRED belongs to a result, not the document: an independent question in the same case stays COMPUTED.
  • A dated parameter with no value on the date is the law’s own silence: the result stays COMPUTED with a warning issue.
  • For collect and positions a candidate’s term failure need not surface as the status. Read issues too.

Observed: with the deadline policy left out, a collect over the German Civil Code periods canon returned NON_EXECUTABLE, an empty value, empty missingInputs, and an error issue coded MISSING_POLICY:

Output
evaluationStatus: NON_EXECUTABLE value: [] missingInputs: []
issue MISSING_POLICY (error): rule urn:de:corpus:clir:bgb-fristen#TagesfristEnde:
head computation — urn:de:corpus:clir:bgb-fristen#frist_ende.arg1: deadline:
DeadlinePolicy is set neither by request nor by context/profile (SPEC §86)

Status: ran locally (@arxo/law 0.3.3, de.bgb.fristen@0.1.0), 2026-10-04; the run also carried two CONTEXT_FIELD_DEFAULTED warnings. Route on the issue code, and never show the empty value as “no deadline”.

For a proposition the engine keeps a pair: is there an accepted positive support, is there an accepted negative one.

truthStatusPositive supportNegative supportReading
TRUE_ONLYyesnoestablished
FALSE_ONLYnoyesthe opposite is established
BOTHyesyesboth derived; show both proof lines
NEITHERnononothing derived either way

NEITHER is neither “false” nor “the law is silent”: the model derived nothing for this question on these facts, and a norm missing from the model is not a norm missing from the law.

Worked example: package kz-labour-code (Labour Code of the Republic of Kazakhstan), predicate feeding_break_too_short, legal time 2026-09-01. A 25-minute break with one child is TRUE_ONLY (resultHash sha256:3e75a474…, shortened). A 30-minute break with one child is NEITHER:

Output
Не установлено ни что «перерыв для кормления ребёнка короче установленного
минимума», ни обратное. Это не утверждение ложности и не заключение о
молчании права: в модели нет вывода ни в одну сторону.

A 30-minute break with two children is TRUE_ONLY again: the one-hour rule for two or more children fires where the thirty-minute rule stays silent. A rule that does not fire proves nothing about the opposite.

Status: ran via the public MCP endpoint (root route), 2026-10-03, all COMPUTED.

law_ask serves six kinds: truth, collect, calc, deadline, positions, why_not. Each has its own value shape and its own meaning of “empty”; do not read them with one helper.

Collect returns the distinct values satisfying the condition. One can be bound into a later step; several mean none is chosen; none is the absence of a derivation, not zero. Over MCP, break minutes for the known parties returned 25; for unknown parties, a computed empty list:

Output
Значение: пустой перечень: в модели не найдено ни одного подходящего значения.

Status: ran via the public MCP endpoint (root route), 2026-10-03.

Over de.bgb.fristen with the duration left out, collect on frist_ende returned an empty list with COMPUTED, truth returned NEITHER, and missingInputs was empty in both. So an empty, computed collection can still mean “a fact was not given”; the why-not report tells which.

Status: ran locally (@arxo/law 0.3.3, de.bgb.fristen@0.1.0), 2026-10-04.

Calc evaluates an arithmetic tree: (2 + 3) computed to 5 with resultHash sha256:6ce72afd202dacd139e47ca63a6d9db82f2914a7196bd30f6e6dc76feb244f68. An unfinished calc is not a number. Deadline computes on the pinned calendar: 10 calendar days after 2026-09-01 expire on 2026-09-11; without its policy and calendar snapshot it is incomplete.

Status (calc, deadline): ran via the public MCP endpoint (root route), 2026-10-03.

Positions lists normative positions that arose from the facts, each with a modality, a status, a bearer, often a beneficiary, source anchors and the creating rule. The executable modalities are duty, liberty, power and immunity; a prohibition is a duty of forbearance, and other surface forms lower to these four. Show every position with its modality. With the feeding-break facts the answer held two positions of modality duty, status ACTIVE, each with an achievement goal and a window from 2016-01-01.

Status: ran via the public MCP endpoint (root route), 2026-10-03.

An empty positions list does not by itself establish a cause: facts may be missing, the canon may not model the position, a reading may be unselected. Read evaluationStatus and issues before saying why.

Why-not takes the truth question’s shape; its root carries the same statuses, judgment requests and missing inputs as the matching truth question, and its value is the blocker report below.

When a derivation is absent, read status, then the diagnostic fields the answer actually has, then the next step they allow. The explanation may be incomplete; do not fill the gap with a guess.

What the answer carriesWhat it saysAllowed next step
whyNot absentno report was built (not requested, or not built for this kind)ask why_not explicitly before explaining
whyNot: []the report was built and no rule head matches the goalsay the model has no rule for this goal on this pin; check interpretationGated
whyNot with blockersper-rule conjuncts marked SATISFIED, UNDETERMINED or not satisfied, with continuationscollect the undetermined facts, or stop on a failed guard
whyNotErrorbuilding the report failedreport the error; no cause is known
whyNotTermErrorsa candidate rule’s term failed (rule, code, message)follow the code, as in the status table
interpretationGatedrules for the goal exist but are switched off because their reading is not selectedshow the readings; a human selects
missingInputsinput-side requirements (rule, code), such as a missing snapshotsupply them
judgmentRequestsa judgment the canon reserves for an authoritystop for a human judgment
truthStatus: BOTHboth supports derived; not an absenceisolate both derivations
issuesengine messages, including warnings that did not change the statuskeep verbatim, route by code

The MCP server attaches a report to a NEITHER truth answer (and to answers over facts with document provenance); the why_not kind always builds one. In the SDK run above, truth held no report and a separate whyNot call built it.

missingInputs is input-side (“not supplied”); blockers are derivation-side (“this conjunct did not hold”). An unsubmitted case fact usually appears only as an undetermined blocker.

The specification names the blocker kinds a why-not graph may show: false body, missing fact, conflicting premise, defeated rule, source not in force, unselected interpretation, missing judgment, unresolved reference. An answer shows some, not necessarily all; undetermined is never false.

Over de.bgb.fristen with the duration left out, the report for frist_ende held two strict, undetermined blockers: TagesfristEnde with one continuation (frist_ereignis satisfied, frist_dauer_tage undetermined) and Verlegung193 with none.

Status: ran locally (@arxo/law 0.3.3, de.bgb.fristen@0.1.0), 2026-10-04.

The same shape over the labour code, with only the child count submitted:

Output
по фактам дела (v3 = 2): тело не определено — фактов не хватает
? v2 < 60 — variables are not bound by the goal: v2
? child_feeding_break_minutes(urn:kz:tk:employee:1, urn:kz:tk:employer:1, v2)
✓ children_under_eighteen_months(urn:kz:tk:employee:1, 2)
✓ v3 ≥ 2 — comparison satisfied

Status: ran via MCP in the authoring session on a regional route that has since been retired; not re-run on the root route.

Next step: ask for the undetermined fact (law_rules with contract: true names the inputs). Stop when answered or when the person has no such fact; record it as unknown to the case.

With 30 minutes and one child, the first rule reads both facts and fails only its comparison:

Output
по фактам дела (v2 = 30, v3 = 1): тело не выполнено
✓ child_feeding_break_minutes(urn:kz:tk:employee:1, urn:kz:tk:employer:1, 30)
✓ children_under_eighteen_months(urn:kz:tk:employee:1, 1)
✓ v3 = 1 — comparison satisfied
✗ v2 < 30 — comparison not satisfied

Status: as above (retired regional route, authoring session).

Nothing is left to collect, and no rule derives “the break is sufficient”. Pass NEITHER on; re-asking cannot change it.

  • Defeat. A body holds but a prioritized exception removes the conclusion; the blocker’s strength separates defeasible rules from defeaters. Only facts or a competent decision change it.
  • Unselected reading. interpretationGated or INTERPRETATION_REQUIRED: a human chooses, never the agent.
  • Both sides. For BOTH, check the case facts for a contradiction first; if they are consistent, report both derivations. Report the two conflict statuses the same way. Never resolve a conflict by preference.

Status: NOT RUN for this page; no defeat, gated reading or BOTH instance was captured. Reproduction: a case satisfying both a rule and its exception; a canon with an interpretation group left unselected; facts satisfying two rules with opposite heads.

An empty search or an empty whyNot says nothing about the act’s text. Never conclude “the norm was never formalized”: search ranks by similarity, and the rule may sit under another predicate, package or unselected reading. Say what was searched on which pin; see Empty search results.

Keep engine messages verbatim and route by code and severity. Over the measurement-uncertainty example case, a computation stopped on a type error while the unfinished record showed an empty collection:

Output
Вычисление прервано ошибкой типов.
Запись незавершённого результата (это не окончательный ответ): Значение:
пустой перечень: в модели не найдено ни одного подходящего значения.
## Сообщения движка
- Ошибка `TYPE_ERROR`: rule urn:jcgm:clir:gum#CombinedStandardUncertainty:
head computation — sqrt_bounds: the argument is Integer, Decimal or Rational,
got number — связанных узлов: 1.

Status: ran locally in an earlier authoring session (law ask in the example project); not re-run.

An unfinished record is not the answer; passing its values on reports a crash as a finding. A why-not blocker lists at most eight continuations per rule and sets truncated: true when it cut any; stop claims at every limit marker.

“Established” is always relative to a support, and four supports answer four questions.

What the text says. law_sources with a fragment from a rule’s anchors returns an excerpt, language, status and the hash of the full pinned source:

Output
urn:kz:corpus:clir:labour-code#TK_ART82 (article/82, ru-KZ/official), выдержка:
Статья 82. Внутрисменные и специальные перерывы
1. На отдельных видах работ работникам предоставляются внутрисменные
перерывы, обусловленные технологией и организацией производства и труда,
которые включаются в рабочее время. ...
hash полного источника: sha256:b9fc7d308b57c2a0ffa7f47de7686115432c77c6247e68f03aaa5b98272c2be6

Status: ran via MCP in the authoring session on the retired regional route; not re-run.

An anchor is an address, not proof that the rule renders the text faithfully. Match is not derivation; the search tool says so on every call:

Output
Это кандидаты ПОИСКА, не ответ права: сходство текста не устанавливает
ни факта, ни нормы.

Status: ran via MCP in the authoring session (top score 0.4027); not re-run.

What derives it. Ask with proof: true to get the evaluation document with its proof graph. law_explain takes that document, or the question with resultHash and codeHash for a verified recomputation, and returns the rule-to-premises chain with a fingerprint a repeat must reproduce. law_inspect reads a saved document without recomputing: hash checks, slices by query, rule, position or node, and diffs.

Status: parameter set of law_explain read from the live tool list, 2026-10-03; NOT RUN as calls. Reproduction: ask the feeding-break question with proof: true and pass the result to both tools.

Will it stand. law_argue returns one of four classes: unassailable, merely defensible, rejected, no arguments. Read it with the skipped-rules list: the dispute profile covers less of the language, so “no arguments” with the decisive rule skipped means robustness was not measured. On a cap refusal raise limits.maxArguments; report a merge refusal verbatim:

Output
мир не слить: пакет "calc-obligations" объявляет семантику 0.2.2, остальные — 0.2.4

Status: ran via MCP on the retired regional route; refused twice before analysis.

SupportQuestionToolFailure looks like
Derivabilitydoes the engine derive itlaw_ask with proofsilence with its diagnostics
Admissibilityis the evidence admittedthe package’s evidence policyunadmitted or refuted support
Robustnessdoes it stand in disputelaw_argue with limitsrejected, or unmeasured when decisive rules were skipped
Fidelitydoes the model render the sourcehuman review via a mismatch reporta filed report, not a derived value

For protected predicates admission controls derivation: a rejected support grounds nothing (see Collect facts and evidence). Robustness reads derivation’s output, not the world. Fidelity conditions all three; a suspected mismatch goes to a report naming the package, fragment or predicate and the answer’s call id.

Show commands, versions and results
CheckWhereResult
Status set (14 values)specification; @arxo/law-types 0.3.3 EvaluationDocumentEvaluationStatusidentical
whyNot / whyNotError / interpretationGated semanticsMCP server source, read 2026-10-04as described
Feeding-break truth, collect, calc, deadline, positions, why-notpublic MCP endpoint, root route, 2026-10-03as quoted
BGB empty collect, NEITHER, blockers, NON_EXECUTABLE with MISSING_POLICY@arxo/law 0.3.3, de.bgb.fristen@0.1.0, 2026-10-04as described
Blocker shapes, source excerpt, search notice, argue refusalMCP, authoring session, retired regional routecarried over, not re-run
Type-error record, CLI refusallocal CLI, authoring sessioncarried over, not re-run
Eight-continuation capspecification onlynot observed live

Previous: Collect facts and evidence Next: Human decisions, interpretations and scenarios Related: Silence · Explain and doubt

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

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