Skip to content

Design decisions and fidelity trade-offs

Every benchmark that consolidates published methods makes choices the original papers never had to make. This page records those choices for PGVL-Gym: what was decided, what the alternative was, and — where a decision costs fidelity — what a reader must not conclude from the resulting number.

It is deliberately written as a ledger rather than a rationale. A reader comparing our numbers to a paper's needs to know exactly where the two diverge.


1. Provenance is recorded, never inferred

The framework's central commitment: a number carries the conditions that produced it. Provenance fields travel from the protocol into the generated config, the run matrix, and aggregate_results.csv.

Field Values Answers
encoder_provenance native, adapted Did the method's own code support this encoder, or does a trainable projection bridge it?
prompt_provenance upstream, generated, classname_template, or a role-qualified mixed condition such as upstream_instance_with_random_classname_bag Where did the embedded text for every prompt role come from?
prompt_source per-method, e.g. cod_chain_runtime_clip_rn50 Which asset and encoding path?
implementation_provenance vendored, mixed, reimplemented, or a precise partial variant Which method implementation actually ran?
upstream_fidelity upstream, partial, local_baseline May this number be described as an upstream reproduction?

All provenance fields are derived from the declared contract and the files on disk, not set by hand, so they cannot drift from what the run actually does.

FOCUS prompt origins and native schema

FOCUS reads a headerless one-column CSV positionally: all low-resolution class prompts, followed by all high-resolution prompts. The earlier PGVL three-column table was a local conversion, not the released schema. The shared loader, runtime, generator validator, and doctor now enforce the native format, explicit file-class binding, provenance, file hash, and ordered class-bound bank hash.

Local bank Origin Upstream status
CAMELYON16 upstream copy Byte-exact released CAMELYON bank
TCGA-NSCLC upstream copy Byte-exact released TCGA-Lung bank
UBC-OCEAN upstream copy Byte-exact released bank; file order CC, HGSC, LGSC, EC, MC is explicitly reordered to benchmark order
TCGA-BRCA generated FOCUS publishes no BRCA prompt CSV
TCGA-RCC generated FOCUS publishes no RCC prompt CSV

The three copies are pinned to commit 66c4015d5ba09657f4c8183bc06947faecd5b01f. The released UBC clear-cell high-resolution row contains unescaped quotes around hobnail; upstream pandas therefore preserves a trailing quote in the parsed text. PGVL preserves the file and parse exactly instead of silently creating a corrected prompt condition. BRCA/RCC extensions use the same native positional format but remain reported as generated.

MSCPT prompt origins

MSCPT prompt provenance follows the embedded text, not whether the protocol selected its path through a legacy field or an explicit prompts: mapping:

Benchmark bank Origin Fidelity note
TCGA-NSCLC Lung.json upstream copy Preserved verbatim, including the released LUSC-content issue described below
TCGA-RCC RCC.json upstream copy Task-matched released bank, 10 small_mag and 30 big_mag prompts per class
UBC-OCEAN UBC-OCEAN.json upstream copy Task-matched released bank, 10 small_mag and 30 big_mag prompts per class
TCGA-BRCA IDC/ILC generated MSCPT's released BRCA.json is a different High/Low recurrence/grade task; the local bank has 10 prompts at each scale
CAMELYON16 generated MSCPT releases no CAMELYON16 bank; this one is compiled from the local canonical prompt profile

MSCPT also releases a separate *_select_pic.json ensemble for offline low-magnification patch selection. The Lung, RCC, and UBC-OCEAN selector files are byte-exact upstream copies, contain 50 independently worded prompt sets, and are not interchangeable with the small_mag descriptions above. The feature-only runtime encodes those sets with the paired text tower, normalizes and averages templates within each set, then normalizes and averages across sets exactly as intended by select_5X_pic.py. The released script indexes 100 sets even though the published JSON assets contain 50; PGVL-Gym consumes the complete available 50-set bank instead of reproducing that out-of-range defect. BRCA IDC/ILC and CAMELYON16 have no task-matched selector bank, so their local extensions retain the generated multiscale-description fallback and do not claim upstream selector fidelity.

The upstream Lung.json places nine adenocarcinoma-associated descriptions in the LUSC block: small_mag indices 0 and 2, and big_mag indices 0, 1, 3, 8, 9, 28, and 29 (zero-based). They mention glandular/acinar architecture, mucin, lepidic growth, signet-ring cells, bronchioloalveolar carcinoma, or micropapillary morphology. MSCPT embeds these descriptions into the LUSC text representation, so this can affect NSCLC results. The upstream file remains unchanged: silently correcting it would create a new prompt condition while still appearing to be an upstream reproduction. The exact indices and policy are machine-readable in text_prompts/PROVENANCE.json.

Generated configs therefore report upstream for NSCLC, RCC, and UBC-OCEAN, and generated for the task-extended BRCA and CAMELYON16 banks. The separate upstream_fidelity: partial implementation label still applies. The feature-only integration now preserves the released branch roles: it sends the complete 20x bag to the full-bag graph and uses the dedicated selector ensemble for class-major, per-class ranking of the precomputed low-magnification bag before the sparse graph. The selection count is 30 patches per class for TCGA and 10 per class for UBC-OCEAN, as in the released task scripts; a short bag is retained with the same class-major duplication behavior. What remains bypassed is the deep visual-prompt image encoder applied upstream to selected RGB patches, because PGVL-Gym starts at final frozen feature files. This is a disclosed feature-only adaptation, not an upstream raw-tile reproduction.

ViLa-MIL prompt format and origins

ViLa-MIL's released prompt loader reads a headerless one-column CSV and splits exactly 2 * n_classes rows into all low-resolution prompts followed by all high-resolution prompts. The earlier PGVL integration incorrectly shared its local three-column FOCUS conversion, so header and class-name cells became prompt text and did not reproduce either upstream method. PGVL now keeps distinct method-owned native assets for ViLa-MIL and FOCUS, even though their released loaders use the same positional layout, and records each asset's file-class binding explicitly.

The TCGA-Lung and TCGA-RCC banks are byte-exact copies from ViLa-MIL commit 68a11cf0d5cf092dd980f0da1cb38ccac8747a82. ViLa-MIL publishes no BRCA, UBC-OCEAN, or CAMELYON16 prompt bank, so those files are generated task extensions and are never reported as upstream. The upstream RCC text spells the third class CRCC at both scales. That wording remains unchanged for fidelity; the provenance record and loader bind its third positional slot to the classifier's CHRCC label. File hashes protect exact copies, while an ordered prompt-bank hash protects the final classifier binding after any declared reordering.

The released PromptLearner has an executable indexing defect. It tokenizes the description alone, inserts 16 learned context embeddings before the description, but lets TextEncoder pool at the description's original end-of-text index. After insertion that position lies inside the learned context rather than at the shifted end-of-text token. PGVL-Gym uses the standard CoOp layout: it tokenizes 16 placeholder tokens plus the description, replaces only those placeholder embeddings with the trainable context, and pools at the resulting real end-of-text index. This corrective deviation is pinned as vila_prompt_layout: coop_16_context_eot_aligned_v1 and reported as partial implementation fidelity.

