Skip to content

task.yaml reference

All keys are validated by Pydantic; unknown keys are rejected.

Top level

Key Type Default Notes
id str directory name [a-z0-9][a-z0-9._-]{1,79}
title str required one line
type bugfix · feature · refactor · perf required
difficulty easy · medium · hard medium
language str python informational
tags list[str] [] filter with --tag on list/validate/run, or load_tasks(tags=)
problem_statement str required shown to the agent
hints list[str] [] shown to the agent
metadata dict {} free-form (miners store provenance here)

repo

Key Default Notes
source local local copies path; git clones url at commit
path repo relative to the task dir
url, commit required / recommended for git
setup [] shell commands run once after materialisation (pip install -e ., npm ci); their output becomes part of the baseline
setup_timeout 600 seconds

tests

Key Default Notes
command python -m pytest -q -p no:cacheprovider --junitxml={junit} {junit} is replaced with a path outside the repo
hidden [] paths under <task>/hidden/ copied into the workspace only at grading time
fail_to_pass [] must fail at baseline and pass after
pass_to_pass [] must pass on both sides
timeout 300 seconds

Test ids accept any of the forms the JUnit parser registers: pytest node ids (tests/test_x.py::test_a, tests/test_x.py::TestK::test_b), classname::name (tests.test_x::test_a) or the bare name.

perf (required for type: perf)

Key Default Notes
command required runs the benchmark once; lower is better
min_speedup 1.5 full credit at or above this
runs 3 interleaved baseline/candidate runs; the minimum of each is used
noise_floor 1.15 speed-ups below this factor score 0
timeout 300 per run
timing wall wall: repogym times the process externally (tamper-proof). reported: trust {"seconds": x} / a bare float printed by the benchmark

constraints

Key Default Notes
paths ["**/*.py"] files that AST metrics and required_patterns are computed on
allowed_files [] if set, changed files must match one of these globs
protected_files [] must never change; files referenced by fail_to_pass/pass_to_pass are always protected
forbidden_patterns [] regexes that must not appear in changed files
required_patterns [] regexes that must appear somewhere in paths
max_function_length lines, per function (Python); objective on refactor tasks, gate otherwise
max_cyclomatic_complexity McCabe, per function (Python); objective on refactor tasks, gate otherwise
max_files_changed
max_lines_changed added + deleted

Globs use ** sensibly: **/*.py matches a.py and pkg/a.py; src/** matches everything under src/.

grading

Key Default Notes
weights {tests: 1.0} per objective grader (tests, perf, quality); normalised. perf is added automatically for perf tasks and quality for refactor tasks with limits. Gates (constraints, regression-only tests, quality on non-refactor tasks) ignore weights and zero the score when they fail
partial_credit true tests score = fraction of fail_to_pass passing
require_all_pass_to_pass true a single regression zeroes the tests score (else proportional penalty)
pass_threshold 1.0 minimum weighted score for passed

solution

Exactly one of:

Key Notes
patch unified diff applied with git apply (falls back to patch -p1)
dir directory overlaid onto the workspace

env

Key Default Notes
max_steps 50 auto-submits when reached
step_timeout 120 seconds for run/test actions
allowed_commands python, python3, pytest, node, npm, cargo, go, ls, cat, grep, find, head, tail, wc, sed, awk, echo, pwd, diff, tree, rg first token of every shell segment must match
max_output_chars 20000 observations are middle-truncated
reward_shaping false test action yields up to 0.1 total for improvements on visible fail_to_pass

Full example

id: feature-ratelimiter
title: "Add a TokenBucket limiter alongside SlidingWindowLimiter"
type: feature
difficulty: medium
language: python
tags: [concurrency, api-design, feature]
problem_statement: |
  `ratelimit.py` ships a `SlidingWindowLimiter`. Add a second strategy,
  `TokenBucket`, with this interface:

      TokenBucket(capacity: float, refill_rate: float, clock=None)
      .tokens(key) -> float               # current balance after refilling
      .try_acquire(key, tokens=1.0) -> bool
      .acquire(key, tokens=1.0) -> None   # raises RateLimitExceeded(key, retry_after)

  Semantics:
  - every key gets its own bucket that starts full
  - tokens refill continuously at `refill_rate` per second (fractional tokens
    accumulate) and never exceed `capacity`
  - `retry_after` is the time until enough tokens are available
  - `capacity <= 0`, `refill_rate <= 0`, `tokens <= 0` or `tokens > capacity`
    raise `ValueError`
  - `clock` defaults to `time.monotonic` and is injectable for tests

  The visible tests in `tests/test_token_bucket.py` currently fail with an
  ImportError. Hidden tests exercise per-key isolation, fractional refill and
  multi-token acquisition.
hints:
  - Store (tokens, last_refill_timestamp) per key and refill lazily on access.
repo:
  source: local
  path: repo
tests:
  command: "python -m pytest -q -p no:cacheprovider --continue-on-collection-errors --junitxml={junit}"
  hidden:
    - tests/test_token_bucket_hidden.py
  fail_to_pass:
    - tests/test_token_bucket.py::test_bucket_starts_full
    - tests/test_token_bucket.py::test_bucket_refills_over_time
    - tests/test_token_bucket.py::test_bucket_never_exceeds_capacity
    - tests/test_token_bucket.py::test_acquire_raises_with_retry_after
    - tests/test_token_bucket.py::test_invalid_arguments
    - tests/test_token_bucket_hidden.py::test_keys_are_independent
    - tests/test_token_bucket_hidden.py::test_fractional_tokens_accumulate
    - tests/test_token_bucket_hidden.py::test_acquire_multiple_tokens
    - tests/test_token_bucket_hidden.py::test_cannot_request_more_than_capacity
  pass_to_pass:
    - tests/test_sliding_window.py::test_allows_up_to_limit
    - tests/test_sliding_window.py::test_window_slides
    - tests/test_sliding_window.py::test_check_raises_with_retry_after
constraints:
  allowed_files: ["ratelimit.py"]
  max_cyclomatic_complexity: 8
grading:
  weights: {tests: 1.0}
solution:
  patch: solution.patch
env:
  max_steps: 40