Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

82 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

renderfact

One full-candor source. Many governed renders.
Audience-gated projections, styled DOCX, diagrams, provenance, and fail-closed QA gates,
from one docs-as-code toolchain.

CI Demo render PyPI Python versions License: MIT

Quickstart · How it works · Capabilities · Demo · Templates · Docs site · Contributing


Write a document once, with everything in it. renderfact projects it per audience (clearance and disclosure gating at the preprocessor level, so excluded content never reaches any output), renders it through pinned engines (styled DOCX, archival PDF via typst, sendable .eml, mermaid/d2/ ArchiMate diagrams, editable draw.io/Visio), stamps every artifact with provenance, and round-trips reviewer edits back toward the source. The name is a double meaning: render + artefact (what it produces), render factory (what it is).

Status: active development, MIT (see the PyPI badge above for the current version). Real pipelines consolidated into one OSS toolchain; the capability matrix below says exactly what runs today vs. what is roadmap.

Quickstart

One markdown source rendered to a branded A4 PDF, cycling the base and financial theme variants and an en/nl-BE locale

One markdown source → a branded, layout-precise PDF. Same document, cycling the base and financial theme variants and an en / nl-BE locale (note the recomputed, reconciled figures).

git clone https://github.com/Wombat164/renderfact && cd renderfact
pip install -e ".[dev]"        # editable install is the supported mode; wires the render CLI
pytest -q                      # the full suite, green from a clean clone

# taste it on the bundled demo (a fictional rail operator's procurement dossier):
python render.py project demo/source/signalling-it-refresh.md \
    --profiles demo/profiles.yaml --all --output-dir demo/renders
python render.py gate demo/source --stages vale,uids   # fail-closed QA on the demo source
python render.py doctor                                 # what your host has vs. tools.lock

# render the branded governance/financial PDF above (needs typst + pandoc):
python render.py pdf demo/source/agm-minutes.md \
    --brand demo/skin/brand.yaml --variant financial --locale en \
    --org "Meridian Rail Infrastructure" --title "AGM Minutes 2026" --date 2026-03-18

The three projected renders differ exactly as the profiles dictate: internal-full keeps everything, bidder-pack keeps commercially shareable content, public-tender carries no internal material, no provenance, and no projection stamp. pip install renderfact from PyPI installs the library layer; the CLI's per-mode pipelines expect the repo checkout.

How it works

Mark blocks in ordinary markdown with the audience they belong to:

The programme starts in Q3.                       <- everyone sees this

::: {.block clearance="internal"}
Budget ceiling before negotiation: 4.2M.          <- internal renders only
:::

::: {.block releasable="bidders" detail="true"}
Interface spec, full protocol tables.             <- bidders, full-disclosure profiles only
:::

Profiles (your own YAML: ladders and audiences are consumer-defined, the engine ships no vocabulary) decide what survives per render. The same source then feeds every output family, and every artifact carries hidden provenance (source identity, content version, git commit) so edited copies can be re-ingested, diffed, and routed back: unless the profile says it is externally bound, in which case provenance is stripped.

What's in the box

