Markdown for LLMs
A package in the corpus: manifest, scenarios, provenance, and checks
The source Markdown for this article. Copy it into your assistant or download it as a text file.
# A package in the corpus: manifest, scenarios, provenance, and checks
The archive package already does everything the corpus does: it imports
a foreign act and a computer, holds an A3 parameter, executes on a merged
world. What remains is what turns it into a **package in a tree** rather
than a set of files: a manifest with catalogue metadata, declared
scenarios, source provenance, and registration in checks. This page is
matched by the whole practicum package,
and the checks compare its forms
against that package's files.
```law
language "law.core" version "0.2";
package tutorial.archive version "0.15.0";
namespace "urn:law:tutorial:archive";
source ARCHIVE_RULES {
kind municipal_act;
jurisdiction VELIKY_USTIN;
number "2026-14";
}
edition ARCHIVE_RULES_2026_RU of ARCHIVE_RULES {
language ru;
officiality official;
adopted @2026-01-15;
in_force [@2026-02-01, infinity);
}
fragment ARCHIVE_RULES_P9 in ARCHIVE_RULES_2026_RU {
kind paragraph;
locator "paragraph/9";
text ru official """Плата за просрочку возврата исчисляется за каждый день просрочки и не может
превышать установленного потолка.
""";
}
```
The quoted fragment reads: "Overdue-return fees accrue per overdue day and may not exceed the set cap."
## Layout
The corpus layout convention is closed:
a package holds a manifest, `package.law` only for the shared, normative
modules, A3 sidecars, `sources.law`, and subdirectories from a closed
list — `tests/`, `sources/`, `deps/`, `i18n/`, `resources/calendars/`…
The linter marks an off-list directory with a remark, and the checks
reject it.
```text
packs/examples/tutorial/archive/
├── law.toml [package], [dependencies], [features], [[tests]]
├── law.lock, deps/ только генератором
├── package.law импорты, словарь, общие отношения
├── 10-tariffs.law модуль: плата за копирование
├── 20-late-fee.law модуль: плата за просрочку
├── late-fee-cap.lawparam.json A3-параметр
├── sources.law провенанс
└── tests/
├── tariffs.lawtest
└── late-fee.lawtest
```
The tree comments read: "generator only"; "imports, vocabulary, shared relations"; "module: copy fee"; "module: overdue fee"; "A3 parameter"; "provenance".
The layout leaves one fork — how to cut normative modules — and answers
it: by source units, not by construction types. For the archive these are
two rule chapters; for a real act modules follow articles and chapters,
and the module name names them.
## Manifest
```text
[package]
name = "tutorial.archive"
version = "0.15.0"
language = "0.2"
namespace = "urn:law:tutorial:archive"
[dependencies]
"tutorial.city" = "0.1.0"
"calc.tiers" = "0.1.0"
[features]
enabled = ["law.params/0.1"]
semanticLayer = "L1"
[[tests]]
family = "tutorial_archive"
suites = ["tests/tariffs.lawtest", "tests/late-fee.lawtest"]
world = ["tutorial.archive", "tutorial.city", "calc.tiers"]
```
The headers in every `.law` file must match the manifest — else
`LDC-E1109`. `[features]` switches A3 surfaces on: an unknown or
partially implemented feature is rejected by the compiler, not silently
skipped. `[[tests]]` declares the package's scenarios:
the family serves as the run and ratchet unit, `suites`
lists the files, `world` names the program — the consumer first,
then dependencies. No separate module is needed to register
scenarios: a file in `tests/` named by no suite drops the checks, as does
a suite naming a nonexistent file.
What the practicum manifest **lacks** is a `[metadata]` section. It
describes the act: title, jurisdiction, publisher, status, fidelity to
source. For a real corpus package it is mandatory and reconciled against
source declarations:
```text
[metadata]
title = "Гражданский кодекс РК (Особенная часть, 409-I): срез — конкурсные обязательства и публичное обещание вознаграждения (ст. 910—912)"
primarySource = "GK_RK_OSOBENNAYA"
jurisdiction = "KZ"
instrument = "code"
sourceFidelity = "pinned_unofficial_copy"
issuer = "Парламент Республики Казахстан"
legalStatus = "in_force"
verifiedAgainstSource = false
```
The title reads: "Civil Code of RK (Special Part, 409-I): slice — competition obligations and public reward promises (art. 910–912)"; the issuer reads "Parliament of the Republic of Kazakhstan".
`jurisdiction` and `instrument` derive from `sources.law`, and the checks
reconcile them literally; `issuer`, `legalStatus`, `verifiedAgainstSource`
derive from nowhere — the author writes them and justifies them in
a comment. A teaching package must not carry `[metadata]` for the same
reason `calc.*` lacks it: substituting a `jurisdiction` would declare the
example law. It does not enter the semantic hash — it is catalogue, not
semantics.
## Provenance
`sources.law` works as the package's "lockfile": it names the source,
the edition with its validity window, and fragments with locator and
text. Rule `@source` anchors and A3-value `anchors` point at fragments;
for a real act a fragment carries the pinned bytes' `content_hash`, and
the checks verify it twice — by address and by content, as in [the pinned
edition tutorial](/tutorials/pinned-edition/). The fictional archive has
nothing to pin, and no `materialization_status` is declared: the page
honestly says there is no source instead of faking one.
## Checks
A new file does not enter checks by itself. A corpus package is
registered across the registries list:
in the CLIR generator's lowered-acts list, a regression family and
its ratchet, scenario manifests, labels and overlays. The practicum has
one registry: it sees every `law.toml` under the practicum tree and does
with it what corpus checks do with a `calc.*` consumer:
```text
$ python3 verify/ci/gates/release/check_tutorial_practicum.py --only archive
archive (потребитель): lock/deps свежие, понижен с контекстом без пустых
предикатов, слитый мир 140 узлов, 10 тестов сходятся у lawc и lawref,
байтово идентичны 10/10
check_tutorial_practicum: OK — пакетов 1
```
The report reads: "archive (consumer): lock/deps fresh, lowered with a context without empty predicates, merged world of 140 nodes, 10 tests agree between both runners, byte-identical 10/10".
Three rules without which a package counts broken even when `check` is
green:
- **generated files are edited only by the generator** — `law.lock`,
`deps/`, CLIR; a hand edit is caught by hash reconciliation (`--regen`
is the only path);
- **a promised outcome is a scenario**, not a comment: a package without
`tests/*.lawtest` prints as unverified and drops the checks;
- **two implementations agree byte-wise**: both runners execute every
scenario, and the reference evaluation document equals the engine's
output. A discrepancy is a qualifying blocker, not a reason to fit one
side to the other.
No heavy runs are needed for one package's sake: narrowing by package
restricts the work to the act and its dependency closure.
## Next
The author track ends here: from the first rule to a checked package.
Next are tracks for other readers: how to ask law via MCP, how to
embed the engine in an application, how to verify someone else's
formalisation, and how to evolve the language itself.