Some answers are in what an organization recorded earlier, not in the law:
The law leaves such terms to the authority and does not say how the authority reads its records back. The position paper does: “Reductie vindt altijd plaats ín de cel waar de betreffende chronolexogrammen zijn vastgelegd”, and “Synthese gebeurt bij de afnemer, niet bij de bron”. The source is the cell. The consumer is the law together with the policy of the authority that decides: the law asks, the policy says where the answer comes from.
Chronolexography shows this at work.
How a cell reduces is up to the cell. The engine only asks it for an answer by name (§2). The cell in packages/cel uses what the engine offers: a reduction in the law format, regulatory_layer: REDUCTIE. It sits in the corpus with the rest of the rulework, at corpus/regulation/nl/reducties/<id>/<valid_from>.yaml, and names its holder, the body whose chronicle it reads, in competent_authority. Each output is an answer. A reduction fills no open term, so it has no implements.
source.decisions (<regulation>#<article>): one row per decision, with fields, outputs and id.source.facts (<regulation>#<article>#<fact>): one row per recorded fact (RFC-051). The last # separates the fact.combine: ONLY on a FOREACH: the one result the filter leaves; null for none, an error for two.source.regulation for a norm, and passes what it found in the chronicle as parameters. Above, the head’s policy says which school year the leave falls in; the reduction applies it to the rows.The cell’s cel.yaml is its catalogue: per answer the reduction that gives it. It holds no logic.
The law asks no cell. Which term an answer fills is the consumer’s choice, made in the UITVOERINGSBELEID of the authority that decides. One article fills the term with implements and takes the answer as an input:
A caller may give an execution an answerer (OpenTermAnswerer, in a Call). Wherever the binding runs, at any depth, the engine asks it for the answer by name with the parameters the binding passes. During a decision the cell is the answerer. It runs the reduction its catalogue names and returns the value with its provenance.
nullable: true). On a term with a default or decided_per_case_by, the binding is then silent and the term falls back; a term decided per case without a finding fails the execution, so a missing answer never grants anything. On a term with neither, null is its value.required: false.REDUCTIE stays out of its implements index.The loader (load_check::reject_misplaced_reduction) keeps the chronicle out of law and policy:
source.decisions and source.facts only in a REDUCTIE, alone in their source;REDUCTIE no implements, hooks, overrides, execution.produces or open_terms;source.reduction only in an article with implements, in a UITVOERINGSBELEID that names one holder by name, from schema v0.8.9, and beside no other key of source except parameters and combine;combine in a source only beside reduction, fitting the input’s type.Schema v0.8.5 to v0.8.8 allowed implements on a REDUCTIE. The loader still accepts it under a $schema of those versions and gives it no meaning; a reduction without $schema is held to the current version.
The cell refuses an answer from a reduction the service does not hold, from one that is no REDUCTIE, and from one whose competent_authority is not the cell. A cell directory with reducties/ does not open, since a reduction sits in the corpus. Before the first valid_from of a reduction the cell is silent, so a decision from before it replays with the authority’s finding. Cell::answers lists the catalogue. Declaring it is a RegelRecht addition (RFC-022 §4.1); in the paper a cell reduces on request and declares nothing.
A decision may take other cells along: its sphere. Which cells the engine asks for a binding’s answer follows from the term it fills:
competent_authority: every answerer of the call it names, an INSTANCE by name and a CATEGORY by category, in name order and without short-circuit;This holds wherever the binding runs. RFC-052 routed on competence only for a term reached through source.regulation; with the answer named in policy that limit had no work left to do.
Every cell is asked for the same answer name. A cell whose catalogue lacks it is silent, as is one that answers null.
| Answers | Value |
|---|---|
| none | null, as in §2 |
| one | that answer |
| several | merged with combine: the term’s (RFC-051 §3), else the binding’s; without either, an error naming the answerers |
The law’s combine wins, since it says how the law weighs several competent actors. The binding’s serves a term that names none.
ArticleResult.open_terms reports filled_by: {answer: {law_id, article, answers}}: the binding’s policy and article, and per answer the cell, the answer’s name, the reduction with its version, and how far it read the chronicle. The trace has a node per answer under the binding’s input, null answers included; a cell without the answer is named in the input’s message. Why is the cell’s to show (Cell::explain_answer), with the steps of the policy the reduction calls; that trace is not stored.
On replay (RFC-046) the cell answers from its chronicle as it stood before the decision. Sphere cells answer from what they recorded up to its day. Only that day is stored. When Awb 7:11 calls a decision anew, the binding runs in that call and the cell answers without the contested decision. Revoked decisions stay in the rows; the reduction leaves them out.
| Choice | Source |
|---|---|
| Reduction in the cell that holds the records | The paper |
Reduction as rulework (REDUCTIE) | Own choice: one option the engine offers; another cell may reduce in its own way |
| A reduction gives a named answer and fills no term; the decider’s policy binds it | Author’s decision (Tim de Jager, 22 October 2026), after the paper: the perspective lies with the one who asks |
| A reduction may call policy for a norm | Author’s decision (Tim de Jager, 22 October 2026) |
The reduction in the corpus under its holder, the catalogue in cel.yaml | Author’s decision (Tim de Jager, 22 October 2026) |
| Synthesis in the asking process | The paper |
| Routing wherever the binding runs | Own choice; departs from RFC-052 |
The term’s combine wins over the binding’s | Own choice |
| Replay asks other cells as of the day; only the day is stored | Author’s decision (Tim de Jager) |
Open points are listed in Open Points in Chronolexography.
FOREACH in the decision’s trace.implements (schema v0.8.5 to v0.8.8). It works, but ties the source to one question of one law.FOREACH in the law. The law would see cells.packages/cel. Rule and competence in Rust; the engine would see one source.| Schema | Adds |
|---|---|
| v0.8.2 | REDUCTIE, source.decisions |
| v0.8.5 | implements on a REDUCTIE |
| v0.8.6 | combine: ONLY (and source.executograms, replaced in v0.8.7) |
| v0.8.7 | source.facts |
| v0.8.9 | no implements on a REDUCTIE; source.reduction and source.combine in a binding; a root competent_authority for the holder |
Engine: answer.rs (OpenTermAnswerer::answer, AnswerRequest, Answer, AnswerProvenance, Call, Authority), resolve_open_term, resolve_answer, combine_with, combine_only, FilledBy::Answer, load_check::chronicle_read, load_check::reject_misplaced_reduction; tests in packages/engine/tests/reduction.rs and synthesis.rs. Cell: cel.yaml with answers, Cell::answers, reading (bindings, bound_terms, Reader), Cell::explain_answer. Corpus: seven reductions under corpus/regulation/nl/reducties/, bound in fictief_beleid_vakantieverlof_obs_de_klimop and in the parking-card policy of Wilgendaal. Not built: calling an article per FOREACH element, so a reduction asks policy once for the case and compares each row with that.
An exploration into transparent, executable legislation, and one of the three projects in the starting selection of the Nederlandse Digitale Dienst.
GitHub repository
How it works
Stay informed
Roadmap (Dutch)
Documentation
Research
Nederlandse Digitale Dienst
Ministry of Economic Affairs and Climate Policy