Remove developer-only scaffolding that leaked into the public user/operator docs, while preserving every user-facing behavior, command, flag, endpoint, constant, and env var. No behavior changes. Removed across 18 files: - internal ticket / sequencing refs (MR-NNN, RFC-NNN, "Phase N"); - source-code paths (crates/**/*.rs, *.pest) and internal struct/function dumps (e.g. the QueryIR / GraphCommit / SchemaMigrationPlan Rust types, internal fn names like fork_branch_from_state, optimize_all_tables); - Lance-internal blocker prose (upstream issue numbers, blob-decode cause, sidecar Phase-B/C mechanics) — keeping the user-visible behavior (e.g. "optimize skips Blob-column tables; reads/writes unaffected"); - pre-v0.4.0 Run-state-machine archaeology. Internal IR/lowering/recovery-internals sections were either trimmed to a brief user-facing note (e.g. "Traversal execution", "interrupted writes recover automatically; recovery commits are recorded under actor omnigraph:recovery") or removed. Kept: all language syntax, lint codes, Cedar actions/scopes, endpoints, error taxonomy, every constant and env var (verified none dropped from the constants cheat-sheet), and the operator-facing explanations of on-disk artifacts. Residual "legacy" mentions are all user-facing (the deprecated omnigraph.yaml, the legacy token chain, old command names). Verified: zero internal-scaffolding leaks (MR/RFC/Phase/.rs/.pest = 0) across docs/user; zero broken links; check-agents-md.sh green. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
3.8 KiB
Query Language (.gq)
Query declarations
query <name>($p1: T1, $p2: T2?, …)
@description("…") @instruction("…") {
…
}
Two body shapes:
- Read:
match { … } return { … } [order { … }] [limit N]— covered on this page. - Mutation: one or more of
insert | update | deletestatements — see mutations.
Multi-modal search functions (nearest, bm25, rrf, …) used inside match,
return, and order are documented on the search page.
Param types reuse all schema scalars; trailing ? makes a param optional. The compiler reserves $__nanograph_now for now().
MATCH clauses
- Binding:
$x: NodeType { prop: <literal | $param | now()>, … } - Traversal:
$src EDGE_NAME { min, max? } $dst— variable-length paths via hop bounds; default 1..1 if bounds omitted. - Filter:
<expr> <op> <expr>with operators>=,<=,!=,>,<,=, and stringcontains. - Negation:
not { clause+ }— desugars to anti-join over the inner pipeline.
RETURN clause
return { <expr> [as <alias>], … } with expressions:
- Variable / property access:
$x,$x.prop - Literals: string, int, float, bool, list
now()- Aggregates:
count,sum,avg,min,max - Search functions (so you can return a score column)
AliasRef— re-use a previous projection alias
ORDER & LIMIT
order { <expr> [asc|desc], … }— supports plain expressions andnearest(...).limit <integer>— required when there is anearest(...)ordering.- Total, deterministic order. Rows with equal user-sort keys are broken by the bound entities' key columns (
<var>.id, ascending) appended as a final tie-break, so the result is a total order — reproducible across runs, andorder … limit Nreturns a deterministic top-N even when ties straddle the cutoff. (Aggregate results have no entity-key columns; their group rows are already distinct on the projected group keys.) - NULL placement is nulls-first ascending, nulls-last descending (i.e.
nulls_first = !descending): a NULL sorts as if smaller than any value.
Write statements (insert / update / delete) are documented on the
mutations page.
Traversal execution
Variable-length traversals (Expand) are executed one of two ways, chosen per-expand by a cost model over cheap manifest counts (frontier size, edge count, source-vertex count, hops) plus index coverage: selective traversals (small frontier relative to the source set) resolve neighbors from the persisted src/dst BTREE (one indexed scan per hop); dense / deep / large-frontier traversals — or those whose BTREE coverage is degraded so a full scan would be paid per hop — use an in-memory CSR adjacency index. Both produce identical results. The OMNIGRAPH_EXPAND_INDEXED_MAX_FRONTIER / OMNIGRAPH_EXPAND_INDEXED_MAX_HOPS ceilings bound the initial dispatch frontier/hops (beyond them CSR is always used); the cost model estimates total indexed work as ~hops × frontier × fanout and prices dense fan-out toward CSR — they are not a hard per-hop bound. OMNIGRAPH_TRAVERSAL_MODE=indexed|csr forces a mode (see constants).
Linting & validation
Codes seen so far:
- Q000 (Error): parse error
- L201 (Warning): nullable property never set by any UPDATE — "{type}.{prop} exists in schema but no update query sets it"
- (Warning): mutation declares no params — hardcoded mutations are easy to miss
- Plus all type errors from type checking (undefined types, mismatched operators, undefined edges, etc.)
Lint output reports an overall status, per-query results (name, kind, status, any error and warnings), and structured findings (severity, code, message, and the type/property/query they apply to).
CLI exits non-zero only on status = Error.