ViLa-MIL's paper explicitly defines the low-scale slide at 5x and high-scale slide at 10x. The former 5x/20x registration was a local configuration error. All current ViLa-MIL configs require vila_scale_recipe: upstream_5x_10x; the doctor rejects a different resolution binding instead of silently changing the method condition.

MAPLE prompt origins and ordering

MAPLE releases complete two-scale attribute graphs for TCGA-Lung, TCGA-RCC, and TCGA-BRCA only. The checked-in LUNG_attributes.json, RCC_attributes.json, and BRCA_attributes.json files are byte-exact copies from commit c38d5d5d55deba3a44e9384c0efeee98e1aec36b, with file hashes recorded in the provenance manifest. MAPLE publishes no UBC-OCEAN or CAMELYON16 bank: those are explicitly generated task extensions. The standalone UBC example now has a real generated asset instead of pointing to a nonexistent file.

Class-key order is semantic, not cosmetic. MAPLE iterates global_info and every entity's attributes mapping to build its class logits. The earlier doctor compared only key sets, so a JSON reordering could silently permute predictions relative to numeric labels. The shared loader, doctor, benchmark validator, and runtime now require every mapping to match classifier order exactly and verify registered upstream file hashes.

The registered NSCLC PLIP stores expose the 768-wide pooled vision output, whereas released MAPLE consumes already projected 512-wide patch features. The runtime therefore applies the pinned PLIP checkpoint's own frozen visual_projection before any MAPLE similarity or graph operation. Configs bind the source as hf:vinid/plip#vision-preprojection, the prompt tower as hf:vinid/plip, and the bridge as native_visual_projection; arbitrary or learned cross-encoder projections remain disallowed.

The paper and released executable disagree on training details. Section 5 of the NeurIPS paper specifies 5x/10x inputs, AdamW at 1e-4, and at most 80 epochs, while released run.sh/main.py use Adam at 2e-4 for 200 epochs. PGVL-Gym therefore keeps maple_paper_5x10x separate from the release-code variants. Its config records the local 224px cached-patch and patient-grouped split deviations rather than presenting the condition as an exact replication.

The released runtime also has an attribute-alignment defect. PromptLearner appends prompts entity-major—every class for entity 0, then every class for entity 1—but obtain_entities_attr reshapes that sequence as class-major. Most entity/class scores therefore consume another pair's description. PGVL restores the emitted entity-major shape directly. This is a disclosed upstream bug fix: the prompt files remain unchanged, but corrected runs are not claimed to reproduce that accidental permutation.

TOP prompt origins

TOP has two distinct prompt roles. Its instance learner uses 26 task-agnostic tissue prototypes; its bag learner uses task-specific class initializers. The standard assets now follow the active literals in the authors' released code:

Cohort/asset Instance prototypes Bag initializer Reported condition
TCGA-NSCLC 26 ordered entries copied from knowledge_from_chatGPT Exact two bagPrompt_ctx_init strings from train_TCGAFeat_MIL_CLIP.py upstream
CAMELYON16 Same released 26-entry bank Exact active normal/tumor initializers from train_CAMELYONFeat_MIL_CLIP.py upstream when TOP is enabled
TCGA-BRCA Same released 26-entry bank No upstream BRCA initializer; random learned context plus IDC/ILC classnames upstream_instance_with_random_classname_bag
TCGA-RCC / UBC-OCEAN examples Same released 26-entry bank No upstream task initializer; random learned context plus task classnames upstream_instance_with_random_classname_bag

The longer NSCLC class descriptions in supplementary Figure 4 are also copied and retained as top/tcga_nsclc_bag_prompts.json, but are marked alternative_unwired. They are a legitimate ablation condition, not the released training-script condition. The adapter accepts either complete code-faithful ctx_init literals or base prompts, checks class-index order and ten-slot placement, and no longer inserts a second period between an instance description and its learnable slots. It also preserves the release's tiny recipe difference: TCGA concatenates the first instance slot directly, while CAMELYON inserts a space. The instance asset records the pinned upstream commit and a digest over all 26 ordered rendered prompts. Every TOP asset is also bound to a manifest file hash and a semantic bank hash; the bag hash includes mode, classifier-label order, initializer text, and the class suffixes actually passed to PromptLearner. Checked-in configs repeat those trusted bindings. One shared loader enforces them in runtime, doctor, and benchmark generation and derives the reportable condition from the selected roles. Consequently, selecting the supplementary bank produces upstream_supplementary_condition, while omitting a published bag bank produces upstream_instance_with_random_classname_bag; neither can be mislabeled as the standard upstream condition.

The upstream trainer passes all_ctx_trainable=False to both prompt learners. PGVL-Gym therefore freezes every initialized description prefix and optimizes only its ten * embeddings. An earlier adapter omission inherited the constructor default True and inflated the trainable set to 2,170,912 parameters. Runtime, compiler, and doctor now enforce the released false setting.

TOP's paper defines the image/text comparisons as cosine similarities. Its released runtime normalizes text embeddings but relies on the private precomputed image-feature arrays to carry the corresponding image-side normalization. PGVL-Gym normalizes each external CLIP-RN50 patch row at model entry, making that mathematical contract explicit for Trident HDF5 bags. This prevents feature norms from saturating TOP's temperature-scaled routing and classification softmaxes. Optimizer liveness is checked across the complete first epoch because an isolated saturated slide can have a finite gradient whose FP32 SGD update rounds to zero; a wholly inert epoch or any non-finite gradient/update remains fatal. Results from the failed zero-update jobs are invalid and must not be reported.

SLIP prompt origins

SLIP assigns three separate roles to its released prompt bank: format templates, slide-class prompts, and tissue-routing prompts. A tissue is itself a text ensemble. The authors encode its short name and its description as two independent prompts, normalize both embeddings, average them, and normalize again. Consequently, joining the pair into one Name: description sentence does not reproduce the released routing vector even though it preserves every word.

Benchmark bank Origin Selected condition
TCGA-NSCLC upstream copy Exact TCGA template ({}), two nested slide-class groups, and all 17 ordered two-text tissue groups
CAMELYON16 generated Local tissue extension, expanded to the native two-text runtime shape
TCGA-BRCA generated Local tissue extension, expanded to the native two-text runtime shape
TCGA-RCC generated Local tissue extension, expanded to the native two-text runtime shape
UBC-OCEAN generated Local tissue extension, expanded to the native two-text runtime shape

The complete released DHMC and PatchGastricADC22 banks are also copied for their original datasets, including the gastric-specific template. The old *_tissues.json conversions of those banks and TCGA are retained only as derived, unwired audit artifacts. Generated configs and the runtime load a complete bank, while the doctor verifies template arity, slide-class order, the nested tissue structure, and the digest of upstream banks. The importer preserves the complete source structure, so refreshing from upstream cannot silently recreate the flattening bug.

