mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-21 02:28:07 +02:00
Merge branch 'main' into ragnorc/omnigraph-mcp-crate
Bring the MCP feature branch up to date with main (14 commits). One conflict — compiler/parser.rs: main's `NanoError` → `CompilerError` rename vs this branch's `@mcp` / per-param `@description` parser additions; resolved by keeping the new parsing under the renamed error type. The CLI `queries list` change (#280, surfacing `@description`/`@instruction`) auto-merged with this branch's `mcp_expose`/`tool_name` columns.
This commit is contained in:
commit
fbf455a250
110 changed files with 6396 additions and 2511 deletions
|
|
@ -22,6 +22,25 @@ A merge resolves to one of three outcomes:
|
|||
simply advances to the source.
|
||||
- **Merged** — both sides diverged; a new merge commit is created with two parents.
|
||||
|
||||
## Indexes after a merge
|
||||
|
||||
A **fast-forward** merge (the common case — the target had no conflicting
|
||||
changes, so the source's rows are adopted) does not build or rebuild indexes on
|
||||
the rows it brings into the target. Newly merged rows (and any index a table does
|
||||
not yet have) are covered the next time `optimize` runs — indexes are derived
|
||||
state, and reads stay correct in the meantime via brute-force scan over the
|
||||
not-yet-covered rows. This keeps a fast-forward merge fast (it never pays an
|
||||
inline vector/FTS rebuild on the publish path), at the cost of brute-force search
|
||||
latency on freshly merged rows until the next `optimize`.
|
||||
|
||||
A **three-way** merge (the `Merged` outcome — both branches changed the table and
|
||||
the rows were reconciled) still rebuilds the table's indexes inline today, as part
|
||||
of the publish. So a Merged-outcome merge of an embedding-bearing table pays the
|
||||
index-build cost up front.
|
||||
|
||||
Either way, run `omnigraph optimize` after a large merge to restore (or, for the
|
||||
fast-forward path, establish) full index coverage.
|
||||
|
||||
## Conflicts
|
||||
|
||||
When both branches changed the same data incompatibly, the merge fails with a
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ omnigraph mutate insert_person --params '{"name":"Mina","age":28}'
|
|||
`omnigraph query` is the canonical read command (pairs with `POST /query`);
|
||||
`omnigraph mutate` is the canonical write command (pairs with `POST /mutate`).
|
||||
The positional argument is the **stored-query name**, invoked from the served
|
||||
catalog (RFC-011 D3) — the graph is addressed by scope (`--server` / `--profile`
|
||||
catalog — the graph is addressed by scope (`--server` / `--profile`
|
||||
/ defaults), and the verb asserts the query's kind (`query` rejects a stored
|
||||
mutation, and vice-versa). The previous names `omnigraph read` and
|
||||
`omnigraph change` keep working as visible aliases — invocations emit a one-line
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
A reference for the `omnigraph` binary's command surface and the per-operator `~/.omnigraph/config.yaml` schema. For a quick-start guide, see [cli.md](index.md).
|
||||
|
||||
Top-level command families and subcommands. Graph-targeting commands accept a positional `file://`/`s3://` URI, `--server <name|url>` (an operator-defined server from `~/.omnigraph/config.yaml` by name, or a literal `http(s)://` URL, optionally with `--graph <id>` for multi-graph servers; exclusive with a positional URI), `--store <uri>` (a single graph's storage directly), or `--profile <name>` / `$OMNIGRAPH_PROFILE` (a named scope bundle; see [Scopes & profiles](#scopes--profiles-rfc-011)); `cluster` commands use `--config <dir>`, while `policy` and `queries` read a cluster's applied state via `--cluster <dir|uri>`. A remote server is addressed only with `--server` — a positional `http(s)://` URI is rejected. **`query`/`mutate` are the exception**: their positional is a stored-query *name* (RFC-011 D3), not a graph URI, so they address the graph only via `--store`/`--server`/`--profile`/defaults.
|
||||
Top-level command families and subcommands. Graph-targeting commands accept a positional `file://`/`s3://` URI, `--server <name|url>` (an operator-defined server from `~/.omnigraph/config.yaml` by name, or a literal `http(s)://` URL, optionally with `--graph <id>` for multi-graph servers; exclusive with a positional URI), `--store <uri>` (a single graph's storage directly), or `--profile <name>` / `$OMNIGRAPH_PROFILE` (a named scope bundle; see [Scopes & profiles](#scopes--profiles)); `cluster` commands use `--config <dir>`, while `policy` and `queries` read a cluster's applied state via `--cluster <dir|uri>`. A remote server is addressed only with `--server` — a positional `http(s)://` URI is rejected. **`query`/`mutate` are the exception**: their positional is a stored-query *name*, not a graph URI, so they address the graph only via `--store`/`--server`/`--profile`/defaults.
|
||||
|
||||
## Top-level commands
|
||||
|
||||
|
|
@ -13,19 +13,20 @@ Top-level command families and subcommands. Graph-targeting commands accept a po
|
|||
| `ingest` | deprecated alias of `load --from <base>` (defaults: `--from main --mode merge`); prints a one-line warning to stderr |
|
||||
| `query <name>` (alias: `read`) | run a read query. **Catalog lane** (default): `<name>` is a stored query invoked **by name** from the served catalog (served-only — address with `--server`/`--profile`; the verb asserts the query is a read). **Ad-hoc lane**: with `--query <path>` or `-e`/`--query-string <GQ>`, runs that source (the positional `<name>` then selects which query in it). No positional graph URI — address via `--store`/`--server`/`--profile`. `read` is the deprecated previous name (one-line stderr warning) |
|
||||
| `mutate <name>` (alias: `change`) | run a mutation query; same catalog (by-name, served-only, verb asserts mutation) / ad-hoc (`--query`/`-e`) lanes as `query`. `change` is the deprecated previous name (one-line stderr warning) |
|
||||
| `alias <name> [args]` | invoke an operator alias — a read-only personal binding (under `aliases:` in `~/.omnigraph/config.yaml`) to a stored query on a named server (RFC-011 D4; replaces the removed `--alias` flag; stored mutations are rejected before execution) |
|
||||
| `alias <name> [args]` | invoke an operator alias — a read-only personal binding (under `aliases:` in `~/.omnigraph/config.yaml`) to a stored query on a named server (replaces the removed `--alias` flag; stored mutations are rejected before execution) |
|
||||
| `snapshot` | print current snapshot (per-table version + row count) |
|
||||
| `export` | dump to JSONL on stdout (`--type T`, `--table K` filters) |
|
||||
| `branch create \| list \| delete \| merge` | branching ops |
|
||||
| `commit list \| show` | inspect commit graph |
|
||||
| `schema plan \| apply \| show (alias: get)` | migrations. `apply` refuses a cluster-managed graph (one whose storage is inside a cluster) and points at `cluster apply` — those graphs evolve through the cluster ledger, not a direct apply |
|
||||
| `lint` (alias: `check`) | offline / graph-backed query validation. Replaces `query lint` / `query check`, which are kept as deprecated argv-level shims that print a one-line warning and rewrite to `omnigraph lint` |
|
||||
| `cluster validate \| plan \| apply \| approve \| status \| refresh \| import \| force-unlock` | declarative cluster control plane. `validate` checks a local `cluster.yaml` folder and referenced schema/query/policy files; `plan` diffs it against local JSON state at `__cluster/state.json`, annotates dispositions, and embeds real schema-migration previews; `apply` converges the cluster — stored-query/policy catalog writes (content-addressed under `__cluster/resources/`), graph creates, schema updates (soft drops only; `--as` records the actor), and graph deletes behind a digest-bound approval from `cluster approve <resource> --as <actor>` (`apply`/`approve` default the actor from `~/.omnigraph/config.yaml`'s `operator.actor` when `--as` is omitted); what apply converges is what an `omnigraph-server --cluster <dir>` deployment serves on its next restart (`--cluster` is the server's only boot source — RFC-011 cluster-only); `status` reads the state ledger; `refresh`/`import` explicitly update local JSON state from read-only graph observations; `force-unlock <LOCK_ID>` manually removes a held local state lock by exact id |
|
||||
| `cluster validate \| plan \| apply \| approve \| status \| refresh \| import \| force-unlock` | declarative cluster control plane. `validate` checks a local `cluster.yaml` folder and referenced schema/query/policy files; `plan` diffs it against local JSON state at `__cluster/state.json`, annotates dispositions, and embeds real schema-migration previews; `apply` converges the cluster — stored-query/policy catalog writes (content-addressed under `__cluster/resources/`), graph creates, schema updates (soft drops only; `--as` records the actor), and graph deletes behind a digest-bound approval from `cluster approve <resource> --as <actor>` (`apply`/`approve` default the actor from `~/.omnigraph/config.yaml`'s `operator.actor` when `--as` is omitted); what apply converges is what an `omnigraph-server --cluster <dir>` deployment serves on its next restart (`--cluster` is the server's only boot source — cluster-only); `status` reads the state ledger; `refresh`/`import` explicitly update local JSON state from read-only graph observations; `force-unlock <LOCK_ID>` manually removes a held local state lock by exact id |
|
||||
| `optimize` | non-destructive Lance compaction (skips tables with `Blob` columns or uncovered drift; `--json` reports `skipped`) |
|
||||
| `repair [--confirm] [--force]` | preview or explicitly publish uncovered manifest/head drift. `--confirm` heals verified maintenance drift and exits non-zero if suspicious/unverifiable drift is refused; `--force --confirm` publishes suspicious/unverifiable drift after operator review |
|
||||
| `cleanup --keep N --older-than 7d --confirm` | destructive version GC (`--confirm` to execute; also needs `--yes` against a non-local `s3://` target — see *Write diagnostics & destructive confirmation*) |
|
||||
| `embed` | offline JSONL embedding pipeline |
|
||||
| `policy validate \| test \| explain` | Cedar tooling against a cluster's applied policies (`--cluster <dir>`; `--graph <id>` picks a graph's bundle when several apply). `test` takes `--tests <file>`; `explain` takes `--actor`/`--action`/`--branch`/`--target-branch` |
|
||||
| `queries list \| validate` | inspect a cluster's applied stored-query registry (`--cluster <dir\|uri>`; `--graph <id>` to scope one graph). `list` prints each query's kind (read/mutation), name, typed params, and `[mcp: …]` exposure; a query's `@description`/`@instruction` are shown as indented `description:` / `instruction:` lines when declared (omitted otherwise). `--json` emits `{name, mcp_expose, tool_name, mutation, params}` plus `description`/`instruction` **only when present** — matching the HTTP `GET /queries` catalog ([server.md](../operations/server.md)). `validate` type-checks the registry and exits non-zero on a broken query |
|
||||
| `profile list \| show [<name>]` | read-only inspection of `~/.omnigraph/config.yaml` profiles. `list` shows each profile's binding (server/cluster/store) + default graph and marks the `$OMNIGRAPH_PROFILE`-active one; JSON keeps `binding` and adds `scope_kind`, `target`, `valid`, and `error`; `show` resolves one profile's scope (endpoint + default graph), defaulting to the active profile, else the flat operator defaults |
|
||||
| `version` / `-v` | print `omnigraph 0.3.x` |
|
||||
|
||||
|
|
@ -52,7 +53,7 @@ To maintain a server-backed graph, run the `direct` verbs from a host with stora
|
|||
|
||||
## Write diagnostics & destructive confirmation
|
||||
|
||||
Two global flags make writes self-documenting and guard the dangerous ones (RFC-011 Decision 9):
|
||||
Two global flags make writes self-documenting and guard the dangerous ones:
|
||||
|
||||
- **Every write echoes its resolved target to stderr** — `omnigraph load → s3://acme/brain/graphs/knowledge.omni (direct, remote)` — so you catch a scope that resolved somewhere unexpected (e.g. *prod*) before it lands. Applies to `load`, `ingest`, `mutate`, `branch create|delete|merge`, `schema apply`, `optimize`, `repair`, `cleanup`. The line is stderr, so `--json` consumers reading stdout are unaffected; suppress it with **`--quiet`**.
|
||||
- **Destructive writes against a non-local scope require confirmation.** `cleanup`, overwrite `load` (`--mode overwrite`), and `branch delete` proceed freely against a local (`file://`) graph, but when the resolved target is **not local** (a served `http(s)://` graph or an `s3://` store/cluster) they require explicit consent: pass **`--yes`** to confirm, an interactive terminal is prompted, and a non-interactive run (no TTY, or `--json`) **refuses with an error** rather than silently destroying. `cleanup` still also requires its existing `--confirm` (preview→execute); `--yes` is the additional non-local consent.
|
||||
|
|
@ -79,15 +80,15 @@ servers: # operator-owned endpoints; names key the credentials
|
|||
url: https://graph.example.com # no tokens in this file, ever
|
||||
defaults:
|
||||
output: table # read format default, below --json/--format/alias
|
||||
server: prod # the everyday SERVED scope when no address is given (RFC-011)
|
||||
server: prod # the everyday SERVED scope when no address is given
|
||||
# store: file:///data/dev.omni # OR a zero-flag LOCAL default (mutually
|
||||
# # exclusive with `server`); the local-dev
|
||||
# # counterpart of `server`
|
||||
default_graph: knowledge # graph selected in a server/cluster scope
|
||||
clusters: # admin-only: managed-cluster storage roots (RFC-011).
|
||||
clusters: # admin-only: managed-cluster storage roots.
|
||||
brain: # the ONLY place a storage root lives in this file.
|
||||
root: s3://acme/clusters/brain
|
||||
profiles: # named scope bundles (RFC-011); pick with --profile
|
||||
profiles: # named scope bundles; pick with --profile
|
||||
staging: { server: staging, default_graph: knowledge } # a served scope
|
||||
brain-admin: { cluster: brain, default_graph: knowledge } # a direct cluster scope
|
||||
```
|
||||
|
|
@ -96,7 +97,7 @@ Absent file = empty layer. Unknown keys warn and load (a file written for a
|
|||
newer CLI works on an older one). Override the config directory with
|
||||
`$OMNIGRAPH_HOME`.
|
||||
|
||||
#### Scopes & profiles (RFC-011)
|
||||
#### Scopes & profiles
|
||||
|
||||
A command resolves a **scope** — a server, a cluster, or a store — then selects a
|
||||
graph in it; the served-vs-direct access path is derived from the scope, not
|
||||
|
|
@ -116,14 +117,15 @@ sticky "current" mode. Inspect what is defined with `omnigraph profile list` and
|
|||
`--cluster <root> --graph <id>`. A `--graph` flag overrides the profile's default.
|
||||
- A `server`-bound scope on a maintenance verb, or a `cluster`-bound scope on a
|
||||
data verb, is rejected with a message pointing at the right addressing.
|
||||
- **No graph selected (RFC-011 D7).** When a scope has no `--graph` and no
|
||||
- **No graph selected.** When a scope has no `--graph` and no
|
||||
`default_graph`, the CLI never silently picks:
|
||||
- **Cluster scope** — exactly **one** applied graph is used automatically;
|
||||
**several** errors and lists the candidates (from the served catalog).
|
||||
- **Server scope** — a multi-graph server (any non-empty `GET /graphs`, even a
|
||||
single entry) errors and lists the candidates: you must pass `--graph <id>`.
|
||||
A single-graph / flat server (405 on `/graphs`), or one whose `/graphs` is
|
||||
policy-gated or unreachable, uses its bare URL as before.
|
||||
- **Server scope** — an `omnigraph-server` is always cluster-backed, so its
|
||||
`GET /graphs` lists the graphs and you must pass `--graph <id>` (the CLI
|
||||
lists the candidates if you omit it). It falls back to the bare URL only
|
||||
when `/graphs` is unavailable: policy-gated, unreachable, or a
|
||||
non-`omnigraph` endpoint.
|
||||
|
||||
`--target`, `--cluster-graph`, and the positional-`http(s)://`→remote dispatch
|
||||
have been **removed** (`--graph` is now the one graph selector across server and
|
||||
|
|
@ -158,7 +160,7 @@ aliases:
|
|||
|
||||
`omnigraph alias triage 2026-06-01` invokes
|
||||
`POST <server>/graphs/spike/queries/weekly_triage` with the keyed
|
||||
credential. Aliases live in their own `alias` namespace (RFC-011 Decision 4),
|
||||
credential. Aliases live in their own `alias` namespace,
|
||||
so an alias can never shadow — or be shadowed by — a built-in verb. (The old
|
||||
`--alias <name>` flag on `query`/`mutate` was removed.)
|
||||
|
||||
|
|
|
|||
|
|
@ -231,9 +231,11 @@ Policy entries additionally record their applied `applies_to` bindings as
|
|||
normalized typed refs — the state ledger is serving-sufficient for the
|
||||
future server-boot stage. A change to `applies_to` alone (the policy file
|
||||
digest unchanged) appears in the plan as an Update marked `binding_change`
|
||||
(human output: `[bindings]`), applies like any catalog change, and counts
|
||||
toward convergence; ledgers written before this field existed are backfilled
|
||||
by the next apply.
|
||||
(human output: `[bindings]`), and as `metadata_change: policy_bindings` in
|
||||
structured output. Embedding provider entries similarly carry their resolved
|
||||
profile in the ledger; pre-profile ledgers are backfilled by an Update with
|
||||
`metadata_change: embedding_profile`. These metadata-only updates apply like
|
||||
catalog changes and count toward convergence.
|
||||
|
||||
Each plan change carries a `disposition` field — an honest preview of what
|
||||
`cluster apply` will do with it in this stage: `applied` (executes), `derived`
|
||||
|
|
@ -322,7 +324,9 @@ cluster apply until the approval-artifact stage. Unsupported migrations
|
|||
(e.g. changing a property's type), engine lock contention, or graphs with
|
||||
user branches fail loudly as `schema_apply_failed` with the engine's message;
|
||||
dependent changes are demoted to `blocked` and graph-moving work stops for
|
||||
the run.
|
||||
the run. These pre-movement failures are checked before the cluster schema
|
||||
recovery sidecar is created, so they do not leave stale recovery files behind
|
||||
or brick later server boot.
|
||||
|
||||
`cluster plan` previews schema updates with the engine's real migration plan:
|
||||
each schema change carries a `migration` field (`supported` + typed steps),
|
||||
|
|
@ -390,7 +394,7 @@ omnigraph-server --cluster company-brain --bind 0.0.0.0:8080
|
|||
```
|
||||
|
||||
`--cluster <dir>` is an **exclusive boot source** (axiom 15): it cannot
|
||||
combine with a graph URI, `--target`, or `--config`, and in this mode
|
||||
combine with a graph URI or `--config`, and in this mode
|
||||
`omnigraph.yaml` is never read — not for graphs, not for queries, not for
|
||||
policies. The server serves the **applied revision**: graph roots recorded in
|
||||
`state.json`, stored-query and policy content from the content-addressed
|
||||
|
|
@ -402,20 +406,29 @@ drift is visible. Routing is always multi-graph (`/graphs/{id}/...`). Bearer
|
|||
tokens and the bind address stay process-level (flags/env) — they are
|
||||
per-replica facts, not cluster facts.
|
||||
|
||||
Boot is fail-fast: missing or unreadable state, pending recovery sidecars,
|
||||
missing/tampered catalog blobs, policy entries without binding metadata
|
||||
(pre-binding ledgers — re-run `cluster apply`), an empty graph set, more than
|
||||
one policy bundle binding a single scope (split or merge bundles; stacked
|
||||
scopes are a later stage), unopenable graph roots, and stored queries that no
|
||||
longer type-check all refuse startup with a remedy. A held state lock is
|
||||
*not* an error — boot reads the atomically-replaced state file without
|
||||
Boot is fail-fast for cluster-global readiness failures: missing or
|
||||
unreadable state, invalid/unattributable recovery sidecars,
|
||||
missing/tampered shared catalog blobs, policy entries without binding
|
||||
metadata (pre-binding ledgers — re-run `cluster apply`), an empty graph set,
|
||||
more than one policy bundle binding a single scope (split or merge bundles;
|
||||
stacked scopes are a later stage), cluster policy problems, or zero healthy
|
||||
graphs. Valid graph-attributed recovery sidecars, unopenable graph roots, and
|
||||
stored queries that no longer type-check quarantine that graph instead; the
|
||||
server logs startup diagnostics, skips the graph's queries and graph-only
|
||||
policy bindings, and serves any remaining healthy graphs. A held state lock
|
||||
is *not* an error — boot reads the atomically-replaced state file without
|
||||
locking.
|
||||
|
||||
Use `omnigraph-server --require-all-graphs` (or
|
||||
`OMNIGRAPH_REQUIRE_ALL_GRAPHS=1`) when degraded serving is not acceptable; it
|
||||
promotes every graph-local quarantine or startup failure back to a boot error.
|
||||
|
||||
Serving is static per process: the server reads the applied revision once at
|
||||
startup, so picking up newly applied state means restarting it. Stored
|
||||
queries are all listed in `GET /queries` in cluster mode (the cluster
|
||||
registry has no expose flag; exposure becomes a policy decision in a later
|
||||
phase).
|
||||
startup, so picking up newly applied state means restarting it. `GET /graphs`
|
||||
lists only ready/served graphs; quarantined graphs are omitted and their
|
||||
routes return 404. Stored queries are all listed in `GET /queries` in cluster
|
||||
mode (the cluster registry has no expose flag; exposure becomes a policy
|
||||
decision in a later phase).
|
||||
|
||||
## Status
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ only the URI and credentials, no checkout of the config repo. The ledger and
|
|||
catalog on the bucket are the deployment artifact.
|
||||
|
||||
`--cluster` is an **exclusive boot source**: it cannot be combined with a
|
||||
graph URI, `--target`, or `--config`, and `omnigraph.yaml` is never read in
|
||||
graph URI or `--config`, and `omnigraph.yaml` is never read in
|
||||
this mode. Routing is always multi-graph:
|
||||
|
||||
```bash
|
||||
|
|
@ -221,7 +221,8 @@ applied revision is not safely servable. Each refusal names its remedy:
|
|||
| Boot error | Meaning | Remedy |
|
||||
|---|---|---|
|
||||
| `cluster_state_missing` | no ledger | `cluster import`, then `apply` |
|
||||
| `cluster_recovery_pending` | interrupted operation awaiting sweep | run `cluster apply` (or any state-mutating command), restart |
|
||||
| `cluster_recovery_pending` | graph was quarantined because an interrupted operation awaits sweep | run `cluster apply` (or any state-mutating command), restart |
|
||||
| `cluster_no_healthy_graphs` | every applied graph is quarantined or failed startup | sweep/fix the graph-specific failures, then restart |
|
||||
| `catalog_payload_missing` / `…_digest_mismatch` | catalog blob lost or tampered | `cluster refresh`, then `apply`, restart |
|
||||
| `policy_bindings_missing` | ledger predates binding metadata | re-run `cluster apply` (backfills), restart |
|
||||
| `cluster_empty` | applied revision has no graphs | apply a cluster with ≥1 graph |
|
||||
|
|
@ -231,6 +232,13 @@ A held *state lock* is deliberately **not** a boot error — the server reads
|
|||
the atomically-replaced ledger without locking, so serving never contends
|
||||
with an in-flight apply.
|
||||
|
||||
When at least one graph is healthy, graph-attributed recovery sidecars and
|
||||
graph-local startup failures do not block the whole server. The affected
|
||||
graph is skipped, its graph-only policy bindings and queries are omitted,
|
||||
and `/graphs` lists only the ready graphs. Pass
|
||||
`omnigraph-server --require-all-graphs` or set
|
||||
`OMNIGRAPH_REQUIRE_ALL_GRAPHS=1` to make any such quarantine fail startup.
|
||||
|
||||
## 6. Deployment patterns
|
||||
|
||||
- **Replicas**: any number of `--cluster` servers can serve the same config
|
||||
|
|
@ -273,7 +281,7 @@ a cluster are created by `cluster apply`, not by hand.
|
|||
|
||||
If the cluster has exactly **one** applied graph you can omit `--graph` — it is
|
||||
used automatically. With **several**, omitting `--graph` errors and lists the
|
||||
candidates (RFC-011 D7); it never picks one for you.
|
||||
candidates; it never picks one for you.
|
||||
|
||||
Against an **`s3://`-backed cluster** the resolved graph storage is non-local, so a
|
||||
destructive `cleanup` additionally requires **`--yes`** (an interactive prompt
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ When no positional args are given, the image entrypoint
|
|||
|---|---|
|
||||
| `OMNIGRAPH_CLUSTER` | Cluster boot source — a config directory or a storage-root URI, forwarded as `--cluster`. The only boot source. |
|
||||
| `OMNIGRAPH_BIND` | Listen address (default `0.0.0.0:8080`). |
|
||||
| `OMNIGRAPH_REQUIRE_ALL_GRAPHS` | When truthy, forwarded as `--require-all-graphs`: any graph-local quarantine or startup failure aborts cluster boot instead of serving the healthy subset. |
|
||||
|
||||
Per-graph and server-level Cedar policy come from the cluster's applied
|
||||
revision (authored in `cluster.yaml` and published with `cluster apply`),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
- **D₂ parse-time rejection**: a single mutation query that mixes inserts/updates with deletes errors out *before any I/O* with kind `BadRequest`. Message: `mutation '<name>' on the same query mixes inserts/updates and deletes; split into separate mutations: (1) inserts and updates, then (2) deletes`. See [query-language.md](../queries/index.md) for the rule.
|
||||
- `MergeConflicts(Vec<MergeConflict>)`
|
||||
|
||||
Compiler-side `NanoError` covers parse / catalog / type / storage / plan / execution / arrow / lance / IO / manifest / unique-constraint, each with structured spans (`SourceSpan { start, end }`) for ariadne-style diagnostics.
|
||||
Compiler-side `CompilerError` covers parse / catalog / type / storage / plan / execution / arrow / lance / IO / manifest / unique-constraint, each with structured spans (`SourceSpan { start, end }`) for ariadne-style diagnostics. The legacy `NanoError` name remains as a deprecated compatibility alias.
|
||||
|
||||
## Result serialization (`omnigraph_compiler::result::QueryResult`)
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
backstop, so it does as much as it can and converges on re-run. The CLI reports
|
||||
any failed tables; rerun `cleanup` to retry them.
|
||||
- CLI guards with `--confirm`; without it, prints a preview line.
|
||||
- **Non-local consent (RFC-011 D9).** Against a non-local target (an `s3://` store/cluster), `cleanup` additionally requires `--yes` on top of `--confirm`: a TTY is prompted, and a non-interactive run (no TTY, or `--json`) refuses rather than destroying. A local (`file://`) target needs only `--confirm`. The same `--yes` gate applies to overwrite `load` and `branch delete`; every maintenance run echoes its resolved target to stderr (suppress with `--quiet`).
|
||||
- **Non-local consent.** Against a non-local target (an `s3://` store/cluster), `cleanup` additionally requires `--yes` on top of `--confirm`: a TTY is prompted, and a non-interactive run (no TTY, or `--json`) refuses rather than destroying. A local (`file://`) target needs only `--confirm`. The same `--yes` gate applies to overwrite `load` and `branch delete`; every maintenance run echoes its resolved target to stderr (suppress with `--quiet`).
|
||||
- **Recovery floor:** `--keep < 3` may garbage-collect versions that crash recovery needs as a rollback target. Default `--keep 10` is safe.
|
||||
- **Orphaned-branch reconciliation:** before the version GC, cleanup reclaims any per-table or commit-graph branch absent from the manifest branch list. These orphans arise when a `branch_delete` flips the manifest authority but a downstream best-effort reclaim does not complete (see [branches-commits.md](../branching/index.md)). The reconciler is idempotent (it no-ops once nothing is orphaned), runs regardless of the `keep_versions` / `older_than` values (those gate version GC only), and never reclaims `main` or system-branch forks. Reclaimed forks are logged.
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ The default actor identity for CLI direct-engine (`--store`) writes is
|
|||
`operator.actor` in `~/.omnigraph/config.yaml`. Override per-invocation with
|
||||
`--as <ACTOR>` — `--as` wins, otherwise `operator.actor`, otherwise no actor.
|
||||
Remote HTTP writes ignore both — they resolve their actor server-side from the
|
||||
bearer token. (Direct-store access carries no Cedar policy under RFC-011; policy
|
||||
bearer token. (Direct-store access carries no Cedar policy; policy
|
||||
lives in the cluster/server.)
|
||||
|
||||
## CLI
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# HTTP Server (`omnigraph-server`)
|
||||
|
||||
Axum 0.8 + tokio + utoipa-generated OpenAPI. **Cluster-only boot** (RFC-011): the server always boots from a cluster (`--cluster <dir | s3://…>`) and serves N graphs (N ≥ 1) under cluster routes. There is no longer a single-graph flat-route mode, no positional `<URI>` boot, no `--target`, and no `omnigraph.yaml`-`graphs:`-map boot. All HTTP is nested under `/graphs/{graph_id}/...`; `/healthz` and the management `/graphs` enumeration stay flat.
|
||||
Axum 0.8 + tokio + utoipa-generated OpenAPI. **Cluster-only boot**: the server always boots from a cluster (`--cluster <dir | s3://…>`) and serves N graphs (N ≥ 1) under cluster routes. There is no longer a single-graph flat-route mode, no positional `<URI>` boot, no `--target`, and no `omnigraph.yaml`-`graphs:`-map boot. All HTTP is nested under `/graphs/{graph_id}/...`; `/healthz` and the management `/graphs` enumeration stay flat.
|
||||
|
||||
## Boot
|
||||
|
||||
|
|
@ -15,11 +15,24 @@ omnigraph-server --cluster <dir | s3://…> --bind 0.0.0.0:8080
|
|||
startup configs (id, URI, optional per-graph policy, stored-query
|
||||
registry) plus an optional server-level policy, then opens every
|
||||
configured graph in parallel at startup (bounded concurrency = 4,
|
||||
fail-fast on the first open error). Routing is always multi-graph —
|
||||
quarantining graph-specific open failures). Routing is always multi-graph —
|
||||
requests to bare flat protected paths (`/read`, `/snapshot`, …) return
|
||||
404; the served surface is `/graphs/{graph_id}/...`. See
|
||||
[cluster-config.md](../clusters/config.md#serving-from-the-cluster-the-mode-switch)
|
||||
for what is read and the fail-fast readiness rules.
|
||||
for what is read and the readiness rules.
|
||||
|
||||
Readiness is fail-fast for cluster-global problems: missing or unreadable
|
||||
state, invalid/unattributable recovery sidecars, unreadable shared catalog
|
||||
payloads, cluster policy errors, or zero healthy graphs. Graph-attributed
|
||||
pending recovery sidecars and graph-specific startup failures quarantine
|
||||
that graph instead; the server logs startup diagnostics and serves the
|
||||
remaining healthy graphs. `GET /graphs` enumerates ready/served graphs only,
|
||||
so quarantined graphs are absent and their routes return 404.
|
||||
|
||||
Operators who want the original all-or-nothing boot contract can pass
|
||||
`--require-all-graphs` or set `OMNIGRAPH_REQUIRE_ALL_GRAPHS=1`. In that mode,
|
||||
any graph quarantine, graph-open failure, stored-query startup failure, or
|
||||
embedding-provider resolution failure aborts startup.
|
||||
|
||||
A scheme-qualified argument (`s3://…`) reads the ledger straight from the
|
||||
storage root, with no local config directory. `--bind`,
|
||||
|
|
@ -27,7 +40,7 @@ storage root, with no local config directory. `--bind`,
|
|||
|
||||
### Stored-query validation at startup
|
||||
|
||||
If a graph declares a `queries:` registry (see [cli-reference](../cli/reference.md)), the server **loads and type-checks every stored query against that graph's live schema at startup** and **refuses to boot** if any query references a type or property the schema lacks — the same fail-loud posture as a malformed policy file, so schema drift surfaces at the deploy boundary rather than at invocation. Two MCP-exposed queries claiming the same tool name is likewise a boot error. Non-blocking advisories (e.g. an MCP-exposed query with a vector parameter an agent cannot supply) are logged. Validate offline before deploying with `omnigraph queries validate`. Discover the exposed queries as a typed tool catalog with `GET /queries`, and invoke one over HTTP with `POST /queries/{name}` (both below).
|
||||
If a graph declares a `queries:` registry (see [cli-reference](../cli/reference.md)), the server **loads and type-checks every stored query against that graph's live schema at startup**. Query parse/type failures quarantine that graph; if no graph remains healthy, startup refuses. Two MCP-exposed queries claiming the same tool name are likewise graph-local startup failures. Non-blocking advisories (e.g. an MCP-exposed query with a vector parameter an agent cannot supply) are logged. Validate offline before deploying with `omnigraph queries validate`. Discover the exposed queries as a typed tool catalog with `GET /queries`, and invoke one over HTTP with `POST /queries/{name}` (both below).
|
||||
|
||||
## Endpoint inventory
|
||||
|
||||
|
|
@ -62,7 +75,7 @@ Server-level management endpoints:
|
|||
|
||||
| Method | Path | Auth | Action |
|
||||
|---|---|---|---|
|
||||
| GET | `/graphs` | bearer + `graph_list` on `Server::"root"` | list registered graphs |
|
||||
| GET | `/graphs` | bearer + `graph_list` on `Server::"root"` | list ready/served graphs |
|
||||
|
||||
### Stored-query catalog (`GET /queries`)
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ boots from the applied cluster ledger, so `cluster validate`, `plan`, and
|
|||
needs no key. Vector dimensions stay schema-driven by the target `Vector(N)`
|
||||
column.
|
||||
|
||||
Direct single-graph serving, embedded callers, and the offline
|
||||
Direct (`--store`) access, embedded callers, and the offline
|
||||
`omnigraph embed` pipeline use environment configuration unless they inject an
|
||||
`EmbeddingConfig` directly.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue