Mirror decision sheet — 41 modified files vs 715474f

a. Purpose

The Sep-8 mirror commit is NOT PERFORMED / blocked (handover §5) because the release owner had no per-file view of what is actually dirty and why. This sheet is that view. It stages nothing, commits nothing and touches no plugin byte: a throwaway Python script (census.py, stdlib only, read-only against the tree) hashed every M row of ./scripts/qwgit.sh status --short (asserted: 41 rows, 0 ??) against four images and classified each row by a fixed ladder. Inputs: mirror GIT_DIR=.git-quizwizz, HEAD 715474f07ddf75c4dd49607aad3f82a405b0eeae; the Sep-8 baseline-manifest.json (35 archive members = exact dirty before images; 19 packet paths, 13 archive-backed and 6 mirror-backed); the sealed final-manifest.json (19-path allowlist, afterSha256 per capture, patch today-source-final.patch SHA-256 d1bc84e7…a93c). The 41 rows equal exactly archive(35) ∪ packet(19).

Class ladder (first match wins): clean-now (current = HEAD) · packet-clean-base (in packet, current = packet after, before = HEAD) · packet-on-drifted-base (in packet, current = packet after, before ≠ HEAD) · post-packet-mutation (in packet, current ≠ packet after) · inherited-catalog-artifact (not in packet, current = before, under languages/) · inherited-unpacketed (not in packet, current = before) · post-sep8-unattributed (not in packet, current ≠ before — RED).

b. Class counts

ClassRows
packet-on-drifted-base13
packet-clean-base6
inherited-unpacketed5
inherited-catalog-artifact17
clean-now0
post-packet-mutation0
post-sep8-unattributed0
total41

Every live byte is accounted for: the 19 packet paths still carry exactly their sealed afterSha256, and the 22 unpacketed paths still carry exactly their Sep-8 archive bytes. Nothing changed after the Sep-9 seal, and nothing is unattributed. (The Sep-14 backup-dropping cleanup removed only untracked files and left all 41 tracked rows byte-identical — receipt §5.)

c. Fresh canonical apply-check of the final packet

This had never been run: the Sep-8 receipt checked only the interim v3 patch. Today: ./scripts/qwgit.sh archive 715474f… | tar -x into a disposable directory, then inside it env -u GIT_DIR -u GIT_WORK_TREE git apply --check -p1 --whitespace=error-all today-source-final.patch (patch SHA-256 verified d1bc84e75939f5fa449b8127c58f271bb59c0e26a7bfb03443d75a4e3083a93c first). Result: exit 1, seven paths fail (patch failed: <path>:<line> / patch does not apply):

  • assets/css/qwizz-admin-settings-core.css:41
  • assets/css/qwizz-admin-settings-layout.css:697
  • assets/css/qwizz-finetune.css:159
  • assets/js/qwizz-admin-settings.js:262
  • assets/js/qwizz-finetune.js:22
  • includes/Frontend/Shortcodes/CraftShortcode.php:459
  • includes/Frontend/views/finetune-editor.php:27

These are the same seven paths the v3 assessment recorded; the final packet does not fail anywhere new. All seven are packet-on-drifted-base; the other six drifted-base paths (qwizz-admin-responsive.css, qwizz-builder.css, ExposureSettings.php, CraftService.php, builder-view.php, PresentationDocument.php) happen to apply against 715474f despite the drift, and all six packet-clean-base paths apply. git apply --check is all-or-nothing, so “expected to apply” below means the file’s hunks individually apply; the patch as a whole does not. The disposable tree was deleted afterwards; no apply without --check was run anywhere.

d. The 41 rows

Hashes are SHA-256 truncated to 8 hex; before names its source (archive = Sep-8 dirty archive member, mirror = mirror object matching the earliest pristine receipt). +N/−M is git diff --numstat 715474f -- <path>; - = binary.

