Skip to content

feat(regulations): parse the grammar, assign ids, merge and diff by structure - #111

Draft
lorenzocorallo wants to merge 2 commits into
feat/regulationsfrom
feat/regulations-latex
Draft

lorenzocorallo wants to merge 2 commits into
feat/regulationsfrom
feat/regulations-latex

Conversation

@lorenzocorallo

Copy link
Copy Markdown
Member

Stacked on #110. The LaTeX layer of the regulations editor, as a pure library (src/regulations/latex), against the
grammar the legal thread is publishing (legal/docs/grammar.md, shared/polinetwork-regolamento.cls):
\regolamento[id=…]{…}, the nestable capo environment, \articolo[id=…]{…}, commi/\comma[id=…],
lettere/\lettera, \rif{id}, \approvazione{direttivo|assemblea}{YYYY-MM-DD}, \rettifica[delegato]{…}.

  • Parser (parse.ts, document.ts): never throws. It builds one structure tree across \input files: an
    included file's nodes join the tree where it is included, e.g. a capo included inside a regolamento. Numbers are
    recomputed from order the way the class numbers headings: capi and articles share a counter at each level.
    Issues carry file, line, column and UTF-16 offsets (the same units as CodeMirror and Y.Text): syntax (braces,
    environments), structure (misplaced commands), ids (missing, invalid, duplicate), unknown \rif, and commands
    outside the inline subset (warning).
  • Ids (ids.ts): 6-char base36 ids, generated by the system. idEdits gives the text edits that add missing
    ids and replace invalid or duplicate ones (the later copy). The collab service applies them while people type.
  • 3-way merge (merge.ts): per structure node keyed by id. A comma is the smallest unit and keeps its lettere.
    Different nodes merge automatically. The same node changed on both sides, or changed on one side and deleted on
    the other, is a conflict, resolved with ours, theirs or custom text. Parent and order merge too, so moves and
    insertions land where they were made. A kept comma brings back its deleted parent, with a warning. Trailing
    whitespace doesn't count as a change. Merging is refused while any side doesn't parse or lacks ids.
  • Structural diff (diff.ts, plain.ts): articles are added, removed, modified, moved (another parent, or out
    of order by LIS) or renumbered. Each change has a word-level diff of the plain text: commi are numbered, lettere
    are a), and \rif is shown as its current number. Changes to regolamenti, capi and free text are listed apart.
  • Delibera (delibera.ts): sets \approvazione, or adds or replaces \rettifica in the entry preamble for
    emanation.

Tests

tests/regulations-latex.test.ts runs on a synthetic fixture: the backend repo is public and the RRI sources are
private, so the RRI isn't committed here. With REGULATIONS_LEGAL_DIR set to a clone of PoliNetworkOrg/legal,
it also checks the real RRI as converted by the legal thread:

  • it parses with no errors (5 regolamenti, 13 capi, 69 articoli, 214 commi);
  • it serializes back byte for byte;
  • two drafts that edit different commi merge cleanly, and the diff finds both articles.
REGULATIONS_LEGAL_DIR=…/legal bunx vitest run tests/regulations-latex.test.ts   # 13 passed

@coderabbitai

coderabbitai Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

…nd diff by structure

A parser for the legal repository's grammar (\regolamento, the capo
environment, \articolo, commi, lettere, \rif) that never fails: it builds the
structure tree across \input files with numbers recomputed from order, and
reports problems with positions. Missing or duplicate ids get edits that
assign new ones. A 3-way merge per structure node (a comma is the smallest
unit) merges different nodes automatically and reports the same node changed
on both sides as a conflict to resolve. A structural diff classifies articles
as added, removed, modified, moved or renumbered with word-level changes, and
the delibera macros are set for emanation.
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.

1 participant