LegalDown is an open specification. Contributions are welcome — from typo fixes to new language features.
The specification is currently v0.2 DRAFT: breaking changes are still possible between draft
revisions, and are recorded in CHANGELOG.md.
| You want to… | Go to |
|---|---|
| Ask a question, float an idea, or discuss a design | Discussions |
| Report an error, ambiguity, or contradiction in the spec | Issues |
| Propose a concrete change | Discussion first, then a pull request |
Design changes start in Discussions. A pull request that changes the language itself is much more likely to land if the design was agreed first — the specification's job is to be unambiguous, and that is easier to settle in prose than in a diff.
Small corrections — typos, broken links, a validation row that contradicts its own section — can go straight to a pull request.
LegalDown has a few standing commitments. A change that conflicts with one of these needs a strong argument:
- No hardcoded numbers in source. Section numbers, list markers, and cross-reference text are generated at render time (§1.2). Anything that puts them back into the document is a regression.
- Content and presentation stay separate. How something looks belongs to the style template (§13.7), not the document.
- Determinism. Two conformant implementations must produce the same result for the same input. If a rule leaves room for interpretation, it is not finished — the identifier algorithm (§5.3) and the directive grammar (§11.2) are the reference standard for the level of precision expected.
- Minimal extensions. LegalDown extends CommonMark only where legal drafting genuinely needs it. Prefer reusing an existing mechanism over adding a new directive.
- Every rule needs a severity. A new requirement belongs in the §16 validation tables as an Error, Warning, or Info — otherwise implementations will disagree about what to do with it.
- Every rule needs a conformance level. Decide whether the check is Core, Rendering, or Full
(§17). Roughly: a check needing only the document file is Core; one needing the active style
template or rendered output is Rendering; one needing another file is Full; one needing
an answers set belongs to the Assembly capability (§17.6). Where a rule sits in a §16 table
whose level differs, §17.2 carves it out by name — as it does for the style-template-dependent §16.3
row and the
supersedes.fileexistence row.
A specification change usually touches more than the specification. Before opening a PR:
-
spec/legaldown-spec.md— the normative change, including any §16 validation rows and §17 conformance placement -
llm/legaldown-spec-llm.md— the condensed reference, if the change is authoring-facing (skip for implementation-only changes, and say so in the PR) -
README.md— if the change affects the introductory material or examples -
examples/— if the change adds a feature, add or extend an example, and update the feature-coverage table inexamples/README.md - §18 ↔
examples/simple/stay byte-identical — three documents claim the specification's §18 fenced blocks and the files inexamples/simple/are the same text. If you edit either, edit both -
CHANGELOG.md— a dated entry under[Unreleased](format below) - The spec's
Revision:date — bump it whenspec/legaldown-spec.mdchanges -
fixtures/— a fixture per new or changed rule (see below); if the change touches template assembly (§15.7), add or update a byte-exact case infixtures/assembly/ - Cross-references still resolve — section numbers shift when sections are added
If you deliberately skip one of these, say why in the PR description. Reviewers check for this.
Entries follow Keep a Changelog with a few local conventions. Look at existing entries for the shape:
- A short paragraph explaining why — what was broken, ambiguous, or missing
#### Added/#### Changed/#### Removedsections as needed- A
#### Validation changestable with Rule | Before | After whenever severities move - A
#### Files touchedlist - Breaking changes get a blockquote at the top of the entry and a migration note
Every document in examples/ must be valid under the current specification — no
Errors. Warnings and Info notes may be configuration-dependent (see the notes in
examples/README.md), so "no Errors" is the bar a contributor can actually
verify. When you add a feature, add or extend an example that exercises it, and
update the feature-coverage table in examples/README.md so the claim and
the file agree.
fixtures/ is the conformance corpus: one directory per §16 rule id, holding a
document that trips that rule and the diagnostic a validator must produce. It is what lets
independent implementations verify they agree.
When you add or change a validation rule:
- Give it a rule id in the §16 table (§16.1) — stable, lowercase, never renamed or reused
- Add
fixtures/invalid/<rule-id>/with a case that trips it, and an expectation file recording rule id, level, and line — never message text, which §16.9 leaves to implementations - If the rule cannot be exercised by a document — because it depends on a style template or on the
implementation rather than the input — record it in
fixtures/coverage.jsonundernot_mechanically_testablewith a reason, rather than writing a fixture that does not test it - If the rule is checked only when assembling a template, or only under the final option (§15.9),
say so in the expectation with
requires_capability: "assembly"andrequires_config({"answers": "answers.yaml"}or{"final": true}) - Run
python fixtures/verify.py, which checks the corpus is self-consistent and that every rule id in §16 is accounted for
When you change how assembly works (§15.7), add or update a case in fixtures/assembly/ — a
template, an answers set, and the exact output a conforming assembler must produce. Assembly is
specified to be byte-identical across implementations, so these cases are compared byte for byte.
- Conformance keywords — MUST / MUST NOT / SHOULD / SHOULD NOT / MAY, per §1.5. Use them deliberately; prose that sounds normative but uses none of them will be read inconsistently.
- Say who is bound. "Renderers MUST…", "Validators SHOULD…", "Authors MAY…" — a requirement without a subject is ambiguous.
- Reference sections as
§5.3, and keep a link to the section where the reader may need it. - Match the surrounding file's line-wrapping.
spec/legaldown-spec.mdandllm/legaldown-spec-llm.mdkeep each prose paragraph on a single line, so that an edit produces a one-line diff instead of a reflow;CHANGELOG.md,CONTRIBUTING.md, and the example documents wrap at roughly 100 characters. Do not reflow a paragraph you did not otherwise change. - Examples should look like real legal documents, not
foo/bar.
The specification is licensed under CC BY 4.0. By contributing, you agree that your contribution is licensed under the same terms.
The license covers the specification document and this repository's contents. It does not cover software that implements LegalDown — parsers, validators, renderers, and editors may be released under any license their authors choose.