Skip to content

Adopt legaldown-validator 0.4.0's public API; remove validator_bridge.py - #3

Merged
dvejsada merged 4 commits into
mainfrom
claude/legaldown-validator-0.4.0
Oct 3, 2026
Merged

dvejsada merged 4 commits into
mainfrom
claude/legaldown-validator-0.4.0

Conversation

@dvejsada

@dvejsada dvejsada commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

The renderer now uses only legaldown-validator 0.4.0's public, semver-covered API, so validator_bridge.py and its private imports are gone. Rendered output is unchanged.

Merge only after legaldown-validator 0.4.0 is on PyPI. The dependency is now legaldown-validator>=0.4.0,<0.5, so the jobs that install from PyPI fail until that release is published. The "Against legaldown-validator main" job should pass straight away.

Changes

Was Now
legaldown.parser.quote_content, MAX_QUOTE_DEPTH, and render's own _without_drafting_marker / DRAFTING_MARKER / past-depth branch legaldown.syntax.quote_blocks / drafting_note_blocks (ForLegalAI/legaldown-validator#88, #93)
legaldown.markdown fence helpers and build.py _code_block legaldown.syntax.code_content (#93)
legaldown.cli._read_answers legaldown.load_answers, with the CLI keeping the same messages
parse_document / validate_document parse / validate
assemble(source, answers) parse_template(source).form(answers).assemble()
result.sections, placed_markers, is_template, *_lookup result.index.*
legaldown.validator constants and conditions; top-level slugify_identifier legaldown.grammar
top-level lex, Directive, find_definition_anchors, is_drafting_note, list_items, render_block legaldown.syntax
resolver _VALUE_TYPES / _DECISION_TYPES grammar.VALID_PLACEHOLDER_TYPES / DECISION_QUESTION_TYPES
  • Deprecation guard: pytest now turns any legaldown DeprecationWarning into an error, so a call that 0.5.0 will remove cannot slip in.
  • Docs: architecture, roadmap, CONFORMANCE (now "legaldown-validator 0.4"), and short notes in ADR 0002 and ADR 0007 saying the bridge is gone.

Behaviour

  • Unit, golden and conformance tests: 192 unit tests pass (2 new) and 197 spec conformance tests pass. The goldens are unchanged, and ruff is clean.
  • Output comparison: I rendered 1438 outputs before (with validator 0.3.0) and after, and they are byte-identical, diagnostics included. They cover every spec example and fixture plus the test documents, in 3 styles × HTML/text, in final mode, and through the CLI with --answers.
  • One edge-case difference: a quote nested past the validator's quote depth (17+ levels) that holds only an HTML comment used to render an empty <p class="ld-p"></p>. It now renders nothing, as at every shallower depth. A new test pins this.

Left as is, on purpose

These are places where the 0.4.0 answer is not exactly what the renderer needs, so the renderer keeps its own logic.

  • The placeholder survey vs result.index.blanks: the renderer needs one decision per occurrence, and Blank.consistent has a different scope.
  • _choose vs grammar.choose_problem: for a choice question with malformed choices, choose_problem passes the directive, but the renderer must still show it as invalid.
  • Answers are not coerced with Template.coerce: the renderer still reports answer-invalid for inputs like 5000 EUR instead of reshaping them. Coercing would be a behaviour change, so it is left for a separate decision.
  • Directive lines: the renderer's own diagnostics still have no line number, because 0.4.0 gives the line of a block or list item but not of a directive inside one.

Release

PUBLISHING.md says a new validator minor version needs a renderer release. The renderer's version is not bumped here; bump it when cutting that release.

🤖 Generated with Claude Code

https://claude.ai/code/session_013WmBAc5T7UCKVdpUmg9qxz


Generated by Claude Code

claude added 2 commits October 3, 2026 07:04
- Depend on legaldown-validator>=0.4.0,<0.5.
- parse_document/validate_document -> parse/validate; assemble() ->
  parse_template(source).form(answers).assemble().
- ValidationResult fields -> result.index (sections, placed_markers,
  is_template, *_lookup).
- Quote content from legaldown.syntax.quote_blocks, a drafting note's from
  drafting_note_blocks (replaces _without_drafting_marker and the
  past-depth branch), code blocks from code_content (replaces _code_block),
  the answers file from legaldown.load_answers (replaces cli._read_answers).
- Lexer, directives and definition helpers from legaldown.syntax; grammar
  constants, value checks and conditions from legaldown.grammar, including
  VALID_PLACEHOLDER_TYPES and DECISION_QUESTION_TYPES for the resolver's
  own copies.
- validator_bridge.py is deleted: nothing beyond the public API is used.
- Tests fail on a legaldown DeprecationWarning (pytest filterwarnings).
- Docs: architecture, roadmap U2/U3, CONFORMANCE, notes on ADR 0002 and 0007.

Output is byte-identical (golden tests, and every specification example
and fixture under each built-in style), except that a quote nested past the
validator's quote depth that holds only a comment no longer renders an
empty <p>, as at every shallower depth.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013WmBAc5T7UCKVdpUmg9qxz
…ator-main job

The job installed the renderer first, which resolves
legaldown-validator>=0.4.0,<0.5 from PyPI, and only then swapped in the
validator from main. Before a validator release is on PyPI that first
step fails, which is exactly when this job is meant to tell us
something. Installing the validator from main first satisfies the
range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013WmBAc5T7UCKVdpUmg9qxz

dvejsada commented Oct 3, 2026

Copy link
Copy Markdown
Contributor Author

CI status on this PR:

  • Tests (Python 3.11/3.12/3.13) and "Specification examples and fixtures" are failing. They fail while installing, before any test runs: Could not find a version that satisfies the requirement legaldown-validator<0.5,>=0.4.0. This PR requires 0.4.0, which is not on PyPI yet. These jobs go green once legaldown-validator 0.4.0 is published (its release commit, ForLegalAI/legaldown-validator@d8b611d, passes CI). There is nothing to fix in this PR for them.
  • "Against legaldown-validator main" failed for a reason that was this PR's. The job installed the renderer from PyPI before swapping in the validator from main, so the new version range could not be met. 54596c3 installs the validator from main first. In a fresh environment set up the same way, that gives legaldown-validator 0.4.0 and 192 passing tests.

Generated by Claude Code

claude added 2 commits October 3, 2026 08:17
- pyproject.toml: filterwarnings is error::legaldown.LegaldownDeprecationWarning,
  the one category every validator deprecation now uses, in place of the
  message regex. Checked: parse_document, validate_document,
  serialize_document, assemble, template_questions and import_definitions=
  each fail a test under it.
- architecture.md: the filter as it now is; the renderer's diagnostics lack
  a line because they are about a directive within a block (a block's line
  is public since 0.4.0, Document.line_of); labels.py has six languages.
- CONFORMANCE.md: validator 0.4 is the current dependency; the released
  legaldown-render 0.2.0 is built on 0.3.0.
- PUBLISHING.md: release after the validator's minor release is on PyPI;
  the tests fail on its deprecations.
- concepts.md: validator diagnostics carry a line (since 0.3.0).
- ADR 0002, 0007: date the 0.4.0 notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013WmBAc5T7UCKVdpUmg9qxz
Install the renderer first and force-reinstall the validator from main
last, so the validator-main job keeps testing main once its version
leaves the renderer's range (pip would otherwise replace it with the
PyPI release). legaldown-validator 0.4.0 is on PyPI, so the range
installs on its own again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q3fBapGwQ2J2vLzpDyjB5t

