Skip to content

Documentation Conventions

Living guidance for how documentation is structured in this repository. It is the agreed-conventions counterpart to the one-off Documentation Audit & OKF Alignment Roadmap, and follows Google's Open Knowledge Format (OKF v0.1): markdown + YAML frontmatter, in git, readable by humans and AI agents alike.

Every doc starts with frontmatter

---
type: guide                       # REQUIRED — one value from the taxonomy below
title: Common Tasks               # REQUIRED — human title (usually matches the H1)
description: How to add a query or command in Foundry.   # one line; powers search + index
status: current                   # current | draft | deprecated | archived
updated: 2026-06-19               # date of last meaningful content change (OKF calls this `timestamp`)
tags: [cqrs, marten, commands]    # for discovery / filtering
resource: src/Domain/...          # OPTIONAL — link to the code/system this documents
audience: developer               # OPTIONAL — developer | end-user | ops
---

Minimum to be conformant: type, title, description, status, updated. Add the rest where they earn their place.

The type taxonomy

A small, closed set. Every doc is exactly one.

type Meaning Lifecycle
index Navigation / table of contents (every README.md) living
concept Explains how/why something works living
guide Task-oriented how-to living
reference Authoritative factual lookup living
design Technical design / rationale evolves, then settles
adr Architecture Decision Record immutable once accepted
runbook Operational procedure living
model Simulation / model documentation living
plan Roadmap / implementation plan ephemeral
evaluation R&D findings, experiments ephemeral
note Working note, review, draft ephemeral
sample Sample data / diagnostic output ephemeral

Naming & placement rules

  • kebab-case for every filename and directory. The conventional uppercase entry files README.md, CONTEXT.md, UPDATING.md are the only exceptions.
  • No ticket numbers in filenames — put LBS-XXXX in tags.
  • No durable docs at docs/ root. Only README.md (the index) and the two pillar docs intro.md and security.md live there.
  • One folder per type-or-domain. ADRs live in adr/; designs in architecture/ (or a future design/); operational procedures in runbooks/.
  • ADRs are immutable. Once an ADR is accepted, don't rewrite it — supersede it with a new one and link back.

Where things go

Folder Holds Typical type
getting-started/ Setup and first-run guides guide
architecture/ How the system is built and why concept, design, reference
developer-guide/ Day-to-day development how-tos guide
adr/ Accepted architecture decisions adr
api/ Endpoint/contract references reference
importers/, integrations/ Feed ingestion and external systems guide
models/ Standalone simulation model docs model
outcome-context/ The Outcome Context platform (self-contained) design, plan, evaluation
runbooks/ Operational procedures runbook
samples/ Sample data and diagnostics sample
user-guides/, end-user-guides/ End-user facing docs guide (audience: end-user)
meta/ Docs about the docs note, guide

Adding a new doc

  1. Pick the folder by domain/type (table above). Don't drop it at docs/ root.
  2. Name it kebab-case.
  3. Add the frontmatter block. Choose type from the taxonomy; write a one-line description; set status: current and updated to today.
  4. Cross-link related docs with ordinary relative markdown links.
  5. Run pnpm docs:index to regenerate the index, and commit the updated docs/README.md.

Keeping the index honest

docs/README.md is generated from frontmatter by tools/docs/docs-index.mjs — don't edit it by hand. After adding or moving a doc, run pnpm docs:index and commit the result. (CLAUDE.md's "Where to find things" table is a separate, hand-curated subset for agents.)

pnpm docs:check validates the tree — every doc has required frontmatter, docs/README.md is in sync, and all relative links resolve. The same check runs in CI (.github/workflows/docs.yml), currently warn-only; remove the continue-on-error line in that workflow to make it a required check.

Docs that live with code

Some docs are best kept next to the component they describe — e.g. predictor READMEs under src/Models/. These stay in place (not moved into docs/) but are still surfaced in the index by adding them to the EXTERNAL list in tools/docs/docs-index.mjs: give the file path, the index section it belongs in, and a type/status. The generator links to the file in place and derives its title from the # H1 and its description from the first paragraph (or honours frontmatter if the file has any). When a file's H1 is too generic to stand alone in the index (e.g. # Engine), set an explicit title (and optionally description) on the EXTERNAL entry. The link and freshness checks cover these files too.

Producing a portable bundle

pnpm docs:bundle writes a self-contained copy of the whole doc set to dist/docs-bundle/ (git-ignored): docs/** plus the code-adjacent EXTERNAL files, laid out so every doc-to-doc link resolves with no rewriting. Package it with tar -czf docs-bundle.tgz -C dist docs-bundle to share it, serve it, or feed it to a viewer. Links into source code, the SDKs, or other repos are reported as external references and intentionally left out of the bundle.

The bundle also includes index.json at its root — a machine-readable manifest (schema: okf-docs-manifest/1) with one record per indexed document (path, section, type, title, description, status, updated, tags), plus a version stamped from the DOCS_VERSION env var (the git short SHA in CI, dev locally). This is the OKF/agent-consumable view of the set.

The documentation site

pnpm docs:site builds a Material for MkDocs site to dist/docs-site/ (git-ignored); pnpm docs:site:serve runs it locally with live reload. Both first regenerate the index and copy docs/README.md to docs/index.md (the site homepage; git-ignored). Requires MkDocs Material — pip install -r tools/docs/requirements.txt (Python 3.11 is already in CI). Mermaid fences render natively; tools/docs/mkdocs_hooks.py rewrites links that escape docs/ into source/SDK/repo-root files to GitHub blob URLs at build time.

Publishing (Cloudflare)

.github/workflows/docs-site.yml runs on pushes to main that touch the docs (and via manual dispatch with a staging/production choice): it validates the docs (merge-blocking), builds the site and the bundle, uploads docs-bundle.tgz + index.json to the foundry-docs-bundle R2 bucket (under <sha>/ and latest/), and deploys the site to a Cloudflare Worker (wrangler.docs.jsonc, served via the static-assets binding). The Worker (tools/docs/worker.js) also serves the bundle at /bundle/<version>/docs-bundle.tgz and the manifest at /manifest.json from R2; the footer shows the build version and a bundle download link. It reuses the CLOUDFLARE_API_TOKEN / CLOUDFLARE_ACCOUNT_ID secrets. Access is gated by a Cloudflare Access policy on the docs hostnames.

One-time Cloudflare setup is required before the workflow can deploy: create the foundry-docs-bundle R2 bucket, the docs.foundry.luckbox.dev / docs.foundry.luckbox.live custom domains, and the Cloudflare Access policy. Known v1 limitation: the 5 code-adjacent EXTERNAL READMEs are linked to GitHub rather than rendered as site pages.