docs← Back to article

Markdown for LLMs

Priority

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# Priority

**In one sentence:** a `priority` declaration states which of two opposite
defeasible inferences wins when both apply. The author uses it when a
general and a special norm collide on one case: without a declared edge, two
incomparable candidates are both preserved (Contradiction), and no “obvious
speciality” decides anything on its own.

The language specification treats priority as an explicit order between
opposite defeasible inferences: when both apply, the higher one wins, and
without a declared edge two incomparable candidates are both preserved. The
exception forms that remove support without an edge live on the
[defeasible-rules page](/constructs/rule-defeasible-unless/).

## 1. When to use and when not to

| Instead | Selection rule |
|---|---|
| `priority` vs `unless` in a rule | A local exception inside one article (“except in cases…”) is an `unless` clause: it expands into a defeater or a contrary rule and needs no separate declaration. A collision of two standalone norms from different articles is `priority` with a `reason`. Criterion: the exception knows only its own rule — `unless`; the norm knows its competitor by name — `priority` |
| `priority` vs a strict negative head | A prohibition without exceptions beats any permission on its own: strict opposite support defeats a defeasible candidate without an edge. `priority` is needed only between two defeasible candidates (or a rule over a defeater). Priority over a strict rule is a rejection `LDC-E4105` |
| `reason lex_specialis` vs `reason lex_posterior` | A special norm beats a general one, a later one beats an earlier one — but neither the number of conditions nor the date of adoption decides anything on its own: the ground is written as an explicit `reason`. Date and act level are facts for a `priority policy` with `when`, not automaticity |
| An explicit edge vs silent Contradiction | Incomparable candidates are both preserved: Contradiction is a substantive answer — “conflict unresolved” — not an error. An edge is declared when the law truly prefers one side; keeping Contradiction is lawful when the collision is genuine |

## 2. Minimal example

Package `research.priority.special_over_general`: a general norm admits a
registered vendor to trading; a special one refuses on licence revocation.
Without the edge both inferences are incomparable; the edge grounded in
`lex_specialis` makes the special norm the winner:

```law
rule GeneralTrade defeasible {
    for v: Vendor;
    when registered_trader(v);
    then may_trade_on_square(v);
}
rule RevocationRefusal defeasible {
    for v: Vendor;
    when licence_revoked(v);
    then not may_trade_on_square(v);
}
priority RevocationOverGeneral {
    prefer RevocationRefusal over GeneralTrade;
    reason lex_specialis;
}
```

Case facts: `registered_trader` + `licence_revoked` (both with
`origin case_input`). Query: `evaluate truth(may_trade_on_square(...))`.

Actual engine answer:

```text
law test research.priority.special_over_general: мир research.priority.special_over_general
  ok   [research.priority.special_over_general#authored] tests/01-special-wins.lawtest / urn:query:research-priority-01
  ok   [research.priority.special_over_general#authored] tests/02-general-alone.lawtest / urn:query:research-priority-02
итого: 2 проверено, 2 прошли, 0 не прошли, 0 не исполнены; код 0
```

`law engine check` — `check OK`, no warnings. The first test answers
Refuted (`RevocationRefusal ≻ GeneralTrade`); the second, with
the single fact `registered_trader`, — Established.

Sensitivity is proven by a pair of packages: `research.priority.no_priority_both`
holds the same two rules without a `priority` declaration, and the same
two-fact case answers Contradiction (`law test`
2/2). The single difference between the packages is the edge: it alone
changes Contradiction to Refuted. Removing the `licence_revoked` fact in
either package gives Established — the examples are not vacuous.

Nearest wrong outcome: expecting “speciality is visible by number of
conditions” so no edge is needed. The core does not count speciality:
without the edge the answer is Contradiction, and that is correct
behaviour, not an engine defect.

## 3. Example by domain

- **Law:** package `kz.corpus.administrative_code` (Administrative Offences Code of Kazakhstan),
  emergency vehicles and signals — a `prefer … over …` edge with `reason lex_specialis`: the railway-crossing
  offence (art. 607 part 1) displaces the general prohibitory-signal offence
  (art. 599 part 1); the in-file comment directly records “without the edge
  the defeater would have given Contradiction” (see the
  [corpus forms](/constructs/priority/corpus-forms/)).
- **Law:** package `kz.corpus.administrative_code` (Administrative Offences Code of Kazakhstan), sanctions —
  a series of edges of the percentage fine over the part 2 art. 44 limits:
  one special norm beats four general limits.
- **International law:** package `intl.labour.c138` (ILO Convention No. 138, minimum age),
  final provisions — a contrary `unless … then not …` proviso: the refusal form of
  an exception without a separate priority declaration.
- **Teaching case:** package `research.priority.no_priority_both` — the same conflict
  without the edge: an executable demonstration that silence gives Contradiction,
  not victory to the “obviously special” norm.

## 4. How the engine answers

Table — actual runs of this section’s teaching packages:

