🚦 Viz pre-flight checks
What: right after the launch splash, nornir viz runs a handful of cheap capability probes and, if any fail, raises a centered popup. It turns the silent, downstream "scan failed: read …/Cargo.lock" class of error into an up-front, actionable prompt — and offers to fix the fixable ones.
Design
- Code:
src/viz/preflight.rs(Preflight,Check), drawn fromUrdrThreadsApp::updateafterdraw_nornir_overlayand only oncestarted_at.elapsed() >= SPLASH_DURATION_SECS, so it appears after the logo. - A
Check={ name, ok, detail, why, fixable, instructions }. - LAW #6:
Preflight::state_json()is folded into the viz dump underpreflight— a test/agent sees the same checks the user sees.
Checks today
| Check | Probe | If failing |
rust toolchain (cargo) |
cargo --version |
⬇ Install rustup for me button |
rustup |
rustup --version |
same |
| MCP integration | warehouse mcp_requests count (via the 📞 MCP tab) |
warning + 📋-copyable claude mcp add … |
The one sanctioned shell-out
nornir is otherwise 100% Rust / no-shell. The only exception (Rickard, 2026-06-13) is the rustup installer, run from the Install rustup for me button — the official curl … | sh -s -- -y --profile minimal one-liner, in a background thread, gated behind an explicit click. We never install anything unasked. When it finishes the checks re-probe so a now-present cargo flips green (restart the shell/service so it's on PATH).
MCP-usage warning
If telemetry is loaded and 0 MCP calls are recorded, no agent has used nornir's 56 tools — so the operator probably hasn't wired the server into their Claude agent. The popup shows the exact claude mcp add command, built from this client's live connection (server endpoint + token — never a hardcoded secret), with a 📋 copy button. It does not pin NORNIR_WORKSPACE: the MCP exposes every workspace (see mcp-from-claude-code.md).
Clipboard
egui (which facett builds on) makes label text selectable and Ctrl+C / Ctrl+V work in any text field, popups included; the command block also has an explicit 📋 Copy button (one click, ctx.copy_text).
Why it matters (the bug it would have caught)
The server's nornir service user had no cargo on PATH, and library crates gitignore Cargo.lock, so Mimir.SecurityScan failed with a cryptic read …/Cargo.lock Internal. A pre-flight check states the real problem ("rust toolchain: cargo not found") and offers the fix, instead of letting it surface as a confusing scan error three clicks later.