RFC-048: A Cell Answers Through a Reduction, and the Process Combines the Answers

ProposedPartially implemented
Depends on

Context

Some answers are in what an organization recorded earlier, not in the law:

  • The head grants leave “slechts eenmaal … per schooljaar” (Leerplichtwet 1969 art. 13a lid 2). Earlier grants are in the school’s own decisions.
  • Leave must fall “buiten de schoolvakanties” (art. 11 onder f). The holidays depend on where the school is established, a fact the school recorded.
  • An examination may be skipped if “aan de aanvrager eerder een gehandicaptenparkeerkaart is verstrekt” (Regeling gehandicaptenparkeerkaart art. 2 lid 2). Another municipality or the CBR may have issued it.

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.

Decision

Chronolexography shows this at work.

1. A reduction is a named answer of its cell

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.

# reductie_verlof_al_verleend_in_schooljaar, shortened competent_authority: name: Het hoofd van OBS De Klimop execution: parameters: [bsn_jongere, eerste_verlofdag] input: - name: besluiten source: decisions: leerplichtwet_1969#13a - name: begin_schooljaar source: regulation: fictief_beleid_vakantieverlof_obs_de_klimop output: begin_schooljaar_van_verlof parameters: {eerste_verlofdag: $eerste_verlofdag} output: - name: verlof_al_verleend_in_schooljaar
  • 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.
  • A reduction may call policy or law with 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.

# corpus/cells/obs_de_klimop/cel.yaml name: Het hoofd van OBS De Klimop category: het hoofd answers: verlof_al_verleend_in_schooljaar: reductie_verlof_al_verleend_in_schooljaar

2. The decider’s policy binds a term to an answer

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:

# fictief_beleid_vakantieverlof_obs_de_klimop art. 3, shortened implements: - {law: leerplichtwet_1969, article: 13a, open_term: verlof_al_verleend_in_schooljaar} execution: input: - name: antwoord_verlof_al_verleend nullable: true source: reduction: verlof_al_verleend_in_schooljaar parameters: {bsn_jongere: $bsn_jongere, eerste_verlofdag: $eerste_verlofdag}

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.

  • The binding is policy like any other, so the order of precedence is unchanged: policy, then the finding, then the default (RFC-045 §5). Where the cell answers, its answer sets a finding aside.
  • Without an answer the input is null (hence 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.
  • The binding passes only the parameters it names. The cell refuses one the reduction does not declare, and a declared one the binding leaves out unless it is required: false.
  • Should the term occur in another article, or in another law the same authority carries out, the policy gets a second article with the same source. The reduction stays as it is.
  • The engine never runs a reduction itself; a REDUCTIE stays out of its implements index.

3. Only a reduction reads a chronicle

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;
  • in a 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.

4. The process combines the answers of competent cells

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:

  • the term names 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;
  • otherwise: the cell of the policy’s holder.

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.

AnswersValue
nonenull, as in §2
onethat answer
severalmerged 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.

5. Who answered is in the result, why is with the cell

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.

6. Replay and reconsideration

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.

Where each choice comes from

ChoiceSource
Reduction in the cell that holds the recordsThe 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 itAuthor’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 normAuthor’s decision (Tim de Jager, 22 October 2026)
The reduction in the corpus under its holder, the catalogue in cel.yamlAuthor’s decision (Tim de Jager, 22 October 2026)
Synthesis in the asking processThe paper
Routing wherever the binding runsOwn choice; departs from RFC-052
The term’s combine wins over the binding’sOwn choice
Replay asks other cells as of the day; only the day is storedAuthor’s decision (Tim de Jager)

Why

Benefits

  • Law and policy say nothing about the chronicle. A jurist reads both without knowing what a cell is; the policy names an answer in words.
  • The source is not tied to one question. The consumer binds the answer where it needs it.
  • A norm such as the school year is written once, in policy, and the reduction applies it.
  • Anyone can answer, however it reduces: a cell, or a scenario with the authority’s finding.
  • A reduction is type-checked and traced like any article.
  • The engine knows no cells; it asks for an answer by name and compares names.

Tradeoffs

  • An authority’s finding on a term the cell answers is set aside; the trace says so.
  • A decision’s trace shows who answered, not why. For why, ask the cell.
  • The catalogue is the only record of which answers are the cell’s. A cell opened from the wrong directory, whose catalogue lacks the answer, replays it as the authority’s finding with the same outcome.

Open points are listed in Open Points in Chronolexography.

Alternatives Considered

  • The reduction returns a list; policy computes. Policy would hold logic that exists only for the chronicle.
  • A reduction or binding language in cell configuration (PR #1689, RFC-022 §4.1). A second language without type checker or trace.
  • The article asks the answer as a parameter (first version). Lost in nested calls, invisible in the trace.
  • The engine runs the reduction as an implementation (16–17 October 2026). That put the reduction’s FOREACH in the decision’s trace.
  • The reduction fills the term with implements (schema v0.8.5 to v0.8.8). It works, but ties the source to one question of one law.
  • Policy reads the chronicle itself. That removes the line between consumer and source.
  • The cell drops revoked decisions from the rows. The reduction would not see the whole picture.
  • A list of answers as a value, with FOREACH in the law. The law would see cells.
  • A composite answerer in packages/cel. Rule and competence in Rust; the engine would see one source.

Implementation

SchemaAdds
v0.8.2REDUCTIE, source.decisions
v0.8.5implements on a REDUCTIE
v0.8.6combine: ONLY (and source.executograms, replaced in v0.8.7)
v0.8.7source.facts
v0.8.9no 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.

References

RegelRecht

An exploration into transparent, executable legislation, and one of the three projects in the starting selection of the Nederlandse Digitale Dienst.

Links

GitHub repository
How it works
Stay informed
Roadmap (Dutch)
Documentation
Research

Contact

regelrecht@minbzk.nl

Part of

Nederlandse Digitale Dienst
Ministry of Economic Affairs and Climate Policy