CASMI 2026 hard rules: timeline, prizes, code requirements, official metric mechanics, submission edge cases

expertconfidence highrelevance 5/517 sources4.5k words
Forced analogyLaw of evidence (rules of procedure/admissibility): admissibility = 'freely and publicly available'; burden = 25-slot list vs binary InChIKey14 identity; hearsay = GNPS propagated annotations the hosts excluded. Paid off: it yields a clean offline-vs-in-notebook rule and exposes that the metric has no standard of proof short of identity.

TL;DR. CASMI 2026 is a Kaggle code competition (Kaggle API field isKernelsSubmissionsOnly: true): an offline notebook (internet off, ≤ 9 h CPU or GPU per mirrored rules) re-runs on a hidden ~400-molecule timsTOF set and must write submission.csv with up to 25 semicolon-separated SMILES per molecule_id. The scorer is public — Kaggle notebook metric/casmi-mean-reciprocal-rank — and does exactly Chem.MolFromSmiles → rdMolStandardize.TautomerEnumerator().Canonicalize → Chem.MolToInchiKey(...)[:14] with RDKit pinned to 2026.03.3 installed from a bundled wheel; the answer key is canonicalised at scoring time with the same function. Hard numbers: 5 submissions/day, max team 5, entry + merge deadline 2026-12-07 23:59 UTC, close 2026-12-14 23:59 UTC, $50,000 across the top five ($16,000 first), data licence CC BY-NC 4.0; the visible test.parquet is a host-acknowledged "dummy" drawn from train and is not what the public leaderboard scores.

Web search budget was exhausted when this worker started; every fact below comes from direct fetches (Kaggle API v1 via the authenticated CLI, pulled Kaggle notebooks, raw GitHub READMEs, the C&EN and Business Wire texts, casmi-contest.org) and from local RDKit 2026.03.6 experiments. Kaggle HTML pages are 6 KB JS shells and were not readable; the Kaggle discussion forum is not reachable through the public API, so forum facts are second-hand and labelled so.

1. Rules table

Status key: V = verified from a primary source I opened; M = mirrored by third parties (quoted rule text in community READMEs/notebooks, ≥ 2 independent, consistent with API fields); I = inferred; U = unknown.

