You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
docs: pages on main describe unreleased behaviour without marking it #985
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 26docs/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.
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.
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 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.
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.
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.
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.
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)
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.jsonbase 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 DocsLayoutbanner 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.
The page map must work per version. The site maps a subset of pages. New pages, such as operations/mcp.md, exist only in Next, so the sync must tolerate a different page set for each version.
Build time roughly doubles. That is small for about 40 pages.
The work is in the site repository plus one workflow line here. There is no engine, format or protocol risk, so the decision is cheap to reverse.
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.
Refresh skills and operator guides for 0.13 #892 (open, CONFLICTING, last commit 2026-10-07) refreshes the skill and operator guides "for 0.13" on main. It adds no markers, and while the site renders main it does not fix this issue. Under option 1, its 0.13-specific guide text belongs on the stable docs. Its skill text already ships inside the binary (omnigraph skill show, main only), and that is versioned by construction.
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.
Activity
ragnorc commentedon Oct 17, 2026
Triage: reproduced, and the defect is wider than the report
Summary
The site omnigraph.dev/docs shows the
docs/userpages frommain. The installer and the cookbooks install 0.13.0.mainis 97 commits ahead ofv0.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 amainbuild 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/userpages. 17 of these pages are on omnigraph.dev, and the other 9 are on GitHubmainonly. The reporter listed 5 pages.4d7536d68b1db6da34bf9cff22a90d9fdd77bed4, rechecked before posting. Clean detached worktree.cargo build --locked -p omnigraph-cli -p omnigraph-server(debug profile) printsomnigraph 0.14.0/internal-schema 16 (serves v14 to v16)/http-contract 0.13.curl -fsSL https://raw.githubusercontent.com/ModernRelay/omnigraph/main/scripts/install.sh | INSTALL_DIR=/tmp/og013 bash(stable channel, releasev0.13.0).Reporter's steps on 0.13.0:
The same documented commands succeed on main. For example,
omnigraph diff --from main --to review --store graph.omniprintsinsert node Source bench.omnigraph branch merge review --into main --as-commitfollowed byomnigraph commit publish <id> --uri graph.omniprintspublished commit … on main.Differences from the report:
docs/userunder its own paths, for example/docs/getting-started/deploymentand/docs/queries-search/queries. Some main-only pages are not on the site, but GitHubmainshows them and other pages link to them.install.mdwarning ("Documentation onmainmay 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.
--helpfor 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 …andorganization invitations …,--organizationonlogin,logout,use,cluster createandcluster operation, andversion --json.omnigraph-server --helpon main adds--bootstrap-handoff,--mcp-allow-adhoc,--mcp-allow-writesand--mcp-allowed-host. Theopenapi.jsondiff (v0.13.0..main) addsGET /graphs/{id}/diff,GET …/branches/diff,GET …/branches/merge-base,POST …/commits/{commit_id}/publish,DELETE …/commits/{commit_id},PUTandDELETE …/blob, andGET /.well-known/oauth-protected-resource/{resource_path}.HTTP_API_CONTRACTstays0.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.changelog.dnotes on main that are absent from thev0.13.0tree, which is the selection rulescripts/release_notes.pyuses withchangelog.d/release.json("base": "refs/tags/v0.13.0","version": "v0.14.0"). There are 86. 61 of them areadded,breaking,changed,removedordeprecatednotes, and those link to 40docs/usersections.docs/userlines 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.deployment.md(getting-started/deployment)--bootstrap-handoff;unix://server address; clean restart in writer topologyserves v14 to v14;unexpected argument '--bootstrap-handoff'install.md(getting-started/install)version --json;http-contractandcommitlines ofversionunexpected argument '--json'operations/upgrade.md(operations/upgrade)stamp-v14-to-v16branching/index.md(branching)branch diff,branch merge-baseand… dry runstatements; 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 branchgivesexpected query_annotationbranching/changes.md(branching/changes)omnigraph diff,branch diff,branch merge-base, the diff routesunrecognized subcommand 'diff'branching/merge.md(branching/merge)--dry-run,--as-commitunexpected argument '--dry-run'and'--as-commit'operations/policy.md(operations/policy)commit_publishandcommit_dropactions,as commit, unattached snapshotsoperations/server.md(operations/server)--bootstrap-handoff, Unix socket, Lance log targetscli/reference.md(cli/reference)cluster list,cluster members,cluster pull,--organization, v15 and v16cli/index.md(cli)blob putandblob clear;unix://servers;skill exportandskill showunrecognized subcommand 'put'and'skill';unsupported storage URI scheme 'unix'clusters/index.md(clusters)unexpected argument '--bootstrap-handoff'queries/index.md(queries-search/queries)return distinct,count(distinct …), aggregate comparisons, correlated-block and nearest-alias changesexpected return_clause;expected kw_and, kw_or, kw_is, kw_in, comp_op;T7: filter comparisons require scalar operandsmutations/index.md(queries-search/mutations)load csverror[Q001]: parse error: expected query_filesearch/index.md,search/embeddings.md,schema/index.md(on site)index.md(/docs)blobs.md(GitHub only)blob putandblob clear;PUTandDELETE …/blobunrecognized subcommand 'put'cli/managed-lifecycle.md(GitHub only)cluster list,cluster pull,cluster members,--organizationunrecognized subcommand 'pull'cli/managed-team.md(new page, GitHub only)organization membersandorganization invitationsunrecognized subcommand 'organization'operations/mcp.md(new page, GitHub only)--mcp-allow-*flags and environment variablesunexpected argument '--mcp-allow-writes'queries/settings.md(GitHub only)query_memory_bytes,write_max_bytes,load_source_max_bytes,explain_dump_dirunknown setting 'query_memory_bytes'; expected one of engine, rrf_plan, merge_lineage, ann_nprobes, stage_write_concurrency, traversal_work_limit, history_release_bytesqueries/catalogue.md(new page, GitHub only)og_catalogscope,@Settingand the other catalogue typesparse error: expected type_namequeries/explain.md,queries/traversal.md,operations/troubleshooting.md(GitHub only)The one-way format step is the riskiest member of the class, because the result cannot be undone.
upgrade.mdsays normal open accepts v14 to v16. That is true for main only:install.mdwarns about this for edge builds, butupgrade.mdanddeployment.mddo not.Root cause
This is a publishing defect. Each page is correct for
main, but the site showsmainas if it were the stable release.docs/dev/documentation.mdandAGENTS.mdrequire 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, …"). Sodocs/useronmaindescribesmainby design..github/workflows/refresh-docs-site.ymlcalls the Vercel deploy hook on every push tomainthat touchesdocs/**. No workflow calls it on a release. The site repository is not public, so I could not read itssync-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 latestmaincommit, so it rendersmain.install.md.scripts/check-docs.pychecks links, RFC metadata, the user-doc boundary, and that the skill'smetadata.versionand HTTP contract match the source tree.scripts/check-catalogue-docs.pyand the skill tests incrates/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 onmain. 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 isdocs/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.dnotes absent from therelease.jsonbasetree. It then requires eachdocs/usersection that such a note links to (reference definitions../docs/user/<page>.md#<anchor>) to contain the wordUnreleased.Sensitivity: in a scratch copy, adding
> **Unreleased:** available from v0.14.0.under## Preview a mergeremoves exactly that failure (40 → 39). This is a proof of the defect, not a finished gate. It has three gaps:edge-builds-pinnable,release-build-identity).Recommended fix
1. Correct by design: show the latest stable tag by default, and
mainas "Next (unreleased)".docs/userfrom the tag thatreleases/latestresolves to (todayv0.13.0) into the default docs root. Syncmaininto a second root.meta.json"root": "version") get a version dropdown that keeps the reader's page (Fumadocs versioning). TheDocsLayoutbannercan label every Next page "Unreleased: describesmain; the latest release is vX.Y.Z".release: publishedtrigger (stable only) torefresh-docs-site.yml, next to the push-to-maintrigger.llms.txtandllms-full.txtfrom the stable root.docs/user/<page>.mdat 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.jsonandscripts/release_notes.pyuse. Nothing indocs/userhas to change. At each release, Next becomes stable with no marker cleanup. It also matches what the cookbooks already do: they pinOMNIGRAPH_REF=v0.13.0and linkblob/v0.13.0/docs/user/..., andscripts/check-cookbooks.pyassertsomnigraph 0.13.0.Tradeoffs and liability:
cluster force-unlock#983 and docs(schema): OG-DS-102/103/104 are listed as refusals, but populated drops plan as supported #984, land onmainand reach the stable site only at the next release. To avoid that, render adocs/v0.13branch cut from the tag and cherry-pick docs-only fixes to it. That is one more branch to keep. My recommendation is to render the tag and backport only when a stable-docs error is serious.operations/mcp.md, exist only in Next, so the sync must tolerate a different page set for each version.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. Checkomnigraph 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
mainand in the site's Next root too. Liabilities:added,breaking,changedorremovednote links its docs section" as a rule the check enforces.I recommend it only as an addition to option 1 if
maindocs 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/usercode 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 atv0.13.0), and upstream is at v14.0.0-beta.19. The "v14 to v16" range is OmniGraph's own__manifeststamp (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
main; it is the trigger here, not a bug.CONFLICTING, last commit 2026-10-07) refreshes the skill and operator guides "for 0.13" onmain. It adds no markers, and while the site rendersmainit does not fix this issue. Under option 1, its 0.13-specific guide text belongs on the stable docs. Its skill text already ships inside the binary (omnigraph skill show, main only), and that is versioned by construction.release.jsonbaseas the source of truth, which both option 1 and the proof check use.OG-DS-102/103/104) was reproduced on both 0.13.0 and main. It is a docs-versus-code error, not version skew, so it does not supersede this issue and is not superseded by it. Its fix will need to reach the stable docs under option 1.deployment.mdimage registry) is a separate defect on the same page.cluster force-unlock#983 are sibling 0.13.0 docs issues from the same reporter. They raise the same backport question.omnigraph embedvectors from the schema's@embeddeclarations #952.Supersession: none. No open issue covers this defect with a broader scope, and this issue stays open.
Limitations
sync-docs.mjs.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.