Grail Computer · research record
Dated experiment record. Statements describe this run, not current submission readiness. Historical H. pylori category names do not establish infection; copy screens are bounded tests. Claims that a source does not exist mean none was identified in that recorded search, not proof of absence. Licensing interpretations in the notes remain unconfirmed. Local access details have been omitted. Current limitations and remaining work.

SWEEP-V2: the v2 cartoon sweep, and what the generator did with it

Work package SWEEP-V2 of the SGH programme (operations/research/sgh-program-20260908/PLAN.md), 8 September 2026. Two spot A100s (fleet slots b and c) ran the 232-job sweep-v2 package to completion, then the whole thing was evaluated on CPU. Slots a and d were not touched. Nothing was committed to git.

Engineering evidence only. Every number below is an image-only measurement — shape, spacing, texture, colour, or one pathology encoder. Nothing here diagnoses, grades or stages anything, no number says an image is diagnostically correct, no pathologist has seen any of it, and Yash has not reviewed a sheet. Every "better" or "worse" names its instrument and its n.

Headline

232 of 232 planned generations landed: 232 records, 232 PNGs, every one non-empty and hashing to its record's output_sha256, 0 skipped manifests, 0 failed jobs, no preemption. The two fix-* jobs reproduced sweep-v1's zero-byte pass-2 image exactly, byte for byte.

On the question the package existed to answer — do gland-calibre cartoon lumens survive the two-pass repaint better than A1's pit-sized rosettes?the answer is no. Pass 1 follows the v2 cartoon slightly better in absolute lumen IoU (0.574 vs 0.544) but identically as a fraction of its own ceiling (89% vs 90%), and by pass 2 the v2 layout has collapsed further than v1's: lumen IoU 0.017 vs 0.084 at start_index 6, 0.044 vs 0.056 at start_index 3, and ring_with_lumen_fraction 0.076 vs 0.221 at si6. The v2 cartoons are a better drawing of a gland and a worse conditioning signal for this generator.

What did improve, consistently and on every category: detail. Mean absolute Laplacian rises 13.18 → 17.03 at pass 1, 17.07 → 18.80 at si6, 19.05 → 19.90 at si3 (real held-out 22.77). And median_ring_area_um2 at pass 2 is now 423-428 um2 against a real 403 (v1: 435-441). The morphometric envelope distance, though, is worse pooled at every depth (si3 pooled D 6.28 vs 5.64): by category, normal improves (6.79 vs 7.10), gastritis regresses (6.14 vs 5.77), IM and mixed are level.

The mechanism is visible in the images and is the risk A1V2_RESULT.md named in its own section 7 item 6: the 5.8-um chromatin-granule lattice that makes ring_topology seal the gland wall is a rendering trick, and the generator reads it as nuclei. The v2 pass-1 output is a regular, evenly spaced field of oval nuclei rather than a wall around a lumen, and a regular field of nuclei has no pale enclosed rings — hence ring_with_lumen_fraction medians of exactly 0.000 at si6 for normal and gastritis, and 0.000 in six of the twelve (category x cut) cells.

Two engineering faults were found in the evaluation harness while doing this, one of which invalidates numbers already published:


1. Timeline

All times UTC, 8 September 2026. Slot map: package slot0 -> fleet b (sgh-histo-qwen-a100-recovery-b, us-central1-b), slot1 -> fleet c (sgh-a100-slot-c, us-central1-c).

what slot b (slot0) slot c (slot1)
instances start issued 18:17:44 18:17:45
ssh + GPU ready 18:18:56 (72 s) 18:18:49 (64 s)
stage (37 / 35 files) 18:20:20-18:21:53 (93 s) 18:20:20-18:21:50 (90 s)
pre-render launched 18:23:00 18:23:00
token-library + token-stats copied from the v1 run root 18:23:02-03 (191 + 193 MB) 18:23:01-02
a1 fix cartoon copied verbatim 18:23:03 -
8 render chunks finish 18:33:27 18:33:40
cartoons/{a1v2,d1v2} published 18:33:30 18:33:43
launch 18:33:57 18:34:25
first generation 18:34:26 (fix-pass1) 18:34:43 (a1v2-pass1)
fix-pass1 / fix-pass2 done 18:35:53 / 18:37:04 -
last generation, WORKER_DONE 0 19:54:59 19:53:57
retrieve (1.7 GB), SHA256SUMS 19:54:59-20:04:53, 116 files OK 19:53:57-20:03:44, 116 files OK
retrieve VM label maps (20 MB) 20:05:02-20:05:17 20:03:46-20:04:08
stopped 20:06:30 20:05:25