PathClassbeforeHEADcurrentpacket after+/− vs HEADProposed disposition
assets/css/qwizz-admin-responsive.csspacket-on-drifted-basee3dd49aa (archive)b1bfb5e7636e08c0636e08c0+24/−4owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
assets/css/qwizz-admin-settings-core.csspacket-on-drifted-base8362571a (archive)92d09a8e988fa373988fa373+16/−85owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
assets/css/qwizz-admin-settings-layout.csspacket-on-drifted-baseb6074ed1 (archive)dd3a99e5e2afa84ce2afa84c+0/−72owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
assets/css/qwizz-admin-settings-workspace.cssinherited-unpacketed48ffbe6b (archive)44f37cc748ffbe6b+46/−155pre-Sep-8 modification with no packet; owner attributes the diff vs HEAD (supplied) or reverts to 715474f
assets/css/qwizz-builder.csspacket-on-drifted-base462a3065 (archive)0b7c728d84e348cc84e348cc+163/−62owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
assets/css/qwizz-finetune.csspacket-on-drifted-base9bc79c29 (archive)dd50310b75c41eae75c41eae+326/−122owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
assets/js/qwizz-admin-settings.jspacket-on-drifted-base6f5cb4ba (archive)352a0b0670a0a62170a0a621+55/−86owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
assets/js/qwizz-builder-controls.jspacket-clean-base16ccb00d (mirror)16ccb00da1ca6258a1ca6258+31/−15stage this file’s hunks from today-source-final.patch against 715474f; expected to apply
assets/js/qwizz-builder-state.jspacket-clean-base9fad4d76 (mirror)9fad4d76800f21e9800f21e9+40/−4stage this file’s hunks from today-source-final.patch against 715474f; expected to apply
assets/js/qwizz-builder-submit.jspacket-clean-base5364dcd9 (mirror)5364dcd9df41d618df41d618+9/−1stage this file’s hunks from today-source-final.patch against 715474f; expected to apply
assets/js/qwizz-finetune.jspacket-on-drifted-basedebe7a3e (archive)e8298a1a2c91b2ef2c91b2ef+432/−245owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
config/settings-tiers.jsoninherited-unpacketed35c27fb7 (archive)3bf8668e35c27fb7+0/−1pre-Sep-8 modification with no packet; owner attributes the diff vs HEAD (supplied) or reverts to 715474f
includes/Admin/SettingsPage.phpinherited-unpacketed5e38f30b (archive)6e6560385e38f30b+0/−14pre-Sep-8 modification with no packet; owner attributes the diff vs HEAD (supplied) or reverts to 715474f
includes/Admin/views/settings-page.phpinherited-unpacketedd73bb702 (archive)2aeee39ed73bb702+5/−18pre-Sep-8 modification with no packet; owner attributes the diff vs HEAD (supplied) or reverts to 715474f
includes/ExposureSettings.phppacket-on-drifted-base89de47bd (archive)910beea063ced03763ced037+8/−4owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
includes/Frontend/Craft/CraftService.phppacket-on-drifted-base09198c23 (archive)bcb3988f29801c7f29801c7f+3/−2owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
includes/Frontend/Shortcodes/CraftShortcode.phppacket-on-drifted-base2952a534 (archive)c9610d1c4508e3044508e304+24/−9owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
includes/Frontend/views/builder-view.phppacket-on-drifted-basee5aa5684 (archive)0727cd0492208da092208da0+30/−29owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
includes/Frontend/views/finetune-editor.phppacket-on-drifted-basede5c89e1 (archive)f3d70c91f2d6c9e3f2d6c9e3+78/−18owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
includes/Generation/GenerationSchemas.phppacket-clean-base0c51d926 (mirror)0c51d926bf8237fbbf8237fb+2/−9stage this file’s hunks from today-source-final.patch against 715474f; expected to apply
includes/Generation/GenerationService.phppacket-clean-base365ab4ac (mirror)365ab4ac6ed4d0766ed4d076+37/−25stage this file’s hunks from today-source-final.patch against 715474f; expected to apply
includes/Pdf/PdfGenerator.phppacket-clean-basec2b6b6bc (mirror)c2b6b6bcc2962248c2962248+6/−3stage this file’s hunks from today-source-final.patch against 715474f; expected to apply
includes/PresentationDocument.phppacket-on-drifted-base7a49e4f0 (archive)b83e479a4d546b6e4d546b6e+12/−5owner picks base: (i) rebase the hunks onto 715474f, or (ii) accept current bytes whole-file; diff vs HEAD supplied
includes/Settings/SettingsSchema.phpinherited-unpacketedc2ef5599 (archive)e8cae74ac2ef5599+2/−3pre-Sep-8 modification with no packet; owner attributes the diff vs HEAD (supplied) or reverts to 715474f
languages/quizwizz-de_DE-520b882d5a62045c160d0dc56eabc58c.jsoninherited-catalog-artifact9490a8c9 (archive)fac23e829490a8c9+135/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-949f8136c01f699e9f8fbc8c66d5f965.jsoninherited-catalog-artifact06227e24 (archive)11ae077006227e24+25/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-cdce7c50e7a4850240f5b7a9ca845996.jsoninherited-catalog-artifact7ad346ce (archive)1aada3cd7ad346ce+312/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-quizwizz-admin-editor.jsoninherited-catalog-artifactece11763 (archive)718a8e95ece11763+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-quizwizz-admin-import.jsoninherited-catalog-artifact8aaa1eb3 (archive)11fcdf3e8aaa1eb3+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-quizwizz-quiz-editor-script.jsoninherited-catalog-artifactc42ef186 (archive)3e6eca73c42ef186+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-qwizz-admin-settings.jsoninherited-catalog-artifact40572f3e (archive)da1609f240572f3e+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-qwizz-admin-shortcode-copy.jsoninherited-catalog-artifact6d39852c (archive)25a9f9646d39852c+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-qwizz-admin-subjects.jsoninherited-catalog-artifact8a5c53f4 (archive)f1a097878a5c53f4+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-qwizz-block-editor-enhance.jsoninherited-catalog-artifact63859fd2 (archive)8c18d16f63859fd2+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-qwizz-builder.jsoninherited-catalog-artifact552dc559 (archive)5cb80776552dc559+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-qwizz-finetune.jsoninherited-catalog-artifactc2745776 (archive)d34654e3c2745776+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-qwizz-player.jsoninherited-catalog-artifact000553f3 (archive)b14925c5000553f3+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE-qwizz-user.jsoninherited-catalog-artifactee2eedf6 (archive)7c771cf5ee2eedf6+1/−1regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE.moinherited-catalog-artifactff5fe922 (archive)ac4471a0ff5fe922+-/−-regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz-de_DE.poinherited-catalog-artifactbf75481d (archive)c16dca2ebf75481d+926/−981regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides
languages/quizwizz.potinherited-catalog-artifactb6e20ef0 (archive)956c6f9bb6e20ef0+898/−953regenerate from catalog commit d61d98c through the locked pipeline, or accept as build output; owner decides

e. What the owner must decide

  • packet-on-drifted-base (13): the sealed packet was captured against a dirty base, so its hunks describe current − before, not current − HEAD. Options: (i) rebase the file’s hunks onto 715474f by hand — the seven failing paths need this, the other six may apply as-is; (ii) accept the current live bytes whole-file as the new source (the diff vs HEAD for each is in the private diffs/); (iii) revert to 715474f and drop the Sep-8 packet for that file. The choice also settles what the pre-Sep-8 drift was, because it is folded into the whole-file diff.
  • packet-clean-base (6): the clean case. Option (i) stage the file’s hunks from today-source-final.patch (expected to apply against 715474f); option (ii) revert to 715474f if the Sep-8 receipt for that file is not accepted.
  • inherited-unpacketed (5 — qwizz-admin-settings-workspace.css, settings-tiers.json, SettingsPage.php, settings-page.php, SettingsSchema.php): modified before Sep-8 with no packet and no receipt naming the change. Options: (i) attribute the diff vs HEAD (supplied privately) to a dated receipt and stage whole-file; (ii) revert to 715474f. These are all Settings-surface files; the Sep-14 UI/UX round touches the first and fourth, after which their attribution is that receipt (see the refresh section when it lands).
  • inherited-catalog-artifact (17 languages/ files: .po, .pot, .mo and 14 script catalogs): build outputs regenerated on the bench after catalog commit d61d98c. Options: (i) regenerate through the locked pipeline from the canonical catalog source and commit the pipeline’s output; (ii) accept the bench bytes as build output; (iii) revert to 715474f. Never hand-edit.

