docs← Back to article

Markdown for LLMs

Recurring duty

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# 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.