Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
163 commits
Select commit Hold shift + click to select a range
1e50a2a
CLI and API robustness (S1, S2, S3, S4, S5, S6, S10 CLI side)
dvejsada Oct 27, 2026
6a65d83
Values: exact long amounts, faithful durations, no raw unit ids, spac…
dvejsada Oct 27, 2026
e5196f8
Build fidelity: comment-only items and quotes, emphasis next to direc…
dvejsada Oct 27, 2026
ef85675
render_file(): a non-UTF-8 file raises DocumentError (S4, API side)
dvejsada Oct 27, 2026
5dd564b
Money keeps every written fraction digit (R2 follow-up)
dvejsada Oct 27, 2026
b876dde
Merge WP2: CLI and API robustness (S1-S6, S10 CLI side)
dvejsada Oct 27, 2026
f36ac33
Merge WP1: values formatting (R1-R4)
dvejsada Oct 27, 2026
9034670
Terms that refer to themselves render instead of crashing (B8 follow-up)
dvejsada Oct 27, 2026
64be9df
B2 guard: an item a marker belongs to never vanishes
dvejsada Oct 27, 2026
c83f6ce
Merge WP4: build fidelity (B2, B3, B4, B8) and self-referencing terms
dvejsada Oct 27, 2026
14b6977
Style validation: blank fallback, extends cycles, flat dumps, overrid…
dvejsada Oct 27, 2026
e035a29
Style templates: an empty labels.condition keeps its render-time fall…
dvejsada Oct 27, 2026
a627090
Merge WP6: style validation (R6, S7-S11)
dvejsada Oct 27, 2026
493c924
Links and images: relative image paths only, deny-list for links, emp…
dvejsada Oct 27, 2026
750cba4
Empty image path shows its alt text; deny-list comments say it is the…
dvejsada Oct 27, 2026
4ccb6e3
Merge WP3: links and images (B6, W3, B9/W8)
dvejsada Oct 27, 2026
680beeb
Text writer fidelity: attachment separators, tables, quotes, list ite…
dvejsada Oct 27, 2026
8579abd
{{term:}} resolves the term as the definition does: a {{ref:}} or pla…
dvejsada Oct 27, 2026
2f0cceb
Preamble labels and print page breaks (R5, W2)
dvejsada Oct 27, 2026
761f90c
Merge WP7: preamble item labels (R5), attachment page breaks (W2)
dvejsada Oct 27, 2026
f9a42bb
A fraction of more than 4300 digits renders: plural category falls ba…
dvejsada Oct 27, 2026
61adf8c
Text writer: attachment separator mirrors the HTML layout; blank sign…
dvejsada Oct 27, 2026
6080014
Merge WP5: plain-text writer fidelity (W1, W4-W7)
dvejsada Oct 27, 2026
3c92e56
-o: only the extension of a format the renderer does not write is a u…
dvejsada Oct 27, 2026
73a845c
CLI: only the program reconfigures the streams; output is UTF-8 with …
dvejsada Oct 27, 2026
b33de5f
Merge wave-1 review fixes: term text with refs, plural limit, -o exte…
dvejsada Oct 27, 2026
5074286
Docs and labels: neutral party-id labels, packaging, documented limit…
dvejsada Oct 27, 2026
d648934
Merge WP8: docs, labels and packaging (S13, S14, S15, documented beha…
dvejsada Oct 27, 2026
f5ad89f
Links: allow-list of schemes, refused link reported, diagnostics esca…
dvejsada Oct 27, 2026
b19901d
Style: validate templates only where a setting is used (review wave 2)
dvejsada Oct 27, 2026
4e11aba
Placeholders: a blank of whitespace or format characters is no visual…
dvejsada Oct 27, 2026
12879c5
Labels: neutral identifier labels, since identification_number covers…
dvejsada Oct 27, 2026
cc4d7b7
Docs: link allow-list, render-link-refused, escaped diagnostics, styl…
dvejsada Oct 27, 2026
278b64e
Merge wave-2 review fixes: link allow-list with render-link-refused, …
dvejsada Oct 27, 2026
6652ab6
Wave 3 review fixes: plural of huge fractions, text list items, -o ex…
dvejsada Oct 27, 2026
a89a0b1
Term texts: memoize per term in every pass, so branching chains are l…
dvejsada Oct 27, 2026
fdbca3d
Cap a term text at 1,000 characters, render-term-too-long (review wav…
dvejsada Oct 27, 2026
faaf47f
Merge wave-3 review fixes: plural fallback, text list items, -o exten…
dvejsada Oct 27, 2026
bceecee
Final review fixes: term budget and depth limit, exact cache reuse, p…
dvejsada Oct 27, 2026
2e48f47
Merge final-review fixes: term budget and depth limit, exact cache re…
dvejsada Oct 27, 2026
2091550
Term budget charges only repeat work; CLI escapes every echoed comman…
dvejsada Oct 27, 2026
1fe197b
Merge term work budget on repeat computations, escaped CLI echoes
dvejsada Oct 27, 2026
1336bbb
Reorganise the tests by topic
dvejsada Oct 27, 2026
e47f98f
Bound the term-work tests by counted work, not wall-clock time
dvejsada Oct 27, 2026
a98cf24
List every test module in the architecture notes
dvejsada Oct 27, 2026
3f08186
Test that first computations of acyclic terms are free of the work bu…
dvejsada Oct 27, 2026
0f86400
Merge test reorganisation by topic and deterministic work bounds
dvejsada Oct 27, 2026
49c3fc4
Check files out with LF line endings
dvejsada Oct 27, 2026
f71ba39
Make the tests independent of the platform's default encoding and lin…
dvejsada Oct 27, 2026
c3f4ff5
Test that plain-text table cells with pipes and backslashes read back…
dvejsada Oct 27, 2026
f234f1f
Run the tests on Windows and gate publishing on CI
dvejsada Oct 27, 2026
87a345b
Merge CI hardening: Windows tests, LF checkouts, publishing gated on CI
dvejsada Oct 27, 2026
3085536
Read the command's standard error in the console encoding in the esca…
dvejsada Oct 27, 2026
1efc63a
Record the source line of every block, list item and heading in the r…
dvejsada Oct 27, 2026
e4bbc66
Name the file and line of every diagnostic the renderer reports
dvejsada Oct 27, 2026
63683b8
Read the lines of a document once instead of checking its shape for e…
dvejsada Oct 27, 2026
753541e
Merge line numbers and file names on the renderer's diagnostics
dvejsada Oct 27, 2026
15e4bd0
Check every file reference against the document root (§2.3)
dvejsada Oct 27, 2026
8523081
Run the spec's file-reference fixtures with their document root
dvejsada Oct 27, 2026
c09041c
Document the file-reference checks and the document root
dvejsada Oct 27, 2026
2940159
Merge file reference checks and the document root (§2.3)
dvejsada Oct 27, 2026
29edc2e
Designate sections under the none scheme by their heading as rendered…
dvejsada Oct 27, 2026
6074e22
Merge branch 'claude/tender-curie-iv97m6' into g4-none
dvejsada Oct 27, 2026
e743323
Describe designations under the none scheme in the docs, and test tha…
dvejsada Oct 27, 2026
a3bc4be
Name the file on the assembly's diagnostics
dvejsada Oct 27, 2026
739d0a7
Merge none-scheme designations from the rendered heading (§13.3)
dvejsada Oct 27, 2026
1fdceb4
Report a party's findings at the field they are in
dvejsada Oct 27, 2026
9eed084
Keep a repeated finding at its lowest line, list the renderer's in li…
dvejsada Oct 27, 2026
be49fcf
Drop the directory from RenderOptions.filename
dvejsada Oct 27, 2026
9d5a157
Refuse control characters in a file reference, read ... as .. for the…
dvejsada Oct 27, 2026
eeb6622
Refuse style values that could leave the stylesheet, and add an untru…
dvejsada Oct 27, 2026
2981e9c
Document the untrusted mode and the style values that are always refused
dvejsada Oct 27, 2026
cbb804a
Merge claude/tender-curie-iv97m6 into g2-style
dvejsada Oct 27, 2026
656f62a
Merge claude/tender-curie-iv97m6 into g3-fixes
dvejsada Oct 27, 2026
c05cf67
Ignore a newline at the end of a file reference
dvejsada Oct 27, 2026
7ed4cbe
Merge diagnostic line and file-reference refinements
dvejsada Oct 27, 2026
05f815c
Bound the nesting depth of a style, so reading one costs time linear …
dvejsada Oct 27, 2026
e462bb1
Merge style hardening and the untrusted mode
dvejsada Oct 27, 2026
8b69281
Report a heading read from a term it uses, count term nesting from th…
dvejsada Oct 27, 2026
cfc3f0c
Merge none-scheme designation follow-ups
dvejsada Oct 27, 2026
1dee684
Close the gaps found reviewing the untrusted mode
dvejsada Oct 28, 2026
a8a6329
Merge style loading follow-ups for untrusted styles
dvejsada Oct 28, 2026
598160c
Update the roadmap for 0.4.0: v0.3 released, hardening release, DOCX …
dvejsada Oct 28, 2026
1726d5c
Bump GitHub Actions to Node 24 majors
dvejsada Oct 28, 2026
427874d
Note the DOCX and PDF milestone renumbering in ADR 0004
dvejsada Oct 28, 2026
2370585
Merge roadmap update for the 0.4.0 hardening release
dvejsada Oct 28, 2026
9ed53e5
Merge GitHub Actions bump to Node 24 versions
dvejsada Oct 28, 2026
df51ee2
Run CI on Python 3.13 only
dvejsada Oct 28, 2026
d80b01c
Merge CI on Python 3.13 only
dvejsada Oct 28, 2026
fd7a7c5
Merge the merged PR branch into main's squash, so the branch moves fo…
dvejsada Oct 28, 2026
7180bed
Raise dependency minimums to the tested releases
dvejsada Oct 28, 2026
84c6fb2
Release 0.4.0
dvejsada Oct 28, 2026
d57b5f7
Merge release 0.4.0 preparation
dvejsada Oct 28, 2026
62d7a69
Merge main (0.4.0 release)
claude Oct 28, 2026
f4cb18a
Expose the numbering structure in the render tree
dvejsada Oct 28, 2026
4455b12
Document the numbering structure of the render tree
dvejsada Oct 28, 2026
92b4b63
Record the DOCX decisions (ADR 0008)
dvejsada Oct 28, 2026
c0c0c4c
Add page.header, page.footer and docx.* style settings
dvejsada Oct 28, 2026
d7b5735
Add the DOCX writer's OOXML package core
dvejsada Oct 28, 2026
0b9f73a
Verify DOCX against the OOXML schemas and LibreOffice
dvejsada Oct 28, 2026
db466d3
Pin and document the numbering structure's edge cases
dvejsada Oct 28, 2026
8c58a34
Merge the numbering structure of the render tree
dvejsada Oct 28, 2026
a9af1f8
Merge branch 'claude/tender-curie-iv97m6' into docx-core
dvejsada Oct 28, 2026
dcd7095
Bound the lengths and colours the DOCX settings accept
dvejsada Oct 28, 2026
fe47efa
Take {version} and {date} from the tree, and warn that the DOCX body …
dvejsada Oct 28, 2026
4460f5c
Harden the DOCX package after review
dvejsada Oct 28, 2026
c1c42da
Fix five small DOCX and style issues: cache v6, CR escaping, tail ref…
dvejsada Oct 28, 2026
ed96a4e
Merge the DOCX package core
dvejsada Oct 28, 2026
a7fe71f
Plan the numbering Word will draw for a resolved tree
dvejsada Oct 28, 2026
a2edc77
Test the DOCX numbering plan against the resolver, and describe the p…
dvejsada Oct 28, 2026
f4804aa
Add the DOCX plan data model
dvejsada Oct 28, 2026
9cbe181
Write the DOCX body from a plan
dvejsada Oct 28, 2026
567c785
Document the DOCX body writer
dvejsada Oct 28, 2026
00d7e74
Merge branch 'claude/tender-curie-iv97m6' into docx-plan
dvejsada Oct 28, 2026
e0fd796
Share the numbering formats a style gives between the resolver and th…
dvejsada Oct 28, 2026
3f7a089
Make the DOCX numbering plan place every unit as the resolver numbere…
dvejsada Oct 28, 2026
6732876
Check the DOCX numbering plan unit by unit
dvejsada Oct 28, 2026
fa122e6
Drop a stale comment from the DOCX plan module
dvejsada Oct 28, 2026
df4175e
Harden the DOCX body writer after review
dvejsada Oct 28, 2026
b5d8b39
Merge the DOCX body writer
dvejsada Oct 28, 2026
a40bd00
Merge the DOCX numbering planner
dvejsada Oct 28, 2026
da8647d
Name the section each contents entry lists
dvejsada Oct 28, 2026
82d5182
Plan the cross-references, bookmarks and contents of a DOCX
dvejsada Oct 28, 2026
2d87b3b
Write DOCX from the planner's plan
dvejsada Oct 28, 2026
5b6b70e
Check the DOCX numbers and references against LibreOffice
dvejsada Oct 28, 2026
3345033
Document the DOCX cross-references, bookmarks and diagnostics
dvejsada Oct 28, 2026
2fff745
Keep a reference that has no cover as text, and keep fields out of th…
dvejsada Oct 28, 2026
edd16d3
Round-trip body paragraphs and edits made in LibreOffice
dvejsada Oct 28, 2026
f4a0e34
Document fixed references, point bookmarks and the reference cycle
dvejsada Oct 28, 2026
046ba2e
Merge the DOCX cross-references, bookmarks and table-of-contents plan
dvejsada Oct 28, 2026
bcc09bc
Write the front and back matter of a DOCX
dvejsada Oct 28, 2026
1ae4e80
Document the DOCX front and back matter and the manual Word checklist
dvejsada Oct 28, 2026
056f8ff
Plan qualified labels, alternatives and resynchronised numbers for DOCX
dvejsada Oct 28, 2026
3611768
Round-trip alternatives, qualified items and edits; find cycles by co…
dvejsada Oct 28, 2026
60ffb0b
Keep attachments without a usable id in the DOCX contents, and define…
dvejsada Oct 28, 2026
59ab77d
Make the Word checklist platform neutral and cover the Word-only sett…
dvejsada Oct 28, 2026
59da613
Take an alternative's holder from the counter, and test fixed references
dvejsada Oct 28, 2026
3bc296b
Merge the DOCX title block, contents, attachments and signatures
dvejsada Oct 28, 2026
6ca33d4
Document the DOCX planner's qualified labels, alternatives and resync…
dvejsada Oct 28, 2026
6c2fbaf
Merge the DOCX front and back matter
dvejsada Oct 28, 2026
c008261
Review fixes: alternative information, precise restart messages, inde…
dvejsada Oct 28, 2026
84fbb4f
Pin the holder, the count check and the explicit num of a restarted h…
dvejsada Oct 28, 2026
9bf408a
Merge the DOCX numbering hard cases: qualified labels, alternatives, …
dvejsada Oct 28, 2026
9e3b6dd
Cover the whole reference text with fields, so a field may stand for …
dvejsada Oct 28, 2026
1186474
Keep path labels of nested lists live: reserved heading levels with t…
dvejsada Oct 28, 2026
6e7c748
Go on past Word's nine list levels in further abstractNums instead of…
dvejsada Oct 28, 2026
28fed31
Add docx.reference_text_switch: what a cross-reference may expect of …
dvejsada Oct 28, 2026
d86479f
Write the number of a skipped heading level as text so the rest of a …
dvejsada Oct 28, 2026
ae5917a
Say why a reference stays fixed text, and document the live-reference…
dvejsada Oct 28, 2026
bcaa4fd
Review follow-ups: skipped-level reasons, bullets past nine levels, p…
dvejsada Oct 28, 2026
c318661
Report where LibreOffice counts a level nothing numbered before a dee…
dvejsada Oct 28, 2026
dace64d
Merge live cross-references wherever Word can express them
dvejsada Oct 28, 2026
72f8f40
Make the attachment-id and page-count tests mean what they say
dvejsada Oct 28, 2026
78f709a
Add the DOCX acceptance corpus
dvejsada Oct 28, 2026
8877dcc
Word checklist: the level nothing numbered, viewers, links, look; che…
dvejsada Oct 28, 2026
21c551c
Document the DOCX writer as it is: README, conformance rules, archite…
dvejsada Oct 28, 2026
51a37b3
Read the LibreOffice tests' text from the document model, not the tex…
dvejsada Oct 28, 2026
8a0e6b6
Merge reading the LibreOffice tests' text from the document model
dvejsada Oct 28, 2026
b10c0a6
Merge branch 'claude/tender-curie-iv97m6' into docx-final
dvejsada Oct 28, 2026
ca5343e
Acceptance tests and docs follow the model-based LibreOffice text
dvejsada Oct 28, 2026
ee70c24
Acceptance: edited documents must read exactly as the text writer pri…
dvejsada Oct 28, 2026
39c989e
Release steps for the Word check; docs: concepts, plan_docx signature…
dvejsada Oct 28, 2026
061a12f
Merge the DOCX acceptance tests and documentation pass
dvejsada Oct 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 178 additions & 2 deletions .github/PUBLISHING.md

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,54 @@ jobs:
env:
LEGALDOWN_SPEC_DIR: .legaldown-spec

docx:
# The DOCX writer is checked against the ISO/IEC 29500 schemas (fetched, not stored: tests/schemas/README.md)
# and against LibreOffice, which opens each document, updates its fields and says what it shows
# (tests/lo/uno_export.py runs under the system Python, which python3-uno provides, not the virtual
# environment's). A missing tool fails the job instead of skipping the tests.
name: DOCX (schemas and LibreOffice)
runs-on: ubuntu-latest
env:
LEGALDOWN_REQUIRE_DOCX_TOOLS: "1"
steps:
- uses: actions/checkout@v7
- name: Check out the LegalDown specification (its documents are validated too)
uses: actions/checkout@v7
with:
repository: ForLegalAI/LegalDown
ref: ${{ env.LEGALDOWN_SPEC_REF }}
path: .legaldown-spec
- uses: actions/setup-python@v7
with:
python-version: "3.13"
cache: pip
- run: |
sudo apt-get update
sudo apt-get install -y libreoffice-writer python3-uno
- name: Show the versions of the system and of LibreOffice
run: |
lsb_release -ds || cat /etc/os-release
soffice --version
- run: pip install -e ".[dev]"
- name: Cache the OOXML schemas
id: schemas
uses: actions/cache@v6
with:
path: tests/schemas/ooxml
key: ooxml-schemas-${{ hashFiles('tests/schemas/fetch.py') }}
- if: steps.schemas.outputs.cache-hit != 'true'
run: python tests/schemas/fetch.py
- run: pytest -q -m ooxml_schema
env:
LEGALDOWN_SPEC_DIR: .legaldown-spec
# The acceptance corpus (tests/test_docx_acceptance.py) is part of both runs; it needs the specification's documents
- run: pytest -q -m libreoffice
env:
LEGALDOWN_SPEC_DIR: .legaldown-spec
- run: pytest -q -m "acceptance and not libreoffice and not ooxml_schema"
env:
LEGALDOWN_SPEC_DIR: .legaldown-spec

validator-main:
# Surfaces changes in legaldown-validator's model before they are released
# (docs/decisions/0001). Informational: a failure here is a heads-up.
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ build/
dist/
.pytest_cache/
.ruff_cache/

# OOXML schemas fetched for the DOCX tests (tests/schemas/README.md)
tests/schemas/ooxml/

# The documents made for the manual Word checks (.github/PUBLISHING.md)
word-check/
72 changes: 70 additions & 2 deletions CONFORMANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ lists the Core rules it covers.

It is checked against the specification's own examples and fixtures corpus (`tests/conformance/`):

- every document renders to HTML and to text
- every document renders to HTML, to text and to DOCX
- every internal link resolves to an anchor that exists
- each invalid fixture renders its rule's failure marker

Expand All @@ -20,6 +20,7 @@ It is checked against the specification's own examples and fixtures corpus (`tes
| `{{include:}}` below Full (§17.5) | ✅ Renders `[NOT PROCESSED: include path]` with a Warning (`render-not-processed`); the path is checked as a file reference (§2.3) |
| Party and side display rules (§3.6) | ✅ |
| At least one output format (§13.6) | ✅ HTML (recommended) and plain text (optional) |
| DOCX output (§13.6, recommended) | ⚠️ Written by `-o x.docx` / `format="docx"` (0.5): numbers, cross-references, the table of contents and page numbers are Word features, not text. Checked against the ISO/IEC 29500 schemas and in LibreOffice in CI; **not yet checked in Word itself**, which is a manual step before the release. See "DOCX output", below. HTML is the format this renderer claims §13.6 with |
| A heading in a list item or a quote | ✅ Shown as a bold line: it is not a section (§4.1), so it has no number or anchor |
| Comment stripping (§8.6) | ✅ Inline comments, and comment blocks across any number of lines. As in CommonMark, a comment block left unclosed runs to the end of the document |
| Templates with answers (§15.8) | ✅ Assembled first with `legaldown-validator`'s Assembly capability (§15.7), then rendered: `answers=` / `--answers answers.yaml`. A template that needs other files is refused (see below) |
Expand Down Expand Up @@ -47,6 +48,73 @@ It is checked against the specification's own examples and fixtures corpus (`tes
| Question prompts next to blanks (§15.8, MAY) | ✅ `placeholders.show_prompt` |
| Final check (§15.9, SHOULD) | ✅ `--final` / `final=True`: the validator's `placeholder-unfilled` and `template-construct-present` Errors; with `--strict`, the document is refused |

## DOCX output (§13.6)

[ADR 0008](docs/decisions/0008-docx-word-native.md) decides the design: in the `.docx` every number, cross-reference,
table of contents entry and page number is a Word numbering definition or field, never literal text, and the values the
renderer computed are only the cached results of the fields. The document therefore reads right before any field is
updated, and stays right when a lawyer inserts a clause and updates fields.

**What is written**, in the order the HTML shows it:

- The title block (header rows and parties, borderless tables), a live table of contents (`TOC \o "1-N" \h \z \u` with cached
entries equal to the HTML contents, each a link with a `PAGEREF` page number that Word fills in when it updates the
field), the sections, the attachments (a heading and a titled placeholder, separated by a page break or a rule per
`attachments.separator`), and the signature blocks (§3.6, borderless tables with signing lines, kept together on one page as
far as one page allows).
- Headings, list items and numbered paragraphs take their numbers from Word numbering definitions: the heading styles are
linked to a multilevel list; lists restart by structure where Word can; the continental `5.1` items and the numbered
paragraphs ride the heading list's next level, with the lists nested in them on its reserved levels; a list nested past
Word's nine levels goes on in further lists, up to 36 levels.
- Every `{{ref:}}` is the delimiters of its designation and `REF` fields on bookmarks, with the values the renderer computed as the cached results (`1.1.1`,
`I.A.1.a(i)`, `1(b)(ii)`). `{{term:}}` and `{{attach:}}` are internal links; under the `none` scheme a reference is a
field for the text of the heading.
- The template view (§15.8): condition labels, drafting notes and choices are shown as in the other formats. Alternatives that
share a number are paragraphs with no number of their own whose number is a `REF` field of the first.
- Images are their alt text (no file is read, §2.3, §17.6). A link is a hyperlink for the same schemes as in HTML.
- A style setting that Word cannot express (a `%` length, a colour name Word does not know) is a style error when the
format is `docx`, before anything is rendered.

**Differences from the other formats**, each reported with a `render-docx-*` diagnostic (the renderer's own rule ids, not the
specification's) at the line of the unit or the reference, once per finding and once for references that fail alike:

| Rule | Level | Meaning |
|---|---|---|
| `render-docx-reference` | Warning | A `{{ref:}}` that Word's fields cannot compose is written as its text: right when the file is opened, but it does not follow edits. The message names the class: a number with text or punctuation around its counter that the reference does not have, where Word's `\t` switch may not be relied on to leave it out (`docx.reference_text_switch`: `off`, `documented`, `guess`); or a number holding the counters of other units that the reference writes itself (`{section}.{n}` under a ref `{n}`). Also this rule: the counter of a heading level the document skips (the Core Error `heading-skip`) is text between the fields of the units that do hold theirs, and a reference that reads differently in Word for another reason |
| `render-docx-reference-cycle` | Warning | Under the `none` scheme, a heading's title refers back to the heading: the reference is written as text |
| `render-docx-section-label` | Warning | A label shows a number that Word's list cannot show there (the section's number on a list that is not the heading list, or the counters of the enclosing items on a list that cannot carry them): Word draws a shorter label, named in the message. References stay fields |
| `render-docx-letter-overflow` | Warning | Past 26 a letter counter reads `aa`, `bb`, `cc` in Word and `aa`, `ab`, `ac` in the renderer |
| `render-docx-roman-overflow` | Warning | Word writes Roman numerals of 4000 and over differently |
| `render-docx-list-depth` | Warning | A list is nested past 36 levels: the items past it are numbered in the format of the last level and restart by fixed values |
| `render-docx-shared-counter` | Warning | A unit shares a counter with others in Word (a sub-heading and the items of its section, a list that goes on from another) and is restarted at its number: right when opened, but a fixed value that does not follow edits made before it |
| `render-docx-number-mismatch` | Warning | Any other difference between Word's number and the renderer's: a catch-all that does not occur outside documents that skip a heading level |
| `render-docx-alternative` | Info | Alternatives that share a number show it as a field of the first: deleting the first in Word breaks the others and every reference to the shared identifier. Render with the condition values or answers for a final document. Once per document |
| `render-docx-static-restart` | Info | A list restarts by a fixed setting, not by structure: nested in a list of another kind, in an item on the heading list that it cannot ride, in an alternative, or the one that begins the next list past nine levels. A parent item added in Word does not restart it |
| `render-docx-libreoffice-count` | Info | Items are numbered as the renderer does in Word but one or more higher in LibreOffice, which counts a level that nothing in the list numbered before a deeper item as 1. Nothing in the file is wrong for Word. Once per document |
| `render-docx-reference-word-only` | Info | A reference relies on Word's `\t` switch, which LibreOffice ignores: there it shows the whole number. Once per document |

Two more differences are not reported, since they follow from the format: at `contents.depth: 1` the attachment titles are
first-level entries of the contents, where the HTML indents them one level more; and the contents show a later
alternative's shared number.

**How it is checked.** In CI, on every part of every document of the corpus (the specification's examples and valid
fixtures, the test documents and documents written to stress the numbering) under the `default`, `outline` and
`continental` styles:

- every part validates against the ISO/IEC 29500-4 transitional schemas, and rendering twice gives the same bytes;
- LibreOffice opens the document, updates its fields and indexes, and what it shows is what the plain-text writer prints
(numbers, references, contents entries, attachments, signatures), except where a diagnostic above says Word draws a
number differently (`tests/test_docx_acceptance.py`);
- after a heading, a list item, a nested item and a numbered paragraph are inserted and a clause is deleted in
LibreOffice, as a lawyer does, and the fields are updated, the document reads as the plain-text writer prints the source
with the same edits (the same module; the finer cases, with the cached results made wrong on purpose, are in
`tests/test_docx_roundtrip.py`).

LibreOffice is the oracle available to CI, and it differs from Word in a few places: it ignores `\t`, `lvlRestart`,
`SEQ \s` and `w:updateFields`, and counts a level that nothing numbered before a deeper item as 1. What only Word shows
(the contents' page numbers, what `\t` does, the count of an unused level, numbering after an insertion, and every
other Word-only assumption of the plan) is a manual checklist before each release (`.github/PUBLISHING.md`).

## Known limitations

- **Assembly reads no other files.** A template with include fragments, LegalDown attachment
Expand All @@ -55,7 +123,7 @@ It is checked against the specification's own examples and fixtures corpus (`tes
- **Line numbers (§16.9).** Every diagnostic names its line, the validator's and the renderer's
own (`render-ref-ambiguous`, `ref-not-enumerated`, `render-not-processed`,
`render-link-refused`, `path-not-relative`, `path-outside-root`, `render-term-limit`, `render-term-too-long`,
`render-designation-cycle`, `render-designation-limit`, `render-locale-fallback`), and the CLI prints it as `file:line:`. The renderer's line is the
`render-designation-cycle`, `render-designation-limit`, `render-locale-fallback`, and the `render-docx-*` rules of the DOCX planner), and the CLI prints it as `file:line:`. The renderer's line is the
**first line of the block it is in**, as `Document.line_of` gives it, whatever line the
directive itself is on: a paragraph's, a table's header row, a quote's first `>`, a code
block's opening fence, a heading's (a section title); for a list item, the line of **its marker**
Expand Down
Loading
Loading