Markdown for LLMs
Compose facts from two cases
The source Markdown for this article. Copy it into your assistant or download it as a text file.
# Compose facts from two cases
## Intention
I want to join selected facts from two cases while keeping their origin.
Composing facts is separate from importing norms.
## Incorrect form and why it stays silent
You cannot overlay a different payload with the same id on top of an HR record.
```text title="Incorrect form"
assert not eligible(entity_ref("urn:recipe:n-package:07:p")) {
id "assert-eligible-record"; origin case_input;
}
```
When a positive record with the same full StableId is attached, composition fails with LDC-E1360.
## Correct form
The composition stand in `resources/07-compose/` contains a manifest, a lock, and two exported snapshots. They are generated by `resources/generate.py`; no outside bytes are borrowed. Program, snapshot declarations, and case:
```law
language "law.core" version "0.2";
package recipes.n.r07 version "0.1.0";
namespace "urn:recipe:n-package:07";
entity Person;
relation eligible(p: Person);
relation verified(p: Person);
relation granted(p: Person);
rule Grant strict { for p: Person; when eligible(p) and verified(p); then granted(p); }
snapshot HR "snapshots/hr.json";
snapshot Audit "snapshots/audit.json";
case Combined {
context {
legal_time @2026-09-13;
decision_time @2026-09-13T09:00:00+05:00;
knowledge_time @2026-09-13T09:00:00+05:00;
timezone "Asia/Almaty";
}
use HR { record "urn:recipe:n-package:07#assert-eligible-record"; }
use Audit { record "urn:recipe:n-package:07#assert-verified-record"; }
}
```
## Frozen execution scene
| Facts | Question | Answer |
|---|---|---|
| eligible from HR, verified from Audit | granted(p) | TRUE_ONLY |
First both evaluators compose one case; then the test runner asks both. The table is not replaced by hand-rewritten asserts.
```law
test "composed case yields both premises" {
given {
context {
legal_time @2026-09-13;
decision_time @2026-09-13T09:00:00+05:00;
knowledge_time @2026-09-13T09:00:00+05:00;
timezone "Asia/Almaty";
}
}
evaluate truth(granted(entity_ref("urn:recipe:n-package:07:p")));
expect truth_status == TRUE_ONLY;
expect applied(Grant);
}
```
## Counterfactual
`teaches` adds a negative payload for an existing id in Combined and runs lower-case inside a copy of the pinned package. The expected result is exactly LDC-E1360, not an error about a missing snapshot.
## Boundary
Importing a program does not carry facts. A snapshot supplies only exported records; origin is preserved. Equal ids with equal payloads fold; when payloads differ there is no “last record wins” rule.
## Pitfall
Two payloads of one `StableId` are rejected with LDC-E1360. The scenario below reduces the example to two facts and one conflicting record, keeping both sides of the composition.