The rules
What you submit
A Hugging Face model repository at a pinned revision, holding a safetensors checkpoint and a config in the published architecture. No participant code ever runs.
The contract
A submission is a Hugging Face model repository at a pinned revision, holding exactly two things that matter:
model.safetensors— the weights of a bpp_libero_v1 checkpoint, as safetensors. Pickle formats are rejected outright.config.yaml— the resolved model configuration, which must match the published architecture template except on the keys the template marks as mutable.
That is all. No participant code is ever executed.
Why the validator owns inference
Context parity is structural, not honour-system. The prompt is one demonstration, encoded the same way for every model on both sides of every duel. Participant-supplied prompt code could break that silently. Validator-supplied code cannot.
Both sides of a duel genuinely receive the same unit. That is what makes a paired comparison mean anything, and what makes the diagnostic won/lost/tied counts readable.
Test-time training and test-time search are excluded by construction rather than by a rule somebody has to police. The forward pass is the validator's.
No arbitrary code execution, which matters when the thing running your model also holds a crown. The validator never unpickles entrant data; the model-side run happens in a container with no network.
The cost is real: the architecture is fixed. A genuinely novel backbone needs a new template before it can compete, and adding one bumps the specification version.
The automated check
Every submission passes through the same gate before it is queued:
- the repository holds model.safetensors, config.yaml;
- every file matches the extension allow-list — .safetensors, .yaml, .yml, .json, .md, .txt;
- the repository is under 4 GiB;
- the config diffs clean against the bpp_libero_v1 template;
- every tensor in the safetensors header matches the canonical name, shape and dtype set, read as bytes — the weights are then loaded strictly;
- the parameter count is under 800M.
The submission gate, from spec.json
- Architecture
- bpp_libero_v1
- Required files
- model.safetensors, config.yaml
- Allowed file extensions
- .safetensors, .yaml, .yml, .json, .md, .txt
- Allowed tensor dtypes
- F32, BF16, F16
- Parameter cap
- 800M
- Repository size cap
- 4 GiB
Rendered from spec.json at build time — the same file the validator reads.
Converting a training checkpoint
Training with the public Behavior Prompting code produces a .ckpt file, which is a pickle and
is refused. The validator ships a converter that writes the two files the gate expects:
From a training checkpoint to a submission
icilval convert-ckpt path/to/last.ckpt --out ./submission
# writes submission/model.safetensors and submission/config.yaml
icilval check-model ./submission
# runs the same gate the validator runs, offlinePush the output directory to a Hugging Face model repository and note the commit hash. The revision you submit is the revision that is evaluated, forever: a branch or tag name is refused, because a mutable name would let the weights that hold a crown quietly stop being the weights that were scored.
What "no weight updates" means
The strict reading: parameters are frozen for the entire unit, and adaptation happens only through the demonstration in the prompt. Fast weights, test-time gradient steps, prompt-vector optimisation, hypernetworks and entrant-supplied retrieval are all out of scope. Attention over the provided demonstration is the thing being scored.
We take the strict reading for one reason: it is the only one enforceable structurally. The validator owns the forward pass, so there is nowhere in the loop for a gradient step to happen.
Budgets
Operational limits, from spec.json
- Soft per-action budget
- 1 s
- Hard per-action budget
- 30 s
- Model errors tolerated per episode
- 3
- Per-unit wall clock
- 300 s
- Per-side wall clock
- 3 h
- Per-duel wall clock
- 8 h
- Model load budget
- 600 s
Rendered from spec.json at build time — the same file the validator reads.
Hard timeouts exist because a duel has to terminate, and because a per-action budget bounds test-time search without needing a separate rule about it. A timeout or a model error ends the episode as a failure and is recorded on the unit like any other outcome. A fault the validator caused voids the unit instead — see void units.
Before you send it
Honest measurement says what is published about your entry and how to check the arithmetic on a duel page. Questions answers the rest.
