Skip to content

Locale / render / money / logging

The cross-cutting kernel services the pipeline and packs read throughout. None is document-specific; a pack composes them.

Money (core/money.py)

money, pct, sum_money — all Decimal with ROUND_HALF_UP, never float. This is what "cent-exact" means: totals are computed and reconciled in exact decimal, carried through the golden record as strings, and stored as decimal128 in the artifact/Parquet. A record that doesn't reconcile refuses to exist, so a rounding drift can never reach a document or the golden set (① realistic).

Locale (core/locale/)

Language / Locale / Currency enums, a table-driven formatting module (number, currency, and date formats per locale), and a LabelRegistry (printed vocabulary per language). The kernel's Jinja filters read locale, currency, and labels from the render context, so templates never format explicitly and a new language is a table entry, not code.

Render & fonts (core/render/, core/fonts/)

core/render/environment.py builds the Jinja environment with the locale-aware filters and exposes render_record(pack, record) = render_template(pack.template_root, pack.archetype_for(record), pack.build_context(record)) — the one call the renderer makes into a pack. core/fonts/ owns the semantic font stacks and the bundled OFL fonts embedded as base64 @font-face data-URIs, so a chosen typeface renders byte-identically on any host (no system-font drift between a laptop and Cloud Run). Packs supply only font selection policy.

Selection (core/selection.py)

Selection is the vocabulary for constraining what a run slice may draw from — locales, companies (a list or "use N"), archetypes, business types, a condition mix, a wear range, goods receipts, an issue-date window. The kernel carries it but does not interpret it: a pack resolves it against its roster and raises UnsupportedConstraint for anything it can't honour (a french slice that emits English is a wasted run nobody notices). It is surfaced twice — as docsynth generate flags and as a --selection-file YAML block — behind one parser.

Logging (core/logging.py)

structlog configuration: console rendering at a terminal, JSON to a pipe or Cloud Run (with Cloud Logging severity/message fields), and contextvars binding so a run id / unit index thread through log lines without passing a logger everywhere.

Registry & enums (core/registry.py, core/enums.py)

registry.py discovers packs through the docsynth.packs entry-point group (register_pack, get_pack, available_packs) — so a third-party pack ships as docsynth-yourpack and is found without a code change. enums.py holds the kernel vocabularies every pack shares: Jurisdiction, DocumentCondition, RunState, WorkUnitState.

The two contracts (DocumentPack, GoldenRecord, ContentCapability) live alongside these and are covered on the Kernel ↔ pack contract page.