🩹 QuizWizz settings remediation — canonical handoff

Do not use as a patch source

This 2026-07-28 patch no longer applies to live source; current status is in Program Masterplan. Current handoff: 2026-08-27 canonical handoff.

Provenance

Authored and verified on the wrdp bench, which is not the canonical QuizWizz repository (SOURCE-PROVENANCE.md: releaseEligible: false). Apply quizwizz-settings-remediation.patch to the canonical checkout and rebuild through the locked signed pipeline (BUILDING.md). Never --reject, force-apply, or infer provenance.

Patch

  • file: q5vault/audits/qwizz/quizwizz-settings-remediation.patch
  • sha256: 5767cf8a2e86ad275873c6dc4020f465d8526624bb9dcc3124833ed0910d4d79
  • format: git diff --no-index --binary --no-prefix a b (apply with git apply -p1)
  • scope: exactly seven modifications, no additions/deletions/renames/mode changes
PathFix
includes/Admin/SettingsPage.phpunsavedOne/unsavedMany via _n() singular/plural pair + translator comment
includes/Admin/views/settings-page.phpdelay input renders exact persisted value; min/max from ExposureSettings constants
assets/js/qwizz-admin-settings.jsunsavedCopy(count) formatter; apiFetch normalization; degraded-mode read-only lockdown (capture-cancel + native disable + model guards); idempotent applyHashTarget() with hashchange listener
includes/Admin/DashboardPage.phpstatus_row() helper; Interface/Theme/Quiz sources static without manage_options
assets/css/qwizz-admin-dashboard.css.qwizz-status-list__static parity styling
includes/Admin/ImportPage.php”Data settings” button gated on manage_options; complete six-row redirect destination table to qw-import
includes/Admin/StarterPage.php”Open settings” gated on manage_options

Canonical apply procedure

  1. git switch -c fix/qw-settings-remediation
  2. git apply -p1 --check quizwizz-settings-remediation.patch — a failed check means port the same contracts onto current canonical source and re-run all checks; never --reject.
  3. git apply -p1 quizwizz-settings-remediation.patch
  4. Run canonical checks and the locked localization pipeline (regenerates POT/MO/JSON catalogs — the new _n() singular msgid %d unsaved change is required for German).
  5. Stage the seven source paths plus only pipeline-generated canonical artifacts.
  6. Commit: Fix QuizWizz settings resilience and admin routing.

Bench verification evidence (2026-07-28)

  • scripts/quizwizz-probe.sh --wave 2: 34/34 PHP assertions + 3/3; --wave all: 30/30, 0 failures.
  • Live php -l clean on all five PHP files; node --check clean on the JS; plugin active.
  • Admin matrix: Dashboard settings rows are links; Import shows “Data settings”; Get Started shows “Open settings”.
  • Editor matrix (role caps edit_qw_quizzes + publish_qw_questions, no manage_options): three settings rows static with values intact, no settings anchors anywhere; direct qw-settings access 403.
  • Delay fidelity: UI save 1800 → reload renders input and localized payload 1800; boundaries 1500 and 2499 render exactly; manual 0 stays 0 in storage, control hidden, seed 2500; min/max sourced from PHP constants.
  • Dirty copy: one diff → “1 unsaved change”; two diffs → “2 unsaved changes”; discard → “All changes saved”; unsavedOne/unsavedMany payload keys present, legacy unsaved key removed.
  • Degraded runtime (api-fetch aborted, cache disabled): inline error notice, 121/121 mutation controls natively disabled, drop zone aria-disabled, zero settings/media requests under forced synthetic events, savebar stays hidden, no beforeunload prompt (defaultPrevented: false); tabs, search, preview, export, backup forms, support link remain operable.
  • Fragments: fresh #qw-theme load activates Appearance; same-document #qw-interface-language activates General and focuses the control; unknown and malformed (#%E0%A4%A) hashes are stable no-ops; 390px viewport scrolls target into view (scroll-margin honored) with no horizontal overflow.
  • Redirect routing (reflection probe, admin context): settings_pack → qw-import#qw-question-pack-import; settings_opentdb → qw-import#qw-opentdb-import; import_page_pack → qw-import#qw-question-pack-import; import_page/unknown/missing → unfragmented qw-import.
  • debug.log delta: only benign WP auto-update lines.
  • Round-trip: git apply -p1 onto pristine baseline reproduces the verified tree byte-for-byte; patch headers parsed — seven allowlisted paths only.

Blocked on bench (canonical release gate)

  • German plural proof: the locked quizwizz-de_DE.mo predates the new singular msgid %d unsaved change (grep count 0). Bench proof covers English singular/plural and payload structure only. The canonical pipeline must regenerate catalogs and re-verify both counts in a cache-disabled German browser session — no mixed-language fallback.

Cleanup performed

  • qw_exposure_settings restored byte-exact from pre-scenario snapshot (OPTION-RESTORED-EXACT).
  • Temporary editor user (ID 41) deleted; probe files removed; no test uploads, drafts, or backups left behind (attachment inventory pre-dates the session; settings backups count 0).