# Rule Value Status Source
1 Competition type Code competition (notebook re-run on hidden test); "Featured" category V Kaggle API v1 competitions/list?search=CASMI: isKernelsSubmissionsOnly: true, category: Featured
2 Notebook runtime limit ≤ 9 h CPU notebook, ≤ 9 h GPU notebook M NoName7n11 README §7; yasu_claude.md ("CPU/GPU とも 9 時間以内"); corentinlaudicina README ("runs offline (≤ 9 h)")
3 Internet during scoring run Off M (+V for the scorer itself) Same three mirrors; official metric notebook metadata enable_internet: false; AmanDubal README step "Disable Internet, then Save Version / Run All"
4 Accelerator available Kaggle standard menu: CPU, GPU T4×2, P100, TPU; host tutorial profiles a T4 (4 vCPU, ~840 ms/step at batch 128) I inversion tutorial code comments; gnshx README ("Accelerator: GPU T4 x2, Internet: Off"); yasu notes used TPU and hit "max 2 concurrent batch GPU kernels"
5 Notebook RAM Not stated for this competition (Kaggle default ~30 GB) U —
6 Output file /kaggle/working/submission.csv, columns molecule_id,smiles V official metric docstring; inversion tutorial SUBMISSION_PATH; sample_submission.csv (400 rows, 25 × CCO per row)
7 External data "You may also use any freely and publicly available external data — see the Rules for what qualifies" V Data page text (mirror dallo_desc.md, verbatim)
8 External data standard "freely and publicly accessible to all participants at minimal cost (Reasonableness Standard, Rule 2.6)"; pretrained weights and public chemical DBs permitted M NoName7n11 README §7 (quotes rule number)
9 External data must ship as Kaggle Datasets Yes — consequence of internet-off; the official scorer itself installs RDKit from dataset metric/rdkit-2026-3-3-wheel V metric notebook dataset_sources; kitopl notebook installs aidensong123/casmi26-offline-rdkit-2026033 wheel offline
10 COCONUT / PubChem / LOTUS / NPAtlas lookup Allowed (public, free); hosts themselves define Class 2 as "in PubChem or COCONUT" V (COCONUT/PubChem), I (LOTUS/NPAtlas: same standard) Data page Class table; press/C&EN silent
11 Pretrained models (DreaMS, MIST, SIRIUS, PRISM) Public pretrained weights allowed; hosts list DreaMS/GeMS, MIST-CF, SIRIUS, matchms, FragHub as resources V for listing; U for commercial-licence tools Data page "Other resources"
12 Ban on commercial / licence-restricted tools No explicit ban found; only the "freely and publicly available" standard U — (settle: read Rules §2.6 after accepting rules)
13 Private code sharing Rule 3.6: code built on competition data may not be shared privately outside the team; public sharing must go on the Kaggle forum M kabir0774 README quoting "rule 3.6"
14 Data licence CC BY-NC 4.0 (do not redistribute train.parquet or weights trained on it publicly without checking) V Kaggle API licenseName; kabir0774 README
15 Team size 5 V Kaggle API maxTeamSize: 5
16 Submissions per day 5 V Kaggle API maxDailySubmissions: 5
17 Final selections 2 M NoName7n11 §6; yasu notes ("最終 2 本選択")
18 Start 2026-09-14 22:57:37 UTC (enabledDate); competition shell created 2026-05-18 V Kaggle API
19 Entry deadline 2026-12-07 23:59:00 UTC V Kaggle API newEntrantDeadline
20 Team merger deadline 2026-12-07 23:59:00 UTC V Kaggle API mergerDeadline
21 Final submission deadline 2026-12-14 23:59:00 UTC V Kaggle API deadline; press release "closes December 14, 2026"
22 Prize pool $50,000 across top five; $16,000 first V Business Wire 2026-09-15 (via Yahoo Finance); Kaggle API reward: 50,000 Usd; C&EN
23 Prize breakdown 2nd–5th $12,000 / $9,000 / $7,000 / $6,000 (sums to $50,000 with $16,000) M NoName7n11 §8 only — single mirror
24 Kaggle points/medals Awarded V Kaggle API awardsPoints: true; casmi-contest.org/2026 ("$50,000 in Kaggle Awards Points & Medals")
25 Winner open-source licence "OSI-approved licence, specifically MIT per Competition-Specific Terms"; press release: "Winning methods will be open-sourced" V (open-sourced) / M (MIT) Business Wire; NoName7n11 §7
26 Eligibility restrictions Not found (standard Kaggle terms presumed) U —
27 Metric MRR@25 on tautomer-canonical InChIKey14; max_rank is "a metric parameter set on the competition page" V official metric notebook
28 Metric label in Kaggle API evaluationMetric: "CASMI: Mean Average Precision" — stale label; scorer docstring says "this is reciprocal rank, not average precision" V Kaggle API vs metric docstring
29 Public/private LB split Exists (solution has a Usage column, Public/Private); fraction unknown V (exists) / U (fraction) metric doctest
30 Hidden test size "~1,500 spectra of ~400 molecules, 1–16 per molecule (median 3)", "approximately the same size" as the visible file (1,213 / 400); press release says "roughly 2,500 mass spectra" V (both, contradictory) Data page; Business Wire
31 Hidden test instrument / chemistry All Bruker timsTOF; masses 157–1,159 Da (median 348); NPs, hypothesised NPs, NP analogs, nature-plausible synthetics; "not been characterized in public datasets" V Data page; C&EN
32 Hidden test adducts Ten listed: [M+H]+, [M+NH4]+, [M-H2O+H]+, [M-2H2O+H]+, [M+Na]+, [M+K]+, [M-H]-, [M-H2O-H]-, [M+CH2O2-H]-, [M+Cl]- — but the column table says "one of the seven above" (internal inconsistency in the official text) V Data page
33 Hidden test cleaning Precursor-inconsistent spectra dropped; base peak < 1,000 raw counts dropped; peaks > precursor + 2 Da removed V Data page
34 Class proportions Hidden "for the duration of the competition"; forum back-solved Class 1 ≈ 16–17 % from a 0.151 library-only public score V (hidden) / M (16 %) Data page; kitopl notebook citing the forum
35 Visible test = decoy Host-acknowledged: "the file you see is comprised of examples from the training dataset; it will be replaced by the hidden test set during re-run"; host clarification thread discussion/741404 V (data page) / M (thread) Data page; mxm-1x README linking the thread

