docs← Back to article

Markdown for LLMs

Constraints

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

Download this articlePlain text ↗
# Constraints

**In one sentence:** `constraint` expresses a mandatory relation between the
already established (facts, positions) but infers nothing: the `when`
antecedent true and the `require` requirement false is a
violated/conflicted/undetermined finding in the results, not a new fact
and not a sanction. The author takes it when a case’s coherence must be
checked without making the checked inferable.

The language specification treats a constraint as a check, not an
inference: when the antecedent holds and the requirement fails, the engine
writes a finding, adds no support, and imposes no sanction. Prohibitions —
norms with a holder, a window, and a lifecycle — live on the
[prohibitions page](/constructs/prohibition/).

## 1. When to use and when not to

| Instead | Selection rule |
|---|---|
| `constraint` vs `rule strict` | A rule infers the consequent as a new fact with support; a constraint adds no logical support. If `Y` must follow from `X`, write a rule; if a case with `X` but without `Y` is incoherent, a constraint. `X only_if Y` desugars exactly into a constraint, not into a rule |
| `constraint` vs `prohibition` | A prohibition is a norm with a holder, a window, and a lifecycle; a constraint is a validation finding without holder or window, computed on every evaluation. A prohibition’s violation is a position violation; a constraint’s failure is a finding without sanction: a sanction is encoded by a separate rule on established facts |
| `constraint` vs `definition … necessary` | A definition’s necessary half is also a constraint (“concept requires condition”) but with the `was_derived_from` provenance edge and a place in the theory. A one-off coherence condition is a bare constraint; a condition entering a concept is a definition |
| `require` vs a power’s `valid_when` | `valid_when` is an exercise-validity condition: without it the effect does not materialize. `require` is a coherence check without effect: without it nothing is extinguished, only a finding is written |

## 2. Minimal example

Package `research.constraint.enrolled_needs_consent`: a child’s enrolment requires a
guardian’s consent. Consent is inferred by a rule from a fact; the
constraint only checks coherence.

```law
rule ConsentFromGuardian strict {
    for c: Child;
    for g: Guardian;
    when consent(g, c);
    then has_consent(c);
}

constraint EnrolledNeedsConsent(c: Child) {
    when enrolled(c);
    require has_consent(c);
    severity error;
    message "зачисление требует согласия законного представителя";
}
```

Case 01 facts: `enrolled(ann)` + `consent(maria, ann)`. Query:
`evaluate truth(has_consent(ann))`.

Actual engine answer:

```text
law test research.constraint.enrolled_needs_consent: мир research.constraint.enrolled_needs_consent
  ok   [research.constraint.enrolled_needs_consent#authored] tests/01-consent-present.lawtest / urn:query:research-constraint-01
  ok   [research.constraint.enrolled_needs_consent#authored] tests/02-consent-missing.lawtest / urn:query:research-constraint-02
итого: 2 проверено, 2 прошли, 0 не прошли, 0 не исполнены; код 0
```

`law engine check` — `check OK`, no warnings.

Sensitivity is double. First, removing the `consent` fact changes the answer
to the same query from Established to Not established, not refuted
(the consent-missing test): the constraint did **not** infer
`has_consent` from `enrolled` — the key property (“adds no logical
support”) visible right in the run. Second, the constraint’s own verdict
follows the verdict table: antecedent Established + requirement Established
→ satisfied (case 01, no issue), antecedent Established + requirement
Not established, not refuted → undetermined with `missing_inputs` (case 02). The `law test` output shows only query statuses —
findings live in the results with a constraint result kind,
which was not printed separately in these runs.

Second package `research.constraint.certified_needs_test` — the same device in the
standards domain with `severity warning`: certified equipment must hold a
passed test record. Case 02 (record present, certificate absent) answers
Established on the record query: the constraint is untriggered without the
antecedent and stays silent — no finding. Runs — 2/2, `check OK`.

## 3. Example by domain

- **Religion (inheritance fiqh):** package `faraid.shares` (Faraid inheritance shares, Islamic law) —
  `constraint SonImpliesMaleDescendant` (see the
  [corpus forms](/constructs/constraint/corpus-forms/)): a declared son means an inheriting male-line
  descendant; inference by rule is deliberately forbidden, otherwise
  negation on `has_male_descendant` would stop working. Exemplary “check,
  don’t infer”.
