Calculate and check: collect the end date, test the candidate
The application asks two questions: when does the period end, and does it end on the date the user proposes? This chapter asks both on the example case and reads what comes back.
At a glance
Section titled “At a glance”-
Goal: compute the end date of the period, and test whether a candidate end date is established.
-
You need: Bind input:
toCaseInputsupplies the case this chapter evaluates. The runtime singleton from Start opens the model once for both calls. -
Run:
Terminal node --import tsx --test test/evaluate.test.ts -
Files:
Output src/query.ts buildCollect, buildTruthsrc/runtime.ts evaluateCollect, evaluateTruth
Compute the end date
Section titled “Compute the end date”The first question leaves the end date open and lets the engine fill it in. This is a collect query. For the example case it computes the value — note the shape: the SDK returns an array of typed elements, not a bare string:
{ "evaluationStatus": "COMPUTED", "value": [{ "kind": "value", "type": { "name": "urn:law:std#Date" }, "value": "2026-03-20" }]}The application’s projection of that answer is the plain list
["2026-03-20"], produced by the readCollect reader in the next
chapter. When this guide shows a bare value, it is always the
projection — handlers must be written against the SDK shape above.
Check a candidate date
Section titled “Check a candidate date”The second question fills the end date with the user’s candidate and asks whether that claim holds. This is a truth query. On the computed date it establishes the claim:
{ "evaluationStatus": "COMPUTED", "truthStatus": "TRUE_ONLY" }On a wrong date — say 2026-03-21 — it answers NEITHER:
{ "evaluationStatus": "COMPUTED", "truthStatus": "NEITHER" }Each answer carries two statuses. evaluationStatus says how the
computation finished: COMPUTED means the engine finished. truthStatus
says what the finished computation supports: TRUE_ONLY means the
claim and not its negation; NEITHER means neither of them.
Ask the two questions in code
Section titled “Ask the two questions in code”The query builders name the question and its arguments. Both ask about
frist_ende, the end of the period with id frist. The collect query
leaves the end date open with the variable ?end; the truth query
fills it with the candidate:
// "?end" marks the free position the engine must fill in.export function buildCollect(id: string = CASE_ID): CollectQuery { return { kind: 'collect', predicate: 'frist_ende', args: [id, '?end'] };}
export function buildTruth(candidate: string, id: string = CASE_ID): TruthQuery { return { kind: 'truth', predicate: 'frist_ende', args: [id, candidate] };}The runtime evaluates through the shared model. One open model serves the whole process; every call passes the case input the adapter built:
// Calculate mode: which date(s) end the period?export async function evaluateCollect(input: FormInput): Promise<Answer> { const model = await openModel(); const query = buildCollect(); return model.collect(query.predicate, query.args, toCaseInput(input));}
// Verify mode: does the period end on the proposed date?export async function evaluateTruth(input: FormInput, candidate: string): Promise<Answer> { const model = await openModel(); const query = buildTruth(candidate); return model.truth(query.predicate, query.args, toCaseInput(input));}The same file also defines the explain calls for an answer that is not
established; Collect missing facts
introduces them where they are first used, and src/runtime.ts in the
archive holds the full runtime.
Why a wrong date answers NEITHER
Section titled “Why a wrong date answers NEITHER”The NEITHER on a wrong date surprises every newcomer, so read it
carefully. NEITHER says the computation supports neither the claim
nor its negation. The canon derives end dates; it does not derive “this
date is not the end”. Nothing in the rules concludes the negation, so a
wrong candidate is not established — and its negation is not
established either. NEITHER is the honest status for “not shown”,
and it is not FALSE_ONLY. FALSE_ONLY would mean the negation was
derived, which takes a rule that concludes it.
The same NEITHER appears when facts are missing: remove
frist_dauer_tage and truth on the right date still answers
NEITHER. “Wrong date” and “missing facts” share a status and differ
in their grounds — which is why the application must read the grounds
of the answer, not the status alone. Chapters 5 and 6 show how.
Limits and errors
Section titled “Limits and errors”evaluationStatusandtruthStatusare separate axes.COMPUTEDsays the engine finished;TRUE_ONLY/NEITHERsay what the finished computation supports. A non-COMPUTEDstatus means the question was not computed at all — there is no truth status then.- The candidate in
buildTruthmust be a validated date from the form schema. An unvalidated string fails inside the call instead of at the form, with a worse message.
Check your understanding
Section titled “Check your understanding”Run the calculate tests and confirm all three shapes:
node --import tsx --test test/evaluate.test.tsok 1 - collect computes 2026-03-20 for 14 days from 2026-03-06ok 2 - truth on the correct date is TRUE_ONLYok 4 - truth on a wrong date is NEITHER, not FALSE_ONLY# tests 13# pass 13# fail 0Before reading each answer, predict it.
The user has not proposed a date yet. Which query does the application need?
Collect. buildCollect leaves the end date open with ?end, and the
engine fills it in: 2026-03-20 for the example case. Truth needs a
candidate to check.
Why does the wrong date 2026-03-21 answer NEITHER and not FALSE_ONLY?
The canon has rules that derive end dates, but no rule that concludes
“this date is not the end”. The wrong date is not established, and its
negation is not derived either, so the status is NEITHER.
FALSE_ONLY would require a derived negation.
You remove the duration fact and check the correct date 2026-03-20. What status comes back?
NEITHER again — the same status as a wrong date. Without the duration
the end date cannot be derived. The two cases differ in their grounds,
not in their status, which is why the application reads the grounds.
- Handle results: every shape gets a rendering
- How to read an answer
- Query types for when to use
collect,truth, and the other operations
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.