spool-memory 0.2.3

Local-first developer memory system โ€” persistent, structured knowledge for AI coding tools
Documentation
//! End-to-end smoke test for the bootstrap flow.
//!
//! Runs against a sandbox `~/.spool` under `/tmp/` to avoid clobbering the
//! developer's real installation. Useful before tagging a release.
//!
//! Run with:
//! ```
//! cargo run --example bootstrap_smoke
//! ```

use spool::bootstrap::{self, SpoolLayout};
use std::path::PathBuf;

fn main() -> anyhow::Result<()> {
    // Sandbox layout under /tmp/.
    let sandbox = std::env::temp_dir().join("spool-bootstrap-smoke");
    let _ = std::fs::remove_dir_all(&sandbox);
    let layout = SpoolLayout::from_root(sandbox.clone());

    // Use the workspace's actual release binaries as the "bundled" source.
    let workspace_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let bundled_dir = workspace_root.join("target/release");

    if !bundled_dir.exists() {
        eprintln!(
            "โŒ Build the release binaries first:\n   cargo build --release --bin spool --bin spool-mcp --bin spool-daemon"
        );
        std::process::exit(1);
    }

    println!("๐Ÿงช spool bootstrap smoke test");
    println!("   sandbox:  {}", sandbox.display());
    println!("   bundled:  {}", bundled_dir.display());
    println!();

    let report = bootstrap::run_bootstrap_with_layout(&layout, &bundled_dir)?;

    println!("๐Ÿ“‹ Bootstrap messages:");
    for msg in &report.messages {
        println!("   โ€ข {msg}");
    }
    println!();

    println!("๐Ÿ“ฆ Layout created:");
    for (label, path) in [
        ("root    ", layout.root().to_path_buf()),
        ("bin     ", layout.bin_dir()),
        ("data    ", layout.data_dir()),
        ("plugins ", layout.plugins_dir()),
        ("version ", layout.version_file()),
    ] {
        let mark = if path.exists() { "โœ…" } else { "โŒ" };
        println!("   {mark} {label}{}", path.display());
    }
    println!();

    println!("๐Ÿ“ Files in ~/.spool/bin/:");
    if let Ok(entries) = std::fs::read_dir(layout.bin_dir()) {
        for entry in entries.flatten() {
            let size = entry.metadata().map(|m| m.len()).unwrap_or(0);
            println!(
                "   โ€ข {} ({} bytes)",
                entry.file_name().to_string_lossy(),
                size
            );
        }
    }
    println!();

    if let Some(release) = &report.release {
        println!("๐Ÿ”„ Release report:");
        println!("   โ€ข copied:  {}", release.copied.len());
        println!("   โ€ข skipped: {}", release.skipped.len());
        println!();
    }

    if let Some(cfg) = &report.auto_configure {
        println!("๐Ÿ”Œ AI client configuration:");
        for client in &cfg.clients {
            let icon = if client.installed {
                "โœ…"
            } else if client.detected {
                "โš ๏ธ "
            } else {
                "โญ๏ธ "
            };
            println!(
                "   {icon} {} โ€” detected={} installed={} status={}",
                client.client, client.detected, client.installed, client.status
            );
            for note in &client.notes {
                println!("      โ†ณ {note}");
            }
        }
        println!();
    }

    if let Some(path) = &report.path_config {
        println!("๐Ÿ›ฃ๏ธ  PATH configuration:");
        println!("   โ€ข configured:    {}", path.configured);
        println!("   โ€ข files modified: {}", path.modified_files.len());
        for f in &path.modified_files {
            println!("     โ†ณ {}", f.display());
        }
        println!();
    }

    println!("๐Ÿ“‹ Final state:");
    let s = &report.state_after;
    println!(
        "   โ€ข service version:  {:?}",
        s.service.as_ref().map(|s| &s.version)
    );
    println!("   โ€ข gui version:      {:?}", s.gui_version);
    println!("   โ€ข mcp_registered:   {}", s.mcp_registered);
    println!("   โ€ข hooks_installed:  {}", s.hooks_installed);
    println!("   โ€ข path_configured:  {}", s.path_configured);
    println!();

    println!("๐ŸŽ‰ Bootstrap smoke test completed successfully");
    println!("   To inspect: ls -la {}", sandbox.display());
    Ok(())
}