diff --git a/app/igneum-app/src/engine.rs b/app/igneum-app/src/engine.rs index 012778395..834631f31 100644 --- a/app/igneum-app/src/engine.rs +++ b/app/igneum-app/src/engine.rs @@ -1818,7 +1818,8 @@ impl Engine { let dir = self.sweep_dir(); let _ = std::fs::create_dir_all(&dir); let script = dir.join("register-power-task.ps1"); - match std::env::current_exe().map(|exe| std::fs::write(&script, [b"\xEF\xBB\xBF".as_slice(), crate::powertask::register_script(&exe).as_bytes()].concat())) { + let installed: Vec = [std::env::var_os("LOCALAPPDATA").map(|l| PathBuf::from(l).join("Programs").join("Igneum Miner").join("igneum-app.exe")), std::env::var_os("ProgramFiles").map(|p| PathBuf::from(p).join("Igneum Miner").join("igneum-app.exe"))].into_iter().flatten().collect(); + match std::env::current_exe().map(|exe| std::fs::write(&script, [b"\xEF\xBB\xBF".as_slice(), crate::powertask::register_script(&crate::powertask::task_exe(&exe, &installed)).as_bytes()].concat())) { Ok(Ok(())) => format!("{} & \"{}\" -NoProfile -ExecutionPolicy Bypass -File \"{}\"", cmds.join(" & "), crate::platform::tool("powershell").display(), script.display()), _ => cmds.join(" & "), } diff --git a/app/igneum-app/src/powertask.rs b/app/igneum-app/src/powertask.rs index 1a4ab9fe8..787142f38 100644 --- a/app/igneum-app/src/powertask.rs +++ b/app/igneum-app/src/powertask.rs @@ -80,6 +80,20 @@ pub fn smi_args(dev: &str, c: &HelperCmd) -> Option> { } } +/// The executable the task should point at: the running one, unless it runs out of a jobs folder (a measurement +/// kit a job fetched: `\app\jobs\\igneum-app-ember.exe`), in which case the installed app's own +/// exe beside it is the durable target (6 October 2026: the first registration on PC 1 came from such a kit). +pub fn task_exe(running: &Path, install_candidates: &[PathBuf]) -> PathBuf { + // either separator: the path comes from Windows, the tests run on the Mac too + let under_jobs = running.to_string_lossy().split(['\\', '/']).any(|c| c.eq_ignore_ascii_case("jobs")); + if under_jobs { + if let Some(p) = install_candidates.iter().find(|p| p.is_file()) { + return p.clone(); + } + } + running.to_path_buf() +} + /// The PowerShell that registers the task (run inside the ONE elevated step, with the caps). `exe` is this /// executable's path in the install folder. Principal: the signed-in user, interactive logon, highest run level; no /// trigger; may start on battery; one hour limit per run; multiple starts are ignored while one runs. @@ -253,6 +267,20 @@ mod tests { assert!(query_command().contains("Get-ScheduledTask -TaskName 'Igneum Power Helper'")); } + #[test] + fn a_kit_run_from_a_jobs_folder_registers_the_installed_exe() { + let kit = Path::new(r"C:\Users\Admin\AppData\Local\igneum\app\jobs\ember-kit-5\igneum-app-ember.exe"); + let own = Path::new(r"C:\Users\Admin\AppData\Local\Programs\Igneum Miner\igneum-app.exe"); + // no installed candidate exists on this machine: the running exe stands + assert_eq!(task_exe(kit, &[PathBuf::from(r"C:\nonexistent\igneum-app.exe")]), kit.to_path_buf()); + assert_eq!(task_exe(own, &[]), own.to_path_buf()); + // an installed candidate that exists (the test binary stands in for it) wins for a kit, not for the installed exe + let here = std::env::current_exe().unwrap(); + assert!(here.is_file()); + assert_eq!(task_exe(kit, &[here.clone()]), here); + assert_eq!(task_exe(own, &[here]), own.to_path_buf()); + } + #[test] fn a_stale_command_file_does_not_run_at_start() { // the helper's start reads the highest sequence already in the file and runs nothing below or at it diff --git a/relay/playbooks/ember-tune-pc1.ps1 b/relay/playbooks/ember-tune-pc1.ps1 index 6baae9042..aa9bc361e 100644 --- a/relay/playbooks/ember-tune-pc1.ps1 +++ b/relay/playbooks/ember-tune-pc1.ps1 @@ -47,11 +47,10 @@ $installedVer = (& (Join-Path $installDir 'igneum-app.exe') --version 2>&1 | Out $installedHasEmber = $false if ($installedVer -match 'igneum-app (\d+)\.(\d+)\.(\d+)') { $installedHasEmber = ([int]$Matches[1] -gt 0) -or ([int]$Matches[2] -gt 3) -or (([int]$Matches[2] -eq 3) -and ([int]$Matches[3] -ge 12)) } $ember = $null -# ember-kit-3 (the engine with Settings::for_measurement) is preferred when present, whatever the installed version; -# older kits only when the installed app predates Ember Tune -$k3 = Join-Path $appDir 'jobs\ember-kit-5\igneum-app-ember.exe' -if (Test-Path $k3) { $ember = $k3 } -elseif (-not $installedHasEmber) { foreach ($cand in @((Join-Path $appDir 'jobs\ember-kit-2\igneum-app-ember.exe'), (Join-Path $appDir 'jobs\ember-kit-1\igneum-app-ember.exe'))) { if (Test-Path $cand) { $ember = $cand; break } } } +# a kit is used only when the installed app predates Ember Tune (0.3.13); from 0.3.13 on the installed engine is the +# tune engine, so the Power Helper task it registers points at the install folder (the 15:28Z run on PC 1 registered +# the kit's path because kit-5 was still preferred) +if (-not $installedHasEmber) { foreach ($cand in @((Join-Path $appDir 'jobs\ember-kit-2\igneum-app-ember.exe'), (Join-Path $appDir 'jobs\ember-kit-1\igneum-app-ember.exe'))) { if (Test-Path $cand) { $ember = $cand; break } } } if ($ember) { Copy-Item -LiteralPath $ember -Destination (Join-Path $bin 'igneum-app.exe') -Force Say ("engine: the Ember build from " + $ember)