From 01719bdff051e2b018e9de6206a062988f5f7ecc Mon Sep 17 00:00:00 2001 From: KooshaPari Date: Sat, 22 Aug 2026 18:25:39 -0700 Subject: [PATCH 1/5] fix(ci): propagate scorecard execution failures --- .github/workflows/scorecard-ci.yml | 15 +++++++++++++-- scripts/miri-permutation-check.ps1 | 20 ++++++++++---------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/.github/workflows/scorecard-ci.yml b/.github/workflows/scorecard-ci.yml index 9a4528f7..8871d32a 100644 --- a/.github/workflows/scorecard-ci.yml +++ b/.github/workflows/scorecard-ci.yml @@ -33,8 +33,19 @@ jobs: ENFORCE=false fi - # Run audit in JSON mode - if ! python scripts/scorecard_ci.py . --output json --threshold "$THRESHOLD" --fail-on-drop > scorecard-report.json 2> scorecard-stderr.txt; then + # Run audit in JSON mode. Exit 1 means an advisory threshold drop; + # any other exit code is an execution/contract failure and must stop + # before attempting to parse a possibly empty report. + set +e + python scripts/scorecard_ci.py . --output json --threshold "$THRESHOLD" --fail-on-drop > scorecard-report.json 2> scorecard-stderr.txt + AUDIT_STATUS=$? + set -e + if [ "$AUDIT_STATUS" -ne 0 ] && [ "$AUDIT_STATUS" -ne 1 ]; then + echo "Scorecard audit failed with exit code $AUDIT_STATUS." >&2 + cat scorecard-stderr.txt >&2 + exit "$AUDIT_STATUS" + fi + if [ "$AUDIT_STATUS" -eq 1 ]; then echo "Scorecard is below the canonical-main threshold; continuing to publish the report." fi diff --git a/scripts/miri-permutation-check.ps1 b/scripts/miri-permutation-check.ps1 index c1d33334..57338011 100644 --- a/scripts/miri-permutation-check.ps1 +++ b/scripts/miri-permutation-check.ps1 @@ -49,14 +49,14 @@ function Write-Check { return $Ok } -function Test-DocContains { +function Test-DocContent { param( [Parameter(Mandatory = $true)][string]$Doc, [Parameter(Mandatory = $true)][string]$Needle, [Parameter(Mandatory = $true)][string]$Label, [string]$Context = "docs/ops/concurrency-safety.md" ) - $ok = $Doc.Contains($Needle) + $ok = $Doc.Contains($Needle) [void](Write-Check -Label $Label -Ok $ok) if (-not $ok) { throw "$Context missing required anchor: '$Needle'" @@ -96,21 +96,21 @@ $raceModel = Get-Content -LiteralPath $raceModelPath -Raw $cargoToml = Get-Content -LiteralPath $cargoTomlPath -Raw Write-Host "Concurrency safety doc anchors (done vs unpaid):" -Test-DocContains -Doc $doc -Needle "Miri permutation checkers" ` +Test-DocContent -Doc $doc -Needle "Miri permutation checkers" ` -Label "miri permutation section heading" -Test-DocContains -Doc $doc -Needle "scripts/miri-permutation-check.ps1" ` +Test-DocContent -Doc $doc -Needle "scripts/miri-permutation-check.ps1" ` -Label "permutation SelfCheck script reference" -Test-DocPattern -Doc $doc -Pattern "Miri permutation SelfCheck\s+\|\s+\*\*done\*\*" ` +Test-DocPattern -Doc $doc -Pattern "(?m)^\| Miri permutation SelfCheck\s+\|\s+\*\*done\*\*\s+\|" ` -Label "permutation SelfCheck gate marked done" -Test-DocPattern -Doc $doc -Pattern "Miri permutation race_model CI\s+\|\s+\*\*done\*\*" ` +Test-DocPattern -Doc $doc -Pattern "(?m)^\| Miri permutation race_model CI\s+\|\s+\*\*done\*\*\s+\|" ` -Label "permutation race_model CI gate marked done" -Test-DocContains -Doc $doc -Needle "miri-permutation.yml" ` +Test-DocContent -Doc $doc -Needle "miri-permutation.yml" ` -Label "miri-permutation workflow reference" -Test-DocContains -Doc $doc -Needle "miri-smoke.yml" ` +Test-DocContent -Doc $doc -Needle "miri-smoke.yml" ` -Label "miri-smoke soft workflow reference retained" -Test-DocPattern -Doc $doc -Pattern "loom_model under Miri\s+\|\s+\*\*unpaid\*\*" ` +Test-DocPattern -Doc $doc -Pattern "(?m)^\| loom_model under Miri\s+\|\s+\*\*unpaid\*\*\s+\|" ` -Label "loom_model under Miri unpaid gate" -Test-DocContains -Doc $doc -Needle "Full loom / shuttle permutation checkers | **unpaid**" ` +Test-DocContent -Doc $doc -Needle "Full loom / shuttle permutation checkers | **unpaid**" ` -Label "shared loom/shuttle unpaid gate retained" Write-Host "Workflow blocking-gate anchors:" From 90d043d59a3d8ac00a22be6273268b8fde9e8450 Mon Sep 17 00:00:00 2001 From: KooshaPari Date: Sat, 22 Aug 2026 20:40:38 -0700 Subject: [PATCH 2/5] fix(viewer): make theme fixture and toggle deterministic --- crates/sl-viewer/src/app.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/crates/sl-viewer/src/app.rs b/crates/sl-viewer/src/app.rs index b96b89ce..52fbe817 100644 --- a/crates/sl-viewer/src/app.rs +++ b/crates/sl-viewer/src/app.rs @@ -351,8 +351,7 @@ fn icon_svg(tab_icon: &str) -> &'static str { pub fn App() -> Element { #[cfg(feature = "web")] use_effect(|| { - let force_light = query_fixture_active("launch-splash-light"); - let script = if force_light { + let script = if query_fixture_active("launch-splash-light") { r#" document.documentElement.lang = 'en'; document.documentElement.dataset.theme = 'light'; @@ -361,6 +360,12 @@ pub fn App() -> Element { } else { r#" document.documentElement.lang = 'en'; + const fixture = new URLSearchParams(window.location.search).get('fixture'); + if (fixture === 'launch-splash-light') { + document.documentElement.dataset.theme = 'light'; + window.localStorage.setItem('sl-viewer-theme', 'light'); + return; + } const stored = window.localStorage.getItem('sl-viewer-theme'); const prefersLight = window.matchMedia?.('(prefers-color-scheme: light)').matches; const theme = stored === 'light' || stored === 'dark' @@ -521,7 +526,9 @@ pub fn App() -> Element { let _ = document::eval(&format!( r#" (function() {{ - const desired = {theme_attr:?}; + const desired = new URLSearchParams(window.location.search).get('fixture') === 'launch-splash-light' + ? 'light' + : {theme_attr:?}; if (desired === 'system') {{ const prefersLight = window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches; @@ -1294,6 +1301,14 @@ pub fn App() -> Element { Theme::Dark | Theme::System => Theme::Light, }; }); + let resolved = match settings_signal().theme { + Theme::Light => "light", + Theme::Dark => "dark", + Theme::System => "dark", + }; + let _ = document::eval(&format!( + "document.documentElement.dataset.theme = '{resolved}'; window.localStorage.setItem('sl-viewer-theme', '{resolved}');" + )); }, "Theme" } From 17bfd3fb3b829cbdc449662ff498d4d3929d169a Mon Sep 17 00:00:00 2001 From: KooshaPari Date: Sat, 22 Aug 2026 20:47:14 -0700 Subject: [PATCH 3/5] fix(ci): use valid scorecard job permissions --- .github/workflows/scorecard.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 722e841f..b6cf4899 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -20,8 +20,6 @@ jobs: analysis: name: Scorecard analysis runs-on: ubuntu-latest - security: - permissions: read-all steps: - name: Checkout From 8c7c11a7b2538fbdd807ee66234ebff1671ff814 Mon Sep 17 00:00:00 2001 From: KooshaPari Date: Sun, 23 Aug 2026 02:59:35 -0700 Subject: [PATCH 4/5] fix(viewer): persist the computed next theme --- crates/sl-viewer/src/app.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/sl-viewer/src/app.rs b/crates/sl-viewer/src/app.rs index 52fbe817..7d48f993 100644 --- a/crates/sl-viewer/src/app.rs +++ b/crates/sl-viewer/src/app.rs @@ -1295,13 +1295,14 @@ pub fn App() -> Element { r#type: "button", "aria-label": "Toggle light and dark theme", onclick: move |_| { + let next_theme = match settings_signal().theme { + Theme::Light => Theme::Dark, + Theme::Dark | Theme::System => Theme::Light, + }; settings_signal.with_mut(|settings| { - settings.theme = match settings.theme { - Theme::Light => Theme::Dark, - Theme::Dark | Theme::System => Theme::Light, - }; + settings.theme = next_theme; }); - let resolved = match settings_signal().theme { + let resolved = match next_theme { Theme::Light => "light", Theme::Dark => "dark", Theme::System => "dark", From 6d5a9261b97c6c7d6bf646921ff0e32b193b9d47 Mon Sep 17 00:00:00 2001 From: KooshaPari Date: Tue, 25 Aug 2026 00:19:38 -0700 Subject: [PATCH 5/5] fix(review): remove dead theme branch and enforce case matching --- crates/sl-viewer/src/app.rs | 6 ------ scripts/miri-permutation-check.ps1 | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/sl-viewer/src/app.rs b/crates/sl-viewer/src/app.rs index 7d48f993..41ebdcfb 100644 --- a/crates/sl-viewer/src/app.rs +++ b/crates/sl-viewer/src/app.rs @@ -360,12 +360,6 @@ pub fn App() -> Element { } else { r#" document.documentElement.lang = 'en'; - const fixture = new URLSearchParams(window.location.search).get('fixture'); - if (fixture === 'launch-splash-light') { - document.documentElement.dataset.theme = 'light'; - window.localStorage.setItem('sl-viewer-theme', 'light'); - return; - } const stored = window.localStorage.getItem('sl-viewer-theme'); const prefersLight = window.matchMedia?.('(prefers-color-scheme: light)').matches; const theme = stored === 'light' || stored === 'dark' diff --git a/scripts/miri-permutation-check.ps1 b/scripts/miri-permutation-check.ps1 index 57338011..b4373269 100644 --- a/scripts/miri-permutation-check.ps1 +++ b/scripts/miri-permutation-check.ps1 @@ -70,7 +70,7 @@ function Test-DocPattern { [Parameter(Mandatory = $true)][string]$Label, [string]$Context = "docs/ops/concurrency-safety.md" ) - $ok = $Doc -match $Pattern + $ok = $Doc -cmatch $Pattern [void](Write-Check -Label $Label -Ok $ok) if (-not $ok) { throw "$Context missing required pattern: '$Pattern'"