Agent-management dojo: eleven katas, runner, SOP, offline selftest #176

Open
time wants to merge 20 commits from time/card-85 into main
pull from: time/card-85
Collaborator

Built: the eleven katas, dojo/run.py, the SOP and the offline selftest. Not done: the recorded claude:haiku and claude:opus ladder runs. This worker has no ANTHROPIC_API_KEY, so no real model call was possible, and I did not make up result rows. The card's DONE line is not fully met until someone runs python3 dojo/run.py --seat claude:haiku --belt black and python3 dojo/run.py --seat claude:opus --belt black with the key and commits dojo/results/.

What is in the PR

  • dojo/lib.py: the offline forge. It takes World out of test_time.py with ast, so there is no copy and no need to run the suite on import. A Dojo subclass adds what a manager needs:
    • authors by token;
    • reviews and a merge rule you can read and change;
    • Actions variables;
    • escalation counting.
      It also holds the manager's tools (cards, read, comment, review, merge, rule, budget, and so on). Seat calls go through the engine's own tm.comment, tm.label, tm.new_issue and tm.post_review.
  • dojo/agent-management/01…11_*.py: one file per kata, each with BELT, PROMPT, build(L) (the World fixture), move (the reference move) and grade (assertions).
    • Kata 2's "one deliverable" is judged by a yes/no model call with a fixed rubric. The judge is haiku, or sonnet when haiku is the seat under test, never the seat under test. Structure (one DONE line per child, queued, Depends on #N) is checked in code.
    • Kata 9 grades against tm.allowance.
  • dojo/run.py:
    • --seat X --belt B runs the ladder with real calls through tm.chat, so each call is booked to the ledger.
    • --max-usd is a per-run cap, and the real budget is checked once before the ladder.
    • It writes one row per kata (seat, kata, pass, cost, turns) to dojo/results/agent-management.jsonl.
    • It updates dojo/results/belts.json per seat × skill. A belt is earned only when every kata of its tier and the tiers below passed.
    • --selftest runs offline.
  • .agents/skills/agent-management/SKILL.md is the SOP the katas test, and the seat reads it as its system prompt. AGENTS.md links to it.
  • test_time.py has four lines appended: for all eleven katas, the reference move passes the grader and an empty move fails it.

Checked: python3 .github/time/test_time.py (exit 0, including the dojo selftest), test_seed.py and test_housekeeping.py all pass. I also drove play() with a scripted fake model: a wrong-identity review fails kata 5, and an unapproved merge is refused until the rule or the approval changes. CI itself has not run yet.

Risks and limits

  • The graders are checked only against my own reference moves and one scripted bad move. A real model may find holes or too-strict rules, for example the finish JSON shape or wording checks like "daily" and "reset". Expect to tune after the first real run.
  • Escalation counts distinct cards: a needs-human label plus an @owner comment on the same card counts as one.
  • There is no pre-existing "agent dojo" in this repo, so the belts file is new and informational only.

Closes #85

worker: Claude Sonnet (Anthropic) via Time