The released repository exposes TCGA in its CLI and includes this lung prompt bank, but imports a datasets/tcga.py file that is not present. Its paper reports CLIP ViT-B/16 results only for PatchGastric and DHMC. Therefore the registered TCGA-NSCLC rows are explicitly local task/protocol extensions, not paper reproductions. The paper states SGD at 2e-4, while the released CLI defaults to 2e-3; PGVL-Gym uses the paper value and records this choice. The separately named slip_plip condition replaces RN50 with paired PLIP: its 768-wide cached vision-preprojection vectors pass through the same frozen PLIP checkpoint's native visual projection before any tissue/text comparison. The upstream PLIP prompt encoder also hardcodes EOT ID 46810, whereas the released vinid/plip tokenizer snapshot used here assigns EOT/padding ID 49407. The hard-coded value is absent and would select token position zero; PGVL-Gym therefore binds EOT and padding to the loaded tokenizer and records this as an upstream-code repair.

Why native and adapted must not share a results table

pathpt_keep and muse_musk can report identical accuracy and mean different things. PathPT ships PathPT_model_KEEP.py, so its number measures KEEP under the published code. MUSE with MUSK features keeps CONCH as the text tower and learns a projection between them, so its number measures MUSE plus that projection — the encoder cannot be credited alone.

The separately named muse_paired_* rows answer a different question again: the cached patch producer and frozen text tower come from one exact checkpoint, but MUSE still retains its trainable visual adapter and replaces the native CONCH token learner with the disclosed final-feature context fallback. These rows are explicit architecture extensions; they do not retroactively change the cross-space muse_keep or muse_musk result identities.

The released KEEP remote module replaces timm's LayerScale with a compatible name but an older constructor. Current supported timm passes device and dtype while creating ViT blocks, so PGVL-Gym locally extends that constructor with those factory arguments without changing its parameterization or forward rule. This is a runtime compatibility repair, not a model alteration.

The generated run matrix records this distinction per row. Counts are derived from the current protocols rather than repeated here because adding an explicit encoder condition changes them.

Trade-off accepted

encoder_provenance has two values, not four. Prompt provenance is a separate axis already carried by prompt_source and prompt_provenance; folding it in would duplicate state and let the two drift.


2. Implementation provenance

The adapter registry is the source of truth for implementation fidelity. The compiler writes its values into every config, matrix row, fold result, and aggregate grouping; the doctor rejects contradictory declarations.

Method Upstream LOC used Local model LOC Status
cod_mil vendored model and objective scale/slice/scheduler fidelity guards partial: preserves the released encoder-specific prompt scales and inert scheduler, while correcting the released final-background-row omission
top 1,195–6,301 0 fully vendored
maple vendored model and objective native PLIP visual-boundary restoration plus attribute-order correction partial: restores cached preprojection features with PLIP's own frozen head and fixes the released entity-major/class-major reshape defect
mscpt vendored model adapter plus feature-only selection bridge partial: the exact selector-prompt ensemble, branch roles, and classwise top-k are restored, but deep visual prompting of raw RGB patches is bypassed
pathpt vendored model, loss, and prompt banks lifecycle adapter upstream in upstream_patch_ssl subtype mode; legacy slide-CE and CAMELYON adaptation are partial
focus vendored model lifecycle adapter upstream architecture with method-specific asset provenance
vila_mil vendored model lifecycle adapter plus prompt-index correction partial: released EOT indexing defect corrected and paper 5x/10x scales enforced
slip 4,411 114 mixed, mostly vendored
wsi_five ~1,000 used of 4,071 175 rebuilt from vendored components; FiVE.py orchestrator is unusable
muse prompt learner, text path, MoE/SFSE/SMMO behavior reconstructed from pinned source and Algorithm 1 adapter plus dependency-light reconstruction partial: released 16-token CONCH prompting and paper full-queue semantic-view training restored; unified orchestration retained
convlm 0 124 reimplemented (self-declared)
sldpc 0 246 reimplemented (CPI/DHNO/SICL written here)
dyko 0 clean equation-level implementation partial: released TITAN prompts/concepts retained; deterministic PyTorch K-means replaces FAISS, paper retrieval corrections are applied, and cached 512px tiles differ from paper 448px tiles
mgpath 0 clean equation-level implementation partial: final-paper 5x/10x, 9e-6, 200-epoch recipe is authoritative over the conflicting release command; the missing PLIP-only ImageMLP, index-zero graph neighbour, and current Transformers signature are corrected; cached tiles remain 224px without upstream augmentation and the primary PLIP-G path is not claimed
hipss 0 clean equation-level implementation partial: complete GPT-5.6 replacement prompts and coordinate-grouped cached geometry replace unavailable upstream assets; layerwise SSF matches the paper parameter budget

SLDPC prompt provenance is intentionally split at the consumer boundary. At upstream commit 3c9580a1f3602a140d7e6bcc75ad93d7554e4e85, the two-stage TitanPromptLearner receives dataset class_names codes. The YAML synonym banks and 23-template ensemble enter only the independently evaluated TITAN zero-shot baseline. Four local YAMLs (NSCLC, RCC, TCGA-OT, and UBC-OCEAN) are byte-exact upstream copies; BRCA and CAMELYON16 are generated task extensions. The complete file hashes, token origins, and pinned source links are recorded in text_prompts/PROVENANCE.json. The unified adapter currently retains the zero-shot assets only as audited, explicitly unwired references and does not report a zero-shot metric.

SLDPC's runtime interface now separates that native TITAN condition from architecture extensions. An exact TITAN slide vector can still use TITAN's frozen native slide projection. A different registered promptable text tower must instead declare slide_projection: linear or mlp; that adapter is trained only on the fold's training slides and the compiler derives an encoder_extension record from the independent slide_encoder and prompt_encoder identities. OpenAI CLIP-RN50 and ViT-B/16 are the first built-in alternate towers with a complete differentiable embedded-prompt wrapper. This makes the swap executable, but it does not make the resulting learned alignment an upstream SLDPC condition.

wsi_five was the most misleading case and has since been rebuilt: the adapter now drives the vendored PatchFusionTransformer, MedCLIPTextModel and LoraWrap, restores the released answer-candidate objective, and reserves the released diagnostic descriptions for evaluation. What remains unused is FiVE.py (500 lines) and _datasets/pipeline.py (1,950 lines) — and FiVE.py is not merely unused but unrunnable, failing both import and construction (see §7). The remaining limitations are the rebuilt orchestration and feature provenance, not a missing prompt pipeline.

Partial adapters emit doctor warnings. A publication-oriented protocol can set require_upstream_fidelity: true to turn those warnings into a hard gate.


3. Vision-language only, by construction

Every registered encoder is a dual-tower vision-language model. Vision-only pathology foundation models — UNI, GigaPath, Virchow, Phikon, CTransPath, H-optimus, ResNet50 — are deliberately absent, even though features for several are extracted and available.

A method that learns or injects text prompts has no text tower to attach to. Including them would produce cells that cannot run, not cells that are blocked for an interesting reason.

Of 130 method × encoder combinations: 48 native, 40 adaptable, 42 blocked. See Compatibility analysis for the cause of every blocked cell.


4. Skip visibly, never silently degrade

A benchmark matrix always contains configurations whose assets do not exist yet. Three mechanisms keep those from producing numbers:

  1. Config generation records unbuildable experiments in skipped_configs.csv with the specific missing asset, and does not emit a config.
  2. common/preflight.py checks one resolved config against the filesystem before any model is built. Failure writes skipped.json and exits 3 — distinct from 0 (completed) and 78 (environment).
  3. train.py fails on the first sample error by default (max_batch_failure_rate: 0). A run may explicitly opt into a non-zero sample-failure ceiling, but past that fraction it fails rather than reporting a number computed on a larger accidental subset. Counts land in metrics.json as sample counts under sample_failures, with the exact identities under failed_slide_ids.