| Facts | Question | Answer | Why |
|---|---|---|---|
| `registered_trader`, `licence_revoked`, edge present | `may_trade_on_square` | Refuted | `RevocationRefusal ≻ GeneralTrade` |
| same facts, no edge | `may_trade_on_square` | Contradiction | candidates incomparable |
| only `registered_trader` | `may_trade_on_square` | Established | second rule not applicable |

Additionally, checked behaviours of the earlier edition (no dedicated tests
in this section’s packages; not fixed by a run here):

| Facts | Question | Answer | Why |
|---|---|---|---|
| `registered_trader`, `sells_prohibited_goods` | `may_trade_on_square` | Refuted | strict support beats a defeasible one without priority |
| `registered_trader`, `sanitary_violation` | `may_trade_on_square` | Not established, not refuted | the defeater removed support; the complement is not derived |
| same + `sells_essential_goods` | `may_trade_on_square` | Not established, not refuted | the priority condition not established — the defeater beats both candidates |
| same + `state_of_emergency` | `may_trade_on_square` | Established | `EssentialGoodsTrade ≻ SanitaryBlock`; a weak candidate does not hinder the strong one |
| same, priority cut | `may_trade_on_square` | Not established, not refuted | counterfactual: the priority over the defeater alone decides the outcome |

The `unless` proviso scenarios (bare and contrary forms) live on the
[defeasible-rules page](/constructs/rule-defeasible-unless/): a proviso’s
expansion belongs to the rule, not to priority.

- Priority is a strict partial order: the transitive closure counts;
  absence of a path is incomparability, not “first/last wins”.
- A preserved conflict is part of the answer: both sides’ candidates,
  priority edges, the reason for unresolvability.
- In `why_not`, a defeated candidate names the winner and the edge; on
  Contradiction — records the absence of a path between candidates.
- A conditional priority applies to a pair of applications only when
  its `when` is established; the corpus does not use it.
- The short edge form — `priority Name: A > B reason ground;`: the same
  declaration in one line. The choice between block and one-line form is a
  matter of readability: with a label and comments the block is clearer,
  otherwise the line is shorter and inferior in nothing.
- Priority of a rule over a defeater is the only lawful case where
  the sides’ heads match in polarity: the general rule survives under the
  defeater, and a weak candidate of the same side does not hinder the strong
  one. The defeated `GeneralTrade` application does not spoil the
  surviving `EssentialGoodsTrade` inference — defeat is pinpoint, not
  contagious.
- A ring closed at runtime from conditional edges gives the conflict group
  `PRIORITY_CONFLICT`: both sides preserved, no tie-break.

## 5. Common mistakes

1. “The special norm wins anyway” — without the edge, Contradiction (pitfalls,
   item 1).
2. Expected Refuted, got Not established, not refuted: a bare defeater/`unless` removes
   support without asserting the opposite (pitfalls, item 2).
3. `unless` on a strict rule — `LDC-E4110` (pitfalls, item 3).
4. Priority over a strict rule — `LDC-E4105` (pitfalls, item 4).
5. Two `prefer` clauses in one block or a block without `prefer` —
   `LDC-E0201`; a side naming no rule — `LDC-E4108`/`LDC-E1318`
   (pitfalls, item 5).
6. A priority ring — `LDC-E4104` already at `check` (pitfalls, item 6).
7. An edge between same-polarity heads — warning `LDC-E2142`: such a pair
   is not opposite, and the edge expresses nothing
   (pitfalls, item 7).

## 6. References

- Neighbour pages: [defeasible rules](/constructs/rule-defeasible-unless/) (`unless`
  provisos, defeater), [strict rules](/constructs/rule-strict/), [negation](/constructs/negation-and-status/).
- The defeater-vs-priority tutorial lives in the [tutorials catalogue](/tutorials/defeaters/).
- The pitfalls page lists the diagnostics (`LDC-E4110`, `LDC-E4105`,
  `LDC-E0201`, `LDC-E4108`/`LDC-E1318`, `LDC-E4104`, `LDC-E2142`) with wrong
  forms and fixes.

## 7. Grammar excerpts

Conflict clauses inside a rule (the `defeat_clause` and `unless_clause`
productions; the full `rule_decl` grammar lives on the
[strict-rules page](/constructs/rule-strict/); the `unless` expansion lives on the
[defeasible-rules page](/constructs/rule-defeasible-unless/)):

```ebnf
defeat_clause           = "defeat", proposition, ";" ;
unless_clause           = "unless", [ identifier, "when" ], formula, [ "then", proposition ], ";" ;
```

A priority declaration (the `priority_decl`, `priority_item` productions;
exactly one edge per declaration; a `priority policy` is the
`priority_policy_decl` production):

```ebnf
priority_decl           = "priority", identifier,
                          ( "{", { priority_item }, "}"
                          | ":", reference, ">", reference,
                            "reason", qualified_name, ";" ) ;
priority_item           = "prefer", reference, "over", reference, ";"
                        | "when", meta_formula, ";"
                        | "reason", qualified_name, ";"
                        | source_anchor_item
                        | label_item
                        | metadata_item ;
```