Setup, boot to first generation: 16.7 minutes (SWEEP-RUN's was 45). Generation 80.6 / 79.2 minutes. Retrieval ~10 minutes each, in parallel.

fleet.sh status after the run:

SLOT  VM                               ZONE            STATUS
a     sgh-a100-slot-a                  us-central1-a   TERMINATED
b     sgh-histo-qwen-a100-recovery-b   us-central1-b   TERMINATED
c     sgh-a100-slot-c                  us-central1-c   TERMINATED
d     sgh-a100-slot-d                  us-central1-f   RUNNING      <- F2, untouched

What the 16.7-minute setup bought

SWEEP-RUN's fix 4 (render the cartoon sets in parallel chunks before launch, so the A100 is never idle behind a single-threaded CPU renderer) was applied from the start, plus two additions:

The manifests use token_reference only, so the worker's own dependency scan reported libraries=[] token_stats=0 and neither library was needed. The copy cost 2 seconds and was insurance against a worker that decided to rebuild them (~50 minutes of A100 each).

The a1 cartoon for the fix job was copied, not re-rendered

packages/sweep-v1/retrieved/records.jsonl records the sweep-v1 pass-1 job's reference_sha256 = c4c934f7…; that cartoon was rendered on fleet slot a, which is busy. Slot b's own v1 run root carries cartoons/a1/intestinal_metaplasia_s14_oblique_cartoon.png hashing to exactly the same c4c934f7…, so prerender.sh copied it verbatim rather than re-rendering. That is what makes the sha comparison in section 4 a real determinism test rather than a re-derivation — and it is itself evidence that slot a and slot b render this cartoon identically, which section 5 extends to slots b and c across all 210 a1v2/d1v2 files.

2. Cost and powered minutes

From fleet/state/<slot>/powered.log, one session per slot, no preemption.

slot VM zone up down minutes
b sgh-histo-qwen-a100-recovery-b us-central1-b 18:18:03 20:06:30 108.45
c sgh-a100-slot-c us-central1-c 18:18:05 20:05:25 107.33
215.8 min = 3.60 h USD 7.62

At USD 2.12/h for a spot a2-highgpu-1g, plus roughly USD 0.41 of internet egress for the 3.4 GB retrieved (3.4 GB of PNGs + 41 MB of label maps).

GPU utilisation: 2.51 GPU-hours of generation against 3.60 powered hours = 69.8%, against SWEEP-RUN's 56%. The remaining 30% is 1.2 min boot, 1.5 min stage, 10.5 min pre-render, ~10 min retrieval, per slot.

Throughput, from the 232 records' own elapsed_seconds:

start_index steps denoiser calls n median s mean s min max
12 8 48 86 32.02 28.46 23.54 34.15
6 14 84 86 45.57 42.01 37.09 45.94
3 17 102 60 52.36 49.59 43.89 52.69

Total 9036 s = 2.51 GPU-hours, mean 38.9 s per 4096x2048 canvas. This reproduces SWEEP-RUN's figures (31.84 / 45.29 / 52.28 s medians) to within 0.2 s at every depth, on the same two VMs four hours later.

3. Coverage: expected vs present, per manifest

packages/sweep-v2/retrieved/merge_records.py (adapted from sweep-v1's) merges the two slots, rewrites each output to slot<i>/out/<path>, adds slot and fleet_slot, and — the addition sweep-v1 needed and did not have — re-hashes every PNG and compares it with the record's output_sha256. sweep-v1's coverage check tested existence only, which is how a zero-byte file was reported as present (EVAL_RESULT.md section 1.1).

manifest b exp/rec/ok c exp/rec/ok total
fix-pass1 1/1/1 - 1
fix-pass2 1/1/1 - 1
a1v2-pass1 30/30/30 30/30/30 60
a1v2-pass2 30/30/30 30/30/30 60
a1v2-pass2-si3 30/30/30 30/30/30 60
d1v2-pass1 12/12/12 13/13/13 25
d1v2-pass2 12/12/12 13/13/13 25
slot total 116/116/116 116/116/116 232

evidence/manifest-summary.json: slot b {"ran":7,"skipped":0,"failed":0}, slot c {"ran":5,"skipped":0,"failed":0}. 232 of 232 outputs exist, are non-empty and hash to their record's output_sha256. 0 duplicate records. All 232 canvases are 4096x2048. 232 of 232 records have token_source equal to their extra.expected_token_source (token_reference throughout). By experiment: a1v2 180, d1v2 50, a1 2. By category: IM 97, normal 45, gastritis 45, mixed 45.

No preemption occurred, so the resume path was not exercised here; FLEET_RESULT.md and SWEEP_RESULT.md both verified it record-by-record.

4. The fix job: sweep-v1's zero-byte image is recovered, exactly

packages/sweep-v2/fix_check.py, output in packages/sweep-v2/eval/fix-check.json.

a1_p1_…s14_oblique (control) a1_p2_…s14_oblique (the repair)
v1 recorded output_sha256 f130a886…d936b575 1779fb07…d042dbb4
v2 recorded output_sha256 f130a886…d936b575 1779fb07…d042dbb4
v2 file on disk, re-hashed f130a886…d936b575 1779fb07…d042dbb4
v1 file on disk 13 630 331 bytes, f130a886… 0 bytes
v2 file on disk 13 630 331 bytes 15 042 363 bytes
reference_sha256 identical (c4c934f7…) identical (f130a886…)
final_latent_sha256 identical (00178959…) identical (1d1e0ccb…)
produced on v1 slot a (us-central1-a) v1 slot a / v2 slot b (us-central1-b)

Pass 1 reproduced sweep-v1's bytes exactly on a different VM in a different zone five hours later — the control that says the generator is deterministic on this rig — and the regenerated pass 2 hashes to precisely the output_sha256 sweep-v1's record claimed for the file that came back empty. The image is recovered, at packages/sweep-v2/retrieved/slot0/out/a1/pass2/intestinal_metaplasia/intestinal_metaplasia_s14_oblique.png. Anyone re-running the sweep-v1 evaluation can copy it into place and the IM pass2-si6 cell becomes n = 5 rather than n = 4.

5. The evaluation, and the harness change it needed

P=research/sgh-synthetic-histopathology/.venv/bin/python
$P packages/sweep-v2/retrieved/merge_records.py
$P packages/sweep-v1/evaluate_sweep.py all \
     --records packages/sweep-v2/retrieved/records.jsonl \
     --out packages/sweep-v2/eval --jobs 12 --probes \
     --exp-alias a1v2=a1,d1v2=d1 --exp-drop a1

stage_a1, stage_d1, arm_label, base_cartoon and the sheets all key on extra.exp being literally "a1" / "d1", so an unaliased run reports "no data" for everything. --exp-alias NEW=OLD and --exp-drop were added to packages/sweep-v1/evaluate_sweep.py — additive, default no-op, 4 hunks. --exp-alias rewrites extra.exp on load and keeps the original in extra.exp_raw and in a new exp_raw column of features.csv; nothing on disk is renamed. --exp-drop removes records by their original exp before aliasing, which is how the two genuine a1 fix records are kept out of the aliased a1 rows (they are checked separately in section 4). Verified on a 5-record fixture: 3 records with exp=a1v2 came out as set=sweep_a1, exp=a1, exp_raw=a1v2, and 2 real a1 records were dropped. Re-running sweep-v1's evaluation without the flags is unchanged except that features.csv gains the exp_raw column.

Everything else is the harness as EVAL-RUN left it, --ncc-refs at its default targeted. Wall clock: features 100 s, a1 <1 s, d1 9 s, arms 13 s, screens 240 s (embed 119 s + 222 NCC pairs), sheets, select, report — about 11 minutes, plus the extra measurements below.

The two measurements EVAL-RUN added by hand

EVAL-RUN's a1-layout-iou and within-arm-diversity scripts were not shipped, so both were rewritten against the harness's own functions (evaluate_sweep._d1_one, analysis_masks, label_mask, iou, the same sydney_qa_v1.json) as packages/sweep-v2/layout_iou.py and packages/sweep-v2/within_arm_diversity.py. The rewrite reproduces EVAL-RUN's own file exactly where they overlap — e.g. within_arm_diversity.py run on sweep-v1's features.csv gives real held-out IM 0.0347 and a1 pass2-si3 IM across 0.4906, both identical to packages/sweep-v1/eval/within-arm-diversity.json. sweep-v1's arms were re-measured with it so both sides of every diversity comparison come off one instrument.

The VM-vs-Mac cartoon caveat is now closed

EVAL_RESULT.md section (c) had to measure every layout IoU against the local Mac cartoon label maps, because the VM-rendered cartoons were never retrieved, and flagged that as its caveat. This package retrieved them (20 MB per slot, retrieved/aux/slot{0,1}/cartoons/).

check result
a1v2: slot b's 180 files vs slot c's 180/180 byte-identical
d1v2: slot b's 30 files vs slot c's 30/30 byte-identical
a1v2: VM vs Mac, by kind cartoon 0/60, labels 0/60, json 3/60 identical
a1v2 label maps, VM vs Mac: differing pixels 11.45%, of which 99.65% are stroma <-> stroma_nucleus
a1v2 label maps: lumen mask IoU, VM vs Mac median 1.000000, min 0.999979
a1v2 label maps: epithelium (2,3,4) mask IoU median 0.999867, min 0.994443
d1v2 label maps: lumen mask IoU median 1.000000, min 1.000000
measured lumen IoU of all 230 outputs, VM labels vs Mac labels identical to 4 decimals in every arm

So the two machines still disagree only about the stochastic scatter of stromal nuclei (the numpy/scipy/Pillow skew SWEEP_RESULT.md section 6 characterised), the lumen label is bit-identical, and EVAL-RUN's Mac-based IoU numbers were safe. Both are reported below anyway (a1-layout-iou-vm.* and a1-layout-iou-mac.*); they agree.

The IoU ceiling is reported from the mac run only: the retrieved aux tree carries label maps, not the 734 MB of cartoon RGB, so a VM-labels ceiling would have to pair a Mac RGB with a VM label map. layout_iou.py --ceiling off refuses that mixture rather than silently producing it.


6. (a) a1v2 per category, beside a1 and the real held-out fields

Medians per category pooled over the three cuts, n = 15 per arm (v1 IM pass2-si6 is n = 14 because of the zero-byte file). env pct is the percentage of that category's real held-out fields at or below this image's envelope distance, so 50 is the real median and 100 is outside the whole real spread. D is the C1 MinCovDet Mahalanobis. lap is C2's mean absolute Laplacian. cart IoU is the lumen IoU against the output's own cartoon label map (VM bytes). within SSIM is the mean pairwise SSIM inside that (arm, category) — real held-out fields sit at 0.034-0.047. The last three columns are the copy screens: phikon-v2 max cosine (fail line 0.95), the fraction of candidate tiles whose nearest real reference is their own donor field, and the max pixel NCC (threshold 0.92). Generated by packages/sweep-v2/report_tables_sweep_v2.py; full file packages/sweep-v2/eval/tables.md.

category arm n ring mean ring med ring dens med ring area D env pct lap cart IoU within SSIM max cos own-src NCC max
normal real held-out 4 0.854 0.884 101 442 3.33 62 22.78 - 0.038 - - -
OLD fullset pass 2 5 0.726 0.826 162 458 8.64 100 14.00 - 0.527 - - -
v1 a1 pass 1 15 0.386 0.441 244 526 8.48 100 11.90 0.722 0.286 - - -
v1 a1 pass2-si6 15 0.339 0.473 141 425 7.43 100 15.64 0.113 0.605 0.874 0.892 0.716
v1 a1 pass2-si3 15 0.591 0.678 113 404 7.10 100 18.12 0.072 0.623 0.905 0.925 0.864
v2 a1v2 pass 1 15 0.199 0.163 168 697 8.40 100 17.49 0.687 0.376 - - -
v2 a1v2 pass2-si6 15 0.051 0.000 124 399 9.68 100 18.86 0.003 0.629 0.895 0.917 0.773
v2 a1v2 pass2-si3 15 0.568 0.686 101 401 6.79 100 19.73 0.041 0.631 0.920 0.942 0.867
gastritis real held-out 6 0.743 0.807 89 365 4.19 58 20.40 - 0.047 - - -
OLD fullset pass 2 5 0.475 0.433 128 435 6.32 83 14.95 - 0.507 - - -
v1 a1 pass 1 15 0.371 0.387 157 769 11.53 100 15.47 0.554 0.357 - - -
v1 a1 pass2-si6 15 0.062 0.026 107 414 7.76 83 17.55 0.022 0.588 0.888 0.792 0.696
v1 a1 pass2-si3 15 0.394 0.294 96 403 5.77 83 18.60 0.053 0.586 0.900 0.925 0.720
v2 a1v2 pass 1 15 0.203 0.162 130 1057 11.52 100 17.31 0.651 0.433 - - -
v2 a1v2 pass2-si6 15 0.028 0.000 107 434 8.37 100 18.59 0.007 0.594 0.873 0.800 0.691
v2 a1v2 pass2-si3 15 0.353 0.200 107 405 6.14 83 19.07 0.048 0.588 0.898 0.925 0.667
IM real held-out 6 0.710 0.774 120 438 2.58 58 23.62 - 0.035 - - -
OLD fullset pass 2 5 0.917 0.927 186 435 5.28 100 14.62 - 0.477 - - -
v1 a1 pass 1 15 0.405 0.459 187 724 7.81 100 12.33 0.508 0.293 - - -
v1 a1 pass2-si6 14 0.251 0.244 170 432 5.56 100 16.90 0.097 0.551 0.887 0.902 0.728
v1 a1 pass2-si3 15 0.645 0.506 153 436 4.67 100 19.32 0.054 0.559 0.879 0.867 0.752
v2 a1v2 pass 1 15 0.186 0.194 128 913 8.87 100 16.31 0.554 0.398 - - -
v2 a1v2 pass2-si6 15 0.092 0.032 147 456 5.67 100 18.64 0.045 0.569 0.903 0.825 0.745
v2 a1v2 pass2-si3 15 0.596 0.447 145 418 4.76 100 20.13 0.042 0.563 0.881 0.875 0.784
mixed real held-out 6 0.726 0.774 101 441 3.66 58 22.77 - 0.034 - - -
OLD fullset pass 2 5 0.726 0.766 141 433 6.74 100 16.64 - 0.481 - - -
v1 a1 pass 1 15 0.411 0.438 150 826 9.19 100 13.87 0.505 0.325 - - -
v1 a1 pass2-si6 15 0.236 0.233 143 463 7.35 100 18.03 0.095 0.560 0.876 0.883 0.647
v1 a1 pass2-si3 15 0.530 0.509 120 484 5.78 100 20.82 0.057 0.568 0.899 0.950 0.677
v2 a1v2 pass 1 15 0.191 0.196 111 1129 10.94 100 17.54 0.547 0.435 - - -
v2 a1v2 pass2-si6 15 0.134 0.109 145 456 8.32 100 20.10 0.075 0.576 0.889 0.883 0.691
v2 a1v2 pass2-si3 15 0.494 0.491 124 487 5.69 100 21.69 0.044 0.573 0.898 0.942 0.666

Pooled over all four categories (n = 60 per arm; the cartoon-IoU column is repeated for the VM and the Mac label maps, which agree):

arm n ring mean ring med ring dens med ring area D lap cart IoU (VM) cart IoU (Mac)
real held-out 22 0.750 0.841 95 403 3.51 22.77 - -
OLD fullset pass 2 20 0.711 0.791 147 435 6.50 14.89 - -
v1 a1 pass 1 60 0.393 0.425 167 685 8.87 13.18 0.544 0.544
v1 a1 pass2-si6 59 0.221 0.174 141 441 7.35 17.07 0.084 0.084
v1 a1 pass2-si3 60 0.540 0.503 119 435 5.64 19.05 0.056 0.056
v2 a1v2 pass 1 60 0.195 0.179 128 962 9.99 17.03 0.574 0.574
v2 a1v2 pass2-si6 60 0.076 0.015 135 428 8.12 18.80 0.017 0.017
v2 a1v2 pass2-si3 60 0.503 0.445 120 423 6.28 19.90 0.044 0.044

7. Did gland-sized lumens survive the repaint better than v1's?

No. The direct instrument is lumen IoU against the output's own cartoon label map, read against the ceiling that map can reach at all (the cartoon PNG measured against itself through the same masks):

set ceiling (n, min-max) pass 1 (si12) pass 2 si6 pass 2 si3
a1 (v1) 0.604 (60, 0.393-0.907) 0.544 = 90% 0.084 = 14% 0.056 = 9%
a1v2 (v2) 0.644 (60, 0.431-0.835) 0.574 = 89% 0.017 = 2.6% 0.044 = 6.8%
d1 (v1) 0.407 (10, 0.393-0.423) 0.353 = 87% 0.060 = 15% -
d1v2 (v2) 0.580 (10, 0.540-0.609) 0.536 = 92% 0.035 = 6.0% -

The v2 cartoons are a better target: their self-IoU ceiling is higher (0.644 vs 0.604 for the a1 grid; 0.580 vs 0.407 for the d1 grid), which is exactly what "gland-calibre lumens instead of pit-sized rosettes" should do to a lumen metric. And pass 1 tracks them just as faithfully — 89% of ceiling against v1's 90%, an absolute IoU of 0.574 against 0.544. That part of A1-V2's hypothesis holds.

But the collapse at pass 2 is worse, not better: 2.6% of ceiling at si6 against v1's 14%, and 6.8% at si3 against 9%. The same is true of the topology metric: ring_with_lumen_fraction pooled falls 0.393 → 0.221 → 0.540 across the v1 ladder and 0.195 → 0.076 → 0.503 across the v2 one, with medians of exactly 0.000 at si6 for normal and gastritis. Bigger lumens did not make the repaint keep them; they made pass 1's rings too big (median ring area 962 um2 against a real 403 and v1's 685) and left pass 2 with nothing.

By cut, pooled over categories (n = 20 per cell):

set arm across along oblique
v1 a1 pass 1, ring / IoU 0.434 / 0.493 0.116 / 0.535 0.629 / 0.556
v2 a1v2 pass 1, ring / IoU 0.209 / 0.572 0.108 / 0.548 0.268 / 0.666
v1 a1 si6, ring / IoU 0.149 / 0.026 0.204 / 0.101 0.316 / 0.099
v2 a1v2 si6, ring / IoU 0.071 / 0.005 0.092 / 0.055 0.066 / 0.008
v1 a1 si3, ring / IoU 0.526 / 0.051 0.527 / 0.056 0.567 / 0.066
v2 a1v2 si3, ring / IoU 0.508 / 0.042 0.507 / 0.043 0.493 / 0.047

The v2 oblique cut is the best-followed cell anywhere in either sweep at pass 1 (IoU 0.666), which is consistent with A1-V2's oblique_frame="mid" change — that frame carries no background at all. It buys nothing by pass 2: v1's oblique advantage at si6 (0.316 ring) is gone in v2 (0.066).

8. Did realism change?

Detail: yes, better, everywhere. C2 called the Laplacian "the largest single lever on the tell", and it moves toward real at every depth and in every category:

arm v1 lap v2 lap real held-out
pass 1 13.18 17.03 22.77
pass 2 si6 17.07 18.80 22.77
pass 2 si3 19.05 19.90 22.77

v2's mixed pass2-si3 at 21.69 is the closest any generated arm in either sweep has come to the real 22.77.

Envelope: no, worse. Pooled MinCovDet distance D is 9.99 vs 8.87 at pass 1, 8.12 vs 7.35 at si6, and 6.28 vs 5.64 at si3 (real held-out 3.51). The per-category si3 medians are normal 6.79 vs 7.10 (better), IM 4.76 vs 4.67 (level), mixed 5.69 vs 5.78 (level), gastritis 6.14 vs 5.77 (worse) — so v2 is not uniformly worse; the pooled median rises because it sits in the middle of the four cells, and gastritis moving up 0.37 while normal moves down 0.31 shifts the middle of the 60-value distribution upward. The honest summary is: normal improves, gastritis regresses, IM and mixed are level, and the pooled figure follows gastritis. Envelope percentile stays saturated: every median except gastritis si3 (83) sits at 100, as it did for v1.

Fraction of pass-2 outputs inside both the real ring range and the real envelope band:

n ring in range inside band both
v1, whole sweep (9 sets) 249 107 41 23 (9.2%)
v1 a1 pass2-si3 60 39 22 14 (23.3%)
v2, whole sweep (2 sets) 145 48 27 11 (7.6%)
v2 a1v2 pass2-si3 60 40 21 11 (18.3%)

All 11 of v2's are pass2-si3: gastritis 5, IM 6. No normal or mixed output is inside both bands (v1 had one normal). Pareto selection (eval/candidates.csv) picks 32 candidates, 8 per category, all on the front, and a1v2 pass2-si3 supplies 26 of them, pass2-si6 5 and d1v2 donor0 1.

Diversity within an arm is slightly worse. Mean pairwise SSIM inside each (arm, category), on the identical instrument for both sweeps (real held-out fields sit at 0.034-0.047; the old two-pass baseline at 0.477-0.527):

arm normal gastritis IM mixed
v1 pass 1 / v2 pass 1 0.286 / 0.376 0.357 / 0.433 0.293 / 0.398 0.325 / 0.435
v1 si6 / v2 si6 0.605 / 0.629 0.588 / 0.594 0.551 / 0.569 0.560 / 0.576
v1 si3 / v2 si3 0.623 / 0.631 0.586 / 0.588 0.559 / 0.563 0.568 / 0.573

The v2 pass-1 outputs are markedly more like one another (+0.08 to +0.11 SSIM) than v1's, which is what a more uniform conditioning field produces. By pass 2 the difference is within 0.02.

9. Copy screens, and a probe-cache fault that invalidates published numbers

Copy screens: nothing fails. phikon-v2 embedding screen over all 145 pass-2 outputs, 1160 candidate tiles against 118 real reference fields, fail line 0.95: max cosine 0.9196, 0 flagged tiles, passed: true, minimum copy margin 0.0304 (on a1v2 pass2-si3). Pixel NCC search (64 px window, stride 256, threshold 0.92, targeted references): 222 pairs, max NCC 0.8666, 0 flagged windows, 0 failures. Both margins are tighter than sweep-v1's (0.9049 / 0.0451 / 0.8635) but neither crosses its line. Own-source tile fraction is high and slightly higher than v1's in three categories (0.917-0.942 for normal/mixed si3), which is donor dependence, not copying — the same distinction EVAL_RESULT.md section (i) drew.

The probe embedding cache is keyed on the set name

probes/run_probes.py line 228 skips embedding any set whose probes/embeddings/<set>__1024.npz already exists, and evaluate_sweep.py never passes --force-embed. Both sweeps register their experiments under the same names (sweep_a1, sweep_d1, …). Consequences, both verified:

  1. This package's probe stage twice reported sweep-v1's numbers (13.3 s for a run that should take ~340 s; sweep_a1 "600 tiles", frac_nearest_in_own_donor_field 0.7716666… identical to sweep-v1's to 16 decimals). Deleting the two stale .npz and re-embedding by hand gave sweep_a1 1440 tiles from 180 fields and different numbers.
  2. Worse: the cached files were never built from the real sweep at all. Reading the provenance inside every sweep_*__1024.npz in probes/embeddings/:
cache tiles fields every tile's source
sweep__1024.npz 240 20 packages/sweep-v1/standin/
sweep_a1__1024.npz 600 55 packages/sweep-v1/standin-rich/
sweep_a2, a3, b1, d1, d2, e2 320/320/80/400/160/240 20/20/5/25/20/15 packages/sweep-v1/standin-rich/

Those are EVAL-BUILD's dry-run fixtures. EVAL_BUILD_RESULT.md section 6.1 describes standin-rich/ as "265 records over the same 30 PNGs" of the old two-pass fullset run, re-labelled across a1/d1/a2/a3/d2/e2/b1, and says in bold that "the pixels are unrelated to the provenance stamped on them ... every table it produces is meaningless as science". load_sets' own docstring — "refresh provenance from the current manifest, so a provenance fix never forces a re-embed" — is what makes the mismatch invisible downstream: the tile labels come from the real manifest, the vectors from the fixture. Every probe A/B/C/D figure EVAL_RESULT.md quotes for a sweep_* set was therefore computed on 30 old-fullset PNGs wearing sweep labels, including its "probe B puts 77.2% of a1 tiles nearest their own donor field", its "probe A separates every one of the nine sweep sets from real tissue at 100% of fields called generated" and its probe-D percentiles. The non-sweep sets (real_heldout, gen_pass2, native_*, lock_*) come from C2's own caches and are unaffected — they reproduce exactly in every run here.

All nine stand-in caches were copied to packages/sweep-v2/eval/cache/probe-embeddings-standin-backup/ and removed, sweep-v1's sets were re-embedded from the real retrieved PNGs, and its probe stage was re-run into packages/sweep-v2/eval/v1-probes-recheck/ (343 s, exit 0). probes/embeddings/ now holds real-image caches for the eight sweep-v1 sets (sweep_a1 1632 tiles from 145 fields, etc.); sweep__1024.npz, which only the standin/ fixture ever used, is in the backup and is no longer in probes/embeddings/. sweep-v2's own caches are kept separately in packages/sweep-v2/eval/cache/probe-embeddings-v2/, because two sweeps cannot occupy one set name at once — which is the defect. Corrected numbers:

probe set EVAL_RESULT.md (stand-ins) corrected v1 (real) v2 a1v2 / d1v2
B: tiles nearest their own donor field a1 0.772 (600 tiles) 0.684 (1632 tiles) 0.671 (1440 tiles)
d1 0.800 (400) 0.470 (400) 0.453 (400)
d2 / e2 0.825 / 0.650 0.394 / 0.463 -
A: tiles called generated a1 0.993 0.912 0.890
A: fields called generated a1 1.000 0.986 0.958
A: mean tile score a1 0.988 0.903 0.876
D: median percentile in held-out a1 71.0 71.6 61.9
D: same, excluding the donor slide a1 96.6 96.6 95.5

Read carefully: probe A trains its discriminator on whatever sets are in the pool, and the v1 pool had nine sweep sets against v2's two, so the a1-vs-a1v2 A comparison is indicative, not controlled. Probe B is a nearest-neighbour count and does not have that problem. On probe B, donor dependence is essentially unchanged between the two cartoon sets (0.684 → 0.671 for the a1 grid, 0.470 → 0.453 for the d1 grid) — the v2 cartoons did not loosen the generator's grip on its donor field. d1v2 at 0.453 is the lowest of any single-donor arm measured.

10. The d1v2 layout factorial, beside d1

25 outputs per pass (5 cartoons x 4 donors, plus 5 rot180 on donor 0), the harness's own d1 stage.

measurement v1 d1 pass 1 v1 d1 pass 2 (si6) v2 d1v2 pass 1 v2 d1v2 pass 2 (si6)
SSIM, same cartoon / different donor 0.874 (n=30) 0.505 (n=30) 0.860 (n=30) 0.511 (n=30)
SSIM, same donor / different cartoon 0.301 (n=40) 0.870 (n=40) 0.421 (n=40) 0.901 (n=40)
SSIM, unrelated 0.282 (n=120) 0.482 (n=120) 0.389 (n=120) 0.496 (n=120)
lumen IoU vs own cartoon label map 0.353 (n=25) 0.060 (n=25) 0.536 (n=25) 0.035 (n=25)
— as a fraction of that set's ceiling 87% 15% 92% 6.0%
rot180: IoU vs the rotated map 0.355 (n=5) 0.062 (n=5) 0.550 (n=5) 0.045 (n=5)
rot180: IoU vs the unrotated map 0.033 (n=5) 0.020 (n=5) 0.018 (n=5) 0.012 (n=5)
— preference for the rotated map 10.8x 3.1x 30.6x 3.8x
donor epithelium-mask NCC, max over shifts 0.125 (n=25) 0.328 (n=25) 0.135 (n=25) 0.342 (n=25)
ceiling: the cartoon against its own label map 0.407 0.580

IoU by donor arm — flat across arms means the donor is not setting the layout:

eval pass donor0 donor1 donor2 donor3 rot180 spread
v1 d1 1 0.360 0.339 0.331 0.355 0.355 0.029
v1 d1 2 0.061 0.006 0.000 0.089 0.062 0.089
v2 d1v2 1 0.548 0.521 0.512 0.536 0.550 0.036
v2 d1v2 2 0.052 0.000 0.000 0.090 0.045 0.090

The v1 conclusion is reproduced exactly and sharpened: at pass 1 the cartoon sets the layout and the donor sets almost nothing — IoU 0.536, 92% of ceiling, flat to 0.036 across four donors, and a rot180 output prefers the rotated label map by 30.6x (v1: 10.8x). By pass 2 that has inverted: same-donor/different-cartoon SSIM 0.901 against same-cartoon/different-donor 0.511, IoU down to 6% of ceiling. The harness's pooled verdict is again "YES, 3 of 5 checks", and again that pooling is what makes it wrong; split by pass it is unambiguous, and the v2 numbers are a stronger version of the v1 ones in both directions.

The donor NCC (0.342) stays well below the native positive control on the same donors (native_generate 0.409, native_img2img 0.642), so pass 2 is still not a spatial re-registration of the donor field — it inherits the donor's content and appearance, not its coordinates.

11. Looking at the images

packages/sweep-v2/eval/sheets-v1v2/v1v2-<category>.png — per category, rows = seed 11 x three cuts, columns = real held-out | v1 cartoon | v1 pass2-si3 | v2 cartoon | v2 pass 1 | v2 pass2-si6 | v2 pass2-si3. Every cell is the identical 768 x 768 px window (192 x 192 um at 0.25 um/px) at x = 1664, y = 640 of its 4096 x 2048 field, shown at 384 px; sheets-v1v2-1to1/ is the across row at 1:1 pixels. Real held-out cells are different tissue from different slides, not the same field. I looked at all four sheets and both 1:1 strips. Honestly:

12. Is normal or gastritis better than v1 on any instrument?

Normal: yes, on four of the eight measures below. At the best arm (pass2-si3, n = 15 each):

instrument v1 a1 v2 a1v2 real held-out verdict
envelope distance D 7.10 6.79 3.33 v2 better
Laplacian detail 18.12 19.73 22.78 v2 better
ring density per mm2 113 101 101 v2 better (exactly on the real median)
ring fraction, mean 0.591 0.568 0.854 level
ring fraction, median 0.678 0.686 0.884 level
ring inside the real range 33.3% 53.3% - v2 better
inside the envelope band 6.7% 0.0% - v1 better
median ring area um2 404 401 442 level

Normal was "the weakest category in the sweep on every count" in EVAL_RESULT.md; on the v2 cartoons it is better on the envelope, on detail, on ring density and on ring-in-range, and it still puts nothing inside the envelope band. It remains the category with no visible glandular lumens.

Gastritis: only on detail. D 6.14 vs 5.77 (worse), ring mean 0.353 vs 0.394 and median 0.200 vs 0.294 (worse), ring-in-range 33.3% vs 46.7% (worse), in-band 100% vs 100% (level — the gastritis band is the wide one, C1 limitation 2), Laplacian 19.07 vs 18.60 (better), median ring area 405 vs 403 (level). The pass-2-makes-gastritis-worse effect is still there and is if anything stronger: pass 1 0.203 -> si6 0.028.

IM and mixed are level on the envelope (4.76 vs 4.67; 5.69 vs 5.78) and better on detail (20.13 vs 19.32; 21.69 vs 20.82). IM si3 is v2's best both-bands cell (6 of 15 = 40%); the best cell in either sweep is still v1's gastritis si3 at 7 of 15 = 47%.

13. What this package found, in order of consequence

  1. The granule trick does not transfer. A1-V2 bought an in-band ring metric on the cartoon by putting dark 5.8-um granules in the epithelial cytoplasm so that ring_topology's 6-um closing would seal the gland wall. The generator reads those granules as nuclei, produces a regular cellular field, and the ring metric on the output collapses further than it did on the pit-sized rosettes. A conditioning signal has to be legible to the generator, not to the metric — a cartoon-side score is not a proxy for an output-side one. This is the single clearest result here.
  2. The cartoon controls layout only at pass 1, on both cartoon sets. v2 sharpens the v1 finding (92% of ceiling at pass 1, 30.6x rot180 preference) and reproduces the pass-2 inversion exactly. The arm with the best envelope and detail (pass2-si3) is still the arm that has thrown the most geometry away.
  3. Detail is where the v2 cartoons pay. +3.85 Laplacian at pass 1, +1.73 at si6, +0.85 at si3, in every category. Which of a1v2's changes drives that was not ablated here — the candidates are the darker fibre strokes, the stronger basement rim, the apical pale cap and the granules themselves — so "keep the detail knobs, drop the granule lattice" is a hypothesis this package supports but does not test.
  4. Published probe numbers for the sweep are wrong (section 9). This is a harness/environment defect, not a modelling one, and the fix is one flag or a content-hashed cache key.
  5. The v1 zero-byte image is recovered exactly (section 4), and the merge script now re-hashes every PNG so the same fault cannot be reported as coverage again.

14. What this package did not do

15. Files

path (under operations/research/sgh-program-20260908/) what
packages/sweep-v2/retrieved/records.jsonl 232 merged records, output relative to retrieved/
packages/sweep-v2/retrieved/merge_records.py the merge, with per-PNG SHA-256 verification
packages/sweep-v2/retrieved/coverage.json expected/records/verified per manifest, integrity lists
packages/sweep-v2/retrieved/slot{0,1}/out/ 232 PNGs, 3.4 GB
packages/sweep-v2/retrieved/slot{0,1}/evidence/ steps.log, manifest-summary.json, SHA256SUMS, per-manifest generator logs
packages/sweep-v2/retrieved/evidence-slot{0,1}-* copies of the above next to the merged file
packages/sweep-v2/retrieved/aux/slot{0,1}/cartoons/ the VM-rendered label maps + sidecars + MANIFEST.sha256.json for a1v2, d1v2 (and a1 on slot 0)
packages/sweep-v2/retrieved/aux/cartoon-sha-comparison.json VM-vs-VM and VM-vs-Mac hash comparison
packages/sweep-v2/retrieved/aux/label-map-vm-vs-mac.json the pixel-level label-map difference and the lumen/epithelium mask IoU
packages/sweep-v2/eval/ the whole evaluation: EVAL_REPORT.md, features.csv, a1-table.csv, d1-*.csv, screen-*.csv, candidates*.csv, sheets/, probes/, stage-*.json
packages/sweep-v2/eval/a1-layout-iou-{vm,mac}.csv/.json, cartoon-iou-ceiling-mac.csv/.json the layout IoU against both label-map sets, and the ceiling
packages/sweep-v2/eval/within-arm-diversity.json, within-arm-diversity-v1.json within-arm SSIM, v2 and v1 on one instrument
packages/sweep-v2/eval/sheets-v1v2/, sheets-v1v2-1to1/ the 7-column contact sheets, 384 px and 1:1
packages/sweep-v2/eval/fix-check.json the sha comparison in section 4
packages/sweep-v2/eval/tables.md every table in sections 6-10, generated
packages/sweep-v2/eval/v1-probes-recheck/ sweep-v1's probes re-run on the real images
packages/sweep-v2/eval/cache/probe-embeddings-standin-backup/ the nine stand-in caches that were in probes/embeddings/ before this package
packages/sweep-v2/eval/cache/probe-embeddings-v2/ sweep-v2's own sweep_a1 / sweep_d1 tile embeddings
packages/sweep-v2/{layout_iou,within_arm_diversity,contact_sheets_v2,report_tables_sweep_v2,fix_check}.py, run_eval.sh the evaluation scripts this package added
code/render_chunk.py, code/manifest_dir.py parallel cartoon rendering and atomic set assembly
fleet/prerender.sh, fleet/run-v2.sh, fleet/drive-v2.sh, fleet/retrieve-aux.sh the on-VM pre-render and the per-slot driver
fleet/logs/v2-{b,c}.out, v2-up-*.out, v2-stage-*.out, v2-prerender-launch-*.out orchestrator logs
packages/sweep-v1/evaluate_sweep.py + --exp-alias, --exp-drop, the exp_raw column (additive, default no-op)

Download public Markdown export