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 <noreply@anthropic.com>
This commit is contained in:
igneum-josh 2026-10-05 23:22:44 +01:00
parent 4173a0ef65
commit e0de2ab18e

View file

@ -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 <e> <d> <dir> class=v3 era=<hex>`; 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<RaceParsed> {
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::*;