← All eighteen builds
VITOMIND · AGENT TEST

Write the parser, run the tests, stop when they pass

The goal: write a cron-expression parser (next_run) so that all 21 tests pass. The models get three tools (read a file, write a file, run the tests) and a budget of twelve turns. The test file is the spec; the expected dates come from an independent brute-force program the models never see. Our own tiny agent loop ran it; nothing was installed on the machine.

Meta Muse Wonder

4 turns of 1224 s$0.117 final: 21 of 21 tests pass

turn 1 · $0.004read_file tests/test_cron.py
turn 2 · $0.066write_file cron.py (4000 chars)
show the file
"""5-field cron next_run implementation (standard library only)."""
from datetime import datetime, timedelta

__all__ = ["next_run"]


def _parse_int(token, whole):
    # Strict integer parsing: only optional leading '-' and digits.
    # int() alone would accept '+5', underscores ('1_0'), whitespace, etc.
    s = token
    if not s:
        raise ValueError(f"Invalid cron field: {whole!r}")
    body = s[1:] if s.startswith("-") else s
    if not body.isdigit():
        raise ValueError(f"Invalid cron field: {whole!r}")
    return int(s)


def _parse_field(text, lo, hi):
    if not text:
        raise ValueError("Empty cron field")
    values = set()
    for part in text.split(","):
        if not part:
            raise ValueError(f"Invalid cron field: {text!r}")
        if part.count("/") > 1:
            raise ValueError(f"Invalid cron field: {text!r}")
        if "/" in part:
            base, step_token = part.split("/", 1)
            step = _parse_int(step_token, text)
            if step <= 0:
                raise ValueError(f"Invalid step in cron field: {text!r}")
            has_step = True
        else:
            base = part
            step = 1
            has_step = False

        if not base:
            raise ValueError(f"Invalid cron field: {text!r}")

        if base == "*":
            start, end = lo, hi
        elif "-" in base:
            # Range; also catches negative numbers / malformed ranges
            # because split will produce empty or extra pieces.
            pieces = base.split("-")
            if len(pieces) != 2 or not pieces[0] or not pieces[1]:
                raise ValueError(f"Invalid range in cron field: {text!r}")
            start = _parse_int(pieces[0], text)
            end = _parse_int(pieces[1], text)
            if start < lo or end > hi or start > end:
                raise ValueError(f"Range out of bounds in cron field: {text!r}")
        else:
            val = _parse_int(base, text)
            if val < lo or val > hi:
                raise ValueError(f"Value out of bounds in cron field: {text!r}")
            if has_step:
                # Step on a plain number: from that number to field max.
                start, end = val, hi
            else:
                values.add(val)
                continue

        for v in range(start, end + 1, step):
            values.add(v)

    if not values:
        raise ValueError(f"Invalid cron field: {text!r}")
    return values


def next_run(expr: str, after: datetime) -> datetime:
    if not isinstance(expr, str):
        raise ValueError("Cron expression must be a string")
    fields = expr.split()
    if len(fields) != 5:
        raise ValueError(f"Cron expression must have 5 fields: {expr!r}")

    minute_f, hour_f, dom_f, month_f, dow_f = fields

    minutes = _parse_field(minute_f, 0, 59)
    hours = _parse_field(hour_f, 0, 23)
    dom = _parse_field(dom_f, 1, 31)
    months = _parse_field(month_f, 1, 12)
    dow = _parse_field(dow_f, 0, 6)

    dom_restricted = not dom_f.startswith("*")
    dow_restricted = not dow_f.startswith("*")
    both_restricted = dom_restricted and dow_restricted

    sorted_minutes = sorted(minutes)
    sorted_hours = sorted(hours)

    # First minute strictly after `after`, seconds/microseconds ignored.
    start = after.replace(second=0, microsecond=0) + timedelta(minutes=1)

    # Search day-by-day. Upper bound generous enough for leap-year-only
    # schedules (Feb 29) while avoiding an infinite loop for impossible
    # schedules such as Feb 31.
    # 20 years of days is cheap when iterating per-day.
    start_date = start.date()
    for offset in range(366 * 20 + 2):
        day = start_date + timedelta(days=offset)
        if day.month not in months:
            continue
        dom_match = day.day in dom
        # Python: Monday=0 .. Sunday=6 ; cron: Sunday=0 .. Saturday=6
        cron_dow = (day.weekday() + 1) % 7
        dow_match = cron_dow in dow
        if both_restricted:
           
turn 3 · $0.021run_tests
test_cron.Cron.test_14) ... ok
test_15 (test_cron.Cron.test_15) ... ok
test_16 (test_cron.Cron.test_16) ... ok
test_17 (test_cron.Cron.test_17) ... ok
test_18 (test_cron.Cron.test_18) ... ok
test_19 (test_cron.Cron.test_19) ... ok
test_20 (test_cron.Cron.test_20) ... ok
test_invalid (test_cron.Cron.test_invalid) ... ok

