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.mdare the only exceptions. - No ticket numbers in filenames — put
LBS-XXXXintags. - No durable docs at
docs/root. OnlyREADME.md(the index) and the two pillar docsintro.mdandsecurity.mdlive there. - One folder per type-or-domain. ADRs live in
adr/; designs inarchitecture/(or a futuredesign/); operational procedures inrunbooks/. - 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¶
- Pick the folder by domain/type (table above). Don't drop it at
docs/root. - Name it kebab-case.
- Add the frontmatter block. Choose
typefrom the taxonomy; write a one-linedescription; setstatus: currentandupdatedto today. - Cross-link related docs with ordinary relative markdown links.
- Run
pnpm docs:indexto regenerate the index, and commit the updateddocs/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.