Skip to main content

verum doc-render — Auto-paper documentation generator

A Verum corpus IS a formal proof AND a paper draft. Pre-this-tool a project had to maintain paper.tex alongside the .vr corpus — two sources of truth, manual sync risk across the formal proof + the human prose. verum doc-render makes the corpus the single source of truth: it walks every public @theorem / @lemma / @corollary / @axiom declaration, projects it into a typed record, and emits Markdown / LaTeX / HTML directly from your .vr files.

What you get

  • LaTeX — paper draft compatible with arXiv / Zenodo templates. Each declaration uses the canonical theorem / lemma / corollary / axiom environment with a cross-referenceable \label. Axioms emit no \begin{proof}.
  • Markdown — CommonMark-friendly web output with a top-of-page TOC, anchor IDs, numbered proof-step lists, and inline closure-hash callouts.
  • HTML — semantic <article class="verum-item verum-{kind}"> per declaration, with anchor IDs and a top-level navigation. Drop into a static-site generator.
  • DOT / JSON citation graph — every theorem's transitive citation closure as a Graphviz digraph (or edge-list JSON).
  • Broken-cross-reference audit — CI gate that fails non-zero on any dangling apply X; / \ref{X} target.

Subcommand reference

verum doc-render render [--format md|markdown|tex|latex|html] \
[--out <PATH>] [--public]
verum doc-render graph [--format dot|json] [--public]
verum doc-render check-refs [--format plain|json] [--public]

Format aliases:

  • mdmarkdown
  • texlatex

--public restricts the corpus to public-visibility declarations only (the default emits everything reachable, including project-internal lemmas).

--out <PATH> writes the rendered corpus to disk; without it the output goes to stdout.

render

Renders the entire corpus as a single document. Markdown output example:

# Verum corpus — formal statements

Auto-generated from 142 declaration(s). Each statement carries a
kernel-cert hash; readers can re-check via `verum cache-closure decide`.

## Table of contents

- [theorem — yoneda_full_faithful](#theorem-yoneda-full-faithful)
- [lemma — succ_pos_lemma](#lemma-succ-pos-lemma)
- ...

---

## <a id="theorem-yoneda-full-faithful"></a>Theorem `yoneda_full_faithful`

The Yoneda embedding `Y : C -> [C^op, Set]` is fully faithful.

**Signature:**

```verum
theorem yoneda_full_faithful(...)
```

**Statement (ensures):**

- `forall (X Y: C). hom(X, Y) ≃ Nat(Y(X), Y(Y))`

**Proof:**

1. `intro`
2. `apply yoneda_lemma`
3. `auto`

**Cites:** [`yoneda_lemma`](#ref:yoneda_lemma)

**Framework citations:**

- *lurie_htt*: HTT 6.2.2.7

**Closure hash:** `7b2a90c4…` (re-check with `verum cache-closure decide yoneda_full_faithful …`)

*Source:* `src/categories/yoneda.vr:42`

LaTeX output for the same item:

\begin{theorem}[yoneda\_full\_faithful]
\label{theorem:yoneda_full_faithful}
The Yoneda embedding ...

\(\text{forall (X Y: C). hom(X, Y) ≃ Nat(Y(X), Y(Y))}\)
\end{theorem}
\begin{proof}
\begin{enumerate}
\item \texttt{intro}
\item \texttt{apply yoneda\_lemma}
\item \texttt{auto}
\end{enumerate}
\end{proof}
\textbf{Framework citations:} \emph{lurie\_htt}: HTT 6.2.2.7
\textit{Closure hash:} \texttt{7b2a90c4...}

HTML output ships the corresponding <article> blocks with anchor IDs matching the LaTeX \labels and Markdown anchors — stable cross-references work across all three formats.

graph

The citation graph: citing → cited. Nodes are coloured by item kind:

  • theorem → light blue
  • lemma → light green
  • corollary → light yellow
  • axiom → light grey
$ verum doc-render graph --format dot
digraph corpus_citations {
rankdir=LR;
node [shape=box, style=filled];
"yoneda_full_faithful" [fillcolor=lightblue, label="yoneda_full_faithful (theorem)"];
"yoneda_lemma" [fillcolor=lightgreen, label="yoneda_lemma (lemma)"];
"yoneda_full_faithful" -> "yoneda_lemma";
}

Pipe to Graphviz to produce SVG / PNG:

verum doc-render graph --format dot | dot -Tsvg -ocitations.svg

JSON output is an edge list — useful for custom visualisation tooling:

{
"schema_version": 1,
"item_count": 142,
"edges": [
{ "from": "yoneda_full_faithful", "to": "yoneda_lemma" },
{ "from": "yoneda_full_faithful", "to": "presheaf_completeness_lemma" }
]
}

check-refs

Audits broken citations: every apply X; in a proof body whose X doesn't resolve to another corpus item is a dangling reference. CI-friendly: non-zero exit on any broken citation.

$ verum doc-render check-refs
✗ Found 2 broken cross-reference(s):
yoneda_full_faithful → presheaf_completeness_lemma
msfs_theorem_10_4 → ac_oc_lemma

JSON output:

{
"schema_version": 1,
"item_count": 142,
"broken_count": 2,
"broken": [
{ "citing_item": "yoneda_full_faithful",
"broken_target": "presheaf_completeness_lemma" },
{ "citing_item": "msfs_theorem_10_4",
"broken_target": "ac_oc_lemma" }
]
}

Reproducibility envelope

Every rendered statement carries an optional closure hash — the same hash the cache-closure cache uses. Readers of the rendered paper can run:

verum cache-closure decide yoneda_full_faithful \
--signature "<copied from paper>" \
--body "<copied from paper>" \
--cite framework_lurie_htt

…to confirm the statement they're reading is the statement that was kernel-checked. This eliminates the LaTeX / Verum dual-source risk: there is no possible drift between the rendered claim and the kernel artefact, because both come from the same fingerprint.

Citation extraction

The renderer extracts citations from proof bodies via name-shape matching:

  • Identifiers ending in _lemma, _thm, _theorem, _axiom.
  • Identifiers starting with lemma_, thm_.

False negatives are acceptable (the citation graph under-counts rather than over-counts). False positives surface as broken refs in the validator (non-resolving names). This means the convention of naming your lemmas with a recognisable suffix or prefix is worth following — your proofs auto-document themselves.

Visibility filtering

--public is the most common production option: it restricts output to declarations marked public. Project-internal lemmas remain in the corpus (your IDE still sees them) but don't appear in the published paper.

public theorem yoneda_full_faithful(...)
ensures /* ... */
proof by /* ... */;

// Internal helper, not exported to the paper draft.
lemma yoneda_internal_step(...)
ensures /* ... */
proof by /* ... */;

Typical CI workflow

# Pre-merge gate: broken citations fail the build.
verum doc-render check-refs

# On release: regenerate paper artefacts.
verum doc-render render --format latex --out paper/sections/auto.tex --public
verum doc-render render --format html --out site/theorems.html --public
verum doc-render graph --format dot --public | dot -Tsvg -opaper/figs/citations.svg

The release workflow can be wired into the same job that runs verum verify --closure-cache so every CI run produces a re-checked paper draft.

Cross-references

  • Tactic catalogue — every combinator carries a stable doc_anchor; the renderer uses these for cross-format-stable hyperlinks when proof steps are embedded.
  • Incremental cache — the closure-hash that powers the reproducibility envelope.
  • Verification → proof corpora — corpus-level conventions (file layout, framework attribution, proof-honesty).
  • Verification → proof export — orthogonal export pipeline (statement-only certificates for Coq / Lean / Dedukti / Metamath).