dvejsada commented Oct 3, 2026

Copy link
Copy Markdown
Contributor Author

Review: adoption of legaldown-validator 0.4.0

The PR moves the renderer onto validator 0.4.0's public API correctly, and rendered output is unchanged apart from the one edge case already described. I found one CI problem and fixed it in 90fccc0. The rest are small comments.

What was checked

  • CI on this head, with 0.4.0 from PyPI (0.4.0 is published now, so the earlier red runs are out of date):
    • ruff is clean.
    • pytest: 192 passed and 1 skipped (the spec corpus) on Python 3.11, 3.12 and 3.13.
    • Conformance: 197 passed.
    • The job against validator main passes.
  • Public API only: every legaldown import is in the __all__ of legaldown, legaldown.syntax or legaldown.grammar, which the validator README says are semver-covered. There are no private names, no internal modules and no 0.4.0-deprecated calls. Nothing refers to validator_bridge except the dated notes in the ADRs and the roadmap.
  • Deprecation guard: LegaldownDeprecationWarning is exported at the top level of legaldown. All 8 warnings.warn calls in 0.4.0 use it. A test calling parse_document fails under the new filterwarnings.
  • Old and new calls behave the same. Each was checked against the 0.3.0 and 0.4.0 sources and by running both:
    • VALID_PLACEHOLDER_TYPES and DECISION_QUESTION_TYPES hold the same values as the old tuples. They are frozensets, so the new isinstance(declared_type, str) guard is needed: checking an unhashable value against a frozenset raises a TypeError.
    • load_answers gives the same CLI messages and exit codes. A BOM is now accepted, and a very deeply nested YAML file now gives a clean error where it used to raise a traceback.
    • parse_template(...).form(...).assemble() returns the same AssemblyResult as assemble().
    • code_content gives the same result as the old _code_block on 30k random fence and indent inputs.
  • Quote depth: passing depth=self.depth before the increment is what the depth parameter of quote_blocks and drafting_note_blocks means: how many list items and quotes enclose the block. The validator counts list items and quotes together, as the builder does, so there is no off-by-one.
  • Rendered output, base (main + 0.3.0) against this PR (0.4.0): about 38k comparisons.
    • Inputs: the spec corpus, every document the test suite renders, sweeps nesting quotes and lists to depths 1–74, code fences, drafting notes, templates with good and bad answers, and the CLI's error paths.
    • Each comparison covers 3 styles, HTML and text, draft and final, strict, the API and the CLI.
    • The only difference is the documented one: an empty <p class="ld-p"></p> no longer appears.

