Collect every matching person
Intent
Section titled “Intent”I want to collect every matching person.
Wrong form and why it stays silent
Section titled “Wrong form and why it stays silent”Collect takes a comprehension, not a predicate call with an unbound variable.
evaluate collect(eligible(p));Correct form
Section titled “Correct form”language "law.core" version "0.2";package recipe.m02 version "1.0.0";namespace "urn:recipe:m-queries:02";entity Person;relation registered(p: Person);relation eligible(p: Person);rule Admit strict { for p: Person; when registered(p); then eligible(p); }Frozen execution scene
Section titled “Frozen execution scene”| Input / variant | Question | Expectation |
|---|---|---|
| 1. two persons | collect p: Person where eligible(p) | evaluation_status == COMPUTED; |
| 2. empty domain | collect p: Person where eligible(p) | evaluation_status == COMPUTED; |
| 3. contested membership | collect p: Person where eligible(p) | evaluation_status == COMPUTED; |
| 4. rule removed | collect p: Person where eligible(p) | evaluation_status == COMPUTED; |
two members collected
test "two members collected" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00Z; knowledge_time @2026-09-13T09:00:00Z; timezone "UTC"; } assert registered(entity_ref("urn:recipe:m-queries:p")); assert registered(entity_ref("urn:recipe:m-queries:q")); } evaluate collect p: Person where eligible(p); expect evaluation_status == COMPUTED;}empty domain collects nothing
test "empty domain collects nothing" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00Z; knowledge_time @2026-09-13T09:00:00Z; timezone "UTC"; }
} evaluate collect p: Person where eligible(p); expect evaluation_status == COMPUTED;}disputed membership excluded
test "disputed membership excluded" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00Z; knowledge_time @2026-09-13T09:00:00Z; timezone "UTC"; } assert registered(entity_ref("urn:recipe:m-queries:p")); assert not eligible(entity_ref("urn:recipe:m-queries:p")); } evaluate collect p: Person where eligible(p); expect evaluation_status == COMPUTED;}Removed from the program: rule Admit strict { for p: Person; when registered(p); then eligible(p); }.
removed rule collects nothing
test "removed rule collects nothing" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00Z; knowledge_time @2026-09-13T09:00:00Z; timezone "UTC"; } assert registered(entity_ref("urn:recipe:m-queries:p")); } evaluate collect p: Person where eligible(p); expect evaluation_status == COMPUTED;}The composition of value is pinned by an extra check: scene 1 returns
[p, q], the others — []. This is a set of a finite known domain,
not a promise of completeness of all possible persons.
A separate negative JSON input is obtained from the scene 1 query by deleting
comprehension.kind. The normative JSON schema rejects it, but both
implementations answer COMPUTED and [p, q], with full byte parity.
This is a reproducible defect of both implementations:
structural input checking is incomplete. The correct query form remains
mandatory; agreement of two answers does not legalize invalid JSON.
Check of result fields and extra inputs:
>>> import runpy>>> checks = runpy.run_path("docs/recipes/m-queries/resources/check.py")>>> checks["collections"](https://github.com/arxohq/law/blob/master/docs/recipes/m-queries/2)TrueCounterfactual
Section titled “Counterfactual”The sidecar mutation reproduces LDC-E0201. Counterfactual table variants are executed separately; input errors are not passed off as NEITHER.
Boundary
Section titled “Boundary”An empty collection is a computed result. A corrupted query must yield QUERY_INVALID; the measured loophole is described above. An ordinary generator requires Established: Contradiction in scene 3 is excluded. Intentional inclusion of conflicting supports needs an explicit supported(P).
Pitfall
Section titled “Pitfall”A wrong form or arity is not a divergence of derivation.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.