Skip to content

Latest commit

 

History

History
348 lines (288 loc) · 17.6 KB

documentation.md

File metadata and controls

348 lines (288 loc) · 17.6 KB

Documentation guide

Documentation is part of OmniGraph's public contract. Keep each fact in one place, at the narrowest audience that needs it.

Content ownership

Location Owns Does not own
docs/user/ Supported behavior, concepts, workflows, configuration, limits, and operator action Code structure, recovery protocols, test evidence, design history
docs/dev/ Current architecture, invariants, support boundaries, and how to change/test the system Roadmaps, stale implementation plans, release history
docs/rfcs/ Proposals, decisions, rationale, alternatives, evidence, and disposition The current user manual or a second implementation reference
changelog.d/ Permanent notes written with each user-visible change Current user instructions
docs/releases/ Published release history and generated version snapshots Evergreen instructions
Code and tests Exact types, fields, constants, and executable assertions Long-form product guidance
Issue tracker Open work, sequencing, and ownership Current architecture

Git history is the archive for superseded drafts. Do not keep a stale design in docs/dev/ merely because it may be interesting later.

User documentation

Write for someone using the CLI, HTTP API, or deployment—not for a contributor reading the implementation.

  • Lead with the task or guarantee.
  • Show one canonical command or request, then link to the reference.
  • Explain public consequences of atomicity, recovery, and indexing without naming internal tables, structs, sidecars, or protocol generations.
  • Document supported behavior only. Put planned work in an issue or draft RFC.
  • State limits when they change what a user must do; omit internal tuning and implementation evidence.
  • Give a concept one owner. Other pages use a sentence and a link rather than a second explanation.
  • Prefer current canonical names. Mention deprecated aliases only in a compact compatibility section.

Most authored user pages should fit in 80–220 lines. Longer reference material must earn its size and should be generated from the defining schema when practical.

Developer documentation

Developer docs answer three questions: what is true now, why must it remain true, and where should a change be made and tested?

  • Describe stable components and flows, not mutable source line numbers.
  • Link to code for exact serialized shapes and constants.
  • Link to an RFC for rationale, rejected alternatives, or historical evidence.
  • Keep benchmarks and migration evidence with the release or RFC that used them; do not grow an evergreen ledger.
  • Remove a plan after it lands. Transfer only the durable outcome into current architecture or invariants.
  • Name unsupported boundaries plainly without presenting a speculative design as current architecture.

RFCs

Every project RFC lives directly under docs/rfcs/ and follows the metadata, filename, lifecycle, and template in the RFC guide. There is one namespace and one lifecycle for public and maintainer-authored RFCs.

An RFC remains a decision record after implementation. Update its disposition, but keep day-to-day instructions in user or developer docs.

Documentation tools

Use Python 3.10 or newer. From the repository root, create and activate a local environment before running the documentation checker or release-note commands:

python3 -m venv .venv-docs
source .venv-docs/bin/activate
python3 -m pip install -r scripts/requirements-docs.txt

The requirements pin markdown-it-py and its mdurl dependency. The checker and composer share its CommonMark parser, with table and strikethrough support, so links in nested lists and code examples have the same meaning in both tools. CI installs these same dependencies in a temporary environment. Reuse the local environment on later runs; reinstall when the requirements change.

Release notes

Add one permanent changelog.d/<descriptive-slug>.<category>.md file with each user-visible change. No PR number or release number is needed: the release page links each note to the pull request whose squash commit added it. Internal-only changes need no note. A note is one bullet with one sentence or two, at most 200 characters of visible text (code spans count, link destinations and definitions do not); move detail into the guide it links. A breaking note may use 400 characters, says who is affected and what to do, and links the guide that holds the steps, usually the upgrade guide. Review the note with its code. There is no separate release-note approver.

Suffix Section
breaking Upgrade actions: who is affected and what to do
added Features
changed Behavior changes
fixed Fixes
performance Performance
deprecated Deprecations
removed Removals

Start the file with a Markdown bullet and end it with a newline. Code spans stay intact; nested lists, fenced examples and second paragraphs are refused in new notes. Local links use reference definitions at column zero, with a relative destination and optional heading anchor:

- Queries accept the new predicate. See the [query guide][predicate-guide].

[predicate-guide]: ../docs/user/queries/index.md

Give reference labels names unique to the note; CommonMark normalizes their case and whitespace. Definitions occupy one line and have no optional title. Local inline links, fragment-only links and URL query parameters on local links are refused; name the destination document explicitly. Raw HTML outside code is unsupported; use Markdown. Inline external URLs are allowed. Code spans follow CommonMark, including literal unmatched backticks and backslashes. Close fenced code blocks so they cannot consume the following note. The composer only rewrites link definitions outside code, preserving the rest of each fragment apart from normalizing CRLF line endings to LF. Do not add release headings to fragments.