Trade-off accepted

Any non-zero ceiling changes the evaluated population and is therefore an explicit protocol decision, not a hidden resilience default. Comparable benchmark protocols keep the fail-fast value.

Stale artifacts are pruned

Generated configs the protocol no longer produces are deleted after each generation pass. A config left behind still names a results directory and still looks valid to anything walking the config tree, so the protocol is treated as the sole source of truth.


5. Encoder loading: pinned provenance over convenience

feature_space_id identifies the exact producer of a feature tensor, and equal widths never establish compatibility. No adapter is inserted implicitly.

PLIP below torch 2.6

transformers refuses torch.load on a .bin checkpoint under torch 2.6 (CVE-2025-32434), and vinid/plip's default revision publishes only pytorch_model.bin.

Rejected: pinning the repository's safetensors-only revision. That revision carries no config.json and no tokenizer files, so the load fails on the missing config instead — and offline compute nodes cannot fetch them.

Chosen: assemble one complete directory (config + tokenizer from the default revision, model.safetensors from the other) and point PLIP_CKPT at it. Verified first that all 400 tensors are bit-identical between the two revisions. transformers prefers safetensors and that path never calls torch.load. scripts/pgvl_job.sh exports it, guarded on the file existing so an unprepared site degrades to the HF cache with a warning.


6. Per-cohort benchmark directories

Each cohort owns benchmarks/<cohort>/ holding its protocol.yaml and everything generated from it. Cohorts are independent so one whose data is not ready cannot hold back the others.

Trade-off: shared feature sources are declared repeatedly across protocols. Accepted, because a single protocol would couple every cohort's readiness.


7. Method-specific fidelity notes

CoD-MIL — cross-magnification maps are reconstructed

The released code loads map_10x_20x_files/<slide>.pt but the repository ships neither the maps nor a generator for them. create_patches_fp.py is stock CLAM at a single magnification; datasets/ is stock CLAM; scripts/ holds only split creation.

scripts/generate_cross_magnification_maps.py reconstructs them from patch coordinates.

Decision Basis
10x → 20x Confirmed — Table I reports 10x and 20x patches for all three of the paper's datasets, and matches the hardcoded map_10x_20x_files
Centre containment Inferred. The paper introduces an alignment matrix but does not state the geometric rule. Robust to tissue filtering in a way index arithmetic is not
Per-slide patch size patch_size_level0 is read from each slide's H5 attributes, not a global constant
Built from feature files, not the patch store The map's indices must address the bag the model loads; building from the feature files' own coords makes that true by construction

The per-slide sizing is not a refinement — BRCA spans three scanner base magnifications:

base 10x 20x slides
40x 896 448 913
30x 1344 672 8
20x 448 224 39

A single global size would have bound roughly four times too many high-power patches per row for 47 of 960 slides — silently, with no error.

Validation: all 960 maps are (N_low, 4), zero empty rows, mean 3.90–3.94 matches per low patch, each high patch in exactly one parent. The 4-way nesting also reconciles the code's topk(A, 16) with the paper's sampling sweep: 16 low-power regions × 4 children ≈ 64 high-power instances, landing on the K≈64 the paper's Fig. 6 favours. The code's 16 and the paper's K are different quantities.

Not comparable to the paper's numbers

Upstream create_patches_fp.py defaults to 256 px patches at stride 256; this benchmark's store holds 224 px patches. The grids differ, so a 10x tile covers a different tissue area and instance counts do not match Table I. The method is reproduced; the numbers are not directly comparable.

CoD-MIL — prompt banks

The published bank is C low-power class prompts + C high-power class prompts + a normal-tissue corpus (21 rows for kidney: 6 organ structures + 15 organ-independent phenotypes). The auxiliary contrastive branch masks the most discriminative low-power instances and contrasts them against normal tissue — so the corpus is the objective, not padding.

The 15 organ-independent rows are reused verbatim across cohorts, including upstream's "tpithelial" typo, because correcting it would change the embedding and break correspondence with the released bank.

Upstream publishes a normal-tissue bank for kidney only. BRCA's six normal breast structures are authored for this benchmark and marked _provenance: generated; the config reports prompt_provenance: upstream_chain_with_generated_normal_tissue so the mixed bank is never reported as fully upstream.

The released CLIP RN50 prompt tensor does not match the published CSV

text_prompt_kidney_v2.csv has 27 rows. ..._plip.pt and ..._quiltnet.pt are exact 27-row encodings of it. ..._clip_rn50.pt has 30 rows.

Cosine alignment shows csv[i] → released[i+3]: the three extra rows are at the front, and released rows 3–9 match the CSV only at 0.92–0.97 (the class prompts were reworded), while rows 10–29 match at exactly 1.0000.

So the CSV is not the source of the released CLIP tensor. Truncating the last three rows — the intuitive fix — would feed unknown text into the low-power branch and low-power text into the high-power branch, misaligning both class branches with no error raised.

The original file remains unchanged as an audit-only upstream artifact. RCC configs instead select rcc_text_prompt_features_clip_rn50_verified.pt, an exact ordered re-encoding of all 27 upstream CSV rows with the official CLIP RN50 checkpoint. The derived payload embeds the prompts, source/checkpoint hashes, feature-space ID, half-open row-role spans, and the explicit encoder_native scale convention. Compiler, doctor, and runtime checks reject a bare, reordered, or incorrectly normalized tensor.

The CSV—not CLIP—is the canonical bank. The local model width now follows feature_dim, and scripts/build_cod_mil_prompt_features.py accepts the three families for which upstream released RCC prompt artifacts: clip-rn50, plip, and QuiltNet. The encoder-sweep name quiltnet is pinned to wisdomik/QuiltNet-B-16. The released QuiltNet prompt tensor retains the separate quiltnet-b32 / hf:wisdomik/QuiltNet-B-32 identity and is never relabelled or paired with B-16 patch features. A B-16 prompt tensor must be re-encoded from the canonical CSV with the B-16 text tower. Upstream's model code itself hardcodes 1024 dimensions, so a PLIP/QuiltNet run is honestly labelled a width-parameterized implementation extension (upstream_fidelity: partial), not an upstream reproduction. It must use patch bags and a verified prompt tensor from the same feature space. This is not a width projection: vectors from unrelated encoders are never compared merely because their dimensions match. Runtime-cached encoding can consume the same CSV directly when the matching text checkpoint is available.

The released artifacts do not share one normalization convention. Direct inspection gives CLIP-RN50 row norms of 9.04–10.42 (mean 9.67), while every PLIP and QuiltNet row has unit norm. The released model does not normalize the tensor again. Runtime encoding and derived caches therefore select the published convention by encoder; the former blanket unit normalization made the BRCA CLIP path roughly ten times smaller than its upstream input.

