The known-failed case: run-ca3-pc1-v4-eff-5090-20261007 as published at 18:27Z (--elevated) waited two minutes for a click and died with exit 251, the card switched off for nothing. The rights path is the installed app's Igneum Power Helper task (app/igneum-app/src/powertask.rs: Start-ScheduledTask by the owning user, the fixed verbs through its cmd.txt), which tools/ca3-v4-amend/pc1-v4-efficiency.ps1 uses; a job without the task reports the fact and takes its measured-only rows. Self-tests: a -Verb RunAs launch fails, a Power Helper task start passes, the publisher refuses --elevated (exit 3). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
78 lines
8.4 KiB
Bash
Executable file
78 lines
8.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# The standing rule of 5 October 2026, 23:05 UTC (CLAUDE.md): a job never quits, pauses, resumes or restarts the
|
|
# installed app it did not start. A test engine started by a job runs on its own data dir with its own URL file; a
|
|
# job may send quit, pause or resume only to an engine it started itself (the URL it created); the installed app is
|
|
# touched only through the signed `restart` and `update-now` job kinds. This check fails any playbook or script under
|
|
# relay/playbooks, tools/windows, tools/proving-v1 or packaging that reads the INSTALLED app's URL file
|
|
# (%LOCALAPPDATA%\igneum\app\app.url, $env:IGNEUM_APP_DIR\app.url, ~/Library/Application Support/Igneum/app/app.url)
|
|
# and sends api/quit, api/pause or api/resume. A scratch root's own app.url (igneum-tune-*, igneum-sweep) is fine.
|
|
# Rule 2 (6 October 2026, 18:xx UTC, main): a script never switches the installed app's cards either. A POST to
|
|
# /api/cards from a script is the same class as /api/pause from a script: the watts job run-ca3-pc1-amd-watts-20261006
|
|
# posted the 9070 XT off, the 0.3.14 update relaunched the app under it and killed the script mid-run, its finally never
|
|
# ran and the card stayed off until a hand POST. A job that needs a card alone asks the RUNNER for it (`publish-jobs.sh
|
|
# add --kind run --cards-off <key,key>`, app/igneum-app/src/jobrun.rs: switched before the script, restored on ANY exit).
|
|
# This check fails any script that sends a request to api/cards (any method, any enabled value: the restore half is a
|
|
# POST too). Reading /api/state stays fine. Rule 1's behaviour is master's, unchanged.
|
|
# bash tools/ci/playbook-quit-check.sh [--self-test]
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/../.."
|
|
check_file() {
|
|
local f="$1" bad=0
|
|
# rule 2: any request to api/cards outside a comment (Invoke-RestMethod, Invoke-WebRequest, curl, fetch: the shape is the URL)
|
|
if grep -vE '^\s*#' "$f" | grep -qE "api/cards"; then
|
|
echo "playbook-quit: $f sends a request to the installed app's api/cards (a script never switches cards; ask the runner: publish-jobs.sh add --kind run --cards-off <key,key>)"; bad=1
|
|
fi
|
|
# rule 3 (STANDING RULE, the project lead through main, 7 October 2026, 18:5x UTC): no PC job raises a UAC prompt or needs a click, ever.
|
|
# A script that launches anything with -Verb RunAs (or runas.exe) raises one; the rights path is the installed app's Igneum
|
|
# Power Helper task (Start-ScheduledTask by the owning user, commands through its cmd.txt: app/igneum-app/src/powertask.rs).
|
|
# publish-jobs.sh refuses --elevated for the same reason (the 18:27Z job run-ca3-pc1-v4-eff-5090-20261007: exit 251 after
|
|
# two minutes waiting for a click).
|
|
if grep -vE '^\s*#' "$f" | grep -qiE -e "(-Verb +['\"]?RunAs)|(\brunas(\.exe)? +/user)"; then
|
|
echo "playbook-quit: $f raises an administrator prompt (-Verb RunAs or runas): no PC job prompts; use the Igneum Power Helper task (app/igneum-app/src/powertask.rs)"; bad=1
|
|
fi
|
|
grep -qE "api/(quit|pause|resume)" "$f" || return $bad
|
|
if grep -vE '^\s*#' "$f" | grep -qE "igneum\\\\app\\\\app\.url|igneum/app/app\.url|Application Support/Igneum/app/app\.url|IGNEUM_APP_DIR[^\n]*app\.url|\\\$appDir[^\n]*'app\.url'"; then
|
|
echo "playbook-quit: $f reads the installed app's URL file and sends quit, pause or resume to it (a job may only quit an engine it started: its own scratch URL file)"; bad=1
|
|
fi
|
|
return $bad
|
|
}
|
|
if [ "${1:-}" = "--self-test" ]; then
|
|
t="$(mktemp -d)"
|
|
printf '%s\n' '$urlFile = Join-Path $env:LOCALAPPDATA '"'"'igneum\app\app.url'"'"'' 'Invoke-WebRequest -Uri ($url + '"'"'api/quit'"'"') -Method POST' > "$t/bad.ps1"
|
|
printf '%s\n' '$u = Join-Path $sApp '"'"'app.url'"'"' # $sApp = $root\app, $root = igneum-tune-<stamp>' 'Invoke-WebRequest -Uri ((Get-Content $u) + '"'"'api/quit'"'"')' > "$t/good.ps1"
|
|
printf '%s\n' '$body = @{ cards = @(@{ key = $k; enabled = $false; identities = 2 }) } | ConvertTo-Json' 'Invoke-RestMethod -Uri "$base/api/cards" -Method POST -Body $body' > "$t/cards.ps1"
|
|
printf '%s\n' '# the old shape posted enabled=False to api/cards; now the runner does it' '$st = Invoke-RestMethod -Uri "$base/api/state" -Method GET' > "$t/state.ps1"
|
|
if check_file "$t/bad.ps1" >/dev/null; then echo "self-test FAILED: the bad playbook passed"; exit 1; fi
|
|
if ! check_file "$t/good.ps1"; then echo "self-test FAILED: the good playbook failed"; exit 1; fi
|
|
if check_file "$t/cards.ps1" >/dev/null; then echo "self-test FAILED: the api/cards switch passed"; exit 1; fi
|
|
if ! check_file "$t/state.ps1"; then echo "self-test FAILED: a read of api/state (api/cards only in a comment) failed"; exit 1; fi
|
|
printf '%s\n' '$p = Start-Process powershell.exe -Verb RunAs -ArgumentList @("-File", $s) -Wait -PassThru' > "$t/runas.ps1"
|
|
printf '%s\n' '# the old shape ran Start-Process -Verb RunAs; now the Power Helper task carries the rights' 'Start-ScheduledTask -TaskName "Igneum Power Helper"' > "$t/helper.ps1"
|
|
if check_file "$t/runas.ps1" >/dev/null; then echo "self-test FAILED: the RunAs launch passed"; exit 1; fi
|
|
if ! check_file "$t/helper.ps1"; then echo "self-test FAILED: the Power Helper task start (RunAs only in a comment) failed"; exit 1; fi
|
|
if ! bash packaging/ota/publish-jobs.sh add --kind run --target ae432dc7 --id self-test-elevated --elevated --script "$t/helper.ps1" --title "self-test" --dest "$t/dest" >/dev/null 2>&1; then :; else echo "self-test FAILED: publish-jobs.sh accepted --elevated (the 18:27Z job as published)"; exit 1; fi
|
|
rm -rf "$t"; echo "self-test passed: the installed app's URL file with a quit fails, a scratch URL file passes, a request to api/cards fails, a read of api/state passes, a -Verb RunAs launch fails, a Power Helper task start passes, publish-jobs.sh refuses --elevated"; exit 0
|
|
fi
|
|
# allowed senders: the installer's own stop step (the update-now path the rule names), and, pending the rule owner's
|
|
# word (6 October 2026, 15:10 UTC): tools/proving-v1/pc2-agg-cost.ps1 and its restore step pc2-agg-cost-restore.ps1, which switch the 5090 off through /api/cards
|
|
# and falls back to /api/pause with /api/resume in its finally block (the aggregation-cost agent's measurement; the
|
|
# rule's letter forbids pause and resume of the installed app, its owner decides whether a card switch's fallback is one)
|
|
# rule 2's pre-rule playbooks (5 and 6 October 2026, before the rule at 18:xx UTC on the 6th), kept as the record of runs
|
|
# already made and never republished: the 5 October PC 1 benches (mixer-x4, readwidth, era, dot4, hot), the 6 October
|
|
# PC 2 family probe and derive job; and the two hand-restore scripts pc1-amd-identities.ps1 and pc1-amd-flag-amd1.ps1,
|
|
# allowed by the rule owner (6 October 2026, 19:xx UTC) because they post enabled TRUE only (a restore, never a switch off)
|
|
PRE_RULE='^(relay/playbooks/(mixer-x4-pc1-bench|mixer-x4-5090-bench|mixer-x4-9070-bench|readwidth-5090-bench|readwidth-5090|readwidth-9070-bench|readwidth-9070|ca2-era-pc1|ca2-hot-5090-bench|ca2-hot-9070-bench|dot4-probe|ca3-derive-pc2)\.ps1|tools/ca3-reserve/pc2-family-probe\.ps1|tools/ca3-pc1-amd/pc1-amd-identities\.ps1|tools/ca3-pc1-amd/pc1-amd-flag-amd1\.ps1)$'
|
|
# 6 October 2026 (0.3.14 gate): ember-tune-pc1.ps1 and the two agg-cost scripts are allowed pending the agg-cost --stop-miners change
|
|
# and the Ember playbook's rewrite (the coordinator's 15:30Z ruling); EXPIRES 0.3.15 (the check below fails the tree at 0.3.15 or later while they stand)
|
|
ALLOW='^(packaging/windows/stop-igneum\.ps1|relay/playbooks/ember-tune-pc1\.ps1|tools/proving-v1/pc2-agg-cost\.ps1|tools/proving-v1/pc2-agg-cost-restore\.ps1)$'
|
|
fail=0
|
|
while IFS= read -r f; do [[ "$f" =~ $ALLOW ]] && continue; [[ "$f" =~ $PRE_RULE ]] && continue; check_file "$f" || fail=1; done < <(git ls-files 'relay/playbooks/**' 'tools/**' 'packaging/**' | grep -E '\.(ps1|sh)$' | grep -v '^tools/ci/')
|
|
# expiry of the dated allow entries (6 October 2026): at 0.3.15 or later the three must be gone from ALLOW
|
|
ver="$(sed -n 's/^version = "\(.*\)"/\1/p' app/igneum-app/Cargo.toml 2>/dev/null | head -1)"
|
|
if [ -n "$ver" ] && [ "$(printf '%s\n0.3.15\n' "$ver" | sort -V | head -1)" = "0.3.15" ]; then
|
|
for e in relay/playbooks/ember-tune-pc1.ps1 tools/proving-v1/pc2-agg-cost.ps1 tools/proving-v1/pc2-agg-cost-restore.ps1; do
|
|
case "$ALLOW" in *"${e//./\\.}"*) echo "playbook-quit: the allow entry for $e expired at 0.3.15 (the tree says $ver): the pause/resume rule applies to it now"; fail=1 ;; esac
|
|
done
|
|
fi
|
|
[ "$fail" = 0 ] && echo "playbook-quit: no playbook quits, pauses, resumes or switches the cards of the installed app"
|
|
exit $fail
|