# 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.