Upstream's model also slices normal prompts as text_feature[2C:-1], dropping the final row — an ordinary tissue prompt, not a sentinel. PGVL-Gym corrects that off-by-one to [2C:], records the correction as partial fidelity, and tests that the last background row reaches the auxiliary branch. The released training loop constructs a plateau scheduler but never calls step; the adapter now returns no scheduler so the unified trainer cannot silently add a different learning-rate recipe.

The benchmark's 4-shot BRCA fold contains eight training slides, whereas the released CoD-MIL recipe is full-data and learns a randomly initialized 1024-wide two-layer text projection (about 2.10 million parameters) in addition to its attention path. Consequently a corrected few-shot score is not expected to reproduce the paper's full-data result; 8/16-shot and full-data runs are the appropriate capacity/data controls.

WSI-FiVE — the vision tower is not method-owned

The compatibility analysis originally attributed 18 blocked cells to "the method owns its vision tower (wsi_five, convlm)". That framing was wrong for WSI-FiVE and conflated PGVL's local ConVLM adapter with ConVLM's released training path. For WSI-FiVE specifically, with the shipped default IS_IMG_PTH: True, upstream sets self.visual = nn.Identity() (MedCLIP vision is commented out), hardcodes embed_dim = 512, never parses the CLIP state dict, and reads precomputed features from CSV. The paper confirms it: "we employed ResNet following [15] as image encoder… while pre-trained BioClinicalBERT as text encoder" — [15] is DSMIL.

No MedCLIP weights load on any path. MedCLIPTextModel, the only MedCLIP class instantiated, calls AutoModel.from_pretrained('./Bio_ClinicalBERT'). Every torch.load in MedCLIPModel.py belongs to a vision class that is never constructed, so checkpoints/wsi_five/medclip_vit.bin is unreachable and is not a blocker. The name is code provenance — upstream's README says "parts of the codes are borrowed from X-CLIP, MedCLIP" — which this project's documentation had turned into a model claim.

The vendored orchestrator does not run

FiVE.py cannot be imported (it wants VisionTransformer; canonical CLIP defines VisualTransformer) and cannot be constructed (CLIP.__init__ raises Trying to create tensor with negative dimension -1 on the vocab_size=-1 arguments build_model passes). Reusing it was never an option, so the model is rebuilt from the vendored components that do work.

What is reproduced

Mechanism Source
Bag aggregation, self-attention + cross-attention branches, concat fusion vendored PatchFusionTransformer
Six clinical questions as cross-attention queries release PROMPT_LIST
BioClinicalBERT text tower with LoRA (r=8, α=32) vendored MedCLIPTextModel + LoraWrap
16 learnable soft prompts injected into BERT embeddings encode_prompt_embed
Positions from patch index within slide; sample_range padding masks vendored get_pos_embed
logit_scale = 300 hardcoded upstream, not learned

Verified: BioClinicalBERT weights load identically to the original checkpoint, LoRA leaves 1.34M of 117.9M parameters trainable with the base frozen, a forward pass over a 137-patch bag returns finite logits, and gradients reach both the soft prompts and the fusion transformer.

Native text supervision and evaluation

FiVE does not train against class names and a slide's answers do not condition its fusion transformer. The official release assigns three separate roles to text:

Text asset Role Local provenance
Six clinical questions Cross-attention queries that condition patch aggregation Derived JSON container preserving upstream configs/wsi/fix_pth.yaml:PROMPT_LIST verbatim
Six answers per case Training answer candidates and targets Generated complete CSV: 912 upstream GPT answers are preserved, 27 blank upstream cells receive disclosed conservative local completions, and 82 benchmark-only cases receive the same conservative template from openai:gpt-5.6
LUAD/LUSC diagnostic descriptions Validation/test comparison bank Derived JSON container preserving upstream LUAD_LUSC_labels_{train,val}_reid.csv text verbatim

These assets are pinned to WSI-FiVE commit 07344c9ac6eef919fcd1440877ea796feef7445a. None is a byte-for-byte upstream file: JSON containers were introduced for questions and evaluation text, and the two answer workbooks were normalized into one CSV. The reproducible answer derivation merges 471 LUAD and 468 LUSC rows, splits the 912 nonblank upstream answers into exactly six stripped fields, fills the 27 blank upstream cells with six deterministic, conservative “not documented/cannot determine” answers, then appends the 82 cases present in PGVL-Gym's NSCLC cohort but absent from the released workbooks using the same conservative template generated by openai:gpt-5.6, and sorts all 1,021 records by case_id. These generated rows do not infer positive clinical findings from unavailable text. The exact fill text, generator, source-cohort hash, and affected case IDs are listed in text_prompts/PROVENANCE.json. scripts/build_wsi_five_prompt_assets.py --check verifies the source workbook hashes, counts, and byte-exact generated CSV.

The NSCLC answer asset covers every one of the benchmark's 946 cases while retaining 75 released-workbook cases outside the local cohort. All six fields are present. Because 109 records contain generated completions (27 blank upstream cells plus 82 cohort extensions), the answer asset and aggregate native condition explicitly report generated answer provenance; they must not be described as a purely upstream answer bank. For each benchmark fold, the adapter reads answers only for training rows, constructs and hashes a unique candidate bank from that fold, randomly drops zero to five aligned question/answer fields, removes Unknown answers, and shuffles retained answer segments. This restores the released aug_question and label-hashing semantics without admitting validation/test answers into the bank. The saved fold trace records the candidate count, asset sources, and a SHA-256 digest, but deliberately does not duplicate patient text.

At validation and test time the dataset does not require or return an answer for inference. The slide is aggregated from patch features, the six questions, and the learned soft prompts, then compared only with the two released diagnostic descriptions in label-index order. This closes the former privileged-text path and makes missing answers on held-out cases harmless.

The released loss retrieves one case-specific answer record from the training bank; it never optimizes the LUAD/LUSC comparison logits used at evaluation. That is workable with the authors' full-cohort bank, but under the frozen 4/8/16/32/64-shot protocol the bank contains 8/16/32/64/128 cases. An audit of the 4-shot fold found useful slide ranking but complete one-class prediction in the native DSMIL, CLIP-R50, KEEP, and QuiltNet conditions. PGVL-Gym therefore keeps the answer-retrieval loss and adds a weight-1 cross-entropy class-boundary anchor against the same released LUAD/LUSC descriptions. The anchor consumes only training-fold slide labels; validation and test data remain absent from both losses. few_shot_class_anchor_weight: 1.0 records this local adaptation, and setting it to 0 recovers the pure released answer objective. Result provenance marks the anchored condition as partial and does not attribute the extra term to the paper.

The answer-bank native mode is declared only for TCGA-NSCLC. CAMELYON16 is a different released condition: fix_pth_cam.yaml supplies the literal normal/tumor class CSVs, 22,528 frames at a 0.50 sampling fraction, and the same six questions. Those questions visibly mention spread through air spaces, pleural invasion, and the current lung organ even in the authors' CAMELYON config. The upstream_classname_bank runtime preserves and hash-binds that exact condition without loading report answers, and provenance explicitly records the upstream content defect. RCC and UBC example configs instead use generated task questions with simplified_classnames; WSI-FiVE published no native assets for those tasks.

