Markdown for LLMs
Recurring duty
The source Markdown for this article. Copy it into your assistant or download it as a text file.
# Recurring duty
## Intention
I want to create a separate duty for each occurrence of a finite schedule. A three-day schedule yields three instances.
## Incorrect form and why it stays silent
```text title="Incorrect form"
recurring every 1 calendar_day over [@2026-09-01, infinity) { ... }
```
The schedule must be finite; an open upper bound does not mean “show only the known part”. The lowering of a correct finite example is fixed; see the boundary.
## Correct form
```law
language "law.core" version "0.2";
package recipes.a.r09 version "0.1.0";
namespace "urn:recipe:a-positions:09";
entity Person;
relation registered(p: Person);
relation done(p: Person);
relation filed(p: Person, period: Integer);
rule R strict { for p: Person; when registered(p);
then duty Report { bearer p;
goal recurring every 1 calendar_day over [@2026-09-01, @2026-09-04) {
achievement { condition filed(p, occurrence.index); window [occurrence.start, occurrence.end); }
}
};
}
```
## Frozen execution scene
**The normative expectations below are executed by both implementations.** Lowering yields occurrence meta-terms — field terms over the occurrence reference; the previous const-ref rejection is closed, and the scenes below show the corrected outcome. The absence of arbitrary rejections is checked separately.
| Facts and snapshot | Question | Answer |
|---|---|---|
| first occurrence; 2026-09-01 | `positions()` | `position_count(Report, ACTIVE, 1); expect position_count(Report, PENDING, 2);` / `COMPUTED` |
| after the schedule; 2026-09-05 | `positions()` | `position_count(Report, UNDETERMINED, 3);` / `COMPUTED` |
| one performed occurrence; 2026-09-05 | `positions()` | `position_count(Report, SATISFIED, 1); expect position_count(Report, UNDETERMINED, 2);` / `COMPUTED` |
```law
test "first occurrence active with later pending" {
given {
context {
legal_time @2026-09-01;
decision_time @2026-09-01T09:00:00+05:00;
knowledge_time @2026-09-30T09:00:00+05:00;
timezone "Asia/Almaty";
}
assert registered(entity_ref("urn:recipe:a-positions:09:p"));
}
evaluate positions();
expect position_count(Report, ACTIVE, 1); expect position_count(Report, PENDING, 2);
expect evaluation_status == COMPUTED;
}
```
```law
test "undetermined after schedule without data" {
given {
context {
legal_time @2026-09-05;
decision_time @2026-09-05T09:00:00+05:00;
knowledge_time @2026-09-30T09:00:00+05:00;
timezone "Asia/Almaty";
}
assert registered(entity_ref("urn:recipe:a-positions:09:p"));
}
evaluate positions();
expect position_count(Report, UNDETERMINED, 3);
expect evaluation_status == COMPUTED;
}
```
```law
test "performed occurrence satisfied with rest undetermined" {
given {
context {
legal_time @2026-09-05;
decision_time @2026-09-05T09:00:00+05:00;
knowledge_time @2026-09-30T09:00:00+05:00;
timezone "Asia/Almaty";
}
assert registered(entity_ref("urn:recipe:a-positions:09:p")); assert filed(entity_ref("urn:recipe:a-positions:09:p"), 0);
}
evaluate positions();
expect position_count(Report, SATISFIED, 1); expect position_count(Report, UNDETERMINED, 2);
expect evaluation_status == COMPUTED;
}
```
```python
>>> import runpy
>>> check = runpy.run_path("docs/recipes/a-positions/resources/check.py")
>>> check["check_boundary"](https://github.com/arxohq/law/blob/master/docs/recipes/a-positions/9)
'А9: граница проверена'
```
## Counterfactual
Mutation: `over [@2026-09-01, @2026-09-04)` → `over [@2026-09-01, infinity)`; rejection LDC-E1346. Additional counterfactuals are shown as separate scenes.
## Boundary
The index starts at zero and is part of the position identity. A monthly step needs month_end; calendar_day here does not need that policy. Lowering of occurrence.start/index/end yields field terms over the occurrence reference; the previous const-ref rejection is closed, see the scenes above.