diff --git a/relay/playbooks/ember-tune-pc1.ps1 b/relay/playbooks/ember-tune-pc1.ps1 index bb5c8eb90..a50b018f3 100644 --- a/relay/playbooks/ember-tune-pc1.ps1 +++ b/relay/playbooks/ember-tune-pc1.ps1 @@ -80,8 +80,17 @@ if (Test-Path $sj) { if ($j.PSObject.Properties.Name -contains 'power_control') { $j.power_control = $false } else { $j | Add-Member -NotePropertyName power_control -NotePropertyValue $false } # every card is due: the stored results are cleared in the COPY only if ($j.cards) { foreach ($p in $j.cards.PSObject.Properties) { $p.Value.sweep_at = 0; $p.Value.pinned = $false } } - $j | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $sj -Encoding utf8 + # PowerShell 5.1's Set-Content -Encoding utf8 writes a BOM, which the engine's JSON parser refuses: the copy then + # read as defaults (no payout address, no cards) and the miners never started (runs 1 and 2, 5 and 6 October 2026) + [IO.File]::WriteAllText($sj, ($j | ConvertTo-Json -Depth 8), (New-Object System.Text.UTF8Encoding $false)) } catch { Say ("settings.json: " + $_.Exception.Message) } + $back = $null + try { $back = Get-Content -LiteralPath $sj -Raw | ConvertFrom-Json } catch { } + $addr = ''; if ($back) { $addr = [string]$back.address } + $bom = (Get-Content -LiteralPath $sj -Encoding Byte -TotalCount 3 -ErrorAction SilentlyContinue) -join ',' + Write-Output ('RESULT TUNE scratch settings: address ' + $(if ($addr) { $addr.Substring(0, [Math]::Min(10, $addr.Length)) + '...' } else { 'EMPTY' }) + ', cards ' + $(if ($back -and $back.cards) { @($back.cards.PSObject.Properties).Count } else { 0 }) + ', first bytes ' + $bom) + if (-not $addr -and -not (Test-Path (Join-Path $sApp 'wallet.json'))) { Write-Output 'RESULT TUNE error=no_address reason=the_copied_settings_carry_no_payout_address_and_no_wallet.json'; exit 2 } + if ($bom -eq '239,187,191') { Write-Output 'RESULT TUNE error=bom reason=settings.json_starts_with_a_BOM'; exit 2 } } else { Write-Output 'RESULT TUNE error=no_settings reason=the_installed_app_has_no_settings.json'; exit 2 } Remove-Item -LiteralPath (Join-Path $sApp 'app.url') -Force -ErrorAction SilentlyContinue diff --git a/relay/playbooks/sweep-5090.ps1 b/relay/playbooks/sweep-5090.ps1 index 8b68f7d0d..29a9c7c02 100644 --- a/relay/playbooks/sweep-5090.ps1 +++ b/relay/playbooks/sweep-5090.ps1 @@ -43,7 +43,7 @@ if (Test-Path $sj) { try { $j = Get-Content -LiteralPath $sj -Raw | ConvertFrom-Json $j.remote_jobs = $false; $j.auto_update = $false; $j.prove = $false; $j.paused = $false; $j.setup_done = $true - $j | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $sj -Encoding utf8 + [IO.File]::WriteAllText($sj, ($j | ConvertTo-Json -Depth 8), (New-Object System.Text.UTF8Encoding $false)) # no BOM: the engine's JSON parser refuses one (C35, runs 1 and 2) } catch { Say ("settings.json: " + $_.Exception.Message) } } else { Write-Output 'RESULT SWEEP error=no_settings reason=the_installed_app_has_no_settings.json'; exit 2 } Remove-Item -LiteralPath (Join-Path $sApp 'app.url') -Force -ErrorAction SilentlyContinue diff --git a/tools/ci/second-engine-check.sh b/tools/ci/second-engine-check.sh index e5a42e318..da127dd0a 100755 --- a/tools/ci/second-engine-check.sh +++ b/tools/ci/second-engine-check.sh @@ -20,6 +20,9 @@ while IFS= read -r f; do if ! grep -qE 'taskkill /T /F' "$f"; then echo "second-engine: $f starts an engine without ending its process tree (taskkill /T /F) at the end"; fail=1 fi + if grep -qE 'settings\.json|\.json' "$f" && grep -vE '^\s*#' "$f" | grep -qE 'Set-Content[^\n]*-Encoding +utf8'; then + echo "second-engine: $f writes JSON with Set-Content -Encoding utf8 (a BOM the engine refuses: the copy read as defaults, no payout address, nothing mined); use [IO.File]::WriteAllText with UTF8Encoding(\$false)"; fail=1 + fi if ! grep -qE "IGNEUM_APP_NO_OTA *= *'1'" "$f"; then echo "second-engine: $f starts an engine without IGNEUM_APP_NO_OTA = '1' (its updater would run the installer, which quits the installed app: PC 1, 5 October 2026, 22:31 UTC)"; fail=1 fi