| Commit message (Collapse) | Author | Age | Files | Lines |
| ... | |
| |
|
|
|
|
|
| |
Requiring HEAD to be exactly a tag made the target unusable: the commit
that adds the download link to the README necessarily comes after the tag
it links to. It now archives the most recent tag and says so when HEAD is
ahead of it.
|
| |
|
|
|
|
|
|
|
|
| |
cgit offers snapshots for every tag or for none, so colitur.git now has
cgit.snapshots=0 and 'make release-tarball' uploads the tagged archive to
a stable URL. Ten tags had meant twenty download links, nineteen of them
stale.
The target refuses to run from an untagged or dirty tree, so what is
published always matches a tag.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Robustness and hackability pass over the shipped program.
The citation parser is strict about numbers, four pairs of books no
longer share a full title, shipped styles re-parse their own output, and
overlay errors are written for the person editing the file rather than
for a compiler author.
colitur-templates(5) already refers to "before colitur 0.9" for the
month-key change, so the version moves with it.
|
| |\
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
An audit of the shipped program, plus the fixes it found.
The citation parser accepted OCaml integer-literal syntax, so a typo like
'Luke 1_1:5' silently became a different chapter. Four pairs of different
books shared a full title -- 1 and 2 Corinthians both rendered 'Epistola
ad Corinthios' -- leaving 108 citations in 2027 alone that a reader could
not resolve to a book. Spec section 8.5 is now delivered rather than
recorded: shipped styles re-parse their own output. Overlay errors no
longer name OCaml source files at the reader.
Also: the new-overlay scaffold shows citations at the right nesting
level, config --show validates before printing, error messages no longer
echo whole file lines, and a month answers to both spellings of its own
name.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
A week object carries month_name/month_num/month_abbr, because at that
level a bare `name` would be ambiguous. An author who learned those names
inside {{#weeks}} reaches for them one level up inside {{#months}} too --
where they resolved to nothing, and an unknown key renders as the empty
string by design, so the result was a silently blank month heading rather
than any error.
Found by writing a template from scratch rather than copying a shipped
one; every shipped template sidesteps it, which is why nothing caught it.
The aliases are additive, so no existing template or golden changes.
colitur-templates(5) now documents both spellings and says why they
exist.
|
| |/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Found by auditing the shipped program rather than the diff.
The parser accepted OCaml integer-literal syntax, so "Luke 1_1:5" read as
chapter ELEVEN and "+5" as 5 -- a typo silently becoming a different
chapter, reachable through any user overlay. Numbers are now plain digits
and positive, and a descending range is rejected: 1:20-10 is always a
transcription error. No shipped citation changed.
FOUR PAIRS OF DIFFERENT BOOKS SHARED A FULL TITLE. 1 and 2 Corinthians
both rendered "Epistola ad Corinthios", as did Thessalonians, Timothy and
Peter -- 108 citations in 2027 alone that a reader cannot resolve to a
book. This is the Kings defect fixed earlier and not generalised. The
titles now carry their volume numeral, marked CONSTRUCTED, and a test
asserts no two books share a name -- while allowing the case where two
ids ARE the same book under different numbering, which a tradition
relates.
Spec section 8.5 is now delivered rather than merely recorded. Shipped
styles did not re-parse their own output: 32 of 52 Latin abbreviations
and 49 of 52 full titles failed, so a citation copied from colitur's own
output into an overlay was passed through untouched and printed in the
wrong language, silently. Every shipped name is registered as a spelling
and split_book learned multi-word titles by longest-token match. Now 0
of 52 fail beyond the same-book aliases.
Overlay errors were written for a compiler author: they named an OCaml
source file the reader does not have and buried the useful token. The
existing five-path rewriter is replaced by a generic one, applied to
every load path rather than one, so "rank: is not one of the allowed
values (at Class9)" replaces the raw Of_sexp_error dump.
Also: the new-overlay scaffold documented citations and layer without
showing them, and its comment implied the wrong nesting -- the single
easiest thing to get wrong; error messages echoed whole file lines,
copying an unrelated file's contents into stderr when a flag pointed at
one; and config --show validated partway down its table, exiting 2 after
writing five rows to stdout.
|
| |
|
|
|
|
|
|
|
|
| |
Citations become configurable: parsed into structure and re-rendered, so
book names, abbreviations, punctuation style and numbering tradition are
files a user edits rather than strings frozen in the data.
New lib/citation (Book, Parse, Render, Sigla); [bible] and [sigla]
sections in language files; lang/traditions.ini; three config keys and
CLI flags. --raw emits every citation byte-for-byte as stored.
|
| |\
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Citations are parsed into structure and re-rendered, so book names,
abbreviations, punctuation style and numbering tradition become files a
user edits rather than strings frozen in the data.
New lib/citation (Book, Parse, Render, Sigla); [bible] and [sigla]
sections in language files; lang/traditions.ini for numbering; three
config keys and CLI flags. --raw emits every citation byte-for-byte as
stored, bypassing the whole pipeline, so output stays diffable against
lectio and the raw view does not depend on the parser being correct.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The branch was RED and reported green. `dune test` exited 1: test/cli.t
pinned the pre-fix output `kings_1 19:3-8`, which the previous commit had
already fixed to `1 Reg 19:3-8`. The gate command piped dune through
`tail`, so it reported tail's exit status, and cram prints its diff
BEFORE the alcotest summary, so the two lines shown were the passing
ones. Verify with `dune test; echo $?`, never through a pipe.
A style file's own `book` key was unreachable. sigla_book resolved
against a hardcoded "abbr" and the result was applied unconditionally,
so the documented `[sigla] book = full` could never win. Render gains
book_string, and the style's own value is now the default that a flag or
config overrides. The unit test pinned style_of_fields correctly while
the wiring defeated it.
`lang --check` filtered the reference set to the celebration prefix, so
a file with no [bible] section at all reported a clean bill of health --
contradicting both the reason the keys change was made and lang.ml's own
comment. It now reports missing book names too.
The token test missed a FOURTH citation-bearing file: adjustments.sexp
writes citations as `Set_citation`, not `(reference ...)`. Its 16
citations all parse, so nothing was broken, but nothing was checking.
The first attempt at this fix read the file and extracted NOTHING -- the
marker stopped before the opening quote, so every payload was the part
label -- which is recorded in the code rather than left as a trap.
Also: colitur-config(5) claimed a trailing period the data does not
carry, and two la.ini scan quotes silently corrected OCR damage
("Ionae 3, I - I O", "Epistolse") while presenting themselves as
verbatim. Both are now marked as corrections.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Three defects, all found by running the documented examples rather than
by reading code.
All seven modern-numbering targets carried their own internal id as
their Latin name (kings_1.full = kings_1), so --sigla-tradition modern
printed "kings_1 19:3-8" -- leaking a key book.mli states is never shown
to a reader. They now carry Vulgate-derived Latin names marked
CONSTRUCTED: the 1962 Missal uses Vulgate numbering throughout, so it
can contain no incipit for a book that exists only under a later
convention. In Latin the modern tradition therefore only moves Kings and
Esdras; Osee, Ionas, Ecclesiasticus and the Apocalypse keep their names
either way, since modern numbering is a vernacular convention.
The coverage test could not catch this. It compares a name against its
KEY ("kings_1.full"), and "kings_1" differs from that, so the row
passed. A second check now asserts no name IS its own id. The two are
complementary: one catches a missing row, the other a row present but
filled with the wrong thing. Mutation-proved.
--help still claimed sigla settings were resolved "but not yet
rendered", stale since the render wiring landed. colitur-config.5
documented none of the three settings even though config --show prints
them.
|
| | |
| |
| |
| |
| | |
Includes that --raw emits citations verbatim, which is the behaviour
someone diffing against lectio depends on.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Both kings_3 and kings_4 carried the full title "Liber Regum", so
--sigla-book full rendered 3 Kings and 4 Kings identically and a reader
could not tell which book a citation named. Seven citations in 2027
alone.
The cause is real and now recorded rather than papered over: this
Missal's incipit "Lectio libri Regum." is UNDIFFERENTIATED -- that exact
unqualified phrase precedes both a "3 Reg." and a "4 Reg." locator in
the same book -- so it is not a valid full title for either volume on
its own. Only the numbered locator distinguishes them, and both "3 Reg"
and "4 Reg" are independently attested in the scans.
The full titles are therefore marked CONSTRUCTED, a third category
beside sourced and UNSOURCED: both halves are transcribed, their
combination is not. The numeral is written in Roman to match this
project's own output convention ("Feria IV", "Hebdomada I").
Abbreviated and --raw output are unchanged.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
la.ini and en.ini both gain [sigla] (the current Vulgate/Latin punctuation
convention, byte-identical to Render.default_style) and [bible] (a .full
and .abbr row for every id in Book.all -- 45 cited ids plus the 7 tradition
targets, 52 total). Shipping [sigla] changes no output, asserted by the
full test run. Shipping [bible] does change rendered book names, which is
the point.
la.ini's titles are sourced from docs/research/scan1.txt/scan2.txt (the
1962 Missal scans), each row citing the line its incipit pattern was read
from. Six pairs (kings_3/4, corinthians_1/2, thessalonians_1/2,
timothy_1/2, peter_1/2) share one Missal incipit and differ only in the
sourced .abbr, matching what the primary text itself does. Three ids
(proverbs, song_of_songs, ecclesiasticus) and the seven tradition targets
are marked UNSOURCED and fall back to the data's own spelling, per this
project's central rule against inventing a Latin title.
Re-running the task's own sourcing note against the scans, counting every
hit rather than eyeballing a frequency-sorted list, found nine of its
NOT-sourced verdicts were undercounted (a single clean hit, buried under
higher-frequency matches): Galatians, Colossians, both Thessalonians, both
Peter, Malachi, Numbers, Jonas, Osee and Esdras all have a clean incipit
in the scans and are sourced here. The note's other three verdicts stand,
confirmed independently. Ecclesiasticus is not simply unfound: this Missal
reuses Wisdom's own Lectio libri Sapientiae incipit for Ecclesiasticus
readings too (both were anciently classed as one Sapiential group), so
using it for Ecclesiasticus would misidentify the book, not merely
abbreviate it -- recorded in that row's own comment.
en.ini's [bible] is filled in full, not left partial the way [celebration]
is: without it, a Vulgate-numbered id would fall through the [meta]
fallback chain to la.ini's Latin name, not merely a less complete English
one. Traditional Douay-Rheims names for the Vulgate ids (3 Kings, Osee,
Ecclesiasticus, Isaias, Apocalypse), modern names for the seven tradition
targets, since --sigla-tradition modern is the reader asking for modern
numbering.
test_lang_coverage.ml gains test_every_book_named, asserting every
Book.all id has both forms in la.ini -- the check that catches a forgotten
tradition target, since nothing else in the suite ever names them.
Shipping real book names changes 11 golden template renders (Render/golden)
and several test/cli.t examples that used to demonstrate the pre-Task-10
default-spelling fallback; both are updated to the new, correct output,
each line checked against a fresh render before promoting.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
View.citation_ref and readings' part_ref are the only two places a
citation reaches output; every emitter goes through View.
--raw passes Sigla.verbatim rather than a style built over Lang.raw:
an identity name table would still reformat punctuation and renumber.
Loosen reject_sigla_for: --sigla-style/--sigla-book/--sigla-tradition
now actually render on readings/table/render/emit/publish (each
builds its own Sigla.t via the new load_sigla), and stay refused only
on commands that render no citation (day, easter, temporal, ...).
names_of degrades a Lang.bible miss to Book.default_spelling rather
than printing the lookup key itself ("luke.abbr"); pinned in cli.t
against a language file with no [bible] section at all, independent
of la.ini/en.ini's own eventual [bible] section.
Regenerate the 11 golden templates for 2027: every changed line is
one canonical citation replacing a stored variant, verified against
the full readings 2027 diff (raw vs default) cell by cell -- 86
distinct (raw, rendered) pairs account for the entire diff across all
11 files, with zero unexplained residue. Two families: the seven
duplicate book spellings collapsing onto one canonical form (Isa./Isa,
3 Kgs./3 Kings, ...), and citations reconstructed from parsed
structure dropping stray punctuation the parser already treats as
noise (a trailing period or semicolon, a comma chapter/verse
separator, an elided inherited chapter) -- each of the latter already
named and tested in test_citation.ml's parse_suite before this task.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| | |
Same flag > config > default precedence as --lang, and each reported by
config --show with its source, so an override is visible rather than
mysterious.
A language file's [sigla] section IS a style; a config key SELECTS one and
may override settings within it -- the two are not a duplicate setting.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Apocalypse -> Revelation was missing from [modern] while `revelation` was
already a declared tradition target, so the target existed with nothing
mapping onto it. Same Vulgate-to-modern shape as Ecclesiasticus -> Sirach.
The injectivity test used to hand-copy the mapping table, which asserted
things about the copy and nothing about the artifact: a mapping added to
traditions.ini and forgotten in the test would have passed. It now reads
lang/traditions.ini and additionally asserts that [vulgate] is empty --
an entry there would silently renumber the DEFAULT, the one thing this
design promises never happens -- and that no declared target is left
unreachable.
Mutation-proved three ways: declaring an unused target, deleting a
mapping, and adding an entry to [vulgate] each redden it, the first two
naming the offending book.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Which book a reference denotes does not vary by language, so it lives in
its own file rather than in la.ini beside [weekday].
Six mappings, not four: Osee/Jonas are the same question as 3 Kings in
transliteration form.
The install rule is added in the same commit deliberately -- lang/ once
shipped without one, so the feature worked from the source tree and was
broken once installed.
bin/dune gains colitur_citation as a linked library, needed for the new
loader; lang_list's directory scan now excludes traditions.ini, which is
not a language file and does not parse as one.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Lang reads a hardcoded list of section names and ignores anything else
silently, so without this a [bible] section would appear to work and do
nothing -- confirmed directly with a scratch executable: before this
change, of_string on text containing a [bible] section parsed without
error and Lang.keys came back empty, no trace of the section anywhere.
Lang.bible keeps the total-lookup contract every other lookup in this
module has: a miss returns the key itself, never the empty string.
Lang.sigla_fields returns the [sigla] section's raw fields, values
trimmed but still quoted, for Render.style_of_fields to unquote.
[bible] joins the keys reference set so lang --check reports missing
book names; [sigla] deliberately does not, being settings with working
defaults rather than translatable names -- adding it would make --check
demand five settings from every language file.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
format never raises and returns an unparseable citation unchanged, so a
gap degrades to today's behaviour rather than to a crash. The coverage
test asserts separately that no shipped citation takes that path.
verbatim is what --raw uses: an identity name table would still reformat
punctuation and renumber, which would break byte-exact diffing against
lectio.
The existing citation-coverage walk (1970-2070) now also drives a
round-trip check in the same pass: parse -> render -> parse must reach
the same structure, using Book.default_spelling for names (Book.to_string
returns the internal id, which is not a registered token and cannot be
read back). Proved with a mutation: changing the default style's
part_sep to a separator the parser does not accept reddened the
round-trip case on 31 multi-part citations and nothing else; reverted.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Book.default_spelling returns the first registered spelling for an id. It
is the fallback display name, and it exists because the alternative is
worse: a language file's [bible] lookup is total and returns THE KEY on a
miss, so a book with no entry would render as "luke.abbr 5:12-14".
Falling back to the data's own spelling makes it render as "Luke
5:12-14" instead -- what colitur printed before this feature existed.
The degraded case is the old behaviour, the same principle Lang states
for its own key-returning misses.
Two test gaps closed, both found by mutation rather than by reading:
Parse's split_book scans a leading ordinal digit over '1'..'4', and no
case in the suite used an ordinal above 1. Narrowing the range to
'1'..'3' passed every test while seven real citations depend on it
("3 Kings 17:8-16", "4 Kings 5:1-15"). Parse-layer cases added; the
first attempt at this test asserted through Book.of_token, which is a
table lookup and never reaches split_book at all.
default_spelling is asserted to round-trip: every cited id's fallback
spelling must itself resolve back to that id, or Render and Parse
disagree the moment a book goes unnamed.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| | |
A style is a set of format strings, so punctuation convention is data.
Values are unquoted here rather than in Overlay_ini: that parser trims
every value and is shared with overlays and [defaults], so teaching it
about quotes would change behaviour this feature has no business
changing.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| | |
Walks 1970-2070 and parses every citation the engine emits. Nothing
validated citation spellings before this, which is why seven books
carried two spellings unnoticed.
Mutation-proved: removing the 'Isa.' spelling from the book table
reddens this test naming that citation.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| | |
The parsed form is a book and a LIST of chapter-parts: the data cites
across chapters and lists disjoint verse ranges within one.
Two rules the shipped data forces and that are not obvious: a
semicolon-separated part may inherit the previous chapter rather than
restate it, and a chapter may be separated from its verses by a comma.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The book table was built against data/ef/lectionary.sexp alone. That
undercounts: sanctoral.sexp carries more citations than the lectionary
and, together with commons.sexp, cites 21 book tokens the table was
missing entirely (62 distinct tokens across all three files, not 42),
several of them common (2 Tim appears 8+ times).
Add the missing spellings to existing ids (2 Cor, Col., Exod, Ezek,
James, Sir, Eccli) and ten new ids for books not cited before (1-2
Timothy, 2 Peter, Apocalypse, Judith, Malachi, Proverbs, Song of Songs,
Tobit, Wisdom). Sir and Rev are modern spellings sitting inside
Vulgate data, so both resolve to their Vulgate ids (ecclesiasticus,
apocalypse) rather than to the sirach/revelation tradition targets --
mapping them to a second id would double-map the same book.
Add a duplicate-spelling invariant test (List.assoc_opt would silently
prefer the first match on a collision) and a test that re-derives the
token set from all three data files at test time and asserts every
token resolves, rather than trusting a survey performed once by hand.
|
| |/
|
|
|
|
|
|
|
| |
Seven books arrive in two spellings, inherited from lectio's ini and
ultimately from Divinum Officium. Collapse them onto one id here rather
than editing generated data.
Naming and renumbering are kept apart: a tradition decides which book an
id denotes, a language file decides what it is called.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ordo.ms's own Build: comment omitted -P-pa5 entirely, so the documented
command produced A5-sized content on a physical A4 PDF page
(595x842pt instead of 419x595pt) -- verified by running the command
verbatim and reading pdfinfo. Both .ms Build: lines were also missing
-Kutf8 and -t, which the Makefile's check-templates target already
carries: without -Kutf8, accented Latin names (e.g. Peñafort) render
as mojibake, confirmed by extracting text from the rendered PDF.
Bring both templates/ef/ordo.ms and templates/ef/grid.ms in line with
the Makefile's actual invocation (-ms -t -Tpdf -Kutf8 <papersize>), so
a user copying the Build: line gets the same result as
'make check-templates'. Updated the two golden fixtures that pin these
templates' rendered output byte-for-byte to match.
Verified every documented build command (README's two pdflatex
invocations, both .ms lines, both .typ lines) by running it verbatim
and checking pdfinfo/pdftotext output; no other flavour's Build: line
or man page example was affected.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ordo.tex was 53 pages / 6.9 days-per-page on 2027 against ordo.typ's 27
pages / 13.5 -- the user prefers the tighter Typst booklet. Read ordo.typ's
own typographic decisions (base size, the day-number/name/detail-line size
hierarchy, box padding, inter-box skip, leading) and matched them: an
explicit 9pt/10.5 base (was \normalsize, 10pt), the day number and feast
name both 9pt bold (bold distinguishes them, not size, as ordo.typ decided),
7pt weekday, 6.5pt detail lines, sharp-cornered boxes, and needspace amounts
re-measured for the shorter boxes. Result: 29 pages / 12.6 days-per-page --
within the "a page or two of 27" target, reached without sacrificing
legibility (verified against the rendered PDF, not assumed).
The one real gotcha: \fontsize set inside a brace group that closes before
the line-ending \\ has no effect on the interline glue TeX inserts for that
break -- the glue uses the OUTER scope's \baselineskip, not the just-closed
group's. This is exactly the shape of bug the pre-retune box already had
(every \fontsize group closed before its own \par), which is why the first
retune pass barely moved the page count. Fixed by declaring \fontsize/
\selectfont/\bfseries/\mdseries inline, ungrouped, immediately before the
text each governs. Recorded in the file's own header for next time.
ordo.ms looked comparatively fine (43 pages) but was rendering on A4, not
A5 -- roughly double an A5 page's area, so normalised for area it was
already looser than ordo.tex's own pre-retune baseline. Fixed, each found
by rendering and reading the real PDF rather than assumed: added -P-pa5 to
the Makefile's groff invocation (mirroring grid.ms's existing -P-pa4l);
fixed the day box reading the RAW rank/colour strings (class-2, green)
instead of the resolved Latin pair (rank_name/colour_name) -- exactly the
"printed slugs" defect the ordo rebuild's own commit message named, which
this file had regressed to; added -Kutf8 (groff's default input encoding
produced visible mojibake on an accented Latin name); tightened fonts/
leading the same way as ordo.tex; found and fixed a stray-blank-line bug
present since the file's original authoring (every day/week/month boundary
left an accidental blank template line, read by groff as its own extra
.sp); found and fixed a genuine print-safety bug (text sitting 0.13mm from
the true page edge -- .pl, groff's text page length, is independent of
-P-pa5's device paper selection and needed matching explicitly before ms's
own FM-based bottom margin would fire at all); and added a .ne guard so a
week header can no longer be stranded alone at a page's foot. Net: 43 pages
(A4, broken) to 39 pages (real A5, print-safe, real Latin names, correct
encoding, zero orphans) -- no numeric target set for this flavour, but no
lower number was reachable without leaving one of the above unfixed.
ordo.html and every grid.* flavour are untouched, as scoped.
Both golden/ordo-2027.{tex,ms} regenerated through the real test harness
path (Test_support's loaders + Test_view's en-with-la-fallback view_of),
not the CLI, whose own --lang default (la) differs from the harness's and
would have pinned content the suite never produces.
Full suite green: 503 tests (504 with the exhaustive sweep). make
check-templates/check-schema/check-citations all clean.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Every ordo booklet week header used to print the month name again
even though the month heading right above it already established it
-- pure noise, repeated once per week for the whole year. All seven
ordo flavours now print the week's own Roman numeral plus the span of
dates it covers instead, e.g. "Hebdomada I (Ian 1-2)", with no month
name on the line; the LaTeX table of contents and the Typst outline
(built automatically from its own headings, so editing the heading is
the whole fix there) read the same way.
A single-day week (e.g. a lone trailing Sunday) renders "Ian 31", not
"Ian 31-31": each flavour's dash sits inside an inverted single_day
section, so the engine -- which cannot itself compare first_dom to
last_dom -- never has to decide anything, it only follows the data.
The dash character matches each flavour's own existing convention:
LaTeX/Typst's own "--" ligature, groff's \(en escape (alongside its
existing \(bu), HTML's – entity (alongside its existing
·), and a literal en dash for the three flavours with no
escaping (adoc/md/txt).
Every in-template comment describing the new fields is written without
ever typing two curly braces together, including in the two comments
this touches that used to embed a live {{month_name}}/{{term.week}}
tag pair inside a LaTeX % comment -- harmless only because that whole
line already started with %, not because the engine has any comment
awareness (it has none).
Goldens regenerated through test_render_golden.ml's own render path
(Test_view.view_of + Template.render_string), not the CLI -- the two
differ in default language and would otherwise pin output the test
suite never produces. Grid goldens are untouched, matching the grid
templates, which have no week header.
Verified against real pdflatex (two passes) and typst compile output,
not merely the golden pins: both flavours print "Hebdomada I (Ian
1-2)", "Hebdomada II (Ian 3-9)", "Hebdomada III (Ian 10-16)" as their
first three week headers and identical text in the table of
contents/outline, and both show "Hebdomada VI (Ian 31)" for January's
own trailing single-day week with no dash.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The ordo booklet's week header repeated the month name on every week
even though the heading above already established it -- pure noise.
Replace it with a Roman week number plus the span of dates the week
covers, e.g. "Hebdomada I (Ian 1-2)", following the project's own rule
that a presentation choice is data, not code.
lang/{la,en}.ini gain a [month_abbr] section (three-letter month
abbreviations); Lang.month_abbr follows Lang.month's exact shape,
including the out-of-range and miss-returns-the-key contracts. The
coverage test now fails loudly if an abbreviation goes missing, the
same as [month] already does.
Every week object in the view gains num_roman (Roman numeral, num
stays as the arabic original -- Roman is a presentation choice, not an
engine change), first_dom/last_dom (the day-of-month of the week's
first and last IN-MONTH days, padding excluded), month_abbr (resolved
through Lang.month_abbr), and single_day (true when the week holds
exactly one in-month day). single_day is a flag, not a preformatted
span string: the engine is logic-less and cannot itself decide between
"Ian 1" and "Ian 1-2", so a template makes that call from the flag
instead -- the same "shape the data, not the template" discipline
in_month and last already follow.
Weeks are built per month with padding only at the two ends, so a
week's in-month days never cross a month boundary -- verified, not
assumed: every week always has at least one real day since no month is
shorter than a single week.
Covered by three new View tests, including a real single-day-week
witness (January 2027's own trailing week is a lone Sunday, the 31st).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
grid.typ used rows: (auto, 1fr) on the assumption that a Typst
fractional row always shrinks to share whatever space is left. It
does not: an 'fr' track's size is the LARGER of its fair share and
its content's own minimum, so it grows PAST 1fr when content is
taller than that share rather than compressing to fit. Adding the
sigla line (Epistle/Gospel references) grew every cell's natural
content past what a 1/6-of-remaining-space row allows, and a 6-week
month (three of twelve in 2027) split its own table between rows,
stranding the last week alone on a fresh page with no heading -- the
user's screenshot showed a row sliced mid-cell, 'I classis' cut off,
the next month's own heading printed underneath it.
Fixed the same way grid.tex's own \cellh already was: an explicit
row height (cellh, computed from the page's text height divided by
six, budgeted with 6mm of deliberate slack after a zero-slack first
attempt still split a table between rows), with each cell's content
wrapped in a height-clipped block sized to match -- content that
still does not fit is truncated rather than spilling into the next
cell or page. block(breakable: false) around the whole table is a
second, independent backstop: even if the budget is ever wrong
again, the WHOLE table jumps to a fresh page rather than splitting a
row across two, a loud failure (an odd blank page) rather than a
silent one (a sliced row).
This reverts the file's own prior divergence from grid.tex (Typst
stretching every month to fill the page regardless of row count,
disclosed as deliberate at the time) -- overflow safety now matters
more than that cosmetic fill. A 5-week month still leaves a blank
sixth row, the same trade-off grid.tex's own header already accepts.
Verified against all twelve months of 2027 (three 6-week: January,
May, October; nine 5-week), typeset through typst compile: exactly
12 pages, one month title per page, no clipped or duplicated
content, day 31 of a 6-week January fully visible. grid.tex itself
re-checked for the same latent risk and found unaffected -- its
fixed-height \cellh box already had enough margin.
Golden regenerated through the same Test_view.view_of path the
other affected templates already use.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
One week per page filled roughly the top third of every A5 page and
cost 65 pages for a year that needed far fewer -- the original
requirement, reversed here: a full 7-day week already occupies most
of an A5 page even at reduced type, so the real saving was always in
the year's many SHORT boundary weeks (a month's first/last week is
rarely a full seven days), not in packing two full weeks together.
lib/render/view.ml gains a [first] field on every week object (true
on a month's own first week, the same 'cheap flag beats invented
template logic' call [last] already made for grid rows) -- there is
still no {{../}} parent-path syntax for a template to test this any
other way.
ordo.tex: the per-week \clearpage is gone. Every week keeps its
existing small header line; the month's own first week additionally
prints a large, ruled banner. \needspace (a template-local LaTeX
dependency, not one of the frozen OCaml deps) keeps a header from
being stranded alone at a page's bottom -- and a real, separate bug
surfaced building it: \label placed BEFORE \needspace captured the
OLD page number when \needspace went on to force a break, producing
a step-stale \pageref in the TOC (fixed by moving \label after both
needspace checks). The day box itself is tightened (rank/colour
folded onto the same line as the citations -- an A5 box is far wider
than tall, so this fits even Holy Week's longest citations with room
to spare) so a second week routinely shares a page with the first.
Measured result: 65 -> 53 pages, two pdflatex passes still settle the
TOC, zero orphaned headers, zero overfull boxes.
ordo.typ: the per-week #pagebreak is gone; #show heading's own
block gains sticky:true, Typst's built-in answer to what ordo.tex
needs \needspace for. The month banner needed its OWN sticky:true,
found live: without it a banner could sit alone at a page's bottom
with the entire month pushed to the next page -- not caught by a
check for an orphaned HEADING, since the banner is plain markup, not
one. Measured result: 65 -> 27 pages (Typst's own page-fill packs
tighter than ordo.tex's needspace-driven approach), one compile pass,
zero orphans.
The five non-paginated flavours (ms/html/md/adoc/txt) never had a
forced page break to remove -- they mainly needed the same header
treatment for structural consistency: a week-level header nested
under each month's existing one, walking months>weeks>days (the
week's own padded, in-month-guarded day list) in place of the old
months>days flat loop. Verified against groff, asciidoctor and an
HTML parser -- zero warnings.
Goldens regenerated through the Test_view.view_of path
test_render_golden.ml itself uses, not the CLI (whose --lang default
would have pinned output the tests never produce).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The booklet's title page and running header read "Ordo 2027 . ef" --
an internal identifier reaching a reader, the same defect class the
sanctoral/temporal slugs were already fixed for.
lang/la.ini and lang/en.ini each gain a [rite] section mapping the
rite id to a reader-facing name, sourced from the Missal's own title
page (docs/research/LT.txt:6 "MISSALE ROMANUM", :15 "EDITIO TYPICA")
plus the 1962 dating this project uses throughout (rules-register.md,
CLAUDE.md) -- both cited in the ini comments, marked PATTERN since the
phrase combines two title-page elements rather than quoting one
verbatim heading.
Lang.t gains a rite table/lookup (same total, miss-echoes-the-key
contract as every other lookup here); View.of_days exposes rite_name
alongside the existing rite field, which stays the stable key exactly
as slug is kept beside name. Every shipped template that printed
{{rite}} now prints {{rite_name}} instead.
test_lang_coverage.ml gains a coverage assertion over every rite id
the engine can emit -- one today -- so a second rite module (OF)
landing without a matching [rite] entry fails loudly instead of
printing its own bare id.
Goldens regenerated through the Test_view.view_of path
test_render_golden.ml itself uses (English with a Latin fallback),
not the CLI (whose --lang default is plain Latin and would have
pinned output the tests never produce). test/cli.t's own JSON prefix
assertion updated to match: rite_name is a real new key in that
generic view dump, sitting right after rite.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The task this branch of work set out to test was whether the template
engine is genuinely flavour-agnostic outside lib/render/escape.ml. It
is not, quite: bin/main.ml's own --flavour error/help text and both
man pages hand-typed the flavour list and its count ("the six
flavours") as literal prose, so adding Typst as a seventh left three
places silently wrong (an incomplete flavour list in two error
messages, and "six" where the true count is now seven) until this
commit.
bin/main.ml's two error messages (unknown --flavour value, and cannot
infer a flavour from an extension) now build their flavour list by
walking Escape.all/to_string instead of a literal string, so the next
flavour added will not reintroduce the same drift; the static --help
body text and colitur(1)/colitur-templates(5) still name flavours and
their count by hand; there was no equivalent gain available for
prose formatted this specifically, so those were updated by hand
instead, along with colitur-templates(5)'s FLAVOURS section, which
gained typst's own subsection alongside latex/groff/html/xml/ics/none.
test/cli.t's two pinned error-text assertions are updated to match,
and gained a new case: .typ inferred from extension, and a real
shipped citation's hyphen surviving --flavour typst's own escaping
live, the same shape the 2035 Ss. Petri et Pauli case already proves
for latex's ampersand just above it.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds templates/ef/ordo.typ (A5, one week per page, each day framed with
a colour swatch, real names, every fixed string through term.*) and
templates/ef/grid.typ (A4 landscape, one month per page, 7 columns,
colour-filled cells, Epistle/Gospel sigla), matching what ordo.tex and
grid.tex already do.
Typst resolves its own table of contents inside a single compile: no
pageref/aux-file dance, unlike pdflatex's own two-pass need for
ordo.tex. ordo.typ's TOC is one flat heading per week (Month . Week N)
rather than ordo.tex's own month-once/weeks-nested layout, since the
view model has no first-of-month flag for a template to test and
inventing one would be new engine state for a cosmetic grouping.
grid.typ deliberately diverges from grid.tex's own partial-fill
behaviour for a 5-week month: Typst's row-size list repeats its own
last entry for every remaining row, so a two-entry rows spec fills the
page completely regardless of week count, where LaTeX's fixed cellh
leaves a 5-week month's bottom sixth blank on purpose. Both divergences
are documented in the templates' own headers.
Two bugs found and fixed while building these against the real typst
0.14.2 binary: two stray hash characters in grid.typ's header comment
that were not actually inside a line-comment (would have been parsed
as Typst code, not prose); and two lines merging into one wherever they
were separated only by a bare newline (still the same soft-wrapped
paragraph in Typst, unlike LaTeX's own explicit paragraph break) --
fixed with a trailing backslash to force a real line break without
adding inter-paragraph spacing, verified against a full-year render
(zero typst warnings across all 365 days of 2027, in both templates).
Goldens (test/golden/ordo-2027.typ, test/golden/grid-2027.typ) were
generated through the harness's own View.of_days/Template.render_string
path, via a throwaway generator, NOT through the CLI: the CLI's default
language table differs from the harness's own English-chained-to-Latin
table, confirmed live (diffing CLI output against the harness's own
render showed exactly the expected language divergence and nothing
else) -- the same trap this project has hit before.
make check-templates now typesets both templates with the typst binary,
using the same SKIPPED-and-exit-0 shape the pdflatex/groff blocks
already use when their own tool is absent, verified in both directions:
absent (PATH without typst) skips loudly and exits 0, and a
deliberately corrupted template fails the target with a non-zero exit
and typst's own error text.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds Escape.Typst: type, all, to_string ("typst"), of_string,
of_extension (.typ), and a per-character expand function, structured
identically to the existing latex escaper (one pass, no re-scan, so
double-escaping stays impossible by construction).
The metacharacter set was verified against the installed typst 0.14.2
binary, not assumed: a probe document escaping each of #, *, _, $, @,
<, >, `, \, ~ and - was compiled and pdftotext'd back to confirm the
literal character survives, and each was separately confirmed to do
something else when left bare (# opens code mode, */_ toggle
strong/emph, $ opens math, @ opens a reference -- a bare unresolved
@word is a hard compile error, not merely mangled output -- </> can
close around a bare word into label syntax that swallows it whole, `
opens raw, ~ is a non-breaking space, and a run of two or three '-'
becomes an en/em dash). All ten are backslash-escapable; none needed a
non-backslash workaround. '-' is escaped unconditionally rather than
only inside a detected run, since this escaper has no lookahead -- a
probe confirmed escaping every hyphen independently still typesets as
literal hyphens for a run of any length, so the single per-character
rule is sufficient.
test_escape.ml's new Typst cases were written first and shown to fail
against a stubbed identity apply before the real escaper landed, per
this project's own regression-test discipline. Comments in both files
mark which new tests are genuine regression tests (the per-character
escaping, including a real shipped citation and a synthetic
markdown-habit overlay name) versus characterisation (to_string/
of_string/of_extension are flat table lookups with no logic to have
been wrong).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
colitur-config.5 documents the file's location, the flag > config >
default precedence, every setting, and that an unknown key is warned
about rather than fatal. Its worked example is a real run against the
shipped example overlay, pasted rather than hand-typed -- including one
genuine gotcha found while verifying it: overlay/template values are not
shell-expanded, so a bare "~/..." written into the config file fails to
load; the full path must be written out instead.
colitur-templates.5's field reference is updated for the view change --
every field checked against lib/render/view.ml and schema/day-v1.json,
not transcribed from memory or an earlier version of this page -- and its
worked example is pasted from a real `colitur table` run. Its
scope-shadowing warning about {{name.la}} is REMOVED and replaced with a
short note that the hazard is now unrepresentable, because name is a
plain resolved string with no dotted path left to fall back through. The
num collision between a month and a week (both carry num, and a bare
{{num}} read from inside a day silently climbs to the week's own value,
not the month's) still exists and is demonstrated with a real render, not
merely asserted. A man page describing a hazard that was fixed is as
wrong as one that omits a real hazard.
Two further stale mentions of the removed {{name.la}} hazard, and two
places describing the schema as "Latin and English names" rather than one
resolved display name, were found in colitur.1 while cross-checking and
fixed alongside the primary rewrite; its own CSV example in EMIT was also
still the pre-Task-5 column list (name_la/name_en, no *_name columns) and
is now the real, verified header.
lang/ already installs beside templates/ and schema/ (a prior hotfix);
colitur-config.5 is added to install/uninstall/man/doc in the Makefile so
`make install`/`make doc` cover it too.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Names are Latin by default now; --raw restores the old byte-exact output,
verified against a pre-branch binary built from a clean HEAD checkout, not
merely asserted. day and readings gain a trailing display-name field
(day's own name suffix, readings' own " | name" suffix) rather than a
substitution in the slug's existing position: a name contains spaces and
would otherwise break the space-separated columns, the same reasoning that
already keeps readings a separate command. The field is present only when
it differs from the slug already shown, which is a direct consequence of
Lang.raw being the identity table (no lookup ever misses), not a special
case threaded through day_line/readings_line -- under --raw, or any
language with no entry for a given day, the trailing field is simply
absent, byte for byte what this project printed before naming existed.
An unknown language is an error naming what is available, never a silent
fallback to Latin: a booklet quietly printed in the wrong language is worse
than one that refuses to print. A declared fallback still chains, so a
partial translation shows its fallback language rather than slugs.
lang_dir mirrors data_dir's probe order exactly -- installed prefix, then
build tree -- because an installed binary that finds calendar data but no
language files is the failure this would otherwise ship.
Config (lang/overlay/template/format) is loaded once, unconditionally,
before dispatch: a config file that exists but fails to parse is fatal on
every command, not only the ones that consult it, because a config the
user wrote and colitur cannot honour is not something to silently carry on
past. An unknown key or unknown section is reported and ignored, worded
differently so a misspelled section reads differently from a misspelled
key inside a recognised one. overlay's config default applies only when
zero --overlay flags were given, never merged with a partial CLI list, so
precedence stays flag > config > default in one direction throughout.
colitur lang --list/--dump/--check and colitur config --show are what make
"anyone can write a language file" true rather than merely permitted, the
same pattern the overlay system already established with new-overlay and
check. --check reports what is missing AND rejects an unknown slug (exit
1), because a key matching nothing is silently dead and its author would
otherwise never learn why their own name does not appear. --dump emits
sections in a fixed order (Lang.keys' own global sort keeps every
section's keys contiguous), so two dumps of the same table are
byte-identical. config --show resolves through the same Config.resolve
every other command uses -- deliberately no separate provenance function,
so the two cannot disagree -- and previews exactly what flags given on the
same command line would resolve to anywhere else.
One authorized change outside this task's own file list: emit_ics.ml's
SUMMARY line was reading the unlocalised rank/colour pair ("class-1,
white") beside an already-localised name, where the JSON schema right next
to it correctly carries rank_name/colour_name ("II classis"/"albus").
Found while reviewing the published site; fixed at the source.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem 1: grid.tex's \daycell pushed the rank/class line to the exact
bottom edge of its fixed-height parbox with \vfill, the same edge \hline
draws the cell's bottom rule along, so 'I classis'/'IV classis'/'II
classis' printed as if sliced by the rule. Fixed by nesting a second,
shorter parbox (\cellh minus a new \cellpad, 1.5mm) inside the
unchanged \cellh-tall outer one, so the \vfill only ever reaches to
\cellpad above the rule, never touching it. \strut on both trailing
lines belt-and-suspenders the fix for lines with no descenders.
Problem 2: each cell now also carries the day's Epistle and Gospel
references (view fields first/gospel), joined by a centred dot/bullet
rather than repeated Ep./Ev. labels -- the same compact convention
ordo.tex already uses between rank_name and colour_name. A grid cell is
only ~3.5cm wide and Holy Week's own citations run 20-30 characters each,
so class label and sigla get their own \tiny line apiece rather than
being crammed onto one line and shrunk past readability; \cellh leaves
about eleven \tiny lines of room, so two short lines cost little. Both
first and gospel are wrapped in their own conditional section so a day
missing either prints no stray separator (defensive: every day in the
shipped EF lectionary has both, but nothing guarantees that of a future
rite or overlay).
grid.ms gains the same sigla, on their own .br line, using tbl's existing
w() wrap rather than any manual line-splitting -- it was never subject to
problem 1 (tbl auto-sizes row height, no fixed-height clipping risk) and
never carried a class label to begin with, so none was added here.
grid.html gains the sigla as a small, muted block-level span; unlike the
two paper flavours it isn't boxed onto a fixed physical page, so the
browser just grows the cell rather than needing any line-budget
compromise.
Verified with two pdflatex passes and groff -ms -t -Tpdf against all
twelve 2027 months: zero Overfull warnings, 7 columns every row, class
label and sigla both fully clear of every rule. test/golden/grid-2027.*
regenerated through test_render_golden.ml's own render path (View.of_days
+ Template.render_string, the EN-with-LA-fallback lang table), not the
CLI, per this project's own standing trap about the two tables differing.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
la.ini and en.ini (725 Latin/English liturgical names -- the entire
point of the naming-and-config work just merged) had no dune install
rule, so make install / dune install never copied them to
<prefix>/share/colitur/lang/. bin/main.ml's lang_dir() probes exactly
that installed path first, falling back to a build-tree layout that
also does not exist for an installed binary -- so every installed
user silently got raw slugs (ef-circumcision) and untranslated terms
(epistle/gospel) instead of resolved names, with no error at all.
The defect existed because nobody had run the installed binary from a
directory with no colitur source tree above it: dune exec and dune
test always resolve lang/ via the build tree, materialized as a side
effect of test/dune's cram deps, so every in-tree check stayed green
while the installed artifact was broken.
Add lang/dune, following schema/dune's exact pattern: an install
stanza placing la.ini and en.ini at <prefix>/share/colitur/lang/,
matching where bin/main.ml's lang_dir() already looked. No code
change was needed there -- only the missing install rule. Update
Makefile's install target help text and summary echo to mention lang
alongside ef/templates/schema.
Verified end to end: uninstalled, removed lang/dune, rebuilt and
reinstalled to reproduce the bug from an outside directory (~/tmp,
colitur table showed ef-circumcision/epistle); restored lang/dune,
reinstalled, and confirmed the same command now shows the resolved
Latin name and rubric terms, that ~/.local/share/colitur/lang/
contains both files, and that colitur emit --format csv shows a real
name in the name column. lang/la.ini and lang/en.ini are untouched.
Full suite: dune test --force, 495 tests, 0 failures.
|
| |\
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
colitur computed the calendar correctly and could not say what it had
computed. A printed ordo read ef-septuagesima-sunday-2 where a reader
expects Dominica in Sexagesima, and the wall calendar showed slugs in
every cell.
lib/naming a language table and a config file, both pure and total,
parsing the INI reader Overlay_ini already had
lang/ la.ini and en.ini -- 725 names, every one transcribed
from the 1962 Missal and citing the line it came from
templates the ordo rebuilt as an A5 booklet: one week per page, a
table of contents, framed days, a colour swatch; the wall
calendar now fills its sheet instead of a quarter of it
tools check_citations.py verifies all 400 citations resolve,
with 33 self-tests of its own
Names resolve through lang -> declared fallback -> the slug, so a partial
translation is usable from its first line and the fully degraded case is
the old output rather than a blank page.
colitur day and colitur readings are BYTE-IDENTICAL to before, verified
against main rather than asserted; --lang, --raw and the lang/config
subcommands are still to come, and man/colitur-templates.5 still
documents the pre-naming view, so writing a custom template needs the
source until that lands.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The six ordo booklet goldens (tex, ms, html, adoc, md, txt) were stale,
not broken: the commemoration-naming task landed 120 Latin names for
sanctoral slugs, so the render path test_render_golden.ml exercises now
prints real names (e.g. 'St. Telesphorus Pope and Martyr', or 'S. Felicis'
via en.ini's own la.ini fallback where English has no entry) where the
committed goldens still pinned the raw slug ('telesphorus-pope-and-martyr',
'felicis').
Regenerated through the same path test_render_golden.ml uses -- en.ini
chained to la.ini via Test_view.view_of, never the CLI's Latin-only
default -- with temporary env-gated scaffolding in the test file, used
once and reverted before this commit. Every changed line is a 1:1
slug-to-name substitution; file structure, line counts, and everything
else are untouched (570 insertions / 570 deletions across the six files).
Verified before committing: no unrendered {{ }} tags, none of the 332
known sanctoral/adjustment slugs leak into any of the six files, all
twelve month headings and all 365 day entries are present in each. Full
suite (495 tests), check-templates, and check-citations all still pass.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
test_lang_coverage.ml's own coverage test used to walk only the OBSERVED
day of each date (one Celebration.t per Liturgical_day.t). A liturgical
day also carries a second stream of slugs -- commemorations (kept when the
observed day does not fully displace a losing candidate, RG 108-111) and
transfers (an impeded I/II-class feast moved to a later date, RG 96-98) --
and nothing here ever looked at them. The test asserted coverage of what
it happened to WALK, not of what the engine can EMIT, so it passed green
while the ordo booklet printed raw slugs ("Commemoratio canute-martyr",
"Commemoratio maur-abbot", "Commemoratio peter"). test_lang_coverage.ml
now walks observed, every entry in commemorations, transferred_in, and
every entry in transferred_out.
That extension turned up 120 slugs with no Latin name across 2020-2045,
now added to lang/la.ini: 112 are data/ef/sanctoral.sexp companions the
temporal-only walk never reached; 5 (barbara, commemoration-of-st-peter,
commemoration-of-the-seven-sorrows, major-litanies, rogation-wednesday)
are data/ef/adjustments.sexp's own hand-authored Add directives; 3
(ef-nativity-octave-day-2/3/4) are temporal days with no calendarium
heading to transcribe, built by the same pattern days 5-7 already use.
Seven of the sanctoral names are cited to docs/research/scan1.txt rather
than LT.txt: the 2006 web-capture transcription silently drops several
real commemorations that both photographic scans carry (donatus, romanus,
eusebius-confessor, naboris-et-felicis, sts-gervasius-and-protasius,
sts-felix-and-adauctus, and praxedis-virginis -- the last for a spurious
ligature LT.txt introduces, "Praxedis" confirmed correct against both
scans). The same 120 names, extracted verbatim from sanctoral.sexp's and
adjustments.sexp's own English fields rather than retyped, are added to
lang/en.ini.
make check-citations: 400 LT.txt citations checked, 0 wrong, 0 malformed,
0 cannot verify. Teeth proved by deleting canute-martyr's own name (a
Commemoration_only slug that can never be the observed day, only ever a
commemoration) and confirming the coverage test fails naming exactly that
slug, then restoring it.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The previous version occupied about the top quarter of an A4 page and
left the rest blank, and printed slugs. Cell height is now computed
from the text height (\textheight-18mm over 6 rows -- every month has
5 or 6 Sunday-started weeks) rather than left to the table's natural
size, which is what made it float at the top. Measured: January 2027's
last row of content now reaches y=566pt of a 595pt-tall page, not a
quarter of the way down.
Real names replace the raw slug in every cell (the observed day's own
resolved display name, a plain string per View.of_days), and each
day's rank name is shown too, so a printed page reads as a calendar
rather than machine keys.
Weekday headings come from the view as a localised list rather than a
hard-coded Dom/Lun/Mar row, so a translated calendar needs no template
edit -- and because the engine rejects an empty tag path, the list
carries named {name; last} fields rather than bare values.
grid.ms and grid.html carry the same two changes (real names, localised
weekday headings) for their own flavours.
Verified with pdflatex/groff: 12 pages, A4 landscape, every row exactly
7 cells (6 ampersands), zero warnings. Goldens regenerated through the
test harness's own render path, not the CLI, whose default language
table differs from the test's.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
A LaTeX table of contents needs two pdflatex passes -- the first pass
leaves every entry showing '??', the second resolves the \pageref
values. A user hit exactly this and reported it as a bug; the template
was fine, the instructions were not.
README's rendering example now runs pdflatex twice for ordo.tex (or
names latexmk -pdf as the one-shot alternative) and notes the wall
calendar needs only one pass, having no cross-references of its own.
make check-templates now runs pdflatex twice per LaTeX template too,
so the target exercises what a user actually has to do rather than
silently passing on a single, incomplete pass.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
geometry's top=11mm/bottom=12mm seated the text block without accounting
for fancyhdr's own header/footer, which live OUTSIDE that block by
default -- pushing the running header ('Ordo 2027 . ef') partly above
the physical page edge (measured: yMin -5.5pt on a 0..595pt page) and
the footer to within 1pt of the bottom edge. The user hit this and
reported the header as clipped.
Adds includehead/includefoot to the geometry options (a5paper,
top=10mm, bottom=10mm) so the header/footer live inside the margins
instead, with headsep/footskip set explicitly (3mm/7mm) rather than
left at article's defaults -- those defaults alone would still overflow
a 10mm margin and silently added 20 extra pages to the whole booklet by
shrinking every day box.
Verified: two pdflatex passes produce a 65-page A5 PDF with the full
'Ordo 2027 . ef' header intact on every page and zero pdflatex
warnings. Golden regenerated through the test harness's own render
path (English-with-Latin-fallback), not the CLI, which defaults to
Latin only and would otherwise pin output the tests never produce.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
A5, one week per page, with a table of contents, each day in a framed box
and a colour swatch so the page is scannable without reading. Real names
throughout, and every fixed string routed through the term vocabulary so
a translated booklet needs no template edit.
The previous version was A4, printed slugs, ran days together with no
visual separation, had no contents, and gave the liturgical colour only
as the word white. It was not usable as a printed booklet.
lib/render/view.ml already carried month_num/month_name on each week
object from Task 5, so no kernel/view change was needed here -- the
template uses those instead of a parent path the engine cannot express.
Box padding, margins and secondary-line font size were tightened past
the brief's own starting values: at the brief's sizes a week with several
long commemoration names (e.g. Feb 21-27, three of seven days carrying
one) overflowed onto a second physical page, breaking one-week-per-page.
Verified by measuring page count against the known week count (63 weeks
in 2027) until every content page carried exactly one week, not by eye.
The header comments of all six flavours were themselves a trap the brief
warns about: writing double braces to NAME a template field inside a
LaTeX %, groff .\", HTML <!-- -->, or AsciiDoc // comment gets parsed as
a real tag by this brace-only engine, not treated as inert prose. An
early draft's own comments did this and produced 'empty tag path' parse
errors and a silently-unclosed section; every comment in all six
templates is now written without ever typing two braces in a row.
The other five flavours keep their existing structure; only the dead
{{#name}}{{la}}{{^la}}{{slug}}{{/la}}{{/name}} idiom is replaced with a
plain {{name}} (extended to comms entries too, which carry their own
resolved name), and the fixed labels (Ordo, Epistle, Gospel,
Commemoration) now come from {{term.*}}.
Golden regeneration could not follow the brief's own `colitur table`
shell-out literally: the CLI's current default language is Latin-only
(bin/main.ml's Task-5 bridge), while test_render_golden.ml renders
through Test_view's English-primary/Latin-fallback table, so the two
produce different text for the same slug. The goldens were regenerated
through the test's own render path instead (a temporary env-gated block
in test_render_golden.ml, reverted before this commit), so they agree
with what the suite actually computes.
All six ordo golden tests pass; the three grid ones are Task 9's scope.
make check-templates passes with zero warnings. The CLI-rendered PDF is
A5 (148x210mm), 65 pages -- 2 pages of title/contents plus exactly one
page per week (63), verified with no overflow.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Ran the round-2 hardened check_citations.py against lang/la.ini and fixed
every WRONG and MALFORMED finding. Baseline before this task: 12 WRONG,
42 CANNOT VERIFY (round-1 tool). After the round-2 tool alone (data
unchanged): 9 WRONG, 10 MALFORMED, 1 CANNOT VERIFY -- the rarity rule
cleared 41 of the 42 CANNOT VERIFY entries by itself, as expected. After
this cleanup: 0 WRONG, 0 MALFORMED, 0 CANNOT VERIFY, 292 citations checked
(up from 272 -- several wide ranges became more granular, individually
verified citations).
What changed, all in comments, no `key = value` entry touched:
- Three genuine wrong citations found and corrected: advent's own
citation was pointing at christmastide's real heading (LT.txt:8631,
"Tempus Nativitatis") 22 lines off from its own (LT.txt:8609) --
christmastide had never had a working citation of its own at all, the
right line sitting unused inside advent's corrective note. Restructured
so each entry cites its own real line, including giving
time-after-epiphany its own citation (LT.txt:8668) for the first time.
- Ten MALFORMED wide ranges (introduced by round 1's own tolerance
removal, never capped until round 2) replaced with precise per-entry
citations -- mostly comma lists of exact bare line numbers, since each
TOC section lists one heading per line; two are legitimate multi-line
wraps kept as capped explicit ranges (a 2-line Nativity-octave heading
split by an unrelated saint's day; Christ the King's own in-body heading
split across a page-number line).
- Six citation-shaped substrings that were never genuine provenance
claims lost their "LT.txt:" prefix (now read "line NNNN"), each with an
inline note explaining why: two were corrective prose quoting a
historical WRONG value ("previously cited LT.txt:8631/12459, which
is..."), three were contextual pointers to a NEARBY but different
heading used for explanation, and one discloses an unmodelled alternate
wording. None of these ever claimed to be this entry's own heading;
writing them as "LT.txt:N" only let the checker mistake documentation
for a claim.
- Two genuinely correct citations left permanently unable to pass an
automated word-overlap check, for reasons orthogonal to correctness
(disclosed in check_citations.py's own docstring as an accepted
trade-off) also lost their "LT.txt:" prefix, each verified by hand and
noted as corroborating rather than primary: class-1..4's "classis" (the
only distinctive word in "I classis" etc., 500+ occurrences across
LT.txt -- RG 8 is the primary source); Corpus Christi's and Holy Name's
own TOC lines, both abbreviated ("Ss.mi"/"Ss.mae") where every entry
below spells the same title out in full, and neither has a spelled-out
occurrence anywhere else in this partial 2006 web-capture transcription
to cite instead (Holy Name also has a stronger primary source already:
temporal_ef.ml's own scan-verified string).
No rule was weakened to reach zero: every de-prefixed reference was
verified by hand against the transcription first, and none of them was
ever wrong -- each was either documentation, context, or evidence the
checker's own disclosed word-overlap/rarity design cannot confirm.
Claude-Session: https://claude.ai/code/session_017ZBxCCRM2ojnBupp3SBxV9
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Round 1 hardened check_citations.py against its own self-poisoning bug;
a review defeated it again. Five fixes, in the order they were found:
1. PATTERN silenced a whole comment block, not just the entry it was
attached to -- a wrong citation on a DIFFERENT, unmarked entry in the
same block (e.g. [season]'s own back-to-back trailing-comment style)
was never checked at all. Fixed by scoping PATTERN with the identical
leading/trailing pooling rule citations already use: an entry is
excluded only by its own marker, never a neighbour's.
2. Explicit per-citation ranges (introduced in round 1 to replace a
blanket +-2-line tolerance) had no upper bound, reintroducing the same
defect at a much larger radius (LT.txt:8600-8650 passed if the text
appeared anywhere in fifty lines). Capped at MAX_RANGE_WIDTH (3 lines);
anything wider is reported MALFORMED, naming the entry and the width,
instead of silently accepted.
3. The "pool too thin to verify" gate counted words, not rarity -- it
flagged 11 genuinely correct citations (short Latin hagionyms with only
one non-stopword) CANNOT VERIFY, while a match on nothing but "classis"
(507 occurrences) passed freely alongside three siblings. Replaced with
a frequency table over the whole LT.txt corpus: a token's evidence is
1/(times seen), an item's evidence is its single rarest matched token
(not a sum -- summing would let several merely-common words add up to
"enough" between them, the same shape as the self-poisoning bug).
4. "LT.txt:12,459" (a comma typo for one number) parsed as two unrelated
bare citations, 12 and 459, either of which could coincidentally match
while the intended line was never checked. Detected as a
thousands-separator-typo shape (a 1-2 digit token immediately followed
by an exactly-3-digit one -- the only way a real LT.txt line number,
which never exceeds 5 digits, splits under one comma) and rejected as
malformed.
5. The self-test suite overstated its own coverage: of round 1's seven
fixture cases, only two actually failed against the pre-round-1 script.
Every test is now labelled REGRESSION or CHARACTERISATION, each
verified by direct replay against the named prior version rather than
asserted -- 14 of 33 are genuine regression tests.
Both of the review's own defeats (block-wide PATTERN silencing, the
50-line range) are reproduced as dedicated fixtures and confirmed caught;
both are also confirmed to slip through the pre-round-2 tool unchanged.
Claude-Session: https://claude.ai/code/session_017ZBxCCRM2ojnBupp3SBxV9
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The view's name is now the RESOLVED display string and slug is untouched,
so machine formats carry both -- a script keeps the stable key, a human
reads the name.
name is a plain string, not a lang-keyed object. That removes the
shadowing hazard outright: a dotted {{name.la}} used to fall back
WHOLESALE to the enclosing month's name.la and print Ianuarius on every
unnamed day, which is how a printed booklet came to show the month where
the feast belonged.
weekday, season, rank and colour all gain localised companions, because a
calendar in a language needs more than feast names, and templates gain a
term vocabulary so fixed strings need no template edit to translate.
Asserted over a whole year: no day renders its slug as its name.
Beyond the brief's own code sample:
- comm_value's own name is now resolved through the same lang.celebration
table too (not only the observed day's), because Task 8's own ordo
template interpolates a plain {{name}} inside {{#comms}} -- an Obj there
would render silently blank. A commemoration slug without Latin
coverage still degrades to the slug, same as everywhere else in this
system; that is a lang/la.ini DATA gap (113 of 327 sanctoral slugs,
measured), not a regression this task introduced.
- bin/main.ml's emit/table/publish call sites needed ~lang to compile at
all, which is collateral from the of_days signature change, not this
task's own file list. Rather than pass Lang.raw and ship the very
slug-as-name defect this branch exists to fix, they load the shipped
Latin table by the same probe order data_dir() already uses -- a
deliberate, commented BRIDGE that Task 6 replaces wholesale with real
--lang/--raw/config resolution. bin/dune gained colitur_naming
accordingly.
- test/cli.t needed two related fixes to stay green: the CSV header/row
example, and a table/LaTeX escaping demonstration that relied on the
kernel's own English name for Sts Peter & Paul -- gone from the view
now that name resolves through lang tables only, and the Missal's own
Latin spells the feast with et, never an ampersand. Escaping itself is
still proved live on 2035 data in test_emit.ml.
- Both schemas gained the new day/week/top-level keys (season_name,
weekday, rank_name, colour_name, term, weekday_headings, month_num,
month_name), not only the name shape change; schema/colitur-v1.xsd
verified against real emitted XML via xmllint (make check-schema).
Render/golden's 9 cases (the shipped ordo/grid templates, all six
flavours) now fail as expected: their old {{name.la}} / {{#name}}...
idiom finds nothing on a plain string. That is Tasks 8/9's own scope to
rewrite, per the plan's own pre-flight conflict scan -- not fixed here,
and not silently pinned by regenerating goldens off broken output.
495 tests run (490 + 5 new), 486 pass; the 9 failures are exactly
Render/golden's ordo/grid cases.
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Sanctoral names are transcribed from the Missal's own calendarium and
kept in the GENITIVE, as the Missal prints them -- noted in the file so
nobody corrects them to the nominative.
English reuses the 327 names already in data/ef/sanctoral.sexp rather
than retyping them, and declares fallback = la, so an untranslated day in
an English booklet shows Latin rather than a slug. The test asserts the
FALLBACK works rather than that en.ini is exhaustive: that is what makes
a partial translation shippable from its first line.
Coverage now demands a name for every slug the engine can emit across
2020-2045, temporal and sanctoral alike.
|