The release file

The release-prep pull request adds changelog.d/<version>.md, named for the version in release.json. It opens with an intro of at most 100 words that says what users get from the release and, when it breaks something, what they must do before they upgrade. Write the intro in ASD-STE100 Simplified Technical English: short sentences (at most 25 words), active voice, simple present, one statement per sentence and no slogans. When the release has any breaking note, a ## Why these changes section of at most 80 words says why the release asks users to act; it is printed at the top of the upgrade actions, and a release with no breaking note refuses it.

A ## Highlights section holds three to five ### highlights for a minor or major release, and up to five for a patch release, each at most 150 words. The heading names the change and what it gives users in a few words, with a measured number when there is one (CSV import: 630 million rows in under five minutes, not CSV loads go through the planner). The body is in database terms: it opens with the mechanism (projection pushdown, copy-on-write branches, compare-and-swap publication), names the benchmark behind any number and the machine and storage it ran on, and lists its pull requests:

### Counting no longer loads every embedding

Projection pushdown: a `Vector` or `Blob` column is read only when the query
names it, so a `count` over embedding-heavy types reads no vectors. #760, #795

The release-prep pull request may leave ## Highlights empty for someone else to write: the preview shows them as still to be written and CI passes, but the snapshot refuses a minor or major release until three to five are in.

Before the snapshot, the release-prep pull request also reads the cycle's notes as one page. Notes stay editable until their release is tagged, so when several notes describe one upgrade step (a saved-plan version, a storage format), keep one that states the final value and delete the others, and say each fact once.

Notes print as one list per section, in file-name order. To put the most important ones first, add a ## Note order section listing note file names, one per - line (- storage-format-14.breaking.md); listed notes lead their sections in that order, the rest follow by file name, and the section itself is not printed. A ## Contributors section lists the GitHub handles to thank, one per - @handle line; the snapshot refuses a release file without it, and the page prints them as one thank-you line. List the pull request authors since the previous release with gh api repos/ModernRelay/omnigraph/compare/<previous>...<target> --paginate --jq '.commits[].author.login' | sort -u, drop bots, and add anyone else worth thanking. No other headings are allowed. Links follow the note rules. The file is immutable once its release is tagged.

Wrap notes and the release file as you like: the page joins each paragraph into one line, because GitHub shows every newline in a release body as a line break. Code blocks and hard line breaks keep their lines.

Pull request titles

