# Coming from DMN **In short:** a DMN decision table is a set of rows plus a hit policy that says what happens when several rows match. In Arxo there is no table-wide hit policy: each row is a defeasible rule, and what DMN decides through the hit policy is written where it applies. Rows that agree simply support the same conclusion; rows that disagree both fire until a priority says which wins; first-hit order is an explicit guard; a default output is a closure over the cases on file; and a missing input is an answer of its own, `NEITHER`. This page follows the portable table of the [DMN comparison](/comparisons/dmn/). The Arxo package quoted here passes `law engine check`; its scenarios and the DMN engines of the experiment have not been run yet, so the page shows how the table is written, not measured outcomes. ## Concept map | DMN | Arxo | What changes for you | |---|---|---| | A row of a decision table | A `rule … defeasible`: the input entries become the `when` condition, the output entry becomes the head | Each row has a name, and an answer can say which rows supported it | | UNIQUE or ANY: rows overlap and disagree (a runtime incident in the table engines) | Two rules that both fire for the case, with no priority between them; Arxo's tabular form reports the same overlap statically, before execution | A violated hit policy is something you see in the answer or in a diagnostic, rather than an engine failure | | COLLECT with rows that agree | Several rules with the same head: each is an independent support | Agreement needs no policy | | FIRST | The later row carries a guard, `not `, that encodes the order of the source table | Row order is spelled out in the rule that depends on it | | PRIORITY (excluded from the portable baseline) | Precedence between particular rules is a `priority` with a reason | There is no table-wide ordering of outputs | | Default output entry, no match | A `closure` over the cases on file: a case in the domain with no supporting row gets an explicit negative | The default applies only to the cases the register covers | | Null input | Absent facts: a predicate without a closure answers `NEITHER`; a closed predicate answers `FALSE_ONLY` | The difference between "unknown" and "no" is chosen per predicate, not per engine | | A table edit that changes a threshold | An exception rule with a `priority` and `reason explicit_exception`; it needs the revision fact to fire | Cases under the old revision are untouched by the new rule | | COLLECT aggregation (SUM, MIN, MAX, COUNT) and list outputs | Not built by this package: it names which rows fired; the aggregated values stay in the neutral case bank | Parity here is observed, not computed | ## A row is a rule Here is a table from the DMN conformance test suite that the experiment uses as an input: two rows, a COLLECT policy with MAX aggregation, and a default output of 0. ```xml Age Years of Service 0 <18,>=60 - 5 - >=30 5 ``` The Arxo package encodes the experiment's own portable table rather than this file line by line, but the closest pair of rows looks like this: two rows granting the same extra amount, one for long service and one for a young employee. In this package the input bands arrive as facts about the case (`years_long`, `age_minor`), so the FEEL tests do not appear in the rule bodies; and the package covers only the under-18 band of the first row above. ```law rule ExtraVeteran defeasible { for c: Case; when years_long(c); then extra5(c); } rule ExtraYoung defeasible { for c: Case; when age_minor(c); then extra5(c); } ``` When both rows match, both rules support `extra5(c)`. There is nothing to reconcile, so there is no hit policy to choose. ## Overlap that disagrees Under UNIQUE or ANY, two matching rows with different outputs are an error in the table engines. In Arxo the same situation is two rules with different conclusions for one case and no priority between them: ```law rule ConflictA defeasible { for c: Case; when overlap_case(c); then award_standard(c); } rule ConflictB defeasible { for c: Case; when overlap_case(c); then award_senior(c); } ``` Both rules fire, and nothing in the package picks one: the priority is left out on purpose, so the overlap stays in the answer for a person to resolve. For the same table in Arxo's tabular form, the overlap is reported before execution. The [DMN comparison](/comparisons/dmn/) calls this a difference of stage, not of meaning. ## First hit as an explicit guard FIRST makes the order of rows part of the table's meaning. In Arxo the order is written into the rule that depends on it: the second row only fires when the first row's outcome is established false, which here comes from the closure on `award_standard` shown below. ```law rule FirstRow1 defeasible { for c: Case; when first_case(c); then award_standard(c); } rule FirstRow2 defeasible { for c: Case; when first_case(c) and not award_standard(c); then award_senior(c); } ``` A negative literal in a body needs the fact to be established false, so when `FirstRow1` fires, `FirstRow2` stays silent. The experiment also switches one table from a conflicting policy to FIRST; on the Arxo side the same pair of rules covers the switched revision. ## Default output and edits A default output entry answers when no row matches. The Arxo counterpart is a closure: a statement that the register of cases is complete as of a given time, so a case in it with no supporting row is explicitly not awarded the standard outcome. Rules that do support it are not affected. ```law closure AwardDefault { predicate award_standard; domain case_on_file; snapshot "urn:stand:dmn-hitoverlap:cases:2026-09-30"; complete_as_of @2026-09-30T00:00:00Z; derive_explicit_negative true; } ``` A table edit that moves an age threshold from 18 to 21 becomes an exception rule that only fires with the revision fact, plus a priority over the row it overrides: ```law rule Threshold21Exception defeasible { for c: Case; when rev_b_threshold_21(c) and age_young_edge(c); then not award_standard(c); } priority Threshold21OverStd { prefer Threshold21Exception over RowStd; reason explicit_exception; } ``` ## What you gain, what you give up - **Gain: a named policy per conflict.** Instead of one hit policy for the whole table, each overlap is either agreement, a declared priority with a reason, or a conflict kept visible. - **Gain: "unknown" separate from "no".** A missing input does not have to be folded into the default; the [DMN comparison](/comparisons/dmn/) notes that the standard leaves no match and null input open and engines diverge. - **Give up: the table as the reading surface.** Analysts read a DMN table directly, in mature editors, and exchange it between engines through a shared interchange file with a community conformance suite. This page shows the rule form, and this package does not compute aggregations or list outputs. - **Combining rather than replacing.** The comparison's combined pattern keeps the tabular fragment in DMN and lets Arxo frame it with editions, conflicts and review trails. ## Next steps - [DMN](/comparisons/dmn/): the full comparison, the studied engines and what is still open. - [Defeasible rules and unless](/constructs/rule-defeasible-unless/), [Priority](/constructs/priority/), [Negation and truth statuses](/constructs/negation-and-status/): the constructs used on this page. - [Missing and conflicting facts](/language/missing-and-conflicting/): `NEITHER` and `BOTH` in a worked example. - [Guide](/guide/): getting started with Arxo.