Legacy WXR import 2026-08-19
Historical record — 2026-08-19
Preserved as observed. Current truth: Program Masterplan.
Headline, all measured on the bench
The legacy export
quizwizz.WordPress.2026-08-19.xml(21,593,668 bytes, sha25690acf85ac2389990923af739ab056ec116ffb7a4503c40e2c80a158392d1e806, 8,401<item>nodes) was mined purely as a data source — never fed to WordPress’ WXR importer. 8,379 cleaneden+dequestions survived extraction, 42 were already live by stem hash, and the remaining 8,337 imported throughQuizWizz\Import\QuestionPackImporter::import_json()in 84 packs with 0 row rejections at import time. Published questions 732 → 9,069, read index 732 → 9,069 (drift 0). Probe after the run:1..46,assertions=46 failures=0.
Source identity
| Property | Value |
|---|---|
| File | quizwizz.WordPress.2026-08-19.xml (bench .usr/, copied local, hashes identical) |
| Size / sha256 | 21,593,668 bytes / 90acf85a…e806 |
| Items | 8,401 — all wp:post_type=qw_question, all wp:status=publish |
| Provenance | OpenTDB export (qw_source=OpenTDB on 8,392 rows), en 4,196 / de 4,196 / no lang 9 |
Meta-key mapping
Trivial: the legacy keys are already the plugin’s own. qw_choices 8,398 (PHP-serialized array, parsed by byte length), qw_correct_idx 8,398, qw_type 8,392 (multiple 7,192 / boolean 1,200), qw_lang 8,392, qw_opentdb_id 8,392, qw_explanation 7, stem in content:encoded, subjects as qw_subject nicenames (22 slugs, all already live terms), difficulty as qw_difficulty (medium→normal).
Cleaning rules
- Single
html.unescape()— the file contains 0&amp;double-encodings (measured). - Strip tags (
<[^>]+>) and shortcodes (\x5b[^\x5d]+\x5d), collapse whitespace. - Comparison signs before digits rewritten per language (
<1%→less than 1%/unter 1%): WP’sQuestionValidatormaps choices throughwp_strip_all_tags(), and PHPstrip_tags()deletes everything after an unclosed<— the untouched choice imports as empty and fails the pack. Found on exactly 2 rows (en+de of the same Timur question);&&&&&&choices survive unharmed. - Choice distinctness checked NFKC + casefold + whitespace-collapse;
correct_idxinteger-in-range; stem ≤2000, choice ≤1000, explanation ≤4000.
Extraction census
Accepted en 4,191 + de 4,188, rejected 22; 4,191 + 4,188 + 22 = 8,401 exactly. Types multiple 7,181 / boolean 1,198; difficulty easy 2,777 / normal 3,834 / hard 1,768; explanations all empty (the 7 legacy qw_explanation values sat on rejected test artifacts or cleaned to empty).
Rejection ledger (named reasons, full detail in rejections.json)
| Reason | Rows |
|---|---|
| within-corpus duplicate stem (first occurrence kept) | 11 |
missing qw_lang/qw_type (test artifact) | 6 |
missing qw_choices (test artifact) | 3 |
| fewer than 2 / more than 8 / empty choices | 2 |
Accepted rows per subject
| Subject | Rows |
|---|---|
animals | 100 |
art | 98 |
celebrities | 100 |
entertainment-board-games | 100 |
entertainment-books | 200 |
entertainment-cartoon-animations | 200 |
entertainment-comics | 100 |
entertainment-film | 600 |
entertainment-japanese-anime-manga | 400 |
entertainment-music | 900 |
entertainment-television | 300 |
entertainment-video-games | 1398 |
general-knowledge | 899 |
geography | 695 |
history | 797 |
mythology | 100 |
politics | 100 |
science-computers | 298 |
science-mathematics | 96 |
science-nature | 498 |
sports | 300 |
vehicles | 100 |
Dedupe against live
Fresh post_content dump of the live 732 published questions; stem-hash (extract_overlap.py normalization, verbatim) dedupe dropped 42 rows (en 41 / de 1) as already live — the 40 live OpenTDB rows plus two hand-curated overlaps. 80 informational qw_opentdb_id collisions (the 40 live ids × en+de) — dedupe is by stem hash, never by opentdb id.
Import
84 packs (legacy-en-001…042, legacy-de-001…042), one language per pack, ≤100 questions, emitted with exactly the 7 allowed question keys and preflighted independently (OK 84 packs, 8337 questions, 0 violations) before any transfer. Each pack imported via wp_set_current_user(admin) + import_json(); every pack logged inserted == questions, skipped 0; Σ inserted = 8,337. Each import created one draft quiz — the 84 drafts are retained as import receipts (consistent with prior runs; a one-line sweep can delete them later if they clutter the admin).
Two run incidents, both recovered without data damage: the loop’s log file was unwritable from inside the CLI container, crashing the runner after a pack had fully imported (twice); resume detection was moved from the log file to the draft-quiz receipts in the database, and no pack was double-imported (0 duplicate Legacy OpenTDB titles measured).
Per-pack results
| Pack | Lang | Questions | Subject rows | Draft quiz | Inserted | Skipped | sha256 (12) |
|---|---|---|---|---|---|---|---|
legacy-en-001.json | en | 100 | 1 | 6688 | 100 | 0 | 7fc06065d4a0 |
legacy-en-002.json | en | 100 | 1 | 6789 | 100 | 0 | ea7675728cdf |
legacy-en-003.json | en | 100 | 1 | 6890 | 100 | 0 | 3f5660bdd8ca |
legacy-en-004.json | en | 100 | 1 | 6991 | 100 | 0 | d355e6ac8ae3 |
legacy-en-005.json | en | 100 | 3 | 7092 | 100 | 0 | 4371ea715105 |
legacy-en-006.json | en | 100 | 3 | 7193 | 100 | 0 | 1e00bfcd5c80 |
legacy-en-007.json | en | 100 | 2 | 7294 | 100 | 0 | 91c04414a548 |
legacy-en-008.json | en | 100 | 2 | 7395 | 100 | 0 | 90aeaf078dbb |
legacy-en-009.json | en | 100 | 3 | 7496 | 100 | 0 | 3d33733476ae |
legacy-en-010.json | en | 100 | 2 | 7597 | 100 | 0 | 9842dfb3035d |
legacy-en-011.json | en | 100 | 2 | 7698 | 100 | 0 | 2062d5413b1f |
legacy-en-012.json | en | 100 | 2 | 7799 | 100 | 0 | 21222172fdd2 |
legacy-en-013.json | en | 100 | 3 | 7900 | 100 | 0 | 26cb37f3b6bd |
legacy-en-014.json | en | 100 | 2 | 8001 | 100 | 0 | f94fa7a1002d |
legacy-en-015.json | en | 100 | 3 | 8102 | 100 | 0 | c7e85fe943de |
legacy-en-016.json | en | 100 | 2 | 8203 | 100 | 0 | 799d88d5d1d1 |
legacy-en-017.json | en | 100 | 2 | 8304 | 100 | 0 | 9eb43496a010 |
legacy-en-018.json | en | 100 | 2 | 8405 | 100 | 0 | 143f88c46b2b |
legacy-en-019.json | en | 100 | 2 | 8506 | 100 | 0 | 1904a1f63ed3 |
legacy-en-020.json | en | 100 | 2 | 8607 | 100 | 0 | c1eb19a193c5 |
legacy-en-021.json | en | 100 | 2 | 8708 | 100 | 0 | 21c897a529cc |
legacy-en-022.json | en | 100 | 5 | 8809 | 100 | 0 | 6687dc6147d1 |
legacy-en-023.json | en | 100 | 2 | 8910 | 100 | 0 | daf4381a40b3 |
legacy-en-024.json | en | 100 | 2 | 9011 | 100 | 0 | fa85d57c782c |
legacy-en-025.json | en | 100 | 3 | 9112 | 100 | 0 | 12593b866278 |
legacy-en-026.json | en | 100 | 3 | 9213 | 100 | 0 | 3beac7d5b068 |
legacy-en-027.json | en | 100 | 4 | 9314 | 100 | 0 | 30cf82bbf442 |
legacy-en-028.json | en | 100 | 1 | 9415 | 100 | 0 | 8d7c53daf736 |
legacy-en-029.json | en | 100 | 2 | 9516 | 100 | 0 | 94b9724ae702 |
legacy-en-030.json | en | 100 | 1 | 9617 | 100 | 0 | 65bbb1ef4298 |
legacy-en-031.json | en | 100 | 1 | 9718 | 100 | 0 | 6cdaac322754 |
legacy-en-032.json | en | 100 | 2 | 9819 | 100 | 0 | 1cb7d06b94f8 |
legacy-en-033.json | en | 100 | 1 | 9920 | 100 | 0 | aea50ff58206 |
legacy-en-034.json | en | 100 | 1 | 10021 | 100 | 0 | f2e27c4f41ad |
legacy-en-035.json | en | 100 | 1 | 10122 | 100 | 0 | d36a46a55ac5 |
legacy-en-036.json | en | 100 | 2 | 10223 | 100 | 0 | 136a6e16fa96 |
legacy-en-037.json | en | 100 | 3 | 10324 | 100 | 0 | 227d5fc362cd |
legacy-en-038.json | en | 100 | 2 | 10425 | 100 | 0 | a7d70a558aaa |
legacy-en-039.json | en | 100 | 3 | 10526 | 100 | 0 | d70c73e268e8 |
legacy-en-040.json | en | 100 | 2 | 10627 | 100 | 0 | e2ab9c3f8ad3 |
legacy-en-041.json | en | 100 | 3 | 10728 | 100 | 0 | 19266c2aae60 |
legacy-en-042.json | en | 50 | 2 | 10779 | 50 | 0 | 7b23d971a8c6 |
legacy-de-001.json | de | 100 | 1 | 2459 | 100 | 0 | af80ead4955b |
legacy-de-002.json | de | 100 | 1 | 2560 | 100 | 0 | a6a966378c46 |
legacy-de-003.json | de | 100 | 1 | 2661 | 100 | 0 | 212848b17576 |
legacy-de-004.json | de | 100 | 1 | 2762 | 100 | 0 | 08ed0e57dc79 |
legacy-de-005.json | de | 100 | 3 | 2863 | 100 | 0 | 56a728a9aa7c |
legacy-de-006.json | de | 100 | 3 | 2964 | 100 | 0 | b715acca0e8f |
legacy-de-007.json | de | 100 | 2 | 3065 | 100 | 0 | dd0f699da95b |
legacy-de-008.json | de | 100 | 2 | 3166 | 100 | 0 | eb3cd1aba8c5 |
legacy-de-009.json | de | 100 | 3 | 3267 | 100 | 0 | 4e516268422f |
legacy-de-010.json | de | 100 | 2 | 3368 | 100 | 0 | 4ed61ac4efb4 |
legacy-de-011.json | de | 100 | 2 | 3469 | 100 | 0 | 8b8f7e11b53e |
legacy-de-012.json | de | 100 | 2 | 3570 | 100 | 0 | adfb9398b023 |
legacy-de-013.json | de | 100 | 2 | 3671 | 100 | 0 | 0ccc86232496 |
legacy-de-014.json | de | 100 | 2 | 3772 | 100 | 0 | f1fb46eb5d6f |
legacy-de-015.json | de | 100 | 3 | 3873 | 100 | 0 | 7bb28bdfa118 |
legacy-de-016.json | de | 100 | 2 | 3974 | 100 | 0 | f4200094acaa |
legacy-de-017.json | de | 100 | 2 | 4075 | 100 | 0 | 5b1fe9828835 |
legacy-de-018.json | de | 100 | 2 | 4176 | 100 | 0 | 117f63e8249e |
legacy-de-019.json | de | 100 | 2 | 4277 | 100 | 0 | 3601db14f6fc |
legacy-de-020.json | de | 100 | 2 | 4378 | 100 | 0 | fd475153d5d4 |
legacy-de-021.json | de | 100 | 2 | 4479 | 100 | 0 | f34192f5a161 |
legacy-de-022.json | de | 100 | 5 | 4580 | 100 | 0 | 2506b4199a02 |
legacy-de-023.json | de | 100 | 2 | 4681 | 100 | 0 | 3e3982b6e7c7 |
legacy-de-024.json | de | 100 | 2 | 4782 | 100 | 0 | 52fa5b1d0925 |
legacy-de-025.json | de | 100 | 3 | 4883 | 100 | 0 | 3ac9f9c9eb07 |
legacy-de-026.json | de | 100 | 3 | 4984 | 100 | 0 | 3093b9e8b712 |
legacy-de-027.json | de | 100 | 4 | 5085 | 100 | 0 | f8778ed6dbfd |
legacy-de-028.json | de | 100 | 1 | 5186 | 100 | 0 | c461e8121501 |
legacy-de-029.json | de | 100 | 2 | 5287 | 100 | 0 | cd26fd6f7b1c |
legacy-de-030.json | de | 100 | 1 | 5388 | 100 | 0 | cfd78d25b19a |
legacy-de-031.json | de | 100 | 1 | 5489 | 100 | 0 | b88c94ecd325 |
legacy-de-032.json | de | 100 | 2 | 5590 | 100 | 0 | 111beb423fad |
legacy-de-033.json | de | 100 | 1 | 5691 | 100 | 0 | 7900637f9553 |
legacy-de-034.json | de | 100 | 1 | 5792 | 100 | 0 | acc17a82f41f |
legacy-de-035.json | de | 100 | 1 | 5893 | 100 | 0 | bacdb1aebc2b |
legacy-de-036.json | de | 100 | 2 | 5994 | 100 | 0 | e7a5e6630015 |
legacy-de-037.json | de | 100 | 3 | 6095 | 100 | 0 | b4081932c37a |
legacy-de-038.json | de | 100 | 3 | 6196 | 100 | 0 | 461a793ec179 |
legacy-de-039.json | de | 100 | 4 | 6297 | 100 | 0 | 85e768f43dac |
legacy-de-040.json | de | 100 | 2 | 6398 | 100 | 0 | 25322067f9dc |
legacy-de-041.json | de | 100 | 3 | 6499 | 100 | 0 | eb5aa5aaa18e |
legacy-de-042.json | de | 87 | 2 | 6587 | 87 | 0 | c443cec7f961 |
Before / after
| Measure | Before | After | Delta |
|---|---|---|---|
Published qw_question | 732 | 9,069 | +8,337 |
wp_qwizz_question_index rows | 732 | 9,069 | +8,337 (drift 0) |
Index lang=en | 561 | 4,711 | +4,150 |
Index lang=de | 57 | 4,244 | +4,187 |
Index lang=es / fr | 57 / 57 | 57 / 57 | 0 |
| Question-subject rows | 978 | 9,315 | +8,337 |
qw_subject terms | 483 | 483 | 0 (no new terms) |
| Draft quizzes | 15 | 99 | +84 receipts |
Spot check end-to-end: DE stem Weißt du, welche dieser indischen Sprachen… survived cleaning intact into legacy-de-001.json, imported as post 2359, post_content matches, qw_correct_idx=3 (Tamil), index row lang='de'.
Probe
./scripts/quizwizz-probe.sh --wave all → 1..46, assertions=46 failures=0. Two Wave 6 fixtures had assumed pre-import content and were modernised to self-provision: the sufficiency assertion now raises its own count ceiling to smallest-pool+1 instead of hoping a ≤19-question pool exists, and the zero-pool assertion (which hardcoded science-computers, now 298 questions) became “every canonical subject remains visible in admin tree regardless of pool”. The plugin itself was not changed in this run.