Find the hardest tasks. Train, then find harder tasks.
Self-play at your fingertips, repeated. Campaign does the finding with our proprietary technology, building verifiable tasks from your data, measuring them, and marking the ones worth training on, over and over again.
One campaign, from the first page to the frontier
Describe the work once.
Every campaign starts from one INSTRUCTION.md: the domain, what a good task looks like, the deliverable a solver must produce, how it is checked, and what to reject. It is the only input the run has, and every task that follows descends from it. This one asks for consensus bugs in a pinned Raft library, each one reproduced by a seeded simulation of crashes, partitions, and reordered messages.
The rules come before the game.
Before a single task exists, the campaign agent turns that page into a task setting: a small package of code that tells the setter how to build a task, what each environment contains, and how a verifier decides a reward.
Proven before it scores anything.
The task setting is checked against known answers before it is trusted to grade anything. Once it passes, the campaign records the certified task pack and a checksum of its contents, so every reward in the run traces back to code that was proven first.
Coverage is planned, not left to chance.
This campaign runs the Mulberry method, so a taxonomy trial first agrees a plan of seven categories for the domain, from leader election to storage recovery. Each new task is sampled against the least-covered category, so a long run spreads across the whole subject instead of circling one corner of it.
Every task arrives with its own test.
Self-play has two sides. On the first, a setter model writes one concrete task: the instruction a solver is handed, an environment with the repository and its dependencies, and a verifier that reads what an attempt produced and returns pass or fail.
Unfair tasks never reach the scoreboard.
A validator checks every authored task against the campaign’s acceptance rules before it can count. The second task’s hidden test fails on some seeds even with a correct fix, so it cannot tell right from wrong, and it is rejected. A rejected task is never measured, never counted, and never spends a single attempt.
Eight attempts, each in its own sandbox.
On the other side, a solver model attempts the task eight times, each rollout in its own sandbox under the same limits. The task’s own verifier scores every attempt pass or fail, and an attempt that could not be measured gets no reward rather than a guessed one, so the solve rate counts only what was checked.
Mixed results are the signal.
This task passed three of its eight attempts, so it lands in the frontier band, the tasks a model solves 12% to 50% of the time, and it lights up. Its attempts hold both successes and failures, the contrast reinforcement learning learns from. A task passed every time, or never, gives training nothing to compare.
Then it keeps going, unattended.
A long-horizon campaign runs iteration after iteration inside the time and attempt budget you set; here, ten batches of ten tasks. Each batch finishes before the next begins, trials inside a batch run side by side up to the concurrency you chose, and nothing needs you while it works.
Later batches lean harder on purpose.
Mulberry hands each new batch the history of the work before it and lowers its target solve rate as the run goes on. Watch the passes thin out: the solver cleared 54% of its attempts in the first batch and 18% in the last, while the frontier kept filling in.
A day of work, and all of it evidence.
After 22 hours and 37 minutes of self-play, inside the 23.5-hour compute budget that is the most one campaign allows, the run measured 94 tasks through 752 graded attempts, rejected six it could not grade fairly, and marked 81 in the frontier band. Every task keeps its instruction, attempts, files, and scores, so any result traces back to what produced it.
Train on it. Raise the bar. Run again.
Export the frontier tasks with their full instructions and measured solve rates, and train your model on them in your own pipeline. When your model outgrows them, raise the bar in the INSTRUCTION.md and launch the next campaign to find harder tasks, round after round.
Read the whole day on one chart.
The same campaign in the Campaign Conclusion Timeseries: tasks started and concluded, the solve rate falling as later batches lean harder, and the share of measured tasks in the frontier band across nearly a day. Drag across the chart to zoom into any hour.
- Iteration 1, measuredday-task-000159m 54s3 of 8 passedFrontier
- Iteration 1, rejectedday-task-00026m 54sNot measured
- Iteration 1, measuredday-task-00031h 4m5 of 8 passed
- Iteration 1, measuredday-task-00041h 9m4 of 8 passedFrontier
- Iteration 1, measuredday-task-00051h 6m2 of 8 passedFrontier
- Iteration 1, measuredday-task-00061h 3m6 of 8 passed
- Iteration 1, measuredday-task-00071h 8m4 of 8 passedFrontier
- Iteration 1, measuredday-task-00081h 5m3 of 8 passedFrontier
- Iteration 1, measuredday-task-00091h 2m8 of 8 passed
- Iteration 1, measuredday-task-00101h 7m4 of 8 passedFrontier
- Iteration 2, measuredday-task-00111h 4m4 of 8 passedFrontier
- Iteration 2, measuredday-task-00121h 1m3 of 8 passedFrontier
- Iteration 2, measuredday-task-00131h 6m5 of 8 passed
- Iteration 2, measuredday-task-00141h 3m2 of 8 passedFrontier
- Iteration 2, measuredday-task-00151h 11m4 of 8 passedFrontier
- Iteration 2, measuredday-task-00161h 5m3 of 8 passedFrontier
- Iteration 2, measuredday-task-00171h 2m7 of 8 passed
- Iteration 2, measuredday-task-00181h 10m4 of 8 passedFrontier
- Iteration 2, measuredday-task-00191h 4m2 of 8 passedFrontier
- Iteration 2, measuredday-task-00201h 1m3 of 8 passedFrontier
- Iteration 3, measuredday-task-00211h 9m3 of 8 passedFrontier
- Iteration 3, measuredday-task-00221h 3m4 of 8 passedFrontier
- Iteration 3, measuredday-task-00231h 0m2 of 8 passedFrontier
- Iteration 3, rejectedday-task-00247m 54sNot measured
- Iteration 3, measuredday-task-00251h 2m4 of 8 passedFrontier
- Iteration 3, measuredday-task-00261h 10m3 of 8 passedFrontier
- Iteration 3, measuredday-task-00271h 7m5 of 8 passed
- Iteration 3, measuredday-task-00281h 1m2 of 8 passedFrontier
- Iteration 3, measuredday-task-00291h 9m4 of 8 passedFrontier
- Iteration 3, measuredday-task-00301h 6m3 of 8 passedFrontier
- Iteration 4, measuredday-task-00311h 0m2 of 8 passedFrontier
- Iteration 4, measuredday-task-00321h 8m3 of 8 passedFrontier
- Iteration 4, measuredday-task-00331h 5m4 of 8 passedFrontier
- Iteration 4, measuredday-task-003459m 54s3 of 8 passedFrontier
- Iteration 4, measuredday-task-00351h 7m2 of 8 passedFrontier
- Iteration 4, measuredday-task-00361h 4m6 of 8 passed
- Iteration 4, measuredday-task-00371h 9m3 of 8 passedFrontier
- Iteration 4, measuredday-task-00381h 6m1 of 8 passedFrontier
- Iteration 4, measuredday-task-00391h 3m4 of 8 passedFrontier
- Iteration 4, measuredday-task-00401h 8m2 of 8 passedFrontier
Start the loop with one page of instructions.
Find the hard tasks, train on them, then find harder ones. Campaign is open to approved Vmax accounts: join the waitlist for early access, or sign in if you already have one.