docs← Back to article

Markdown for LLMs

Return the case and create a new duty

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

Download this articlePlain text ↗
# Return the case and create a new duty

## Intent

I want, after a return to consideration, to open a new instance of a duty.

## Wrong form and why it stays silent

```text title="Incorrect form"
state Decided terminal; // затем transition Return from Decided
```

A state with a lawful reverse transition is not terminal. A repeated entered_state carries a different event and creates a second Report position, keeping the first.

## Correct form

```law
language "law.core" version "0.2";
package recipes.k.r03 version "0.1.0";
namespace "urn:recipe:k-procedures:03";

entity Application;
event Tick { }
relation report(app: Application);
procedure Appeal(app: Application) {
    state Draft initial;
    state Review;
    state Decided;
    state Closed terminal;
    transition Submit { from Draft; to Review; on Tick; }
    transition Decide { from Review; to Decided; on Tick; }
    transition Return { from Decided; to Review; on Tick; }
    transition Close { from Decided; to Closed; on Tick; }
}
rule Reporting strict { for app: Application; for e: Tick;
    when procedure_instance(app);
    then duty Report { bearer app; activation entered_state(app,Review,e);
        achieve report(app) during [e.time.start, @2026-09-20T09:00:00Z]; };
}
```

## Frozen execution scene

P and Q in the table are different instances; E1/E2/E3 are carriers with an explicitly given time.
All identifiers and instants are pinned in the scenes.

| Events and facts | Question | Answer |
|---|---|---|
| initial state | `positions()` | `not positions_present();` / `COMPUTED` |
| first entry | `positions()` | `position_count(Report, ACTIVE, 1);` / `COMPUTED` |
| return to consideration | `positions()` | `position_count(Report, ACTIVE, 2);` / `COMPUTED` |
| in consideration again | `truth(current_state(P,Review))` | `truth_status == TRUE_ONLY;` / `COMPUTED` |
| first entry remains | `truth(entered_state(P,Review,Tick { id: "urn:recipe:k:N:E1", time: @2026-09-02T09:00:00Z }))` | `truth_status == TRUE_ONLY;` / `COMPUTED` |
| after the shared bound | `positions()` | `position_count(Report, UNDETERMINED, 2);` / `COMPUTED` |

```law
test "initial state holds no positions" {
    given {
        context {
            legal_time @2026-09-13T09:00:00Z;
            decision_time @2026-09-13T09:00:00Z;
            knowledge_time @2026-09-13T09:00:00Z;
            timezone "UTC";
        }
        assert procedure_instance(entity_ref("urn:recipe:k-procedures:03:p"));
    }
    evaluate positions();
    expect not positions_present();
    expect evaluation_status == COMPUTED;

}
```

```law
test "first entry activates duty" {
    given {
        context {
            legal_time @2026-09-13T09:00:00Z;
            decision_time @2026-09-13T09:00:00Z;
            knowledge_time @2026-09-13T09:00:00Z;
            timezone "UTC";
        }
        assert procedure_instance(entity_ref("urn:recipe:k-procedures:03:p"));assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Submit, Tick { id: "urn:recipe:k-procedures:03:E1", time: @2026-09-02T09:00:00Z });
    }
    evaluate positions();
    expect position_count(Report, ACTIVE, 1);
    expect evaluation_status == COMPUTED;

}
```

```law
test "return opens second duty" {
    given {
        context {
            legal_time @2026-09-13T09:00:00Z;
            decision_time @2026-09-13T09:00:00Z;
            knowledge_time @2026-09-13T09:00:00Z;
            timezone "UTC";
        }
        assert procedure_instance(entity_ref("urn:recipe:k-procedures:03:p"));assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Submit, Tick { id: "urn:recipe:k-procedures:03:E1", time: @2026-09-02T09:00:00Z });assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Decide, Tick { id: "urn:recipe:k-procedures:03:E2", time: @2026-09-03T09:00:00Z });assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Return, Tick { id: "urn:recipe:k-procedures:03:E3", time: @2026-09-05T09:00:00Z });
    }
    evaluate positions();
    expect position_count(Report, ACTIVE, 2);
    expect evaluation_status == COMPUTED;

}
```

