ODR enrichment lives in the markdown; HTML is generated from it every build
Mechanism updated 2026-05-29 (see ADR-0025). The decision below stands — ODR content (incl. its
```mermaiddiagrams) lives in the markdown and HTML is generated every build, nothing committed. Only the mechanism changed: ODRs now render through the Astroodrcontent collection (render(entry)→<Content/>, the same path as the manual) rather than the bespokemarkedgenerator.generate-odr-html.mjsand theset:htmlserving are retired;```mermaidfences become<div class="mermaid">via theremarkMermaidFenceplugin. The “Implementation sketch” below describes the original (now-retired)markedapproach and is kept for the record.
Context and Problem Statement
Current implementation amendment — 2026-09-05
The owner requested local, renumbered modelling decisions and distribution through
the normal website build. The current implementation uses the Astro odr content
collection and render(entry); the original implementation sketch below is historical.
scripts/gen-odr-registry.mjs derives the listing, navigation and search metadata
from canonical top-level docs/ontology/odr/ODR-*.md files. Existing short display
titles are preserved. src/integrations/generate-odr-sources.mjs regenerates that
registry and copies those Markdown sources to /decisions/odr/ during Astro setup.
The normal CI build therefore packages both rendered pages and downloadable sources
in dist/, without a remote source-project dependency. Relative decision links
are resolved to site pages in the shared Markdown pipeline.
New local adaptations follow the living-decision conventions in docs/adr/README.md:
status and dated amendments expose authorised changes; they do not retrospectively
claim implementation or external council ratification. Existing historical source
records and their identifiers retain their original context. This amendment replaces
the universal immutability wording for new local adaptations only.
Confirmation for this amendment is source inspection and static syntax checks. Build, browser and test execution remain deferred at the owner’s request; accepted status is retained rather than claiming complete implementation validation.
ADR-0023 chose to freeze
each ODR’s markdown, author Mermaid diagrams into a separate committed HTML
artefact (docs/ontology/odr/_html/ODR-NNNN.html), and serve that frozen file
forever (produce-once / freeze / commit / never-regenerate). Two pilot artefacts
(ODR-0001, ODR-0005) were produced this way.
In practice that model has a structural flaw: the enrichment is divorced from the canonical record. The diagrams live only in the HTML; the ODR markdown — the artefact people actually read, review, and diff in git — does not contain them. The HTML and the markdown drift apart by construction, and the “single source of truth” is split across two files with no mechanical link between them.
The Council’s intent in enriching ODRs is to make the decision record read visually. That value belongs in the record (the markdown), not in a derived presentation layer. This ADR reverses ADR-0023’s locus-of-enrichment decision.
Decision Drivers
- Single source of truth. The diagrams should live where the decision lives — in the ODR markdown — so the canonical record is self-contained and the git diff shows the enrichment.
- No derived-artefact drift. Committing generated HTML (ADR-0023) is the classic anti-pattern; the markdown and HTML diverge silently.
- Reuse the existing render path.
client.jsalready renders<div class="mermaid">client-side, now with lightbox + clickable nodes (ADR-0022). ODR pages should inherit it for free. - Immutability. Accepted ODRs are frozen (ODR-0001 §Immutability). Any enrichment must not constitute a substantive amendment.
- Build cost is negligible. Converting 18 markdown files to HTML on each build is trivial; freezing buys nothing.
Considered Options
- A — Render the ODR markdown directly via a content collection (like the manual). Astro renders MD→HTML natively; no generator. Rejected here only because it gives less control over the curated page header (provenance note, meta pills, heading anchors) than a dedicated generator.
- B — Generate HTML from the enriched markdown and commit it (frozen). Keeps ADR-0023’s in-git artefact but derives it from the MD. Rejected: reintroduces a committed derived artefact that can drift, for no benefit once the MD is canonical.
- C — Enrich the markdown; generate HTML from it every build, gitignored (chosen). Diagrams are authored into the ODR
.md. A build-time generator converts each.md→ an HTML fragment insrc/generated/odr/(gitignored, regenerated every build); the page serves it viaset:html. Nothing generated is committed. - D — Keep ADR-0023 (author + commit + freeze HTML). Rejected: the enrichment is divorced from the canonical record (the motivating flaw).
Decision Outcome
Chosen option: C — enrich the markdown, generate HTML every build, do not commit
the output. The ODR markdown is the single source of truth and carries its own
Mermaid diagrams. A build-time Astro integration (mirroring the ADR-0021 report
generator) converts each ODR .md to an HTML fragment under src/generated/odr/
(gitignored); /modelling/odr/<id> serves the fragment via set:html; the
diagrams render client-side through client.js (clickable + lightbox per
ADR-0022). This supersedes ADR-0023: the locus of enrichment moves from a
committed HTML artefact to the canonical markdown, and the refresh policy moves
from freeze-forever to regenerate-every-build.
Immutability reconciliation
Adding diagrams to an accepted ODR’s markdown edits a record that ODR-0001 calls frozen. This is permitted under a narrow, explicit boundary:
- Illustrative enrichment is non-substantive. A diagram that visualises content already present in the prose (the options considered, the chosen outcome, a consequence/dependency graph) asserts nothing new and changes no decision. It is presentational — comparable to formatting or anchors — not an amendment.
- Substantive change still requires a new ODR. Any diagram (or text) that would assert a claim, relationship, or outcome not already in the record is out of scope for enrichment and must go through a superseding ODR. The enrichment must be faithful to the existing record, never extend it.
This boundary is the authoring contract for the enrichment work (one agent per ODR): diagrams must derive strictly from the existing decision text.
Implementation sketch
Indicative; the implementing session owns the detail.
- Authoring — diagrams are added to
docs/ontology/odr/ODR-NNNN-*.mdas plain```mermaidfenced blocks (2–4 per ODR), authored via the/diagrammingskill, illustrating the decision faithfully (options → outcome → consequences; supersession/dependency graph). - Generator —
src/integrations/generate-odr-html.mjs, anastro:config:setupintegration. For each ODR: read MD, liftstatus/date/kindfrom frontmatter- the registry, inject a provenance header +
<h1>ODR-NNNN — Title</h1>+ meta pills, render the body withmarkedusing a custom code-renderer that emits```mermaidblocks as<div class="mermaid">…</div>, rewrite intra-ODR.mdlinks viaODR_LINK_MAP, and writesrc/generated/odr/ODR-NNNN.html.
- the registry, inject a provenance header +
- Serving —
src/pages/modelling/odr/[id].astrogetStaticPathsnow covers all ODRs (every ODR has a generated fragment), read viaset:html. The listing links all ODRs; an “enriched” indicator may flag which carry diagrams. - Gitignore —
src/generated/is already gitignored; the two committed pilot artefacts underdocs/ontology/odr/_html/are removed from git (their diagrams are back-ported into ODR-0001/0005 markdown).
Consequences
- Good, because the canonical ODR markdown is self-contained and richer — the diagrams are in the record, visible in the git diff and to anyone reading the
.md. - Good, because there is no committed derived artefact to drift; the build regenerates HTML from the one source.
- Good, because ODR pages reuse the existing
client.jsMermaid render path and inherit ADR-0022 clickable + lightbox behaviour with no new machinery. - Good, because turning the generator on makes all 18 ODRs live pages immediately (rendered from MD); diagram enrichment is then purely additive.
- Bad, because it relaxes strict ODR immutability to admit illustrative diagrams. Mitigation: the narrow non-substantive boundary above; substantive change still needs a superseding ODR.
- Bad, because the enrichment is one-time authoring effort (16 remaining ODRs × 2–4 diagrams). Mitigation: one agent per ODR via the
/diagrammingskill. - Neutral, because it discards ADR-0023’s “frozen committed artefact in git” property — the markdown is now the frozen, diffable record instead.
Confirmation
- Each ODR’s diagrams live in its
docs/ontology/odr/ODR-NNNN-*.md(not in HTML);grep -l mermaidover the corpus matches the enriched set. - No generated ODR HTML is committed (
src/generated/is gitignored;docs/ontology/odr/_html/no longer tracked). /modelling/odr/<id>renders for every ODR, with its Mermaid diagrams rendering client-side (clickable + lightbox where ADR-0022 applies).- A clean build regenerates every fragment from markdown; no manual step.
- Enrichment diagrams are faithful to the existing record (no new claims) — the non-substantive boundary holds.
More Information
- Supersedes: ADR-0023 — moves enrichment from a committed frozen HTML artefact to the canonical markdown, and the refresh policy from freeze-forever to regenerate-every-build.
- Reuses: the ADR-0021 report-generator pattern (
marked+astro:config:setup+set:html) and the ADR-0022 clickable/lightboxclient.jsrender path. - Site integration anchor: ADR-0015.
- Immutability basis: ODR-0001 §Immutability — self-amendment is a new ODR; this ADR scopes a non-substantive illustrative-enrichment carve-out.
- Enrichment tool: the
/diagrammingskill — Cagle palette,accTitle/accDescr, validated Mermaid.
Comments
Loading comments…
Sign in to post a comment