Pinning source text
Pinning binds the article-level text stored in a package to the exact bytes of the publication it was taken from. The binding is mechanical: a small declaration file lists which publication bytes become which fragments, and a command regenerates the fragment block from those bytes. When the bytes and the fragments disagree, the check fails instead of guessing.
Environment: the pinning loop requires a source checkout (I) —
./law gen exists only in the checkout composition; run it from the
repository root. The compiler checks of pinned text are available in
the public release (S). Marks
follow the topic legend.
What pinning guarantees, exactly
Section titled “What pinning guarantees, exactly”Each row below is one mechanical promise plus the line it stops at. Nothing here judges whether the pinned text is the right law — that judgment stays human.
| Guarantee | What holds | Exact limit |
|---|---|---|
| Document hash | the bytes on disk must match the declared document hash when read back; anything else fails with LDC-E5204 | covers only bytes pinned locally; a matching hash says nothing about whether the file is the right, current, or authentic document |
| Fragment hash | a fragment’s text must match its own declared digest (LDC-E5201), and every official text on a pinned edition must carry one (LDC-E5205) | binds text to digest only — the right digest on the wrong article still passes |
| Containment | every official fragment text must occur byte-for-byte inside the pinned publication bytes (LDC-E5202) | substring only: stale surroundings, missing articles, and swallowed headings around the quote are invisible to this check |
| Retrieve-freshness | per-act retrieve scripts fetch the portal bytes again, and their read-only check mode reports local bytes that no longer match | compares local bytes with whatever the portal serves today; says nothing about legal validity, and the scripts are internal tooling, not a user command |
| Content review | cut entries record in plain words why document furniture was excluded, and the bytes stay a substring either way | no automated check: a wrong article, a wrong edition, or a cut that drops normative words all pass — only human review catches them |
When the bytes change, these checks fail loudly instead of guessing; the limits in the table are the places a loud failure cannot reach.
The pinning loop
Section titled “The pinning loop”One command owns the loop. It requires a source checkout (I):
./law gen is absent from the public composition, so it needs the
checkout launcher (see Before you start):
$ ./law --help...law gen pinning (<package> | --all <root>) [--write | --check | --diff | --json | --emit] pinning.toml → §194 fragment block between markers in the package .law; without flags — check, writing — only --writeThe declaration file is pinning.toml. It names a source text, a
target source file, an edition, an article prefix, and the marker
comments between which the generated fragment block lives. Nothing is
written unless --write is passed: running the command with no flags,
or with --check, only verifies that the generated block matches what
the bytes would produce. --diff previews the sync result for a human,
--json and --emit serve automation.
A real check against package id.halal passes silently with exit
status 0, while --diff confirms what was compared:
$ ./law gen pinning corpus/laws/id/halal --check$ echo $?0$ ./law gen pinning corpus/laws/id/halal --diff ✓ pinning.toml → 01-sources.law [id] (68 articles)A package without a pinning.toml also exits 0: there is nothing to
compare, so the check is vacuous rather than failed.
What the declaration file says
Section titled “What the declaration file says”The shape is data, not code: source bytes in, fragment block out.
This is the head of the real declaration used by id.halal, with its
author comments trimmed:
source = "sources/uu-33-2014/id.txt"target = "01-sources.law"edition = "UUJPH_ID"prefix = "UUJPH_ART"profile = "id-uu-pasal"kind = "article"stops = ["bab", "bagian"]lang = "id"status = "official"
begin = "// BEGIN GENERATED UU JPH FRAGMENTS"end = "// END GENERATED UU JPH FRAGMENTS"The cut entries below the head (one per article that needs it) record
where non-normative document furniture — promulgation formulas, dates,
signatures, gazette lines — is cut away so that a locator keeps
addressing the norm and not the colophon. Each cut carries a reason in
plain words; the bytes stay a substring of the publication either way.
The fragment text rule
Section titled “The fragment text rule”The compiler enforces one plain rule: every fragment’s text must appear verbatim inside its publication’s bytes, and the publication bytes must match their declared document hash. Four diagnostics enforce the rule. They are available in the public release (S) and are all raised when a package is checked:
- fragment text whose digest differs from its declared content hash
(
LDC-E5201); - a fragment with official text but no content hash on an edition that
declares pinned bytes (
LDC-E5205); - fragment text that is not a substring of the publication bytes
(
LDC-E5202); - publication bytes that cannot be read back — the file is missing, the
path escapes the package, or the bytes differ from the declared
document hash (
LDC-E5204).
Note the split the numbers hide: LDC-E5201 fires on a wrong hash,
while LDC-E5205 fires on a missing hash where a pinned edition
requires one.
Retrieving the bytes
Section titled “Retrieving the bytes”Fetching a publication from an official portal and syncing fragments
into packages is handled by per-act retrieve and sync scripts
(I). Each script supports a read-only --check mode, and the full
profile wires several hundred of those --check invocations, one per
act, so that stale bytes surface without any script ever writing
during a check run.
One retrieve path deserves a callout (T): the Kazakh official legal portal now renders act pages as a single-page application, so fetching the page address returns only the application shell. The sanctioned path pins Kazakh acts through the portal’s JSON data API instead of the page markup.
The full-profile pinning check
Section titled “The full-profile pinning check”Beyond the per-package command, the full continuous-integration profile runs a pinning check per act (G) that promises four things:
- every fragment block has its declaration counterpart and back — no orphan blocks, no orphan declarations;
- the materialization record of a pinned act points at a publication node with bytes present locally;
- text coverage is measured only against pinned bytes, never against prose claims about the source;
- a watch for glued headings catches fragments whose boundaries swallowed neighboring titles.
A companion report mode prints the same findings with an always-zero exit status for dashboards; the enforcing mode fails the run.
Reproduction details
Section titled “Reproduction details”Toolchain, hashes, and full transcripts
This page uses two executors. The public block below is the lab’s
pinned tool, shown for reference; every fenced command on this
page ran on the checkout block, because gen exists only in the
checkout composition:
$ law version # public route: law-v0.1.1, macOS arm64law 0.1.1semantics: law.core/0.2std for language 0.2: 0.2.0lawql: lawql/1 (queryResult 0.1)binary hash: sha256:cfa7c17232f2dc594e665dbbf2ad3c154675797ef4be07ef7d758c9abfb80a28$ ./law version # checkout route: commit b2e9e746b9, debug build via cargo runlaw 0.1.1semantics: law.core/0.2std for language 0.2: 0.2.0lawql: lawql/1 (queryResult 0.1)binary hash: sha256:7fddf8d081e7fd527c36cc0393aea6cbf9e00ea814e960a76ac701f74794c01fAll ./law fences below were recorded 2026-10-04 against that
checkout block from the repository root.
(Compiler warnings on stderr are omitted from every transcript on this page; only stdout is shown unless a diagnostic is the point.)
Further reading
Section titled “Further reading”Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.