```law
test "review state holds after return" {
    given {
        context {
            legal_time @2026-09-13T09:00:00Z;
            decision_time @2026-09-13T09:00:00Z;
            knowledge_time @2026-09-13T09:00:00Z;
            timezone "UTC";
        }
        assert procedure_instance(entity_ref("urn:recipe:k-procedures:03:p"));assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Submit, Tick { id: "urn:recipe:k-procedures:03:E1", time: @2026-09-02T09:00:00Z });assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Decide, Tick { id: "urn:recipe:k-procedures:03:E2", time: @2026-09-03T09:00:00Z });assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Return, Tick { id: "urn:recipe:k-procedures:03:E3", time: @2026-09-05T09:00:00Z });
    }
    evaluate truth(current_state(entity_ref("urn:recipe:k-procedures:03:p"),Review));
    expect truth_status == TRUE_ONLY;
    expect evaluation_status == COMPUTED;

}
```

```law
test "first entry event preserved" {
    given {
        context {
            legal_time @2026-09-13T09:00:00Z;
            decision_time @2026-09-13T09:00:00Z;
            knowledge_time @2026-09-13T09:00:00Z;
            timezone "UTC";
        }
        assert procedure_instance(entity_ref("urn:recipe:k-procedures:03:p"));assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Submit, Tick { id: "urn:recipe:k-procedures:03:E1", time: @2026-09-02T09:00:00Z });assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Decide, Tick { id: "urn:recipe:k-procedures:03:E2", time: @2026-09-03T09:00:00Z });assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Return, Tick { id: "urn:recipe:k-procedures:03:E3", time: @2026-09-05T09:00:00Z });
    }
    evaluate truth(entered_state(entity_ref("urn:recipe:k-procedures:03:p"),Review,Tick { id: "urn:recipe:k-procedures:03:E1", time: @2026-09-02T09:00:00Z }));
    expect truth_status == TRUE_ONLY;
    expect evaluation_status == COMPUTED;

}
```

```law
test "closed common window leaves undetermined" {
    given {
        context {
            legal_time @2026-09-21T09:00:00Z;
            decision_time @2026-09-21T09:00:00Z;
            knowledge_time @2026-09-21T09:00:00Z;
            timezone "UTC";
        }
        assert procedure_instance(entity_ref("urn:recipe:k-procedures:03:p"));assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Submit, Tick { id: "urn:recipe:k-procedures:03:E1", time: @2026-09-02T09:00:00Z });assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Decide, Tick { id: "urn:recipe:k-procedures:03:E2", time: @2026-09-03T09:00:00Z });assert attempted_transition(entity_ref("urn:recipe:k-procedures:03:p"), Return, Tick { id: "urn:recipe:k-procedures:03:E3", time: @2026-09-05T09:00:00Z });
    }
    evaluate positions();
    expect position_count(Report, UNDETERMINED, 2);
    expect evaluation_status == COMPUTED;

}
```

```python
>>> import runpy
>>> check = runpy.run_path("docs/recipes/k-procedures/resources/check.py")
>>> check["check_positions"](https://github.com/arxohq/law/blob/master/docs/recipes/k-procedures/3)
'К3: две позиции с разными activationEvent; первая сохраняется; lawc = lawref'
```

## Counterfactual

Mutation check — LDC-E1313.

Original fragment:

```text
state Decided;
```

Replacement:

```text
state Decided terminal;
```

Scenes with a condition removed are marked separately; the same inputs get a different outcome.

## Boundary

The example isolates the start of the window: the rule gives both positions a shared end instant of 20 September; a repeated entry does not extend it. A term of “N days from each entry” needs a separate expression of the term. Carrier Tick carries no extra entity_ref fields; the known bound of reading them is described in [Duty from entering a state](/recipes/a-positions/event-activation/).

Position statuses are read on the decision date: the scene past the shared boundary names a decision moment past it, otherwise both positions would stay active.