The CAMELYON condition is a downstream transfer experiment, not a from-scratch eight-slide learner. Section 4.4 of the paper states that downstream networks are initialized from FiVE weights pretrained on TCGA image-report pairs. The authors' released five_fix_pth_95.4.pth is 648,822,747 bytes with SHA-256 5891c7cf02a8232879d9cad8f023a59536c9947e4efb78e46570bdcf7a62c1c9; registered CAMELYON configs bind both values and the doctor rejects a missing or altered file. A strict namespace translator maps upstream transformer.* weights into the rebuilt text.* module and requires exact target coverage and shapes. The only omitted source entries are the unused learned logit_scale (upstream's executable forward path hardcodes 300) and BERT's deterministic position_ids range buffer (the installed Transformers release represents it as non-persistent). This is initialization, not a resume operation; optimizer, epoch, and scheduler state are deliberately not loaded.

The TCGA checkpoint allocates both MIT positional_embedding parameters for 16,384 patches, whereas fix_pth_cam.yaml constructs the downstream model for 22,528. PyTorch cannot load that shape mismatch even with strict=False. Those two parameters are non-executable in the released code: their addition is commented out and get_pos_embed supplies sinusoidal encodings from each patch index instead. The translator therefore initializes just those dead parameters at the CAMELYON shape and records wsi_checkpoint_position_transfer: reinitialize_unused_mit_position_parameters_v1; all active fusion weights remain strict checkpoint copies.

The same audit fixed two smaller orchestration differences. Soft-prompt encoding now averages BERT hidden layers 1, 2, and the last layer before its projection, matching upstream instead of pooling only the final layer. During CAMELYON training the two class strings are treated as one answer segment while zero to five questions are dropped, preserving the released augmentation even when dropping field zero deduplicates both strings and yields a zero-loss update. Full two-class logits are still emitted for unified training diagnostics, but they do not replace that upstream loss.

The sampling fraction is executable, not descriptive metadata. Upstream SampleWSIData chooses min(int(total_patches * NUM_FRAMES_PERCENT), NUM_FRAMES) positions, drawing one random position from each integer interval during training and each floating interval midpoint during evaluation. The earlier unified loader ignored num_frames_percent and used a random subset/endpoint linspace up to the absolute cap. On the 399 imported CAMELYON16 bags, 397 fall below the cap after halving; consequently that defect used roughly twice the requested patches for almost every slide (median 10,853 instead of 5,426). The runtime now restores the interval sampler and generated configs pin wsi_sampling_policy: upstream_stratified_percent_v1, which also makes those pre-fix result identities stale.

Runtime, config compilation, and the doctor load all three roles through the same strict contract. Each config binds the asset byte hash, a semantic ordered bank hash, and role provenance; edited, reordered, relabelled, or substituted text fails before training.

The fixed-feature launch recipe now also follows the released executable NSCLC configuration: 100 epochs, 16,384 frames, batch size 1 with eight-step gradient accumulation, AdamW (betas=(0.9, 0.98), eps=1e-8), base LR 3e-6, 10x LR for the released fusion/message/prompt parameter-name groups, weight decay 0.001, five warmup epochs, and per-update cosine decay. The doctor rejects a native config that silently falls back to the former 30-epoch/2,048-frame local defaults.

Remaining deviations

  • Rebuilt orchestration. The released FiVE.py cannot be imported or constructed, so the lifecycle is rebuilt around its usable vendored components and remains marked partial.
  • Fold scope. The release publishes a fixed full training candidate bank. PGVL-Gym rebuilds it from each benchmark training fold to prevent answer leakage across few-shot folds.
  • Few-shot class anchor. Registered NSCLC benchmark configs add a weight-1 task-class loss on training-fold labels because answer-only 4-shot training left the evaluation boundary unconstrained and caused one-class collapse. This term is local and can be disabled with few_shot_class_anchor_weight: 0 for a pure-objective ablation.
  • Generated cohort completion. Eighty-two benchmark cases are absent from the released answer workbooks. Their GPT-5.6 conservative “not documented/cannot determine” rows make the shared benchmark folds executable but are not the paper's supervision.
  • Scheduler integration. The released timm cosine schedule is reproduced directly in the adapter at optimizer-update boundaries because the unified trainer exposes epoch-level scheduler hooks. This changes orchestration, not the declared LR curve.
  • Incomplete accumulation groups. The release silently drops a final group containing fewer than eight batches. PGVL-Gym flushes that group so a nonstandard split cannot discard examples. The registered two-class 4/8/16/32/64-shot training folds contain 8/16/32/64/128 batches, so this safeguard does not change the benchmark recipe.
  • Feature provenance. The paper uses DSMIL SimCLR-ResNet18 512-d features. A run using a different 512-d feature space is dimensionally valid but not the paper's encoder condition.

Registered WSI-FiVE encoder extensions

The native wsi_five experiment remains pinned to the paper's offline DSMIL SimCLR-ResNet18 512-wide bags. The TCGA-NSCLC protocol additionally registers seven separately named 20x feature conditions: CONCH v1 and QuiltNet-B-16 (512), PLIP, KEEP, and CONCH v1.5 vision-preprojection (768), plus CLIP-RN50 and MUSK (1024). The model already projects BioClinicalBERT into feature_dim and constructs patch fusion at that same width, so these are executable architecture extensions rather than width-only relabellings.

They are not same-VLM semantic swaps. WSI-FiVE never invokes the selected VLM's text tower: its six questions, answer candidates, and evaluation texts continue through LoRA-adapted BioClinicalBERT. The text output projection and patch-fusion module learn alignment to the selected cached patch space during training. Every generated extension config therefore records feature_encoder, feature_space_id, BioClinicalBERT as prompt_encoder, and alignment_mode: learned_projection; result rows are extended / partial with encoder_provenance: adapted and cannot share the native DSMIL label.

Six additional NSCLC paired-tower ablations are registered for CONCH v1, QuiltNet-B-16, CLIP-RN50, PLIP, KEEP, and MUSK. In these rows every fixed text role (questions, answer candidates, and evaluation descriptions) is encoded by the exact frozen text tower paired with the cached visual checkpoint. Sixteen native-width, native-context soft prompts and WSI-FiVE's patch-fusion module are trained per fold; the VLM tower and cached patch features remain frozen. PLIP's stored 768-wide preprojection vectors pass through that same frozen checkpoint's native 768-to-512 visual projection before normalization and fusion. KEEP uses its 256-token BERT inputs_embeds path, while MUSK uses its 100-token BEiT3 embedded-token path and language head. These are explicitly extended / partial ablations: replacing BioClinicalBERT/LoRA changes the published WSI-FiVE architecture even though visual and text spaces now match. CONCH v1.5 is excluded because this registry does not expose an exact matching promptable text tower for the cached v1.5 preprojection space.

The paired CLIP-RN50 condition has an additional fixed-tower boundary. Its tokenizer cannot represent more than 77 positions, while 183 of the 1,021 full NSCLC answer candidates exceed that limit (maximum 144 CLIP BPE tokens). Rather than dropping report rows, altering the answer bank, or silently substituting a long-context tower, this condition calls OpenAI CLIP's own truncate=True tokenizer path. That path retains the start token and replaces position 76 with EOT. The behavior is serialized as clip_eot_truncate_77_v1, applies only to overlength paired-CLIP strings, and remains an extension rather than upstream WSI-FiVE behavior. The BioClinicalBERT path and all non-CLIP paired towers are untouched.