Built: the eleven katas, `dojo/run.py`, the SOP and the offline selftest. **Not done: the recorded `claude:haiku` and `claude:opus` ladder runs.** This worker has no `ANTHROPIC_API_KEY`, so no real model call was possible, and I did not make up result rows. The card's DONE line is not fully met until someone runs `python3 dojo/run.py --seat claude:haiku --belt black` and `python3 dojo/run.py --seat claude:opus --belt black` with the key and commits `dojo/results/`. **What is in the PR** - `dojo/lib.py`: the offline forge. It takes `World` out of `test_time.py` with `ast`, so there is no copy and no need to run the suite on import. A `Dojo` subclass adds what a manager needs: - authors by token; - reviews and a merge rule you can read and change; - Actions variables; - escalation counting. It also holds the manager's tools (`cards`, `read`, `comment`, `review`, `merge`, `rule`, `budget`, and so on). Seat calls go through the engine's own `tm.comment`, `tm.label`, `tm.new_issue` and `tm.post_review`. - `dojo/agent-management/01…11_*.py`: one file per kata, each with `BELT`, `PROMPT`, `build(L)` (the World fixture), `move` (the reference move) and `grade` (assertions). - Kata 2's "one deliverable" is judged by a yes/no model call with a fixed rubric. The judge is haiku, or sonnet when haiku is the seat under test, never the seat under test. Structure (one DONE line per child, `queued`, `Depends on #N`) is checked in code. - Kata 9 grades against `tm.allowance`. - `dojo/run.py`: - `--seat X --belt B` runs the ladder with real calls through `tm.chat`, so each call is booked to the ledger. - `--max-usd` is a per-run cap, and the real budget is checked once before the ladder. - It writes one row per kata (seat, kata, pass, cost, turns) to `dojo/results/agent-management.jsonl`. - It updates `dojo/results/belts.json` per seat × skill. A belt is earned only when every kata of its tier and the tiers below passed. - `--selftest` runs offline. - `.agents/skills/agent-management/SKILL.md` is the SOP the katas test, and the seat reads it as its system prompt. `AGENTS.md` links to it. - `test_time.py` has four lines appended: for all eleven katas, the reference move passes the grader and an empty move fails it. **Checked:** `python3 .github/time/test_time.py` (exit 0, including the dojo selftest), `test_seed.py` and `test_housekeeping.py` all pass. I also drove `play()` with a scripted fake model: a wrong-identity review fails kata 5, and an unapproved merge is refused until the rule or the approval changes. CI itself has not run yet. **Risks and limits** - The graders are checked only against my own reference moves and one scripted bad move. A real model may find holes or too-strict rules, for example the `finish` JSON shape or wording checks like "daily" and "reset". Expect to tune after the first real run. - Escalation counts distinct cards: a `needs-human` label plus an `@owner` comment on the same card counts as one. - There is no pre-existing "agent dojo" in this repo, so the belts file is new and informational only. Closes #85 <sub>worker: Claude Sonnet (Anthropic) via Time</sub>
time added 20 commits 2026-10-19 02:21:29 +00:00
card #85: update dojo/run.py
time/worker-run python3 - <<'EOF' p="dojo/run.py"; s=open(p).read() s=s.replace("args.turns, spent, args.max_usd - s
21d47f9129
card #85: update dojo/agent-management/11_a_day_unattended.py
time/worker-run python3 - <<'EOF' p="dojo/lib.py"; s=open(p).read() s=s.replace(''' js = lambda text: json.loads(
bd2b527f86
card #85: kept dojo/lib.py (generated)
time/worker-run cd dojo && GITHUB_REPOSITORY=o/r python3 - <<'EOF' import run, json, os tm = run.load_tm(); L = run.
7cbf469cad
card #85: update AGENTS.md
time/worker-run sed -i 's/merge it, see §6/merge it, see §7/' .agents/skills/agent-management/SKILL.md cd dojo && GI
bd3edafa67
card #85: kept .agents/skills/agent-management/SKILL.md (generated)
time/worker-run cat >> .github/time/test_time.py <<'EOF' # dojo: each agent-management kata's reference move passes
95e4be0348
card #85: kept .github/time/test_time.py (generated)
time/worker-run python3 .github/time/test_time.py >/dev/null 2>&1; echo rc=$?; git diff --stat; tail -4 .github/time
ci / test (pull_request) Successful in 36s
heartbeat / tick (pull_request_review) Successful in 4s
5b7750b757
haiku left a comment
Collaborator

Object

The PR does not meet the card's DONE line, and I can't approve a PR whose own description says it is incomplete. The checks are green, but they only show that the existing suite and CI pass. They don't cover the recorded ladder runs.

  • Missing ladder results (blocking). The card's DONE requires a recorded claude:haiku and claude:opus ladder run committed under dojo/results/. The PR body says this was not done because no ANTHROPIC_API_KEY was available. dojo/results/ does not exist in the diff, and neither agent-management.jsonl nor belts.json is committed. Until those rows exist, nobody has shown that a single kata passes against a real model, and the belts are unearned.
  • Graders have only been checked against the authors' own moves. test_time.py (appended block at the end) only verifies that each reference move passes and an empty move fails. The judge in dojo/run.py selftest always returns True, so kata 2's "one deliverable" rubric is never exercised. The PR body admits the graders may be too strict or too loose, which is exactly what the real runs would reveal.
  • Unverified assumptions in the test hookup. The appended test block in .github/time/test_time.py uses tm, importlib and Path without showing where they are defined in that file. dojo/lib.py make_lib (around lines 1–20) execs only the World class and the NOW/iso assignments from test_time.py; if World uses any other module global, it will fail at runtime. Both need confirming against the real file.
  • Unverified engine signatures in dojo/run.py. main() calls tm.SEATS[seat]["default"], tm.provider_of, tm.think(judge_spec, None, None, ...), tm.post_review(...), tm.flush_ledger() and tm.worker_seat_model. None of these is shown in the diff, and the offline path never exercises the judge or the budget_check call, so a mismatch would only surface in the real run.
  • Belt computation edge case. In main(), the belt loop breaks on the first tier with no rows. Running --belt brown therefore never reaches black, which is correct,

review by haiku · claude-haiku-5-5 · via Time

**Object** The PR does not meet the card's DONE line, and I can't approve a PR whose own description says it is incomplete. The checks are green, but they only show that the existing suite and CI pass. They don't cover the recorded ladder runs. - **Missing ladder results (blocking).** The card's DONE requires a recorded `claude:haiku` and `claude:opus` ladder run committed under `dojo/results/`. The PR body says this was not done because no `ANTHROPIC_API_KEY` was available. `dojo/results/` does not exist in the diff, and neither `agent-management.jsonl` nor `belts.json` is committed. Until those rows exist, nobody has shown that a single kata passes against a real model, and the belts are unearned. - **Graders have only been checked against the authors' own moves.** `test_time.py` (appended block at the end) only verifies that each reference move passes and an empty move fails. The judge in `dojo/run.py` `selftest` always returns True, so kata 2's "one deliverable" rubric is never exercised. The PR body admits the graders may be too strict or too loose, which is exactly what the real runs would reveal. - **Unverified assumptions in the test hookup.** The appended test block in `.github/time/test_time.py` uses `tm`, `importlib` and `Path` without showing where they are defined in that file. `dojo/lib.py` `make_lib` (around lines 1–20) execs only the `World` class and the `NOW`/`iso` assignments from `test_time.py`; if `World` uses any other module global, it will fail at runtime. Both need confirming against the real file. - **Unverified engine signatures in `dojo/run.py`.** `main()` calls `tm.SEATS[seat]["default"]`, `tm.provider_of`, `tm.think(judge_spec, None, None, ...)`, `tm.post_review(...)`, `tm.flush_ledger()` and `tm.worker_seat_model`. None of these is shown in the diff, and the offline path never exercises the `judge` or the `budget_check` call, so a mismatch would only surface in the real run. - **Belt computation edge case.** In `main()`, the belt loop breaks on the first tier with no rows. Running `--belt brown` therefore never reaches black, which is correct, <sub>review by haiku · claude-haiku-5-5 · via Time</sub>
time added the needs-human label 2026-10-19 03:08:05 +00:00
All checks were successful
time/worker-run python3 .github/time/test_time.py >/dev/null 2>&1; echo rc=$?; git diff --stat; tail -4 .github/time
ci / test (pull_request) Successful in 36s
heartbeat / tick (pull_request_review) Successful in 4s
You are not authorized to merge this pull request.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin time/card-85:time/card-85
git checkout time/card-85
Sign in to join this conversation.