2. Code-competition mechanics (Q1)

  • The Kaggle API is unambiguous: isKernelsSubmissionsOnly: true. The notebook that produced the output is re-executed with the hidden test.parquet mounted at /kaggle/input/competitions/enveda-CASMI26-molecule-id-mass-spectra/; the host tutorial reads TEST_PATH from there and warns that "test.parquet carries no labels" and that molecule_id must ride along because scoring is per molecule.
  • Runtime/internet: the 9 h / internet-off pair is the standard Kaggle code-competition text and is quoted by three independent mirrors; I could not open the Rules page itself. The scoring notebook runs with internet off and installs RDKit from a wheel, which is strong circumstantial evidence that participant notebooks are in the same regime.
  • RDKit is not in the Kaggle Python image (# RDKit is not in docker-python, so the wheel ships as a competition input). The host wheel dataset metric/rdkit-2026-3-3-wheel carries rdkit-2026.3.3-cp310/cp311/cp312/cp313-manylinux_2_28_x86_64.whl (≈ 37 MB each, uploaded 2026-09-08) — so scoring runs on CPython 3.10–3.13, Linux x86_64. The tutorial's first cell is # pip install rdkit==2026.3.3 "Use the Dependency Manager".
  • Budget reality (from the tutorial): a T4 trains the host's de novo transformer at ~840 ms/step, batch 128; 200 k spectra ≈ 22 min; all 1.39 M non-enveda-180 spectra ≈ 2.5 h. The 66 GB-activation OOM warning in the same notebook shows the session has far less than that.
  • GPU quota: yasu's notes record "Kaggle batch GPU max 2 concurrent" and switching to TPU; q7 cites a 30 h/week quota (not re-verified here).

3. Admissible external data and models (Q2)

Verified: the Data page invites "any freely and publicly available external data — see the Rules for what qualifies", names PubChem and COCONUT as the Class 2 universe, and points to MIST-CF, SIRIUS, matchms, GNPS suspect annotations ("excluded from train.parquet because the labels are inferred rather than measured"), MassIVE, GeMS/DreaMS and FragHub. The mirrored Rule 2.6 adds "at minimal cost" and the standard Kaggle "Reasonableness Standard". Nothing I opened bans commercial tools; SIRIUS's own licence terms (academic vs commercial) were not checked in this session and must be before any SIRIUS-derived artefact goes into a winning (MIT-licensed) submission. Practical constraint, not a rule: everything must be attachable as a Kaggle Dataset and must finish inside 9 h offline, so PubChem-scale pools (community dataset dmitriigluzdov/casmi26-pubchem-popularity-prior, 1.29 GB) and model weights (e.g. hengck23/hengck23-dreams-enveda-casmi26, 5.7 GB) are the norm.

4. The decoy test (Q3)

Verbatim, Data page: "Note: the file you see is comprised of examples from the training dataset; it will be replaced by the hidden test set during re-run, and will be approximately the same size." Community audits (mxm-1x, Clyde0513, AmanDubal, josefreitasalvesneto item 10, kitopl §2) all map 1,213/1,213 visible spectra to enveda-180 rows by exact peak-array match; mxm-1x additionally links a "host clarification" at .../discussion/741404 calling it a dummy file (thread not opened; status M). There is no rule against using it and no benefit: q7 measured a public LB (2,673 teams, max 0.480) that library search cannot saturate, so the public LB is scored on the hidden set, not on the visible file. Use the visible file only for schema/runtime smoke tests; the hosts' phrase "approximately the same size" is the only official statement about hidden-set size that agrees with the 1,213-row file.

5. Official metric mechanics (Q5) — metric/casmi-mean-reciprocal-rank

Pulled with kaggle kernels pull metric/casmi-mean-reciprocal-rank (author "Kaggle Competition Metrics", last run 2026-09-14 12:59 UTC, docker image gcr.io/kaggle-images/python@sha256:dafd4ce5…). Key lines, quoted:

# Solution key canonicalized with RDKit 2026.03.3. RDKit's TautomerEnumerator output has changed
# between releases, so this pin decides which submissions match; it is not a convenience.
EXPECTED_RDKIT_VERSION = '2026.03.3'
RDKIT_REQUIREMENT = 'rdkit==2026.3.3'
RDKIT_WHEEL_DIR = '/kaggle/input/datasets/metric/rdkit-2026-3-3-wheel'
...
    _tautomer_canonicalizer = rdMolStandardize.TautomerEnumerator()

def canonicalize_smiles_to_ik14(smiles: str) -> str:
    """Canonicalize SMILES to InChIKey14, or None if parsing fails."""
    if not isinstance(smiles, str):
        return None
    try:
        mol = Chem.MolFromSmiles(smiles)
        if mol is None:
            return None
        canonical_mol = _tautomer_canonicalizer.Canonicalize(mol)
        inchikey = Chem.MolToInchiKey(canonical_mol)
        return inchikey[:14]
    except (ValueError, RuntimeError, TypeError):
        return None

Answers to the sub-questions:

Question Answer (verified from the code)
RDKit pin 2026.03.3 (PyPI spelling 2026.3.3); on mismatch the scorer only warnings.warn(...), it does not abort
Canonicalisation call rdMolStandardize.TautomerEnumerator() with default parameters, method .Canonicalize(mol); no MolStandardize.Cleanup, no charge neutralisation, no fragment/salt stripping, no Uncharger
Order InChIKey is computed after tautomer canonicalisation: MolToInchiKey(canonical_mol)[:14]
Answer key Not stored: solution SMILES are canonicalised at scoring time with the same function ("one source of truth"); a solution row may hold comma-separated multiple acceptable SMILES, and the docstring says the loop stays reciprocal rank "even if canonical_ik14s_all is later extended to accept several indistinguishable isomers"
Gate A cheap heavy_atom_composition (element counts excluding H, charge ignored) is computed per guess; if it is not in the answer's set, canonicalisation is skipped — "a formula gate would wrongly reject" protomers, so the gate is deliberately not on full formula
Score ap = 1/rank of the first match, break; mean over solution molecules; a molecule missing from the submission gets 0 (guesses_by_molecule.get(mol_id, [])) — the scorer itself does not raise for missing ids (Kaggle's upstream validator may)
Memoisation canon_cache per distinct SMILES string

Local checks on RDKit 2026.03.6 (closest build on this machine; defaults maxTautomers=1000, maxTransforms=1000, removeSp3Stereo=True, removeBondStereo=True, reassignStereo=True): keto/enol pairs that differ in raw InChIKey14 (acetylacetone YRKCREAYFQTBPV vs POILWHVDKZOXJZ; warfarin PJVWKTKQMONHTI vs FVSFCRPKSVCTBA) collapse to one key after Canonicalize; 2-hydroxypyridine/2-pyridone, guanine, quercetin already share a raw key (standard InChI mobile-H handling); quercetin costs 335 ms per call (q7 saw MaxTransformsReached on polyphenols at this cap). Stereo (C[C@H](O)CC vs enantiomer vs flat) and E/Z share InChIKey14 regardless. Isotopes ([13CH3]CO, [2H]C([2H])([2H])O) do not change block 1. Charge states CC(=O)[O-] vs CC(=O)O share a key, but salts do not: [Na+].CC(=O)[O-] gives VMHLLURERBWHNL, acetic acid QTBSBXVTEAMEQO. Community measurement (kitopl, 2026-09-21): 4,370 of 275,810 train structures (1.58 %) change key under canonicalisation and 3,167 structures (1.15 %) collapse into shared keys; over COCONUT's 738,827 structures 10.4 % re-key, 2.30 % can matter, simulated MRR cost 0.48 % (dariushafshar, cited by kitopl; not opened).

6. Submission format edge cases (Q6)

Case Scorer behaviour (from code)
Separator str(raw).split(';'), each token .strip()ped; "A semicolon cannot occur inside a valid SMILES"
Empty tokens (CCO;;CC, trailing ;) Dropped silently; they do not count toward 25
Row with no non-empty token (empty string) ParticipantVisibleError('No guesses for molecule_id …') → whole submission rejected. Note pd.read_csv turns an empty field into NaN, which is caught earlier as "NaN in required columns"; the tutorial uses FALLBACK_SMILES = 'CCO'
> 25 non-empty tokens ParticipantVisibleError('At most 25 … got N for m_x')
Duplicates within a row Allowed; each consumes a rank, "repeating it gains nothing" (doctest 0.5)
Invalid SMILES MolFromSmiles → None → non-match; consumes a rank; never crashes scoring
Whitespace in token Stripped; RDKit would otherwise read CCO ethanol as ethanol with a name
Duplicate molecule_id Rejected ("Each molecule_id must appear exactly once")
Missing molecule_id/smiles column, empty file, NaN Rejected
Unknown molecule_id Printed (first 5) and ignored, not rejected
Row order Irrelevant (dict lookup)
Wrong element composition Skipped by the gate before canonicalisation — costs a slot only

7. What is known about the hidden test and host FAQ (Q7)

Verified official statements (Data page): ~1,500 spectra / ~400 molecules, 1–16 spectra per molecule (median 3), all timsTOF, 157–1,159 Da (median 348), three novelty classes with hidden proportions, minimal cleaning (three listed steps), collision_energy_orig_units always eV, ten adducts. Press release (Business Wire 2026-09-15, via Yahoo Finance): "roughly 2,500 mass spectra", "All unpublished data", 90-day contest, lead organiser David Healey (Founding Data Science Fellow). C&EN (Oldach, 2026-09-17, DOI 10.47287/cen.612552.newsarticle): test "curated … from molecules that have not been characterized in public datasets"; Fiehn: "They did not try to have real datasets with … overlapping coeluting entities, chimeric spectra, weird adducts … They focused on mass spectra of isolated compounds"; Allen: "CASMI hasn't yet had its AlphaFold moment". casmi-contest.org/2026 (last modified 2026-10-02) only redirects to Kaggle and names Enveda as organiser. Host discussion threads could not be opened; the only thread id surfaced is 741404 (decoy clarification, via mxm-1x).

8. Forced analogy: law of evidence — rules of procedure and admissibility

The analogy, precisely. The Rules page is a code of evidence. (a) Admissibility is the "freely and publicly available … at minimal cost" standard (Rule 2.6): an exhibit (external DB, pretrained weights) is admissible only if the opposing parties could have obtained it too; Enveda's internal 1.2 B-spectrum PRISM corpus is held by the court, not admissible to litigants. (b) Burden and standard of proof sit entirely on the submitter: 25 ordered assertions per molecule, judged against a single binary identity test (canonical InChIKey14). There is no preponderance standard — a Tanimoto-0.95 analog is as worthless as CCO. (c) Discovery: the visible test.parquet is a disclosed but non-probative exhibit — the court told everyone it is a copy of training evidence and will be swapped at trial. (d) Hearsay: the hosts excluded GNPS propagated ("suspect") annotations from train "because the labels are inferred rather than measured" — the hearsay rule applied by the court to its own record. (e) Court-appointed expert: the metric notebook is the published jury instruction; the judge even canonicalises its own answer key live rather than trusting a stored column.

Derived rule — what may be pre-computed and what must run live. In court, documentary exhibits prepared before trial are admissible if authenticated and disclosed; testimony about the facts at issue must be given live. Translated: anything that is a function of admissible, pre-existing material may be computed offline and shipped as a Kaggle Dataset — candidate pools (COCONUT/PubChem/LOTUS/NPAtlas) already deduplicated on the scorer's key (RDKit 2026.03.3 TautomerEnumerator().Canonicalize → InChIKey14) and indexed by heavy-atom composition and neutral monoisotopic mass; fingerprints of every candidate; trained model weights; library-spectrum indices built from train. Only functions of the hidden exhibit (the test spectra) must run inside the 9 h offline notebook: spectrum embedding, formula/mass windows, candidate scoring, aggregation across a molecule's spectra, writing 25 SMILES. Concrete, testable idea: because the scorer re-keys both sides with the same function, the only thing that can hurt is a disagreement about identity between our pool key and the scorer's. So (1) build the pool key with the exact metric/rdkit-2026-3-3-wheel wheel (cp312 is in the dataset; it is public, attachable), never with 2026.03.6; (2) store, per candidate, the key and a flag tautomer_shifted (raw IK14 ≠ canonical IK14); (3) at submission time emit one SMILES per canonical key and emit the RDKit-canonical tautomer's SMILES, not the database spelling, so that whatever RDKit the scorer runs, the guess is already in the canonical form. Prediction to test on a held-out enveda-np-examples split keyed both ways: the measured MRR difference between raw-key dedup and canonical-key dedup should be ≤ 0.005 (kitopl's 1.15 %-collapse upper bound times the fraction of answers that rank high) — if it is larger, our dedup is merging things the scorer separates. A second testable derivation from the "no standard short of identity" point: slots 20–25 should hold tautomer/protomer-distinct spellings of nothing — i.e. there is zero value in hedging with near-isomers that share a key; every slot must carry a distinct canonical key, which is cheap to assert in the notebook (len(set(keys)) == len(keys)).

Where the analogy holds, partially holds, breaks. Holds: admissibility by public availability; burden on the submitter; disclosed-but-non-probative discovery; the hearsay exclusion the hosts applied; published jury instructions. Partially holds: "best evidence rule" (submit the parent structure, not the salt — my local test shows the sodium salt gets a different key) maps well, but the court here never weighs credibility: frivolous guesses cost only a slot, there are no sanctions, and no cross-examination. Breaks: there is no adversary (other teams do not contest our evidence), no appeal (a ParticipantVisibleError just burns one of five daily filings), and the judge is a lookup, not a fact-finder — the metric cannot be persuaded, only matched. The analogy also says nothing about the public/private split, which is the one procedural fact (what fraction of the hidden set the public LB sees) that we still cannot verify.

9. Gotchas — what could silently fool us

  1. The Kaggle API labels the metric "Mean Average Precision". It is MRR@25; the scorer's variable is still named ap. Anyone building local eval from the API label will compute the wrong thing.
  2. train.inchikey14 is not the scoring key. It is derived from normalized_smiles without tautomer canonicalisation; 1.58 % of train structures shift and 1.15 % collapse (kitopl). Deduplicate and validate on the canonical key or local MRR will undercount.
  3. RDKit version drift is a one-sided risk. The scorer warns but continues on mismatch. If our notebook keys a pool with 2026.03.6 and the scorer uses 2026.03.3, a correct candidate can be merged away before it is emitted. Pin the same wheel.
  4. Salts and multi-fragment SMILES are not stripped by the scorer. [Na+].CC(=O)[O-] ≠ acetic acid. Any pool that keeps COCONUT/PubChem salt forms must be parent-stripped by us (the hosts' normalized_smiles is "RDKit-standardised", so train labels are presumably parents — not verified for every library).
  5. Polyphenol canonicalisation hits maxTransforms=1000 (q7: MaxTransformsReached on quercetin/rutin/tetracycline; my timing 335 ms for quercetin). A truncated enumeration is the configuration most likely to differ between builds; it is also why canonical-keying a 740 k pool costs ~ 1 CPU-hour (4.7 ms/structure median per kitopl; polyphenols 50–70× worse).
  6. Hidden-set size is stated three ways: ~1,500 spectra (Data page), "approximately the same size" as 1,213 (Data page), ~2,500 (press release). Seven vs ten adducts is also inconsistent in the same official text. Treat the adduct list as ten and the per-molecule median as 3.
  7. Public LB is a sample of the hidden set with an unknown fraction. With ~400 molecules and per-molecule reciprocal-rank SD ≈ 0.45, the public score's standard error is ≈ 0.045 if the public share is 100 molecules, 0.032 at 200, 0.022 at 400 (inferred; see Open questions). q7's observed 228-team pile-up in 0.42–0.43 reflects shared public notebooks, not precision.
  8. Missing molecule_ids are not rejected by the scorer — they score 0 silently. Always start from sample_submission.csv (the tutorial does this) so every id is present.
  9. Invalid SMILES consume slots silently. A generator that emits 30 % unparsable strings wastes 7–8 of 25 ranks unless filtered through MolFromSmiles first.
  10. Rule 3.6 and CC BY-NC 4.0: a public GitHub repo containing competition-derived code or weights during the competition is a rules exposure (kabir0774's reading); keep repos private until the close.
  11. Entry status: as of this run the Kaggle API returns userHasEntered: true for the local account (q7 reported 403 earlier the same day) — someone accepted the rules; the Rules page text is now readable from a logged-in browser and should be captured verbatim to close the "M" rows above.

Implications for the challenge

  1. Attach metric/rdkit-2026-3-3-wheel (or a copy) to every notebook and pip install --no-index --find-links … rdkit==2026.3.3; key every candidate and every validation answer with the scorer's exact three-line function. Never key with 2026.03.6.
  2. Pre-compute offline (Explorer cluster) and ship as Kaggle Datasets: the canonical-keyed, salt-stripped, heavy-atom-composition-indexed candidate pool; per-candidate fingerprints; model weights; train library index. Reserve the 9 h window for inference only; target ≤ 3 h to leave headroom for Kaggle's slower CPUs.
  3. Enforce in the notebook before writing: 400 rows from sample_submission.csv, 1–25 non-empty tokens, all parseable, all distinct canonical keys, no ; or whitespace inside tokens, no NaN. A rejected file burns one of five daily submissions.
  4. Emit RDKit-canonical tautomer SMILES (post-Canonicalize) rather than database spellings; emit parent structures only.
  5. Build the local validation set as "novel molecules on timsTOF" (hold out by canonical key, assert zero exact spectral matches remain, per kitopl §6) and report MRR with ±1 SE for n = 250 (≈ ±0.03); do not react to public-LB deltas < 0.01 (q7).
  6. Budget submissions: 68 days × 5 = 340 slots remain before 2026-12-14; the leaders average ~2.3/day. Keep two clearly different final selections (e.g. retrieval-heavy vs generation-heavy).
  7. Licence hygiene for the MIT open-source obligation: COCONUT CC0/CC BY, LOTUS CC BY 4.0, NPAtlas CC BY-NC 4.0 (q7's table), competition data CC BY-NC 4.0 — record attribution now; check SIRIUS/CSI:FingerID terms before depending on them.
  8. Somebody with the accepted account should copy the Rules, Overview/Evaluation and Timeline pages verbatim into research/q4_challenge_intelligence/ to convert every "M" row to "V" and to settle rows 5, 12, 26, 29.

Open questions (and how to settle each)

Unknown How to settle
Exact Rules text (2.6 external data, 3.6 sharing, licence clause, eligibility) Logged-in browser on /rules; copy verbatim
Public/private split fraction Host post on the Evaluation page or forum; otherwise estimate from the public score's day-to-day variance of a fixed deterministic notebook (resubmit identical output twice: identical score ⇒ deterministic; no information on fraction) — only the hosts can settle it
Notebook RAM and whether TPU sessions are eligible for the scoring re-run Kaggle notebook settings page of the competition; host FAQ
Whether errored re-runs count against the 5/day limit Kaggle docs; empirical
Hidden spectra count (1,500 vs 2,500) Host clarification; irrelevant to scoring, relevant to runtime planning — plan for 2,500
Contents of discussion/741404 and any other host threads Open with a logged-in browser; the API does not expose discussions
SIRIUS / CSI:FingerID licence for non-academic use inside an MIT-released solution Read the SIRIUS licence; ask hosts on the forum

Sources