refactor(cli): drop cluster init — no replacement scaffold

Andrew's call, and the right one by the repo's own lens: a minimal
cluster.yaml is five lines; a generator is a second copy of the schema to
keep in sync forever, emitting a file that is unusable until hand-edited
anyway (graphs: {} cannot apply or serve). Terraform has no config
scaffolder either. New users copy from the cluster quick-start; migrants
get a ready-to-review cluster.yaml from config migrate. RFC-008 stage 3
becomes purely subtractive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
aaltshuler 2026-06-11 23:45:18 +03:00
parent 3adbc65af2
commit 5328c91341
5 changed files with 8 additions and 105 deletions

View file

@ -345,23 +345,6 @@ pub(crate) enum Command {
#[derive(Debug, Subcommand)]
pub(crate) enum ClusterCommand {
/// Scaffold a minimal cluster.yaml in the config directory (refuses
/// if one exists). The cluster checkout replaces the legacy
/// omnigraph.yaml scaffold (RFC-008 stage 3).
Init {
/// Directory to scaffold into (default: .)
#[arg(long, default_value = ".")]
config: PathBuf,
/// Optional deployment label (metadata.name)
#[arg(long)]
name: Option<String>,
/// Optional storage root URI (s3://bucket/prefix); omit for the
/// config-dir layout
#[arg(long)]
storage: Option<String>,
#[arg(long)]
json: bool,
},
/// Validate cluster.yaml and referenced schemas, queries, and policy files.
Validate {
/// Cluster config directory containing cluster.yaml.

View file

@ -1217,43 +1217,6 @@ async fn main() -> Result<()> {
}
}
Command::Cluster { command } => match command {
ClusterCommand::Init {
config,
name,
storage,
json,
} => {
let target = config.join("cluster.yaml");
if target.exists() {
bail!(
"'{}' already exists — cluster init refuses to overwrite",
target.display()
);
}
std::fs::create_dir_all(&config)?;
let mut scaffold = String::from("version: 1\n");
if let Some(name) = &name {
scaffold.push_str(&format!("metadata:\n name: {name}\n"));
}
match &storage {
Some(root) => scaffold.push_str(&format!("storage: {root}\n")),
None => scaffold.push_str(
"# storage: s3://bucket/prefix # omit: this folder is the storage root\n",
),
}
scaffold.push_str(
"graphs: {}\n# graphs:\n# knowledge:\n# schema: knowledge.pg\n# queries: queries/\n",
);
std::fs::write(&target, scaffold)?;
if json {
print_json(&serde_json::json!({ "created": target.display().to_string() }))?;
} else {
println!(
"created {} — declare graphs, then `omnigraph cluster import` and `apply`",
target.display()
);
}
}
ClusterCommand::Validate { config, json } => {
let output = validate_config_dir(config);
finish_cluster_validate(&output, json)?;

View file

@ -950,49 +950,3 @@ graphs:
assert!(!leaked.contains("phantom") && !leaked.contains("9999"), "{leaked}");
}
/// RFC-008 stage 3: `cluster init` scaffolds a minimal valid cluster.yaml
/// (the replacement for the retired omnigraph.yaml scaffold) and refuses
/// to overwrite.
#[test]
fn cluster_init_scaffolds_minimal_valid_config_and_refuses_overwrite() {
let temp = tempdir().unwrap();
let output = cli()
.arg("cluster")
.arg("init")
.arg("--config")
.arg(temp.path())
.arg("--name")
.arg("brain")
.output()
.unwrap();
assert!(output.status.success(), "{output:?}");
let text = fs::read_to_string(temp.path().join("cluster.yaml")).unwrap();
assert!(text.contains("version: 1") && text.contains("name: brain"), "{text}");
// The scaffold validates clean.
let output = cli()
.arg("cluster")
.arg("validate")
.arg("--config")
.arg(temp.path())
.arg("--json")
.output()
.unwrap();
assert!(output.status.success(), "{output:?}");
let payload: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap();
assert_eq!(payload["ok"], true, "{payload}");
// Refuses a second run.
let output = cli()
.arg("cluster")
.arg("init")
.arg("--config")
.arg(temp.path())
.output()
.unwrap();
assert!(!output.status.success());
assert!(
String::from_utf8_lossy(&output.stderr).contains("refuses to overwrite"),
"{output:?}"
);
}