Live agent plot evaluation¶
scripts/run_agent_plot_eval.py captures an opt-in, trusted local agent journey:
CSV request → durable rendered plot → style revision in the same session →
retrieval of both artifacts in a fresh session. It does not generate a plotting
solution for the agent. It changes no production MCP contracts or global host
settings. Fixed cases are line, groupedbar, scatter, and custom2panel.
Use the locked development environment with Python 3.12 and the optional MCP extra already installed. No live host runs during pytest.
export UV_PYTHON=3.12
uv run --no-sync pytest tests/mcp/agent_loop/test_capture.py tests/mcp/agent_loop/test_oracle.py -q
Repeat retained evaluations without model calls¶
The retained phase-0 evidence is at
~/scratch/dartwork-mpl-agent-loop-eval-2026-10-20. These commands only read saved
members, replay observations and review sidecars; they do not execute source or
invoke a model. Keep the evidence tree intact, including runtime/ and the frozen
baseline record.
export UV_PYTHON=3.12
export AGENT_EVAL_ROOT="$HOME/scratch/dartwork-mpl-agent-loop-eval-2026-10-20"
uv run --no-sync python scripts/evaluate_agent_plot.py evaluate --run "$AGENT_EVAL_ROOT/candidate/line"
uv run --no-sync python scripts/evaluate_agent_plot.py compare --baseline "$AGENT_EVAL_ROOT/baseline" --candidate "$AGENT_EVAL_ROOT/candidate"
evaluate --run DIR prints one episode’s JSON and exits 0 only when all six
independent dimensions pass: delivery, declared_validation, model_review,
semantic_replay, visual_review, and human_code_edits. Failure or unchecked
returns 1. The same command works for each of the four case directories.
compare prints both labels and candidate_gate; its overall exit also requires
the baseline to pass. This frozen comparison intentionally exits 1 while
candidate_gate is true. An incomplete baseline must remain visible.
Results and limits of this comparison¶
All four candidate evaluate calls exit 0. Their selected original/revision
bundles pass the independent data/row/mask/group/panel oracle, strict saved replay
pixels, both retrieval paths, review receipts, cleanup and explicit zero human
plotting-code edits. Four frozen baseline run hashes still match.
Case |
Preserved baseline result |
Candidate result |
|---|---|---|
line |
Final revision full-report receipt missing; other dimensions pass |
Six dimensions pass |
groupedbar |
Final report receipt missing; native NumPy scalar JSON serialization broke both saved replays, leaving semantics/pixels unchecked |
Six dimensions pass |
scatter |
No artifact: a production-valid 60-second request hit an undisclosed evaluator-only 20-second cap |
Six dimensions pass, including the final sentinel row |
custom2panel |
Six dimensions pass; global chart-hint warning retained |
Six dimensions pass; same warning retained |
The evaluator’s four-field numeric normalization was fixed after the baseline
(e71e0b46) and before candidate capture (810b4541). Baseline grouped-bar
replays were never reconstructed or rerendered after cleanup. The scatter cap
was absent from model input and within the production API’s allowed timeout;
its failure is not a demonstrated model/user-contract violation. These confounds
and four single episodes do not establish general model performance or prompt
causality. Baseline collection completion and candidate quality are separate.
Both custom2panel full reports expose line_no_lines for the scatter panel
because one global line hint covers both axes. Their complete status and empty
failed_checks do not erase this warning or prove data accuracy. Host previews
can resize larger images; actual decoded, artifact-correlated image receipt is
recorded separately from independent evaluator visual review. Five-member
recovery remains byte-exact, and replay versus stored PNG compares decoded
pixels strictly. The evaluator independently read all 14 retained original/
revision PNGs; baseline scatter has explicit missing tiles. No human wrote or
repaired the model’s plotting Python.
Two failed smokes plus eight scored attempts invoked USD 37.8 of the USD 41 stage-cap budget, within the original 7,500-second corpus clock. Known reported costs sum to USD 3.1587164; this is not the billing total because baseline scatter cost is unknown. Configured effort is recorded; effective effort remains null.
Execution receipts, frozen hashes, independent visual/zero-edit attestations,
and the actual equal-scale image PoC are retained in
~/scratch/dartwork-mpl-agent-loop-execution-2026-10-20/task-4-evidence/
(comparison.json, command-receipts.json, evaluator-versions.json,
independent-visual-and-human-review.json, visual-review.html). The PoC was
previewed at desktop/mobile widths before any merge or deployment. Source and
member evidence survives owned cwd/store cleanup; replaying source that needs a
removed absolute CSV path is not supported by this read-only comparison.
Cheap CI and follow-up scope¶
The existing tests/ collection runs the oracle and real stdio capture tests.
The Python 3.12 coverage job’s existing
scripts/check_integration_junit.py REPORT.xml requires a passing executed case
from each protected module, including tests.mcp.agent_loop.test_oracle and
tests.mcp.agent_loop.test_capture. Missing or only skipped/failed/error cases
fail that guard; pytest itself still rejects any failed case. No model job,
additional matrix, dependency or repeated suite is added.
This guide connects #483’s agent loop. Updating #482’s roadmap criteria remains a proposal; #499 viewer repair and #470 measured CI are independent tracks. Other P0 work stays on the backlog. Immutable run/revision and retained-input permission/lifetime/deletion, wire/discovery changes, hosted execution, website/ login/community and separate docs require their own approved scope. Phase 0 keeps native Figure/Axes, the five-member v1 bundle’s seven-day retention, 18/10/9/2 discovery and trusted local execution contracts.