The ONE renderer for a project's surface goldens.
A surface golden is a document generated from a source scan, listing what the code declares, gated so that it cannot disagree with the code: CI regenerates it and byte-compares, and a difference fails the build. The document therefore cannot lie — which is the only property that makes a generated document worth reading three weeks later.
Each scanner builds a plain data spec and hands it here. The renderer IS the convention: notation lives in one place, so per-file dialects cannot form — and, now that more than one project renders goldens, per-project dialects cannot either.
The shape a golden always has
- Header block — line 1
# <NAME>; line 2 the one-line:purpose; line 3 the machine-parseable attributionGenerated bymix <task> --write· gate<gate>(HARD|ADVISORY) — do not edit; a drift FAILS the gate. Domain:prose(semantics, class ladders) FOLLOWS the block, unconstrained. - Stats line(s) — each
**<lead>** · <label> <n> · …(seestat_line/2); every golden carries at least a row count. - Tables — first column = the catalogued item (backticked); last column
conventionally
Locus. Cells are TYPED (cell/0) so the renderer — not each caller — owns the backtick/atom/locus/—notation. Optional grouping:## <heading>with per-group tables.
No timestamps or VCS data are ever emitted. A golden is a stable function of source; a date makes it drift against itself on a quiet day, and a gate that cries wolf gets disabled. Dates belong in a report, never here. This is a lesson paid for once already in the project this came from, and it is the one rule most likely to be re-broken.
What this does NOT know
The evidence ladder — whether a thing is model_checked, static_gate, property,
unit_test or NOTHING — is the calling project's vocabulary, and differs between them.
So does what a surface is. This renders typed cells; it never interprets them.
Determinism
render/1 is a pure function of its spec and is invariant under the input order of a row
map's keys (cells are pulled in :columns order) and under the input order of the row
list (rows are sorted by :sort, default the first column's natural key). So two specs
that differ only in such orderings render identical bytes — the property every drift
gate rests on, and the reason it is asserted in this package's tests rather than
assumed.
Extracted from
agentronic'sMaatronic.SourceScan.Golden, where ten goldens have used it in production. Behaviour is unchanged; only the prose was rewritten for a home that serves more than one project.
Summary
Types
A typed table cell — the renderer formats it, so notation is central, not per-caller
A ## <heading> grouped table. :columns overrides the spec's top-level columns for this group —
for a golden whose sub-tables have different shapes (e.g. AUTHZ's boundary ops vs runtime seams).
One table row: column-name => cell. Order-independent (cells pulled in :columns order).
A surface-golden spec. :groups and :rows are mutually exclusive — supply :groups for a
grouped golden (SPEC_COVERAGE), :rows for a flat one. :sort is a row → sortable key (rows
are sorted within each group); it defaults to the first column's natural key.
Functions
A natural sort key for an identifier-ish string: alternating text / integer chunks, so Foo.9
sorts before Foo.10. The renderer's default row order when a spec supplies no :sort.
Render spec to golden markdown. Pure; order-invariant per the moduledoc.
A stats line as DATA (stat/0): lead + dims + the rendered text. Each golden
passes these in spec.stats; a cross-surface report reads lead/dims from the same value, so the
report's counts round-trip the golden's stats line by construction.
Build the stats line STRING: **<lead>** · <label> <value> · …. lead is the pre-bold
summary ("963 sections", or a label like "Freshness (of tagged validations)"); dims is a list
of {label, value} (a bare label is a flag). Prefer stat/2 in a spec so the counts stay data.
Types
@type cell() :: {:code, iodata()} | {:atom, atom()} | {:locus, String.t() | nil, pos_integer() | nil} | {:version, String.t() | nil} | {:raw, iodata()} | :absent | nil | binary()
A typed table cell — the renderer formats it, so notation is central, not per-caller:
{:code, io}→`io`(the backticked-item rule){:atom, a}→`:a`(atoms always backticked, e.g. an effect class:local){:locus, file, line}→`file:line`(anilfile ⇒—; anilline drops the:line, so a hashed-locus surface passes{:locus, file, nil}for a bare-path Locus){:version, hash}→`hash`(a content version —Surfex.SourceScan.definition_hash/1's 8-hex output; anilhash ⇒—). Named rather than a bare{:code, …}so the content-version notation lives in one place across every golden'sVersioncolumn.{:raw, io}→ verbatim (escape hatch for a composite cell like`unit_test` · tagged):absent/nil→—(the absent-value glyph)- a plain binary → verbatim
A ## <heading> grouped table. :columns overrides the spec's top-level columns for this group —
for a golden whose sub-tables have different shapes (e.g. AUTHZ's boundary ops vs runtime seams).
One table row: column-name => cell. Order-independent (cells pulled in :columns order).
@type spec() :: %{ :name => String.t(), :purpose => iodata(), :task => String.t(), :gate => String.t(), :hardness => :hard | :advisory, :columns => [String.t()], optional(:prose) => iodata(), optional(:stats) => [stat()], optional(:notes) => iodata(), optional(:groups) => [group()], optional(:rows) => [row()], optional(:sort) => (row() -> term()) }
A surface-golden spec. :groups and :rows are mutually exclusive — supply :groups for a
grouped golden (SPEC_COVERAGE), :rows for a flat one. :sort is a row → sortable key (rows
are sorted within each group); it defaults to the first column's natural key.
One stats line as DATA: the bold :lead, its :dims ({label, value} pairs / bare flags), and
the rendered :text. Built by stat/2 so the renderer AND any cross-surface report read the
same counts — the report never parses the markdown.
Functions
A natural sort key for an identifier-ish string: alternating text / integer chunks, so Foo.9
sorts before Foo.10. The renderer's default row order when a spec supplies no :sort.
Render spec to golden markdown. Pure; order-invariant per the moduledoc.
A stats line as DATA (stat/0): lead + dims + the rendered text. Each golden
passes these in spec.stats; a cross-surface report reads lead/dims from the same value, so the
report's counts round-trip the golden's stats line by construction.
Build the stats line STRING: **<lead>** · <label> <value> · …. lead is the pre-bold
summary ("963 sections", or a label like "Freshness (of tagged validations)"); dims is a list
of {label, value} (a bare label is a flag). Prefer stat/2 in a spec so the counts stay data.