The PR Title check holds the title to type(scope)!: description (CONTRIBUTING.md, Pull Requests) and also reads its type: a feat, fix or perf pull request adds a note, and a ! title adds a .breaking.md note. A maintainer adds the skip-changelog label when a typed change has nothing users can see. The squash commit keeps the title and its (#NNN), which is where the release page's pull request links come from.

Preview local edits and untracked notes from the repository root after activating the documentation environment:

python3 scripts/release_notes.py preview --working-tree
python3 scripts/check-docs.py

Working previews have local links relative to docs/releases/; save them there temporarily if viewing in a Markdown reader. For a committed preview, use preview --target HEAD. Its links point to the full selected Git SHA, so the downloaded Markdown also works outside the checkout. The existing documentation CI job uploads this output as release-notes-preview; no generated preview is checked in and no bot comment is needed.

changelog.d/release.json names the next version, the previous release base for that maintenance line, an optional legacy baseline SHA and the cycle's release format (2, or 1 when the field is absent). These are explicit inputs, not inferred from the newest tag. Set base to null only for an initial release without a predecessor. The base and optional legacy source must be available with enough history to prove ancestry. The selected notes are paths present in the target tree and absent from the base tree. Content comes from the target; category and filename ordering are deterministic.

An unreleased note can be edited or removed with a reverted change. Once a release includes it, retain its path and content: a correction or reversal gets a new note. A backport carries the same path and uses that branch's previous release. CRLF and LF checkouts have the same identity; other content changes do not. The checker validates selected notes' links against the selected tree; historical raw notes are not checked against today's moving documentation.

With the documentation environment active and changelog.d/<version>.md written, release preparation creates a versioned snapshot and updates docs/releases/README.md from committed inputs and an explicit date:

python3 scripts/release_notes.py snapshot --target HEAD --date 2026-10-01

Replace the example date with the intended release date. A release that still carries a hand-written document names it with legacy in release.json, a durable, already-landed ancestor containing that exact document, and passes --replace-legacy for its first snapshot. --replace regenerates an existing generated snapshot before its tag exists. Nothing moves, deletes or stages fragments. Preview accepts --base REF, --version vX.Y.Z and --initial-release for comparison runs. A snapshot must agree with the version, base and legacy source in release.json, including base: null for an initial release. Configuration itself remains part of the recorded inputs.

The snapshot records the selected target SHA, base SHA and note digests. The target SHA documents where generation ran; squash merging may remove that commit. Validation compares the complete selected note set and digests, configuration, and regenerated document against the audited release tree. It requires ancestry only for the durable release base and legacy source. Any later note or configuration change requires regeneration. Format-2 snapshots also record the release file's digest, the previous release tag and the pull request link of each note; a recorded link must still match history when the release is verified. Verify a prepared committed snapshot with the documentation environment active:

python3 scripts/release_notes.py verify --version v0.12.0 --target HEAD

Snapshot creation validates both outputs before writing and replaces each file atomically. An interruption between replacements can leave a current snapshot with an old index; retry with --replace. The checker detects a stale index. To repair only the index, including after a version is tagged, activate the documentation environment and run:

python3 scripts/release_notes.py index --write

Without --write, the index command only prints its result. With --write, it validates the version documents before atomically replacing the existing index.

The stable publisher validates the snapshot from its audited checkout and renders its local links at the release tag. Versions before v0.12.0 retain asset-only backfills; v0.12.0 onward require a valid snapshot. Edge releases need no snapshot: each shows the unreleased preview at its commit (release workflows). After publication, update the configuration for the next release: set its base to the release just published, advance the version, set legacy to null and keep "format": 2. Advance the workspace package version too: edge builds are refused while it is not above the latest stable release (release workflows).

v0.12.0 through v0.14.0 are format 1, and each snapshot records its format, so their snapshots keep that shape. v0.14.0's GitHub release body was replaced by hand after publication with a format-2 page; its snapshot is unchanged. v0.12.0's hand-written document was converted into two notes, changelog.d/a-release-highlights.added.md and changelog.d/a-compatibility-and-behavior-changes.changed.md. The v0.14.1 cycle is the first in format 2; a format-2 GitHub release body is the snapshot without its heading, status line and provenance comment. The length caps and the release file apply only to a format-2 cycle. Generated snapshots require exact verification, and existing published documents and URLs stay unchanged.

A release may also have a curated docs/releases/vX.Y.Z-overview.md, linked from the generated release index. Reconcile superseded fragments against the code at the release tag and explain the final shipped behavior and upgrade actions. Link the complete immutable vX.Y.Z.md snapshot from the overview; do not edit the published snapshot or source notes to resolve contradictions. The overview is a maintained guide to that release, not a replacement for its recorded history. After adding it, regenerate the index with python3 scripts/release_notes.py index --write.

Release checklist

Every release runs these steps in order.

  1. Confirm the cycle: changelog.d/release.json names the version, its base and "format": 2.
  2. Smoke-test the candidate: install the edge build of the commit to be released (release channels) and run the quickstart against a fresh local graph.
  3. Open the release-prep pull request. Run python3 scripts/release_notes.py preview --working-tree, read the page against the docs at that commit, fix each stale note in its own file, and merge notes that repeat one upgrade step.
  4. Add changelog.d/<version>.md to that pull request: the intro, the why when anything breaks, the highlights, the contributors and, if useful, the note order. An agent can draft the highlights from the cycle's notes; run preview again and read the rendered page.
  5. Review the pull request against the rendered preview, not only the files.
  6. After the review, run python3 scripts/release_notes.py snapshot --target HEAD --date <release date>, commit the snapshot and the index to the same pull request, and merge it.
  7. Tag the merged commit <version> and push the tag. Tag CI audits it and release.yml publishes the archives and the GitHub release from the snapshot. Do not edit the published page or its notes; correct a mistake with a new note or in the release's overview.
  8. Open the next cycle: update release.json and the workspace package version as described above.

Review checklist

Before merging documentation:

  1. Verify behavior against current code, CLI help, OpenAPI, and existing tests.
  2. Check whether another page already owns the concept.
  3. Remove future promises and internal detail from user docs.
  4. Remove stale plans, evidence ledgers, and duplicated RFC content from developer docs.
  5. Use relative Markdown links and run the documentation checks.
  6. Read the rendered diff for examples, headings, and scanability.

After activating the documentation environment:

bash scripts/check-agents-md.sh
python3 scripts/check-docs.py
typos   # from the repository root; exemptions in .typos.toml