# Exercise 9. An anchor the compiler checks An exercise for the [real article: source and anchor](/tutorials/real-article-source/) page. The page's norm is anchored by the string key `@source("KZ-SOCIAL-CODE-224-VII-ART-175")`. In CLIR such an anchor stays an opaque string: tools walking from the norm to the text arrive nowhere by it. **Setup.** Replace the string anchor with a fragment-identifier reference and confirm over CLIR that the anchor became an address. Then write a positive test: a foreigner with established disability permanently residing in the country is entitled to benefit. The test must pass, and the first attempt at writing it against the page's norm will fail. Find out why. **Hint.** A case fact writes an interval just like a norm: `[@2024-01-01, infinity)`. Look at how the norm reads the interval: it holds a variable. Check on a small package whether the engine matches such an interval against a fact. Below is the solution. Try it yourself first. ## Solution The page's ontology unchanged, except one thing: the jurisdiction constant in the case fact is fed by name, `KZ`, not by an `entity_ref` with the same address — a constant reference and an entity reference are not equal in a case. ```law language "law.core" version "0.2"; package tutorial.kz.social version "0.1.1"; namespace "urn:law:tutorial:kz:social"; entity Actor; entity Person : Actor; entity DisabilityStatus; entity Benefit; const KZ: Jurisdiction = entity_ref("urn:law:jurisdiction:KZ"); 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 permanently_resident(person: Person, jurisdiction: Jurisdiction, during: Interval) kind institutional; relation citizen_of(person: Person, jurisdiction: Jurisdiction) kind institutional; relation foreign_citizen(person: Person) kind institutional; relation stateless_person(person: Person) kind institutional; relation entitled(person: Person, benefit: Benefit) kind institutional; source SOCIAL_CODE { kind code; jurisdiction KZ; number "224-VII"; } edition SOCIAL_CODE_2023_RU of SOCIAL_CODE { language ru-KZ; officiality official; adopted @2023-04-20; in_force [@2023-07-01, infinity); materialization_status ABSTRACT_ONLY; } fragment SOCIAL_CODE_ART175_TEACHING in SOCIAL_CODE_2023_RU { kind article; locator "article/175"; text ru-KZ unofficial """Учебная выдержка, не официальный текст: право на пособие по инвалидности имеют лица с установленной инвалидностью, постоянно проживающие на территории Республики Казахстан. """; content_hash "sha256:46a9b7144940cc1e85c2878749f2903a7ba915b8f72bf9ec29a72808dbc7483d"; } ``` The label reads: "Disability benefit". The quoted fragment reads: "Teaching excerpt, not the official text: persons with established disability permanently residing on the territory of the Republic of Kazakhstan are entitled to disability benefit." An anchor by fragment identifier. The residence condition is changed, and that is the task's second half: ```law @source(SOCIAL_CODE_ART175_TEACHING) rule DisabilityBenefitEntitlement strict { label ru-KZ official "Статья 175. Право на пособие по инвалидности"; for person: Person; for status: DisabilityStatus; for from: Date; for during: Interval; when disability_established(person, status, from) and permanently_resident(person, KZ, during) and (citizen_of(person, KZ) or foreign_citizen(person) or stateless_person(person)); then entitled(person, DisabilityBenefit); } ``` The rule label reads: "Article 175. The right to disability benefit". Why changed. On the page, residence is recorded as `permanently_resident(person, KZ, [from, infinity))`: an interval with a variable inside. As of 05.09.2026, neither engine matches such a term against a case fact: feed a fact with the interval `[@2024-01-01, infinity)` and a 1 January 2024 establishment date and the norm stays silent. A small three-rule package shows the boundary exactly: an interval literal in a body matches, a variable over the whole interval matches, an interval with a variable inside does not, and the comparison `during == [from, infinity)` is silent too. There is no function reading an interval's start on the closed surface. So the page's norm never fires on a case, while the compiler says nothing about it: silently dead law, and the find is recorded in STATUS. What is lost. The "resides since the disability establishment date" link is not expressed in this form: the norm only requires a permanent residence fact with some interval. If the article truly establishes that link, it awaits another form: a separate "resides since date" fact of type `Date` and a date comparison. A positive test: ```law test "иностранец с установленной инвалидностью, проживающий постоянно, — право есть" { given { context { decision_time @2026-06-01T09:00:00+05:00; knowledge_time @2026-06-01T09:00:00+05:00; legal_time @2026-06-01; timezone "Asia/Almaty"; } assert disability_established(entity_ref("urn:tutorial:ivanova"), entity_ref("urn:tutorial:group2"), @2024-01-01) { id "assert-disability"; origin case_input; } assert permanently_resident(entity_ref("urn:tutorial:ivanova"), KZ, [@2024-01-01, infinity)) { id "assert-resident"; origin case_input; } assert foreign_citizen(entity_ref("urn:tutorial:ivanova")) { id "assert-foreign"; origin case_input; } } evaluate truth(entitled(entity_ref("urn:tutorial:ivanova"), DisabilityBenefit)); expect truth_status == TRUE_ONLY; expect evaluation_status == COMPUTED; } ``` The test name reads: "A permanently residing foreigner with established disability is entitled." The second test is the same person without the residence fact: `NEITHER` in the same file. What changed in CLIR. The same norm, two anchors: ```text $ lawc lower 09-real-article-source.law.md # строковый ключ …#DisabilityBenefitEntitlement/alt/1 | anchors: ['KZ-SOCIAL-CODE-224-VII-ART-175'] $ lawc lower 39-exercise-real-article-source.law.md # идентификатор …#DisabilityBenefitEntitlement/alt/1 | anchors: ['urn:law:tutorial:kz:social#SOCIAL_CODE_ART175_TEACHING'] ``` The comments read "string key" and "identifier". The second anchor is a node address in the same package: by it the depth measure finds the article, and the sources tool the text. The first is just a string. One more boundary: the compiler silently accepts a nonexistent identifier in `@source`, and CLIR receives an address with nothing at it. This also shows what the norm lowered into: three alternatives `/alt/1`, `/alt/2`, `/alt/3`, one per `or` branch in the condition. This matters for tests: the `applied(DisabilityBenefitEntitlement)` observation will not find such a rule in the program, because three rules stand under this name in CLIR. So this task's tests are limited to the answer status. ## Check Both tests are in the ready-made test file, executed on the page's program. The first of them fails on the page's norm, and that is how the find was obtained. What is **not** checked: the identifier's existence in the anchor. The compiler accepts `@source(НЕТ_ТАКОГО)` ("NO_SUCH_THING") without diagnostics, and CLIR receives an address with nothing at it. This is verified when pinning corpus sources, not by the package check, and is named here as a boundary, not hidden. What the exercise teaches. The teaching excerpt is marked `unofficial`, and the edition `ABSTRACT_ONLY`: the package holds no bytes of the real article, and the hash reconciles against the excerpt, not the statute. An identifier anchor does not make the excerpt law, but it makes the norm-to-text link addressable. And the main point: a green `check` does not mean the norm can fire. A positive test for every norm is not a formality but the only way to learn it is alive.