Post the agent's duration with the run

da57aa907fb1 · AtlantisPleb · · parent 8ff2060e7c51

Post the agent's duration with the run

Sums each trial's agent_execution span and sends duration_seconds, so
the Gym's new Duration column fills for every future run — duration is
the local lane's whole cost.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GoYpb8FEmdxVErsv7ABCYi
Co-Authored-By
Claude Fable 5 <noreply@anthropic.com>

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified bench/post_gym_run.py

Diff

1 file changed, +10 -0

bench/post_gym_run.py modified +10

@@ -48,6 +48,7 @@ def main() -> int:

48 48
    trials = []
49 49
    input_tokens = 0
50 50
    output_tokens = 0
51
    duration_seconds = 0.0
51 52
    agent_version = None
52 53
    model = None
53 54
    for trial_dir in sorted(job_dir.iterdir()):

@@ -56,6 +57,14 @@ def main() -> int:

56 57
            continue
57 58
        trial = json.loads(trial_result.read_text())
58 59
        trials.append(trial)
60
        execution = trial.get("agent_execution") or {}
61
        started = execution.get("started_at")
62
        finished = execution.get("finished_at")
63
        if started and finished:
64
            from datetime import datetime
65
66
            span = datetime.fromisoformat(finished.replace("Z", "+00:00")) - datetime.fromisoformat(started.replace("Z", "+00:00"))
67
            duration_seconds += span.total_seconds()
59 68
        trajectory_path = trial_dir / "agent" / "trajectory.json"
60 69
        if trajectory_path.exists():
61 70
            trajectory = json.loads(trajectory_path.read_text())

@@ -98,6 +107,7 @@ def main() -> int:

98 107
        "tasks_passed": tasks_passed,
99 108
        "input_tokens": input_tokens or None,
100 109
        "output_tokens": output_tokens or None,
110
        "duration_seconds": int(duration_seconds) or None,
101 111
        "recipe_digest": recipe_digest,
102 112
        "report": {
103 113
            "job_id": result.get("id"),

This page updates live while a promote is in flight · changelog