Native DSMIL high-score audit

The NSCLC fold-0 4-shot native result was checked for an accidentally easier split. It predicts all 208 canonical test slides (109 LUAD, 99 LUSC; 190 patients), has zero failed samples and zero missing DSMIL files, and uses the same exact test slide-ID set as every other completed fold-0 method. Train, validation, and test contain 8, 8, and 208 slides respectively, with no case or slide overlap. No duplicate HDF5 inode or sampled feature fingerprint was found across partitions.

The feature space itself is unusually separable: a text-free nearest-centroid classifier fitted to only the eight training-slide mean vectors reaches 0.908 slide balanced accuracy and 0.982 AUROC, compared with WSI-FiVE's 0.917 and 0.983. The high WSI-FiVE score is therefore consistent with the released DSMIL representation rather than observed split leakage or a hidden WSI-FiVE checkpoint. The upstream representation recipe is transductive relative to our folds: DSMIL's simclr/run.py globs every patch under the selected TCGA-Lung dataset into all_patches.csv before the SimCLR loader applies its independent 10% SSL validation split. The released WSI-FiVE README identifies its downloadable TCGA features as the DSMIL-provided artifacts. Test-slide images can therefore influence the frozen representation without their labels. This is unlabeled representation exposure, not supervised train/test label leakage, and must be disclosed when comparing against a strictly inductive feature encoder.

The downloaded release archives are retained in staging and imported with scripts/import_wsi_five_dsmil_features.py. It verifies ZIP integrity and a pinned SHA-256, restricts installation to frozen manifest slide IDs, validates the upstream headered 512-column CSV matrices, rejects empty/non-finite data, and atomically writes float32 HDF5 bags with source URL, archive digest, and member provenance. The CAMELYON16 and TCGA source archives are respectively 9d4e1ab1edc875c6b00d6af4a53969ec06177b563cbd0a6fdde65e27f2ffaad5 and 14ac4cf214874aa62a6076b1d14924c375433eb6bb8ce77030e28e4a98263463.

ConVLM — missing upstream attributes and a local feature-bag reconstruction

The release is pinned at commit a399e51585eeb4c7974b274174ca9b0360a9120d. It does not contain a reusable class prompt bank or the dataset-specific att_splits.mat loaded by train.py. Its two text utilities do not fill that gap:

  • generate_text.py asks Quilt-LLaVA for one description per input image. It produces image-specific JSONL, not an ordered class bank.
  • attribute_embedding_generation.py is hard-coded to the two NSCLC labels, contains malformed quoted input, calls quilt_model.encode_text(text)(text), and never saves an attribute matrix.

There is therefore no honest upstream bank to import. The CAMELYON16, TCGA-NSCLC, TCGA-BRCA, TCGA-RCC, and UBC-OCEAN JSONs checked into text_prompts/convlm/ are all generated substitutes. NSCLC deliberately selects its bank for one explicitly partial local reconstruction; the other four remain unwired. Their file hashes, ordered prompt-content hashes, class order, prompt counts, and copied_from_upstream: false declarations are pinned in text_prompts/PROVENANCE.json. Selecting one reports prompt_provenance: generated and prompt_source: convlm_generated_attribute_prompts regardless of whether its path came from prompts:, a legacy cohort key, or the compiler.

The runtime preserves every prompt through loading, then performs a local aggregation: it normalizes each encoded prompt, averages within class, and normalizes the resulting class vector. Because upstream publishes no executable equivalent, this is disclosed as a reconstruction rather than described as the paper's QuiltNet attribute protocol.

Precomputed attributes use schema pgvl.convlm.attribute_embeddings.v1. The doctor and runtime reject a bare tensor or .npy: the artifact must carry exact ordered classnames, the source prompt-bank SHA-256, prompt provenance, feature-space ID, and encoder metadata including checkpoint SHA-256. This boundary is encoder-agnostic—QuiltNet is one valid declared space, not a hard-coded requirement—but a matrix from one text tower cannot silently be paired with another.

The registered NSCLC reconstruction uses complete QuiltNet-B-16 20x patch bags and encodes the generated attributes at runtime with the pinned wisdomik/QuiltNet-B-16 checkpoint a5a588b6cec62d610bfc25f64dfe1df30fa6af98 (SHA-256 b059d20776597f0f4ab92635b24b756376fd669b580d6b266c8daa184b0f7379). It caps each WSI at 512 sampled patches so full self-attention has an executable memory boundary. The source JSON remains the canonical, encoder-agnostic bank; no anonymous tensor is required.

The architecture boundary also differs from the release. PGVL's adapter reads precomputed WSI patch bags and applies a locally written attribute-conditioned token-pruning transformer. The released train.py instead constructs the raw-image ViT from convlm.py, whose PatchEmbed consumes 224×224 RGB images. The repository contains a separate UNI feature extractor and its README discusses ROI features, but the released training script does not consume those bags. PRECOMPUTED/PATCH_BAG consequently describes this benchmark adapter, not an upstream-compatible data path. The active NSCLC row consequently reports reimplemented_feature_bag_reconstruction and upstream_fidelity: partial.

MUSE — upstream and generated prompt banks

The release at commit 9f2ec37bad5a10bb79616900ec017830b0bdfa0a covers camelyon_all, tcga_brca, and tcga_nsclc. All six selected CSVs are byte-exact imports with 300 indexed descriptions per class. Their SHA-256, classname, and class index are pinned in text_prompts/PROVENANCE.json.

Its kidney folder is IgA nephropathy grading, a different disease and task from renal cell carcinoma subtyping; "carcinoma" appears zero times across its six files. It is not a substitute for RCC. The release contains no UBC-OCEAN bank either.

RCC and UBC-OCEAN MUSE banks are local conversions of description text released for MSCPT. Reusing released text from a different method does not create an upstream MUSE condition: all eight CSVs report prompt_provenance: generated and prompt_source: muse_generated_task_extension_csvs. A result on either task is not prompt-faithful to MUSE and must not be tabled as though it were.

MUSE's CSV shape is part of the runtime contract. The shared loader and doctor require the exact ,0 header, sequential zero-based row indices, one non-empty description per row, exact classname coverage, and audited class-to-file binding. Registered assets additionally enforce their row counts and SHA-256. Released duplicate descriptions are intentionally retained because changing their multiplicity changes the authors' stochastic sampling distribution.

Registered MUSE runs no longer substitute one learned class vector for the released prompt learner. They execute the shared 16-token CONCH context inside the frozen differentiable text tower. Description CSVs are encoded through the same released MUSE text path, and the training-only semantic queue contains the ground-truth class's 20 most similar descriptions in shuffled order. The paper's SFSE equations apply top-20% patch filtering to both the base and auxiliary priors; PGVL-Gym follows that published definition rather than the public forward's unfiltered base branch. Paper Algorithm 1 exhausts that queue for every WSI, so the adapter makes 20 Adam updates per bag rather than sampling one description with replacement. The 8-expert noisy top-2 router and Equation 12 mean of base and auxiliary logits are active. The fixed learning rate reflects the released trainer, which constructs a plateau scheduler but never steps it; checkpoints minimize validation error with patience 20 and earliest stop after epoch 80. muse_prompt_learning: token_16_conch and muse_runtime: sfse_smmo_full_queue_token_prompt_v2 make this runtime identity explicit. The public model sums the two logits despite Equation 12's mean and retrieves only one semantic view in the exposed forward path; those source/paper conflicts are recorded as corrections rather than silently inherited. The frozen CONCH tower and deterministic description embeddings are cached per process across folds; every fold still receives a newly initialized, independently optimized 16-token context and trainable MUSE head. The cache therefore removes repeated setup work without carrying learned fold state.