Capability
Author + project Audience/clearance/disclosure projection render project
Styled DOCX with generic house style + field numbering render docx
Layout-native branded PDF via typst (archival/tagged; statement tables), no LibreOffice render pdf
Plain-text, sendable RFC822 .eml with a skin signature block render eml
Diagrams (mermaid, d2, the layered-stack archetype from plain YAML or an ArchiMate Exchange File) with pre-render lint + visual-QA metrics render diagram
Brand tokens to per-engine themes render tokens
Template import: derive a skin from any branded DOCX, incl. per-style fonts + a structural scan of an accompanying guidance doc render import-template
Genre template pack (executive summary, briefs, pitches, purchase request) with rendered exemplars templates/
Project registry (manifest, render-ledger, git facts) + a built-in template library render projects / render templates
Round-trip Hidden provenance across DOCX/XLSX/PPTX render provenance
Mechanical DOCX re-ingestion: verdicts, reviewer-edit report, fast-forward apply, embedded-doc triage render reingest
Document-edit decision capture (contextualize a reingest diff; deterministic first, LLM past a gate) render contextualize
Editable-diagram round-trip (draw.io lead adapter; stable IDs; semantic/style/layout routing) render drawio
Editable-diagram round-trip, Visio adapter (NameU anchors; OPC provenance; optional vsdx lib) render vsdx
Diagram-edit decision capture (deterministic first; LLM only past a confidence gate) render decision-capture
Vision-review with a D16 gate (deterministic svg-metrics verdict first; LLM only past a threshold) render copy-paste vision-review
D16 gate telemetry: escalation-rate stats + storm detection from an opt-in decision log render gate-stats
Gate + verify Fail-closed QA chain: Vale, lychee (offline), veraPDF (PDF/A + PDF/UA), duplicate-uid detection render gate
Post-render QA: leak probes, table geometry, paragraph weight render qa
Host-vs-lock drift report (never fails: that is the container's job) render doctor
Operate Dual-mode LLM steps: your harness or plain copy-paste, one schema render init-ai / copy-paste
Localhost HTTP API + thin reference UI render serve
Roadmap Slide decks, A2 posters; structured source editor (designed)

Why this exists

Strong prior art covers parts of this pattern; none covers the whole. The gap: source-vs-render disclosure gating + archival, accessible PDF targets + many output families from one source + provenance and round-trip, as a lightweight framework.

Prior-art comparison (what we borrow, what was missing)
System Licence Does well Doesn't
S1000D + s1kd-tools GPL-3.0 defence/aero technical pubs, data-module single source (CSDB) heavyweight; no clearance/disclosure projection; no decks/posters
DITA-OT Apache-2.0 one source to many formats via transformation types no audience/clearance gating; no PDF/UA+PDF/A guarantee; no decks/posters
NIST OSCAL + compliance-trestle Apache-2.0 compliance-docs-as-code; profile-as-projection data interchange, not human-facing styled render
GOV.UK tech-docs / govspeak OSS gov docs-as-code, live HTML HTML-centric; no projection gating; no archival PDF

We borrow DITA-OT's transformation-type abstraction, OSCAL's profile-as-projection, and S1000D's data-module discipline.

Architecture: generic core, private skin

The core is domain-neutral: any organisation supplies its own private skin (brand token values, reference templates, audience profiles, markings) and its content. The public core never contains domain content, and the bundled demo proves the split end to end.

your private config (skin)            renderfact (this repo, generic)
  brand.yaml values  ----------------> tokens/  (mechanism + neutral defaults)
  reference.docx     ----------------> container/ (engines, pinned)
  audience profiles  ----------------> render <mode> (one entry point)
  source corpus      ----------------> gates + QA -> governed artifacts
Repository layout
render.py    the single entry point: render <mode> [args...]
projection/  the projection engine: profiled fenced-div blocks -> one governed render per
             profile; consumer-defined ladders, preprocessor-level exclusion, fail-closed
docstyle/    generic DOCX house-style post-processor + field-based heading numbering
             (template-profile yaml, neutral defaults)
api/         stdlib HTTP API: step contracts + projection over localhost, opt-in /ui,
             openapi.json + /docs; loopback-Host/origin/path-jail guards
gates/       fail-closed QA chain (vale / lychee / verapdf / uids stages)
container/   OCI image + render wrapper + render-doc.sh + bundle-annex-linux.py + verify-pins.sh
lint/        diagram render harness + pre-render linters + visual-QA metrics + render_qa +
             the first LLM step contract (vision review)
tokens/      brand.yaml token mechanism + per-engine generators
contracts/   dual-mode LLM step mechanism: one schema for harness, copy-paste, and HTTP
roundtrip/   provenance (embed/extract/adopt/retarget/strip), source identity, DOCX
             re-ingestion, drawio round-trip
demo/        the fictional showcase: profiled source, profiles, skin, golden rules,
             committed rendered exemplars
docs/        architecture, decisions, roadmap, prior-art research (see docs/README.md)
tests/       fixture-based tests; fixtures built in-test, no committed binaries
tools.lock   pinned engine versions (the single source of truth the container asserts)
Full CLI reference
python render.py docx <source.md> [--pdf] [--qc] [--lint] ...    # markdown -> styled DOCX pipeline
python render.py project <src.md> --profiles <cfg.yaml> --all    # one source -> one render per profile
python render.py diagram <files...> [--formats svg,pdf]          # mermaid/d2 render harness
python render.py tokens [--brand path/to/brand.yaml]             # brand.yaml -> per-engine themes
python render.py import-template <corp.docx> [--check probe.md]  # derive a template profile from a DOCX
python render.py provenance embed|extract|adopt|retarget|strip . # hidden provenance operations
python render.py reingest <edited.docx> --source <md> [--apply]  # re-ingestion: report-only by default
python render.py drawio generate <graph.yaml> [--layout l.yaml]  # concept graph -> editable .drawio
python render.py drawio reingest <edited.drawio|.png> --source <g>  # classify + route hand-edits
python render.py vsdx generate <graph.yaml> [-o d.vsdx]          # concept graph -> editable Visio .vsdx
python render.py vsdx reingest <edited.vsdx> --source <g>        # classify + route Visio hand-edits
python render.py decision-capture --source <g> --reingest <j.json> # capture edit intent (deterministic+gate)
python render.py gate <files...> [--stages vale,lychee,verapdf,uids] # fail-closed QA chain
python render.py qa leaks|tables|paras|figs|all ...              # post-render QA (report-only default)
python render.py init-ai [--assistant claude|copilot|all]        # install harness-mode instructions
python render.py copy-paste <step> [--tier T] ...                # LLM step without harness or API key
python render.py serve [--port N] [--enable-ui] [--root DIR]     # localhost API + reference UI
python render.py doctor [--json]                                 # host tools vs tools.lock: warn only
python render.py container <podman-args...>                      # passthrough to the container wrapper

Each mode is a thin dispatcher to its own pipeline; tests/test_render_entrypoint.py covers the dispatch layer.

Container mode

Pinned engines (pandoc, typst, mermaid-cli, d2, marp, vale, lychee, veraPDF, LibreOffice) ship in one OCI image; verify-pins.sh asserts the build matches tools.lock, fail-closed. Native mode runs the same pipelines against host tools, with render doctor reporting drift instead.

cd container && ./build.sh
sudo podman run --rm localhost/renderfact:latest bash verify-pins.sh

Documentation

The documentation site (built with Quartz from wiki/, Diataxis-structured) is the reader-friendly entry: getting-started, how-to recipes, the command reference, and the architecture explanations.

In-repo, start at docs/README.md: the decision record (DECISIONS.md, D1-D22), the forward roadmap with adopt/imitate/build tags (ROADMAP.md), and the prior-art research passes.

Contributing

Contributions welcome: see CONTRIBUTING.md (test discipline, generic-core rule), SECURITY.md for private vulnerability reporting, and CODE_OF_CONDUCT.md. Licence: MIT; bundled engine licences in THIRD-PARTY-LICENSES.md.

About

Docs-as-code render framework: one full-candor markdown source to layout-precise branded PDF (typst) and governed DOCX + diagrams. Semantic governance/financial blocks, self-reconciling ledgers, locales, a fuzzy-gated LLM pipeline, provenance + QA gates, and a localhost HTTP render API.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages