brulee-1 commited on
Commit
901a5f5
·
verified ·
1 Parent(s): 3ba8a2b

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. .gitattributes +5 -35
  2. .gitignore +26 -0
  3. LICENSE +21 -0
  4. README.md +284 -0
  5. pyproject.toml +43 -0
  6. samples/avif_q70_protected_high/pm4-060-9ea3ad52.png +0 -0
  7. samples/avif_q70_protected_high/pm4-080-78dedcb6.png +0 -0
  8. samples/avif_q70_protected_high/pm4-090-c71ebd94.png +0 -0
  9. samples/jpeg_q100_repair_zero/pm4-016-fd1eb48d.png +0 -0
  10. samples/jpeg_q100_repair_zero/pm4-075-3906d66e.png +0 -0
  11. samples/jpeg_q100_repair_zero/pm4-086-90e23232.png +0 -0
  12. samples/jpeg_q100_repair_zero/pm4-097-0b860832.png +0 -0
  13. samples/jpeg_q80_protected_high/pm4-002-effb6eaa.png +0 -0
  14. samples/jpeg_q80_protected_high/pm4-016-fd1eb48d.png +0 -0
  15. samples/jpeg_q80_protected_high/pm4-051-093f1478.png +0 -0
  16. samples/jpeg_q80_protected_high/pm4-060-9ea3ad52.png +0 -0
  17. samples/jpeg_q80_protected_high/pm4-075-3906d66e.png +0 -0
  18. samples/jpeg_q80_protected_high/pm4-076-a577a15d.png +0 -0
  19. samples/jpeg_q80_protected_high/pm4-078-a77b762e.png +0 -0
  20. samples/jpeg_q80_protected_high/pm4-080-78dedcb6.png +0 -0
  21. samples/jpeg_q80_protected_high/pm4-082-6adb4a49.png +0 -0
  22. samples/jpeg_q80_protected_high/pm4-089-60ad56aa.png +0 -0
  23. samples/jpeg_q80_protected_high/pm4-090-c71ebd94.png +0 -0
  24. samples/jpeg_q80_protected_high/pm4-097-0b860832.png +0 -0
  25. samples/webp_lossless/pm4-002-effb6eaa.png +0 -0
  26. samples/webp_lossless/pm4-051-093f1478.png +0 -0
  27. samples/webp_lossless/pm4-075-3906d66e.png +0 -0
  28. samples/webp_lossless/pm4-082-6adb4a49.png +0 -0
  29. samples/webp_lossless/pm4-089-60ad56aa.png +0 -0
  30. samples/webp_q80_protected_high/pm4-002-effb6eaa.png +0 -0
  31. samples/webp_q80_protected_high/pm4-016-fd1eb48d.png +0 -0
  32. samples/webp_q80_protected_high/pm4-051-093f1478.png +0 -0
  33. samples/webp_q80_protected_high/pm4-060-9ea3ad52.png +0 -0
  34. samples/webp_q80_protected_high/pm4-075-3906d66e.png +0 -0
  35. samples/webp_q80_protected_high/pm4-076-a577a15d.png +0 -0
  36. samples/webp_q80_protected_high/pm4-078-a77b762e.png +0 -0
  37. samples/webp_q80_protected_high/pm4-080-78dedcb6.png +0 -0
  38. samples/webp_q80_protected_high/pm4-082-6adb4a49.png +0 -0
  39. samples/webp_q80_protected_high/pm4-089-60ad56aa.png +0 -0
  40. samples/webp_q80_protected_high/pm4-090-c71ebd94.png +0 -0
  41. samples/webp_q80_protected_high/pm4-097-0b860832.png +0 -0
  42. tests/test_cross_codec.py +482 -0
  43. tests/test_cross_codec_experiment.py +552 -0
  44. tests/test_cross_codec_report.py +547 -0
  45. tests/test_jpeg_repair.py +238 -0
  46. tests/test_render_visual_tables.py +182 -0
  47. tests/test_verify_archive.py +186 -0
  48. uv.lock +0 -0
  49. weights/README.md +7 -0
  50. weights/manifest.csv +14 -0
.gitattributes CHANGED
@@ -1,35 +1,5 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ weights/**/*.png filter=lfs diff=lfs merge=lfs -text
2
+ weights/**/*.jpg filter=lfs diff=lfs merge=lfs -text
3
+ weights/**/*.webp filter=lfs diff=lfs merge=lfs -text
4
+ weights/**/*.avif filter=lfs diff=lfs merge=lfs -text
5
+ weights/**/*.jxl filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ .venv/
7
+ venv/
8
+ .cache/
9
+ .DS_Store
10
+ *.log
11
+
12
+ # Secrets and local state
13
+ .env
14
+ .env.*
15
+ *.pem
16
+ *.key
17
+
18
+ # Scratch outputs only; archived results and weights remain tracked
19
+ scratch/
20
+ tmp/
21
+ runs/
22
+ outputs/
23
+
24
+ # Local agent/project notes
25
+ tasks/
26
+ .hermes/
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PixelModel-v4 image codec study contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - research
5
+ - weight-compression
6
+ - image-codecs
7
+ ---
8
+
9
+ # PixelModel-v4 Image Codec Experiments
10
+
11
+ This repository is a research archive for measuring how image codecs affect a
12
+ PixelModel-v4 weight image and the model reconstructed from it. It is not the
13
+ main PixelModel-v4 model repository and is not a replacement model card.
14
+
15
+ ## Scope/Provenance
16
+
17
+ The upstream model card and model assets are licensed under MIT by
18
+ [bench-labs/PixelModel-v4](https://huggingface.co/bench-labs/PixelModel-v4). The
19
+ upstream model revision used by the experiment is
20
+ `80878fdd6e130d229c2581424a3456b47b979d4b`. The packaged experimental source was captured from robustness-study commit
21
+ `939465cee88e49ae212df48aac18e74459763a72`.
22
+
23
+ The archive records a fixed comparison: 100 prompts, 50 sampling steps, CFG 6,
24
+ Apple MPS, and identical prompt, seed, initial latent, and settings across
25
+ conditions. The archive is intended for auditability and re-running the
26
+ experiment, not for making claims about codecs outside these recorded settings.
27
+ The `samples/` tree contains one artifact for every successful generation row
28
+ (800 artifacts in the full 17-condition run), while failed rows retain null
29
+ sample provenance.
30
+
31
+ ## Motivation
32
+
33
+ PixelModel-v4 stores trained weights as image data, which makes ordinary image
34
+ storage and transport tools relevant to model serialization. Earlier work used
35
+ PNG as the lossless weight container. This repository explores what happens when
36
+ the same fp16 weight image is passed through modern lossless and lossy codecs,
37
+ then reconstructed with several byte-level methods. This is exploratory research:
38
+ the goal is to record the observed relationship between codec output,
39
+ reconstructed weight values, and generation behavior without proposing a
40
+ general-purpose compression result.
41
+
42
+ ## Experimental Setup
43
+
44
+ - Model: PixelModel-v4 DiT with an fp16 weight image, using the upstream revision above.
45
+ - Weight representation: each fp16 word is serialized across image bytes; the
46
+ high byte contains the sign, exponent, and upper mantissa bits.
47
+ - Prompts: 100 prompts.
48
+ - Sampling: 50 steps, CFG 6.
49
+ - Controls: identical prompt, seed, initial latent, and inference settings.
50
+ - Device: Apple MPS for the archived full run.
51
+ - Raw reconstruction is accepted only when the decoded weight tensor is finite.
52
+ A NaN count by itself is not called “nonfinite”; the gate checks the complete
53
+ tensor and reports NaN, +Inf, and -Inf separately.
54
+ - FID is N/A for this archive. CLIP and confidence intervals are not included
55
+ unless they are present in the archived CSV.
56
+
57
+ ## Codecs Evaluated
58
+
59
+ | Codec | Fixed setting | Role |
60
+ |---|---:|---|
61
+ | PNG | lossless | baseline |
62
+ | WebP | lossless | lossless control |
63
+ | JPEG | Q100 | lossy codec |
64
+ | JPEG | Q80 | lossy codec |
65
+ | WebP | Q80 | lossy codec |
66
+ | AVIF | Q70 | lossy codec |
67
+ | JPEG XL | distance 1 (`d1`) | lossy codec |
68
+
69
+ The protected representation keeps the high byte as PNG data and stores the low
70
+ byte through the lossy codec. The code also records the raw and finite-repair
71
+ paths separately.
72
+
73
+ ## Reconstruction Methods
74
+
75
+ | Method | Description |
76
+ |---|---|
77
+ | Raw | Decode the codec payload directly into the weight image representation. |
78
+ | Finite Repair Zero | Replace decoded NaN, +Inf, and -Inf values with zero while leaving finite values unchanged. |
79
+ | Protected High Byte | Preserve the high byte losslessly and decode only the low byte through the lossy codec. |
80
+
81
+ ## Representative Results
82
+
83
+ The following links are relative archive paths. A failed cell is rendered as an
84
+ explicit “NO SAMPLE” panel; it is not replaced with a black image or an inferred
85
+ metric.
86
+
87
+ ![Representative cross-codec comparison tables](images/visual_tables_contact_sheet.png)
88
+
89
+ *Caption: representative prompt panels across PNG, WebP lossless, raw lossy,
90
+ finite repair, and protected high-byte reconstructions.*
91
+
92
+ ![Representative JPEG Q100 comparison table](images/visual_table_jpeg_q100.png)
93
+
94
+ *Caption: JPEG Q100 table showing raw, finite-repair, and protected cells for representative prompts.*
95
+
96
+ ![Representative JPEG Q80 comparison table](images/visual_table_jpeg_q80.png)
97
+
98
+ *Caption: JPEG Q80 table. Raw and Finite Repair Zero cells have no generated sample; Protected High Byte cells show the archived outputs.*
99
+
100
+ ![Representative WebP Q80 comparison table](images/visual_table_webp_q80.png)
101
+
102
+ *Caption: lossy WebP Q80 table with explicit failed cells and archived Protected High Byte outputs.*
103
+
104
+ ![Representative AVIF Q70 comparison table](images/visual_table_avif_q70.png)
105
+
106
+ *Caption: AVIF Q70 table with the same prompts, seeds, and inference settings as the controls.*
107
+
108
+ ![Representative JPEG XL d1 comparison table](images/visual_table_jxl_d1.png)
109
+
110
+ *Caption: JPEG XL distance 1 table. Failed conditions are marked `NO SAMPLE`; no replacement image is used.*
111
+
112
+ ## Results table from available CSV only
113
+
114
+ The values below are transcribed from the archived CSV outputs for the full
115
+ 100-prompt run. They are counts and payload measurements, not estimates.
116
+
117
+ | Condition | Raw generation | Finite Repair Zero | Protected High Byte | Raw NaN / +Inf / -Inf | Protected exponent mismatch | Reliable payload saving vs PNG |
118
+ |---|---:|---:|---:|---:|---:|---:|
119
+ | PNG | 100/100 | N/A | N/A | 0 / 0 / 0 | 0 | 0.0000% |
120
+ | WebP lossless | 100/100 | N/A | N/A | 0 / 0 / 0 | 0 | 24.2799% |
121
+ | JPEG Q100 | 0/100 | 100/100 | 100/100 | 1,257 / 0 / 0 | 0 | -6.8825% |
122
+ | JPEG Q80 | 0/100 | 0/100 | 100/100 | 144,962 / 289 / 0 | 0 | 36.5568% |
123
+ | WebP Q80 | 0/100 | 0/100 | 100/100 | 1,097,350 / 0 / 0 | 0 | 37.6701% |
124
+ | AVIF Q70 | 0/100 | 0/100 | 100/100 | 445,041 / 59 / 0 | 0 | 39.2740% |
125
+ | JPEG XL d1 | 0/100 | 0/100 | 100/100 | 59,017 / 13 / 0 | 0 | 37.2180% |
126
+
127
+ The lossless WebP payload divided by the PNG payload is
128
+ `0.7572009918694315`. The saving percentages use PNG baseline payload bytes as
129
+ the denominator; Protected High Byte payloads include the high-byte PNG and the
130
+ codec-specific low-byte payload. If an
131
+ archive CSV is absent or differs, the CSV is authoritative and this table must
132
+ not be treated as an additional measurement.
133
+
134
+ ## Main Observations
135
+
136
+ - PNG and WebP lossless completed 100/100 generations.
137
+ - All five lossy raw conditions completed 0/100 generations.
138
+ - JPEG was not uniquely fragile in this matrix: every tested lossy Raw setting
139
+ introduced non-finite fp16 values and was blocked before generation.
140
+ - Finite Repair Zero completed 100/100 only for JPEG Q100; the other four lossy
141
+ conditions recorded non-finite generation-stage failures.
142
+ - Protected High Byte completed 100/100 for all five lossy codecs.
143
+ - The protected rows recorded zero exponent mismatches.
144
+ - The raw diagnostic counts differ substantially across codecs; NaN, +Inf, and
145
+ -Inf are kept as separate fields.
146
+
147
+ ## Discussion
148
+
149
+ Facts are the counts, byte diagnostics, exponent-mismatch counts, and payload
150
+ measurements recorded in the CSV files. They describe this run and do not by
151
+ themselves establish a causal mechanism.
152
+
153
+ A hypothesis consistent with the observations is that the fp16 high byte—which
154
+ contains the sign, exponent, and upper mantissa bits—is substantially more
155
+ important to the recorded model behavior than the lower byte. Protected High
156
+ Byte preserves that high byte while allowing low-byte compression to alter less
157
+ significant bits. The successful protected runs demonstrate the outcome for this
158
+ matrix, but they do not establish the proposed bit-importance mechanism as a
159
+ general causal fact. Protected High Byte is also a hybrid representation, not a
160
+ pure lossy weight artifact. Codec implementation choices, decoder behavior,
161
+ tensor layout, and the MPS runtime may contribute.
162
+
163
+ ## Repository Contents
164
+
165
+ ```text
166
+ images/ Archived figures and representative images
167
+ results/ CSV results, reports, and archive_manifest.json
168
+ samples/ 800 successful sample artifacts for all successful generation rows
169
+ weights/ Archived payloads and weights/manifest.csv
170
+ scripts/cross_codec_report.py Report generation
171
+ scripts/render_visual_tables.py Portable fail-closed visual-table renderer
172
+ scripts/verify_archive.py Hash, byte-count, containment, and symlink verifier
173
+ scripts/pixelmodel_robustness/ 11 packaged robustness modules
174
+ scripts/dit.py Packaged DiT implementation
175
+ scripts/config/ Experiment configuration and prompt manifests
176
+ tests/ Focused codec, repair, report, renderer, and archive tests
177
+ ```
178
+
179
+ ## Reproducibility
180
+
181
+ The full runner may require Apple MPS because that is the archived runtime. The
182
+ following commands are generic and intentionally do not promise universal
183
+ hardware reproducibility.
184
+
185
+ ```bash
186
+ uv sync --locked
187
+ uv run --locked pytest
188
+ PYTHONPATH=scripts uv run --locked python scripts/verify_archive.py --root .
189
+ PYTHONPATH=scripts uv run --locked python scripts/render_visual_tables.py \
190
+ --run-dir . \
191
+ --prompt-ids-manifest results/representative_prompt_ids.json \
192
+ --output scratch/rendered-tables
193
+ ```
194
+
195
+ The complete archived experiment uses the packaged runner and the archived
196
+ configuration. Start with a small smoke test before attempting the full run.
197
+ The full implementation may require MPS and the source assets.
198
+
199
+ ## How to verify/re-run
200
+
201
+ 1. Verify the archive before reading results:
202
+
203
+ ```bash
204
+ PYTHONPATH=scripts uv run --locked python scripts/verify_archive.py --root .
205
+ ```
206
+
207
+ 2. Run the focused tests:
208
+
209
+ ```bash
210
+ uv run --locked pytest
211
+ ```
212
+
213
+ 3. Inspect the packaged report and experiment command surfaces:
214
+
215
+ ```bash
216
+ PYTHONPATH=scripts uv run --locked python scripts/cross_codec_report.py --help
217
+ PYTHONPATH=scripts uv run --locked python -m pixelmodel_robustness.cross_codec_experiment --help
218
+ ```
219
+
220
+ 4. For a fresh source checkout, obtain the upstream assets at the exact
221
+ revision. This command is a prerequisite only; it does not alter this
222
+ archive:
223
+
224
+ ```bash
225
+ hf download bench-labs/PixelModel-v4 \
226
+ --revision 80878fdd6e130d229c2581424a3456b47b979d4b
227
+ ```
228
+
229
+ 5. Use the packaged runner's `--help` output to select the input paths and
230
+ output run directory, then run on a machine with the required model runtime.
231
+ Preserve the runner manifest, encoded payloads, materialized weight images,
232
+ samples, resource log, and raw rows together. `samples/` contains all 800
233
+ successful sample artifacts, so raw sample provenance is complete even though
234
+ the compact archive intentionally deduplicates payloads. Complete
235
+ report regeneration should target a fresh canonical run directory with
236
+ materialized weight images; the compact archive layout is not sufficient for
237
+ a fully fresh report regeneration.
238
+
239
+ For AVIF, Pillow must have AVIF support. JPEG XL requires an ImageMagick build
240
+ with the libjxl delegate. These codec prerequisites are recorded by the
241
+ experiment where available.
242
+
243
+ ## Weights archive explanation
244
+
245
+ The `weights/` directory is an archive of experiment inputs and codec payloads,
246
+ not a new or fine-tuned model release. `weights/manifest.csv` records the path,
247
+ byte count, and SHA-256 for each listed payload. Git LFS is configured for this
248
+ directory. The archive verifier checks that paths stay inside the repository,
249
+ that listed files exist with the recorded bytes and hashes, that paths are not
250
+ duplicated, and that no symlink is used in the archived trees.
251
+
252
+ ## Limitations
253
+
254
+ - The experiment covers one model version, PixelModel-v4 at the pinned revision.
255
+ - Only the listed codec settings were evaluated; the setting matrix is limited.
256
+ - No result here establishes that one codec is universally superior.
257
+ - The full run uses one fixed prompt/seed/latent/settings protocol and one
258
+ Apple MPS runtime.
259
+ - The results do not establish codec performance for other models, tensor
260
+ layouts, image dimensions, devices, Pillow versions, or libjxl versions.
261
+ - Generation success is a gate outcome, not a quality ranking.
262
+ - No FID result is reported; FID is N/A here.
263
+ - Missing or failed samples are not imputed.
264
+ - The archive does not claim that protected high-byte storage preserves every
265
+ aspect of a model outside the recorded experiment.
266
+ - These observations should not be generalized beyond this experiment without
267
+ additional models, settings, runtimes, and independently specified evaluations.
268
+
269
+ ## Future Work
270
+
271
+ - Perform bit-level importance analysis with pre-registered corruption masks.
272
+ - Evaluate exponent-only corruption.
273
+ - Evaluate mantissa-only corruption at controlled bit positions.
274
+ - Test additional codecs and codec settings.
275
+ - Investigate learned, weight-aware compression methods.
276
+ - Repeat the protocol across additional model revisions, tensor layouts, prompt
277
+ sets, devices, and decoder versions.
278
+
279
+ ## License and acknowledgment
280
+
281
+ This archive is released under the MIT License. It acknowledges
282
+ [bench-labs/PixelModel-v4](https://huggingface.co/bench-labs/PixelModel-v4) and
283
+ its MIT-licensed upstream model card. This repository is an experimental archive
284
+ built from the robustness-study source; it is not the upstream model repository.
pyproject.toml ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "pixelmodel-v4-image-codec-study"
3
+ version = "0.1.0"
4
+ description = "Research archive for PixelModel-v4 weight-image codec robustness experiments"
5
+ requires-python = ">=3.11,<3.12"
6
+ dependencies = [
7
+ "numpy",
8
+ "pillow",
9
+ "pandas",
10
+ "matplotlib",
11
+ "scikit-image",
12
+ "pytest",
13
+ "ruff",
14
+ "torch",
15
+ "diffusers==0.31.0",
16
+ "transformers==4.49.0",
17
+ "safetensors",
18
+ "torchmetrics",
19
+ "torch-fidelity",
20
+ "scipy",
21
+ "accelerate>=1.14.0",
22
+ ]
23
+
24
+ [tool.pytest.ini_options]
25
+ testpaths = ["tests"]
26
+ pythonpath = ["scripts"]
27
+
28
+ [tool.ruff]
29
+ line-length = 120
30
+ target-version = "py311"
31
+ exclude = [
32
+ "scripts/cross_codec_report.py",
33
+ "scripts/dit.py",
34
+ "scripts/pixelmodel_robustness/**",
35
+ "tests/test_cross_codec.py",
36
+ "tests/test_cross_codec_experiment.py",
37
+ "tests/test_cross_codec_report.py",
38
+ "tests/test_jpeg_repair.py",
39
+ ".venv",
40
+ ".pytest_cache",
41
+ ".ruff_cache",
42
+ "scratch",
43
+ ]
samples/avif_q70_protected_high/pm4-060-9ea3ad52.png ADDED
samples/avif_q70_protected_high/pm4-080-78dedcb6.png ADDED
samples/avif_q70_protected_high/pm4-090-c71ebd94.png ADDED
samples/jpeg_q100_repair_zero/pm4-016-fd1eb48d.png ADDED
samples/jpeg_q100_repair_zero/pm4-075-3906d66e.png ADDED
samples/jpeg_q100_repair_zero/pm4-086-90e23232.png ADDED
samples/jpeg_q100_repair_zero/pm4-097-0b860832.png ADDED
samples/jpeg_q80_protected_high/pm4-002-effb6eaa.png ADDED
samples/jpeg_q80_protected_high/pm4-016-fd1eb48d.png ADDED
samples/jpeg_q80_protected_high/pm4-051-093f1478.png ADDED
samples/jpeg_q80_protected_high/pm4-060-9ea3ad52.png ADDED
samples/jpeg_q80_protected_high/pm4-075-3906d66e.png ADDED
samples/jpeg_q80_protected_high/pm4-076-a577a15d.png ADDED
samples/jpeg_q80_protected_high/pm4-078-a77b762e.png ADDED
samples/jpeg_q80_protected_high/pm4-080-78dedcb6.png ADDED
samples/jpeg_q80_protected_high/pm4-082-6adb4a49.png ADDED
samples/jpeg_q80_protected_high/pm4-089-60ad56aa.png ADDED
samples/jpeg_q80_protected_high/pm4-090-c71ebd94.png ADDED
samples/jpeg_q80_protected_high/pm4-097-0b860832.png ADDED
samples/webp_lossless/pm4-002-effb6eaa.png ADDED
samples/webp_lossless/pm4-051-093f1478.png ADDED
samples/webp_lossless/pm4-075-3906d66e.png ADDED
samples/webp_lossless/pm4-082-6adb4a49.png ADDED
samples/webp_lossless/pm4-089-60ad56aa.png ADDED
samples/webp_q80_protected_high/pm4-002-effb6eaa.png ADDED
samples/webp_q80_protected_high/pm4-016-fd1eb48d.png ADDED
samples/webp_q80_protected_high/pm4-051-093f1478.png ADDED
samples/webp_q80_protected_high/pm4-060-9ea3ad52.png ADDED
samples/webp_q80_protected_high/pm4-075-3906d66e.png ADDED
samples/webp_q80_protected_high/pm4-076-a577a15d.png ADDED
samples/webp_q80_protected_high/pm4-078-a77b762e.png ADDED
samples/webp_q80_protected_high/pm4-080-78dedcb6.png ADDED
samples/webp_q80_protected_high/pm4-082-6adb4a49.png ADDED
samples/webp_q80_protected_high/pm4-089-60ad56aa.png ADDED
samples/webp_q80_protected_high/pm4-090-c71ebd94.png ADDED
samples/webp_q80_protected_high/pm4-097-0b860832.png ADDED
tests/test_cross_codec.py ADDED
@@ -0,0 +1,482 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Task 1 cross-codec adapterの契約テスト。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import FrozenInstanceError, replace
6
+ from io import BytesIO
7
+
8
+ import numpy as np
9
+ import pytest
10
+ from PIL import Image
11
+
12
+ from pixelmodel_robustness.cross_codec import (
13
+ CODEC_SPECS,
14
+ CONDITION_IDS,
15
+ CONDITION_REGISTRY,
16
+ CodecSpec,
17
+ ConditionSpec,
18
+ JxlCodecError,
19
+ ProtectedArtifact,
20
+ decode_l_plane,
21
+ decode_protected_high,
22
+ decode_rgb,
23
+ encode_l_plane,
24
+ encode_protected_high,
25
+ encode_rgb,
26
+ preflight_codecs,
27
+ repair_nonfinite_zero,
28
+ semantic_hash,
29
+ )
30
+
31
+
32
+ def rgb_image() -> Image.Image:
33
+ return Image.fromarray(
34
+ np.array(
35
+ [[[0, 1, 2], [20, 40, 60]], [[100, 120, 140], [240, 220, 200]]],
36
+ dtype=np.uint8,
37
+ ),
38
+ "RGB",
39
+ )
40
+
41
+
42
+ def gray_plane() -> np.ndarray:
43
+ return np.arange(16, dtype=np.uint8).reshape(4, 4) * 13
44
+
45
+
46
+ def test_registry_has_exact_order_and_stable_semantic_hash() -> None:
47
+ assert CONDITION_IDS == (
48
+ "png_baseline", "webp_lossless", "jpeg_q100_raw", "jpeg_q100_repair_zero",
49
+ "jpeg_q100_protected_high", "jpeg_q80_raw", "jpeg_q80_repair_zero",
50
+ "jpeg_q80_protected_high", "webp_q80_raw", "webp_q80_repair_zero",
51
+ "webp_q80_protected_high", "avif_q70_raw", "avif_q70_repair_zero",
52
+ "avif_q70_protected_high", "jxl_d1_raw", "jxl_d1_repair_zero",
53
+ "jxl_d1_protected_high",
54
+ )
55
+ assert tuple(CONDITION_REGISTRY) == CONDITION_IDS
56
+ assert semantic_hash(CONDITION_REGISTRY) == semantic_hash(tuple(CONDITION_REGISTRY))
57
+ with pytest.raises(TypeError):
58
+ CONDITION_REGISTRY["new"] = CONDITION_REGISTRY["png_baseline"] # type: ignore[index]
59
+
60
+
61
+ def test_codec_spec_is_immutable_and_options_are_fixed() -> None:
62
+ spec = CODEC_SPECS["jpeg_q80"]
63
+ assert isinstance(spec, CodecSpec)
64
+ assert spec.quality == 80
65
+ assert spec.options["subsampling"] == 0
66
+ with pytest.raises(FrozenInstanceError):
67
+ spec.quality = 99 # type: ignore[misc]
68
+ assert CODEC_SPECS["webp_lossless"].options == {"lossless": True, "exact": True, "method": 6}
69
+ assert CODEC_SPECS["jxl_d1"].quality == 90
70
+ assert CODEC_SPECS["jxl_d1"].metadata["libjxl_distance"] == 1.0
71
+ assert "jxl:distance" not in str(CODEC_SPECS["jxl_d1"].options)
72
+
73
+
74
+ def test_all_codec_options_and_nested_registry_objects_are_immutable() -> None:
75
+ expected = {
76
+ "png": {},
77
+ "webp_lossless": {"lossless": True, "exact": True, "method": 6},
78
+ "jpeg_q100": {"quality": 100, "subsampling": 0, "optimize": False},
79
+ "jpeg_q80": {"quality": 80, "subsampling": 0, "optimize": False},
80
+ "webp_q80": {"quality": 80, "lossless": False, "method": 6, "exact": True},
81
+ "avif_q70": {"quality": 70, "subsampling": "4:4:4", "speed": 6, "range": "full", "codec": "aom", "max_threads": 1, "autotiling": False},
82
+ "jxl_d1": {"quality": 90},
83
+ }
84
+ assert {name: dict(spec.options) for name, spec in CODEC_SPECS.items()} == expected
85
+ assert all(spec.grayscale is True for spec in CODEC_SPECS.values())
86
+ for spec in CODEC_SPECS.values():
87
+ with pytest.raises(TypeError):
88
+ spec.options["quality"] = 1 # type: ignore[index]
89
+ with pytest.raises(TypeError):
90
+ spec.metadata["changed"] = True # type: ignore[index]
91
+ entry = CONDITION_REGISTRY["png_baseline"]
92
+ assert isinstance(entry, ConditionSpec)
93
+ with pytest.raises(FrozenInstanceError):
94
+ entry.mode = "tampered" # type: ignore[misc]
95
+
96
+
97
+ @pytest.mark.parametrize("codec", ("png", "webp_lossless", "jpeg_q100", "jpeg_q80", "webp_q80", "avif_q70"))
98
+ def test_rgb_encode_decode_uses_fixed_contract(codec: str) -> None:
99
+ available = {item.name: item for item in preflight_codecs()}
100
+ if not available[codec].available:
101
+ pytest.skip(available[codec].reason or "codec unavailable")
102
+ payload = encode_rgb(rgb_image(), CODEC_SPECS[codec])
103
+ decoded = decode_rgb(payload, CODEC_SPECS[codec])
104
+ assert isinstance(payload, bytes)
105
+ assert decoded.mode == "RGB"
106
+ assert decoded.size == (2, 2)
107
+ if codec in {"png", "webp_lossless"}:
108
+ np.testing.assert_array_equal(np.asarray(decoded), np.asarray(rgb_image()))
109
+
110
+
111
+ def test_grayscale_plane_round_trip_for_lossless_png() -> None:
112
+ payload = encode_l_plane(gray_plane(), CODEC_SPECS["png"])
113
+ decoded = decode_l_plane(payload, CODEC_SPECS["png"])
114
+ np.testing.assert_array_equal(decoded, gray_plane())
115
+
116
+
117
+ def test_l_plane_adapter_passes_single_channel_image_to_encoder(monkeypatch: pytest.MonkeyPatch) -> None:
118
+ import pixelmodel_robustness.cross_codec as module
119
+
120
+ modes: list[str] = []
121
+ original_save = Image.Image.save
122
+
123
+ def capture_save(self: Image.Image, *args: object, **kwargs: object) -> object:
124
+ modes.append(self.mode)
125
+ return original_save(self, *args, **kwargs)
126
+
127
+ monkeypatch.setattr(Image.Image, "save", capture_save)
128
+ encode_l_plane(gray_plane(), CODEC_SPECS["png"])
129
+ assert modes[-1] == "L"
130
+ assert module.decode_l_plane(encode_l_plane(gray_plane(), CODEC_SPECS["png"]), CODEC_SPECS["png"]).dtype == np.uint8
131
+
132
+
133
+ def test_jxl_l_plane_writes_l_mode_source_png(monkeypatch: pytest.MonkeyPatch) -> None:
134
+ import pixelmodel_robustness.cross_codec as module
135
+
136
+ source_modes: list[str] = []
137
+ seen_argv: list[list[str]] = []
138
+
139
+ def fake_jxl_run(argv: list[str]) -> object:
140
+ seen_argv.append(argv)
141
+ with Image.open(argv[2]) as source:
142
+ source_modes.append(source.mode)
143
+ Image.new("L", (4, 4)).save(argv[-1], format="PNG")
144
+ return type("Completed", (), {"returncode": 0, "stdout": "", "stderr": ""})()
145
+
146
+ monkeypatch.setattr(module, "_jxl_run", fake_jxl_run)
147
+ module._jxl_encode(Image.fromarray(gray_plane(), "L"))
148
+ assert source_modes == ["L"]
149
+ assert seen_argv[0][0:2] == ["-quality", "90"]
150
+ assert seen_argv[0][2].endswith("source.png")
151
+ assert seen_argv[0][3].endswith("payload.jxl")
152
+
153
+
154
+ def test_protected_high_is_exact_and_payload_is_combined_bytes() -> None:
155
+ values = np.array([0.0, -0.0, 1.5, -2.25, 3.125, -4.5], dtype=np.float16)
156
+ artifact = encode_protected_high(values, (2, 3), CODEC_SPECS["jpeg_q80"])
157
+ assert isinstance(artifact, ProtectedArtifact)
158
+ decoded, metadata = decode_protected_high(artifact, (2, 3), values)
159
+ np.testing.assert_array_equal(decoded.view(np.uint16) >> 8, values.view(np.uint16) >> 8)
160
+ assert metadata["decoded_high_exact"] is True
161
+ assert metadata["high_mode"] == metadata["low_mode"] == "L"
162
+ assert metadata["dimensions"] == [2, 3]
163
+ assert metadata["combined_payload_bytes"] == len(artifact.payload)
164
+ assert metadata["combined_payload_sha256"]
165
+ with Image.open(BytesIO(artifact.low_codec_bytes)) as low_image:
166
+ assert metadata["low_mode"] == low_image.mode
167
+ assert metadata["high_encoded_bytes"] == len(artifact.high_png_bytes)
168
+ assert metadata["low_encoded_bytes"] == len(artifact.low_codec_bytes)
169
+ assert metadata["high_encoded_sha256"]
170
+ assert metadata["low_encoded_sha256"]
171
+ assert metadata["decoded_low_sha256"]
172
+ assert metadata["high_dimensions"] == metadata["low_dimensions"] == [2, 3]
173
+
174
+
175
+ @pytest.mark.parametrize("mode", ["RGB", "P"])
176
+ def test_protected_high_rejects_non_l_high_plane(mode: str) -> None:
177
+ values = np.array([0.0, 1.5, -2.25, 3.125, -4.5, 5.0], dtype=np.float16)
178
+ artifact = encode_protected_high(values, (2, 3), CODEC_SPECS["jpeg_q80"])
179
+ high = np.asarray(Image.open(BytesIO(artifact.high_png_bytes)).convert("L"), dtype=np.uint8)
180
+ stream = BytesIO()
181
+ tampered_image = np.stack([high] * 3, axis=-1) if mode == "RGB" else high
182
+ Image.fromarray(tampered_image, mode).save(stream, format="PNG")
183
+ tampered = ProtectedArtifact(stream.getvalue(), artifact.low_codec_bytes, artifact.low_codec)
184
+ with pytest.raises(ValueError, match="high plane mode"):
185
+ decode_protected_high(tampered, (2, 3), values)
186
+
187
+
188
+ def test_protected_high_rejects_high_shape_tamper() -> None:
189
+ values = np.arange(6, dtype=np.float16)
190
+ artifact = encode_protected_high(values, (2, 3), CODEC_SPECS["jpeg_q80"])
191
+ stream = BytesIO()
192
+ Image.fromarray(np.zeros((1, 6), dtype=np.uint8), "L").save(stream, format="PNG")
193
+ tampered = ProtectedArtifact(stream.getvalue(), artifact.low_codec_bytes, artifact.low_codec)
194
+ with pytest.raises(ValueError, match="dimensions"):
195
+ decode_protected_high(tampered, (2, 3), values)
196
+
197
+
198
+ def test_protected_high_zero_pads_to_capacity_and_checks_full_high_plane() -> None:
199
+ values = np.array([1.5, -2.25, 3.125], dtype=np.float16)
200
+ artifact = encode_protected_high(values, (2, 3), CODEC_SPECS["jpeg_q80"])
201
+ decoded, metadata = decode_protected_high(artifact, (2, 3), values)
202
+ expected_high = np.zeros(6, dtype=np.uint16)
203
+ expected_high[:3] = values.view(np.uint16)
204
+ np.testing.assert_array_equal(decoded.view(np.uint16) >> 8, expected_high >> 8)
205
+ assert decoded.size == 6
206
+ assert metadata["source_value_count"] == 3
207
+ with pytest.raises(ValueError, match="capacity"):
208
+ encode_protected_high(np.zeros(7, dtype=np.float16), (2, 3), CODEC_SPECS["jpeg_q80"])
209
+
210
+
211
+ def test_zero_repair_changes_only_nonfinite_fp16_words() -> None:
212
+ raw = np.array([0.0, -0.0, np.nan, np.inf, -np.inf, 2.0], dtype=np.float16)
213
+ result = repair_nonfinite_zero(raw, {"layer": (0, len(raw))})
214
+ assert np.isfinite(result.values).all()
215
+ np.testing.assert_array_equal(result.values.view(np.uint16)[[0, 1, 5]], raw.view(np.uint16)[[0, 1, 5]])
216
+ assert result.repaired_value_count == 3
217
+
218
+
219
+ def test_jxl_failure_preserves_subprocess_diagnostics(monkeypatch: pytest.MonkeyPatch) -> None:
220
+ import pixelmodel_robustness.cross_codec as module
221
+
222
+ def failed_run(*args: object, **kwargs: object) -> object:
223
+ class Completed:
224
+ returncode = 7
225
+ stdout = "ImageMagick 7.1.2"
226
+ stderr = "libjxl unavailable"
227
+
228
+ failed_run.args = args # type: ignore[attr-defined]
229
+ failed_run.kwargs = kwargs # type: ignore[attr-defined]
230
+ return Completed()
231
+
232
+ monkeypatch.setattr(module.subprocess, "run", failed_run)
233
+ with pytest.raises(JxlCodecError, match="returncode=7") as error:
234
+ module._jxl_run(["/tmp/in.png", "/tmp/out.jxl"])
235
+ assert error.value.stderr == "libjxl unavailable"
236
+ assert error.value.argv == ("/etc/profiles/per-user/scratchbrulee/bin/magick", "/tmp/in.png", "/tmp/out.jxl")
237
+ assert failed_run.kwargs["shell"] is False # type: ignore[attr-defined]
238
+
239
+
240
+ def test_jxl_preflight_reports_version_and_argv_without_silent_fallback() -> None:
241
+ result = {item.name: item for item in preflight_codecs()}["jxl_d1"]
242
+ assert isinstance(result.available, bool)
243
+ if result.available:
244
+ assert result.version
245
+ assert result.argv
246
+ assert result.metadata["quality"] == 90
247
+ assert result.metadata["libjxl_distance"] == 1.0
248
+ assert result.metadata["probe_q90_bytes"] > 0
249
+ assert result.metadata["probe_q50_bytes"] > 0
250
+ assert result.metadata["probe_q90_sha256"] != result.metadata["probe_q50_sha256"]
251
+ assert result.metadata["probe_dimensions"] == (8, 8)
252
+ assert result.metadata["probe_q50_dimensions"] == (8, 8)
253
+ assert "ImageMagick" in result.version
254
+ assert result.metadata["imagemagick_full_version"] == result.version
255
+ assert result.metadata["libjxl_delegate_version"] == "0.11.2"
256
+ assert result.metadata["argv_template"] == (
257
+ "/etc/profiles/per-user/scratchbrulee/bin/magick", "-quality", "90", "<source>", "<target>"
258
+ )
259
+ with pytest.raises(TypeError):
260
+ result.metadata["argv_template"][0] = "tampered" # type: ignore[index]
261
+ else:
262
+ assert result.reason
263
+
264
+
265
+ def test_encoded_bytes_are_readable_without_temp_artifact() -> None:
266
+ payload = encode_rgb(rgb_image(), CODEC_SPECS["png"])
267
+ with Image.open(BytesIO(payload)) as image:
268
+ assert image.format == "PNG"
269
+ assert isinstance(payload, bytes)
270
+
271
+
272
+ def test_zero_repair_does_not_mutate_and_preserves_all_finite_fp16_bits() -> None:
273
+ raw = np.array([0.0, -0.0, np.nextafter(np.float16(0), np.float16(1)), np.finfo(np.float16).max, np.nan], dtype=np.float16)
274
+ before = raw.view(np.uint16).copy()
275
+ result = repair_nonfinite_zero(raw, {"layer": (0, len(raw))})
276
+ np.testing.assert_array_equal(raw.view(np.uint16), before)
277
+ np.testing.assert_array_equal(result.values.view(np.uint16)[:4], before[:4])
278
+
279
+
280
+ def test_preflight_diagnostics_are_structured_for_jxl_failure(monkeypatch: pytest.MonkeyPatch) -> None:
281
+ import pixelmodel_robustness.cross_codec as module
282
+
283
+ def failed_run(*args: object, **kwargs: object) -> object:
284
+ return type("Completed", (), {"returncode": 9, "stdout": "version out", "stderr": "format err"})()
285
+
286
+ monkeypatch.setattr(module.subprocess, "run", failed_run)
287
+ result = module._jxl_version()
288
+ assert result.available is False
289
+ assert result.diagnostics == {
290
+ "argv": (module.MAGICK_PATH, "-version"), "stdout": "version out", "stderr": "format err", "returncode": 9,
291
+ }
292
+
293
+
294
+ def test_non_jxl_encode_does_not_run_global_or_jxl_preflight(monkeypatch: pytest.MonkeyPatch) -> None:
295
+ import pixelmodel_robustness.cross_codec as module
296
+
297
+ monkeypatch.setattr(module, "preflight_codecs", lambda: (_ for _ in ()).throw(AssertionError("global preflight")))
298
+ monkeypatch.setattr(module, "_jxl_version", lambda: (_ for _ in ()).throw(AssertionError("JXL probe")))
299
+ payload = encode_rgb(rgb_image(), CODEC_SPECS["png"])
300
+ assert payload.startswith(b"\x89PNG")
301
+
302
+
303
+ def test_avif_raw_decode_is_rgb_when_available() -> None:
304
+ status = {item.name: item for item in preflight_codecs()}["avif_q70"]
305
+ if not status.available:
306
+ pytest.skip(status.reason or "AVIF unavailable")
307
+ decoded = decode_rgb(encode_rgb(rgb_image(), CODEC_SPECS["avif_q70"]), CODEC_SPECS["avif_q70"])
308
+ assert decoded.mode == "RGB"
309
+
310
+
311
+ def test_jxl_preflight_rejects_unparseable_libjxl_version(monkeypatch: pytest.MonkeyPatch) -> None:
312
+ import pixelmodel_robustness.cross_codec as module
313
+
314
+ def fake_run(args: list[str]) -> object:
315
+ if args == ["-version"]:
316
+ return type("Completed", (), {"returncode": 0, "stdout": "ImageMagick Delegates: jxl", "stderr": ""})()
317
+ if args == ["-list", "format"]:
318
+ return type("Completed", (), {"returncode": 8, "stdout": "format out", "stderr": "format err"})()
319
+ raise AssertionError(args)
320
+
321
+ monkeypatch.setattr(module, "_jxl_run", fake_run)
322
+ result = module._jxl_version()
323
+ assert result.available is False
324
+ assert result.reason
325
+ assert result.diagnostics == {
326
+ "argv": (module.MAGICK_PATH, "-list", "format"), "stdout": "format out", "stderr": "format err", "returncode": 8,
327
+ }
328
+
329
+
330
+ def test_protected_high_rejects_l_mode_non_png_formats() -> None:
331
+ values = np.arange(6, dtype=np.float16)
332
+ artifact = encode_protected_high(values, (2, 3), CODEC_SPECS["jpeg_q80"])
333
+ for image_format in ("BMP", "TIFF"):
334
+ stream = BytesIO()
335
+ Image.fromarray(np.zeros((2, 3), dtype=np.uint8), "L").save(stream, format=image_format)
336
+ tampered = ProtectedArtifact(stream.getvalue(), artifact.low_codec_bytes, artifact.low_codec)
337
+ with pytest.raises(ValueError, match="format"):
338
+ decode_protected_high(tampered, (2, 3), values)
339
+
340
+
341
+ def test_protected_low_codec_has_immutable_lossy_allowlist() -> None:
342
+ import pixelmodel_robustness.cross_codec as module
343
+
344
+ assert module.LOSSY_CODEC_NAMES == ("jpeg_q100", "jpeg_q80", "webp_q80", "avif_q70", "jxl_d1")
345
+ values = np.arange(6, dtype=np.float16)
346
+ for name in ("png", "webp_lossless"):
347
+ with pytest.raises(ValueError, match="lossy"):
348
+ encode_protected_high(values, (2, 3), CODEC_SPECS[name])
349
+ artifact = encode_protected_high(values, (2, 3), CODEC_SPECS["jpeg_q80"])
350
+ with pytest.raises(ValueError, match="lossy"):
351
+ decode_protected_high(replace(artifact, low_codec="png"), (2, 3), values)
352
+ with pytest.raises(TypeError):
353
+ module.LOSSY_CODEC_NAMES[0] = "png" # type: ignore[index]
354
+
355
+
356
+ def test_jxl_probe_failure_preserves_probe_diagnostics(monkeypatch: pytest.MonkeyPatch) -> None:
357
+ import pixelmodel_robustness.cross_codec as module
358
+
359
+ def fake_run(args: list[str]) -> object:
360
+ if args == ["-version"]:
361
+ return type("Completed", (), {"returncode": 0, "stdout": "ImageMagick Delegates: jxl", "stderr": "version err"})()
362
+ if args == ["-list", "format"]:
363
+ return type("Completed", (), {"returncode": 0, "stdout": "JXL* rw+ JPEG XL (libjxl 0.11.2)", "stderr": "format err"})()
364
+ raise AssertionError(args)
365
+
366
+ expected = module.JxlCodecError(
367
+ "probe failed", argv=[module.MAGICK_PATH, "-quality", "90", "source", "target"],
368
+ stdout="probe out", stderr="probe err", returncode=13,
369
+ )
370
+ monkeypatch.setattr(module, "_jxl_run", fake_run)
371
+ monkeypatch.setattr(module, "_jxl_encode", lambda *args, **kwargs: (_ for _ in ()).throw(expected))
372
+ result = module._jxl_version()
373
+ assert result.available is False
374
+ assert result.diagnostics["probe"] == {
375
+ "argv": expected.argv, "stdout": expected.stdout, "stderr": expected.stderr, "returncode": expected.returncode,
376
+ }
377
+
378
+
379
+ def test_preflight_diagnostics_are_immutable_for_pillow_results() -> None:
380
+ result = preflight_codecs()[0]
381
+ with pytest.raises(TypeError):
382
+ result.diagnostics["changed"] = True # type: ignore[index]
383
+
384
+
385
+ def test_condition_registry_has_exact_full_semantics() -> None:
386
+ expected = (
387
+ ("png_baseline", "png", "raw", None, False),
388
+ ("webp_lossless", "webp_lossless", "raw", None, False),
389
+ ("jpeg_q100_raw", "jpeg_q100", "raw", None, False),
390
+ ("jpeg_q100_repair_zero", "jpeg_q100", "repair_zero", "zero", False),
391
+ ("jpeg_q100_protected_high", "jpeg_q100", "protected_high", None, True),
392
+ ("jpeg_q80_raw", "jpeg_q80", "raw", None, False),
393
+ ("jpeg_q80_repair_zero", "jpeg_q80", "repair_zero", "zero", False),
394
+ ("jpeg_q80_protected_high", "jpeg_q80", "protected_high", None, True),
395
+ ("webp_q80_raw", "webp_q80", "raw", None, False),
396
+ ("webp_q80_repair_zero", "webp_q80", "repair_zero", "zero", False),
397
+ ("webp_q80_protected_high", "webp_q80", "protected_high", None, True),
398
+ ("avif_q70_raw", "avif_q70", "raw", None, False),
399
+ ("avif_q70_repair_zero", "avif_q70", "repair_zero", "zero", False),
400
+ ("avif_q70_protected_high", "avif_q70", "protected_high", None, True),
401
+ ("jxl_d1_raw", "jxl_d1", "raw", None, False),
402
+ ("jxl_d1_repair_zero", "jxl_d1", "repair_zero", "zero", False),
403
+ ("jxl_d1_protected_high", "jxl_d1", "protected_high", None, True),
404
+ )
405
+ assert tuple((e.condition_id, e.codec, e.mode, e.repair, e.protected) for e in CONDITION_REGISTRY.values()) == expected
406
+
407
+
408
+ def test_protected_encode_decode_do_not_mutate_source_bits() -> None:
409
+ values = np.array([0.0, -0.0, 1.5, -2.25, 3.125, -4.5], dtype=np.float16)
410
+ before = values.view(np.uint16).copy()
411
+ artifact = encode_protected_high(values, (2, 3), CODEC_SPECS["jpeg_q80"])
412
+ decode_protected_high(artifact, (2, 3), values)
413
+ np.testing.assert_array_equal(values.view(np.uint16), before)
414
+
415
+
416
+ def test_expected_formats_and_forged_codec_spec_are_binding() -> None:
417
+ import pixelmodel_robustness.cross_codec as module
418
+
419
+ expected = {
420
+ "png": "PNG", "webp_lossless": "WEBP", "jpeg_q100": "JPEG", "jpeg_q80": "JPEG",
421
+ "webp_q80": "WEBP", "avif_q70": "AVIF", "jxl_d1": "JXL",
422
+ }
423
+ assert dict(module.EXPECTED_FORMAT_BY_CODEC) == expected
424
+ with pytest.raises(TypeError):
425
+ module.EXPECTED_FORMAT_BY_CODEC["png"] = "JPEG" # type: ignore[index]
426
+ forged = replace(CODEC_SPECS["jpeg_q80"], format="PNG")
427
+ with pytest.raises(ValueError, match="semantic"):
428
+ encode_protected_high(np.arange(6, dtype=np.float16), (2, 3), forged)
429
+
430
+
431
+ @pytest.mark.parametrize("codec", ("jpeg_q100", "jpeg_q80", "webp_q80", "avif_q70"))
432
+ def test_non_jxl_decode_l_plane_rejects_payload_format_mismatch(codec: str) -> None:
433
+ png_payload = encode_l_plane(gray_plane(), CODEC_SPECS["png"])
434
+ with pytest.raises(ValueError, match="format"):
435
+ decode_l_plane(png_payload, CODEC_SPECS[codec])
436
+
437
+
438
+ @pytest.mark.parametrize("codec", ("jpeg_q100", "jpeg_q80", "webp_q80", "avif_q70", "jxl_d1"))
439
+ def test_protected_decode_rejects_png_bytes_for_every_lossy_codec(codec: str) -> None:
440
+ values = np.arange(6, dtype=np.float16)
441
+ artifact = encode_protected_high(values, (2, 3), CODEC_SPECS["jpeg_q80"])
442
+ png_payload = encode_l_plane(np.zeros((2, 3), dtype=np.uint8), CODEC_SPECS["png"])
443
+ tampered = replace(artifact, low_codec=codec, low_codec_bytes=png_payload)
444
+ with pytest.raises((ValueError, JxlCodecError)):
445
+ decode_protected_high(tampered, (2, 3), values)
446
+
447
+
448
+ @pytest.mark.parametrize("codec", ("jpeg_q100", "jpeg_q80", "webp_q80", "avif_q70", "jxl_d1"))
449
+ def test_decode_rgb_rejects_png_payload_for_every_lossy_codec(codec: str) -> None:
450
+ png_payload = encode_rgb(rgb_image(), CODEC_SPECS["png"])
451
+ with pytest.raises((ValueError, JxlCodecError)):
452
+ decode_rgb(png_payload, CODEC_SPECS[codec])
453
+
454
+
455
+ def test_verified_preflight_token_skips_jxl_probe(monkeypatch: pytest.MonkeyPatch) -> None:
456
+ import pixelmodel_robustness.cross_codec as module
457
+ token = {"jxl_d1": module.CodecPreflight("jxl_d1", True, "fixture", None, ("fixture",), {})}
458
+ monkeypatch.setattr(module, "_jxl_version", lambda: (_ for _ in ()).throw(AssertionError("probe bypassed")))
459
+ monkeypatch.setattr(module, "_jxl_encode", lambda image: b"jxl-payload")
460
+ monkeypatch.setattr(module, "_jxl_decode", lambda payload: Image.new("RGB", (2, 2)))
461
+ assert module.encode_rgb(rgb_image(), CODEC_SPECS["jxl_d1"], verified_preflight=token) == b"jxl-payload"
462
+ assert module.decode_rgb(b"jxl-payload", CODEC_SPECS["jxl_d1"], verified_preflight=token).mode == "RGB"
463
+
464
+
465
+ def test_verified_preflight_token_rejects_missing_or_unavailable_codec() -> None:
466
+ import pixelmodel_robustness.cross_codec as module
467
+ with pytest.raises(RuntimeError, match="unavailable"):
468
+ module.encode_rgb(rgb_image(), CODEC_SPECS["jxl_d1"], verified_preflight={})
469
+ token = {"jxl_d1": module.CodecPreflight("jxl_d1", False, None, "missing", (), {})}
470
+ with pytest.raises(RuntimeError, match="missing"):
471
+ module.encode_rgb(rgb_image(), CODEC_SPECS["jxl_d1"], verified_preflight=token)
472
+
473
+
474
+ def test_decode_uses_canonical_format_for_forged_and_unknown_specs() -> None:
475
+ png_payload = encode_rgb(rgb_image(), CODEC_SPECS["png"])
476
+ forged = replace(CODEC_SPECS["jpeg_q80"], format="PNG")
477
+ unknown = CodecSpec("unknown_codec", "PNG", None, {}, {})
478
+ for spec in (forged, unknown):
479
+ with pytest.raises(ValueError, match="canonical|unknown"):
480
+ decode_rgb(png_payload, spec)
481
+ with pytest.raises(ValueError, match="canonical|unknown"):
482
+ decode_l_plane(png_payload, spec)
tests/test_cross_codec_experiment.py ADDED
@@ -0,0 +1,552 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Cross-codec Task 2 runnerの厳格TDD契約。"""
2
+ from __future__ import annotations
3
+
4
+ import hashlib
5
+ import json
6
+ from argparse import Namespace
7
+ from pathlib import Path
8
+
9
+ import numpy as np
10
+ import pytest
11
+ from PIL import Image
12
+
13
+ import pixelmodel_robustness.cross_codec as codecs
14
+ from pixelmodel_robustness.prompts import CATEGORIES
15
+
16
+
17
+ @pytest.fixture
18
+ def fixture_inputs(tmp_path: Path) -> dict[str, Path]:
19
+ values = np.arange(16, dtype=np.float16)
20
+ pixels = np.zeros((4, 4, 3), dtype=np.uint8)
21
+ bits = values.view(np.uint16)
22
+ pixels.reshape(-1, 3)[:, 0] = (bits >> 8).astype(np.uint8)
23
+ pixels.reshape(-1, 3)[:, 1] = bits.astype(np.uint8)
24
+ image = tmp_path / "model.png"
25
+ Image.fromarray(pixels, "RGB").save(image)
26
+ manifest = tmp_path / "model_png.json"
27
+ manifest.write_text(json.dumps({"total_parameters": 16, "params": [{"name": "a", "numel": 8}, {"name": "b", "numel": 8}]}), encoding="utf-8")
28
+ config = tmp_path / "config.json"
29
+ config.write_text(json.dumps({"architecture": "fixture"}), encoding="utf-8")
30
+ model = tmp_path / "model.safetensors"
31
+ model.write_bytes(b"fixture")
32
+ prompts = tmp_path / "prompts.json"
33
+ rows = []
34
+ for index, category in enumerate(CATEGORIES):
35
+ rows.append({"prompt_id": f"first-{category}", "category": category, "prompt": f"first {category}", "seed": index, "initial_latent_seed": index})
36
+ for index in range(92):
37
+ category = CATEGORIES[index % len(CATEGORIES)]
38
+ rows.append({"prompt_id": f"p-{index}", "category": category, "prompt": f"prompt {index}", "seed": 100 + index, "initial_latent_seed": 100 + index})
39
+ prompts.write_text(json.dumps(rows), encoding="utf-8")
40
+ return {"image": image, "manifest": manifest, "config": config, "model": model, "prompts": prompts}
41
+
42
+
43
+ def make_args(inputs: dict[str, Path], output: Path, **overrides: object) -> Namespace:
44
+ values = {"profile": "pilot", "image": str(inputs["image"]), "manifest": str(inputs["manifest"]), "config": str(inputs["config"]), "model": str(inputs["model"]), "prompts_manifest": str(inputs["prompts"]), "prompts": 8, "steps": 50, "cfg": 6.0, "device": "mps", "output": str(output), "conditions": "", "recover_lock": False, "fixture": True, "fake_runtime": False, "vae": "vae", "clip": "clip", "pilot_manifest": None}
45
+ values.update(overrides)
46
+ return Namespace(**values)
47
+
48
+
49
+ def preflight() -> tuple[codecs.CodecPreflight, ...]:
50
+ return tuple(codecs.CodecPreflight(name, True, "fixture", None, ("fixture", name), {"fixture": True}) for name in codecs.CODEC_SPECS)
51
+
52
+
53
+ def payload_factory(image: Image.Image, spec: codecs.CodecSpec) -> tuple[bytes, Image.Image]:
54
+ from io import BytesIO
55
+ stream = BytesIO()
56
+ image.convert("RGB").save(stream, format="PNG")
57
+ payload = stream.getvalue()
58
+ return payload, Image.open(BytesIO(payload)).convert("RGB")
59
+
60
+
61
+ class Runtime:
62
+ def generate(self, prompt: str, seed: int) -> tuple[Image.Image, float]:
63
+ return Image.new("RGB", (4, 4), seed % 255), 0.5
64
+
65
+
66
+ def runtime_factory(args: Namespace, device: str) -> tuple[object, object]:
67
+ return (lambda path: object()), Runtime()
68
+
69
+
70
+ def test_pilot_selection_is_category_order_and_full_is_exact() -> None:
71
+ from pixelmodel_robustness.cross_codec_experiment import select_prompts
72
+ prompts = [{"prompt_id": f"{category}-{index}-{duplicate}", "category": category, "prompt": f"{category}-{index}-{duplicate}", "seed": index, "initial_latent_seed": index} for index, category in enumerate(CATEGORIES) for duplicate in range(2)]
73
+ selected = select_prompts(prompts, "pilot")
74
+ assert [item["prompt_id"] for item in selected] == [next(item["prompt_id"] for item in prompts if item["category"] == category) for category in CATEGORIES]
75
+ with pytest.raises(ValueError, match="exactly 100"):
76
+ select_prompts(prompts, "full")
77
+
78
+
79
+ def test_cli_contract_rejects_before_output(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
80
+ from pixelmodel_robustness.cross_codec_experiment import build_parser, run
81
+ args = build_parser().parse_args(["--profile", "pilot", "--image", str(fixture_inputs["image"]), "--manifest", str(fixture_inputs["manifest"]), "--config", str(fixture_inputs["config"]), "--model", str(fixture_inputs["model"]), "--prompts-manifest", str(fixture_inputs["prompts"]), "--output", str(tmp_path / "out"), "--prompts", "7"])
82
+ with pytest.raises(ValueError, match="8"):
83
+ run(args)
84
+ assert not Path(args.output).exists()
85
+
86
+
87
+ def test_fixture_e2e_has_complete_rows_and_artifacts(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
88
+ from pixelmodel_robustness.cross_codec_experiment import run
89
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
90
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
91
+ weights = [row for row in rows if row["row_type"] == "weight"]
92
+ layers = [row for row in rows if row["row_type"] == "layer"]
93
+ generations = [row for row in rows if row["row_type"] == "generation"]
94
+ assert len(weights) == 17 and len(layers) == 34 and len(generations) == 136
95
+ assert all(row["attempted"] and row["completed"] and row["success"] for row in generations if not row["blocked"])
96
+ assert all((result / row["sample_path"]).is_file() and row["sample_bytes"] == (result / row["sample_path"]).stat().st_size and row["sample_hash"] == hashlib.sha256((result / row["sample_path"]).read_bytes()).hexdigest() for row in generations if row["success"])
97
+ baseline = next(row for row in weights if row["condition"] == "png_baseline")
98
+ assert (result / baseline["materialized"]["path"]).read_bytes() == fixture_inputs["image"].read_bytes()
99
+ assert json.loads((result / "pilot_gate.json").read_text())["pass"] is True
100
+
101
+
102
+ def test_save_sample_supports_pil_chw_and_rejects_nonfinite(tmp_path: Path) -> None:
103
+ from pixelmodel_robustness.cross_codec_experiment import _save_sample
104
+ class Tensor:
105
+ def __init__(self, value: np.ndarray): self.value = value
106
+ def detach(self): return self
107
+ def cpu(self): return self
108
+ def clamp(self, low: float, high: float): return Tensor(np.clip(self.value, low, high))
109
+ def permute(self, *axes: int): return Tensor(np.transpose(self.value, axes))
110
+ def numpy(self): return self.value
111
+ path = tmp_path / "nested" / "sample.png"
112
+ artifact = _save_sample(Tensor(np.ones((3, 4, 4), dtype=np.float32)), path, base=tmp_path)
113
+ assert path.is_file() and artifact["sha256"] == hashlib.sha256(path.read_bytes()).hexdigest()
114
+ with pytest.raises((ValueError, FloatingPointError)):
115
+ _save_sample(Tensor(np.full((3, 4, 4), np.nan, dtype=np.float32)), tmp_path / "bad.png", base=tmp_path)
116
+
117
+
118
+ def test_loader_called_once_per_condition_and_baseline_path_exists(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
119
+ from pixelmodel_robustness.cross_codec_experiment import run
120
+ calls: list[str] = []
121
+ def loader(path: str) -> object:
122
+ calls.append(path)
123
+ assert Path(path).is_file()
124
+ return object()
125
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=lambda a, d: (loader, Runtime()))
126
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
127
+ nonblocked = {row["condition"] for row in rows if row["row_type"] == "weight" and not row["blocked"]}
128
+ assert len(calls) == len(nonblocked)
129
+ assert any(path.endswith("png_baseline.png") for path in calls)
130
+
131
+
132
+ def test_model_loader_failure_is_one_attempt_and_gate_fails(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
133
+ from pixelmodel_robustness.cross_codec_experiment import run
134
+ calls: list[str] = []
135
+ def loader(path: str) -> object:
136
+ calls.append(path)
137
+ raise ValueError("load failed")
138
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=lambda a, d: (loader, Runtime()))
139
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
140
+ assert len(calls) == 17
141
+ assert all(not row["attempted"] and row["blocked"] and row["failure_stage"] == "model_load" and row["sample_path"] is None for row in rows if row["row_type"] == "generation")
142
+ assert json.loads((result / "pilot_gate.json").read_text())["pass"] is False
143
+
144
+
145
+ def test_raw_block_repair_count_and_shared_payload(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
146
+ from pixelmodel_robustness.cross_codec_experiment import run
147
+ def candidate(condition: str, values: np.ndarray) -> np.ndarray:
148
+ result = values.copy()
149
+ if condition == "jpeg_q100_raw": result[:3] = [np.nan, np.inf, -np.inf]
150
+ if condition == "jpeg_q80_raw": result[:3] = [np.nan, np.inf, -np.inf]
151
+ return result
152
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory, candidate_factory=candidate)
153
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
154
+ weights = {row["condition"]: row for row in rows if row["row_type"] == "weight"}
155
+ assert weights["jpeg_q100_raw"]["blocked"] is True
156
+ assert weights["jpeg_q100_repair_zero"]["repaired_count"] == 3
157
+ assert weights["jpeg_q100_raw"]["payload_sha256"] == weights["jpeg_q100_repair_zero"]["payload_sha256"]
158
+
159
+
160
+ def test_payload_storage_metrics_and_protected_artifacts(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
161
+ from pixelmodel_robustness.cross_codec_experiment import run
162
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
163
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
164
+ weights = {row["condition"]: row for row in rows if row["row_type"] == "weight"}
165
+ for row in weights.values():
166
+ assert {"payload_bytes", "payload_over_png", "png_over_payload", "size_saving_percent"} <= row.keys()
167
+ protected = weights["jpeg_q100_protected_high"]
168
+ assert {"high", "low"} <= protected["protected"].keys()
169
+ assert protected["payload_bytes"] == protected["protected"]["high"]["bytes"] + protected["protected"]["low"]["bytes"]
170
+
171
+
172
+ def test_strict_rows_and_condition_completion_reject_tamper(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
173
+ from pixelmodel_robustness.cross_codec_experiment import condition_complete, load_rows_strict, run
174
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
175
+ manifest = json.loads((result / "manifest.json").read_text())
176
+ rows = load_rows_strict(result / "results" / "raw_rows.jsonl", manifest["run_identity_hash"])
177
+ sample = next(row for row in rows if row["row_type"] == "generation" and row["success"])
178
+ (result / sample["sample_path"]).write_bytes(b"tampered")
179
+ assert condition_complete(rows, sample["condition"], set(manifest["prompt_ids"]), {"a", "b"}, result) is False
180
+ with pytest.raises(ValueError, match="identity"):
181
+ load_rows_strict(result / "results" / "raw_rows.jsonl", "wrong")
182
+
183
+
184
+ def test_strict_rows_reject_duplicate_canonical_identity(tmp_path: Path) -> None:
185
+ from pixelmodel_robustness.cross_codec_experiment import load_rows_strict
186
+ path = tmp_path / "rows.jsonl"
187
+ row = {"row_type": "weight", "stage": "weight", "condition": "png_baseline", "prompt_id": None, "run_identity_hash": "identity"}
188
+ path.write_text(json.dumps(row) + "\n" + json.dumps(row) + "\n", encoding="utf-8")
189
+ with pytest.raises(ValueError, match="duplicate"):
190
+ load_rows_strict(path, "identity")
191
+
192
+
193
+ def test_resume_skips_completed_and_rejects_completed_resume(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
194
+ from pixelmodel_robustness.cross_codec_experiment import run
195
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
196
+ args = make_args(fixture_inputs, result)
197
+ with pytest.raises(ValueError, match="completed"):
198
+ run(args, preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
199
+
200
+
201
+ def test_full_gate_validation_rejects_tampered_gate_before_output(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
202
+ from pixelmodel_robustness.cross_codec_experiment import run
203
+ pilot = run(make_args(fixture_inputs, tmp_path / "pilot"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
204
+ gate = pilot / "pilot_gate.json"
205
+ value = json.loads(gate.read_text())
206
+ value["prompt_ids"] = ["tampered"]
207
+ gate.write_text(json.dumps(value), encoding="utf-8")
208
+ args = make_args(fixture_inputs, tmp_path / "full", profile="full", prompts=100, fixture=False, pilot_manifest=str(gate))
209
+ with pytest.raises(ValueError, match="pilot gate"):
210
+ run(args, preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
211
+ assert not Path(args.output).exists()
212
+
213
+
214
+ def test_invalid_prompt_category_and_duplicate_ids_rejected_before_output(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
215
+ from pixelmodel_robustness.cross_codec_experiment import run
216
+ prompts = json.loads(fixture_inputs["prompts"].read_text())
217
+ prompts[0]["category"] = "invalid"
218
+ fixture_inputs["prompts"].write_text(json.dumps(prompts), encoding="utf-8")
219
+ with pytest.raises(ValueError, match="category"):
220
+ run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight)
221
+
222
+
223
+ def test_preflight_identity_order_and_duplicates_rejected(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
224
+ from pixelmodel_robustness.cross_codec_experiment import run
225
+ statuses = list(preflight())
226
+ statuses[0], statuses[1] = statuses[1], statuses[0]
227
+ with pytest.raises(RuntimeError, match="preflight"):
228
+ run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=lambda: tuple(statuses))
229
+
230
+
231
+ def test_resource_sample_is_measured_and_three_violation_guard(fixture_inputs: dict[str, Path], tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
232
+ from pixelmodel_robustness import cross_codec_experiment as experiment
233
+ snapshot = experiment.sample_resource(tmp_path)
234
+ assert snapshot["rss_bytes"] > 0 and snapshot["system_available_percent"] > 0 and snapshot["disk_free_bytes"] > 0
235
+ monkeypatch.setattr(experiment, "sample_resource", lambda output: {"rss_bytes": 13 * 1024**3, "system_available_percent": 5.0, "disk_free_bytes": 1})
236
+ with pytest.raises(experiment.ResourceGuardError):
237
+ experiment.run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight)
238
+ assert not (tmp_path / "out").exists()
239
+
240
+
241
+ def test_generation_failure_has_no_fake_sample(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
242
+ from pixelmodel_robustness.cross_codec_experiment import run
243
+ class Failing(Runtime):
244
+ def generate(self, prompt: str, seed: int): raise FloatingPointError("nonfinite image")
245
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=lambda a, d: (lambda path: object(), Failing()))
246
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
247
+ assert all(not row["success"] and row["sample_path"] is None and row["clip_score"] is None and row["first_error"] for row in rows if row["row_type"] == "generation")
248
+
249
+
250
+ def test_generation_row_schema_and_layer_rows_have_no_prompt_hack(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
251
+ from pixelmodel_robustness.cross_codec_experiment import run
252
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
253
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
254
+ generation = next(row for row in rows if row["row_type"] == "generation")
255
+ assert {"category", "prompt", "seed", "initial_latent_seed", "attempt_count", "completed", "elapsed_seconds", "failure_stage", "failure_class", "first_error", "sample_path", "sample_hash", "sample_bytes"} <= generation.keys()
256
+ assert all(not str(row.get("prompt_id", "")).startswith("layer:") for row in rows if row["row_type"] == "layer")
257
+
258
+
259
+ def test_full_fixture_gate_binding_unit_does_not_create_gate(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
260
+ from pixelmodel_robustness.cross_codec_experiment import run
261
+ pilot = run(make_args(fixture_inputs, tmp_path / "pilot"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
262
+ gate = pilot / "pilot_gate.json"
263
+ args = make_args(fixture_inputs, tmp_path / "full", profile="full", prompts=100, fixture=False, pilot_manifest=str(gate))
264
+ with pytest.raises(ValueError):
265
+ run(args, preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
266
+ assert not (Path(args.output) / "pilot_gate.json").exists()
267
+
268
+
269
+ def test_preflight_unavailable_fails_before_output(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
270
+ from pixelmodel_robustness.cross_codec_experiment import run
271
+ def unavailable() -> tuple[codecs.CodecPreflight, ...]:
272
+ return tuple(codecs.CodecPreflight(name, name != "avif_q70", "fixture", None if name != "avif_q70" else "missing", ("fixture", name), {}) for name in codecs.CODEC_SPECS)
273
+ with pytest.raises(RuntimeError, match="preflight"):
274
+ run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=unavailable)
275
+ assert not (tmp_path / "out").exists()
276
+
277
+
278
+ @pytest.mark.parametrize("artifact_key", ["sample", "payload", "materialized", "protected_high", "protected_low"])
279
+ def test_validate_pilot_gate_rehashes_every_persisted_artifact(fixture_inputs: dict[str, Path], tmp_path: Path, artifact_key: str) -> None:
280
+ from pixelmodel_robustness.cross_codec_experiment import run, validate_pilot_gate
281
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
282
+ rows_path = result / "results" / "raw_rows.jsonl"
283
+ rows = [json.loads(line) for line in rows_path.read_text().splitlines()]
284
+ if artifact_key == "sample":
285
+ target = next(row for row in rows if row["row_type"] == "generation" and row["success"])
286
+ path = result / target["sample_path"]
287
+ elif artifact_key == "payload":
288
+ target = next(row for row in rows if row["row_type"] == "weight")
289
+ path = result / target["payload"]["path"]
290
+ elif artifact_key == "materialized":
291
+ target = next(row for row in rows if row["row_type"] == "weight" and row["materialized"])
292
+ path = result / target["materialized"]["path"]
293
+ else:
294
+ target = next(row for row in rows if row["row_type"] == "weight" and row["protected"])
295
+ path = result / target["protected"]["high" if artifact_key.endswith("high") else "low"]["path"]
296
+ path.write_bytes(path.read_bytes() + b"tamper")
297
+ with pytest.raises(ValueError, match="pilot gate"):
298
+ validate_pilot_gate(result / "pilot_gate.json")
299
+
300
+
301
+ @pytest.mark.parametrize("status", ["running", "resource_guard_failed"])
302
+ @pytest.mark.parametrize("tree_key", ["payload", "protected", "materialized"])
303
+ def test_resume_revalidates_existing_weight_artifact_tree(fixture_inputs: dict[str, Path], tmp_path: Path, status: str, tree_key: str) -> None:
304
+ from pixelmodel_robustness.cross_codec_experiment import run
305
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
306
+ manifest_path = result / "manifest.json"
307
+ manifest = json.loads(manifest_path.read_text())
308
+ manifest["status"] = status
309
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
310
+ rows_path = result / "results" / "raw_rows.jsonl"
311
+ rows = [json.loads(line) for line in rows_path.read_text().splitlines()]
312
+ weight = next(row for row in rows if row["row_type"] == "weight" and row[tree_key])
313
+ artifact = weight[tree_key]
314
+ if tree_key == "protected":
315
+ artifact = artifact["high"]
316
+ (result / artifact["path"]).write_bytes(b"tampered")
317
+ with pytest.raises(ValueError, match="artifact tamper"):
318
+ run(make_args(fixture_inputs, result, recover_lock=True), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
319
+
320
+
321
+ def test_codec_encode_failure_is_canonical_and_gate_fails(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
322
+ from pixelmodel_robustness.cross_codec_experiment import run
323
+ def failing_payload(image: Image.Image, spec: codecs.CodecSpec) -> tuple[bytes, Image.Image]:
324
+ if spec.name == "jpeg_q80":
325
+ raise OSError("encoder unavailable")
326
+ return payload_factory(image, spec)
327
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=failing_payload, runtime_factory=runtime_factory)
328
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
329
+ failed = [row for row in rows if row["row_type"] == "weight" and row["condition"].startswith("jpeg_q80")]
330
+ assert len(failed) == 3 and all(row["status"] == "codec_pipeline_failed" and row["blocked"] for row in failed)
331
+ assert all(row["failure_stage"] == "encode" for row in rows if row["row_type"] == "generation" and row["condition"].startswith("jpeg_q80"))
332
+ assert json.loads((result / "manifest.json").read_text())["status"] == "completed_with_pipeline_failures"
333
+ assert json.loads((result / "pilot_gate.json").read_text())["pass"] is False
334
+
335
+
336
+ def test_codec_decode_failure_is_canonical_and_gate_fails(fixture_inputs: dict[str, Path], tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
337
+ import pixelmodel_robustness.cross_codec as module
338
+ from pixelmodel_robustness.cross_codec_experiment import run
339
+ original = module.decode_rgb
340
+ def failing_decode(payload: bytes, spec: codecs.CodecSpec, **kwargs: object) -> Image.Image:
341
+ if spec.name == "jpeg_q80":
342
+ raise ValueError("decoder rejected payload")
343
+ return original(payload, spec, **kwargs)
344
+ monkeypatch.setattr(module, "decode_rgb", failing_decode)
345
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, runtime_factory=runtime_factory)
346
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
347
+ failed = [row for row in rows if row["row_type"] == "generation" and row["condition"].startswith("jpeg_q80")]
348
+ assert len(failed) == 8 * 3 and all(not row["attempted"] and row["failure_stage"] == "decode" for row in failed)
349
+ assert json.loads((result / "pilot_gate.json").read_text())["pass"] is False
350
+
351
+
352
+ def test_resource_preflight_is_persisted_once(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
353
+ from pixelmodel_robustness.cross_codec_experiment import run
354
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
355
+ rows = [json.loads(line) for line in (result / "results" / "resource_monitor.jsonl").read_text().splitlines()]
356
+ preflight_rows = [row for row in rows if row["row_type"] == "resource_guard" and row["stage"] == "preflight"]
357
+ assert len(preflight_rows) == 1 and preflight_rows[0]["rss_bytes"] > 0
358
+
359
+
360
+ def test_protected_payload_is_read_back_before_generation(fixture_inputs: dict[str, Path], tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
361
+ import pixelmodel_robustness.cross_codec as module
362
+ from pixelmodel_robustness.cross_codec_experiment import run
363
+ calls = 0
364
+ original = module.decode_protected_high
365
+ def counted(*args: object, **kwargs: object):
366
+ nonlocal calls
367
+ calls += 1
368
+ return original(*args, **kwargs)
369
+ monkeypatch.setattr(module, "decode_protected_high", counted)
370
+ run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
371
+ assert calls == 5
372
+
373
+
374
+ def test_scientific_gate_identity_projection_is_immutable_and_profile_neutral() -> None:
375
+ from pixelmodel_robustness.cross_codec_experiment import SCIENTIFIC_GATE_IDENTITY_KEYS, scientific_identity_hash
376
+ assert isinstance(SCIENTIFIC_GATE_IDENTITY_KEYS, tuple)
377
+ base = {key: f"value-{key}" for key in SCIENTIFIC_GATE_IDENTITY_KEYS}
378
+ base["mode"] = "real"
379
+ pilot = {**base, "profile": "pilot", "prompt_ids": ["p1"], "prompt_selection_hash": "pilot", "completed_at": "old"}
380
+ full = {**base, "profile": "full", "prompt_ids": ["p1", "p2"], "prompt_selection_hash": "full", "completed_at": "new"}
381
+ assert scientific_identity_hash(pilot) == scientific_identity_hash(full)
382
+ changed = {**full, "code_hashes": "tampered"}
383
+ assert scientific_identity_hash(full) != scientific_identity_hash(changed)
384
+
385
+
386
+ def test_manifest_binds_jpeg_repair_module_hash_to_run_identity(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
387
+ from pixelmodel_robustness import jpeg_repair
388
+ from pixelmodel_robustness.cross_codec_experiment import run, scientific_identity_hash, sha256_file
389
+
390
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
391
+ manifest = json.loads((result / "manifest.json").read_text())
392
+ expected = sha256_file(jpeg_repair.__file__)
393
+
394
+ assert manifest["run_identity"]["code_hashes"]["jpeg_repair"] == expected
395
+ assert manifest["scientific_identity_hash"] == scientific_identity_hash(manifest["run_identity"])
396
+ changed = {**manifest["run_identity"], "code_hashes": {**manifest["run_identity"]["code_hashes"], "jpeg_repair": "tampered"}}
397
+ assert scientific_identity_hash(changed) != manifest["scientific_identity_hash"]
398
+
399
+
400
+ def test_webp_lossless_pixel_mismatch_is_pipeline_failure(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
401
+ from pixelmodel_robustness.cross_codec_experiment import run
402
+ def mismatching_payload(image: Image.Image, spec: codecs.CodecSpec) -> tuple[bytes, Image.Image]:
403
+ payload, decoded = payload_factory(image, spec)
404
+ if spec.name == "webp_lossless":
405
+ decoded = decoded.copy()
406
+ decoded.putpixel((0, 0), (255, 0, 0))
407
+ return payload, decoded
408
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=mismatching_payload, runtime_factory=runtime_factory)
409
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
410
+ affected = [row for row in rows if row["condition"] == "webp_lossless"]
411
+ assert len([row for row in affected if row["row_type"] == "weight"]) == 1
412
+ assert all(row["failure_stage"] == "decode_invariant" for row in affected)
413
+ assert json.loads((result / "manifest.json").read_text())["status"] == "completed_with_pipeline_failures"
414
+ assert json.loads((result / "pilot_gate.json").read_text())["pass"] is False
415
+
416
+
417
+ def test_protected_decode_failure_is_condition_local(fixture_inputs: dict[str, Path], tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
418
+ import pixelmodel_robustness.cross_codec as module
419
+ from pixelmodel_robustness.cross_codec_experiment import run
420
+ original = module.decode_protected_high
421
+ def failing_decode(artifact: object, shape: object, values: object, **kwargs: object):
422
+ if getattr(artifact, "low_codec", None) == "jpeg_q80":
423
+ raise RuntimeError("protected decoder failed")
424
+ return original(artifact, shape, values, **kwargs)
425
+ monkeypatch.setattr(module, "decode_protected_high", failing_decode)
426
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
427
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
428
+ failed_weights = [row for row in rows if row["row_type"] == "weight" and row["status"] == "codec_pipeline_failed"]
429
+ assert [row["condition"] for row in failed_weights] == ["jpeg_q80_protected_high"]
430
+ assert all(row["failure_stage"] == "protected_invariant" for row in failed_weights)
431
+ assert json.loads((result / "pilot_gate.json").read_text())["pass"] is False
432
+
433
+
434
+ def test_incomplete_failed_generation_rejects_any_sample_artifact_field(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
435
+ from pixelmodel_robustness.cross_codec_experiment import condition_complete, load_rows_strict, run
436
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
437
+ manifest = json.loads((result / "manifest.json").read_text())
438
+ rows = load_rows_strict(result / "results" / "raw_rows.jsonl", manifest["run_identity_hash"])
439
+ target = next(row for row in rows if row["row_type"] == "generation")
440
+ target["success"] = False
441
+ target["attempted"] = True
442
+ target["completed"] = True
443
+ target["failure_stage"] = "generation"
444
+ target["sample_bytes"] = 1
445
+ assert condition_complete(rows, target["condition"], set(manifest["prompt_ids"]), set(manifest["layer_ids"]), result) is False
446
+
447
+
448
+ def test_completed_manifest_records_raw_rows_bytes(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
449
+ from pixelmodel_robustness.cross_codec_experiment import run
450
+
451
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
452
+ manifest = json.loads((result / "manifest.json").read_text())
453
+ raw = result / "results" / "raw_rows.jsonl"
454
+ assert manifest["raw_rows_bytes"] == raw.stat().st_size
455
+
456
+
457
+ def test_resource_monitor_is_bound_and_gate_rejects_resource_tamper(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
458
+ from pixelmodel_robustness.cross_codec_experiment import run, validate_pilot_gate
459
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
460
+ manifest = json.loads((result / "manifest.json").read_text())
461
+ metadata = manifest["resource_monitor"]
462
+ assert metadata["binding_method"] == "run_completion" and metadata["bytes"] > 0 and metadata["sha256"]
463
+ resource = result / metadata["path"]
464
+ resource.write_bytes(resource.read_bytes() + b'{}\n')
465
+ with pytest.raises(ValueError, match="pilot gate|resource"):
466
+ validate_pilot_gate(result / "pilot_gate.json")
467
+
468
+
469
+ def test_resource_monitor_migration_preserves_data_and_is_idempotent(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
470
+ from pixelmodel_robustness.cross_codec_experiment import (
471
+ bind_completed_resource_monitor,
472
+ run,
473
+ validate_pilot_gate,
474
+ validate_resource_monitor,
475
+ )
476
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
477
+ manifest_path = result / "manifest.json"
478
+ manifest = json.loads(manifest_path.read_text())
479
+ original_identity = {key: manifest[key] for key in ("source_sha256", "run_identity", "run_identity_hash", "scientific_identity_hash")}
480
+ manifest.pop("resource_monitor")
481
+ manifest["mode"] = "real"
482
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
483
+ tracked = [result / "results" / "raw_rows.jsonl", result / "results" / "resource_monitor.jsonl"]
484
+ tracked += [path for path in result.rglob("*") if path.is_file() and ("payloads" in path.parts or "samples" in path.parts)]
485
+ before = {str(path.relative_to(result)): (path.stat().st_size, hashlib.sha256(path.read_bytes()).hexdigest()) for path in tracked}
486
+ bind_completed_resource_monitor(result, fixture_inputs["image"])
487
+ bind_completed_resource_monitor(result, fixture_inputs["image"])
488
+ after = {str(path.relative_to(result)): (path.stat().st_size, hashlib.sha256(path.read_bytes()).hexdigest()) for path in tracked}
489
+ updated = json.loads(manifest_path.read_text())
490
+ assert before == after
491
+ assert {key: updated[key] for key in original_identity} == original_identity
492
+ assert updated["resource_monitor"]["binding_method"] == "post_run_verified"
493
+ gate_data = validate_pilot_gate(result / "pilot_gate.json")
494
+ assert gate_data["gate"]["resource_monitor"] == updated["resource_monitor"]
495
+ actual = validate_resource_monitor(result, updated, [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()])
496
+ assert all(updated["resource_monitor"][key] == actual[key] for key in actual)
497
+
498
+
499
+ def test_migration_gate_rejects_forged_resource_annotations(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
500
+ from pixelmodel_robustness.cross_codec_experiment import (
501
+ _hash,
502
+ bind_completed_resource_monitor,
503
+ run,
504
+ sha256_file,
505
+ validate_pilot_gate,
506
+ )
507
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
508
+ manifest_path = result / "manifest.json"
509
+ manifest = json.loads(manifest_path.read_text())
510
+ manifest["mode"] = "real"
511
+ manifest.pop("resource_monitor")
512
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
513
+ bind_completed_resource_monitor(result, fixture_inputs["image"])
514
+ gate_path = result / "pilot_gate.json"
515
+ gate = json.loads(gate_path.read_text())
516
+ gate["resource_monitor"]["binding_method"] = "unknown"
517
+ gate_path.write_text(json.dumps(gate), encoding="utf-8")
518
+ with pytest.raises(ValueError, match="pilot gate|tampered"):
519
+ validate_pilot_gate(gate_path)
520
+ manifest = json.loads(manifest_path.read_text())
521
+ manifest["resource_monitor"]["binding_method"] = "unknown"
522
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
523
+ gate = json.loads(gate_path.read_text())
524
+ gate["resource_monitor"] = manifest["resource_monitor"]
525
+ gate["manifest_sha256"] = sha256_file(manifest_path)
526
+ gate["gate_hash"] = _hash({key: value for key, value in gate.items() if key != "gate_hash"})
527
+ gate_path.write_text(json.dumps(gate), encoding="utf-8")
528
+ with pytest.raises(ValueError, match="resource|pilot gate"):
529
+ validate_pilot_gate(gate_path)
530
+
531
+
532
+ def test_bound_resource_rejects_invalid_post_run_annotations(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
533
+ from pixelmodel_robustness.cross_codec_experiment import _validate_bound_resource, run, validate_resource_monitor
534
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
535
+ manifest = json.loads((result / "manifest.json").read_text())
536
+ rows = [json.loads(line) for line in (result / "results" / "raw_rows.jsonl").read_text().splitlines()]
537
+ actual = validate_resource_monitor(result, manifest, rows)
538
+ for annotation in ({"bound_at": "not-utc", "binding_code_hash": "a" * 64}, {"bound_at": "2026-01-01T00:00:00+00:00", "binding_code_hash": "A" * 64}):
539
+ recorded = {**actual, "binding_method": "post_run_verified", **annotation}
540
+ with pytest.raises((ValueError, TypeError), match="bound_at|binding_code_hash"):
541
+ _validate_bound_resource(recorded, actual)
542
+
543
+
544
+ def test_resource_monitor_migration_rejects_wrong_source(fixture_inputs: dict[str, Path], tmp_path: Path) -> None:
545
+ from pixelmodel_robustness.cross_codec_experiment import bind_completed_resource_monitor, run
546
+ result = run(make_args(fixture_inputs, tmp_path / "out"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
547
+ manifest_path = result / "manifest.json"
548
+ manifest = json.loads(manifest_path.read_text())
549
+ manifest.pop("resource_monitor")
550
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
551
+ with pytest.raises(ValueError, match="source"):
552
+ bind_completed_resource_monitor(result, tmp_path / "wrong.png")
tests/test_cross_codec_report.py ADDED
@@ -0,0 +1,547 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import csv
4
+ import hashlib
5
+ import json
6
+ from pathlib import Path
7
+ from types import MappingProxyType
8
+ from typing import ClassVar
9
+
10
+ import numpy as np
11
+ import pytest
12
+ from PIL import Image
13
+
14
+ import cross_codec_report as report
15
+ from pixelmodel_robustness import cross_codec
16
+ from pixelmodel_robustness.cross_codec import CONDITION_IDS
17
+ from pixelmodel_robustness.cross_codec_experiment import _hash, scientific_identity_hash, validate_resource_monitor
18
+
19
+
20
+ def _artifact(root: Path, relative: str, data: bytes) -> dict[str, object]:
21
+ path = root / relative
22
+ path.parent.mkdir(parents=True, exist_ok=True)
23
+ path.write_bytes(data)
24
+ return {"path": relative, "bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()}
25
+
26
+
27
+ def _run(tmp_path: Path, *, status: str = "completed", mode: str = "real", prompt_count: int = 2, prompt_projection: str = "base") -> Path:
28
+ run = tmp_path / "run"
29
+ run.mkdir()
30
+ source = np.zeros((4, 4, 3), dtype=np.uint8)
31
+ Image.fromarray(source, "RGB").save(run / "source.png")
32
+ _artifact(run, "source.png", (run / "source.png").read_bytes())
33
+ prompts = [
34
+ {"prompt_id": f"p-{i}", "category": f"cat-{i}", "prompt": f"prompt {i}", "seed": i, "initial_latent_seed": i + 10}
35
+ for i in range(prompt_count)
36
+ ]
37
+ rows: list[dict[str, object]] = []
38
+ for index, condition in enumerate(CONDITION_IDS):
39
+ family = condition.replace("_repair_zero", "_raw").replace("_protected_high", "_raw")
40
+ payload = _artifact(run, f"payloads/{family}.bin", bytes([CONDITION_IDS.index(family) + 1, 2, 3]))
41
+ weight: dict[str, object] = {
42
+ "row_type": "weight", "stage": "weight", "condition": condition, "run_identity_hash": "run-hash",
43
+ "status": "completed", "failure_stage": None, "payload": payload, "protected": None,
44
+ "payload_bytes": payload["bytes"], "payload_sha256": payload["sha256"], "source_bytes": 3,
45
+ "payload_definition": "source payload; protected=high+low; materialized excluded",
46
+ "nan_count": index % 2, "posinf_count": 0, "neginf_count": 0,
47
+ "sign_mismatch_count": index, "exponent_mismatch_count": index * 2, "mantissa_mismatch_count": index * 3,
48
+ "repaired_count": 1 if "repair" in condition else 0, "mse": float(index), "mae": float(index) / 2,
49
+ "cosine": 1.0, "finite_pair_label": "all_elements", "observed": True,
50
+ }
51
+ if "protected_high" in condition:
52
+ high = _artifact(run, f"payloads/{condition}-high.png", b"high")
53
+ low = _artifact(run, f"payloads/{condition}-low.bin", b"low")
54
+ weight["protected"] = {"high": high, "low": low, "bytes": 7, "sha256": hashlib.sha256(b"highlow").hexdigest()}
55
+ weight["payload"] = {"high": high, "low": low, "bytes": 7, "sha256": hashlib.sha256(b"highlow").hexdigest()}
56
+ weight["payload_bytes"] = 7
57
+ weight["payload_sha256"] = hashlib.sha256(b"highlow").hexdigest()
58
+ rows.append(weight)
59
+ rows.append({"row_type": "layer", "stage": "layer", "condition": condition, "layer": "layer0", "prompt_id": None, "run_identity_hash": "run-hash", "finite": True, "mse": 0.0, "mae": 0.0, "cosine": 1.0})
60
+ for prompt in prompts:
61
+ success = not (condition == "jpeg_q80_raw" and prompt["prompt_id"] == "p-1")
62
+ sample = None
63
+ score = None
64
+ if success:
65
+ sample_path = f"samples/{condition}/{prompt['prompt_id']}.png"
66
+ sample = _artifact(run, sample_path, b"sample")
67
+ score = 0.5 + index / 100 + int(prompt["seed"]) / 1000
68
+ rows.append({
69
+ "row_type": "generation", "stage": "generation", "condition": condition,
70
+ "prompt_id": prompt["prompt_id"], "category": prompt["category"], "prompt": prompt["prompt"],
71
+ "seed": prompt["seed"], "initial_latent_seed": prompt["initial_latent_seed"],
72
+ "run_identity_hash": "run-hash", "attempted": True, "completed": True,
73
+ "success": success, "blocked": False, "failure_stage": None if success else "generation",
74
+ "first_error": None if success else "CLIP failed", "clip_score": score,
75
+ "sample": sample, "sample_path": sample["path"] if sample else None,
76
+ "sample_hash": sample["sha256"] if sample else None, "sample_bytes": sample["bytes"] if sample else None,
77
+ })
78
+ raw = run / "results" / "raw_rows.jsonl"
79
+ raw.parent.mkdir()
80
+ raw.write_text("".join(json.dumps(row, sort_keys=True) + "\n" for row in rows), encoding="utf-8")
81
+ resource = run / "results" / "resource_monitor.jsonl"
82
+ resource_rows = [{"row_type": "resource_guard", "stage": "preflight", "condition": None, "prompt_id": None, "run_identity_hash": "placeholder", "rss_bytes": 1, "system_available_percent": 90.0, "mps_allocated_bytes": None, "mps_driver_allocated_bytes": None, "violation_reason": None}]
83
+ resource_rows += [{"row_type": "resource", "stage": "resource", "condition": row["condition"], "prompt_id": row["prompt_id"], "run_identity_hash": "placeholder", "rss_bytes": 1, "system_available_percent": 90.0, "mps_allocated_bytes": None, "mps_driver_allocated_bytes": None, "violation_reason": None} for row in rows if row["row_type"] == "generation" and row["attempted"] and not row["blocked"]]
84
+ resource.write_text("".join(json.dumps(row, sort_keys=True) + "\n" for row in resource_rows), encoding="utf-8")
85
+ prompt_ids = [p["prompt_id"] for p in prompts]
86
+ selected_prompts = prompts if prompt_projection == "base" else [{**prompt, "paired_seed": prompt["seed"]} for prompt in prompts]
87
+ prompt_hash = _hash(selected_prompts)
88
+ identity = {"source_sha256": hashlib.sha256((run / "source.png").read_bytes()).hexdigest(), "source_bytes": (run / "source.png").stat().st_size, "model_sha256": None, "config_sha256": "config", "prompt_sha256": "prompts", "upstream_revision": "upstream", "code_hashes": {}, "runtime_git": {}, "runtime_platform": {}, "package_versions": {}, "vae": {}, "clip": {}, "requested_device": "mps", "resolved_device": "mps", "mode": mode, "steps": 50, "cfg": 6.0, "profile": "pilot", "prompt_ids": prompt_ids, "prompt_selection_hash": prompt_hash, "condition_registry_hash": cross_codec.semantic_hash(cross_codec.CONDITION_REGISTRY), "codec_preflight": []}
89
+ run_hash = _hash(identity)
90
+ for row in rows: row["run_identity_hash"] = run_hash
91
+ raw.write_text("".join(json.dumps(row, sort_keys=True) + "\n" for row in rows), encoding="utf-8")
92
+ resource_rows = [{**row, "run_identity_hash": run_hash} for row in resource_rows]
93
+ resource.write_text("".join(json.dumps(row, sort_keys=True) + "\n" for row in resource_rows), encoding="utf-8")
94
+ resource_metadata = validate_resource_monitor(run, {"run_identity_hash": run_hash}, rows)
95
+ manifest = {
96
+ "status": status, "mode": mode, "profile": "pilot", "run_identity": identity,
97
+ "run_identity_hash": run_hash, "scientific_identity_hash": scientific_identity_hash(identity), "raw_rows_sha256": hashlib.sha256(raw.read_bytes()).hexdigest(),
98
+ "raw_rows_bytes": raw.stat().st_size, "source_sha256": identity["source_sha256"], "source_bytes": identity["source_bytes"],
99
+ "condition_registry_hash": cross_codec.semantic_hash(cross_codec.CONDITION_REGISTRY), "conditions": list(CONDITION_IDS), "prompt_ids": prompt_ids, "layer_ids": ["layer0"],
100
+ "bootstrap": {"seed": 20260727, "resamples": 10000}, "prompt_selection_hash": prompt_hash, "resource_monitor": {**resource_metadata, "binding_method": "run_completion"},
101
+ }
102
+ (run / "manifest.json").write_text(json.dumps(manifest, sort_keys=True), encoding="utf-8")
103
+ return run
104
+
105
+
106
+ def _csv(path: Path) -> list[dict[str, str]]:
107
+ with path.open(newline="", encoding="utf-8") as stream:
108
+ return list(csv.DictReader(stream))
109
+
110
+
111
+ def test_condition_registry_is_exactly_ordered() -> None:
112
+ assert len(report.CONDITION_IDS) == 17
113
+ assert report.CONDITION_IDS == CONDITION_IDS
114
+
115
+
116
+ def test_bootstrap_is_sorted_and_known_fixture() -> None:
117
+ pairs = [("p-2", 2.0), ("p-0", 0.0), ("p-1", 1.0)]
118
+ assert report.paired_bootstrap(pairs, seed=1, samples=1000) == report.paired_bootstrap(list(reversed(pairs)), seed=1, samples=1000)
119
+ result = report.paired_bootstrap(pairs, seed=1, samples=1000)
120
+ assert result["n"] == 3 and result["mean_delta"] == 1.0 and result["ci_low"] <= 1.0 <= result["ci_high"]
121
+
122
+
123
+ def test_bootstrap_empty_is_na() -> None:
124
+ assert report.paired_bootstrap([], seed=1, samples=10)["n"] == 0
125
+ assert report.paired_bootstrap([], seed=1, samples=10)["ci_low"] is None
126
+
127
+
128
+ def test_generate_exact_csv_schemas_and_counts(tmp_path: Path) -> None:
129
+ output = report.generate_report(_run(tmp_path), fixture=True)
130
+ assert {p.name for p in output.iterdir()} >= {"codec_conditions.csv", "weight_metrics.csv", "generation_metrics.csv", "storage_metrics.csv", "summary.md", "final_conclusion.md", "index.html", "report_manifest.json"}
131
+ assert len(_csv(output / "codec_conditions.csv")) == len(_csv(output / "weight_metrics.csv")) == len(_csv(output / "storage_metrics.csv")) == 17
132
+ assert len(_csv(output / "generation_metrics.csv")) == 34
133
+ assert list(_csv(output / "codec_conditions.csv")[0]) == list(report.CONDITION_COLUMNS)
134
+
135
+
136
+ def test_failed_clip_is_na_not_zero(tmp_path: Path) -> None:
137
+ output = report.generate_report(_run(tmp_path), fixture=True)
138
+ failed = next(row for row in _csv(output / "generation_metrics.csv") if row["condition_id"] == "jpeg_q80_raw" and row["prompt_id"] == "p-1")
139
+ assert failed["clip_score"] in {"", "N/A"} and failed["success"] == "0"
140
+
141
+
142
+ def test_condition_aggregate_has_fixed_denominator_and_failure_stage(tmp_path: Path) -> None:
143
+ output = report.generate_report(_run(tmp_path), fixture=True)
144
+ summary = _csv(output / "condition_summary.csv")
145
+ row = next(item for item in summary if item["condition_id"] == "jpeg_q80_raw")
146
+ assert row["attempted"] == "2" and row["completed"] == "2" and row["denominator"] == "2" and row["first_failure_stage"] == "generation"
147
+
148
+
149
+ def test_payload_protected_raw_repair_share_and_materialized_exclusion(tmp_path: Path) -> None:
150
+ output = report.generate_report(_run(tmp_path), fixture=True)
151
+ rows = _csv(output / "storage_metrics.csv")
152
+ assert all(row["payload_definition"].startswith("encoded payload") for row in rows)
153
+ assert all(row["payload_bytes"] != "" for row in rows)
154
+ assert report.validate_protected_payload_rows(rows)
155
+
156
+
157
+ def test_grid_has_thirteen_columns_and_q80_grid(tmp_path: Path) -> None:
158
+ output = report.generate_report(_run(tmp_path), fixture=True)
159
+ assert report.GRID_COLUMNS == ("PNG", "JPEG Q100 Raw", "JPEG Q100 Repair", "JPEG Q100 Protected", "WebP Q80 Raw", "WebP Q80 Repair", "WebP Q80 Protected", "AVIF Q70 Raw", "AVIF Q70 Repair", "AVIF Q70 Protected", "JXL d1 Raw", "JXL d1 Repair", "JXL d1 Protected")
160
+ for name in ("generation_comparison_grid.png", "generation_comparison_grid_jpeg_q80.png"):
161
+ assert (output / "plots" / name).is_file()
162
+
163
+
164
+ def test_all_plots_are_decodable_and_nonempty(tmp_path: Path) -> None:
165
+ output = report.generate_report(_run(tmp_path), fixture=True)
166
+ for path in (output / "plots").glob("*.png"):
167
+ with Image.open(path) as image:
168
+ assert image.width >= 400 and image.height >= 200
169
+
170
+
171
+ def test_identity_binds_required_inputs(tmp_path: Path) -> None:
172
+ output = report.generate_report(_run(tmp_path), fixture=True)
173
+ manifest = json.loads((output / "report_manifest.json").read_text())
174
+ for key in ("run_identity_hash", "raw_rows_sha256", "report_code_hash", "condition_registry_hash", "profile", "prompt_selection_hash"):
175
+ assert key in manifest["report_identity"]
176
+
177
+
178
+ def test_same_identity_is_deterministic_except_generated_at(tmp_path: Path) -> None:
179
+ run = _run(tmp_path)
180
+ first = report.generate_report(run, fixture=True)
181
+ before = {str(p.relative_to(first)): p.read_bytes() for p in first.rglob("*") if p.is_file() and p.name != "report_manifest.json"}
182
+ second = report.generate_report(run, fixture=True)
183
+ after = {str(p.relative_to(second)): p.read_bytes() for p in second.rglob("*") if p.is_file() and p.name != "report_manifest.json"}
184
+ assert before == after
185
+
186
+
187
+ def test_identity_mismatch_rejected_without_force(tmp_path: Path) -> None:
188
+ run = _run(tmp_path)
189
+ report.generate_report(run, fixture=True)
190
+ value = json.loads((run / "manifest.json").read_text())
191
+ value["prompt_selection_hash"] = "changed"
192
+ (run / "manifest.json").write_text(json.dumps(value), encoding="utf-8")
193
+ with pytest.raises(ValueError, match="identity|hash"):
194
+ report.generate_report(run, fixture=True)
195
+
196
+
197
+ def test_force_report_allows_replacement(tmp_path: Path) -> None:
198
+ run = _run(tmp_path)
199
+ report.generate_report(run, fixture=True, report_options={"version": "A"})
200
+ assert report.generate_report(run, fixture=True, report_options={"version": "B"}, force_report=True).is_dir()
201
+
202
+
203
+ def test_report_manifest_contains_relative_rehashed_artifacts(tmp_path: Path) -> None:
204
+ output = report.generate_report(_run(tmp_path), fixture=True)
205
+ manifest = json.loads((output / "report_manifest.json").read_text())
206
+ for artifact in manifest["artifacts"]:
207
+ path = output / artifact["path"]
208
+ assert not path.is_absolute() or str(path).startswith(str(output))
209
+ assert path.stat().st_size == artifact["bytes"]
210
+ assert hashlib.sha256(path.read_bytes()).hexdigest() == artifact["sha256"]
211
+
212
+
213
+ def test_raw_tamper_rejected(tmp_path: Path) -> None:
214
+ run = _run(tmp_path)
215
+ (run / "results" / "raw_rows.jsonl").write_text("tampered\n", encoding="utf-8")
216
+ with pytest.raises(ValueError, match="raw"):
217
+ report.generate_report(run, fixture=True)
218
+
219
+
220
+ def test_completed_pipeline_failure_is_rejected(tmp_path: Path) -> None:
221
+ run = _run(tmp_path, status="completed_with_pipeline_failures")
222
+ with pytest.raises(ValueError, match="pipeline|scientific"):
223
+ report.generate_report(run, fixture=True)
224
+
225
+
226
+ def test_fixture_mode_is_not_scientific_conclusion(tmp_path: Path) -> None:
227
+ run = _run(tmp_path, mode="fixture")
228
+ output = report.generate_report(run, fixture=True)
229
+ text = (output / "final_conclusion.md").read_text()
230
+ assert "fixture" in text.lower() and "not final" in text.lower()
231
+
232
+
233
+ def test_summary_and_conclusion_have_observations_questions_and_fid_na(tmp_path: Path) -> None:
234
+ output = report.generate_report(_run(tmp_path), fixture=True)
235
+ summary = (output / "summary.md").read_text()
236
+ conclusion = (output / "final_conclusion.md").read_text()
237
+ assert "Observations" in summary and "Conclusions" not in summary
238
+ assert "Questions" in conclusion and "FID" in conclusion and "N/A" in conclusion
239
+ assert all(f"Question {i}" in conclusion for i in range(1, 7))
240
+
241
+
242
+ def test_weight_map_helper_uses_injected_decoder() -> None:
243
+ values = np.array([0, 1, 2, 3], dtype=np.uint8)
244
+ decoded = report.compute_weight_error_map(values, values + 1, decoder=lambda payload: payload)
245
+ assert decoded.shape == (2, 2) and float(decoded.mean()) == 1.0
246
+
247
+
248
+ def test_missing_sample_is_annotated_not_synthesized(tmp_path: Path) -> None:
249
+ run = _run(tmp_path)
250
+ sample = run / "samples/png_baseline/p-0.png"
251
+ sample.unlink()
252
+ with pytest.raises(ValueError, match="sample|artifact|condition_complete"):
253
+ report.generate_report(run, fixture=True)
254
+
255
+
256
+ def test_cli_parser_has_required_options() -> None:
257
+ parser = report.build_parser()
258
+ args = parser.parse_args(["--run-dir", "run", "--force-report"])
259
+ assert args.run_dir == "run" and args.force_report is True and args.output is None
260
+
261
+
262
+ def test_paired_quality_csv_has_exact_order_and_png_zero(tmp_path: Path) -> None:
263
+ output = report.generate_report(_run(tmp_path), fixture=True)
264
+ rows = _csv(output / "paired_quality_metrics.csv")
265
+ assert [row["condition_id"] for row in rows] == list(CONDITION_IDS)
266
+ assert list(rows[0]) == list(report.PAIRED_COLUMNS)
267
+ assert rows[0]["paired_n"] == "2" and rows[0]["mean_delta"] == "0.0" and rows[0]["ci_low"] == "0.0" and rows[0]["ci_high"] == "0.0"
268
+
269
+
270
+ def test_required_artifact_allowlist_and_public_manifest_verifier(tmp_path: Path) -> None:
271
+ output = report.generate_report(_run(tmp_path), fixture=True)
272
+ assert {item["path"] for item in json.loads((output / "report_manifest.json").read_text())["artifacts"]} == report.REQUIRED_ARTIFACTS
273
+ assert report.verify_report_manifest(output)
274
+
275
+
276
+ def test_report_records_and_rehashes_source_and_resource_provenance(tmp_path: Path) -> None:
277
+ run = _run(tmp_path)
278
+ output = report.generate_report(run, fixture=True)
279
+ manifest = json.loads((output / "report_manifest.json").read_text())
280
+ provenance = manifest["input_provenance"]
281
+ assert provenance["source_sha256"] == json.loads((run / "manifest.json").read_text())["source_sha256"]
282
+ assert provenance["source_bytes"] == json.loads((run / "manifest.json").read_text())["source_bytes"]
283
+ assert "source_path" not in provenance and "source_path" not in manifest["report_identity"]
284
+ assert provenance["baseline_source_path"] == "payloads/png_baseline.bin"
285
+ assert provenance["baseline_source_sha256"] and provenance["baseline_source_bytes"] == 3
286
+ assert provenance["resource_monitor_path"] == "results/resource_monitor.jsonl"
287
+ assert provenance["resource_monitor_sha256"] and provenance["resource_monitor_bytes"] > 0
288
+ assert report.verify_report_manifest(output)
289
+ (run / provenance["baseline_source_path"]).write_bytes(b"tampered")
290
+ assert report.verify_report_manifest(output) is False
291
+
292
+
293
+ def test_storage_ratios_use_baseline_payload_bytes_not_scientific_source_bytes(tmp_path: Path) -> None:
294
+ run = _run(tmp_path)
295
+ manifest_path = run / "manifest.json"
296
+ manifest = json.loads(manifest_path.read_text())
297
+ manifest["source_bytes"] = 10
298
+ manifest_path.write_text(json.dumps(manifest, sort_keys=True), encoding="utf-8")
299
+ rows = [json.loads(line) for line in (run / "results" / "raw_rows.jsonl").read_text().splitlines()]
300
+ target = next(row for row in rows if row.get("row_type") == "weight" and row.get("condition") == "jpeg_q100_raw")
301
+ payload = run / target["payload"]["path"]
302
+ payload.write_bytes(b"123456")
303
+ payload_hash = hashlib.sha256(payload.read_bytes()).hexdigest()
304
+ for row in rows:
305
+ if row.get("row_type") == "weight" and row.get("condition") in {"jpeg_q100_raw", "jpeg_q100_repair_zero"}:
306
+ row["payload_bytes"] = 6
307
+ row["payload_sha256"] = payload_hash
308
+ row["payload"]["bytes"] = 6
309
+ row["payload"]["sha256"] = payload_hash
310
+ raw = run / "results" / "raw_rows.jsonl"
311
+ raw.write_text("".join(json.dumps(row, sort_keys=True) + "\n" for row in rows), encoding="utf-8")
312
+ manifest["raw_rows_sha256"] = hashlib.sha256(raw.read_bytes()).hexdigest()
313
+ manifest["raw_rows_bytes"] = raw.stat().st_size
314
+ manifest_path.write_text(json.dumps(manifest, sort_keys=True), encoding="utf-8")
315
+ output = report.generate_report(run, fixture=True)
316
+ storage = {row["condition_id"]: row for row in _csv(output / "storage_metrics.csv")}
317
+ assert storage["png_baseline"]["source_bytes"] == "3"
318
+ assert storage["png_baseline"]["payload_over_png"] == "1.0"
319
+ assert storage["jpeg_q100_raw"]["payload_over_png"] == "2.0"
320
+ assert storage["jpeg_q100_raw"]["png_over_payload"] == "0.5"
321
+ assert storage["jpeg_q100_raw"]["size_saving_percent"] == "-100.0"
322
+
323
+
324
+ def test_report_rejects_run_dir_as_output(tmp_path: Path) -> None:
325
+ run = _run(tmp_path)
326
+ with pytest.raises(ValueError, match="run directory"):
327
+ report.generate_report(run, run, fixture=True)
328
+
329
+
330
+ def test_task2_fixture_run_integrates_with_report(tmp_path: Path) -> None:
331
+ from test_cross_codec_experiment import fixture_inputs, make_args, payload_factory, preflight, runtime_factory
332
+ (tmp_path / "task2").mkdir(parents=True)
333
+ inputs = fixture_inputs.__wrapped__(tmp_path / "task2")
334
+ from pixelmodel_robustness.cross_codec_experiment import run
335
+ run_dir = run(make_args(inputs, tmp_path / "task2-run"), preflight_factory=preflight, payload_factory=payload_factory, runtime_factory=runtime_factory)
336
+ output = report.generate_report(run_dir, fixture=True)
337
+ assert len(_csv(output / "generation_metrics.csv")) == 17 * 8
338
+
339
+
340
+ def test_actual_exponent_map_is_nonzero_and_plot_calls_helper() -> None:
341
+ source = np.array([0x3C, 0x00, 0, 0], dtype=np.uint8)
342
+ candidate = source.copy(); candidate[0] ^= 0x7C
343
+ mapping = report.compute_exponent_density_map(source, candidate)
344
+ assert float(np.nansum(mapping)) > 0.0
345
+
346
+
347
+ def _rewrite_raw(run: Path, mutator: object) -> None:
348
+ raw = run / "results" / "raw_rows.jsonl"
349
+ rows = [json.loads(line) for line in raw.read_text().splitlines()]
350
+ mutator(rows)
351
+ raw.write_text("".join(json.dumps(row, sort_keys=True) + "\n" for row in rows), encoding="utf-8")
352
+ manifest_path = run / "manifest.json"
353
+ manifest = json.loads(manifest_path.read_text())
354
+ manifest["raw_rows_sha256"] = hashlib.sha256(raw.read_bytes()).hexdigest()
355
+ manifest["raw_rows_bytes"] = raw.stat().st_size
356
+ resource_path = run / "results" / "resource_monitor.jsonl"
357
+ resource_rows = [json.loads(line) for line in resource_path.read_text().splitlines()]
358
+ expected = {(row["condition"], str(row["prompt_id"])) for row in rows if row.get("row_type") == "generation" and row.get("attempted") is True and not row.get("blocked")}
359
+ resource_rows = [row for row in resource_rows if row.get("row_type") == "resource_guard" or (row.get("condition"), str(row.get("prompt_id"))) in expected]
360
+ resource_path.write_text("".join(json.dumps(row, sort_keys=True) + "\n" for row in resource_rows), encoding="utf-8")
361
+ manifest["resource_monitor"] = {**validate_resource_monitor(run, manifest, rows), "binding_method": "run_completion"}
362
+ manifest_path.write_text(json.dumps(manifest, sort_keys=True), encoding="utf-8")
363
+
364
+
365
+ @pytest.mark.parametrize("field", ["payload_bytes", "payload_sha256"])
366
+ def test_top_level_payload_metadata_mismatch_is_rejected(tmp_path: Path, field: str) -> None:
367
+ run = _run(tmp_path)
368
+ rows = [json.loads(line) for line in (run / "results" / "raw_rows.jsonl").read_text().splitlines()]
369
+ weight = next(row for row in rows if row["row_type"] == "weight" and row["condition"] == "jpeg_q100_raw")
370
+ weight[field] = weight[field] + 1 if field == "payload_bytes" else "bad"
371
+ with pytest.raises(ValueError, match="payload metadata"):
372
+ report._verify_payload_contract(run, rows)
373
+
374
+
375
+ def test_protected_nested_payload_mismatch_is_rejected(tmp_path: Path) -> None:
376
+ run = _run(tmp_path)
377
+ rows = [json.loads(line) for line in (run / "results" / "raw_rows.jsonl").read_text().splitlines()]
378
+ weight = next(row for row in rows if row["row_type"] == "weight" and row["condition"] == "jpeg_q100_protected_high")
379
+ weight["payload"]["bytes"] = 6
380
+ with pytest.raises(ValueError, match="payload metadata|protected"):
381
+ report._verify_payload_contract(run, rows)
382
+
383
+
384
+ def test_all_blocked_has_explicit_n_zero_na_text(tmp_path: Path) -> None:
385
+ run = _run(tmp_path)
386
+ def block(rows: list[dict[str, object]]) -> None:
387
+ for row in rows:
388
+ if row.get("row_type") == "generation":
389
+ row.update(success=False, blocked=True, completed=True, clip_score=None, sample=None, sample_path=None, sample_hash=None, sample_bytes=None, failure_stage="blocked")
390
+ _rewrite_raw(run, block)
391
+ output = report.generate_report(run, fixture=True)
392
+ paired = _csv(output / "paired_quality_metrics.csv")
393
+ assert all(row["paired_n"] == "0" and row["mean_delta"] == "" and row["ci_low"] == "" and row["ci_high"] == "" and row["na_reason"] == "no successful finite prompt intersection" for row in paired)
394
+ summary = (output / "summary.md").read_text()
395
+ assert "N/A (no successful finite prompt intersection; N=0)" in summary and "None" not in summary
396
+ assert "None" not in (output / "final_conclusion.md").read_text()
397
+
398
+
399
+ def test_lossless_sample_sha_rates_are_condition_specific(tmp_path: Path) -> None:
400
+ output = report.generate_report(_run(tmp_path), fixture=True)
401
+ rows = _csv(output / "condition_summary.csv")
402
+ by = {row["condition_id"]: row for row in rows}
403
+ assert by["png_baseline"]["sample_sha_match_rate"] == "1.0"
404
+ assert by["webp_lossless"]["sample_sha_match_rate"] == "1.0"
405
+ assert all(by[condition]["sample_sha_match_rate"] == "N/A" for condition in CONDITION_IDS if condition not in {"png_baseline", "webp_lossless"})
406
+
407
+
408
+ def test_hypothesis_status_uses_observed_association_rule() -> None:
409
+ summaries = [{"condition_id": name, "nan_count": 1, "success": 0} for name in ("jpeg_q100_raw", "jpeg_q80_raw", "webp_q80_raw", "avif_q70_raw", "jxl_d1_raw")]
410
+ summaries += [{"condition_id": name, "success": 0} for name in ("jpeg_q100_repair_zero", "jpeg_q80_repair_zero", "webp_q80_repair_zero", "avif_q70_repair_zero", "jxl_d1_repair_zero")]
411
+ summaries += [{"condition_id": name, "success": 1, "exponent_mismatch_count": 0} for name in ("jpeg_q100_protected_high", "jpeg_q80_protected_high", "webp_q80_protected_high", "avif_q70_protected_high", "jxl_d1_protected_high")]
412
+ assert report.hypothesis_status(summaries) == "supported (5/5 associated lossy raw codecs)"
413
+
414
+
415
+ def test_json_normalize_handles_immutable_nested_preflight_metadata() -> None:
416
+ value = MappingProxyType({"dims": (8, 8), "nested": MappingProxyType({"x": 1})})
417
+ assert report._json_normalize(value) == {"dims": [8, 8], "nested": {"x": 1}}
418
+
419
+
420
+ def test_jxl_preflight_json_normalization_invokes_verified_decode(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
421
+ payload = _artifact(tmp_path, "payload.jxl", b"jxl")
422
+ class Preflight:
423
+ name = "jxl_d1"
424
+ version = "1"
425
+ metadata: ClassVar[dict[str, object]] = {"levels": (1, 2)}
426
+ called: dict[str, object] = {}
427
+ monkeypatch.setattr(report.cross_codec, "preflight_codecs", lambda: [Preflight()])
428
+ monkeypatch.setattr(report.cross_codec, "decode_rgb", lambda data, spec, verified_preflight=None: called.update(data=data, verified=verified_preflight) or np.zeros((1, 1, 3), dtype=np.uint8))
429
+ decoded, reason = report._decode_sample_payload(tmp_path, {"payload": payload}, "jxl_d1_raw", {"codec_preflight": [{"name": "jxl_d1", "version": "1", "metadata": {"levels": [1, 2]}}]}, fixture=False)
430
+ assert decoded is not None and reason is None and called["verified"]
431
+
432
+
433
+ def test_jxl_preflight_changed_identity_rejects(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
434
+ payload = _artifact(tmp_path, "payload.jxl", b"jxl")
435
+ class Preflight:
436
+ name = "jxl_d1"
437
+ version = "2"
438
+ metadata: ClassVar[dict[str, object]] = {"levels": (1, 2)}
439
+ monkeypatch.setattr(report.cross_codec, "preflight_codecs", lambda: [Preflight()])
440
+ with pytest.raises(ValueError, match="JXL preflight identity mismatch"):
441
+ report._decode_sample_payload(tmp_path, {"payload": payload}, "jxl_d1_raw", {"codec_preflight": [{"name": "jxl_d1", "version": "1", "metadata": {"levels": [1, 2]}}]}, fixture=False)
442
+
443
+
444
+ def test_pilot_conclusion_uses_concrete_codec_semantics(tmp_path: Path) -> None:
445
+ summaries = []
446
+ for condition in CONDITION_IDS:
447
+ raw = condition.endswith("_raw")
448
+ protected = condition.endswith("_protected_high")
449
+ summaries.append({"condition_id": condition, "success": 0 if raw else 8 if protected or condition in {"png_baseline", "webp_lossless", "jpeg_q100_repair_zero"} else 0, "denominator": 8, "nan_count": 1 if raw else 0, "exponent_mismatch_count": 1 if raw else 0, "payload_over_png": 0.8 if protected else 1.0, "clip_mean": 0.9 if not raw else None, "sample_sha_match_rate": 1.0 if condition in {"png_baseline", "webp_lossless"} else "N/A"})
450
+ paired = [{"condition_id": condition, "paired_n": 8, "mean_delta": 0.01, "ci_low": -0.01, "ci_high": 0.02} for condition in CONDITION_IDS]
451
+ report._documents(tmp_path, {"profile": "pilot"}, summaries, paired, fixture=False)
452
+ conclusion = (tmp_path / "final_conclusion.md").read_text()
453
+ assert "Hypothesis status: supported (5/5 associated lossy raw codecs)" in conclusion
454
+ assert "JPEG is not uniquely fragile in pilot" in conclusion
455
+ assert "Repair Zero recovered only JPEG Q100 (1/5)" in conclusion
456
+ assert "WebP Lossless" in conclusion and "WebP Q80 Protected" in conclusion
457
+ assert "JXL" in conclusion and "Question 6" in conclusion
458
+ assert "partially supported (1/5)" not in conclusion
459
+
460
+
461
+ def test_full_conclusion_uses_dynamic_scope_and_full_run_language(tmp_path: Path) -> None:
462
+ summaries = []
463
+ for condition in CONDITION_IDS:
464
+ raw = condition.endswith("_raw")
465
+ protected = condition.endswith("_protected_high")
466
+ success = 100 if condition == "png_baseline" or protected or condition == "jpeg_q100_repair_zero" else 0
467
+ summaries.append({
468
+ "condition_id": condition,
469
+ "success": success,
470
+ "denominator": 100,
471
+ "nan_count": 1 if raw else 0,
472
+ "exponent_mismatch_count": 1 if raw else 0,
473
+ "payload_over_png": 0.8 if protected else 1.0,
474
+ "clip_mean": 0.9 if success else None,
475
+ "sample_sha_match_rate": 1.0 if condition in {"png_baseline", "webp_lossless"} else "N/A",
476
+ })
477
+ paired = [{"condition_id": condition, "paired_n": 100, "mean_delta": 0.01, "ci_low": -0.01, "ci_high": 0.02} for condition in CONDITION_IDS]
478
+
479
+ report._documents(tmp_path, {"profile": "full"}, summaries, paired, fixture=False)
480
+ conclusion = (tmp_path / "final_conclusion.md").read_text()
481
+
482
+ assert "JPEG is not uniquely fragile in full run" in conclusion
483
+ assert "all had 0/100 blocked" in conclusion
484
+ assert "other four 0/100" in conclusion
485
+ assert "protected candidates maintained baseline success" in conclusion
486
+ assert "Overall observed best" in conclusion
487
+ assert "pilot" not in conclusion.lower()
488
+ assert "limited to this pilot" not in conclusion
489
+
490
+
491
+ def test_report_options_bind_identity_and_force_replacement(tmp_path: Path) -> None:
492
+ run = _run(tmp_path)
493
+ output = report.generate_report(run, fixture=True, report_options={"label": "A"})
494
+ first = json.loads((output / "report_manifest.json").read_text())["report_identity_hash"]
495
+ with pytest.raises(ValueError, match="identity"):
496
+ report.generate_report(run, fixture=True, report_options={"label": "B"})
497
+ report.generate_report(run, fixture=True, report_options={"label": "B"}, force_report=True)
498
+ second = json.loads((output / "report_manifest.json").read_text())["report_identity_hash"]
499
+ assert first != second
500
+
501
+
502
+ def test_manifest_verifier_rejects_traversal_sha_tamper_and_duplicate(tmp_path: Path) -> None:
503
+ output = report.generate_report(_run(tmp_path), fixture=True)
504
+ manifest_path = output / "report_manifest.json"
505
+ manifest = json.loads(manifest_path.read_text())
506
+ manifest["artifacts"][0]["path"] = "../escape"
507
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
508
+ assert report.verify_report_manifest(output) is False
509
+ (tmp_path / "again").mkdir()
510
+ output = report.generate_report(_run(tmp_path / "again"), fixture=True)
511
+ manifest_path = output / "report_manifest.json"
512
+ manifest = json.loads(manifest_path.read_text())
513
+ manifest["artifacts"][0]["sha256"] = "bad"
514
+ manifest["artifacts"].append(dict(manifest["artifacts"][1]))
515
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
516
+ assert report.verify_report_manifest(output) is False
517
+
518
+
519
+ def test_same_run_report_manifest_is_byte_deterministic(tmp_path: Path) -> None:
520
+ run = _run(tmp_path)
521
+ output = report.generate_report(run, fixture=True)
522
+ first = {str(path.relative_to(output)): path.read_bytes() for path in output.rglob("*") if path.is_file()}
523
+ report.generate_report(run, fixture=True)
524
+ second = {str(path.relative_to(output)): path.read_bytes() for path in output.rglob("*") if path.is_file()}
525
+ assert first == second
526
+
527
+
528
+ def test_real_runner_paired_seed_hash_projection_is_resolved(tmp_path: Path) -> None:
529
+ run = _run(tmp_path, prompt_projection="paired")
530
+ output = report.generate_report(run, fixture=True)
531
+ manifest = json.loads((output / "report_manifest.json").read_text())
532
+ assert manifest["report_identity"]["prompt_projection"] == "paired_seed_equals_seed"
533
+ assert manifest["input_provenance"]["prompt_projection"] == "paired_seed_equals_seed"
534
+ assert [row["prompt_id"] for row in _csv(output / "generation_metrics.csv")[:2]] == ["p-0", "p-1"]
535
+
536
+
537
+ def test_prompt_projection_rejects_unmatched_hash(tmp_path: Path) -> None:
538
+ prompts = [{"prompt_id": "p-0", "category": "cat", "prompt": "x", "seed": 1, "initial_latent_seed": 2}]
539
+ with pytest.raises(ValueError, match="prompt selection hash"):
540
+ report._resolve_prompt_projection(prompts, "not-a-candidate")
541
+
542
+
543
+ def test_prompt_projection_fails_closed_on_ambiguous_hash(monkeypatch: pytest.MonkeyPatch) -> None:
544
+ prompts = [{"prompt_id": "p-0", "category": "cat", "prompt": "x", "seed": 1, "initial_latent_seed": 2}]
545
+ monkeypatch.setattr(report, "_hash", lambda value: "same-hash")
546
+ with pytest.raises(ValueError, match="ambiguous"):
547
+ report._resolve_prompt_projection(prompts, "same-hash")
tests/test_jpeg_repair.py ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """JPEG repair Task 1-2の契約テスト。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from io import BytesIO
6
+
7
+ import numpy as np
8
+ import pytest
9
+ from PIL import Image
10
+
11
+ from pixelmodel_robustness.jpeg_repair import (
12
+ CLIP_STRATEGIES,
13
+ CONDITION_IDS,
14
+ build_jpeg_registry,
15
+ clip_candidate,
16
+ decode_jpeg_rgb,
17
+ decode_protected,
18
+ diagnostics,
19
+ encode_jpeg_q100,
20
+ encode_protected,
21
+ materialize_fp16_png,
22
+ repair_nonfinite,
23
+ semantic_hash,
24
+ validate_layer_offsets,
25
+ )
26
+
27
+
28
+ def _image() -> Image.Image:
29
+ return Image.fromarray(
30
+ np.array([[[0, 1, 2], [20, 40, 60]], [[100, 120, 140], [240, 220, 200]]], dtype=np.uint8),
31
+ "RGB",
32
+ )
33
+
34
+
35
+ def test_registry_is_exact_ordered_and_semantically_hashed() -> None:
36
+ registry = build_jpeg_registry()
37
+ assert tuple(entry.condition_id for entry in registry) == CONDITION_IDS
38
+ assert len(registry) == 18
39
+ assert len({entry.parent_raw_sha256 for entry in registry[1:17]}) == 1
40
+ assert semantic_hash(registry) == semantic_hash(build_jpeg_registry())
41
+ assert tuple(entry.condition_id for entry in registry) == CONDITION_IDS
42
+
43
+
44
+ def test_jpeg_q100_source_is_one_reusable_decode() -> None:
45
+ raw = encode_jpeg_q100(_image())
46
+ first = decode_jpeg_rgb(raw)
47
+ second = decode_jpeg_rgb(raw)
48
+ assert raw.startswith(b"\xff\xd8")
49
+ np.testing.assert_array_equal(first, second)
50
+ assert first.shape == (2, 2, 3)
51
+
52
+
53
+ def test_fp16_flat_materialization_preserves_bits_and_png_contract() -> None:
54
+ values = np.array([0.0, -0.0, 1.5, -2.25, np.float16("inf")], dtype=np.float16)
55
+ png = materialize_fp16_png(values)
56
+ pixels = np.asarray(Image.open(BytesIO(png)).convert("RGB"), dtype=np.uint8).reshape(-1, 3)
57
+ np.testing.assert_array_equal((pixels[: len(values), 0].astype(np.uint16) << 8) | pixels[: len(values), 1], values.view(np.uint16))
58
+ assert pixels[:, 2].tolist() == [0] * len(values)
59
+
60
+
61
+ def test_finite_repair_materialize_decode_preserves_original_uint16_bits() -> None:
62
+ original = np.array([0.0, -0.0, 1.5, -2.25, 3.125, -4.5], dtype=np.float16)
63
+ repaired = repair_nonfinite(original, "layer_mean", {"layer": (0, len(original))}).values
64
+ png = materialize_fp16_png(repaired)
65
+ pixels = np.asarray(Image.open(BytesIO(png)).convert("RGB"), dtype=np.uint8).reshape(-1, 3)
66
+ decoded_bits = (pixels[: len(original), 0].astype(np.uint16) << 8) | pixels[: len(original), 1].astype(np.uint16)
67
+ np.testing.assert_array_equal(decoded_bits, original.view(np.uint16))
68
+
69
+
70
+ def test_protected_high_png_is_exact_low_jpeg_only_changes() -> None:
71
+ values = np.array([0.0, -0.0, 1.5, -2.25, 3.125, -4.5], dtype=np.float16)
72
+ artifact = encode_protected(values, (2, 3))
73
+ decoded, metadata = decode_protected(artifact.payload, (2, 3))
74
+ np.testing.assert_array_equal(decoded.view(np.uint16), values.view(np.uint16))
75
+ high = np.asarray(Image.open(BytesIO(artifact.high_png_bytes)).convert("L"), dtype=np.uint8)
76
+ np.testing.assert_array_equal(high.reshape(-1), (values.view(np.uint16) >> 8).astype(np.uint8))
77
+ assert metadata["payload_size_bytes"] == len(artifact.high_png_bytes) + len(artifact.low_jpeg_bytes)
78
+ assert metadata["high_mode"] == metadata["low_mode"] == "L"
79
+
80
+
81
+ def test_repair_replaces_only_nonfinite_and_reports_signed_zero_bits() -> None:
82
+ raw = np.array([0.0, -0.0, np.nan, np.inf, -np.inf, 2.0], dtype=np.float16)
83
+ result = repair_nonfinite(raw, "layer_mean", {"layer": (0, len(raw))})
84
+ assert result.repaired_value_count == 3
85
+ assert result.nan_count == result.posinf_count == result.neginf_count == 1
86
+ assert np.isfinite(result.values).all()
87
+ np.testing.assert_array_equal(result.values.view(np.uint16)[[0, 1, 5]], raw.view(np.uint16)[[0, 1, 5]])
88
+
89
+
90
+ def test_zero_repair_accepts_all_nonfinite_layer_and_preserves_finite_bits() -> None:
91
+ raw = np.array([np.nan, np.inf, -np.inf, 1.5, -0.0, np.nan], dtype=np.float16)
92
+ original_bits = raw.view(np.uint16).copy()
93
+
94
+ result = repair_nonfinite(raw, "zero", {"all_nonfinite": (0, 3), "mixed": (3, 6)})
95
+
96
+ assert np.isfinite(result.values).all()
97
+ assert result.repaired_value_count == 4
98
+ assert result.nan_count == 2
99
+ assert result.posinf_count == 1
100
+ assert result.neginf_count == 1
101
+ assert [record.repaired_count for record in result.layer_records] == [3, 1]
102
+ assert [record.nan_count for record in result.layer_records] == [1, 1]
103
+ assert [record.posinf_count for record in result.layer_records] == [1, 0]
104
+ assert [record.neginf_count for record in result.layer_records] == [1, 0]
105
+ finite = np.isfinite(raw)
106
+ np.testing.assert_array_equal(result.values.view(np.uint16)[finite], original_bits[finite])
107
+
108
+
109
+ def test_repair_rejects_empty_finite_layer() -> None:
110
+ raw = np.array([np.nan, np.inf], dtype=np.float16)
111
+ with pytest.raises(ValueError, match="finite values"):
112
+ repair_nonfinite(raw, "layer_median", {"empty": (0, 2)})
113
+
114
+
115
+ @pytest.mark.parametrize("method", ["layer_median", "layer_mean"])
116
+ def test_repair_rejects_empty_finite_layer_for_statistical_methods(method: str) -> None:
117
+ raw = np.array([np.nan, np.inf, -np.inf], dtype=np.float16)
118
+ with pytest.raises(ValueError, match="finite values"):
119
+ repair_nonfinite(raw, method, {"empty": (0, 3)})
120
+
121
+
122
+ @pytest.mark.parametrize("strategy", CLIP_STRATEGIES)
123
+ def test_clip_strategies_use_candidate_only_and_record_changes(strategy: str) -> None:
124
+ candidate = np.array([-10.0, -1.0, 0.0, 1.0, 10.0], dtype=np.float16)
125
+ result = clip_candidate(candidate, {"layer": (0, 5)}, strategy)
126
+ assert result.values.dtype == np.float16
127
+ assert result.layers[0].strategy == strategy
128
+ assert result.layers[0].changed_count == int(np.count_nonzero(result.values.view(np.uint16) != candidate.view(np.uint16)))
129
+ assert np.isfinite(result.values).all()
130
+ assert result.layers[0].lower <= result.layers[0].upper
131
+
132
+
133
+ def test_clip_uses_population_std_and_linear_percentile() -> None:
134
+ candidate = np.array([0.0, 1.0, 2.0, 100.0], dtype=np.float16)
135
+ result = clip_candidate(candidate, {"layer": (0, 4)}, "layer_mean_std_6")
136
+ expected = float(np.mean(candidate.astype(np.float64)) + 6 * np.std(candidate.astype(np.float64), ddof=0))
137
+ assert result.layers[0].upper == pytest.approx(expected)
138
+ percentile = clip_candidate(candidate, {"layer": (0, 4)}, "layer_pct_0.1_99.9")
139
+ expected_percentile = float(np.percentile(candidate.astype(np.float64), 99.9, method="linear"))
140
+ assert percentile.layers[0].upper == pytest.approx(expected_percentile)
141
+
142
+
143
+ def test_clip_degenerate_and_threshold_equal_are_unchanged() -> None:
144
+ candidate = np.array([2.0, 2.0], dtype=np.float16)
145
+ result = clip_candidate(candidate, {"one": (0, 2)}, "layer_mean_std_5")
146
+ np.testing.assert_array_equal(result.values.view(np.uint16), candidate.view(np.uint16))
147
+ assert result.layers[0].changed_count == 0
148
+
149
+
150
+ def test_fp16_bit_diagnostics_and_bounded_histogram() -> None:
151
+ baseline = np.array([1.0, -1.0, 0.0, 1.0], dtype=np.float16)
152
+ candidate = np.array([20.0, -1.0, np.float16("inf"), np.float16("nan")], dtype=np.float16)
153
+ result = diagnostics(baseline, candidate, {"layer": (0, 4)})
154
+ assert result["sign_mismatch_count"] == 0
155
+ assert result["exponent_mismatch_count"] == 3
156
+ assert result["mantissa_mismatch_count"] == 2
157
+ assert result["exponent_to31_count"] == 2
158
+ assert result["finite_extreme_outlier_count"] == 1
159
+ assert set(result["histograms"]) == {"baseline", "candidate", "delta"}
160
+ assert all(len(item["counts"]) <= 64 for item in result["histograms"].values())
161
+
162
+
163
+ def test_registry_parent_identity_is_only_shared_by_raw_jpeg_conditions() -> None:
164
+ raw = encode_jpeg_q100(_image())
165
+ registry = build_jpeg_registry(raw)
166
+ assert len({entry.parent_raw_sha256 for entry in registry[1:17]}) == 1
167
+ assert registry[0].parent_raw_sha256 != registry[1].parent_raw_sha256
168
+ assert registry[17].parent_raw_sha256 != registry[1].parent_raw_sha256
169
+ assert registry[0].parent_raw_sha256 != registry[17].parent_raw_sha256
170
+
171
+
172
+ def test_layer_offsets_are_contiguous_and_fail_closed() -> None:
173
+ assert validate_layer_offsets({"a": (0, 2), "b": (2, 4)}, 4) == {"a": (0, 2), "b": (2, 4)}
174
+ with pytest.raises(ValueError, match="contiguous"):
175
+ validate_layer_offsets({"a": (0, 2), "b": (3, 4)}, 4)
176
+ with pytest.raises(ValueError, match="overlap"):
177
+ validate_layer_offsets({"a": (0, 3), "b": (2, 4)}, 4)
178
+
179
+
180
+ def test_diagnostics_extreme_uses_layer_baseline_max_and_reports_finite_stats() -> None:
181
+ baseline = np.array([1.0, 2.0, 0.0, 0.0], dtype=np.float16)
182
+ candidate = np.array([25.0, 2.0, 1.0, 0.0], dtype=np.float16)
183
+ result = diagnostics(baseline, candidate, {"first": (0, 2), "zero": (2, 4)})
184
+ assert result["finite_extreme_outlier_count"] == 2
185
+ assert result["finite_count"] == 4
186
+ assert result["max_abs_weight"] == pytest.approx(25.0)
187
+ assert result["nan_count"] == result["posinf_count"] == result["neginf_count"] == 0
188
+ assert result["layers"][0]["finite_extreme_outlier_count"] == 1
189
+ assert result["layers"][1]["finite_extreme_outlier_count"] == 1
190
+ assert result["layers"][1]["max_abs_weight"] == pytest.approx(1.0)
191
+
192
+
193
+ def test_repair_has_layer_records_and_bounded_repaired_histogram() -> None:
194
+ raw = np.array([np.nan, np.inf, -np.inf, 1.0], dtype=np.float16)
195
+ result = repair_nonfinite(raw, "zero", {"layer": (0, 4)})
196
+ record = result.layer_records[0]
197
+ assert record.layer == "layer"
198
+ assert record.repaired_count == 3
199
+ assert record.nan_count == record.posinf_count == record.neginf_count == 1
200
+ assert sum(result.repaired_histogram["counts"]) == 3
201
+ assert len(result.repaired_histogram["counts"]) <= 64
202
+
203
+
204
+ def test_clip_has_total_count_and_changed_value_histograms() -> None:
205
+ candidate = np.array([-100.0, -1.0, 0.0, 1.0, 100.0], dtype=np.float16)
206
+ result = clip_candidate(candidate, {"layer": (0, 5)}, "layer_mean_std_5")
207
+ assert result.total_clipped_count == result.layers[0].changed_count
208
+ assert sum(result.changed_pre_histogram["counts"]) == result.total_clipped_count
209
+ assert sum(result.changed_post_histogram["counts"]) == result.total_clipped_count
210
+ assert sum(result.changed_delta_histogram["counts"]) == result.total_clipped_count
211
+
212
+
213
+ def test_protected_metadata_reports_decoded_planes_and_low_changes() -> None:
214
+ rng = np.random.default_rng(20260727)
215
+ values = rng.integers(0, 65536, size=32 * 32, dtype=np.uint16).view(np.float16)
216
+ artifact = encode_protected(values, (32, 32))
217
+ decoded, metadata = decode_protected(artifact.payload, (32, 32), source_values=values)
218
+ assert metadata["decoded_high_exact"] is True
219
+ assert metadata["decoded_high_sha256"]
220
+ assert metadata["decoded_low_sha256"]
221
+ assert metadata["decoded_low_changed_count"] > 0
222
+ assert 0.0 < metadata["decoded_low_changed_rate"] <= 1.0
223
+ assert metadata["pillow_version"]
224
+ assert metadata["combined_payload_exact"] is True
225
+ assert metadata["high_mode"] == metadata["low_mode"] == "L"
226
+ assert metadata["high_dimensions"] == metadata["low_dimensions"] == [32, 32]
227
+ assert metadata["combined_payload_sha256"]
228
+ assert metadata["combined_payload_bytes"] == metadata["high_bytes"] + metadata["low_bytes"]
229
+ assert "jpeg_codec_version" in metadata
230
+ assert decoded.shape == values.shape
231
+
232
+
233
+ def test_combined_payload_parser_rejects_invalid_png_chunk_bounds() -> None:
234
+ values = np.arange(16, dtype=np.float16)
235
+ artifact = encode_protected(values, (4, 4))
236
+ broken = artifact.payload[:16] + b"\xff"
237
+ with pytest.raises(ValueError, match="PNG"):
238
+ decode_protected(broken, (4, 4))
tests/test_render_visual_tables.py ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import json
5
+ import os
6
+ from pathlib import Path
7
+
8
+ import pytest
9
+ from PIL import Image
10
+ from render_visual_tables import CODECS, load_prompt_ids, load_rows, render
11
+
12
+
13
+ def test_load_prompt_ids_accepts_manifest_object(tmp_path: Path) -> None:
14
+ path = tmp_path / "prompts.json"
15
+ path.write_text(json.dumps({"prompt_ids": ["p2", "p1"]}), encoding="utf-8")
16
+
17
+ assert load_prompt_ids(path) == ["p2", "p1"]
18
+
19
+
20
+ def test_load_rows_fails_closed_when_a_success_has_no_sample(tmp_path: Path) -> None:
21
+ run = tmp_path / "run"
22
+ (run / "results").mkdir(parents=True)
23
+ row = {"row_type": "generation", "condition": "png_baseline", "prompt_id": "p1", "success": True}
24
+ (run / "results/raw_rows.jsonl").write_text(json.dumps(row) + "\n", encoding="utf-8")
25
+
26
+ with pytest.raises(ValueError, match="sample"):
27
+ load_rows(run, ["p1"])
28
+
29
+
30
+ def test_load_rows_rejects_raw_rows_symlink(tmp_path: Path) -> None:
31
+ run = tmp_path / "run"
32
+ (run / "results").mkdir(parents=True)
33
+ target = tmp_path / "raw_rows.jsonl"
34
+ target.write_text("", encoding="utf-8")
35
+ (run / "results/raw_rows.jsonl").symlink_to(target)
36
+
37
+ with pytest.raises(ValueError, match="symlink"):
38
+ load_rows(run, ["p1"])
39
+
40
+
41
+ def test_load_rows_rejects_raw_rows_path_escape(tmp_path: Path) -> None:
42
+ run = tmp_path / "run"
43
+ (run / "results").mkdir(parents=True)
44
+ (run / "results/raw_rows.jsonl").symlink_to(tmp_path / "outside.jsonl")
45
+ (tmp_path / "outside.jsonl").write_text("", encoding="utf-8")
46
+
47
+ with pytest.raises(ValueError, match="escapes run|symlink"):
48
+ load_rows(run, ["p1"])
49
+
50
+
51
+ def test_render_rejects_sample_replaced_with_symlink_after_validation(tmp_path: Path) -> None:
52
+ run = tmp_path / "run"
53
+ sample = run / "samples/sample.png"
54
+ sample.parent.mkdir(parents=True)
55
+ Image.new("RGB", (4, 4), "blue").save(sample)
56
+ sample_hash = hashlib.sha256(sample.read_bytes()).hexdigest()
57
+ conditions = {"png_baseline", "webp_lossless"} | {
58
+ condition for codec in CODECS.values() for condition in codec[1:]
59
+ }
60
+ rows = [
61
+ {
62
+ "row_type": "generation",
63
+ "condition": condition,
64
+ "prompt_id": "p1",
65
+ "prompt": "test prompt",
66
+ "category": "test",
67
+ "success": True,
68
+ "sample_path": "samples/sample.png",
69
+ "sample_hash": sample_hash,
70
+ "clip_score": 1.0,
71
+ }
72
+ for condition in sorted(conditions)
73
+ ]
74
+ results = run / "results"
75
+ results.mkdir()
76
+ (results / "raw_rows.jsonl").write_text(
77
+ "".join(json.dumps(row) + "\n" for row in rows),
78
+ encoding="utf-8",
79
+ )
80
+ loaded = load_rows(run, ["p1"])
81
+ outside = tmp_path / "outside.png"
82
+ Image.new("RGB", (4, 4), "red").save(outside)
83
+ sample.unlink()
84
+ sample.symlink_to(outside)
85
+
86
+ with pytest.raises(ValueError, match="symlink"):
87
+ render(
88
+ "jpeg_q100",
89
+ CODECS["jpeg_q100"],
90
+ run.resolve(),
91
+ [loaded[("png_baseline", "p1")]],
92
+ loaded,
93
+ tmp_path / "output",
94
+ )
95
+
96
+
97
+ def test_render_rejects_regular_sample_changed_after_validation(tmp_path: Path) -> None:
98
+ run = tmp_path / "run"
99
+ sample = run / "samples/sample.png"
100
+ sample.parent.mkdir(parents=True)
101
+ Image.new("RGB", (4, 4), "blue").save(sample)
102
+ sample_hash = hashlib.sha256(sample.read_bytes()).hexdigest()
103
+ conditions = {"png_baseline", "webp_lossless"} | {
104
+ condition for codec in CODECS.values() for condition in codec[1:]
105
+ }
106
+ rows = [
107
+ {
108
+ "row_type": "generation",
109
+ "condition": condition,
110
+ "prompt_id": "p1",
111
+ "prompt": "test prompt",
112
+ "category": "test",
113
+ "success": True,
114
+ "sample_path": "samples/sample.png",
115
+ "sample_hash": sample_hash,
116
+ "clip_score": 1.0,
117
+ }
118
+ for condition in sorted(conditions)
119
+ ]
120
+ results = run / "results"
121
+ results.mkdir()
122
+ (results / "raw_rows.jsonl").write_text(
123
+ "".join(json.dumps(row) + "\n" for row in rows),
124
+ encoding="utf-8",
125
+ )
126
+ loaded = load_rows(run, ["p1"])
127
+ Image.new("RGB", (4, 4), "red").save(sample)
128
+
129
+ with pytest.raises(ValueError, match="hash mismatch"):
130
+ render(
131
+ "jpeg_q100",
132
+ CODECS["jpeg_q100"],
133
+ run.resolve(),
134
+ [loaded[("png_baseline", "p1")]],
135
+ loaded,
136
+ tmp_path / "output",
137
+ )
138
+
139
+
140
+ @pytest.mark.skipif(not hasattr(os, "mkfifo"), reason="FIFO is unavailable on this platform")
141
+ def test_render_rejects_fifo_replacement_without_blocking(tmp_path: Path) -> None:
142
+ run = tmp_path / "run"
143
+ sample = run / "samples/sample.png"
144
+ sample.parent.mkdir(parents=True)
145
+ Image.new("RGB", (4, 4), "blue").save(sample)
146
+ sample_hash = hashlib.sha256(sample.read_bytes()).hexdigest()
147
+ conditions = {"png_baseline", "webp_lossless"} | {
148
+ condition for codec in CODECS.values() for condition in codec[1:]
149
+ }
150
+ rows = [
151
+ {
152
+ "row_type": "generation",
153
+ "condition": condition,
154
+ "prompt_id": "p1",
155
+ "prompt": "test prompt",
156
+ "category": "test",
157
+ "success": True,
158
+ "sample_path": "samples/sample.png",
159
+ "sample_hash": sample_hash,
160
+ "clip_score": 1.0,
161
+ }
162
+ for condition in sorted(conditions)
163
+ ]
164
+ results = run / "results"
165
+ results.mkdir()
166
+ (results / "raw_rows.jsonl").write_text(
167
+ "".join(json.dumps(row) + "\n" for row in rows),
168
+ encoding="utf-8",
169
+ )
170
+ loaded = load_rows(run, ["p1"])
171
+ sample.unlink()
172
+ os.mkfifo(sample)
173
+
174
+ with pytest.raises(ValueError, match="not a regular file"):
175
+ render(
176
+ "jpeg_q100",
177
+ CODECS["jpeg_q100"],
178
+ run.resolve(),
179
+ [loaded[("png_baseline", "p1")]],
180
+ loaded,
181
+ tmp_path / "output",
182
+ )
tests/test_verify_archive.py ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import csv
4
+ import hashlib
5
+ import json
6
+ from pathlib import Path
7
+
8
+ import pytest
9
+ from verify_archive import verify_archive
10
+
11
+
12
+ def _write_archive(root: Path) -> None:
13
+ for relative, content in {
14
+ "images/example.png": b"image",
15
+ "results/metrics.csv": b"condition,success\npng,1\n",
16
+ "samples/example.png": b"sample",
17
+ "weights/model.png": b"weights",
18
+ }.items():
19
+ path = root / relative
20
+ path.parent.mkdir(parents=True, exist_ok=True)
21
+ path.write_bytes(content)
22
+ rows = []
23
+ for relative in ("weights/model.png",):
24
+ path = root / relative
25
+ rows.append(
26
+ {
27
+ "path": relative,
28
+ "bytes": str(path.stat().st_size),
29
+ "sha256": hashlib.sha256(path.read_bytes()).hexdigest(),
30
+ }
31
+ )
32
+ with (root / "weights/manifest.csv").open("w", newline="", encoding="utf-8") as handle:
33
+ writer = csv.DictWriter(handle, fieldnames=["path", "bytes", "sha256"])
34
+ writer.writeheader()
35
+ writer.writerows(rows)
36
+ manifest = {
37
+ "files": [
38
+ {
39
+ "path": relative,
40
+ "bytes": (root / relative).stat().st_size,
41
+ "sha256": hashlib.sha256((root / relative).read_bytes()).hexdigest(),
42
+ }
43
+ for relative in (
44
+ "images/example.png",
45
+ "results/metrics.csv",
46
+ "samples/example.png",
47
+ "weights/manifest.csv",
48
+ )
49
+ ]
50
+ }
51
+ (root / "results/archive_manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
52
+
53
+
54
+ def _refresh_manifest(root: Path) -> None:
55
+ manifest_path = root / "results/archive_manifest.json"
56
+ manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
57
+ manifest.pop("files", None)
58
+ manifest["artifacts"] = []
59
+ for path in sorted(p for directory in ("images", "results", "samples", "weights")
60
+ for p in (root / directory).rglob("*") if p.is_file() and p.name != "archive_manifest.json"):
61
+ relative = path.relative_to(root).as_posix()
62
+ manifest["artifacts"].append({"path": relative, "bytes": path.stat().st_size,
63
+ "sha256": hashlib.sha256(path.read_bytes()).hexdigest()})
64
+ manifest.update({"profile": "test", "prompt_count": 1, "conditions": ["png_baseline", "webp_lossless"]})
65
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
66
+
67
+
68
+ def _add_generation_rows(root: Path) -> None:
69
+ sample = root / "samples/example.png"
70
+ rows = [
71
+ {"row_type": "generation", "condition": "png_baseline", "prompt_id": "p1", "success": True,
72
+ "sample_path": "samples/example.png", "sample_bytes": sample.stat().st_size,
73
+ "sample_hash": hashlib.sha256(sample.read_bytes()).hexdigest(), "sample_sha256": None},
74
+ {"row_type": "generation", "condition": "webp_lossless", "prompt_id": "p1", "success": False,
75
+ "sample_path": None, "sample_bytes": None, "sample_hash": None, "sample_sha256": None},
76
+ ]
77
+ (root / "results/raw_rows.jsonl").write_text("".join(json.dumps(row) + "\n" for row in rows), encoding="utf-8")
78
+ _refresh_manifest(root)
79
+
80
+
81
+ def test_verify_archive_accepts_hash_and_containment_valid_archive(tmp_path: Path) -> None:
82
+ _write_archive(tmp_path)
83
+ _add_generation_rows(tmp_path)
84
+
85
+ report = verify_archive(tmp_path)
86
+
87
+ assert report["checked_files"] == 7
88
+ assert report["checked_weight_entries"] == 1
89
+ assert report["generation_rows"] == 2
90
+ assert report["successful_samples"] == 1
91
+
92
+
93
+ def test_verify_archive_rejects_path_escape(tmp_path: Path) -> None:
94
+ _write_archive(tmp_path)
95
+ _add_generation_rows(tmp_path)
96
+ manifest_path = tmp_path / "results/archive_manifest.json"
97
+ manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
98
+ manifest["artifacts"].append({"path": "../outside", "bytes": 0, "sha256": ""})
99
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
100
+
101
+ with pytest.raises(ValueError, match="containment"):
102
+ verify_archive(tmp_path)
103
+
104
+
105
+ @pytest.mark.parametrize("mutation, message", [
106
+ ("missing", "sample"),
107
+ ("hash", "SHA-256"),
108
+ ("bytes", "byte count"),
109
+ ])
110
+ def test_verify_archive_rejects_invalid_success_provenance(tmp_path: Path, mutation: str, message: str) -> None:
111
+ _write_archive(tmp_path)
112
+ _add_generation_rows(tmp_path)
113
+ raw = tmp_path / "results/raw_rows.jsonl"
114
+ row = json.loads(raw.read_text(encoding="utf-8").splitlines()[0])
115
+ if mutation == "missing":
116
+ row["sample_path"] = None
117
+ elif mutation == "hash":
118
+ row["sample_hash"] = "0" * 64
119
+ else:
120
+ row["sample_bytes"] += 1
121
+ raw.write_text(json.dumps(row) + "\n" + raw.read_text(encoding="utf-8").splitlines()[1] + "\n", encoding="utf-8")
122
+ _refresh_manifest(tmp_path)
123
+
124
+ with pytest.raises(ValueError, match=message):
125
+ verify_archive(tmp_path)
126
+
127
+
128
+ def test_verify_archive_rejects_failed_row_with_sample(tmp_path: Path) -> None:
129
+ _write_archive(tmp_path)
130
+ _add_generation_rows(tmp_path)
131
+ raw = tmp_path / "results/raw_rows.jsonl"
132
+ rows = [json.loads(line) for line in raw.read_text(encoding="utf-8").splitlines()]
133
+ rows[1]["sample_path"] = "samples/example.png"
134
+ raw.write_text("\n".join(json.dumps(row) for row in rows) + "\n", encoding="utf-8")
135
+ _refresh_manifest(tmp_path)
136
+
137
+ with pytest.raises(ValueError, match="failed row"):
138
+ verify_archive(tmp_path)
139
+
140
+
141
+ def test_verify_archive_rejects_raw_rows_symlink(tmp_path: Path) -> None:
142
+ _write_archive(tmp_path)
143
+ _add_generation_rows(tmp_path)
144
+ raw = tmp_path / "results/raw_rows.jsonl"
145
+ raw.unlink()
146
+ raw.symlink_to(tmp_path / "outside.jsonl")
147
+ (tmp_path / "outside.jsonl").write_text("", encoding="utf-8")
148
+
149
+ with pytest.raises(ValueError, match="symlink"):
150
+ verify_archive(tmp_path)
151
+
152
+
153
+ def test_verify_archive_rejects_duplicate_manifest_path(tmp_path: Path) -> None:
154
+ _write_archive(tmp_path)
155
+ _add_generation_rows(tmp_path)
156
+ manifest_path = tmp_path / "results/archive_manifest.json"
157
+ manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
158
+ manifest["artifacts"].append(manifest["artifacts"][0])
159
+ manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
160
+
161
+ with pytest.raises(ValueError, match="duplicate archive path"):
162
+ verify_archive(tmp_path)
163
+
164
+
165
+ def test_verify_archive_rejects_listed_hash_tamper(tmp_path: Path) -> None:
166
+ _write_archive(tmp_path)
167
+ _add_generation_rows(tmp_path)
168
+ path = tmp_path / "samples/example.png"
169
+ path.write_bytes(b"tampeR")
170
+
171
+ with pytest.raises(ValueError, match="SHA-256"):
172
+ verify_archive(tmp_path)
173
+
174
+
175
+ def test_verify_archive_rejects_archived_tree_symlink_and_unlisted_file(tmp_path: Path) -> None:
176
+ _write_archive(tmp_path)
177
+ _add_generation_rows(tmp_path)
178
+ extra = tmp_path / "samples/unlisted.bin"
179
+ extra.write_bytes(b"extra")
180
+ with pytest.raises(ValueError, match="unlisted"):
181
+ verify_archive(tmp_path)
182
+ extra.unlink()
183
+ extra.symlink_to(tmp_path / "weights/model.png")
184
+
185
+ with pytest.raises(ValueError, match="symlink"):
186
+ verify_archive(tmp_path)
uv.lock ADDED
The diff for this file is too large to render. See raw diff
 
weights/README.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Archived codec payloads
2
+
3
+ This directory stores byte-exact encoded payloads from the full run. Raw and Finite Repair Zero share the same encoded codec payload, so identical files are stored once and mapped to both conditions in `manifest.csv`. Protected High Byte stores one deduplicated lossless high-byte PNG plus one low-byte payload per lossy codec.
4
+
5
+ The reconstructed fp16 weight PNGs are not duplicated here: they are deterministic materializations of these payloads and would add substantial redundant storage. The original PixelModel-v4 source assets remain available from [`bench-labs/PixelModel-v4`](https://huggingface.co/bench-labs/PixelModel-v4) at revision `80878fdd6e130d229c2581424a3456b47b979d4b`.
6
+
7
+ All payload sizes and SHA-256 hashes are recorded in `manifest.csv`. Protected combined hashes follow the canonical experiment's high-plus-low payload definition.
weights/manifest.csv ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ artifact_path,role,codec,source_conditions,bytes,sha256,combined_payload_bytes,combined_payload_sha256
2
+ weights/codec_payloads/png_baseline.png,codec_payload,PNG baseline,png_baseline,89711808,a7b64d9d69c6ba1e428a5957bf1eae7a60145dc60cf8341300e8bdbcf80b2b31,,
3
+ weights/codec_payloads/webp_lossless.webp,codec_payload,WebP lossless,webp_lossless,67929870,134c0c741635bb91b0f80d386d03e7ae4b4652fe82a640d6ceb8e228eced0934,,
4
+ weights/codec_payloads/jpeg_q100.jpg,codec_payload,JPEG Q100,jpeg_q100_raw;jpeg_q100_repair_zero,156060019,d74c6e5e16cdf93a5afef3a95b08ef8f2d529cef452beeff71c38fe9359d08d6,,
5
+ weights/codec_payloads/jpeg_q80.jpg,codec_payload,JPEG Q80,jpeg_q80_raw;jpeg_q80_repair_zero,50283220,de6fadf8ec9b44b429629418d79d77b8e852a5cfcc43b0cd3035013eb59accc9,,
6
+ weights/codec_payloads/webp_q80.webp,codec_payload,WebP Q80,webp_q80_raw;webp_q80_repair_zero,25810802,9139ab3d637498f7fb40f71d531a674098164a3226057cbd51dfb85be1b7da70,,
7
+ weights/codec_payloads/avif_q70.avif,codec_payload,AVIF Q70,avif_q70_raw;avif_q70_repair_zero,29691217,b83258bd00e22d5e5d21236f5c441971c7c94b246e63d6eb6b41a1e23ce7952a,,
8
+ weights/codec_payloads/jxl_d1.jxl,codec_payload,JPEG XL distance 1,jxl_d1_raw;jxl_d1_repair_zero,39437937,e7ef2f74cc503897f120d3b414c61bdcb198c8c91c012fa65c668f47c119966d,,
9
+ weights/protected/high_byte.png,protected_high_byte,PNG lossless,jpeg_q100_protected_high;jpeg_q80_protected_high;webp_q80_protected_high;avif_q70_protected_high;jxl_d1_protected_high,32686473,82b3031ec79cf1541334e3f454a0af8705da2166f6bde7780196dd1e024df5ab,,
10
+ weights/protected/low_byte/jpeg_q100_low.jpg,protected_low_byte,JPEG Q100,jpeg_q100_protected_high,63199775,99c2c391d129bd1df40e58a25f79ee8b954c7e78fcb1814774b4bf7ac3a6e277,95886248,f660afccf973caa294d8778a4b29596b0ab41266102e822944c5abb6f0982f74
11
+ weights/protected/low_byte/jpeg_q80_low.jpg,protected_low_byte,JPEG Q80,jpeg_q80_protected_high,24229532,d32d9d1e7be1ea666a37fd761e1c74f94445562120313d01ba940711baeeddb1,56916005,30feef679679487aebd1e075cceea5823778c8cdec6643ec9e7296a04fb24000
12
+ weights/protected/low_byte/webp_q80_low.webp,protected_low_byte,WebP Q80,webp_q80_protected_high,23230766,f200066cf1ffbace7aaa9733d3a5c017379037e4e5fa58b8b09b3c6985655fc9,55917239,f04180148fa0decf546c978319c45c683b38d9264d6ccef14a5b0feb697226c1
13
+ weights/protected/low_byte/avif_q70_low.avif,protected_low_byte,AVIF Q70,avif_q70_protected_high,21791910,1698fedd0949bfdcf787576d35a81192e6f1adfc21f3499acb610d67d7a443e4,54478383,cd648cea401a6491c4f0829880ac483b497756266f6824548420606142aa7f62
14
+ weights/protected/low_byte/jxl_d1_low.jxl,protected_low_byte,JPEG XL distance 1,jxl_d1_protected_high,23636365,a58701006f3b535cfc27473f9ae741c7d3d888c1f7741c53d047d91c82d0a050,56322838,637e8752eb53d94ffd2f2ee997292382d67afc405139dc9a50bd4d3061cb6877