From 9c7ed6dcd039852cd3b65216ae37edadb3ec3adf Mon Sep 17 00:00:00 2001 From: aaltshuler Date: Sun, 14 Jun 2026 21:12:47 +0300 Subject: [PATCH] =?UTF-8?q?docs(rfc):=20RFC-011=20=E2=80=94=20rename=20"co?= =?UTF-8?q?ntext"=20=E2=86=92=20"profile"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "context" (borrowed from kubectl) collides with agent/LLM "context". Rename the named-operator-defaults concept to "profile" (AWS-CLI precedent: --profile, OMNIGRAPH_PROFILE, profiles:). Doc-only — the concept was unshipped. "scope" (the resolved addressing target a profile populates) is unchanged. Co-Authored-By: Claude Opus 4.8 --- docs/dev/index.md | 2 +- docs/dev/rfc-011-cli-refactoring.md | 72 ++++++++++++++--------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/docs/dev/index.md b/docs/dev/index.md index c41853ed..8f4cf860 100644 --- a/docs/dev/index.md +++ b/docs/dev/index.md @@ -80,7 +80,7 @@ Working documents for in-flight feature work. Removed when the work lands. | Deprecate `omnigraph.yaml` — one concern per config surface; key-by-key migration map and staged retirement | [rfc-008-deprecate-omnigraph-yaml.md](rfc-008-deprecate-omnigraph-yaml.md) | | Unify CLI embedded/remote access paths — parity referee, shared wire-DTO crate, `GraphClient` trait, declared plane capabilities | [rfc-009-unify-access-paths.md](rfc-009-unify-access-paths.md) | | Restructure the CLI around explicit planes — one graph-addressing model, declared capability surface, plane-grouped help (expands RFC-009 Phase 4) | [rfc-010-cli-planes-restructure.md](rfc-010-cli-planes-restructure.md) | -| CLI refactoring — one addressing & config model post-`omnigraph.yaml`: scope + `--graph` + derived access path, served-default / privileged-direct, contexts, named queries, capability classifier (completes RFC-008) | [rfc-011-cli-refactoring.md](rfc-011-cli-refactoring.md) | +| CLI refactoring — one addressing & config model post-`omnigraph.yaml`: scope + `--graph` + derived access path, served-default / privileged-direct, profiles, named queries, capability classifier (completes RFC-008) | [rfc-011-cli-refactoring.md](rfc-011-cli-refactoring.md) | ## Boundary diff --git a/docs/dev/rfc-011-cli-refactoring.md b/docs/dev/rfc-011-cli-refactoring.md index c0671496..768509b2 100644 --- a/docs/dev/rfc-011-cli-refactoring.md +++ b/docs/dev/rfc-011-cli-refactoring.md @@ -19,9 +19,9 @@ Refactor the CLI around one coherent model once `omnigraph.yaml` is gone. The shape: - **One ontology** (store, server, cluster; cluster config vs operator config; - catalog; context; capability) where each term names exactly one concept. + catalog; profile; capability) where each term names exactly one concept. - **Addressing = scope + `--graph`, with the access path *derived*.** A command - resolves a *scope* (operator defaults, an optional named *context*, or one + resolves a *scope* (operator defaults, an optional named *profile*, or one explicit primitive address — `--store` / `--server` / `--cluster`), selects a graph inside it with `--graph`, and the **served-vs-direct access path falls out of the scope's bindings × the verb's capability** — it is never a per-command @@ -30,7 +30,7 @@ shape: is a *server* (a bearer token, no bucket credentials). Reading or writing a remote store/cluster directly is an explicit, credentialed, admin/break-glass act — never the default, never baked into everyday operator config. -- **The CLI is stateless per command.** No `current_context` pointer, no +- **The CLI is stateless per command.** No `current_profile` pointer, no `USE`-style mode; every command is fully determined by its flags + static config. You *select* a graph, you do not *switch into* one. - **Definitions are named; payloads are passed.** Queries (`.gq`) and schema @@ -91,12 +91,12 @@ Every term is one concept. The rest of this RFC uses them precisely. catalog is the applied result.)* - **Operator config** — `~/.omnigraph/config.yaml`, your **personal** file: identity (actor), default graph, named servers/clusters, output prefs, optional - contexts. Declares *who I am*, never what the system is. -- **Context** — an optional named bundle of **defaults inside the operator + profiles. Declares *who I am*, never what the system is. +- **Profile** — an optional named bundle of **defaults inside the operator config** (one of {cluster, server, store} + a default graph). Config data, **not state**: selecting one fills in omitted flags for a command; it does not - put you "in" a mode. Chosen per command (`--context `) or per shell - (`OMNIGRAPH_CONTEXT`). + put you "in" a mode. Chosen per command (`--profile `) or per shell + (`OMNIGRAPH_PROFILE`). - **Credential** — a bearer token keyed to a **server name**, resolved via `OMNIGRAPH_TOKEN_` or `~/.omnigraph/credentials` (`0600`); sent only to the server it is keyed to. (Per RFC-007 — the operator config holds endpoints, @@ -117,7 +117,7 @@ Every term is one concept. The rest of this RFC uses them precisely. ### How a command resolves - **Scope** — the resolved environment a command addresses: operator defaults, a - named context, or one explicit primitive address. + named profile, or one explicit primitive address. - **Access path** — **served** (through a server) or **direct** (open storage in-process). Derived from scope × capability; see "Access path" below. - **Capability** — what a verb requires: `any`, `served`, `direct`, `control`, @@ -132,12 +132,12 @@ Every term is one concept. The rest of this RFC uses them precisely. - **Exactly two config surfaces:** **cluster config** (team) and **operator config** (personal). Nothing else is "a config." -- A **context is not a third config** — it lives *inside* the operator config, and +- A **profile is not a third config** — it lives *inside* the operator config, and it is **defaults, not state**. - A **catalog is not config** — it is the *applied state* the cluster owns. - A **store is one graph; a cluster is many graphs** + catalog + control state. - A **graph is the logical thing**; store/server/cluster are ways to reach it. -- "State" elsewhere is not the context: *graph state* is committed data in Lance; +- "State" elsewhere is not the profile: *graph state* is committed data in Lance; *cluster state* is the applied control-plane ledger. Neither is operator config. ## Design @@ -153,7 +153,7 @@ Every command answers four orthogonal questions — kept orthogonal here: | Axis | Question | Today | Target | |---|---|---|---| -| Scope | which environment? | `omnigraph.yaml` defaults / `--target` | operator defaults · `--context` · one primitive | +| Scope | which environment? | `omnigraph.yaml` defaults / `--target` | operator defaults · `--profile` · one primitive | | Target shape | whole scope or one graph? | implicit in command family | declared per verb | | Graph | which graph in it? | tangled into the address | `--graph` only for graph-scoped server/cluster verbs | | Access path | served or direct? | inferred from scheme / target | **derived** from scope × capability | @@ -161,7 +161,7 @@ Every command answers four orthogonal questions — kept orthogonal here: ### A scope binds one entity — and served is the default -A scope (a context, the flat defaults, or one primitive flag) binds **exactly one +A scope (a profile, the flat defaults, or one primitive flag) binds **exactly one of** {server, cluster, store}. Server and cluster scopes may contain many graphs and can carry a `default_graph`; a store scope is already one graph and does not accept `--graph`. They differ by privilege, and **the everyday default is a @@ -259,7 +259,7 @@ The CLI validates through verb capability, not plane jargon: | `served` | requires an HTTP server; may be graph-scoped or scope-scoped | `graphs list`, `queries list` | | `direct` | graph-scoped storage-native or graph-backed validation; no server form exists | `init`, `optimize`, `repair`, `cleanup`, `schema plan`, graph-backed `lint` | | `control` | cluster-scoped catalog/control-plane work; addresses the cluster, not a single raw store | `cluster *`, `queries validate` | -| `local` | does not address a graph or scope | `config`, `context`, `lint --query ... --schema ...` | +| `local` | does not address a graph or scope | `config`, `profile`, `lint --query ... --schema ...` | `any` does **not** mean "the user picks": the resolver picks from the scope. Internally the exhaustive `command_plane` match (`planes.rs`) stays as the drift @@ -297,7 +297,7 @@ control/catalog check against the cluster-owned query definitions. A bare a **literal** — `--server https://…`, `--store s3://…` — bypasses it. Per Decision 2: a value containing `://` is a literal, otherwise a config-name lookup.)* -3. Else if `--context ` (or `OMNIGRAPH_CONTEXT`) selects a context, use it. +3. Else if `--profile ` (or `OMNIGRAPH_PROFILE`) selects a profile, use it. 4. Else use the operator config's flat defaults. Error only if neither resolves. *(No sticky "current" pointer — each command resolves scope fresh.)* 5. Resolve the graph only for **graph-scoped** verbs. Server/cluster scopes: @@ -342,7 +342,7 @@ defaults: servers: prod: { url: https://graph.example.com } # token keyed by name (RFC-007); no creds here staging: { url: https://staging.example.com } -contexts: # optional, only for multiple environments +profiles: # optional, only for multiple environments staging: { server: staging, default_graph: knowledge } ``` @@ -353,7 +353,7 @@ storage explicitly. **Maintainer — opts into a cluster root (and has bucket credentials):** ```yaml -contexts: +profiles: brain-admin: { cluster: brain, default_graph: knowledge } # direct; admin/control/maintenance clusters: brain: { root: s3://acme/clusters/brain } # the s3:// root lives ONLY here @@ -376,10 +376,10 @@ Assume the everyday flat defaults: server `prod`, default graph `knowledge`. | …with params | `omnigraph query find_people --params '{"title":"Eng"}'` | served | | Another graph in scope | `omnigraph query find_people --graph archive` | served | | Write | `omnigraph load --data batch.jsonl --mode append` | served | -| A different environment | `omnigraph --context staging query find_people` | served | +| A different environment | `omnigraph --profile staging query find_people` | served | | One-off server, no config | `omnigraph query find_people --server https://graph.example.com --graph knowledge` | served | | Maintain (admin, explicit storage) | `omnigraph optimize --cluster s3://acme/clusters/brain --graph knowledge` | direct (privileged) | -| Maintain (admin, via admin context) | `omnigraph --context brain-admin optimize --graph knowledge` | direct (privileged) | +| Maintain (admin, via admin profile) | `omnigraph --profile brain-admin optimize --graph knowledge` | direct (privileged) | | List catalog queries | `omnigraph queries list` | served | | Validate cluster query catalog | `omnigraph queries validate --cluster s3://acme/clusters/brain` | control (privileged) | | Offline query lint | `omnigraph lint --query new.gq --schema schema.pg` | local | @@ -407,7 +407,7 @@ files, `--cluster-graph`, scheme inference). **After** = this model. | Another graph | `omnigraph query --target archive --query find.gq --name find_people` | `omnigraph query find_people --graph archive` | | Load | `omnigraph load --data b.jsonl --mode append --target knowledge` | `omnigraph load --data b.jsonl --mode append` | | Maintain (admin) | `omnigraph optimize --cluster brain --cluster-graph knowledge` | `omnigraph optimize --cluster s3://acme/clusters/brain --graph knowledge` | -| Another environment | edit `omnigraph.yaml`, or re-address with full URIs | `--context staging …` or `OMNIGRAPH_CONTEXT=staging` | +| Another environment | edit `omnigraph.yaml`, or re-address with full URIs | `--profile staging …` or `OMNIGRAPH_PROFILE=staging` | | One-off remote | `omnigraph query --uri https://… --query find.gq` *(scheme→remote)* | `omnigraph query find_people --server https://… --graph knowledge` | | Raw storage of a served graph | `omnigraph query s3://…/knowledge.omni --query find.gq` *(looks like a normal query)* | `omnigraph query --file find.gq --store s3://…/knowledge.omni` *(explicit bypass)* | @@ -463,7 +463,7 @@ staged and release-noted. this RFC only makes the split explicit. - **No new transport.** Addressing surface, not protocol. - **No positional sigil grammar** (`@server/graph`, `%cluster/graph`). Considered - and rejected: explicit flags are more discoverable; contexts already give + and rejected: explicit flags are more discoverable; profiles already give brevity. Revisit only on demonstrated expert-terseness demand. ## Decisions @@ -472,7 +472,7 @@ The questions this RFC opened are resolved as follows. Two are explicitly deferred (see below); they do not block the model. 1. **Local-dev path → embedded `--store` scope.** Local dev runs the engine - in-process against a `--store ` (or a store-scoped context); `omnigraph + in-process against a `--store ` (or a store-scoped profile); `omnigraph serve` stays available but is not required. Consistent with embedded ≡ remote (RFC-009). 2. **Primitives are one flag, typed by content.** `--server` and `--cluster` @@ -487,11 +487,11 @@ deferred (see below); they do not block the model. 4. **Aliases live under an `alias` namespace** — `omnigraph alias [args]`, never bare top-level. An alias can therefore neither shadow nor be shadowed by a built-in (current or future) verb. -6. **Context merge: scope wholesale, prefs layered.** The entity binding + - `default_graph` come *wholesale* from the active scope (a context, or flat +6. **Profile merge: scope wholesale, prefs layered.** The entity binding + + `default_graph` come *wholesale* from the active scope (a profile, or flat defaults if none) — never per-key merged across the entity dimension (that would yield "server *and* cluster"). Only non-scope preferences (`output`, table - layout) take flat defaults as a base. Precedence: explicit flag > context > flat + layout) take flat defaults as a base. Precedence: explicit flag > profile > flat defaults. 7. **No default graph → error + list candidates.** A graph-scoped verb with no `--graph`, no `default_graph`, and >1 graph in scope errors and lists candidates @@ -524,19 +524,19 @@ Non-blocking; settle when convenient. - **D5 — combined admin scope.** A scope binds one entity; admins read via a server scope and maintain via `--cluster`. A `deployments: { … }` object - (server + cluster validated coherent, referenced by a context) is revisited only + (server + cluster validated coherent, referenced by a profile) is revisited only if admin ergonomics demand it — and Decision 11 largely removes the need. -- **D8 — the `context` command surface.** `context list` / `context show` +- **D8 — the `profile` command surface.** `profile list` / `profile show` (read-only inspection) are additive diagnostics, shippable anytime; they don't - touch the grammar or resolution. The *no sticky `context use`* constraint holds + touch the grammar or resolution. The *no sticky `profile use`* constraint holds regardless — it is a design principle, not a command. ## Safety -Dropping the sticky `current_context` pointer removes the main footgun — a +Dropping the sticky `current_profile` pointer removes the main footgun — a destructive command silently inheriting a "current" environment from an earlier session. Because each command resolves scope fresh, what is on the command line is -what runs. Two guards remain (a flat default or `OMNIGRAPH_CONTEXT` can still point +what runs. Two guards remain (a flat default or `OMNIGRAPH_PROFILE` can still point at prod): echo the resolved scope + access path on writes, and require confirmation (or `--yes`) for destructive verbs when the resolved scope is not local (Decision 9). The most dangerous direct writes (`cleanup`, overwrite @@ -557,7 +557,7 @@ normal operator's setup mostly cannot issue them by accident at all. default — narrowing the blast radius of a leaked operator config. - **§6 strong consistency:** both paths are snapshot-isolated per query; this RFC changes addressing, not isolation. -- **Deny-list (no state that drifts):** contexts and aliases are static config +- **Deny-list (no state that drifts):** profiles and aliases are static config sugar that resolve to canonical scopes; they declare nothing the cluster or server doesn't already own. No sticky session state is introduced. - No Hard Invariant is weakened; the change is CLI surface + config removal. @@ -612,7 +612,7 @@ omnigraph │ └─ local — no graph ├─ policy { validate | test | explain } offline Cedar tooling - ├─ context { list | show } read-only; NO mutating `use` (no sticky state) + ├─ profile { list | show } read-only; NO mutating `use` (no sticky state) ├─ alias [args] personal shortcut; expands to its bound stored-query call (D4) ├─ config { migrate } finish the omnigraph.yaml split (RFC-008) ├─ login / logout per-server bearer credentials @@ -631,13 +631,13 @@ no `--cluster-graph`, no `--uri` scheme-dispatch, no `--via`. | Form | Resolves to | Access | Privilege | |---|---|---|---| -| **server scope** — operator default, a `--context`, or `--server ` | a served endpoint + keyed token | served | everyday (bearer token) | -| **cluster scope** — an admin context, or `--cluster ` | a managed cluster's storage + catalog | direct | privileged (bucket creds) | +| **server scope** — operator default, a `--profile`, or `--server ` | a served endpoint + keyed token | served | everyday (bearer token) | +| **cluster scope** — an admin profile, or `--cluster ` | a managed cluster's storage + catalog | direct | privileged (bucket creds) | | **store scope** — `--store ` | one graph's storage (no catalog) | direct | local-dev (file) / break-glass (s3) | | **`--graph `** | selects the graph for graph-scoped verbs in server/cluster scopes; invalid for store scopes and scope-scoped verbs | — | — | -Resolution: explicit primitive (`--server`/`--cluster`/`--store`) → `--context` / -`OMNIGRAPH_CONTEXT` → operator flat defaults. Access path is then derived from the +Resolution: explicit primitive (`--server`/`--cluster`/`--store`) → `--profile` / +`OMNIGRAPH_PROFILE` → operator flat defaults. Access path is then derived from the scope kind × the verb's capability (see the Resolution rule); it is never inferred from a URI scheme and never toggled. @@ -653,7 +653,7 @@ from a URI scheme and never toggled. | `cluster *` | Control | **control** (unchanged) | | `policy *`/`embed`/`login`/`logout`/`config`/`version`/offline `lint --query --schema` | Session | **`local`** | | `ingest`; `--target`; `--cluster-graph`; `--uri http` dispatch | present | **removed** | -| — | — | **added:** `context { list | show }` (read-only) | +| — | — | **added:** `profile { list | show }` (read-only) | Cross-capability families: `schema` (`plan` is `direct`, `show`/`apply` are `any`), `queries` (`list` is `served`, `validate` is `control`), and `lint`