Prerequisite that no option removes: the real mirror index must be inspected for unrelated work before any qwgit.sh add, and canonical target/port stays the owner’s call (handover §5).

f. Provenance

  • evidence/2026-09-14-mirror-decision/ (private, mode 0700, not published): census.py, census.json, apply-check.txt, diffs/<path>.diff (41 files; may contain source, never copied to the vault).
  • census.json SHA-256: 34f2e88abfec9e580d85c222f31c7a27509577fe6e5f595d548834457a032c10.
  • Independent replay: 5/5 rows confirmed (first row of each of the four classes present plus a second catalog row), re-hashed by hand against the live file, qwgit.sh show 715474f:<path>, the baseline inventory and the final capture; apply-check re-run in a fresh archive extraction. The read-only evidence-auditor verdict, quoted: “Independent replay confirms the census: live status is exactly 41 M rows with zero ??, row_count 41 and class_counts (packet-on-drifted-base 13, inherited-catalog-artifact 17, packet-clean-base 6, inherited-unpacketed 5) sum to 41, all five audited rows reproduce their current/head/before/packet_after hashes, numstats and ladder-derived class byte-for-byte, and the fresh final-packet apply-check independently returns exit 1 with the identical seven failure paths and byte-identical stderr — zero mismatches.”
  • Bench model roles: bench_edit/bench_probe/bench_audit were null in .omp/config.yml until 2026-09-14 (the evidence-auditor agent died with No model selected); now bound to anthropic/claude-opus-5 at medium/low/high. Proven in-session: omp config get modelRoles prints all three, and the replay above was produced by evidence-auditor itself.

Refresh after round F

The UX repair round changed 21 plugin files after the census above was taken, so the sheet’s 41-row view is now the pre-round-F state. Sections a through f are left exactly as they were measured; this section states what moved. The refresh artifact is evidence/2026-09-14-mirror-decision/census-refresh.json, created 2026-09-14T03:58:53Z against the same head 715474f.

Two limits on that artifact, stated because they change what it can decide:

  • it recorded row_count 49 by bypassing the script’s expected_rows 41 assertion through a refresh suffix, so the 41-row invariant that guarded the original census did not run.
  • it did not re-run the canonical apply-check. The exit-1 / seven-path result in section c still describes the pre-round-F packet only, and no apply-check exists for the round-F tree.

Refreshed class counts, same ladder, first match wins:

ClassRows before round FRows after round F
post-sep8-unattributed013
post-packet-mutation08
packet-on-drifted-base135
packet-clean-base66
inherited-unpacketed53
inherited-catalog-artifact1714
clean-now00
total4149

Six of the seven classes are non-empty after the round, against four before. The two that were 0 are the two RED-adjacent classes, and they hold exactly the 21 round-F files.

The 13 post-sep8-unattributed rows — not in the packet, current bytes differ from the Sep-8 before image:

  • assets/css/qwizz-admin-dashboard.css
  • assets/css/qwizz-admin-editor.css
  • assets/css/qwizz-admin-shell.css
  • includes/Admin/DashboardPresenter.php
  • includes/Admin/ListTables.php
  • includes/Admin/SettingsPage.php
  • includes/Admin/views/quiz-editor.php
  • includes/Admin/views/settings-page.php
  • includes/LanguageFlags.php
  • includes/Rest/AdminController.php
  • languages/quizwizz-de_DE.mo
  • languages/quizwizz-de_DE.po
  • languages/quizwizz.pot

The 8 post-packet-mutation rows — in the packet, but current bytes no longer equal the sealed afterSha256:

  • assets/css/qwizz-admin-responsive.css
  • assets/css/qwizz-admin-settings-core.css
  • assets/css/qwizz-builder.css
  • assets/css/qwizz-finetune.css
  • assets/js/qwizz-admin-settings.js
  • assets/js/qwizz-finetune.js
  • includes/Frontend/views/builder-view.php
  • includes/Frontend/views/finetune-editor.php