Two boundaries remain disclosed. The standard visual-encoder extensions map a different offline patch producer through MUSE's learned visual adapter into the native CONCH prompt space; they are not paired-tower swaps. A new opt-in text-tower extension can instead select any registered black-box text encoder with a declared shared dimension. It encodes every description and initial class semantic with that frozen tower, then trains MUSE's visual adapter and a class-specific delta directly in the selected shared feature space. Because that path replaces the released 16-token CONCH learner, it must set muse_prompt_learning: feature_space_context_fallback, carry a derived encoder_extension record, and remain a separately named partial condition. It is not described as the upstream MUSE architecture even when the cached vision and selected text tower happen to share a family. Also, the public source requests the least cosine-similar descriptions despite the paper specifying the most similar; PGVL-Gym follows the paper and records that correction in implementation provenance. The current registry's 5x/10x/20x feature rows are magnification sweeps: the paper reports 512-pixel CONCH tiles at 40x. Generated provenance and doctor warnings retain that distinction even when the runtime itself is faithful.

PathPT — published 20x recipe and family-specific pseudo loss

All PathPT subtyping rows use the paper's 20x feature resolution. Optimizer, LR, epochs, prompt length, and base loss weights are held constant across PLIP/CONCH/KEEP/MUSK. The one intentional encoder-specific switch is the published pseudo-label policy: it starts at epoch 10 for CONCH and KEEP, and is disabled for PLIP and MUSK because the authors report unstable training for those families. The adapter overrides build_optimizer and build_scheduler to enforce the shared portion regardless of the YAML. Generator and doctor label a non-20x run as a magnification extension and reject a contradictory pseudo-loss setting.

The executable source is pinned at commit 0ab7f1b3bfc70ce3a85d4daaba3e018cc61fb087. Its epoch-level LambdaLR evaluates step zero during construction, so the two warm-up epochs train at 0 and 0.5 times the configured rate before reaching the full rate. The adapter preserves that released zero-start behavior; the generated pathpt_scheduler field prevents results from the former shifted schedule from being resumed or mixed with this condition.

Generated configs use training_mode: upstream_patch_ssl. After the fold's model and training loader are built, PathPT encodes all combinations of its 22 templates and task synonyms, scores 200 sampled prompt classifiers on training slides only, and averages the best 100. That frozen classifier creates Normal, known subtype, and negative candidate patch labels. Training calls the vendored PatchSSLoss; WSI inference counts patch votes, removes the synthetic Normal class, and uses the released all-Normal/tie fallback. The selected classifier and full score trace are persisted per fold. The old mean-patch-probability slide CE path is retained as the explicit simplified_slide_ce compatibility mode.

Prompt selection normalizes patch rows at the adapter boundary because PathPT defines cosine similarity while external feature writers may preserve vector norm. Candidate ties use the released np.argsort(...)[::-1] ordering exactly; ties are frequent in few-shot folds and changing this detail changes which 100 classifiers are averaged.

The common PGVL-Gym cohort is not the paper's direct reproduction protocol. For TCGA-BRCA, this benchmark uses the full eligible, naturally imbalanced cohort with 4/8/16/32/64-shot five-fold splits. The PathPT paper reports a balanced 150-slide IDC/ILC cohort, 1/5/10-shot settings, and ten resamples. Compare PGVL-Gym methods within the frozen common split and report slide balanced accuracy as primary; do not compare these values directly with the paper's table.

Prompt provenance is cohort-specific:

Cohort Bank Fidelity note
TCGA-BRCA upstream PathPT brca_names native subtype pipeline
UBC-OCEAN upstream PathPT ubc_names native subtype pipeline
TCGA-NSCLC generated here native algorithm, local task bank
TCGA-RCC generated here native algorithm, local task bank
CAMELYON16 upstream PathPT camelyon_names validation-calibrated top-1% tumour-evidence WSI adaptation; the paper evaluates CAMELYON region segmentation, so fidelity remains partial

The old CAMELYON integration applied PathPT's hard patch-count vote directly to a normal-versus-metastatic slide task. That vote is suitable only after the synthetic Normal row has been removed from a tumour-subtyping decision; on a positive lymph-node WSI, normal tissue can still occupy most patches. It thus collapsed to Normal even when ranking was useful (the KEEP diagnostic reached about 0.755 AUROC). The registered binary adaptation now averages the strongest 1% tumour probabilities and chooses a monotonic decision boundary using only the fold's validation labels. The threshold is stored in the model checkpoint and an audited fold*_pathpt_binary_calibration.json; held-out test labels are never read by calibration.

The CAMELYON upstream list has a missing comma that concatenates non-cancerous tissue and normal breast tissue. The upstream condition is kept byte-for-byte and the defect is recorded in text_prompts/PROVENANCE.json. Correcting it would be a separate derived prompt condition.


Paired-VLM ports for encoder-bound architectures

FOCUS, ViLa-MIL, TOP, MGPATH, Libra-MIL, DyKo, and HIPSS formerly rejected every non-native encoder. That was safer than a width-only substitution, but it also prevented controlled paired-tower ablations. PGVL-Gym now exposes opt-in ports without changing any native branch or existing protocol row.

The compiler requires an exact final shared feature_space_id, matching vision and text encoder names/checkpoints, and encoder_extension: true. Crossed KEEP-vision/MUSK-text conditions and same-width private tensors are rejected. Resolved configs store distinct patch_encoder, prompt_encoder, encoder_extension, and encoder_extension_strategy records.

The modifications are deliberately method-specific:

  • Libra-MIL needs no bridge: both prompt roles are simply re-encoded in the selected paired space and all learned prototype/SOT equations are retained.
  • FOCUS, ViLa-MIL, TOP, and MGPATH retain their visual aggregation and losses, but replace encoder-specific token learners with zero-initialized additive context in final text-feature space. TOP keeps separate bag and instance contexts; MGPATH keeps four independent views.
  • DyKo keeps its released TITAN concept tensor. A trainable linear projection maps that fixed 768-wide bank into the selected paired space, while class token prompting becomes feature-space context. This row measures DyKo plus the concept bridge.
  • HIPSS cannot apply CONCH residual-block SSF to KEEP or MUSK. Its extension encodes WSI/region roles separately, combines them in paired feature space, and applies identity-initialized feature-wise affine layers there. The hierarchy is retained, but this is not layerwise SSF.

No extension is automatically added to the campaign. An authored protocol must select the feature stores and create a separately named experiment; the doctor and provenance resolver then enforce the disclosed boundary.

8. Decisions still open

Item Question
ConVLM Can the authors release the data-specific att_splits.mat and a working generator so a true upstream attribute condition can be added?