Markdown for LLMs
Exercise 14. A transition period with two bounds
The source Markdown for this article. Copy it into your assistant or download it as a text file.
# Exercise 14. A transition period with two bounds
An exercise for the [time](/tutorials/time/) page. The old-card
replacement norm on the page applies indefinitely. In the archive rules
it is transitional: cards issued before 1 February 2026 are subject to
replacement during 2026, and from 2027 the transition period is closed.
**Setup.** Write the norm so that on the 1 June 2026 date of law, a card
of 10 January 2026 is subject to replacement, a card of 1 March 2026 is
not, while on the 1 March 2027 date of law the first card is not subject
to replacement either, and the norm does not apply to it.
**Hint.** The norm has two bounds of different nature: the norm's own
validity window and an issue-date condition. The first is `effective`,
the second a date comparison in the condition. They are easy to confuse,
with different answers.
Below is the solution. Try it yourself first.
## Solution
```law
language "law.core" version "0.2";
package tutorial.archive version "0.4.2";
namespace "urn:law:tutorial:archive";
entity Person;
relation reader_card_issued(p: Person, on: Date) kind empirical { key(p); }
relation card_reissue_required(p: Person) kind institutional;
const OLD_CARD_CUTOFF: Date = @2026-02-01;
```
The norm with a validity window and a cutoff date:
```law
rule TransitionalCardReissue strict {
effective [@2026-02-01, @2027-01-01);
for p: Person;
for on: Date;
when reader_card_issued(p, on) and on < OLD_CARD_CUTOFF;
then card_reissue_required(p);
}
```
The `effective` window is half-open: 1 January 2027 is already outside
it. The cutoff date is a named constant, not a number in a condition: in
the text it is the same date as the rules' commencement, and in a year
nobody will guess where it came from.
The closed-window test, expecting "the norm not applied":
```law
test "переходный период закончился — старая карточка больше не подлежит замене" {
given {
context {
decision_time @2027-03-01T09:00:00+05:00;
knowledge_time @2027-03-01T09:00:00+05:00;
legal_time @2027-03-01;
timezone "Asia/Almaty";
}
assert reader_card_issued(entity_ref("urn:tutorial:ivanova"), @2026-01-10) {
id "assert-card";
origin case_input;
}
}
evaluate truth(card_reissue_required(entity_ref("urn:tutorial:ivanova")));
expect truth_status == NEITHER;
expect evaluation_status == COMPUTED;
expect not applied(TransitionalCardReissue);
}
```
The test name reads: "The transition period ended — the old card is no longer subject to replacement."
## Check
On the 1 June 2026 date of law, three cases execute:
| Facts | Answer on `card_reissue_required(ivanova)` |
|---|---|
| card of 10 January 2026 | `TRUE_ONLY` |
| card of 1 March 2026 | `NEITHER` |
| card of 1 March 2026, without the issue-date condition | `TRUE_ONLY` |
The third row is a counterfactual: without the date comparison the norm
would swap all cards in a row. The test above executes on the 1 March
2027 date of law from `tests/44-exercise-time.lawtest`.
What the exercise teaches. A norm's window answers "when is the norm in
force", the condition's date "which facts it concerns". The first
compares against the date of law, the second against the case's date.
Moving the cutoff into `effective` would say the norm applies from
1 February, not that it concerns cards before 1 February.