# Source hierarchy ## Intention I want to compare source rank while keeping the rules defeasible. ## Incorrect form and why it stays silent ```law title="Incorrect form" rule Higher strict { for p: Person; when eligible(p); then not allowed(p); } // Объявление entity RuleApplication отсутствует. for high: RuleApplication; ``` Strictness is a logical category. Legal rank is given by data and policy; a missing rank is not a highest or zero rank. RuleApplication is a local type here, not a built-in: it must be declared. Meta-predicates rule_of and conflicts, by contrast, are supplied by the engine; a local twin would shadow them. ## Correct form ```law language "law.core" version "0.2"; package recipes.b.r07 version "0.1.0"; namespace "urn:recipe:b-rules:07"; entity Person; relation eligible(p: Person); relation special(p: Person); relation allowed(p: Person); entity RuleApplication; relation rank(rule_name: Text, level: Integer); rule Lower defeasible { for p: Person; when eligible(p); then allowed(p); } rule Higher defeasible { for p: Person; when eligible(p); then not allowed(p); } priority policy Hierarchy { for high: RuleApplication; for low: RuleApplication; when conflicts(high, low) and exists hr in (collect hr: Text where rule_of(high, hr)) where exists lr in (collect lr: Text where rule_of(low, lr)) where exists hk in (collect hk: Integer where rank(hr, hk)) where exists lk in (collect lk: Integer where rank(lr, lk)) where hk < lk; prefer high over low; reason lex_superior; } ``` ## Frozen execution scene | Facts and choice | Question | Answer | |---|---|---| | higher level | `truth(allowed(entity_ref("urn:recipe:b-rules:07:p")))` | `FALSE_ONLY` / `COMPUTED` | | rank not given | `truth(allowed(entity_ref("urn:recipe:b-rules:07:p")))` | `BOTH` / `COMPUTED` | | policy removed | `truth(allowed(entity_ref("urn:recipe:b-rules:07:p")))` | `BOTH` / `COMPUTED` | | swapped ranks | `truth(allowed(entity_ref("urn:recipe:b-rules:07:p")))` | `TRUE_ONLY` / `COMPUTED` | ```law test "senior level" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert eligible(entity_ref("urn:recipe:b-rules:07:p")); assert rank(Higher, 1); assert rank(Lower, 2); } evaluate truth(allowed(entity_ref("urn:recipe:b-rules:07:p"))); expect truth_status == FALSE_ONLY; expect evaluation_status == COMPUTED; } ``` ```law test "rank not given" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert eligible(entity_ref("urn:recipe:b-rules:07:p")); } evaluate truth(allowed(entity_ref("urn:recipe:b-rules:07:p"))); expect truth_status == BOTH; expect evaluation_status == COMPUTED; } ``` ```law test "ranking policy removed" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert eligible(entity_ref("urn:recipe:b-rules:07:p")); assert rank(Higher, 1); assert rank(Lower, 2); } evaluate truth(allowed(entity_ref("urn:recipe:b-rules:07:p"))); expect truth_status == BOTH; expect evaluation_status == COMPUTED; } ``` ```law test "ranks swapped" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert eligible(entity_ref("urn:recipe:b-rules:07:p")); assert rank(Higher, 2); assert rank(Lower, 1); } evaluate truth(allowed(entity_ref("urn:recipe:b-rules:07:p"))); expect truth_status == TRUE_ONLY; expect evaluation_status == COMPUTED; } ``` ## Counterfactual Mutation: `entity RuleApplication;` → ``; rejection LDC-E2101. Scenes that delete a fragment are marked explicitly in the table. The same swapped ranks: replace `rule Higher defeasible` with `rule Higher strict`. The result is FALSE_ONLY instead of TRUE_ONLY. This is a rank-model error: strict support cannot be lifted, so this is not an evaluator defect. This extra scene is executed by the adapter on the mutated program, with both evaluators and a byte comparison: ```law test "strict higher source refuses" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } assert eligible(entity_ref("urn:recipe:b-rules:07:p")); assert rank(Higher, 2); assert rank(Lower, 1); } evaluate truth(allowed(entity_ref("urn:recipe:b-rules:07:p"))); expect truth_status == FALSE_ONLY; expect evaluation_status == COMPUTED; } ``` ```python >>> import runpy >>> checks = runpy.run_path("docs/recipes/b-rules/resources/check.py") >>> checks["check_strength"](https://github.com/arxohq/law/blob/master/docs/recipes/b-rules/7) 'Б7: FALSE_ONLY; lawc = lawref; ошибка выбора силы подтверждена' ``` ## Boundary The rank is instructional: a smaller number means a higher level. Linking a rule to a source in a real package must have provenance. Here rule → rank is set directly for a minimal witness. The extra counterfactual below replaces Higher with strict and shows that rank can no longer override it.