Fixed in 90fccc0

The validator-main CI job would quietly stop testing main. It installed validator main first and the renderer second. That works only while main's version is inside >=0.4.0,<0.5. Once main becomes 0.5.0.dev, pip replaces it with 0.4.x from PyPI. The job would then pass against the released validator just when 0.5 starts removing the deprecated names. Now that 0.4.0 is on PyPI, the commit puts the original order back: the editable install first, then pip install --force-reinstall --no-deps from main. It also updates the matching sentence in PUBLISHING.md. Checked: ruff is clean, pytest has 192 passed and 1 skipped, and after the CI steps pip freeze shows the validator installed from git main.

Nits (no change needed to merge)

  • PR description: the empty-paragraph difference is triggered at 17+ levels of quotes and list items combined, not quotes alone. For example, 10 list levels around 6 quotes holding a comment-only drafting note also trigger it.
  • cli.py comment "Read as legaldown-validator reads an answers set": the validator's own CLI also runs Template.coerce, so 5000 EUR is accepted there and refused here (answer-invalid). The description already says this is deliberate. The comment could say the same.
  • ADR 0007 lines 32–34 still name ValidationResult.placed_markers / is_template, and ADR 0002 line 27 still names legaldown.directives. The dated notes below them correct this, so it reads fine as history.
  • Version: __version__ is still 0.2.0 while the package now needs validator 0.4. Bump it to 0.3.0 when cutting the release, as the description says.

Possible follow-ups using 0.4.0 features

  • result.index.blanks (Blank.type / .consistent) could replace part of the placeholder survey.
  • Document.line_of could give the renderer's own diagnostics block-level lines.

Generated by Claude Code

@dvejsada
dvejsada merged commit 4057c1a into main Oct 3, 2026
6 checks passed
dvejsada added a commit that referenced this pull request Oct 3, 2026
Bump the version to 0.3.0 for the release built on legaldown-validator 0.4.0's public API (#3), and name it in CONFORMANCE.md and the roadmap. The planned DOCX and PDF milestones move to v0.4 and v0.5 (ADR 0004 gets a dated note). The two HTML goldens carry the generator version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q3fBapGwQ2J2vLzpDyjB5t
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants