Markdown for LLMs
Exercise 10. The same date via two norms
The source Markdown for this article. Copy it into your assistant or download it as a text file.
# Exercise 10. The same date via two norms
An exercise for the [from article text to
norm](/tutorials/real-article-rules/) page. On the page the benefit grant
date is computed by one term: `max(from, registered)`. The same meaning
can be written as two norms with guards, a record closer to the article
text, where two cases are named apart.
**Setup.** Replace the one `max` norm with two norms: if disability was
established no earlier than the application registration, benefit is
granted from the establishment date; if earlier, from the registration
date. On all three cases the answer must match the `max` form:
| Established | Application registered | Grant date |
|---|---|---|
| 15 January 2026 | 10 March 2026 | 10 March 2026 |
| 10 March 2026 | 15 January 2026 | 10 March 2026 |
| 10 March 2026 | 10 March 2026 | 10 March 2026 |
**Hint.** The third row is the boundary. One of the two norms must take
equality, and only one: two norms with one head and one value would give
the same answer, but sloppily.
Below is the solution. Try it yourself first.
## Solution
```law
language "law.core" version "0.2";
package tutorial.kz.social version "0.2.1";
namespace "urn:law:tutorial:kz:social";
entity Actor;
entity Person : Actor;
entity DisabilityStatus;
entity Benefit;
entity BenefitApplication;
const DisabilityBenefit: Benefit = entity_ref("urn:law:tutorial:kz:social#DisabilityBenefit") {
label ru-KZ official "Пособие по инвалидности";
};
relation disability_established(person: Person, status: DisabilityStatus, from: Date) kind institutional;
relation entitled(person: Person, benefit: Benefit) kind institutional;
relation application_for(application: BenefitApplication, person: Person, benefit: Benefit) kind empirical;
relation application_registered(application: BenefitApplication, day: Date) kind institutional;
relation benefit_start_date(person: Person, benefit: Benefit, day: Date) kind institutional;
```
The label reads: "Disability benefit".
Two norms. Equality goes to the first:
```law
@source("KZ-SOCIAL-CODE-224-VII-ART-175")
rule DisabilityBenefitStartFromDisability strict {
label ru-KZ official "Статья 175. Назначение с даты установления инвалидности";
for person: Person;
for status: DisabilityStatus;
for from: Date;
for application: BenefitApplication;
for registered: Date;
when entitled(person, DisabilityBenefit)
and disability_established(person, status, from)
and application_for(application, person, DisabilityBenefit)
and application_registered(application, registered)
and from >= registered;
then benefit_start_date(person, DisabilityBenefit, from);
}
@source("KZ-SOCIAL-CODE-224-VII-ART-175")
rule DisabilityBenefitStartFromApplication strict {
label ru-KZ official "Статья 175. Назначение с даты регистрации заявления";
for person: Person;
for status: DisabilityStatus;
for from: Date;
for application: BenefitApplication;
for registered: Date;
when entitled(person, DisabilityBenefit)
and disability_established(person, status, from)
and application_for(application, person, DisabilityBenefit)
and application_registered(application, registered)
and from < registered;
then benefit_start_date(person, DisabilityBenefit, registered);
}
```
The labels read: "Article 175. Grant from the disability establishment date" and "Article 175. Grant from the application registration date".
Which form is better. `max` is shorter and has no boundary to lose. Two
norms read as the article's two cases and each gets its label: in
verbalisation and in the derivation explanation, the answer's consumer
will see **which** case fired. Both forms are correct; the choice is
about what matters more to show the answer's reader.
## Check
The setup's three rows execute on this package. The fourth
check is a counterfactual: without the `and from >= registered` guard,
the first norm grants benefit from the establishment date on the first
case too. The answer to the 10 March question stays `TRUE_ONLY`, but the
15 January question also answers `TRUE_ONLY`: one person holds two grant
dates at once. A key over person and benefit does not catch this: it
reconciles case facts, not norm conclusions, and declares no conflict.
This page's first version promised `BOTH` here, and the check corrected
it.
What the exercise teaches. Two norms' guards must cover the axis without
gaps or overlaps: `>=` and `<`. A gap yields `NEITHER` on the boundary,
an overlap two values the engine silently holds side by side. The
compiler sees neither mistake; only a boundary case and a **wrong**-date
question catch them.