π 2026-08-19 question-corpus audit
Superseded β 2026-08-19
The 679-question / 456-subject bench state measured here at 06:45 UTC is superseded by the 2026-08-19 corpus import and the 2026-08-19 legacy WXR import, which closed the same day at 9,069 questions and 483 subject terms. Preserved as observed.
One sentence
The live bench still holds 679 published questions with a matching 679-row index and 0
QuestionValidatorviolations; the repaired local-corpus pass finds 5,701 distinct local stems and 360 overlaps with the bench; one exact published duplicate and the English progressive subject pool remain the live defects.
Status vocabulary on this page: done Β· verified Β· open Β· blocked(<what>) Β· retracted.
What this page already proved before the 06:45 UTC bench pass
The existing page already proved the core corpus shape: 679 published questions, 679 index rows, 0 content-vs-index drift, 456 subject terms, 908 question-subject rows, language rows en=508 / de=57 / es=57 / fr=57, 0 validator violations over published questions, one exact normalised Mona Lisa duplicate, local union 1,425 fingerprints, and 324 bench/local overlaps. The 06:45 UTC pass below re-measured the bench half with a single mounted wp eval-file audit script and supersedes stale sufficiency text: the deployed gate now exposes only 2 specific subjects for default English progressive criteria (general-knowledge, geography) plus the synthetic any card, not 3 specific subjects. The local-corpus handoff then superseded the earlier local union/overlap numbers after fixing XLSX shared-string parsing and adding more corpus paths.
Bench command transcript
All bench measurements in the State, Taxonomy, Conformance, Duplicates, and Sufficiency sections came from this mounted read-only PHP audit command:
ssh loca@178.18.250.170 'cd ~/dev/wrdp && sudo -n docker compose --profile cli run --rm -v /tmp/qw_corpus_audit.php:/tmp/qw_corpus_audit.php wpcli wp eval-file /tmp/qw_corpus_audit.php'
Script source path on the bench: /tmp/qw_corpus_audit.php. The script reads wp_posts, wp_qwizz_question_index, wp_qwizz_question_subjects, term assignments, and question meta only; it does not update options, post meta, posts, or plugin files.
Headline cross-check command:
ssh loca@178.18.250.170 'cd ~/dev/wrdp && sudo -n docker compose --profile cli run --rm wpcli wp post list --post_type=qw_question --post_status=publish --format=count' β 679.
Code contracts cited by this page:
| Contract | Source |
|---|---|
Validator payload for indexed questions is built from qw_type, post content/title, qw_choices, qw_correct_idx, qw_explanation, qw_lang, and exactly one qw_difficulty term. | wp/wp-content/plugins/quizwizz/includes/QuestionIndex.php:223-233 |
QuestionValidator accepts only multiple/boolean, non-empty stem β€2000 chars, 2-8 non-empty string choices, boolean exactly 2 choices, each choice β€1000 chars, distinct normalised choices, in-range integer correct_idx, explanation β€4000 chars, valid language slug, and difficulty `easy | normal |
Progressive capacity is 2 * min(easy, harder) + (easy > harder ? 1 : 0), where harder = normal + hard; a progressive selection of count 10 needs easy >= 5 and normal+hard >= 5. | wp/wp-content/plugins/quizwizz/includes/QuestionSelector.php:160-177, wp/wp-content/plugins/quizwizz/includes/QuestionSelector.php:181-196 |
Builder cards are only advertised when enabled, pool β₯1, and SubjectTaxonomy::can_satisfy(...) returns true. | wp/wp-content/plugins/quizwizz/includes/SubjectTaxonomy.php:395-428, wp/wp-content/plugins/quizwizz/includes/SubjectTaxonomy.php:436-502 |
State
Re-measured 2026-08-19 at 06:45 UTC. Headline publish count equals the wp post list cross-check above: 679.
| Metric | Value | Command / key |
|---|---|---|
Published qw_question | 679 | count.qw_question.publish=679 from the mounted wp eval-file; cross-check wp post list --post_type=qw_question --post_status=publish --format=count β 679 |
Auto-draft qw_question | 1 (ID 1351, empty title) | count.qw_question.auto-draft=1; local-corpus bench census dumped all qw_question posts and identified ID 1351 |
| Draft / pending / private / trash questions | 0 / 0 / 0 / 0 | no grouped count.qw_question.* rows for those statuses in the mounted output |
Published qw_quiz | 13 | count.qw_quiz.publish=13 |
Draft qw_quiz | 10 | count.qw_quiz.draft=10 |
| Draft quiz IDs | 598, 613, 694, 710, 938, 1556, 1657, 1758, 1859, 1960 | quiz.draft_ids=598,613,694,710,938,1556,1657,1758,1859,1960 |
| Index rows | 679 | index.rows=679 (SELECT COUNT(*) FROM wp_qwizz_question_index) |
| Valid index rows | 679 | index.valid_rows=679 |
wp_qwizz_question_subjects rows | 908 | subjects.rows=908 |
| Published questions missing from index | 0 | drift.published_not_indexed=0 |
| Index rows without published question | 0 | drift.indexed_not_published=0 |
| Subject rows without indexed question | 0 | drift.subject_rows_orphan_question=0 |
| Content-vs-index drift | 0 | drift.published_not_indexed=0 and drift.indexed_not_published=0 |
The five imported drafts named on now (1556, 1657, 1758, 1859, 1960) are still draft. Five older draft quizzes also remain: 598, 613, 694, 710, 938. The previous page note about a deleted workstream-E scratch quiz is historical evidence; the current grouped query reports no such draft ID.
Language
Rows by lang from SELECT lang, COUNT(*) FROM wp_qwizz_question_index GROUP BY lang in /tmp/qw_corpus_audit.php:
| lang | rows |
|---|---|
| en | 508 |
| es | 57 |
| fr | 57 |
| de | 57 |
Retracted
now.mdpreviously said content languages wereenonly. That isretracted. The index still holds 171 non-English rows (57 Γ de/es/fr). Interface language is a separate setting and is not the content-language count.
Taxonomy
Difficulty
Index difficulty rows and taxonomy term assignments both agree in the 06:45 UTC pass:
| difficulty | index rows | qw_difficulty term rows |
|---|---|---|
| easy | 276 | 276 |
| normal | 240 | 240 |
| hard | 163 | 163 |
no qw_difficulty term on published questions | 0 | 0 |
multiple qw_difficulty terms on one published question | 0 | 0 |
Command keys: index.difficulty.easy=276, index.difficulty.normal=240, index.difficulty.hard=163, term.difficulty.easy=276, term.difficulty.normal=240, term.difficulty.hard=163, term.difficulty.none_count=0, term.difficulty.multi_count=0.
Difficulty is a qw_difficulty term for validator/index purposes (QuestionIndex.php:207-233), not qw_difficulty post meta. A validator payload that reads the empty meta key would report a false qw_invalid_difficulty on every row.
Subjects
qw_subject terms: 456 (subject.terms=456). Published-question pool size per qw_subject term, counting distinct indexed published questions via wp_qwizz_question_subjects:
| pool | subjects | Command key |
|---|---|---|
| 20+ | 3 | subject.hist.20+=3 |
| 10-19 | 16 | subject.hist.10-19=16 |
| 5-9 | 11 | subject.hist.5-9=11 |
| 1-4 | 408 | subject.hist.1-4=408 |
| 0 | 18 | subject.hist.0=18 |
Top 20 by published count (subject.top20=...): geography 26, history 26, general-knowledge 22, science 16, language 13, society 13, animals 12, art 12, film-tv 12, food-drink 12, games 12, literature 12, math 12, entertainment-music 12, mythology 12, politics 12, sports 12, tech 12, science-nature 10, science-physics 9.
Zero-pool subjects: 18 (subject.zero_pool_count=18). First 15 by term order (subject.zero_pool_first15=...): animals-nature, entertainment-japanese-anime-manga, entertainment-board-games, entertainment-books, entertainment-cartoon-animations, celebrities, entertainment-comics, science-computers, entertainment, entertainment-film, games-technology, literature-arts, science-mathematics, people-society, qw-svg-probe-4lhqftjo.
Conformance
Conformance was re-run over all published and draft qw_question posts. The scan set is conformance.scanned=679, with conformance.published=679 and conformance.draft=0; the one qw_question auto-draft is intentionally outside the requested published+draft set.
Implementation notes: the audit script mirrored the indexed payload contract from QuestionIndex.php:223-233 and also called QuizWizz\QuestionValidator::validate_array(...) for each scanned question. The exact rule source is QuestionValidator.php:35-120.
| rule | violations | sample ids | Command key |
|---|---|---|---|
| type not in `multiple | boolean` | 0 | β |
| stem empty or > 2000 | 0 | β | absent rule.stem_empty_or_over_2000; conformance.rule_violations=0 |
| choices not a 2-8 list / empty / non-string | 0 | β | absent rule.choices_not_list, rule.choice_not_string, rule.choices_outside_2_8_or_empty; conformance.rule_violations=0 |
| boolean not exactly 2 choices | 0 | β | absent rule.boolean_not_exactly_2; conformance.rule_violations=0 |
| any choice > 1000 chars | 0 | β | absent rule.choice_over_1000; conformance.rule_violations=0 |
| choices not distinct after validator normalisation | 0 | β | absent rule.choices_not_distinct; conformance.rule_violations=0 |
correct_idx missing or out of range | 0 | β | absent rule.correct_idx_missing_or_out_of_range; conformance.rule_violations=0 |
| explanation > 4000 chars | 0 | β | absent rule.explanation_over_4000; conformance.rule_violations=0 |
invalid lang slug | 0 | β | absent rule.lang_invalid; conformance.rule_violations=0 |
| no / multiple difficulty terms | 0 | β | absent rule.no_difficulty_term, rule.multiple_difficulty_terms; conformance.rule_violations=0 |
0 violations. The direct validator call also returned 0 failures (conformance.validator_failures=0, conformance.validator_failure_detail=). Missing qw_choices/qw_type meta: 0 (conformance.missing_meta=0).
Choice-count histogram over the 679 scanned questions:
| choices | questions | Command key |
|---|---|---|
| 2 | 91 | choice_hist.2=91 |
| 4 | 585 | choice_hist.4=585 |
| 5 | 2 | choice_hist.5=2 |
| 8 | 1 | choice_hist.8=1 |
Empty explanation is allowed by the validator; the rule is only a 4000-character cap. Current empty-explanation count: 40 (conformance.empty_explanation=40).
Duplicates
Normalisation for duplicate detection: use the question stem from post content when non-empty, otherwise post title; strip tags; lowercase; replace punctuation/non-alphanumeric runs with one space; collapse whitespace; trim. The local-corpus handoff separately proved question text lives in post_title and post_content duplicates it for ID 67; meta keys are qw_type, qw_choices, qw_correct_idx, qw_explanation, qw_lang, qw_source, and qw_opentdb_id, none of which holds the stem.
| kind | groups | posts | 10 largest groups / evidence | Command key |
|---|---|---|---|---|
| Exact normalised stem among published questions | 1 | 2 | 2x [357/publish 1915/publish] "who painted the mona lisa" | dup.groups_publish_only=1; dup.group1=2x [357/publish 1915/publish] "who painted the mona lisa" |
| Exact normalised stem across published + draft questions | 1 | 2 | same group; there are no draft qw_question posts | dup.groups_total=1, conformance.draft=0 |
| Published-vs-draft collisions | 0 | 0 | none | dup.groups_publish_vs_draft=0 |
| Unique bench fingerprints in published + draft scan | 678 | β | 679 scanned posts minus the one 2-post group | dup.unique_fingerprints=678 |
The local-corpus bench census agrees: duplicate group ID 357 Who painted the 'Mona Lisa'? equals ID 1915 Who painted the Mona Lisa? after quote stripping; publish distinct count is 678.
Historical near-duplicate evidence retained
The earlier page also listed a near-duplicate pair, 1574
Which compound is chiefly responsible for the heat of chili peppers?and 1591Which compound is chiefly responsible for the pungent heat of hot chili.... That was a heuristic first-40-normalised-character check, not part of the exact-normalised duplicate requirement re-measured in this pass, so it remains historical evidence and is not counted in the exact collision table above.
Sufficiency against the default English progressive request
Default criteria measured through the deployed code path: GenerationCriteria::from_array(array('lang'=>'en','difficulty'=>'prog','count'=>10), ExposureSettings::get()) produced suff.criteria=source=dynamic lang=en difficulty=prog type=mixed count=10; default language is en (suff.default_lang=en) and default count is 10 (suff.count_default=10).
The codeβs own progressive rule is not 3/3/3. QuestionSelector::capacity() computes progressive capacity as 2 * min(easy, harder) + (easy > harder ? 1 : 0), where harder is normal + hard (QuestionSelector.php:160-177). QuestionSelector::select() then requires easy >= ceil(count / 2) and harder >= floor(count / 2) (QuestionSelector.php:181-196). For a 10-question progressive English quiz, the real requirement is therefore 5 easy English questions and 5 normal-or-hard English questions under the selected subject.
Builder advertisement also uses that same rule: SubjectTaxonomy::can_satisfy() clones the criteria, sets the subject categories, calls QuestionSelector::capacity($probe), and requires capacity >= count (SubjectTaxonomy.php:395-428); builder_cards() skips cards unless pool >= 1 and can_satisfy(...) is true (SubjectTaxonomy.php:436-502).
| Metric | Value | Command key |
|---|---|---|
| Subject terms considered | 456 | suff.subjects_advertised=456 |
| Specific subject terms satisfying default English progressive 10 | 2 | suff.subjects_can_satisfy=2 |
| Satisfying specific subjects | general-knowledge, geography | suff.can_satisfy_slugs=general-knowledge, geography |
| Non-empty but insufficient subject pools | 197 | suff.nonempty_but_insufficient=197 |
| Zero-capacity subject pools for the progressive criteria | 257 | suff.zero_capacity=257 |
Synthetic any card satisfies the same criteria | yes | suff.any_can_satisfy=yes |
Synthetic any progressive capacity | 438 | suff.any_capacity=438 |
Top progressive capacities under the code rule (suff.top12_prog_capacity=...): geography 14, general-knowledge 13, science-nature 7, history 6, language 4, society 4, science 3, animals 3, geography-maps 3, geography-world-capitals 3, food-drink 2, film-tv 2.
Superseded 2026-08-19 06:45 UTC
The earlier text on this page used two hand-derived thresholds (
3/3/3and1/1/1) and said history also qualified under the relaxed bar. That is now superseded. The deployed codeβs rule is easy-vs-harder progressive capacity; under that rule historyβs capacity is only 6, so the real specific-subject count is 2, not 3. Including the syntheticanycard, the builder can advertise 3 cards:any,general-knowledge, andgeography.
Local corpus inventory
Method from local-corpus handoff: stdlib XLSX reader /tmp/corpus-work/xlsx.py using zipfile + ElementTree, with sharedStrings indexed and t="s" resolved as an index; fingerprint is sha1(lower β strip punctuation β collapse whitespace β strip); fingerprints live in /tmp/corpus-fingerprints/*.txt. Bench dump command used by that handoff: scp /tmp/corpus-work/dump.php loca@β¦:/tmp/dump.php then ssh loca@178.18.250.170 'cd ~/dev/wrdp && sudo -n docker compose --profile cli run --rm -v /tmp/dump.php:/tmp/dump.php wpcli wp eval-file /tmp/dump.php'; it emitted 680 qw_question rows.
| dataset | sheet/node | question column | records | non-empty | unique norm | β© bench pub | % of set |
|---|---|---|---|---|---|---|---|
04 QUESTIONS/Qwizz_Gold_Question_Corpus_240.xlsx | Question Bank | Question | 240 | 240 | 240 | 65 | 27.1% |
04 QUESTIONS/Qwizz_Gold_Question_Corpus_360.xlsx | Question Bank | Question | 360 | 360 | 360 | 70 | 19.4% |
04 QUESTIONS/Qwizz_Gold_Question_Corpus_504.xlsx | Question Bank | Question | 504 | 504 | 504 | 70 | 13.9% |
04 QUESTIONS/Qwizz_Gold_Question_Corpus_1008.xlsx | Question Bank | Question | 1008 | 1008 | 1008 | 101 | 10.0% |
04 QUESTIONS/Qwizz_10k_Content_Runway.xlsx | Question Bank (+ Production Queue: 8992 placeholder rows, empty Question) | Question | 10000 | 1008 | 1008 | 101 | 10.0% |
04 QUESTIONS/Qwizz_10k_Content_Runway_dfq.xlsx | byte-identical to above | Question | 10000 | 1008 | 1008 | 101 | 10.0% |
04 QUESTIONS/Qwizz_Wave_01_Editorial_Candidates_168 (1).xlsx | Question Bank | Question | 168 | 168 | 165 | 19 | 11.5% |
04 QUESTIONS/Qwizz_Wave_01_Editorial_Candidates_168.xlsx | byte-identical to above | Question | 168 | 168 | 165 | 19 | 11.5% |
04 QUESTIONS/Qs.json | questions[] | stem | 32 | 32 | 32 | 2 | 6.2% |
02 DOCS/questions.json | questions[] | question | 229 | 229 | 229 | 205 | 89.5% |
04 QUESTIONS/World Quiz Datase files 4 qwizz/questions.json | identical copy | question | 229 | 229 | 229 | 205 | 89.5% |
04 QUESTIONS/quiz-lib_claude-jam_files/questions.json | identical copy | question | 229 | 229 | 229 | 205 | 89.5% |
04 QUESTIONS/loca-dev-trivia-atlas/data/physical-sciences/easy.jsonl | jsonl | q | 26 | 26 | 24 | 0 | 0.0% |
04 QUESTIONS/loca-dev-trivia-atlas/meta/rejections.jsonl | jsonl | packet.q | 33 | 26 | 26 | 0 | 0.0% |
04 QUESTIONS/world_quiz_reference_demo_v1/data/items.jsonl | jsonl | prompt.stem | 33 | 33 | 33 | 1 | 3.0% |
01 APP/quizwizz-1.3.1-external-audit/β¦/assets/data/opentdb-local.json | json array | question_en | 4196 | 4196 | 4192 | 37 | 0.9% |
Superseded local inventory
The earlier local section on this page reported a 1,425-fingerprint local union and 324 bench overlaps. The local-corpus handoff supersedes that after fixing the XLSX shared-string reader and including additional corpus files: total distinct local is 5,701, local β© bench is 360, and grand distinct union is 6,019.
Overlap with the bench
| set | unique fingerprints | Method / proof |
|---|---|---|
| Bench published posts | 679 | local-corpus bench dump and this pageβs wp post list cross-check agree |
| Bench published distinct | 678 | one exact duplicate group, ID 357 vs ID 1915 |
| Total distinct local | 5,701 | local-corpus fingerprint union using sha1(lower β strip punctuation β collapse whitespace β strip) |
| Local β© bench | 360 | local-corpus cross-match against the 678 distinct bench published stems |
| Bench questions in no local dataset | 318 | 678 distinct bench stems minus 360 shared |
| Grand distinct union | 6,019 | 5,701 local + 678 bench - 360 shared |
Notable structure from the local-corpus handoff:
- Gold 360 β 504 β 1008, and Gold 1008 is identical to the 10k Runway
Question Bank. - Gold 240 carries into Gold 360 at 239/240; exactly one 240-era question was replaced or reworded.
- Byte-identical file pairs/triples:
10k_Content_Runway.xlsxequals_dfq.xlsx; both Wave 01 files are identical; the threequestions.jsoncopies are identical. - Sixteen discovered dataset files collapse to thirteen real corpora after byte-identical duplicates.
- Wave 01 shares only one item with the Gold line and has three internal duplicates.
- Gold is almost disjoint from imported material: Gold β© OpenTDB pack = 2; Gold β© 229-pack = 1.
- The trivia-atlas material has not been imported: 0 bench overlap for
easy.jsonl;easy.jsonlhas 24 unique stems andrejections.jsonlhas 26, with 2 shared. Qs.jsonneeded in-memory repair only: line 287 contains one illegal JSON escape, a bare\lin\lim; source was untouched.- No workbook carries a language column;
Qs.jsondeclaresmeta.languages = [en,es,fr,de,zh-Hans,pt-BR]but every stem is English.
Deltas this programme
Every bench number below was re-measured on 2026-08-19 at 06:45 UTC where possible; source-history items that cannot be re-derived from current database state are marked [cited] with the page that records them.
| change | then | now | proof |
|---|---|---|---|
Import blocker (chess vs games-chess) | packs died on slug mismatch | [cited] slug resolution fixed and recorded complete | completed task log 2026-08-18 completed row |
| Corpus import | 269 published [cited] | 679 published, index 679, drift 0 | mounted audit keys count.qw_question.publish=679, index.rows=679, drift.published_not_indexed=0, drift.indexed_not_published=0; headline cross-check wp post list --post_type=qw_question --post_status=publish --format=count β 679 |
| Five English packs | β | drafts 1556 / 1657 / 1758 / 1859 / 1960 still draft; five older drafts also remain | quiz.draft_ids=598,613,694,710,938,1556,1657,1758,1859,1960 |
| Sufficiency gate / Wave 6 #12 | guest cards 11 [cited] | code-derived default English progressive: 2 specific subjects (general-knowledge, geography) plus synthetic any; 197 non-empty subject pools still insufficient | sufficiency census; mounted audit keys suff.subjects_can_satisfy=2, suff.can_satisfy_slugs=general-knowledge, geography, suff.any_can_satisfy=yes, suff.nonempty_but_insufficient=197 |
| B001 player review restore | in-process review length 58 [cited] | browser-verified anonymous quiz 413 result 13 / 58 (22%), 58 .qwizz-player__review-item, 0 console errors [cited] | play and print answers; screenshot 03 EVIDENCE/2026-08-19-quiz-413-playthrough-review.webp |
| Assumed reveal enum `instant | end | never` | written as the player contract |
| Answers operator UI | one hidden/preserved bit | two visible controls on the quiz metabox and the builder; sheet bit persists independently; player-review disabled under Forced site policy [cited] | metabox/browser proof from answers-switch workstream |
| German catalog | 153 missing / 76 obsolete | 1650 = 1650, missing 0 / obsolete 0 [cited] | task 2.1.1 |
| Probe harness | 1..46 / 46 / 0 | no probe run by this bench-corpus pass; latest known post-install probe remains [cited] | coordinator-owned probe receipts, not this pageβs bench audit command |
| Debug log | 38,433 | not re-measured by this pass | previous page evidence retained; no current claim |
Open recommendations
Each open, one line, no schedule.
| id | status | recommendation |
|---|---|---|
| QC-01 | open | Merge published pair 357 / 1915 (Mona Lisa) β same English easy item, punctuation-only difference. |
| QC-02 | open | Decide whether chili pair 1574 / 1591 is a rewrite to keep or a near-duplicate to drop; it is not part of the exact-normalised collision count. |
| QC-03 | open | Fill or explicitly mark the 40 published questions with an empty explanation. |
| QC-04 | open | English progressive pool is the bottleneck, not raw count: only general-knowledge and geography satisfy the real code rule for a specific subject; any satisfies through the aggregate pool. |
| QC-05 | open | Gold 1008 and the 10k runway sheet are the same 1008 non-empty rows β do not count them twice in the fusion ledger. |
| QC-06 | open | Treat doctrine files separately from inventory; the repaired local pass did not count qwizz-irresist.yaml as a question corpus. |
| QC-07 | open | Drop byte-identical duplicate corpus files from the working tree so future globs do not double-count them. |
| QC-08 | open | qw-svg-probe-4lhqftjo is a leftover probe subject with a zero pool β delete or quarantine. |
| QC-09 | open | Owner decision UX-ANS-01 (may Forced honour per-quiz sheet off?) is still open; todayβs REST already honours per-quiz '0' for the sheet flag. |