okf-frontmatter
OpenInvest's docs live in docs/wiki/ (numbered chapters) and docs/wiki/adr/ (decision
records). Under OKF each doc starts with a YAML frontmatter block that is the single
source of truth about that doc. Tooling reads the frontmatter; humans read the prose. The
goal: stop maintaining huge prose docs that duplicate what the code already says — link to
the code instead, and let find_docs.py do navigation.
Point the script at a repo with --repo <path>, or just run it from inside that repo (it
auto-detects the nearest ancestor containing docs/wiki/, else uses the working dir). It is
read-only except for docs you explicitly edit. The conventions below use openInvest as the
worked example, but the mechanics (find / schema / lint) work on any repo whose
markdown carries OKF frontmatter.
Job 1 — maintain docs the OKF way
The rule of thumb: frontmatter is structured truth; prose is explanation. Anything that
is a schema (a Pydantic model, a dataclass, a config key, an endpoint contract) lives in
code — the doc points to it via schema_source / documents, it does not re-type it.
When the code changes, lint tells you which doc's pointer went stale. Don't grow a doc past
a few screens of "why / how it fits together"; if you're copying field tables out of code,
stop and add a schema_source pointer instead.
Frontmatter schema
Common to every doc:
| field |
required |
meaning |
type |
✅ |
wiki-chapter | adr | index | reference | report | readme |
title |
rec. |
human title (usually the H1) |
tags |
opt. |
[api, rest, ...] — coarse categories |
intent |
opt. |
one short phrase the lookup ranks on, e.g. API Contract, 决策参数, 部署 |
schema_source |
opt. |
list of relpath:Symbol pointers to the authoritative code, e.g. connectors/web_api/models.py:PortfolioResponse |
documents |
opt. |
{endpoints: [GET /api/x], config_keys: [a.b], symbols: [Foo]} — concrete things this doc covers |
ADR-only (lifecycle):
| field |
meaning |
status |
proposed | accepted | superseded (normalizes the old **状态** line) |
date |
decision date |
supersedes / superseded_by |
ADR ids, e.g. [010] |
Relationships between docs stay as ordinary markdown links in the body (that's the OKF
knowledge graph). supersedes/superseded_by are typed mirrors lint cross-checks.
Adding / changing a doc
- Scaffold:
run.sh new <type> <name> prints a frontmatter skeleton to stdout — paste it
at the top of the new file, fill it in.
- Fill
schema_source/documents from the code the doc describes (grep
connectors/web_api/models.py, core/schemas.py, core/config/).
- Run
run.sh lint before committing — fix any error (broken link / dangling pointer /
missing type).
See references/conventions.md for the full schema + the "no thousand-line prose" rule, and
references/okf-spec.md for what OKF is.
Job 2 — find the right doc fast (grep first, script as fallback)
find_docs.py is not the first move. grep is. The script only pays off when grep can't
tell you which doc is authoritative.
1. grep the literal term first (ripgrep) — zero script overhead.
2. grep is decisive? → read that doc, done.
"decisive" = the term hits one file, or hits a heading / frontmatter (that doc owns it).
3. grep is ambiguous? → run.sh find <query>
"ambiguous" = hits scattered across ≥3 files / only in prose / 0 hits (synonym mismatch).
Why: on a clean literal hit, grep is already optimal and the script just adds a call. The
win comes from not calling the script on easy queries — so don't run both in parallel.
The script's real value is matching intent, not strings: it ranks the doc whose
frontmatter owns the symbol/endpoint/config-key first, even when the literal keyword is
buried. Full decision tree + the benchmark behind it: references/lookup-strategy.md.
Commands
| command |
use |
run.sh find <query> |
symbol (PortfolioResponse), endpoint (GET /api/holdings), config key (verdict.risk_profile), intent/tag, or keyword → ranked owning docs (JSON, strongest match first) |
run.sh schema <doc> |
resolve a doc's schema_source and print the real code definitions — read the authoritative schema without opening the prose |
run.sh index [--cache] |
dump the whole frontmatter index as JSON (--cache writes docs/.okf-index.json) |
run.sh lint [--ci] |
OKF compliance + drift; --ci exits non-zero only on errors (un-migrated docs are info, never a failure) |
run.sh new <type> <name> |
print a frontmatter skeleton |
References
| file |
when to read |
references/okf-spec.md |
what the Open Knowledge Format is (the 1-page version) |
references/conventions.md |
this repo's frontmatter schema + maintenance rules |
references/lookup-strategy.md |
the grep-first / script-fallback decision tree + benchmark |
1---2name: okf-frontmatter3description: Maintain openInvest's docs (docs/wiki chapters + docs/wiki/adr) under Google's Open Knowledge Format (OKF). Two jobs. (1) Teach agents to maintain docs the OKF way — every doc carries a small YAML frontmatter block as the single source of truth (type, title, tags, intent, schema_source, documents); schema details link to the authoritative code instead of being copied into prose; no more hand-maintained thousand-line markdown. (2) Look docs up fast — grep the literal term FIRST; only when grep is ambiguous (hits scattered across files / synonym mismatch / zero hits) run find_docs.py to rank the owning doc by frontmatter intent, or resolve a doc's schema_source to the real code. Trigger phrases — "which doc covers X", "find the schema for PortfolioResponse", "where is GET /api/holdings documented", "docs for verdict.risk_profile", "add OKF frontmatter to this doc", "lint the wiki", "scaffold a new ADR/chapter". Run: scripts/run.sh find|schema|index|lint|new (or python3 scripts/find_docs.py --repo <path> ...).4---56# okf-frontmatter78OpenInvest's docs live in `docs/wiki/` (numbered chapters) and `docs/wiki/adr/` (decision9records). Under **OKF** each doc starts with a YAML frontmatter block that is the *single10source of truth* about that doc. Tooling reads the frontmatter; humans read the prose. The11goal: stop maintaining huge prose docs that duplicate what the code already says — link to12the code instead, and let `find_docs.py` do navigation.1314Point the script at a repo with `--repo <path>`, or just run it from inside that repo (it15auto-detects the nearest ancestor containing `docs/wiki/`, else uses the working dir). It is16read-only except for docs you explicitly edit. The conventions below use openInvest as the17worked example, but the mechanics (`find` / `schema` / `lint`) work on any repo whose18markdown carries OKF frontmatter.1920---2122## Job 1 — maintain docs the OKF way2324**The rule of thumb:** frontmatter is structured truth; prose is explanation. Anything that25*is* a schema (a Pydantic model, a dataclass, a config key, an endpoint contract) lives in26code — the doc **points** to it via `schema_source` / `documents`, it does not re-type it.27When the code changes, `lint` tells you which doc's pointer went stale. Don't grow a doc past28a few screens of "why / how it fits together"; if you're copying field tables out of code,29stop and add a `schema_source` pointer instead.3031### Frontmatter schema3233Common to every doc:3435| field | required | meaning |36|---|---|---|37| `type` | ✅ | `wiki-chapter` \| `adr` \| `index` \| `reference` \| `report` \| `readme` |38| `title` | rec. | human title (usually the H1) |39| `tags` | opt. | `[api, rest, ...]` — coarse categories |40| `intent` | opt. | one short phrase the lookup ranks on, e.g. `API Contract`, `决策参数`, `部署` |41| `schema_source` | opt. | list of `relpath:Symbol` pointers to the authoritative code, e.g. `connectors/web_api/models.py:PortfolioResponse` |42| `documents` | opt. | `{endpoints: [GET /api/x], config_keys: [a.b], symbols: [Foo]}` — concrete things this doc covers |4344ADR-only (lifecycle):4546| field | meaning |47|---|---|48| `status` | `proposed` \| `accepted` \| `superseded` (normalizes the old `**状态**` line) |49| `date` | decision date |50| `supersedes` / `superseded_by` | ADR ids, e.g. `[010]` |5152Relationships between docs stay as ordinary markdown links in the body (that's the OKF53knowledge graph). `supersedes`/`superseded_by` are typed mirrors `lint` cross-checks.5455### Adding / changing a doc56- Scaffold: `run.sh new <type> <name>` prints a frontmatter skeleton to stdout — paste it57 at the top of the new file, fill it in.58- Fill `schema_source`/`documents` from the code the doc describes (grep59 `connectors/web_api/models.py`, `core/schemas.py`, `core/config/`).60- Run `run.sh lint` before committing — fix any `error` (broken link / dangling pointer /61 missing `type`).6263See `references/conventions.md` for the full schema + the "no thousand-line prose" rule, and64`references/okf-spec.md` for what OKF is.6566---6768## Job 2 — find the right doc fast (grep first, script as fallback)6970`find_docs.py` is **not** the first move. grep is. The script only pays off when grep can't71tell you which doc is authoritative.7273```741. grep the literal term first (ripgrep) — zero script overhead.752. grep is decisive? → read that doc, done.76 "decisive" = the term hits one file, or hits a heading / frontmatter (that doc owns it).773. grep is ambiguous? → run.sh find <query>78 "ambiguous" = hits scattered across ≥3 files / only in prose / 0 hits (synonym mismatch).79```8081Why: on a clean literal hit, grep is already optimal and the script just adds a call. The82win comes from **not** calling the script on easy queries — so don't run both in parallel.83The script's real value is matching *intent*, not strings: it ranks the doc whose84frontmatter *owns* the symbol/endpoint/config-key first, even when the literal keyword is85buried. Full decision tree + the benchmark behind it: `references/lookup-strategy.md`.8687### Commands88| command | use |89|---|---|90| `run.sh find <query>` | symbol (`PortfolioResponse`), endpoint (`GET /api/holdings`), config key (`verdict.risk_profile`), intent/tag, or keyword → ranked owning docs (JSON, strongest match first) |91| `run.sh schema <doc>` | resolve a doc's `schema_source` and print the real code definitions — read the authoritative schema without opening the prose |92| `run.sh index [--cache]` | dump the whole frontmatter index as JSON (`--cache` writes `docs/.okf-index.json`) |93| `run.sh lint [--ci]` | OKF compliance + drift; `--ci` exits non-zero only on errors (un-migrated docs are info, never a failure) |94| `run.sh new <type> <name>` | print a frontmatter skeleton |9596---9798## References99| file | when to read |100|---|---|101| `references/okf-spec.md` | what the Open Knowledge Format is (the 1-page version) |102| `references/conventions.md` | this repo's frontmatter schema + maintenance rules |103| `references/lookup-strategy.md` | the grep-first / script-fallback decision tree + benchmark |