diff --git a/.github/workflows/pplns-parse-seedpin.yml b/.github/workflows/pplns-parse-seedpin.yml new file mode 100644 index 000000000..5030319a5 --- /dev/null +++ b/.github/workflows/pplns-parse-seedpin.yml @@ -0,0 +1,46 @@ +name: PPLNS parse seed-pin guard + +# Permanent regression guard for the PPLNS parse property suite. +# +# The random-seeded web-static job (build.yml) can pass even when a specific +# fast-check sequence still reproduces a bug, because it never replays that +# sequence. This job pins seed -1679627146 — the counterexample that found +# the non-finite legacy bare-number regression (input [Infinity] -> +# totalPrimary Infinity, fixed in PR #51) — so the exact failing path is +# re-exercised deterministically on every change to the parser or its tests. + +on: + push: + branches: [master] + paths: + - "web-static/sharechain-explorer/**" + - ".github/workflows/pplns-parse-seedpin.yml" + pull_request: + branches: [master] + paths: + - "web-static/sharechain-explorer/**" + - ".github/workflows/pplns-parse-seedpin.yml" + +jobs: + seedpin: + name: PPLNS parse seed-pin replay + runs-on: ubuntu-24.04 + defaults: + run: + working-directory: web-static/sharechain-explorer + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-node@v5 + with: + node-version: "22" + cache: npm + cache-dependency-path: web-static/sharechain-explorer/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Replay pinned seed -1679627146 against PPLNS parse property suite + run: | + node --import tsx --import ./.ci-seed-pin.mjs \ + --test "tests/unit/pplns-parse-properties.test.ts" diff --git a/web-static/sharechain-explorer/.ci-seed-pin.mjs b/web-static/sharechain-explorer/.ci-seed-pin.mjs new file mode 100644 index 000000000..81352119d --- /dev/null +++ b/web-static/sharechain-explorer/.ci-seed-pin.mjs @@ -0,0 +1,12 @@ +// CI-only fast-check seed pin for the PPLNS parse property suite. +// +// Replays seed -1679627146 — the counterexample that surfaced the +// non-finite legacy bare-number regression (shrunk input [Infinity], +// totalPrimary -> Infinity). Fixed in PR #51 (parseLegacyShape now routes +// the bare-number branch through num()); this preload makes that exact +// path part of permanent CI, so a random-seeded run can never again pass +// while the pinned sequence still fails. +// +// Loaded via: node --import ./.ci-seed-pin.mjs (see pplns-parse-seedpin.yml) +import fc from "fast-check"; +fc.configureGlobal({ ...fc.readConfigureGlobal(), seed: -1679627146 });