use std::{ fs::{self, OpenOptions}, io::{self, Write}, net::Ipv4Addr, path::{Path, PathBuf}, process::ExitCode, time::Duration, }; use chrono::{DateTime, Utc}; use clap::{Args, Parser, Subcommand, ValueEnum}; use serde::Serialize; use serde_json::{Value, json}; use sha2::{Digest, Sha256}; use ultimate_tool_core::{ DebugCaptureAuthorization, DebugCapturePreparationRequest, Error, LoadedManifest, LocationSemantics, NativeAuthorizationMode, NativeHealthCheckRequest, NativeRepository, NativeRunRequest, ProbeRequest, ProgressEvent, ResolveMatch, RiscvSmokeRequest, RunOutcome, RunRepository, SourceLinkedCaptureAuthorization, SourceLinkedCapturePreparationRequest, TIMELINE_DEFAULT_LIMIT, TargetKind, TestRequest, TimelineAccess, TimelineCursor, TimelineItem, TimelineQuery, execute_source_linked_capture, inspect_ue2, pack_elf_as_ue2, parse_address, parse_timeline_address_range, prepare_source_linked_capture, probe_ultimate, run_native, run_native_health_check, run_riscv_smoke, run_test_matrix_observed, validate_ue2_for_elf, }; use uuid::Uuid; const CLI_SCHEMA_VERSION: u32 = 1; #[derive(Debug, Parser)] #[command(version, about = "Hardware-in-the-loop C64 development")] struct Cli { /// Select human output or a versioned machine-readable envelope. #[arg(long, global = true, value_enum, default_value_t = OutputFormat::Human)] format: OutputFormat, #[command(subcommand)] command: Command, } #[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)] enum OutputFormat { Human, Json, Jsonl, } #[derive(Debug, Subcommand)] enum Command { /// Validate a c64dev.toml project contract. Validate(ManifestArgs), /// Inspect local prerequisites without executing commands or contacting targets. Doctor { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long, value_enum, default_value_t = TargetChoice::Fake)] target: TargetChoice, }, /// Probe a target without mutating it. Probe { #[command(subcommand)] target: ProbeTarget, }, /// Build once and execute a named test on one or more targets. Test(TestArgs), /// Capture one bounded C64 Ultimate 6510 debug stream. Capture { #[command(subcommand)] command: CaptureCommand, }, /// Inspect immutable run records and registered evidence. Runs { #[command(subcommand)] command: RunsCommand, }, /// Inspect, validate, or package a volatile U64-II update container. Ue2 { #[command(subcommand)] command: Ue2Command, }, /// Run the trusted volatile U64-II RISC-V smoke and recover stock firmware. Riscv { #[command(subcommand)] command: RiscvCommand, }, /// Produce reviewed, sanitized static derivatives without changing run evidence. Showcase { #[command(subcommand)] command: ShowcaseCommand, }, /// Start the loopback development service and embedded dashboard. Serve { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long, default_value_t = 6464)] port: u16, }, } impl Command { const fn name(&self) -> &'static str { match self { Self::Validate(_) => "validate", Self::Doctor { .. } => "doctor", Self::Probe { .. } => "probe", Self::Test(_) => "test", Self::Capture { command: CaptureCommand::DebugStream(_), } => "capture.debug_stream", Self::Capture { command: CaptureCommand::SourceLinked(_), } => "capture.source_linked", Self::Runs { command: RunsCommand::List(_), } => "runs.list", Self::Runs { command: RunsCommand::Show(_), } => "runs.show", Self::Runs { command: RunsCommand::Evidence(_), } => "runs.evidence", Self::Runs { command: RunsCommand::Resolve(_), } => "runs.resolve", Self::Runs { command: RunsCommand::Timeline(_), } => "runs.timeline", Self::Runs { command: RunsCommand::CrashReport(_), } => "runs.crash_report", Self::Runs { command: RunsCommand::Compare(_), } => "runs.compare", Self::Runs { command: RunsCommand::Report(_), } => "runs.report", Self::Runs { command: RunsCommand::ReportItems(_), } => "runs.report_items", Self::Runs { command: RunsCommand::CompareCheckpoints(_), } => "runs.compare_checkpoints", Self::Runs { command: RunsCommand::Comparisons(_), } => "runs.comparisons", Self::Runs { command: RunsCommand::Comparison(_), } => "runs.comparison", Self::Ue2 { command: Ue2Command::Inspect(_), } => "ue2.inspect", Self::Ue2 { command: Ue2Command::Validate(_), } => "ue2.validate", Self::Ue2 { command: Ue2Command::Pack(_), } => "ue2.pack", Self::Riscv { command: RiscvCommand::Smoke(_), } => "riscv.smoke", Self::Riscv { command: RiscvCommand::Prepare(_), } => "riscv.prepare", Self::Riscv { command: RiscvCommand::Run(_), } => "riscv.run", Self::Riscv { command: RiscvCommand::HealthCheck(_), } => "riscv.health_check", Self::Riscv { command: RiscvCommand::Intent { command: RiscvIntentCommand::Create(_), }, } => "riscv.intent.create", Self::Riscv { command: RiscvCommand::Intent { command: RiscvIntentCommand::Show(_), }, } => "riscv.intent.show", Self::Riscv { command: RiscvCommand::Intent { command: RiscvIntentCommand::Revoke(_), }, } => "riscv.intent.revoke", Self::Showcase { command: ShowcaseCommand::Export(_), } => "showcase.export", Self::Serve { .. } => "serve", } } } #[derive(Debug, Subcommand)] enum CaptureCommand { /// Capture the configured multicast stream with exact start/stop authorization. DebugStream(DebugCaptureArgs), /// Build, source-link, launch, and capture the bounded timeline probe. SourceLinked(SourceLinkedCaptureArgs), } #[derive(Debug, Args)] struct DebugCaptureArgs { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, /// Literal wired IPv4 address of the intended C64 Ultimate. #[arg(long)] device: String, /// Local stream-capable interface IPv4 address. #[arg(long)] interface: Ipv4Addr, #[arg(long)] expect_device_id: Option, #[arg(long)] expect_hostname: Option, /// Must be exactly 1. #[arg(long)] confirm_stream_start_count: u16, /// Must be exactly 1; cleanup is attempted even if start fails. #[arg(long)] confirm_stream_stop_count: u16, } #[derive(Debug, Args)] struct SourceLinkedCaptureArgs { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long)] test: String, /// Literal wired IPv4 address of the intended C64 Ultimate. #[arg(long)] device: String, /// Local stream-capable interface IPv4 address. #[arg(long)] interface: Ipv4Addr, #[arg(long)] expect_device_id: Option, #[arg(long)] expect_hostname: Option, /// Must be exactly 1; run_prg performs one reset, DMA load, and launch. #[arg(long)] confirm_reset_count: u16, /// Must be exactly 1. #[arg(long)] confirm_stream_start_count: u16, /// Must be exactly 1; cleanup is attempted on every post-preflight path. #[arg(long)] confirm_stream_stop_count: u16, } #[derive(Debug, Args)] struct ManifestArgs { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, } #[derive(Debug, Subcommand)] enum ProbeTarget { /// Read C64 Ultimate REST identity and version information. Ultimate { #[arg(long)] device: String, #[arg(long, default_value_t = 8_000)] timeout_ms: u64, /// Issue each probe read once, with no retry, redirect, or swallowed /// optional-capability failure. A strict restriction, not a permission. #[arg(long)] strict_gate: bool, }, } #[derive(Debug, Args)] struct TestArgs { test: String, #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long, value_enum, required = true)] target: Vec, #[arg(long)] device: Option, #[arg(long)] expect_device_id: Option, #[arg(long)] expect_hostname: Option, #[arg(long)] allow_reset: bool, /// Permit one declared REU image write per Ultimate iteration. #[arg(long)] allow_reu_write: bool, /// Compare this build with one immutable baseline and preserve the result. #[arg(long)] baseline_run: Option, /// Compare frozen checkpoints, requiring VICE then Ultimate and one iteration. #[arg(long)] compare_checkpoints: bool, /// Opt-in strict physical-gate restriction. Defaults to off; when enabled it /// fails closed on the first transport, status, body, or parse error instead /// of retrying or falling back. It adds no authorization. #[arg(long)] strict_gate: bool, #[arg(long, default_value_t = 1)] repeat: u16, } #[derive(Debug, Clone, Copy, ValueEnum)] enum TargetChoice { Fake, Vice, Ultimate, } #[derive(Debug, Subcommand)] enum RunsCommand { /// List newest immutable runs. List(RunsListArgs), /// Show one complete immutable run. Show(RunsShowArgs), /// Locate or copy one registered evidence file. Evidence(RunsEvidenceArgs), /// Resolve an address through one immutable run's snapshotted build analysis. Resolve(RunsResolveArgs), /// Page through one immutable debug-stream bus timeline. Timeline(RunsTimelineArgs), /// Report an immutable run's exact instrumented crash site. CrashReport(RunsCrashReportArgs), /// Compare build artifacts, sections, objects, and symbols between two runs. Compare(RunsCompareArgs), /// Explain recorded expectations, outcomes and verified evidence. Report(RunsReportArgs), /// Read one bounded page of recorded diagnostic detail. ReportItems(RunsReportItemsArgs), /// Compare verified frozen checkpoints from two completed runs without target access. CompareCheckpoints(RunsCompareCheckpointsArgs), /// List separately persisted checkpoint-comparison records. Comparisons(ComparisonsListArgs), /// Inspect a checksummed immutable checkpoint-comparison record. Comparison(ComparisonShowArgs), } #[derive(Debug, Args)] struct RunsListArgs { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long, default_value_t = 50)] limit: usize, } #[derive(Debug, Args)] struct RepositoryArgs { /// Inspect a repository without loading a current manifest. #[arg(long, conflicts_with = "manifest")] project_root: Option, /// Use this manifest's project root (defaults to c64dev.toml). #[arg(long, conflicts_with = "project_root")] manifest: Option, } impl RepositoryArgs { fn root(&self) -> ultimate_tool_core::Result { if let Some(root) = &self.project_root { Ok(root.clone()) } else { Ok( LoadedManifest::load(self.manifest.as_deref().unwrap_or(Path::new("c64dev.toml")))? .project_root, ) } } fn repository(&self) -> ultimate_tool_core::Result { Ok(RunRepository::new(&self.root()?)) } } #[derive(Debug, Args)] struct RunsCompareCheckpointsArgs { baseline: Uuid, candidate: Uuid, #[command(flatten)] repository: RepositoryArgs, } #[derive(Debug, Args)] struct ComparisonsListArgs { #[arg(long, default_value_t = 50)] limit: usize, #[command(flatten)] repository: RepositoryArgs, } #[derive(Debug, Args)] struct ComparisonShowArgs { comparison_id: Uuid, #[command(flatten)] repository: RepositoryArgs, } #[derive(Debug, Subcommand)] enum ShowcaseCommand { /// Export a new static directory; this does not publish it. Export(ShowcaseExportArgs), } #[derive(Debug, Args)] struct ShowcaseExportArgs { #[arg(long)] run: Uuid, #[arg(long)] output: PathBuf, #[arg(long, default_value = "Recorded development evidence")] label: String, #[arg(long)] section: Option, #[arg(long, default_value_t = 50)] limit: usize, #[arg(long)] cursor: Option, #[command(flatten)] repository: RepositoryArgs, } #[derive(Debug, Args)] struct RunsReportArgs { run_id: Uuid, #[command(flatten)] repository: RepositoryArgs, } #[derive(Debug, Args)] struct RunsReportItemsArgs { run_id: Uuid, /// checkpoints, budget, assertions, comparison_sections, comparison_objects or comparison_symbols. #[arg(long)] section: String, #[arg(long, default_value_t = 50)] limit: usize, #[arg(long)] cursor: Option, #[command(flatten)] repository: RepositoryArgs, } #[derive(Debug, Args)] struct RunsShowArgs { run_id: Uuid, #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, } #[derive(Debug, Args)] struct RunsEvidenceArgs { run_id: Uuid, name: String, #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, /// Copy exact evidence bytes to a new file. Existing files are never replaced. #[arg(long)] output: Option, } #[derive(Debug, Args)] struct RunsResolveArgs { run_id: Uuid, address: String, #[arg(long)] context: Option, #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, } #[derive(Debug, Clone, Copy, ValueEnum)] enum TimelineAccessChoice { Read, Write, } impl From for TimelineAccess { fn from(value: TimelineAccessChoice) -> Self { match value { TimelineAccessChoice::Read => Self::Read, TimelineAccessChoice::Write => Self::Write, } } } #[derive(Debug, Args)] struct RunsTimelineArgs { run_id: Uuid, #[arg(long)] cursor: Option, #[arg(long, default_value_t = TIMELINE_DEFAULT_LIMIT)] limit: usize, /// One address or an inclusive range such as $D020-$D021. #[arg(long)] address: Option, #[arg(long, value_enum)] access: Option, #[arg(long)] context: Option, #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, } #[derive(Debug, Args)] struct RunsCrashReportArgs { run_id: Uuid, #[arg(long)] context: Option, #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, } #[derive(Debug, Args)] struct RunsCompareArgs { baseline_run_id: Uuid, candidate_run_id: Uuid, #[arg(long)] context: Option, #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, } #[derive(Debug, Subcommand)] enum Ue2Command { /// Parse and enforce the bounded canonical container policy. Inspect(Ue2InspectArgs), /// Prove that a UE2 is the exact canonical encoding of an ELF. Validate(Ue2ValidateArgs), /// Create a canonical UE2 from an ELF without replacing an existing file. Pack(Ue2PackArgs), } #[derive(Debug, Args)] struct Ue2InspectArgs { file: PathBuf, } #[derive(Debug, Args)] struct Ue2ValidateArgs { file: PathBuf, #[arg(long)] elf: PathBuf, } #[derive(Debug, Args)] struct Ue2PackArgs { #[arg(long)] elf: PathBuf, #[arg(long)] output: PathBuf, } #[derive(Debug, Subcommand)] enum RiscvCommand { /// Build, validate, and immutably snapshot a standalone trusted native project. Prepare(RiscvPrepareArgs), /// Create and manage hash-bound native launch authorization. Intent { #[command(subcommand)] command: RiscvIntentCommand, }, /// Execute the exact prepared UE2 authorized by a durable launch intent. Run(RiscvRunArgs), /// Complete a pending post-recovery C64 health check without relaunching native code. HealthCheck(RiscvHealthCheckArgs), /// Execute one bounded trusted-payload smoke over Wi-Fi. Smoke(RiscvSmokeArgs), } #[derive(Debug, Args)] struct RiscvPrepareArgs { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, } #[derive(Debug, Subcommand)] enum RiscvIntentCommand { /// Bind one preparation hash to an exact probed Ultimate. Create(RiscvIntentCreateArgs), /// Show one durable launch intent. Show(RiscvIntentShowArgs), /// Permanently revoke one launch intent. Revoke(RiscvIntentRevokeArgs), } #[derive(Debug, Clone, Copy, ValueEnum)] enum RiscvAuthorizationChoice { OneShot, Standing, } impl From for NativeAuthorizationMode { fn from(value: RiscvAuthorizationChoice) -> Self { match value { RiscvAuthorizationChoice::OneShot => Self::OneShot, RiscvAuthorizationChoice::Standing => Self::Standing, } } } #[derive(Debug, Args)] struct RiscvIntentCreateArgs { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long)] preparation: Uuid, #[arg(long)] device: String, #[arg(long)] expect_device_id: Option, #[arg(long)] expect_hostname: Option, #[arg(long, value_enum)] authorization: RiscvAuthorizationChoice, #[arg(long)] expires_at: Option>, #[arg(long)] maximum_runs: Option, /// Confirm that standing mode grants repeated bounded native mutations. #[arg(long)] confirm_standing_native_execution: bool, } #[derive(Debug, Args)] struct RiscvIntentShowArgs { intent: Uuid, #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, } #[derive(Debug, Args)] struct RiscvIntentRevokeArgs { intent: Uuid, #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long)] reason: String, } #[derive(Debug, Args)] struct RiscvRunArgs { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long)] intent: Uuid, #[arg(long)] device: String, #[arg(long)] expect_device_id: Option, #[arg(long)] expect_hostname: Option, } #[derive(Debug, Args)] struct RiscvHealthCheckArgs { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long)] intent: Uuid, #[arg(long)] after_run: Uuid, #[arg(long)] device: String, #[arg(long)] expect_device_id: Option, #[arg(long)] expect_hostname: Option, } #[derive(Debug, Args)] struct RiscvSmokeArgs { #[arg(long, default_value = "c64dev.toml")] manifest: PathBuf, #[arg(long)] device: String, #[arg(long)] expect_device_id: Option, #[arg(long)] expect_hostname: Option, /// Use an exact eight-character uppercase hexadecimal nonce for a new smoke. #[arg(long)] nonce: Option, /// Resume one eligible pre-Run-Update failure without creating another FTP file. #[arg(long)] resume_staged_run: Option, #[arg(long)] allow_ftp_create: bool, #[arg(long)] allow_run_update: bool, #[arg(long)] allow_machine_reboot: bool, #[arg(long)] allow_recovery_reset: bool, #[arg(long)] allow_startup_write: bool, } #[derive(Debug)] struct ExecutionOutput { data: Value, human: Vec, exit_code: u8, } #[derive(Debug, Serialize)] struct MachineEnvelope<'a> { schema_version: u32, record_kind: &'a str, command: &'a str, data: Value, #[serde(skip_serializing_if = "Option::is_none")] error: Option, } #[derive(Debug, Serialize)] struct MachineError { code: &'static str, layer: &'static str, message: String, exit_code: u8, } #[derive(Debug, Serialize)] struct EvidenceInfo { run_id: Uuid, name: String, canonical_path: PathBuf, size: u64, sha256: String, copied_to: Option, } #[tokio::main] async fn main() -> ExitCode { let cli = Cli::parse(); let format = cli.format; let command = cli.command.name(); match execute(cli, command).await { Ok(output) => { render_success(format, command, &output); ExitCode::from(output.exit_code) } Err(error) => { render_error(format, command, &error); ExitCode::from(error.exit_code()) } } } async fn execute(cli: Cli, command: &'static str) -> ultimate_tool_core::Result { let format = cli.format; match cli.command { Command::Validate(arguments) => { let manifest = LoadedManifest::load(arguments.manifest)?; Ok(ExecutionOutput { data: json!({ "project": manifest.manifest.project.name, "manifest_schema_version": manifest.manifest.schema_version, "manifest": manifest.path, }), human: vec![format!( "valid: {} (schema {})", manifest.manifest.project.name, manifest.manifest.schema_version )], exit_code: 0, }) } Command::Doctor { manifest, target } => { let target = match target { TargetChoice::Fake => TargetKind::Fake, TargetChoice::Vice => TargetKind::Vice, TargetChoice::Ultimate => TargetKind::Ultimate, }; let report = ultimate_tool_core::doctor::doctor(&manifest, target); let mut human = vec![format!( "local prerequisites: {:?}; target runtime is not verified", report.status )]; human.extend( report.checks.iter().map(|check| { format!(" {:?}: {:?} — {}", check.id, check.status, check.detail) }), ); Ok(ExecutionOutput { data: serde_json::to_value(&report) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: report.exit_code(), }) } Command::Probe { target: ProbeTarget::Ultimate { device, timeout_ms, strict_gate, }, } => { let identity = tokio::task::spawn_blocking(move || { probe_ultimate(&ProbeRequest { host: device, request_timeout: Duration::from_millis(timeout_ms), strict_gate, }) }) .await .map_err(|error| Error::Preflight(format!("probe worker failed: {error}")))??; Ok(ExecutionOutput { data: serde_json::to_value(&identity) .map_err(|error| Error::Evidence(error.to_string()))?, human: vec![ serde_json::to_string_pretty(&identity) .map_err(|error| Error::Evidence(error.to_string()))?, ], exit_code: 0, }) } Command::Test(arguments) => { let (summaries, comparison_pair) = tokio::task::spawn_blocking(move || { let observer = |progress: ProgressEvent| { if format == OutputFormat::Jsonl { emit_machine(MachineEnvelope { schema_version: CLI_SCHEMA_VERSION, record_kind: "progress", command, data: serde_json::to_value(progress).unwrap_or_else( |error| json!({"serialization_error": error.to_string()}), ), error: None, }); } }; let request = TestRequest { manifest_path: arguments.manifest, test: arguments.test, targets: arguments .target .into_iter() .map(|target| match target { TargetChoice::Fake => TargetKind::Fake, TargetChoice::Vice => TargetKind::Vice, TargetChoice::Ultimate => TargetKind::Ultimate, }) .collect(), device: arguments.device, expected_device_id: arguments.expect_device_id, expected_hostname: arguments.expect_hostname, allow_reset: arguments.allow_reset, allow_reu_write: arguments.allow_reu_write, baseline_run_id: arguments.baseline_run, repeat: arguments.repeat, strict_gate: arguments.strict_gate, }; if arguments.compare_checkpoints { let matrix = ultimate_tool_core::runner::run_checkpoint_matrix_observed( &request, &observer, )?; Ok((matrix.runs, Some(matrix.pair))) } else { run_test_matrix_observed(&request, &observer).map(|runs| (runs, None)) } }) .await .map_err(|error| Error::Preflight(format!("test worker failed: {error}")))??; let mut exit_code = summaries .iter() .filter(|summary| summary.outcome != RunOutcome::Passed) .map(|summary| summary.exit_code) .max() .unwrap_or(0); if comparison_pair.as_ref().is_some_and(|pair| { pair.state != ultimate_tool_core::checkpoints::CheckpointComparisonState::Matched }) { exit_code = exit_code.max(4); } let outcome = if exit_code == 0 && summaries .iter() .all(|summary| summary.outcome == RunOutcome::Passed) { RunOutcome::Passed } else if summaries .iter() .any(|summary| summary.outcome == RunOutcome::Error) { RunOutcome::Error } else { RunOutcome::Failed }; let mut human = Vec::new(); for summary in &summaries { human.push(format!( "{} iteration {}/{}: {:?} evidence={}", summary.target, summary.iteration, summary.iteration_total, summary.outcome, summary.directory.display() )); if let Some(error) = &summary.error { human.push(format!(" {error}")); } } if let Some(pair) = &comparison_pair { human.push(format!( "checkpoint comparison {:?}: {} (earliest recorded logical checkpoint only)", pair.state, pair.comparison_id )); } let mut data = json!({"outcome": outcome, "exit_code": exit_code, "runs": summaries}); if let Some(pair) = &comparison_pair { data["checkpoint_comparison"] = serde_json::to_value(pair) .map_err(|error| Error::Evidence(error.to_string()))?; } Ok(ExecutionOutput { data, human, exit_code, }) } Command::Capture { command: CaptureCommand::DebugStream(arguments), } => { let summary = tokio::task::spawn_blocking(move || { let observer = |progress: ProgressEvent| { if format == OutputFormat::Jsonl { emit_machine(MachineEnvelope { schema_version: CLI_SCHEMA_VERSION, record_kind: "progress", command, data: serde_json::to_value(progress).unwrap_or_else( |error| json!({"serialization_error": error.to_string()}), ), error: None, }); } }; let preparation = ultimate_tool_core::prepare_debug_capture(&DebugCapturePreparationRequest { manifest_path: arguments.manifest, device: arguments.device, interface: arguments.interface, expected_device_id: arguments.expect_device_id, expected_hostname: arguments.expect_hostname, })?; ultimate_tool_core::execute_debug_capture( preparation, DebugCaptureAuthorization { confirmed_stream_start_count: arguments.confirm_stream_start_count, confirmed_stream_stop_count: arguments.confirm_stream_stop_count, }, &observer, ) }) .await .map_err(|error| Error::Preflight(format!("capture worker failed: {error}")))??; let mut human = vec![format!( "debug stream: {:?} evidence={}", summary.outcome, summary.directory.display() )]; if let Some(error) = &summary.error { human.push(format!(" {error}")); } Ok(ExecutionOutput { data: serde_json::to_value(&summary) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: summary.exit_code, }) } Command::Capture { command: CaptureCommand::SourceLinked(arguments), } => { if arguments.confirm_reset_count != 1 || arguments.confirm_stream_start_count != 1 || arguments.confirm_stream_stop_count != 1 { return Err(Error::Configuration( "source-linked capture requires --confirm-reset-count 1, --confirm-stream-start-count 1, and --confirm-stream-stop-count 1" .into(), )); } let summary = tokio::task::spawn_blocking(move || { let observer = |progress: ProgressEvent| { if format == OutputFormat::Jsonl { emit_machine(MachineEnvelope { schema_version: CLI_SCHEMA_VERSION, record_kind: "progress", command, data: serde_json::to_value(progress).unwrap_or_else( |error| json!({"serialization_error": error.to_string()}), ), error: None, }); } }; let preparation = prepare_source_linked_capture(&SourceLinkedCapturePreparationRequest { manifest_path: arguments.manifest, test: arguments.test, device: arguments.device, interface: arguments.interface, expected_device_id: arguments.expect_device_id, expected_hostname: arguments.expect_hostname, })?; execute_source_linked_capture( preparation, SourceLinkedCaptureAuthorization { confirmed_reset_count: arguments.confirm_reset_count, confirmed_stream_start_count: arguments.confirm_stream_start_count, confirmed_stream_stop_count: arguments.confirm_stream_stop_count, }, &observer, ) }) .await .map_err(|error| Error::Preflight(format!("capture worker failed: {error}")))??; let mut human = vec![format!( "source-linked timeline: {:?} evidence={}", summary.outcome, summary.directory.display() )]; if let Some(hash) = &summary.artifact_sha256 { human.push(format!(" artifact_sha256={hash}")); } if let Some(error) = &summary.error { human.push(format!(" {error}")); } Ok(ExecutionOutput { data: serde_json::to_value(&summary) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: summary.exit_code, }) } Command::Runs { command: RunsCommand::CompareCheckpoints(arguments), } => { let bundle = ultimate_tool_core::checkpoints::compare_run_checkpoints( &arguments.repository.repository()?, arguments.baseline, arguments.candidate, )?; let matched = bundle.comparison.state == ultimate_tool_core::checkpoints::CheckpointComparisonState::Matched; Ok(ExecutionOutput { human: vec![format!( "checkpoint comparison {:?}; earliest recorded logical checkpoint, not execution-time cause", bundle.comparison.state )], data: serde_json::to_value(&bundle.comparison) .map_err(|error| Error::Evidence(error.to_string()))?, exit_code: if matched { 0 } else { 4 }, }) } Command::Runs { command: RunsCommand::Comparisons(arguments), } => { let repository = ultimate_tool_core::checkpoints::CheckpointComparisonRepository::new( &arguments.repository.root()?, ); let listing = repository.list(arguments.limit)?; Ok(ExecutionOutput { human: listing .summaries .iter() .map(|entry| format!("{} {:?}", entry.comparison_id, entry.state)) .collect(), data: serde_json::to_value(listing) .map_err(|error| Error::Evidence(error.to_string()))?, exit_code: 0, }) } Command::Runs { command: RunsCommand::Comparison(arguments), } => { let repository = ultimate_tool_core::checkpoints::CheckpointComparisonRepository::new( &arguments.repository.root()?, ); let record = repository.load(arguments.comparison_id)?; Ok(ExecutionOutput { human: vec![format!("{} {:?}", record.comparison_id, record.state)], data: serde_json::to_value(record) .map_err(|error| Error::Evidence(error.to_string()))?, exit_code: 0, }) } Command::Runs { command: RunsCommand::Report(arguments), } => { let report = arguments .repository .repository()? .diagnostic_report(arguments.run_id)?; let mut human = vec![format!( "{} {:?}: {} on {} (evidence {:?})", report.run_id, report.outcome, report.test, report.target_kind, report.evidence.integrity )]; if let Some(failure) = &report.failure { human.push(format!( " {} / {}: {}", failure.layer, failure.stage, failure.message )); } human.push(format!( " expectations {:?}; terminal {:?}; screen {:?}", report.expectations.availability, report.results.terminal_verdict, report.results.screen_verdict )); Ok(ExecutionOutput { data: serde_json::to_value(&report) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: 0, }) } Command::Runs { command: RunsCommand::ReportItems(arguments), } => { use ultimate_tool_core::report::{ DIAGNOSTIC_REPORT_SCHEMA_VERSION, DiagnosticCursor, DiagnosticItemsQuery, }; let query = DiagnosticItemsQuery { schema_version: DIAGNOSTIC_REPORT_SCHEMA_VERSION, section: arguments.section.parse()?, limit: arguments.limit, cursor: arguments .cursor .as_deref() .map(DiagnosticCursor::parse) .transpose()?, }; let page = arguments .repository .repository()? .diagnostic_items(arguments.run_id, &query)?; let mut human = vec![format!( "{} {}: {} of {} rows", page.run_id, page.section, page.items.len(), page.total )]; for item in &page.items { human.push( serde_json::to_string(item) .map_err(|error| Error::Evidence(error.to_string()))?, ); } if let Some(cursor) = &page.next_cursor { human.push(format!("next cursor: {cursor}")); } Ok(ExecutionOutput { data: serde_json::to_value(&page) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: 0, }) } Command::Runs { command: RunsCommand::List(arguments), } => { let manifest = LoadedManifest::load(arguments.manifest)?; let listing = RunRepository::new(&manifest.project_root).list(arguments.limit)?; let mut human = listing .runs .iter() .map(|run| { format!( "{} {} {} {:?} iteration {}/{}", run.run_id, run.target_kind, run.test, run.outcome, run.iteration, run.iteration_total ) }) .collect::>(); human.extend( listing .warnings .iter() .map(|warning| format!("warning: {warning}")), ); Ok(ExecutionOutput { data: serde_json::to_value(&listing) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: 0, }) } Command::Runs { command: RunsCommand::Show(arguments), } => { let manifest = LoadedManifest::load(arguments.manifest)?; let record = RunRepository::new(&manifest.project_root).load(arguments.run_id)?; Ok(ExecutionOutput { data: serde_json::to_value(&record) .map_err(|error| Error::Evidence(error.to_string()))?, human: vec![ serde_json::to_string_pretty(&record) .map_err(|error| Error::Evidence(error.to_string()))?, ], exit_code: 0, }) } Command::Runs { command: RunsCommand::Evidence(arguments), } => { let manifest = LoadedManifest::load(arguments.manifest)?; let repository = RunRepository::new(&manifest.project_root); let source = repository.evidence_path(arguments.run_id, &arguments.name)?; let bytes = fs::read(&source)?; let copied_to = arguments .output .as_deref() .map(|output| copy_create_new(output, &bytes)) .transpose()?; let info = EvidenceInfo { run_id: arguments.run_id, name: arguments.name, canonical_path: fs::canonicalize(&source)?, size: bytes.len() as u64, sha256: format!("{:x}", Sha256::digest(&bytes)), copied_to, }; Ok(ExecutionOutput { data: serde_json::to_value(&info) .map_err(|error| Error::Evidence(error.to_string()))?, human: vec![format!( "{} {} bytes sha256={}{}", info.canonical_path.display(), info.size, info.sha256, info.copied_to .as_ref() .map_or_else(String::new, |path| format!(" copied={}", path.display())) )], exit_code: 0, }) } Command::Runs { command: RunsCommand::Resolve(arguments), } => { let manifest = LoadedManifest::load(arguments.manifest)?; let address = parse_address(&arguments.address)?; let result = RunRepository::new(&manifest.project_root).resolve_address( arguments.run_id, address, arguments.context.as_deref(), )?; let mut human = vec![format!( "{} {} at {}", arguments.run_id, format!("{:?}", result.state).to_lowercase(), result.address_hex )]; human.extend(result.matches.iter().map(|resolved| { format!( " {} {}+{} [{}]{}{}", resolved.rank, resolved.symbol, resolved.offset, resolved.context, resolved .section .as_ref() .map_or_else(String::new, |section| format!(" section={section}")), human_source_location(resolved) ) })); Ok(ExecutionOutput { data: serde_json::to_value(&result) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: 0, }) } Command::Runs { command: RunsCommand::Timeline(arguments), } => { let manifest = LoadedManifest::load(arguments.manifest)?; let address = arguments .address .as_deref() .map(parse_timeline_address_range) .transpose()?; let page = RunRepository::new(&manifest.project_root).timeline( arguments.run_id, &TimelineQuery { cursor: arguments.cursor, limit: arguments.limit, address, access: arguments.access.map(Into::into), context: arguments.context, ..TimelineQuery::default() }, )?; let mut human = vec![format!( "{} {:?} complete={} truncated={} gap={} next={}", arguments.run_id, page.mode, page.capture_complete, page.capture_truncated, page.crosses_gap, page.next_cursor .map_or_else(|| "end".into(), |cursor| cursor.to_string()) )]; human.extend(page.items.iter().map(|item| match item { TimelineItem::Bus(item) => format!( " {} seq={} {} {}={} data={} phi2={} irq_n={} nmi_n={} source={:?}", item.cursor, item.packet_sequence, item.capture_phase, match item.access { TimelineAccess::Read => "read", TimelineAccess::Write => "write", }, item.address_hex, item.data_hex, u8::from(item.signals.phi2), u8::from(item.signals.irq_n), u8::from(item.signals.nmi_n), item.address_resolution.result.state, ), TimelineItem::Gap(item) => format!( " {} gap={:?} expected={} observed={} uncertain={} missing={} length={}", item.cursor, item.discontinuity, item.expected_sequence .map_or_else(|| "unknown".into(), |value| value.to_string()), item.observed_sequence .map_or_else(|| "unknown".into(), |value| value.to_string()), item.uncertain_intervening_datagrams, item.missing_packet_count .map_or_else(|| "unknown".into(), |value| value.to_string()), item.payload_length .map_or_else(|| "unknown".into(), |value| value.to_string()), ), TimelineItem::Instruction(item) => format!( " {} instruction pc=${:04X} bytes={:02X?} class={}", item.cursor, item.pc, item.bytes, item.instruction_class ), })); Ok(ExecutionOutput { data: serde_json::to_value(&page) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: 0, }) } Command::Runs { command: RunsCommand::CrashReport(arguments), } => { let manifest = LoadedManifest::load(arguments.manifest)?; let report = RunRepository::new(&manifest.project_root) .crash_report(arguments.run_id, arguments.context.as_deref())?; let mut human = vec![format!( "{} {}{}", arguments.run_id, format!("{:?}", report.state).to_lowercase(), report .site_address_hex .as_ref() .map_or_else(String::new, |address| format!(" at {address}")) )]; if let Some(reason) = report.unavailable_reason { human.push(format!(" reason={reason}")); } human.extend(report.matches.iter().map(|resolved| { format!( " {} {}+{} [{}]{}{}", resolved.rank, resolved.symbol, resolved.offset, resolved.context, resolved .section .as_ref() .map_or_else(String::new, |section| format!(" section={section}")), human_source_location(resolved) ) })); for warning in &report.warnings { human.push(format!(" warning {}: {}", warning.code, warning.message)); } Ok(ExecutionOutput { data: serde_json::to_value(&report) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: 0, }) } Command::Runs { command: RunsCommand::Compare(arguments), } => { let manifest = LoadedManifest::load(arguments.manifest)?; let comparison = RunRepository::new(&manifest.project_root).compare_runs( arguments.baseline_run_id, arguments.candidate_run_id, arguments.context.as_deref(), )?; let human = vec![ format!( "{} -> {}: {:?}", arguments.baseline_run_id, arguments.candidate_run_id, comparison.state ), format!( " artifact={} sections={} objects={} symbols={} warnings={}", comparison.artifact.as_ref().map_or_else( || "unavailable".into(), |delta| format!("{:+} bytes", delta.delta_bytes) ), comparison.sections.len(), comparison.objects.len(), comparison.symbols.len(), comparison.warnings.len() ), ]; Ok(ExecutionOutput { data: serde_json::to_value(&comparison) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: 0, }) } Command::Ue2 { command: Ue2Command::Inspect(arguments), } => { let bytes = fs::read(&arguments.file).map_err(|error| { Error::Artifact(format!( "cannot read UE2 file {}: {error}", arguments.file.display() )) })?; let inspection = inspect_ue2(&bytes)?; let mut human = vec![format!( "{}: {} records, {} loaded bytes, entry={} sha256={}", arguments.file.display(), inspection.record_count, inspection.total_loaded_bytes, inspection.entry_point_hex, inspection.sha256 )]; human.extend(inspection.records.iter().map(|record| { format!( " record {}: {:#010x}..{:#010x} length={} start={:#010x} sha256={}", record.index, record.load_address, record.end_address, record.length, record.start_address, record.payload_sha256 ) })); Ok(ExecutionOutput { data: serde_json::to_value(&inspection) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: 0, }) } Command::Ue2 { command: Ue2Command::Validate(arguments), } => { let ue2_bytes = fs::read(&arguments.file).map_err(|error| { Error::Artifact(format!( "cannot read UE2 file {}: {error}", arguments.file.display() )) })?; let elf_bytes = fs::read(&arguments.elf).map_err(|error| { Error::Artifact(format!( "cannot read ELF file {}: {error}", arguments.elf.display() )) })?; let validation = validate_ue2_for_elf(&ue2_bytes, &elf_bytes)?; Ok(ExecutionOutput { data: serde_json::to_value(&validation) .map_err(|error| Error::Evidence(error.to_string()))?, human: vec![format!( "valid: {} exactly matches {} (entry={}, sha256={})", arguments.file.display(), arguments.elf.display(), validation.elf_entry_point_hex, validation.inspection.sha256 )], exit_code: 0, }) } Command::Ue2 { command: Ue2Command::Pack(arguments), } => { let elf_bytes = fs::read(&arguments.elf).map_err(|error| { Error::Artifact(format!( "cannot read ELF file {}: {error}", arguments.elf.display() )) })?; let packed = pack_elf_as_ue2(&elf_bytes)?; let canonical_output = write_artifact_create_new(&arguments.output, &packed.bytes)?; Ok(ExecutionOutput { data: json!({ "elf": arguments.elf, "output": canonical_output, "validation": packed.validation, }), human: vec![format!( "{}: {} bytes, {} records, entry={}, sha256={}", canonical_output.display(), packed.validation.inspection.file_size, packed.validation.inspection.record_count, packed.validation.elf_entry_point_hex, packed.validation.inspection.sha256 )], exit_code: 0, }) } Command::Riscv { command: RiscvCommand::Prepare(arguments), } => { let loaded = LoadedManifest::load(&arguments.manifest)?; let repository = NativeRepository::new(&loaded.project_root); let prepared = tokio::task::spawn_blocking(move || repository.prepare(&arguments.manifest)) .await .map_err(|error| { Error::Build(format!("native preparation worker failed: {error}")) })??; Ok(ExecutionOutput { data: serde_json::to_value(&prepared.record) .map_err(|error| Error::Evidence(error.to_string()))?, human: vec![ format!( "prepared native application {}", prepared.record.preparation_id ), format!( " ELF {} bytes sha256={}", prepared.record.elf.size, prepared.record.elf.sha256 ), format!( " UE2 {} bytes sha256={} policy={}", prepared.record.ue2.size, prepared.record.ue2.sha256, prepared.record.ue2_validation.policy ), format!(" evidence={}", prepared.directory.display()), ], exit_code: 0, }) } Command::Riscv { command: RiscvCommand::Intent { command: RiscvIntentCommand::Create(arguments), }, } => { let loaded = LoadedManifest::load(&arguments.manifest)?; if matches!(arguments.authorization, RiscvAuthorizationChoice::Standing) && !arguments.confirm_standing_native_execution { return Err(Error::Preflight( "standing authorization requires --confirm-standing-native-execution".into(), )); } let device = arguments.device.clone(); let request_timeout = Duration::from_millis(loaded.manifest.ultimate.request_timeout_ms); let identity = tokio::task::spawn_blocking(move || { probe_ultimate(&ProbeRequest { host: device, request_timeout, strict_gate: false, }) }) .await .map_err(|error| Error::Preflight(format!("probe worker failed: {error}")))??; ultimate_tool_core::target::ultimate::UltimateTarget::verify_expected_identity( &identity, arguments.expect_device_id.as_deref(), arguments.expect_hostname.as_deref(), )?; let intent = NativeRepository::new(&loaded.project_root).create_intent( arguments.preparation, &identity, arguments.authorization.into(), arguments.expires_at, arguments.maximum_runs, )?; Ok(ExecutionOutput { data: serde_json::to_value(&intent.record) .map_err(|error| Error::Evidence(error.to_string()))?, human: vec![ format!( "created {:?} native launch intent", intent.record.authorization ), format!(" intent={}", intent.record.intent_id), format!(" ue2_sha256={}", intent.record.ue2_sha256), format!(" remote_path={}", intent.record.remote_path), format!( " device={} firmware={:?} fpga={:?} core={:?}", intent.record.target.product, intent.record.target.firmware_version, intent.record.target.fpga_version, intent.record.target.core_version ), ], exit_code: 0, }) } Command::Riscv { command: RiscvCommand::Intent { command: RiscvIntentCommand::Show(arguments), }, } => { let loaded = LoadedManifest::load(&arguments.manifest)?; let intent = NativeRepository::new(&loaded.project_root).load_intent(arguments.intent)?; Ok(ExecutionOutput { data: serde_json::to_value(&intent.record) .map_err(|error| Error::Evidence(error.to_string()))?, human: vec![ format!( "native intent {}: {:?} {:?}", intent.record.intent_id, intent.record.authorization, intent.record.state ), format!( " uses={} maximum={:?} expires={:?}", intent.record.use_count, intent.record.maximum_runs, intent.record.expires_at ), format!( " ue2_sha256={} remote_path={}", intent.record.ue2_sha256, intent.record.remote_path ), ], exit_code: 0, }) } Command::Riscv { command: RiscvCommand::Intent { command: RiscvIntentCommand::Revoke(arguments), }, } => { let loaded = LoadedManifest::load(&arguments.manifest)?; let repository = NativeRepository::new(&loaded.project_root); repository.revoke_intent(arguments.intent, &arguments.reason)?; let intent = repository.load_intent(arguments.intent)?; Ok(ExecutionOutput { data: serde_json::to_value(&intent.record) .map_err(|error| Error::Evidence(error.to_string()))?, human: vec![format!( "revoked native launch intent {}: {}", intent.record.intent_id, intent.record.state_reason.as_deref().unwrap_or("") )], exit_code: 0, }) } Command::Riscv { command: RiscvCommand::Run(arguments), } => { let summary = tokio::task::spawn_blocking(move || { run_native(&NativeRunRequest { manifest_path: arguments.manifest, intent_id: arguments.intent, device: arguments.device, expected_device_id: arguments.expect_device_id, expected_hostname: arguments.expect_hostname, }) }) .await .map_err(|error| Error::Preflight(format!("native run worker failed: {error}")))??; let mut human = vec![ format!( "trusted native run {:?}: run={} display={} evidence={}", summary.outcome, summary.run_id, summary.invocation_display_id, summary.directory.display() ), format!( " intent={} preparation={}", summary.intent_id, summary.preparation_id ), ]; if let Some(health_check) = summary.post_recovery_health_check_run_id { human.push(format!( " post-recovery C64 health-check run={health_check}" )); } if let Some(error) = &summary.error { human.push(format!(" {error}")); } Ok(ExecutionOutput { data: serde_json::to_value(&summary) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: summary.exit_code, }) } Command::Riscv { command: RiscvCommand::HealthCheck(arguments), } => { let summary = tokio::task::spawn_blocking(move || { run_native_health_check(&NativeHealthCheckRequest { manifest_path: arguments.manifest, intent_id: arguments.intent, after_run_id: arguments.after_run, device: arguments.device, expected_device_id: arguments.expect_device_id, expected_hostname: arguments.expect_hostname, }) }) .await .map_err(|error| { Error::Preflight(format!("native health-check worker failed: {error}")) })??; let mut human = vec![ format!( "post-recovery C64 health check {:?}: run={} evidence={}", summary.outcome, summary.health_check_run_id, summary.directory.display() ), format!( " native_run={} intent={}", summary.after_run_id, summary.intent_id ), ]; if let Some(error) = &summary.error { human.push(format!(" {error}")); } Ok(ExecutionOutput { data: serde_json::to_value(&summary) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: summary.exit_code, }) } Command::Riscv { command: RiscvCommand::Smoke(arguments), } => { let summary = tokio::task::spawn_blocking(move || { run_riscv_smoke(&RiscvSmokeRequest { manifest_path: arguments.manifest, device: arguments.device, expected_device_id: arguments.expect_device_id, expected_hostname: arguments.expect_hostname, nonce: arguments.nonce, resume_staged_run_id: arguments.resume_staged_run, allow_ftp_create: arguments.allow_ftp_create, allow_run_update: arguments.allow_run_update, allow_machine_reboot: arguments.allow_machine_reboot, allow_recovery_reset: arguments.allow_recovery_reset, allow_startup_write: arguments.allow_startup_write, }) }) .await .map_err(|error| Error::Preflight(format!("RISC-V worker failed: {error}")))??; let mut human = vec![format!( "RISC-V smoke {:?}: run={} evidence={}", summary.outcome, summary.run_id, summary.directory.display() )]; if let Some(recovery) = summary.recovery_run_id { human.push(format!(" post-recovery C64 health-check run={recovery}")); } if let Some(error) = &summary.error { human.push(format!(" {error}")); } Ok(ExecutionOutput { data: serde_json::to_value(&summary) .map_err(|error| Error::Evidence(error.to_string()))?, human, exit_code: summary.exit_code, }) } Command::Showcase { command: ShowcaseCommand::Export(arguments), } => { use ultimate_tool_core::showcase::{ ShowcaseExportRequest, ShowcaseRowWindow, ShowcaseSection, ShowcaseSelection, export_showcase, }; let root = arguments.repository.root()?; if arguments.cursor.is_some() && arguments.section.is_none() { return Err(Error::Configuration( "showcase --cursor requires --section".into(), )); } let mut selection = ShowcaseSelection::new(vec![ShowcaseSection::Workflow]); if let Some(section) = arguments.section { let window = if section == "timeline" { ShowcaseRowWindow::Timeline { limit: arguments.limit, cursor: arguments.cursor.clone(), } } else { let section = section.parse()?; match section { ultimate_tool_core::report::DiagnosticSection::Budget => { selection.sections.push(ShowcaseSection::Budget) } ultimate_tool_core::report::DiagnosticSection::Assertions => { selection.sections.push(ShowcaseSection::Assertions) } ultimate_tool_core::report::DiagnosticSection::ComparisonSections | ultimate_tool_core::report::DiagnosticSection::ComparisonObjects | ultimate_tool_core::report::DiagnosticSection::ComparisonSymbols => { selection.sections.push(ShowcaseSection::Comparison) } ultimate_tool_core::report::DiagnosticSection::Checkpoints => {} } ShowcaseRowWindow::DiagnosticItems { section, limit: arguments.limit, cursor: arguments.cursor.clone(), } }; selection = selection.with_row_window(window); } let output = if arguments.output.is_absolute() { arguments.output } else { std::env::current_dir()?.join(arguments.output) }; let request = ShowcaseExportRequest::new(root.clone(), output, selection) .with_review_label(arguments.label); let export = export_showcase(&RunRepository::new(&root), arguments.run, &request)?; Ok(ExecutionOutput { human: vec![format!( "sanitized derivative: {}; not published", export.html_file.display() )], data: serde_json::to_value(&export) .map_err(|error| Error::Evidence(error.to_string()))?, exit_code: 0, }) } Command::Serve { manifest, port } => { ultimate_tool_server::serve(ultimate_tool_server::ServerConfig { manifest_path: manifest, port, }) .await?; Ok(ExecutionOutput { data: json!({"stopped": true}), human: Vec::new(), exit_code: 0, }) } } } fn human_source_location(resolved: &ResolveMatch) -> String { let Some(location) = &resolved.location else { return String::new(); }; let mut rendered = location.file.clone(); if let Some(line) = location.line { rendered.push_str(&format!(":{line}")); if let Some(column) = location.column { rendered.push_str(&format!(":{column}")); } } match resolved.location_semantics { Some(LocationSemantics::AddressCallsite) => format!(" callsite={rendered}"), Some(LocationSemantics::SymbolStart) => format!(" symbol-start-source={rendered}"), None => format!(" unlabeled-source={rendered}"), } } fn copy_create_new(output: &Path, bytes: &[u8]) -> ultimate_tool_core::Result { let mut file = OpenOptions::new() .write(true) .create_new(true) .open(output) .map_err(|error| { Error::Evidence(format!( "cannot create evidence output {}: {error}", output.display() )) })?; file.write_all(bytes)?; file.sync_all()?; fs::canonicalize(output).map_err(Error::Io) } fn write_artifact_create_new(output: &Path, bytes: &[u8]) -> ultimate_tool_core::Result { let mut file = OpenOptions::new() .write(true) .create_new(true) .open(output) .map_err(|error| { Error::Artifact(format!( "cannot create UE2 output {}: {error}", output.display() )) })?; file.write_all(bytes).map_err(|error| { Error::Artifact(format!( "cannot write UE2 output {}: {error}", output.display() )) })?; file.sync_all().map_err(|error| { Error::Artifact(format!( "cannot sync UE2 output {}: {error}", output.display() )) })?; fs::canonicalize(output).map_err(|error| { Error::Artifact(format!( "cannot canonicalize UE2 output {}: {error}", output.display() )) }) } fn render_success(format: OutputFormat, command: &'static str, output: &ExecutionOutput) { match format { OutputFormat::Human => { for line in &output.human { println!("{line}"); } } OutputFormat::Json | OutputFormat::Jsonl => emit_machine(MachineEnvelope { schema_version: CLI_SCHEMA_VERSION, record_kind: "result", command, data: output.data.clone(), error: None, }), } } fn render_error(format: OutputFormat, command: &'static str, error: &Error) { match format { OutputFormat::Human => eprintln!("error: {error}"), OutputFormat::Json | OutputFormat::Jsonl => emit_machine(MachineEnvelope { schema_version: CLI_SCHEMA_VERSION, record_kind: "error", command, data: Value::Null, error: Some(MachineError { code: error.code(), layer: error.layer(), message: error.to_string(), exit_code: error.exit_code(), }), }), } } fn emit_machine(envelope: MachineEnvelope<'_>) { let stdout = io::stdout(); let mut lock = stdout.lock(); serde_json::to_writer(&mut lock, &envelope).expect("machine envelope serializes"); lock.write_all(b"\n").expect("stdout accepts envelope"); lock.flush().expect("stdout flushes envelope"); } #[cfg(test)] mod tests { use tempfile::tempdir; use super::*; #[test] fn evidence_copy_refuses_overwrite() { let root = tempdir().unwrap(); let output = root.path().join("evidence.bin"); fs::write(&output, b"existing").unwrap(); assert!(copy_create_new(&output, b"replacement").is_err()); assert_eq!(fs::read(output).unwrap(), b"existing"); } #[test] fn ue2_output_refuses_overwrite() { let root = tempdir().unwrap(); let output = root.path().join("native.ue2"); fs::write(&output, b"existing").unwrap(); assert!(write_artifact_create_new(&output, b"replacement").is_err()); assert_eq!(fs::read(output).unwrap(), b"existing"); } #[test] fn human_output_labels_exact_and_symbol_start_locations() { let mut resolved = ResolveMatch { rank: "containing".into(), context: "resident".into(), symbol: "crash".into(), raw_symbol: "crash".into(), aliases: Vec::new(), symbol_address: 0x1000, symbol_address_hex: "$1000".into(), symbol_size: 16, offset: 4, section: Some(".text".into()), object_file: None, kind: "text".into(), location: Some(ultimate_tool_core::analysis::SourceLocation { file: "src/main.rs".into(), line: Some(42), column: Some(7), }), location_semantics: Some(LocationSemantics::AddressCallsite), provenance: vec!["elf".into()], }; assert_eq!( human_source_location(&resolved), " callsite=src/main.rs:42:7" ); resolved.location_semantics = Some(LocationSemantics::SymbolStart); assert_eq!( human_source_location(&resolved), " symbol-start-source=src/main.rs:42:7" ); } }