From e0de2ab18ea328927108ca421cfcd8e3312fe92c Mon Sep 17 00:00:00 2001 From: igneum-josh <337424239+igneum-josh@users.noreply.github.com> Date: Mon, 5 Oct 2026 23:22:44 +0100 Subject: [PATCH] App: every worker gets --prepare-packs in the platform's path form and runs with the app data folder as cwd (program class v3: the Metal worker compiles v3 only from a prepared pack; the Macs would have answered need lines at the first v3 epoch) cargo test --release -p igneum-app under the build lock: 113 + 27 + 8 passed, 0 failed (the prepare_packs_tests, resume_tests and provedefault tests among them). Co-Authored-By: Claude Fable 5.1 --- app/igneum-app/src/engine.rs | 43 ++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/app/igneum-app/src/engine.rs b/app/igneum-app/src/engine.rs index 84d356d5f..5278f089b 100644 --- a/app/igneum-app/src/engine.rs +++ b/app/igneum-app/src/engine.rs @@ -449,6 +449,12 @@ fn jitter_secs(seed: u64) -> u64 { 5 + (seed.wrapping_mul(2654435761) >> 7) % 56 } +/// The `--prepare-packs` directory the miner gets, relative to the app data folder (its cwd), in the platform's +/// separator: `packs\prepare` on Windows, `packs/prepare` elsewhere. Every worker gets it (program class v3). +pub(crate) fn prepare_packs_arg() -> String { + if cfg!(windows) { "packs\\prepare".to_string() } else { "packs/prepare".to_string() } +} + /// Seconds after a resume before every enabled card must be mining (a worker takes 10 to 60 s to its first STATUS /// line with a hash rate; the pack export before it a few seconds more). pub(crate) const RESUME_CHECK_SECS: u64 = 90; @@ -1464,13 +1470,16 @@ impl Engine { a.push("--network".into()); a.push(r.network.clone()); } + // The miner runs with the app data folder as its cwd: the pack paths stay relative (the miner splits + // --worker-args on spaces, and %LOCALAPPDATA% may carry a space in the user name). Every worker gets + // --prepare-packs (5 October 2026, program class v3: the Metal worker too compiles v3 only from a prepared + // pack, `prepare class=v3 era=`; before this the flag went to the CUDA and OpenCL + // workers only and a Mac would answer `need` lines at the first v3 epoch and stop mining, the 18:23Z class). + a.push("--prepare-packs".into()); + a.push(prepare_packs_arg()); if card.worker != "Metal" { - // The miner runs with the app data folder as its cwd: the pack paths stay relative (the miner splits - // --worker-args on spaces, and %LOCALAPPDATA% may carry a space in the user name). The prebuilt workers - // take the exported pack with --pack and build the next program from --prepare-packs; a worker built - // from source has the program compiled in and exits 42 at the boundary instead. - a.push("--prepare-packs".into()); - a.push("packs\\prepare".into()); + // The prebuilt workers take the exported pack with --pack and build the next program from + // --prepare-packs; a worker built from source has the program compiled in and exits 42 at the boundary. if card.worker == "OpenCL" { a.push("--job-nonces".into()); a.push("2097152".into()); @@ -1505,7 +1514,9 @@ impl Engine { self.miners[i].starts += 1; let seg = if self.miners[i].starts > 1 { format!("-r{}", self.miners[i].starts) } else { String::new() }; let log = self.shared.runtime.log_dir.join(format!("miner-{}-{}{seg}.log", self.miners[i].label, self.stamp)); - let cwd = if card.worker == "Metal" { None } else { Some(self.shared.runtime.app_dir.clone()) }; + // every worker runs with the app data folder as its cwd, so the relative pack paths resolve (the Metal worker + // too, since it takes --prepare-packs now) + let cwd = Some(self.shared.runtime.app_dir.clone()); self.miners[i].prepared = false; // the fleet's per-card kernel tuning (from the signed manifest) reaches the GPU worker through the miner's environment let envs: Vec<(String, String)> = self.ota.tuning_path().map(|p| vec![("IGNEUM_TUNING_FILE".to_string(), p.display().to_string())]).unwrap_or_default(); @@ -3447,6 +3458,24 @@ pub fn parse_race(body: &str) -> Option { Some(r) } +#[cfg(test)] +mod prepare_packs_tests { + use super::*; + + /// Program class v3 (5 October 2026): the Metal worker needs the prepare directory too, in the platform's + /// separator, relative to the app data folder the miner runs in. + #[test] + fn every_worker_gets_the_prepare_directory_in_the_platform_form() { + let arg = prepare_packs_arg(); + if cfg!(windows) { + assert_eq!(arg, "packs\\prepare"); + } else { + assert_eq!(arg, "packs/prepare", "the Mac's Metal worker gets a forward-slash path"); + } + assert!(!arg.contains(' ') && !arg.starts_with('/'), "relative, no space: the miner splits --worker-args on spaces and the data folder may carry one"); + } +} + #[cfg(test)] mod resume_tests { use super::*;