mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-15 01:55:13 +02:00
feat(cli): plane-grouped --help + clap 4.6.1 (RFC-010 Slice 2) (#220)
* chore(deps): bump clap to 4.6.1
Workspace constraint "4" → "4.6" so the resolver picks up the 4.6 line
(a plain `cargo update` stayed on 4.5.x). clap 4.5.58 → 4.6.1
(clap_builder 4.6.0, clap_derive 4.6.1). Minor bump, no API breakage; the
workspace builds and all CLI suites pass unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(cli): group --help by plane (RFC-010 Slice 2)
Slice 1 declared the planes (the command_plane table + the wrong-plane
guard); this makes them visible in `--help`. clap can't print labeled
heading rows between subcommand groups (verified against the source —
help_heading is args-only, {subcommands} is one flat block), so per the
chosen approach: cluster + legend.
- Reorder the `Command` enum into plane bands (clap lists subcommands in
declaration order): data (query, mutate, load, branch, snapshot, export,
commit, schema, graphs) → storage/local-graph ops (init, optimize,
repair, cleanup, lint, queries) → control (cluster) → session (policy,
embed, login, logout, config, version). No magic display_order numbers —
the source order IS the help order, with band comments for readers. The
band placement matches `command_plane` (lint/queries are storage-plane:
they reject --server), so the help grouping and the guard agree.
- Add an `after_help` legend on `Cli` naming the planes. Written to
describe the planes (not enumerate every command) so it doesn't drift.
Help-polish (post-review): hide the deprecated `ingest` from the list
(still a valid command); trim the long `login` and `--as` descriptions to
one line each so the columns don't blow up.
The behavioral source of truth for planes stays `planes::command_plane`;
this ordering is its cosmetic counterpart.
Test: `help_groups_commands_by_plane` pins the legend phrase + the cluster
ordering (query < optimize < cluster). Doc: a line under cli-reference's
*Command planes* section.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(cli): qualify mixed-plane commands in the --help legend
Addresses the Greptile P2 on #220: the legend placed `schema` entirely in
Data and `queries` entirely in Storage, but per `command_plane` the
subcommands differ — `schema plan` is storage-plane (rejects --server) and
`queries list` is session (no graph). A user reading the legend then running
`schema plan --server` would hit a rejection contradicting it. The Commands
list is one entry per top-level command (necessarily coarse), so the legend
carries the nuance: `schema [plan: storage]` and `queries [list: session]`.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
4187d56f8a
commit
d6cf5b298c
5 changed files with 239 additions and 191 deletions
24
Cargo.lock
generated
24
Cargo.lock
generated
|
|
@ -83,9 +83,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.21"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
|
||||
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
|
|
@ -104,9 +104,9 @@ checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
|
|||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.7"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
|
@ -1314,9 +1314,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.58"
|
||||
version = "4.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806"
|
||||
checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -1324,9 +1324,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.58"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2"
|
||||
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -1336,9 +1336,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.55"
|
||||
version = "4.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
|
||||
checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
|
@ -5323,9 +5323,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.44"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ pest = "2"
|
|||
pest_derive = "2"
|
||||
thiserror = "2"
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "macros", "time", "net", "signal", "sync"] }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
clap = { version = "4.6", features = ["derive"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_yaml = "0.9"
|
||||
|
|
|
|||
|
|
@ -9,15 +9,24 @@ pub(crate) const DEFAULT_BEARER_TOKEN_ENV: &str = "OMNIGRAPH_BEARER_TOKEN";
|
|||
#[command(name = "omnigraph")]
|
||||
#[command(about = "Omnigraph graph database CLI")]
|
||||
#[command(version = env!("CARGO_PKG_VERSION"), disable_version_flag = true)]
|
||||
// Subcommands are listed grouped by plane (clap renders them in declaration
|
||||
// order). clap can't print labeled headings between subcommand groups, so this
|
||||
// legend names the planes; the grouping is the variant order in `Command`.
|
||||
#[command(after_help = "\
|
||||
COMMANDS BY PLANE:\n \
|
||||
Data — run against a graph, embedded or via --server (query, mutate, load, \
|
||||
branch, snapshot, export, commit, schema [plan: storage], graphs).\n \
|
||||
Storage — direct storage or local files; reject --server (init, optimize, \
|
||||
repair, cleanup, lint, queries [list: session]).\n \
|
||||
Control — manage a cluster directory via --config (cluster).\n \
|
||||
Session — no graph; local config & tooling (policy, embed, login, logout, \
|
||||
config, version).\n\
|
||||
See the 'Command planes' section of the CLI reference for which flags apply where.")]
|
||||
pub(crate) struct Cli {
|
||||
/// Actor identity for direct-engine writes (MR-722). Overrides
|
||||
/// `cli.actor` from `omnigraph.yaml`. When the configured policy
|
||||
/// is in effect, Cedar evaluates this actor against the requested
|
||||
/// action and scope; with policy configured but neither this flag
|
||||
/// nor `cli.actor` set, the engine-layer footgun guard fires and
|
||||
/// the write is denied (no silent bypass). Has no effect on remote
|
||||
/// HTTP writes — those resolve their actor server-side from the
|
||||
/// bearer token.
|
||||
/// Actor id for direct-engine writes; overrides `cli.actor`. No effect on
|
||||
/// remote writes (the server resolves the actor from the bearer token).
|
||||
/// With a policy configured but no actor set, the write is denied — see
|
||||
/// docs/user/policy.md.
|
||||
#[arg(long = "as", global = true, value_name = "ACTOR")]
|
||||
pub(crate) as_actor: Option<String>,
|
||||
|
||||
|
|
@ -38,170 +47,7 @@ pub(crate) struct Cli {
|
|||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(crate) enum Command {
|
||||
/// Print the CLI version
|
||||
Version,
|
||||
/// Store a bearer token for a named server in ~/.omnigraph/credentials
|
||||
/// (0600). Token from --token or one line on stdin:
|
||||
/// `echo $TOKEN | omnigraph login prod`. The keyed token applies to
|
||||
/// requests whose URL matches the server's `url` in the operator
|
||||
/// config's `servers:` map.
|
||||
Login {
|
||||
/// Server name (keys the credential; declare its url under
|
||||
/// `servers:` in ~/.omnigraph/config.yaml)
|
||||
name: String,
|
||||
/// The token. Prefer piping via stdin over this flag (shell
|
||||
/// history).
|
||||
#[arg(long)]
|
||||
token: Option<String>,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Legacy-config tooling (RFC-008): split omnigraph.yaml into its
|
||||
/// two destinations.
|
||||
Config {
|
||||
#[command(subcommand)]
|
||||
command: ConfigCommand,
|
||||
},
|
||||
/// Remove a named server's stored credential. Idempotent.
|
||||
Logout {
|
||||
name: String,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Generate, clean, or refresh explicit seed embeddings
|
||||
Embed(EmbedArgs),
|
||||
/// Initialize a new graph from a schema
|
||||
Init {
|
||||
#[arg(long)]
|
||||
schema: PathBuf,
|
||||
/// Graph URI (local path or s3://)
|
||||
uri: String,
|
||||
/// Overwrite existing schema artifacts at the URI. Without
|
||||
/// this flag, init refuses to touch a URI that already holds
|
||||
/// `_schema.pg`, `_schema.ir.json`, or `__schema_state.json`
|
||||
/// — closes the re-init footgun (MR-668 follow-up). With the
|
||||
/// flag, the operator opts in to destructive semantics.
|
||||
#[arg(long)]
|
||||
force: bool,
|
||||
},
|
||||
/// Load data into a graph (local or remote)
|
||||
Load {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
data: PathBuf,
|
||||
/// Target branch (defaults to main). Without --from it must exist.
|
||||
#[arg(long)]
|
||||
branch: Option<String>,
|
||||
/// Base branch to fork --branch from when it doesn't exist yet.
|
||||
/// Without this flag a missing branch is an error, never a fork.
|
||||
#[arg(long)]
|
||||
from: Option<String>,
|
||||
/// How existing rows are handled: overwrite | append | merge.
|
||||
/// Required — overwrite is destructive, so there is no default.
|
||||
#[arg(long)]
|
||||
mode: CliLoadMode,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Deprecated alias of `load --from <base>` (defaults: --mode merge, --from main)
|
||||
Ingest {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
data: PathBuf,
|
||||
#[arg(long)]
|
||||
branch: Option<String>,
|
||||
#[arg(long)]
|
||||
from: Option<String>,
|
||||
#[arg(long, default_value = "merge")]
|
||||
mode: CliLoadMode,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Branch operations
|
||||
Branch {
|
||||
#[command(subcommand)]
|
||||
command: BranchCommand,
|
||||
},
|
||||
/// Schema planning operations
|
||||
Schema {
|
||||
#[command(subcommand)]
|
||||
command: SchemaCommand,
|
||||
},
|
||||
/// Validate queries against a schema (offline) or repo (repo-backed).
|
||||
///
|
||||
/// Canonical name is `lint` (matches the `omnigraph_compiler::lint`
|
||||
/// module and the `OG-XXX-NNN` lint-code vocabulary). Replaces the
|
||||
/// deprecated `omnigraph query lint` / `omnigraph query check` /
|
||||
/// `omnigraph check` invocations — each is kept as an argv-level
|
||||
/// shim that prints a one-line stderr warning and rewrites to
|
||||
/// `omnigraph lint`. Aliases are deliberately *not* exposed via
|
||||
/// clap's `visible_alias` because that would advertise two
|
||||
/// equivalent canonical names, which agents emit interchangeably
|
||||
/// (see MR-981).
|
||||
Lint {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
query: PathBuf,
|
||||
#[arg(long)]
|
||||
schema: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Operate on the server-side stored-query registry (`queries:`).
|
||||
Queries {
|
||||
#[command(subcommand)]
|
||||
command: QueriesCommand,
|
||||
},
|
||||
/// Show graph snapshot
|
||||
Snapshot {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
branch: Option<String>,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Export a full graph snapshot as JSONL
|
||||
Export {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
branch: Option<String>,
|
||||
#[arg(long, hide = true)]
|
||||
jsonl: bool,
|
||||
#[arg(long = "type")]
|
||||
type_names: Vec<String>,
|
||||
#[arg(long = "table")]
|
||||
table_keys: Vec<String>,
|
||||
},
|
||||
/// Commit history operations
|
||||
Commit {
|
||||
#[command(subcommand)]
|
||||
command: CommitCommand,
|
||||
},
|
||||
// ── Data plane ── run against a graph (embedded or via --server).
|
||||
/// Execute a read query against a branch or snapshot.
|
||||
///
|
||||
/// Canonical read endpoint. The previous name `omnigraph read` is
|
||||
|
|
@ -274,10 +120,115 @@ pub(crate) enum Command {
|
|||
#[arg()]
|
||||
alias_args: Vec<String>,
|
||||
},
|
||||
/// Policy administration and diagnostics
|
||||
Policy {
|
||||
/// Load data into a graph (local or remote)
|
||||
Load {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
data: PathBuf,
|
||||
/// Target branch (defaults to main). Without --from it must exist.
|
||||
#[arg(long)]
|
||||
branch: Option<String>,
|
||||
/// Base branch to fork --branch from when it doesn't exist yet.
|
||||
/// Without this flag a missing branch is an error, never a fork.
|
||||
#[arg(long)]
|
||||
from: Option<String>,
|
||||
/// How existing rows are handled: overwrite | append | merge.
|
||||
/// Required — overwrite is destructive, so there is no default.
|
||||
#[arg(long)]
|
||||
mode: CliLoadMode,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Deprecated alias of `load --from <base>` (defaults: --mode merge, --from main)
|
||||
#[command(hide = true)]
|
||||
Ingest {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
data: PathBuf,
|
||||
#[arg(long)]
|
||||
branch: Option<String>,
|
||||
#[arg(long)]
|
||||
from: Option<String>,
|
||||
#[arg(long, default_value = "merge")]
|
||||
mode: CliLoadMode,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Branch operations
|
||||
Branch {
|
||||
#[command(subcommand)]
|
||||
command: PolicyCommand,
|
||||
command: BranchCommand,
|
||||
},
|
||||
/// Show graph snapshot
|
||||
Snapshot {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
branch: Option<String>,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Export a full graph snapshot as JSONL
|
||||
Export {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
branch: Option<String>,
|
||||
#[arg(long, hide = true)]
|
||||
jsonl: bool,
|
||||
#[arg(long = "type")]
|
||||
type_names: Vec<String>,
|
||||
#[arg(long = "table")]
|
||||
table_keys: Vec<String>,
|
||||
},
|
||||
/// Commit history operations
|
||||
Commit {
|
||||
#[command(subcommand)]
|
||||
command: CommitCommand,
|
||||
},
|
||||
/// Schema planning operations
|
||||
Schema {
|
||||
#[command(subcommand)]
|
||||
command: SchemaCommand,
|
||||
},
|
||||
/// Manage graphs on a multi-graph server (MR-668)
|
||||
Graphs {
|
||||
#[command(subcommand)]
|
||||
command: GraphsCommand,
|
||||
},
|
||||
|
||||
// ── Storage / local graph ops ── direct storage or local files; reject --server.
|
||||
/// Initialize a new graph from a schema
|
||||
Init {
|
||||
#[arg(long)]
|
||||
schema: PathBuf,
|
||||
/// Graph URI (local path or s3://)
|
||||
uri: String,
|
||||
/// Overwrite existing schema artifacts at the URI. Without
|
||||
/// this flag, init refuses to touch a URI that already holds
|
||||
/// `_schema.pg`, `_schema.ir.json`, or `__schema_state.json`
|
||||
/// — closes the re-init footgun (MR-668 follow-up). With the
|
||||
/// flag, the operator opts in to destructive semantics.
|
||||
#[arg(long)]
|
||||
force: bool,
|
||||
},
|
||||
/// Compact small Lance fragments in every table of the graph
|
||||
Optimize {
|
||||
|
|
@ -331,16 +282,79 @@ pub(crate) enum Command {
|
|||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Validate queries against a schema (offline) or repo (repo-backed).
|
||||
///
|
||||
/// Canonical name is `lint` (matches the `omnigraph_compiler::lint`
|
||||
/// module and the `OG-XXX-NNN` lint-code vocabulary). Replaces the
|
||||
/// deprecated `omnigraph query lint` / `omnigraph query check` /
|
||||
/// `omnigraph check` invocations — each is kept as an argv-level
|
||||
/// shim that prints a one-line stderr warning and rewrites to
|
||||
/// `omnigraph lint`. Aliases are deliberately *not* exposed via
|
||||
/// clap's `visible_alias` because that would advertise two
|
||||
/// equivalent canonical names, which agents emit interchangeably
|
||||
/// (see MR-981).
|
||||
Lint {
|
||||
/// Graph URI
|
||||
uri: Option<String>,
|
||||
#[arg(long)]
|
||||
target: Option<String>,
|
||||
#[arg(long)]
|
||||
config: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
query: PathBuf,
|
||||
#[arg(long)]
|
||||
schema: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Operate on the server-side stored-query registry (`queries:`).
|
||||
Queries {
|
||||
#[command(subcommand)]
|
||||
command: QueriesCommand,
|
||||
},
|
||||
|
||||
// ── Control plane ── manage a cluster directory (--config <dir>).
|
||||
/// Validate and plan read-only cluster configuration.
|
||||
Cluster {
|
||||
#[command(subcommand)]
|
||||
command: ClusterCommand,
|
||||
},
|
||||
/// Manage graphs on a multi-graph server (MR-668)
|
||||
Graphs {
|
||||
|
||||
// ── Session / config ── no graph addressing; local tooling.
|
||||
/// Policy administration and diagnostics
|
||||
Policy {
|
||||
#[command(subcommand)]
|
||||
command: GraphsCommand,
|
||||
command: PolicyCommand,
|
||||
},
|
||||
/// Generate, clean, or refresh explicit seed embeddings
|
||||
Embed(EmbedArgs),
|
||||
/// Store a bearer token for a named server (0600 credentials file). Token
|
||||
/// via --token or piped on stdin; see the CLI reference for token resolution.
|
||||
Login {
|
||||
/// Server name (keys the credential; declare its url under
|
||||
/// `servers:` in ~/.omnigraph/config.yaml)
|
||||
name: String,
|
||||
/// The token. Prefer piping via stdin over this flag (shell
|
||||
/// history).
|
||||
#[arg(long)]
|
||||
token: Option<String>,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Remove a named server's stored credential. Idempotent.
|
||||
Logout {
|
||||
name: String,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Legacy-config tooling (RFC-008): split omnigraph.yaml into its
|
||||
/// two destinations.
|
||||
Config {
|
||||
#[command(subcommand)]
|
||||
command: ConfigCommand,
|
||||
},
|
||||
/// Print the CLI version
|
||||
Version,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
|
|
|
|||
|
|
@ -24,6 +24,38 @@ fn version_command_prints_current_cli_version() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn help_groups_commands_by_plane() {
|
||||
// RFC-010 Slice 2: `--help` clusters commands by plane (declaration order
|
||||
// in the Command enum) and explains the planes in an after_help legend.
|
||||
// Pinned lightly — the legend phrase + the cluster ordering — to avoid
|
||||
// brittle full-text assertions on clap's help body.
|
||||
let output = output_success(cli().arg("--help"));
|
||||
let stdout = stdout_string(&output);
|
||||
|
||||
assert!(
|
||||
stdout.contains("COMMANDS BY PLANE"),
|
||||
"plane legend (after_help) missing from --help:\n{stdout}"
|
||||
);
|
||||
|
||||
// The Commands list precedes the legend, so first occurrences sit in the
|
||||
// list and must appear in plane order: a data verb, then a storage verb,
|
||||
// then the control verb.
|
||||
let pos = |needle: &str| {
|
||||
stdout
|
||||
.find(needle)
|
||||
.unwrap_or_else(|| panic!("'{needle}' not found in --help:\n{stdout}"))
|
||||
};
|
||||
assert!(
|
||||
pos("query") < pos("optimize"),
|
||||
"data commands should be listed before storage commands"
|
||||
);
|
||||
assert!(
|
||||
pos("optimize") < pos("cluster"),
|
||||
"storage commands should be listed before the control command"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn init_creates_graph_successfully_on_missing_local_directory() {
|
||||
let temp = tempdir().unwrap();
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ These restrictions are enforced and reported, not silent:
|
|||
|
||||
To maintain a server-backed graph, run the maintenance verbs from a host with storage access against the graph's storage URI (or `--target`), out-of-band from the serving process — there are no server routes for `optimize` / `repair` / `cleanup` by design.
|
||||
|
||||
`omnigraph --help` lists commands **clustered by plane** (data → storage → control → session) with a plane legend at the bottom.
|
||||
|
||||
## Config surfaces
|
||||
|
||||
Two config surfaces with single owners (RFC-007/RFC-008), plus a zero-config
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue