# Building the documentation

```bash
uv venv && uv pip install -r docs/requirements.txt
.venv/bin/python -m sphinx -b html docs docs/_build/html -W
# or, with the environment active
make -C docs html
```

`-W` turns warnings into errors, deliberately. A warning is a defect in the documentation,
and the same standard applies here as to the code. `.github/workflows/docs.yml` runs the
same build on every pull request, and publishes to GitHub Pages from `main` - so the
question "does it still build" is answered before a merge rather than after one.

Written in **MyST Markdown**, not reStructuredText. Every page under `docs/` is read three
ways - on the site, in the repository, and in the published tarball, which carries `docs`
in `files` - so plain Markdown is what the pages are, and Sphinx syntax appears only where
a site needs something a Markdown file cannot say: the toctrees and the cards on
`index.md`.

Python is a documentation dependency and nothing more. The library is TypeScript, `npm
test` and `npm run typecheck` never reach this directory, and `package.json` still depends
on the pi SDK alone.

## Layout

```
docs/
  index.md              the landing page: what combo is, and where to start
  guide/                task-oriented: how to do a thing
    quickstart.md       the first subagent, the first workflow, the first build
    agents.md           defining an agent in Markdown, tools, scopes
    lifetime.md         the central choice: disposable or persistent
    workflows.md        the combinators and the options they share
    flows.md            a task graph written in Markdown, checked whole before it runs
    from-pipelines.md   rewriting a linear pipeline as a flow
    build.md            plan, pair, check, audit, unattended
    display.md          reporters, herdr splits, the pi TUI widget
    measurements.md     what Usage counts, and what it refuses to guess
    export.md           runs/<timestamp>/, HTML, JSONL, usage.json
    experiments.md      one workflow, M models, N repetitions, one table
    extension.md        the subagent tool, /run, /interview, /herdr
  tutorials/            problem-oriented: twelve sittings in front of pi, in order
  reference/            lookup-oriented: what an export or a file does
    cheatsheet.md       everything on one page, each section linking to its guide
    api/                generated from the TSDoc by `npm run docs`
    flows/              each shipped flow as a Mermaid diagram, generated by `npm run docs`
    examples.md         one runnable script per shape
  development.md        tests, typechecking, conventions, how the docs stay honest
  decisions.md          why the library is shaped this way, and what was reversed
  _static/custom.css    the palette, the type and the devices, per selector
  _pygments.py          the code blocks, in the same two hues
  _static/logo/         the marks, and README.md for what each one is for
  _static/tutorials/    one drawing per tutorial, from scripts/draw-tutorials.py; README.md
                        says what each sign means
  _static/fonts/        EB Garamond and Inter, subset, with their licence
```

The two faces are **served by this site and by nobody else**: a font CDN would tell a
third party who reads this documentation, and would leave every page waiting on a host we
do not control. `scripts/subset-fonts.py` fetches them from a pinned commit of
`google/fonts`, cuts them down to the characters these pages use, and writes both the
`woff2` files and `coverage.json` beside them. Regenerating is one command:

```bash
uv run --with fonttools --with brotli python scripts/subset-fonts.py
```

`test/fonts.test.ts` compares the prose of every page against that coverage, because a
character no shipped face carries does not fail - it is quietly drawn from whatever the
reader has installed, and only they ever see it.

`reference/api/` is **generated** - `npm run docs` writes it from the TSDoc of everything
`src/index.ts` exports, and `test/docs.test.ts` fails when the checked-in pages no longer
match the source. Its index carries the hidden toctree that gives those pages a place in
the site's navigation, so a module that disappears takes its navigation entry with it.
`reference/flows/` is generated and held the same way, one Mermaid diagram per flow in
`flows/`, drawn from the checked flow; `sphinxcontrib-mermaid` draws it on the site, and
GitHub draws the same fence natively.

Navigation is the toctrees and nothing else. `scripts/doc-links.ts` reads them to check
that every hand-written page is reachable and every entry exists, which is the same
question Sphinx asks - asked offline, in `npm test`, where the answer is cheap.
