nornir 0.3.1

Companion to cargo: dependency tracking, release gating, deploy, benchmarks, and documentation assembly. Project-agnostic.
Documentation
//! Launcher for the Urðr Threads visualizer.
//!
//! Usage:
//!     cargo run --release --features viz --bin urdr-threads \
//!         -- --warehouse /tmp/nornir-demo-warehouse --workspace norninr-demo

use std::path::PathBuf;

use anyhow::Result;
use clap::Parser;

use nornir::viz::UrdrThreadsApp;

#[derive(Parser)]
#[command(name = "urdr-threads")]
#[command(about = "Time-travel visualizer for the Urðr warehouse", long_about = None)]
struct Cli {
    /// Path to the Iceberg warehouse root directory.
    #[arg(long, default_value = "/tmp/nornir-demo-warehouse")]
    warehouse: PathBuf,

    /// Workspace name (matches the `[workspace] name =` from the
    /// descriptor used at release time).
    #[arg(long, default_value = "norninr-demo")]
    workspace: String,

    /// Optional path to `nornir.toml`. If omitted we try to discover one
    /// from the current directory; if that also fails the Knowledge tab
    /// just renders with no repos.
    #[arg(long)]
    config: Option<PathBuf>,
}

fn main() -> Result<()> {
    let cli = Cli::parse();

    let (workspace_root, repos) = match cli.config.as_deref() {
        Some(p) => match nornir::config::load_explicit(p) {
            Ok(loaded) => (
                loaded.workspace_root,
                loaded.nornir.repo.keys().cloned().collect(),
            ),
            Err(_) => (PathBuf::new(), Vec::new()),
        },
        None => match std::env::current_dir()
            .ok()
            .and_then(|cwd| nornir::config::discover(&cwd).ok())
        {
            Some(loaded) => (
                loaded.workspace_root,
                loaded.nornir.repo.keys().cloned().collect(),
            ),
            None => (PathBuf::new(), Vec::new()),
        },
    };

    let native_options = eframe::NativeOptions {
        viewport: eframe::egui::ViewportBuilder::default()
            .with_inner_size([1200.0, 700.0])
            .with_title("Urðr Threads — nornir time machine"),
        ..Default::default()
    };
    eframe::run_native(
        "Urðr Threads",
        native_options,
        Box::new(move |_cc| {
            Ok(Box::new(UrdrThreadsApp::with_repos(
                cli.warehouse,
                cli.workspace,
                workspace_root,
                repos,
            )))
        }),
    )
    .map_err(|e| anyhow::anyhow!("eframe error: {e}"))?;
    Ok(())
}