diff --git a/CHANGELOG.md b/CHANGELOG.md index 69cfd6f..87bfaa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,67 @@ without a major version bump until v1.0. --- -## [Unreleased] — 2026-06-16 +## [Unreleased] -### Definitions overhaul (BREAKING) +### Frontmatter: locale/currency cleanup and template placeholders — 2026-06-17 + +Tightens the document-metadata model so the schema and the rendering rules agree, and adds a +reuse-first way to author templates and drafts. No new structural complexity — these changes +*remove* dangling references and *reuse* the existing `{{placeholder:}}` mechanism. + +#### Changed + +- **No document-level locale or default currency.** The rendering rules previously told renderers to + read "the document's locale" and "a default currency from the document metadata" (§10.2–§10.5), + but the frontmatter schema defined neither field. Formatting (date order, separators, currency + symbol) is **presentation**, so it is now explicitly a render-time setting — the **active locale** + from the render template or renderer configuration (§10.1). Currency stays per `{{money:}}` + directive; an omitted `currency` emits a validation warning and MAY fall back to a render-template + default, but there is **no document-level default currency**. + +- **`identification_number` is a cross-type reserved field.** Clarified (§3.4) that + `identification_number` is the reserved field name for a registration/national identifier on **any** + party — RECOMMENDED for `legal_entity`, OPTIONAL for `natural_person` (not every individual has + one). Prefer it over a custom field so tooling can locate the identifier consistently. Documentation + clarification, not a schema change. + +#### Added + +- **Placeholders in frontmatter (spec §3.10).** Template and draft documents MAY use the existing + `{{placeholder:}}` directive (§10.7) as a **quoted** string value in frontmatter, reusing its ids, + types, and rendering unchanged: + + ```yaml + legal_name: "{{placeholder: client-legal-name}}" + effective_date: "{{placeholder: effective-date, type=date}}" + ``` + + - Allowed in **value** fields (`title`, `legal_name`, `address`, `identification_number`, + `effective_date`, `governing_law`, …); **not** in identifier or structural fields (any `name`, + `type`, `document_type`, `sides`/`parties` structure). + - Must be a quoted YAML string (an unquoted `{{` is invalid YAML). + - A required field holding a placeholder counts as present — the document is treated as a + template/draft with unfilled blanks; a placeholder id shared with the body is the same blank. + +#### Validation changes + +| Rule | Before | After | +|---|---|---| +| `{{placeholder:}}` in a frontmatter identifier/structural field | — | **Added (Error)** | +| `{{money:}}` omitted `currency` looks up a *document* default | (implied) | **Removed** — no document default; warning only | + +#### Files touched + +- [`spec/legaldown-spec.md`](spec/legaldown-spec.md) — §3.4 (identifier note), new §3.10 + (frontmatter placeholders), §10.1 (active-locale note), §10.2–§10.5 (locale wording), §10.3 + (currency clause), §10.7 (cross-reference), §13.7 (locale listed among style-template settings), + §15.5 (validation row). +- [`llm/legaldown-spec-llm.md`](llm/legaldown-spec-llm.md) — Sides and Parties notes, Placeholder + section, validation summary. + +--- + +### Definitions overhaul (BREAKING) — 2026-06-16 This revision reworks how defined terms are declared (spec §7). The goal was to support the way lawyers actually define terms — including **inline, at first use** — while making the schema diff --git a/llm/legaldown-spec-llm.md b/llm/legaldown-spec-llm.md index a12ce01..020a79d 100644 --- a/llm/legaldown-spec-llm.md +++ b/llm/legaldown-spec-llm.md @@ -81,6 +81,8 @@ tags: [tag1, tag2] # OPTIONAL - Party `type` is explicit: `legal_entity` or `natural_person` - Unknown party fields are allowed and must be ignored by implementations - Display fallback: side `label` → title-cased/pluralized `name`; party `label` → `legal_name` +- `identification_number` is the reserved field for a registration/national ID — RECOMMENDED for `legal_entity`, OPTIONAL for `natural_person` (not every individual has one); prefer it over a custom field when present +- Template/draft frontmatter MAY use `{{placeholder:}}` as a **quoted** string in value fields (e.g. `legal_name: "{{placeholder: client-name}}"`), but NOT in identifier/structural fields (any `name`, `type`, `document_type`, `sides`/`parties` structure); same id in frontmatter and body means the same blank ### Amendments @@ -256,7 +258,7 @@ Value must be valid ISO 8601 (`YYYY-MM-DD`). Optional `note` provides an automat {{placeholder: fee, type=money, currency=EUR, note=Base monthly fee}} ``` -- Pure inline directive; no frontmatter declaration needed +- No separate declaration needed; appears in document text, and MAY also appear as a quoted string value in frontmatter value fields (not identifier/structural fields) for templates and drafts - `type`: optional, defaults to `text` - Supported types: `text` | `date` | `money` - Same placeholder id used multiple times means the same logical blank @@ -315,6 +317,7 @@ Separate files per language with identical heading structure and section identif - `field_types` keys that are malformed or collide with built-in directive names - Missing or malformed `type` on `{{field:}}` - Invalid `{{placeholder:}}` identifiers or inconsistent placeholder types across repeated uses +- `{{placeholder:}}` in a frontmatter identifier or structural field (any `name`, `type`, `document_type`, `sides`/`parties` structure) - Mismatched bilingual structure - `amends.title` is empty or missing when `amends` is present - `amends.file` path does not exist when specified diff --git a/spec/legaldown-spec.md b/spec/legaldown-spec.md index edf1f82..e15b2ec 100644 --- a/spec/legaldown-spec.md +++ b/spec/legaldown-spec.md @@ -240,6 +240,8 @@ Each party object describes an individual or organization that appears in the do |---|---|---| | `date_of_birth` | RECOMMENDED | Date of birth in ISO 8601 format | +A `natural_person` MAY also include `identification_number` (OPTIONAL) when the individual has a registration or national identification number (national ID, birth number, passport, etc.). `identification_number` is the reserved field name for this value across **all** party types — prefer it over a custom field so tooling can locate the identifier consistently. It is never required for a natural person, since not every individual has such a number. + Additional custom fields MAY be included on any party object. Implementations MUST ignore unknown party fields rather than failing. This allows organizations to include jurisdiction-specific information, tax identifiers, or any other relevant party metadata. ### 3.5 Representatives @@ -375,6 +377,32 @@ attachments: --- ``` +### 3.10 Placeholders in Frontmatter + +Frontmatter value fields MAY use the `{{placeholder:}}` directive (§10.7) to mark unfilled values in template and draft documents. This reuses the placeholder mechanism unchanged — same identifiers, types, and rendering — rather than introducing a separate "draft" concept. + +```yaml +sides: + - name: clients # identifier — stays concrete + parties: + - name: client # identifier — stays concrete + type: legal_entity # structural — stays concrete + legal_name: "{{placeholder: client-legal-name}}" + identification_number: "{{placeholder: client-id}}" + address: "{{placeholder: client-address}}" +effective_date: "{{placeholder: effective-date, type=date}}" +``` + +**Rules:** + +- A placeholder in frontmatter MUST be written as a quoted YAML string, because an unquoted `{{` begins a YAML flow mapping and is not valid YAML +- Placeholders MAY appear in **value** fields (for example `title`, `legal_name`, `address`, `identification_number`, `effective_date`, `governing_law`) +- Placeholders MUST NOT appear in **identifier** or **structural** fields — any side or party `name` (these must satisfy the identifier format; a party `name` is additionally referenced by `{{party:}}`), party `type`, `document_type`, or the `sides`/`parties` array structure +- Type-specific placeholders follow §10.7 (for example `"{{placeholder: effective-date, type=date}}"`) +- A required field whose value is a placeholder satisfies that field's presence requirement; the document is treated as a template or draft with unfilled values +- A placeholder id used in both frontmatter and body refers to the same logical blank (§10.7) +- Renderers render frontmatter placeholders as a visible blank, consistent with §13.5 (for example `[_____]`, or `[TBD: id]` when no visual blank is available) + --- ## 4. Document Structure @@ -791,6 +819,8 @@ Standard Markdown tables do not support merged cells or complex formatting. For Field specs are typed inline directives that represent structured values — including dates, monetary amounts, pass-through custom values, and fillable placeholders — within the document text. They enable renderers to format values consistently according to locale and template settings, and validators to verify that values are well-formed. +The **active locale** used for formatting (date order, decimal and grouping separators, etc.) is a render-time setting — part of the style template or renderer configuration (style templates list the locale among their settings, §13.7) — not a frontmatter field. LegalDown documents do not declare a formatting locale. Renderers MAY use the document `language` as a hint. The underlying value (ISO date, numeric amount) is stored canonically, so only its display varies by locale. + All field specs MAY include an optional `note` parameter to provide a plain-text explanation of the value for automation or machine-processing purposes. The `note` value MUST NOT affect rendered output, MUST NOT contain commas or closing braces (`}}`), and MUST be preserved in structured output formats when present. ### 10.2 Date Directive @@ -816,7 +846,7 @@ Provider shall deliver the final report no later than {{date: 2027-03-31, note=F - The date value MUST be in ISO 8601 format (`YYYY-MM-DD`) - The date MUST be a valid calendar date (e.g., `2026-02-30` is invalid) -- Renderers MUST format the date according to the document's locale or render template settings (e.g., "June 1, 2026", "1 June 2026", "2026-06-01") +- Renderers MUST format the date according to the active locale or render template settings (e.g., "June 1, 2026", "1 June 2026", "2026-06-01") - The raw ISO 8601 value and `note` (if present) MUST be preserved in structured output formats for machine processing ### 10.3 Money Directive @@ -847,8 +877,8 @@ The monthly fee is {{money: 500, currency=EUR, note=Base monthly service fee}}. - The amount MUST be a numeric value (integer or decimal, using period `.` as the decimal separator) - The amount MUST NOT include grouping separators, currency symbols, or whitespace - The optional `currency` parameter specifies the currency using an ISO 4217 three-letter code (e.g., `USD`, `EUR`, `CZK`, `GBP`) -- If `currency` is omitted, the renderer SHOULD use a default currency from the document metadata or render template, or emit a validation warning -- Renderers MUST format the amount according to the document's locale or render template settings (e.g., "$10,000.00", "USD 10,000.00", "€500.00") +- If `currency` is omitted, the renderer MAY apply a default currency configured in the render template or renderer configuration; if none is configured, it MUST emit a validation warning. LegalDown defines no document-level default currency — currency is specified per `{{money:}}` directive +- Renderers MUST format the amount according to the active locale or render template settings (e.g., "$10,000.00", "USD 10,000.00", "€500.00") - The raw numeric value, currency code, and `note` (if present) MUST be preserved in structured output formats for machine processing ### 10.4 Party Directive @@ -880,7 +910,7 @@ Notices under this Agreement shall be delivered to {{party: beta-industries}}. - The directive MUST resolve against a party `name` in the frontmatter `sides[].parties[]` arrays - The optional `label` parameter specifies display text for rendering; if omitted, the renderer MUST use the party's `label` and fall back to `legal_name` - The `label` value is plain text — it MUST NOT contain commas or closing braces (`}}`) -- Renderers MUST format the resolved party reference according to the document's locale or render template settings +- Renderers MUST format the resolved party reference according to the active locale or render template settings - The raw `party-name` value, `label` (if present), and `note` (if present) MUST be preserved in structured output formats for machine processing ### 10.5 Duration Directive @@ -910,7 +940,7 @@ The service level response time shall not exceed {{duration: 4, unit=H, note=Cri - The `value` MUST be a positive numeric value (integer or decimal, using period `.` as the decimal separator); zero and negative values are not allowed - The `unit` parameter is REQUIRED and MUST be one of: `S`, `M`, `H`, `D`, `MO`, `Y` -- Renderers MUST format the duration according to the document's locale or render template settings (e.g., "12 months", "30 days", "4 hours", "1 year") +- Renderers MUST format the duration according to the active locale or render template settings (e.g., "12 months", "30 days", "4 hours", "1 year") - The raw numeric value, unit code, and `note` (if present) MUST be preserved in structured output formats for machine processing ### 10.6 Custom Field Directive @@ -958,7 +988,7 @@ Invoice {{field: INV-2026-0042, type=invoice-id}} remains unpaid. ### 10.7 Placeholder Directive -The `{{placeholder:}}` directive represents a fillable inline blank. Placeholders are declared directly where they are used in document text and MUST NOT require any frontmatter declaration. +The `{{placeholder:}}` directive represents a fillable inline blank. Placeholders are declared directly where they are used and MUST NOT require any separate frontmatter declaration. They appear in document text and MAY also appear as quoted string values in frontmatter (see §3.10). **Syntax:** @@ -1270,6 +1300,7 @@ Renderers SHOULD support external style templates specifying: - Table formatting - Paragraph spacing and indentation - Cover page format +- Locale for value formatting (date order, number and decimal separators, currency display) Templates SHOULD be defined in a separate configuration file (e.g., YAML or JSON) completely independent of document content. The same LegalDown source SHOULD render correctly with any compatible template. @@ -1408,6 +1439,7 @@ Validators MUST categorize issues at three levels: | `{{placeholder:}}` `type` parameter, when present, is one of `text`, `date`, or `money` | Error | | Repeated `{{placeholder:}}` occurrences with the same `placeholder-id` use the same effective `type` | Error | | `{{placeholder:}}` `currency` parameter for `type=money` is a recognized ISO 4217 code | Warning | +| `{{placeholder:}}` in frontmatter appears in an identifier or structural field (any `name`, `type`, `document_type`, `sides`/`parties` structure) | Error | | Field spec `note` parameter is plain text and does not contain commas or closing braces | Error | ### 15.6 Document Metadata Validation