How the movement reconciles, from the counts above: packet-on-drifted-base lost exactly those 8 files, which is why it falls 13 → 5. inherited-catalog-artifact lost 3 and inherited-unpacketed lost 2, so 5 previously classified rows moved into post-sep8-unattributed; the three catalog rows are the .mo, .po and .pot artifacts in the list above, because round F regenerated them and the class requires current = before. That leaves 8 of the 13 as rows that were not among the original 41 at all, which is the arithmetic behind 41 + 8 = 49. The per-row identity of the 2 rows that left inherited-unpacketed is in census-refresh.json and was not re-derived for this section; section e already anticipated two of its five Settings files being touched, qwizz-admin-settings-workspace.css and settings-page.php.

What this does to the owner’s options in section e:

  • the 8 post-packet-mutation paths have no option (i). Their hunks in today-source-final.patch describe bytes that are no longer on disk, so staging that patch would discard round-F work. They need either the live bytes accepted whole-file against the round-F receipt, or a fresh capture.
  • the 13 post-sep8-unattributed paths are attributable, not orphaned: the round F receipt names the change, the slice and the anchors for each. That is what the class name asks for and what the original census had none of.
  • the 5 remaining packet-on-drifted-base and 6 packet-clean-base rows are unchanged by round F and their section e options stand as written.

Nothing here stages, commits or hand-edits anything, and no languages/ artifact was hand-edited: the catalog files moved class because round F regenerated the .mo through the normal path. releaseEligible: false.

Refresh after phase G

The 2026-09-14 Settings premium restyle changed six plugin files after the round-F refresh above, two of which were not tracked-modified before, so the census moves from 49 rows to 51 at the same head 715474f with 0 ??. Sections a through f and the round-F refresh are left exactly as they were measured; this section states what moved. The artifact is evidence/2026-09-14-mirror-decision/census-refresh-g.json, created 2026-09-14T06:15:40Z, and it carries both limits of its predecessor: it recorded row_count 51 against the script’s expected_rows 41, so the original row invariant did not run, and apply_check is null — no canonical apply-check exists for the round-F tree or for this one.

ClassRows after round FRows after phase G
post-sep8-unattributed1316
post-packet-mutation89
packet-clean-base66
packet-on-drifted-base54
inherited-unpacketed32
inherited-catalog-artifact1414
total4951

Four movements account for the whole delta, and they reconcile the counts exactly:

  • assets/css/qwizz-admin-settings-layout.css moved packet-on-drifted-basepost-packet-mutation, which is why the first class falls 5 → 4 and the second rises 8 → 9. Its live bytes no longer equal the sealed afterSha256.
  • assets/css/qwizz-admin-settings-workspace.css moved inherited-unpacketedpost-sep8-unattributed, so inherited-unpacketed falls 3 → 2.
  • assets/css/qwizz-admin-settings-search-preview.css is a new row in post-sep8-unattributed.
  • assets/css/qwizz-tokens.css is a new row in post-sep8-unattributed.

post-sep8-unattributed therefore rises 13 → 16: one file moved in and two are new rows, which is also the arithmetic behind 49 + 2 = 51. The two remaining phase G files were already carried by the round-F refresh — assets/css/qwizz-admin-settings-core.css as post-packet-mutation and includes/Admin/views/settings-page.php as post-sep8-unattributed — so their class did not change even though their bytes did.

What this does to the owner’s options in section e:

  • nine post-packet-mutation paths now have no option (i), one more than after round F. today-source-final.patch describes qwizz-admin-settings-layout.css bytes that are no longer on disk, so staging it would discard phase G work on that sheet as well.
  • all four new or moved rows are attributable rather than orphaned: the phase G receipt names the owned files, their live SHA-256 values and the rounds that changed each one. assets/css/qwizz-tokens.css deserves separate attention because it is not a Settings-only sheet: phase G added three admin tokens at :91-93 and an accent block scoped to .qwizz-settings.qwizz-settings--premium at :398-406, so the file is shared while the accent is not.
  • the 4 remaining packet-on-drifted-base and 6 packet-clean-base rows are unchanged by phase G and their section e options stand as written.

Nothing here stages, commits or hand-edits anything, and no languages/ artifact moved in this refresh. releaseEligible: false.