Skip to content

docs: pages on main describe unreleased behaviour without marking it #985

Open

Description

@pronskiy

omnigraph.dev/docs renders main, while install.sh and the cookbooks give 0.13.0. A few pages describe behaviour that 0.13.0 users then hit as errors:

Page What it says What 0.13.0 does
deployment.md servers "open graph storage formats v14 to v16" serves v14 only: omnigraph version prints internal-schema 14 (serves v14 to v14)
branching/changes.md, branching/merge.md omnigraph diff, omnigraph branch diff, branch merge --dry-run (#966, merged today) omnigraph branch diff → error: unrecognized subcommand 'diff'
branching/index.md, operations/policy.md unpublished commits (as commit, commit publish / commit drop), unattached branches omnigraph commit publish → error: unrecognized subcommand 'publish'

install.md warns that docs on main may be newer than the stable binary. A reader landing on one of these pages from search never sees that warning.

Suggested fix:

  • Mark sections for not-yet-released features inline, for example "Unreleased, next version".
  • Longer term: versioned docs, so the site can show the stable release by default.

Activity

  1. ragnorc commented on Oct 17, 2026

    @ragnorc
    Contributor

    Triage: reproduced, and the defect is wider than the report

    Summary

    The site omnigraph.dev/docs shows the docs/user pages from main. The installer and the cookbooks install 0.13.0. main is 97 commits ahead of v0.13.0, and its user pages describe many commands, flags, routes, settings, query statements and a storage format that 0.13.0 does not have. No page marks this content as unreleased. A 0.13.0 user who follows these pages gets errors. A user who mixes a main build with 0.13.0 can also make a graph that 0.13.0 cannot open.

    Verdict: reproduced

    All the reporter's steps give the reported output. The scope is wider. I found main-only content on 26 docs/user pages. 17 of these pages are on omnigraph.dev, and the other 9 are on GitHub main only. The reporter listed 5 pages.

    • main: 4d7536d68b1db6da34bf9cff22a90d9fdd77bed4, rechecked before posting. Clean detached worktree. cargo build --locked -p omnigraph-cli -p omnigraph-server (debug profile) prints omnigraph 0.14.0 / internal-schema 16 (serves v14 to v16) / http-contract 0.13.
    • 0.13.0: installed as the reporter did it: curl -fsSL https://raw.githubusercontent.com/ModernRelay/omnigraph/main/scripts/install.sh | INSTALL_DIR=/tmp/og013 bash (stable channel, release v0.13.0).
    • Host: Linux x86_64 (kernel 6.12). Local file-backed graphs from the quickstart schema and data.

    Reporter's steps on 0.13.0:

    $ omnigraph version
    omnigraph 0.13.0
    internal-schema 14 (serves v14 to v14)
    $ omnigraph branch diff
    error: unrecognized subcommand 'diff'
    $ omnigraph diff
    error: unrecognized subcommand 'diff'
    $ omnigraph commit publish
    error: unrecognized subcommand 'publish'
    $ omnigraph commit drop
    error: unrecognized subcommand 'drop'
    $ omnigraph branch merge review --into main --dry-run --store graph.omni
    error: unexpected argument '--dry-run' found
    

    The same documented commands succeed on main. For example, omnigraph diff --from main --to review --store graph.omni prints insert node Source bench. omnigraph branch merge review --into main --as-commit followed by omnigraph commit publish <id> --uri graph.omni prints published commit … on main.

    Differences from the report:

    • None in the listed commands. All of them reproduce.
    • feat(changes): graph diff, branch review and merge dry run #966 merged at 2026-10-13T20:20Z, and this issue was opened at 20:45Z. "Merged today" is correct.
    • omnigraph.dev shows a hand-picked subset of docs/user under its own paths, for example /docs/getting-started/deployment and /docs/queries-search/queries. Some main-only pages are not on the site, but GitHub main shows them and other pages link to them.
    • The same main content is in https://www.omnigraph.dev/llms-full.txt (25 matching lines), so agents that read it get main behaviour too.
    • The install.md warning ("Documentation on main may describe behavior newer than the latest stable binary") is only on the install page, as reported.

    Method: how I found the whole class

    I did not guess. I used four mechanical sources and ran each documented command on both binaries.

    1. CLI tree diff. A script walks --help for every subcommand of both binaries. main adds 353 help lines and removes 0. Reduced to new commands and flags, main adds: diff, branch diff, branch merge-base, branch merge --dry-run, branch merge --as-commit, commit publish, commit drop, commit list --unpublished, commit list --unattached, blob put, blob clear, skill export, skill show, cluster list, cluster members list, cluster pull, organization members … and organization invitations …, --organization on login, logout, use, cluster create and cluster operation, and version --json.
    2. Server. omnigraph-server --help on main adds --bootstrap-handoff, --mcp-allow-adhoc, --mcp-allow-writes and --mcp-allowed-host. The openapi.json diff (v0.13.0..main) adds GET /graphs/{id}/diff, GET …/branches/diff, GET …/branches/merge-base, POST …/commits/{commit_id}/publish, DELETE …/commits/{commit_id}, PUT and DELETE …/blob, and GET /.well-known/oauth-protected-resource/{resource_path}. HTTP_API_CONTRACT stays 0.13, so a main CLI and a 0.13.0 server accept each other's header, but the new routes are absent on 0.13.0.
    3. Unreleased release notes. These are the changelog.d notes on main that are absent from the v0.13.0 tree, which is the selection rule scripts/release_notes.py uses with changelog.d/release.json ("base": "refs/tags/v0.13.0", "version": "v0.14.0"). There are 86. 61 of them are added, breaking, changed, removed or deprecated notes, and those link to 40 docs/user sections.
    4. Line map. Each new item from steps 1 and 2 is matched to the docs/user lines on main that are new since the tag.

    Pages on main that describe behaviour 0.13.0 does not have

    No page has a version marker on these lines. The only version-scoped prose I found is "Release archives from v0.14.0 on" in install.md, and it covers attestation only.

    Page (site path) Main-only content 0.13.0 result (run)
    deployment.md (getting-started/deployment) "storage formats v14 to v16"; --bootstrap-handoff; unix:// server address; clean restart in writer topology serves v14 to v14; unexpected argument '--bootstrap-handoff'
    install.md (getting-started/install) version --json; http-contract and commit lines of version unexpected argument '--json'
    operations/upgrade.md (operations/upgrade) open accepts v14 to v16; v14 is "stamped v16 at its first publish"; stamp-v14-to-v16 see the one-way format step below
    branching/index.md (branching) branch diff, branch merge-base and … dry run statements; unpublished commits (as commit, commit publish, commit drop, --unpublished); unattached branches; names "used exactly as written" (0.13.0 trims them) error[Q001]: parse error: expected kw_create, kw_delete, kw_merge, kw_list; as unattached branch gives expected query_annotation
    branching/changes.md (branching/changes) omnigraph diff, branch diff, branch merge-base, the diff routes unrecognized subcommand 'diff'
    branching/merge.md (branching/merge) --dry-run, --as-commit unexpected argument '--dry-run' and '--as-commit'
    operations/policy.md (operations/policy) commit_publish and commit_drop actions, as commit, unattached snapshots the commands do not exist
    operations/server.md (operations/server) new routes, --bootstrap-handoff, Unix socket, Lance log targets routes absent from the 0.13.0 OpenAPI
    cli/reference.md (cli/reference) merge-base, dry run, publish and drop, cluster list, cluster members, cluster pull, --organization, v15 and v16 help-tree diff
    cli/index.md (cli) blob put and blob clear; unix:// servers; skill export and skill show unrecognized subcommand 'put' and 'skill'; unsupported storage URI scheme 'unix'
    clusters/index.md (clusters) first boot from a bootstrap receipt unexpected argument '--bootstrap-handoff'
    queries/index.md (queries-search/queries) branch read statements, return distinct, count(distinct …), aggregate comparisons, correlated-block and nearest-alias changes expected return_clause; expected kw_and, kw_or, kw_is, kw_in, comp_op; T7: filter comparisons require scalar operands
    mutations/index.md (queries-search/mutations) load csv error[Q001]: parse error: expected query_file
    search/index.md, search/embeddings.md, schema/index.md (on site) typed search options; embed exact source text; dropped-property storage text only (behaviour-change notes, not run)
    index.md (/docs) link to managed team administration text only
    blobs.md (GitHub only) blob put and blob clear; PUT and DELETE …/blob unrecognized subcommand 'put'
    cli/managed-lifecycle.md (GitHub only) cluster list, cluster pull, cluster members, --organization unrecognized subcommand 'pull'
    cli/managed-team.md (new page, GitHub only) organization members and organization invitations unrecognized subcommand 'organization'
    operations/mcp.md (new page, GitHub only) --mcp-allow-* flags and environment variables unexpected argument '--mcp-allow-writes'
    queries/settings.md (GitHub only) query_memory_bytes, write_max_bytes, load_source_max_bytes, explain_dump_dir unknown setting 'query_memory_bytes'; expected one of engine, rrf_plan, merge_lineage, ann_nprobes, stage_write_concurrency, traversal_work_limit, history_release_bytes
    queries/catalogue.md (new page, GitHub only) og_catalog scope, @Setting and the other catalogue types parse error: expected type_name
    queries/explain.md, queries/traversal.md, operations/troubleshooting.md (GitHub only) plan acceptance, typed result columns; cross-type hop bound; served write refusals text only (notes, not run)

    The one-way format step is the riskiest member of the class, because the result cannot be undone. upgrade.md says normal open accepts v14 to v16. That is true for main only:

    $ omnigraph(0.13.0) init + load            -> internal_schema_version: 14
    $ omnigraph(main) mutate --store g.omni -e 'query add() { insert Source { slug: "x", title: "X" } }'
    changed main via add: 1 nodes, 0 edges     -> internal_schema_version: 16
    $ omnigraph(0.13.0) snapshot g.omni
    Error: __manifest is stamped at internal schema v16 but this binary reads only v14 to v14 — upgrade omnigraph before opening this graph
    

    install.md warns about this for edge builds, but upgrade.md and deployment.md do not.

    Root cause

    This is a publishing defect. Each page is correct for main, but the site shows main as if it were the stable release.

    • docs/dev/documentation.md and AGENTS.md require user docs to change in the same PR as the behaviour ("Document supported behavior only"; "Update user-visible docs in the same change as a flag, endpoint, …"). So docs/user on main describes main by design.
    • .github/workflows/refresh-docs-site.yml calls the Vercel deploy hook on every push to main that touches docs/**. No workflow calls it on a release. The site repository is not public, so I could not read its sync-docs.mjs. The live site shows the 2026-10-16 edge text added by feat(release): publish daily pinnable edge builds and stamp and attest every release #1031, the latest main commit, so it renders main.
    • No ref, version label or banner ties a page to a release. The only signal is one sentence in install.md.
    • No check ties docs content to released behaviour. scripts/check-docs.py checks links, RFC metadata, the user-doc boundary, and that the skill's metadata.version and HTTP contract match the source tree. scripts/check-catalogue-docs.py and the skill tests in crates/omnigraph-cli/src/skill.rs (skill_command_index_lists_every_public_command, skill_states_the_storage_formats_this_binary_reports) compare docs with the binary built from the same commit. They prove that docs and code agree on main. They cannot see the gap to the last release.

    The site's "GitHub" link for each page goes to blob/main/content/docs/<page>.md, which returns 404. This is a separate defect in the site repository; the correct path is docs/user/<page>.md.

    Executable proof (fails on main)

    The cheapest owner is a scripts/check-docs.py-style docs check. GQT is the wrong tier because the defect is in published text, not in engine rows. The check needs no binary. It uses the release tooling's own definition of "unreleased": changelog.d notes absent from the release.json base tree. It then requires each docs/user section that such a note links to (reference definitions ../docs/user/<page>.md#<anchor>) to contain the word Unreleased.

    $ python3 check_unreleased_markers.py --root <checkout at 4d7536d>
    base refs/tags/v0.13.0, next v0.14.0: 61 unreleased notes, 40 linked docs sections checked
    22 unreleased notes link to no docs/user page (not checkable): … unattached-graph-branches.added.md, unpublished-graph-commits.added.md, blob-cli-put-clear.added.md, …
    FAIL graph-diff-and-branch-review.added.md: docs/user/branching/merge.md#preview-a-merge: unreleased in v0.14.0 (base refs/tags/v0.13.0) but the section has no 'Unreleased' marker
    FAIL load-csv-statement.added.md: docs/user/mutations/index.md#csv-loading: …
    … (40 FAIL lines)
    40 unmarked sections
    exit 1
    

    Sensitivity: in a scratch copy, adding > **Unreleased:** available from v0.14.0. under ## Preview a merge removes exactly that failure (40 → 39). This is a proof of the defect, not a finished gate. It has three gaps:

    • It misses notes without a docs link (22, including unpublished commits and unattached branches).
    • It flags notes about release infrastructure that is already live (edge-builds-pinnable, release-build-identity).
    • It does not check GQ syntax. The binary-based CLI diff covers that.

    Recommended fix

    1. Correct by design: show the latest stable tag by default, and main as "Next (unreleased)".

    • In the site's sync script, sync docs/user from the tag that releases/latest resolves to (today v0.13.0) into the default docs root. Sync main into a second root.
    • The site is Fumadocs, which supports this natively: root folders of one type (meta.json "root": "version") get a version dropdown that keeps the reader's page (Fumadocs versioning). The DocsLayout banner can label every Next page "Unreleased: describes main; the latest release is vX.Y.Z".
    • Add a release: published trigger (stable only) to refresh-docs-site.yml, next to the push-to-main trigger.
    • Build llms.txt and llms-full.txt from the stable root.
    • Set the canonical URL of Next pages to the stable page, so search lands on stable docs.
    • Fix the per-page GitHub link to point at docs/user/<page>.md at the rendered ref.

    Why this is the right shape: one fact, the git tag, decides what "released" means, and it is the same fact release.json and scripts/release_notes.py use. Nothing in docs/user has to change. At each release, Next becomes stable with no marker cleanup. It also matches what the cookbooks already do: they pin OMNIGRAPH_REF=v0.13.0 and link blob/v0.13.0/docs/user/..., and scripts/check-cookbooks.py asserts omnigraph 0.13.0.

    Tradeoffs and liability:

    2. Stopgap, now: a site-wide banner on every page, through the layout banner: "These docs describe the development branch (main). The latest release is v0.13.0. Check omnigraph version." It costs one line and removes the "reader from search never sees the warning" failure. It does not tell the reader which section is new.

    3. Alternative (the reporter's first suggestion): inline "Unreleased" markers, enforced by a check like the proof. This works on GitHub main and in the site's Next root too. Liabilities:

    • Every feature PR writes a marker, and every release must remove or rewrite about 40 of them (for example "Unreleased" becomes "Since v0.14.0").
    • The rule depends on a note linking its docs section. Today 22 unreleased notes do not, so the documentation guide would need "every added, breaking, changed or removed note links its docs section" as a rule the check enforces.
    • It needs an opt-out for release-infrastructure notes.

    I recommend it only as an addition to option 1 if main docs on GitHub must also be self-describing.

    4. Optional nightly safety net: run the CLI help-tree diff against the latest release asset. Fail when a docs/user code fence on the stable root uses a command or flag the release binary does not have. It catches what the note-based check misses, but it covers the CLI surface only and downloads a release.

    Lance upstream assessment

    Lance is not relevant to this defect. The pinned Lance is =11.0.0 (Cargo.toml, the same at v0.13.0), and upstream is at v14.0.0-beta.19. The "v14 to v16" range is OmniGraph's own __manifest stamp (omnigraph:internal_schema_version, crates/omnigraph-catalog/src/migrations.rs), not a Lance file or table format. No Lance PR or release changes how OmniGraph publishes docs. A future Lance upgrade that changes the storage format would be one more release-scoped fact that the versioned site (option 1) shows correctly without extra work.

    Related issues and PRs

    Supersession: none. No open issue covers this defect with a broader scope, and this issue stays open.

    Limitations

    • The site repository is private. I inferred its behaviour from the live HTML: Fumadocs page tree, page paths, and the edge text from feat(release): publish daily pinnable edge builds and stamp and attest every release #1031. I did not read sync-docs.mjs.
    • Seven pages (search/index.md, search/embeddings.md, schema/index.md, queries/explain.md, queries/traversal.md, operations/troubleshooting.md, index.md) are listed from the release notes and a text diff. I did not run their behaviour changes on both binaries.
    • The CLI diff compares command and flag names only. It does not detect a flag whose meaning changed.
    • The line map uses patterns, so its line counts are approximate. Every page in the table has at least one hit that I read by hand.
    • The proof script is a local script, not part of the repository. I opened no PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageAwaiting maintainer triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions