feat(cli): aura new — CLI wiring, load-bypass guard, authoring-loop e2e (0103 tasks 2-4)
Command::New + NewCmd + dispatch_new (usage faults exit 2, runtime refusals exit 1, the C14 partition); the main() guard exempts aura new from the eager project load so scaffolding works inside unbuilt trees. E2e (tests/project_new.rs, 6 tests): scaffold -> cargo build -> aura run twice byte-identical with manifest.project.namespace stamped; introspect lists the project type beside std; refusals for existing destination (1), invalid names (2), missing engine path with --engine-path hint (1); aura new inside an unbuilt project tree succeeds (the bypass proof); namespace override reaches the built vocabulary (an additive e2e beyond the plan, kept). Verification: cargo build --workspace clean; cargo test --workspace 873 passed / 0 failed; clippy -D warnings clean. refs #180
This commit is contained in:
+59
-12
@@ -3760,6 +3760,8 @@ enum Command {
|
||||
Runs(RunsCmd),
|
||||
/// Reproduce a recorded family by content id.
|
||||
Reproduce(ReproduceCmd),
|
||||
/// Scaffold a new research project crate.
|
||||
New(NewCmd),
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
@@ -3774,6 +3776,19 @@ struct ChartCmd {
|
||||
panels: bool,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
struct NewCmd {
|
||||
/// Directory / crate name to create.
|
||||
name: String,
|
||||
/// Engine checkout the project depends on (path deps). Default: the
|
||||
/// engine root this binary was built from.
|
||||
#[arg(long)]
|
||||
engine_path: Option<std::path::PathBuf>,
|
||||
/// Vocabulary namespace (default: the name with dashes as underscores).
|
||||
#[arg(long)]
|
||||
namespace: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
struct GraphCmd {
|
||||
#[command(subcommand)]
|
||||
@@ -4348,6 +4363,31 @@ fn dispatch_reproduce(a: ReproduceCmd, env: &project::Env) {
|
||||
reproduce_family(&a.id, env);
|
||||
}
|
||||
|
||||
fn dispatch_new(a: NewCmd, _env: &project::Env) {
|
||||
let cwd = std::env::current_dir().unwrap_or_else(|e| {
|
||||
eprintln!("aura: {e}");
|
||||
std::process::exit(1);
|
||||
});
|
||||
let spec = scaffold::scaffold_spec(
|
||||
&a.name,
|
||||
a.engine_path.as_deref(),
|
||||
a.namespace.as_deref(),
|
||||
&cwd,
|
||||
)
|
||||
.unwrap_or_else(|m| {
|
||||
eprintln!("aura: {m}");
|
||||
std::process::exit(2);
|
||||
});
|
||||
scaffold::scaffold(&spec).unwrap_or_else(|m| {
|
||||
eprintln!("aura: {m}");
|
||||
std::process::exit(1);
|
||||
});
|
||||
println!(
|
||||
"created project `{}` (namespace `{}`)",
|
||||
spec.name, spec.namespace
|
||||
);
|
||||
}
|
||||
|
||||
/// `aura sweep`: loaded-blueprint by-name axis sweep (or `--list-axes` probe) when the
|
||||
/// first-positional is an existing `.json`, else the built-in `--strategy` grid sweep.
|
||||
fn dispatch_sweep(a: SweepCmd, env: &project::Env) {
|
||||
@@ -4637,18 +4677,24 @@ fn main() {
|
||||
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
|
||||
}
|
||||
let cli = Cli::parse();
|
||||
let env = match std::env::current_dir()
|
||||
.ok()
|
||||
.and_then(|d| project::discover_from(&d))
|
||||
{
|
||||
Some(root) => match project::load(&root, cli.release) {
|
||||
Ok(p) => project::Env::with_project(p),
|
||||
Err(e) => {
|
||||
eprintln!("aura: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
None => project::Env::std(),
|
||||
// `aura new` scaffolds; it must not require a loadable project even
|
||||
// when invoked inside one (e.g. an unbuilt tree).
|
||||
let env = if matches!(cli.command, Command::New(_)) {
|
||||
project::Env::std()
|
||||
} else {
|
||||
match std::env::current_dir()
|
||||
.ok()
|
||||
.and_then(|d| project::discover_from(&d))
|
||||
{
|
||||
Some(root) => match project::load(&root, cli.release) {
|
||||
Ok(p) => project::Env::with_project(p),
|
||||
Err(e) => {
|
||||
eprintln!("aura: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
None => project::Env::std(),
|
||||
}
|
||||
};
|
||||
match cli.command {
|
||||
Command::Run(a) => dispatch_run(a, &env),
|
||||
@@ -4660,6 +4706,7 @@ fn main() {
|
||||
Command::Mc(a) => dispatch_mc(a, &env),
|
||||
Command::Runs(a) => dispatch_runs(a, &env),
|
||||
Command::Reproduce(a) => dispatch_reproduce(a, &env),
|
||||
Command::New(a) => dispatch_new(a, &env),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user