----------------------------------------------------------------------
Ran 21 tests in 0.005s

OK
turn 4 · $0.026All 21 tests pass. Built `cron.py` exposing `next_run(expr, after)` using only the standard library: - Parses 5 fields (minute, hour, day-of-month, month, day-of-week 0=Sunday) supporting `*`, lists `,`, ranges `-`, and steps `/` (including `10-50/15`, `*/7`, and `5/20` meaning 5-to-max). - Returns the first minute strictly after `after` (truncating seconds, then +1 minute), searching efficiently day-by-day sorted by hour/minute. - Implements classic cron day logic: if both DOM and DOW are restricted (neither starts with `*`), either match qualifies; otherwise both must match. - Strict valida
Claude Opus 5.5

3 turns of 1221 s$0.065 final: 21 of 21 tests pass

turn 1 · $0.004read_file tests/test_cron.py
turn 2 · $0.032write_file cron.py (2374 chars)
show the file
"""Minimal 5-field cron evaluator (standard library only)."""
from datetime import datetime, timedelta

_RANGES = [(0, 59), (0, 23), (1, 31), (1, 12), (0, 6)]


def _num(s, lo, hi):
    if not s.isdigit():
        raise ValueError(f"bad number: {s!r}")
    v = int(s)
    if not lo <= v <= hi:
        raise ValueError(f"out of range: {v}")
    return v


def _field(text, lo, hi):
    out = set()
    for part in text.split(','):
        if not part:
            raise ValueError("empty token")
        base, step = part, 1
        if '/' in part:
            base, st = part.split('/', 1)
            if not st.isdigit() or int(st) == 0:
                raise ValueError(f"bad step: {st!r}")
            step = int(st)
        if base == '*':
            a, b = lo, hi
        elif '-' in base:
            x, y = base.split('-', 1)
            a, b = _num(x, lo, hi), _num(y, lo, hi)
            if a > b:
                raise ValueError("reversed range")
        else:
            a = _num(base, lo, hi)
            b = hi if '/' in part else a
        out.update(range(a, b + 1, step))
    return out


def next_run(expr: str, after: datetime) -> datetime:
    fields = expr.split()
    if len(fields) != 5:
        raise ValueError("need 5 fields")
    mins, hours, doms, mons, dows = (_field(f, *r) for f, r in zip(fields, _RANGES))
    dom_star, dow_star = fields[2].startswith('*'), fields[4].startswith('*')

    def day_ok(d):
        dm = d.day in doms
        dw = (d.isoweekday() % 7) in dows
        if not dom_star and not dow_star:
            return dm or dw
        return dm and dw

    t = after.replace(second=0, microsecond=0) + timedelta(minutes=1)
    limit = t.replace(year=t.year + 9) if not (t.month == 2 and t.day == 29) else t + timedelta(days=9 * 366)
    while t < limit:
        if t.month not in mons:
            y, m = (t.year + 1, 1) if t.month == 12 else (t.year, t.month + 1)
            t = datetime(y, m, 1)
            continue
        if not day_ok(t):
            t = datetime(t.year, t.month, t.day) + timedelta(days=1)
            continue
        if t.hour not in hours:
            t = datetime(t.year, t.month, t.day, t.hour) + timedelta(hours=1)
            continue
        if t.minute not in mins:
            t += timedelta(minutes=1)
            continue
        return t
    raise ValueError("no matching time found")
turn 2 · $0.032run_tests
test_cron.Cron.test_14) ... ok
test_15 (test_cron.Cron.test_15) ... ok
test_16 (test_cron.Cron.test_16) ... ok
test_17 (test_cron.Cron.test_17) ... ok
test_18 (test_cron.Cron.test_18) ... ok
test_19 (test_cron.Cron.test_19) ... ok
test_20 (test_cron.Cron.test_20) ... ok
test_invalid (test_cron.Cron.test_invalid) ... ok

----------------------------------------------------------------------
Ran 21 tests in 0.004s

OK
turn 3 · $0.029I wrote `cron.py`, and all 21 tests in `tests/test_cron.py` pass on the first run (3 turns out of the 12). `next_run(expr, after)` takes a standard 5-field cron expression and returns the first minute strictly after `after` that matches. Seconds are ignored. **Reading the expression:** - Each field accepts `*`, single numbers, lists (`a,b`), ranges (`a-b`) and steps (`*/n`, `a-b/n`). - A step on a plain number, like `5/20`, runs from that number up to the field's maximum. - Day-of-week uses 0 for Sunday through 6 for Saturday. - It raises `ValueError` for: - the wrong number of fields -