- **Standard (IFRS):** package `eu.ias.provisions` (IAS 37, provisions) —
  `constraint Para14RequiresPresentObligation`: a recognised provision
  requires a present obligation; `severity error` with an expanded `message`
  from the paragraph 14 text.
- **Custom:** package `custom.warlpiri.kinship` (Warlpiri kinship, Australian customary law) —
  `constraint WrongSkinMarriageConstraint`: Warlpiri marriage
  classes as case incoherence, not as a holder-bearing prohibition.
- **Teaching cases:** package `research.constraint.enrolled_needs_consent` (guardianship,
  `severity error`), package `research.constraint.certified_needs_test` (standard, `severity
  warning`).

## 4. How the engine answers

Table — actual runs of this section’s teaching packages (query statuses):

| Facts | Question | Answer | Why |
|---|---|---|---|
| `enrolled`, `consent` | `has_consent` | Established | rule inferred; constraint satisfied, no issue |
| `enrolled` | `has_consent` | Not established, not refuted | constraint infers nothing; its verdict is undetermined |
| `certified`, `lab_passed` | `test_passed` | Established | rule inferred; constraint satisfied |
| `lab_passed` | `test_passed` | Established | rule fires without certificate; constraint untriggered and silent |

The full verdict table (antecedent Established ×
requirement Established/Refuted/Contradiction/Not established, not refuted → satisfied/
violated/conflicted/undetermined; a conflicted antecedent →
conflicted). In 0.2 a constraint evaluates on every evaluation —
after all strata and the norm runtime, before
the answer. The result is a results element with
a constraint result kind, applicable status, and a stable
runtime id; the `constraint_check`
proof node is a graph root. A violated verdict gives issue `CONSTRAINT_VIOLATED`,
conflicted gives `CONSTRAINT_CONFLICTED`; satisfied and undetermined
produce no issue. `severity critical` is written as `error` with
`details.severity = "critical"`. These details were not printed separately
in the section’s runs and are stated from the language description.

## Grounding: which substitutions are checked

Substitutions are enumerated over the positive binding literals of the
scope-and-when conjunction. Enumeration includes atoms with Contradiction status: a
contradictory antecedent is a finding (conflicted), not a reason to hide
it. A substitution whose antecedent support pair is negative-only is untriggered
— it has no result. For an undetermined verdict, the `missing_inputs` field names
the requirement literals with Not established, not refuted status.
The implicit-established wrapper
(`require age(p)` lowers to `established(age(p))`, like a body literal)
reads four-valued — otherwise Contradiction/Not established, not refuted outcomes would not exist;
other status tests (`not_known`, `supported`, `refuted`, `unknown`) stay
boolean.

A judge in requirement: the requirement can carry the
judgment channel. On an undetermined verdict with an open judge, the
result carries an evaluation status of `REQUIRES_JUDGMENT` and
`judgment_requests` with constraint addresses;
the verdict and `missing_inputs` are unchanged.

## 5. Common mistakes

1. Expecting inference from a constraint: `require Y` does not establish
   `Y` — Not established, not refuted where the author expected Established (pitfalls,
   item 1).
2. Expecting a sanction: a constraint’s failure is a finding, a violation
   is inferred from a position instance by a separate rule
   (pitfalls, item 2).
3. A constraint as a producer: the “constraint reads what it infers” cycle —
   a constraint cannot be a producer for its strata (pitfalls, item
   3).
4. Repeated `scope`/`effective`, silently skipped body elements —
   `LDC-E1329`/`LDC-E0201` (pitfalls, item 4).
5. `effective` outside the law date: the constraint silently does not apply
   (pitfalls, item 5).
6. An unexecutable body: formulas outside the executable subset — issue
   `NON_EXECUTABLE_CONSTRAINT`, the constraint is not evaluated
   (pitfalls, item 6).

## 6. References

- Neighbour pages: [prohibitions](/constructs/prohibition/),
  [definitions](/constructs/definition/), [powers](/constructs/power/).
- The pitfalls page lists the diagnostics (`LDC-E1329`, `LDC-E0201`) with
  wrong forms and fixes.