docs← Back to article

Markdown for LLMs

PRIORITY_CONFLICT — Two ranking rules point at each other

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

Download this articlePlain text ↗
# PRIORITY_CONFLICT — Two ranking rules point at each other

## What it means

When two defeasible rules disagree, ranking rules say which one wins.
Those rankings are expected to form a coherent order. Sometimes two
conditional rankings both fire on the same pair of rules in opposite
directions: each says the other loses. There is no coherent winner then,
and the engine refuses to break the tie by fiat. The conflict is reported
so the package author can see the cycle and repair it.

This status is about the rankings, not the facts. The same facts under a
repaired order compute normally.

## When you see it

```law
language "law.core" version "0.2";
package demo.diagnostics version "0.1.0";
namespace "urn:law:demo:diagnostics";

entity Applicant;
relation resident(a: Applicant) kind empirical;
relation badge_holder(a: Applicant) kind empirical;
relation permit_eligible(a: Applicant) kind institutional;

rule Eligibility defeasible {
    for a: Applicant;
    when resident(a);
    then permit_eligible(a);
}

rule BadgeRefusal defeasible {
    for a: Applicant;
    when badge_holder(a);
    then not permit_eligible(a);
}

priority CondFirst {
    prefer Eligibility over BadgeRefusal;
    when conflicts(higher, lower);
    reason lex_specialis;
}

priority CondSecond {
    prefer BadgeRefusal over Eligibility;
    when conflicts(higher, lower);
    reason lex_posterior;
}
```

```lawtest
language "law.core" version "0.2";
package demo.diagnostics version "0.1.0";
namespace "urn:law:demo:diagnostics";

test "contextual priorities collide" {
    given {
        context { legal_time @2026-03-01; decision_time @2026-03-01T09:00:00Z; knowledge_time @2026-03-01T09:00:00Z; timezone "UTC"; }
        assert resident(entity_ref("urn:demo:diagnostics:ann")) { origin case_input; }
        assert badge_holder(entity_ref("urn:demo:diagnostics:ann")) { origin case_input; }
    }
    evaluate truth(permit_eligible(entity_ref("urn:demo:diagnostics:ann")));
    expect evaluation_status == PRIORITY_CONFLICT;
}
```

Both conditional rankings fire on the same pair of rules in opposite
directions. There is no winner, so the eligibility question ends here.

## What to do

Repair the rankings in the package: narrow the conditions so they cannot
both fire on one pair, or add a higher ranking that orders the two.
Facts alone cannot fix this — the cycle lives in the rules.

## Related

- [Testing a package](/language/testing-a-package/) — how scenarios pin outcomes.
- [UNRESOLVED_NORMATIVE_CONFLICT](/diagnostics/UNRESOLVED_NORMATIVE_CONFLICT/) — when norms collide with no ranking at all.