Skip to content

feat(agents): serve ggplot2 in the agent chat (R runtime) - #12448

Merged
MarkusNeusinger merged 13 commits into
mainfrom
claude/r-runtime
Oct 29, 2026
Merged

MarkusNeusinger merged 13 commits into
mainfrom
claude/r-runtime

Conversation

@MarkusNeusinger

Copy link
Copy Markdown
Owner

Summary

  • RRuntime (agents/anyplot/render/runtimes/r.py) serves ggplot2 through the runtime registry on top of PR 3a's R profile (feat(agents): R (ggplot2) code profile for the agent chat #12443).
    • The registry dispatches on the library's language.
    • The contract gains the column kinds for the loader, per-runtime blocking rules (R adds dataset-package, so a working form that keeps gapminder or palmerpenguins is refused) and adaptation targets.
    • The R row runs in exec mode under the exec filter, with a repair reserve of 15 s.
    • agents/cloudbuild.yaml adds ggplot2 to the admin deploy's _LIBRARIES; the 80 % eval matrix still gates the public release.
  • Prompts.
    • adapter.md is split into shared rules with slots, filled by adapter_python.md and adapter_r.md (and likewise adapter_highlights.md). Python's assembled prompts are pinned byte-identical by SHA-256.
    • Matplotlib/probe-only lines moved into Python's slots; R's say an R render has no probe.
    • The scope judge and the fixed other_library reply (11 languages) were stale since 2026-10-25: they still said only matplotlib and seaborn. They now name the served libraries from AGENT_LIBRARIES through a {{libraries}} slot, so a request for this plot in a served library is in scope.
  • Data fidelity (owner decision of 2026-10-29): when R reads integer cells beyond ±2^53 as the nearest double, the version's "what changed" list names each column with its count, and the plot stays ok.
  • Evals: 60 ggplot2 fixtures for the 10 matrix specs × 6 perturbations, plus the smoke case scatter-basic-ggplot2-renamed. Eligibility and the dev fixture find files by the library's language. ggplot2: 310 of 325 eligible (4 clean, 306 coupled, 15 blocked).
  • Frontend fix: a result card highlighted every version in the page's language, so after a library switch an older matplotlib version showed as R or the other way round. It now uses the version's own library.

Plan

agentic/specs/261024-agent-all-libraries.md, step 2c ("What PR 3b built").

Test plan

  • uv run ruff check . and uv run ruff format --check .
  • uv run --extra typecheck --extra agents mypy api core agents: no issues in 167 files.
  • uv run pytest tests/unit tests/integration -n 6: 19,273 passed, 27 skipped.
  • App: yarn lint, fm:check, type-check, test and yarn build on Node 24.
  • Browser check with the BFF mock (AGENT_LIBRARIES=matplotlib,ggplot2): after a plot in matplotlib, a switch to ggplot2 and a second plot, version 1 shows language-python and version 2 language-r. The only console errors are the known font CORS errors on port 3002.
  • Local render without a model: an identity adaptation of line-basic-ggplot2-renamed through LocalDockerBackend on the renderer image gives 3200x1800 in both themes, R1–R3 pass, and exec_deny: on.
  • Gemini 3.8 Flash checked the diff before the PR. All three findings were checked and none needed a change:
    • the heredoc in ci-image.yml: the YAML block strips the indentation, and bash -n passes on the extracted step;
    • the refusals() cache: process-wide, like get_settings;
    • the note length: bounded by the 64-character column cap.
  • .github/workflows/ci-image.yml: the new agents-image step (the R grammar loads, an R readiness scan runs in the built image) has no local loop; its first real run is this PR's CI.
  • After merge and deploy, two owner steps: the ggplot2 eval matrix on Vertex, then the first live admin test, which confirms the readr types end to end.

MarkusNeusinger and others added 11 commits October 29, 2026 12:51
The registry dispatches on the library's language: PythonRuntime for the six
Python libraries, RRuntime for ggplot2, which binds the R code profile of
PR 3a and runs plot.R through the renderer's R row in exec mode. The ADAPTATION
rules that reject the code and the targets of the others come from the
runtime (R adds dataset-package), loader_block takes the column kinds, and the
runtime's loader_notes put R's inexact reads of integers beyond 2^53 first
among a shipped plot's notes, with the count per column. The admin deploy
serves ggplot2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
…lot2

adapter.md keeps every rule the languages share and names a slot wherever the
code differs; adapter_python.md and adapter_r.md fill the slots
(policy.adapter_prompt). The Python prompt is byte for byte the one before the
split, which a test pins by its SHA-256. The R prompt tells the adapter the
placeholder df <- load_user_data(), the column constants read through
.data[[...]], the protected statements, the packages it may attach and that
dataset packages go, and what the validator refuses. root.md and gates.py lose
their Python-only wording, and the agents image's build check composes one
adapter instruction per language.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
dev_fixture.snapshot_from_repo and the eligibility sweep find a library's
files under its language with its extension (implementations/r/ggplot2.R)
instead of python/*.py, and the sweep scans through the library's runtime.
make_fixtures writes the ten matrix specs for ggplot2 (60 cases, 420 in all)
with the smoke case scatter-basic-ggplot2-renamed. The sweep over the real
catalogue pins ggplot2's counts: 325 files, 4 clean, 306 coupled, 15 blocked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
…guage

The result card highlighted every version with the page's language, which
follows the page's current library. After a library switch the thread holds
versions of several languages, so a matplotlib version above a ggplot2 one was
highlighted as R. The card now takes the language of the version's library
and keeps the page's language only for a library the app does not know.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
…scan

The agents-image job checks that every grammar the builder stage keeps loads
in the built image and that a catalogue ggplot2 file, piped in from the
checkout, normalises and gets the R runtime's readiness scan, as
POST /v1/sessions does. The COPY list check names the two runtime prompts and
the ggplot2 library prompt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
…elog

The plan's step 2c gains "What PR 3b built" with its decisions, the
eligibility of all seven libraries and what comes next; the design doc and the
agents README describe RRuntime, the registry's seven libraries, the adapter
prompt per language and the loader's notes; a changelog fragment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
… leave R

The scope judge's rubric named matplotlib and seaborn as the only libraries
the assistant adapts, so this plot in plotnine, altair, pygal, lets-plot or
ggplot2, all served to the admin, could be refused as other_library.
scope_judge.md now has one injected passage (policy.libraries_passage): the
libraries of AGENT_LIBRARIES and the catalogue's others, grouped by language.
A request for this plot in a served library is in_scope, and a question about
the session's code is in scope in any served language.

The adapter prompt's sentences that only matplotlib's probe makes true (the
VQ-03 and VQ-06 gate lines, the drawn-text check, the polar hint) move into
the Python slots; R's slots say that the host gates judge an R render without
a probe. adapter_highlights.md gets a slot for its code example, with ggplot2
idioms that pass the R validator. Both Python prompts stay byte-identical
(SHA-256 tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
Owner decision of 2026-10-29: the note that R reads integers beyond 2^53 as
the nearest double is the first entry of the shipped version's "what changed"
list, not a residual note, so the plot's status stays its own (ok stays ok).
The line fits a change note: the total, then each column with its count as
long as they fit 200 characters, the rest counted. The adapter notes give way
under the cap, and root.md has the root name the note in every reply to that
result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
The fixed reply to a request for this plot in another library said, in all
eleven languages, that the assistant adapts only in Python, with matplotlib
or seaborn. Each translation now has a {{libraries}} slot in place of that
clause, filled with the served libraries by name (policy.refusals_for), from
the same source as the scope judge's passage; library names need no
translation, and the rest of each text is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
Copilot AI lite review requested due to automatic review settings October 29, 2026 13:05
@codecov

codecov Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.96610% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
agents/anyplot/pipeline.py 92.30% 2 Missing ⚠️
agents/evals/ladder_lab.py 0.00% 2 Missing ⚠️
agents/anyplot/policy.py 98.98% 1 Missing ⚠️
agents/anyplot/render/contract.py 93.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

An active documentation nit makes the README’s eligibility statement inaccurate because the broader catalogue sweep includes blocked ggplot2 files.

1 open issue
What changed in this PR

Adds ggplot2 support to agent chat through a new R runtime, extending runtime dispatch, typed R data loading, prompts, deployment configuration, and evaluation coverage. It also corrects result-card syntax highlighting after switching libraries.

Changes:

  • Adds RRuntime with exec-mode rendering, R-specific validation, typed readr loading, large-integer fidelity notes, and ggplot2 registry support.
  • Splits adapter prompts by language and updates scope/refusal prompts for all served libraries.
  • Adds 60 ggplot2 evaluation fixtures, language-aware catalogue lookup, CI image smoke coverage, and a frontend highlighting fix.
File Description
tests/​unit/​agents/​test_image.py Updated as part of this pull request.
tests/​unit/​agents/​runtime/​test_pipeline.py Updated as part of this pull request.
tests/​unit/​agents/​runtime/​test_dev_fixture.py Updated as part of this pull request.
tests/​unit/​agents/​evals/​test_make_fixtures.py Updated as part of this pull request.
tests/​unit/​agents/​evals/​test_eligibility.py Updated as part of this pull request.
tests/​unit/​agents/​evals/​test_cases.py Updated as part of this pull request.
changelog.d/​r-runtime.md Updated as part of this pull request.
app/​src/​sections/​agent-chat/​ResultCard.tsx Updated as part of this pull request.
app/​src/​sections/​agent-chat/​ResultCard.test.tsx Updated as part of this pull request.
agents/​renderer/​commands.py Updated as part of this pull request.
agents/​evals/​stress.py Updated as part of this pull request.
agents/​evals/​matrix.py Updated as part of this pull request.
agents/​evals/​ladder_lab.py Updated as part of this pull request.
agents/​evals/​fixtures/​README.md Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​violin-basic-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​violin-basic-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​violin-basic-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​violin-basic-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​violin-basic-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​violin-basic-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​violin-basic-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​scatter-basic-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​scatter-basic-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​scatter-basic-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​scatter-basic-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​scatter-basic-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​scatter-basic-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​scatter-basic-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-x10/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-renamed/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-decimal-comma/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-date/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​pie-basic-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-timeseries-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-timeseries-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-timeseries-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-timeseries-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-timeseries-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-timeseries-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-timeseries-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-x10/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-renamed/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-decimal-comma/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-date/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​line-basic-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​histogram-basic-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​histogram-basic-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​histogram-basic-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​histogram-basic-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​histogram-basic-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​histogram-basic-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​histogram-basic-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-x10/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-renamed/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-decimal-comma/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​heatmap-basic-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​box-basic-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​box-basic-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​box-basic-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​box-basic-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​box-basic-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​box-basic-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​box-basic-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-x10/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-renamed/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-decimal-comma/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-date/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​bar-grouped-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-x10/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-x10/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-renamed/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-renamed/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-n5000/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-n12/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-n12/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-decimal-comma/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-decimal-comma/​case.json Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-date/​data.csv Updated as part of this pull request.
agents/​evals/​fixtures/​cases/​area-basic-ggplot2-date/​case.json Updated as part of this pull request.
agents/​evals/​eligibility.py Updated as part of this pull request.
agents/​evals/​cases.py Updated as part of this pull request.
agents/​Dockerfile Updated as part of this pull request.
agents/​cloudbuild.yaml Updated as part of this pull request.
agents/​anyplot/​settings.py Updated as part of this pull request.
agents/​anyplot/​render/​runtimes/​python.py Updated as part of this pull request.
agents/​anyplot/​render/​runtimes/​__init__.py Updated as part of this pull request.
agents/​anyplot/​render/​gates.py Updated as part of this pull request.
agents/​anyplot/​render/​contract.py Updated as part of this pull request.
agents/​anyplot/​render/​__init__.py Updated as part of this pull request.
agents/​anyplot/​prompts/​scope_judge.md Updated as part of this pull request.
agents/​anyplot/​prompts/​root.md Updated as part of this pull request.
agents/​anyplot/​prompts/​refusals.yaml Updated as part of this pull request.
agents/​anyplot/​prompts/​adapter_python.md Updated as part of this pull request.
agents/​anyplot/​prompts/​adapter_highlights.md Updated as part of this pull request.
agents/​anyplot/​dev_fixture.py Updated as part of this pull request.
.github/​workflows/​ci-image.yml Updated as part of this pull request.

Review effort: Lite

Comment thread agents/evals/fixtures/README.md Resolved
…to the matrix specs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
@MarkusNeusinger
MarkusNeusinger merged commit e054e35 into main Oct 29, 2026
16 checks passed
@MarkusNeusinger
MarkusNeusinger deleted the claude/r-runtime branch October 29, 2026 13:30
MarkusNeusinger added a commit that referenced this pull request Oct 30, 2026
)

## Summary
- **Makie served for the admin**, as #12448 served ggplot2.
`JuliaRuntime` (`agents/anyplot/render/runtimes/julia.py`) mirrors
`RRuntime` on J2a's Julia code profile: `plot.jl` renders through the
renderer's strict Julia row in exec mode under the exec filter, with the
precompiled depot and the J1.1 workload; command and environment match
the row key for key; `review_texts` on (no probe); `dataset-package`
blocks; the export runs `julia --project=. plot.jl`. Registered as
`JULIA_LIBRARIES = {"makie"}`; `agents/cloudbuild.yaml` `_LIBRARIES`
gains `makie` (admin-only deploy; the 80 % eval matrix gates the public
release, owner decision).
- **Loader note** (owner decision 2026-10-29): datetime cells whose
digits below the millisecond Julia's `DateTime` cannot hold are counted
per column and named first in "what changed"; the status stays the
render's. The 200-character note fitting moved from `r.py` into a shared
`runtimes/notes.py` (R's output byte-identical, its tests unchanged).
- **Julia errors read right.** `RuntimeCommand.stderr_head = "ERROR:"`
for the Julia row only: `executor.stderr_tail` keeps the first `ERROR:`
line (cut to 300 characters) in front of the tail within the same 2,000
characters (renderer and local backend); every other row's tail is byte
for byte as before. `error_summary(..., run_form=...)` maps the run
form's line numbers back to the code the adapter edits (the loader adds
15+ lines); Python and R accept and ignore the keyword. Before: "an
error (the tail cut off its first line) at line 116; in Legend()"; now:
"MethodError for initialize_block!() at line 86; in Legend()".
- **Prompt and evals.** `prompts/adapter_julia.md` fills every slot of
`adapter.md` (Python's prompt pinned by SHA-256, unchanged): the
placeholder and how the loader types each column, `df[!, COL]`, the
protected statements, the allowed packages (CSV and TimeZones
loader-only), a `fmt` helper for the plot language's decimal/thousands
marks (Julia's Printf has none), and Makie 0.24's refusals measured in
the image (a Date column with a missing cell: `dropmissing`, not
`filter`; spans, `vlines!` and `band!` on a date axis: numeric day
offsets; text as `barplot!` x: integer positions and `xticks`). Its
idioms pass both Julia validators and render in the image. 60
`*-makie-*` fixtures and the smoke case `scatter-basic-makie-renamed`;
eligibility: 325 files, 0 clean, 308 coupled, 17 blocked; all ten matrix
specs coupled.

Gemini 3.8 Flash pre-PR check: sound, no findings. Follow-ups left out
on purpose (Todoist): Python's error line also counts the run form (the
new keyword would fix it, but that changes Python's feedback text); deep
Makie failures without a Base exception type stay "an error"; telemetry
still classifies R/Julia render failures with Python's grammar.

## Plan

[agentic/specs/261024-agent-all-libraries.md](agentic/specs/261024-agent-all-libraries.md),
step 5 (J2b)

## Test plan
- [x] `uv run ruff check . && uv run ruff format --check .`; `uv run
--extra typecheck --extra agents mypy agents` (125 files clean)
- [x] `uv run --extra agents --extra test pytest tests/unit -q -n auto`
(20,326 passed, 27 skipped); the Julia image tests (4) against
`anyplot-renderer:julia`
- [x] `uv run --extra agents python -m agents.evals.make_fixtures
--check`; eligibility sweep (makie row above); `uv run python -m
tools.changelog check --base origin/main`
- [x] End to end without a model (`LocalDockerBackend`, the renderer
image with the workload): an identity adaptation of the smoke fixture
with a timestamp column (offsets, `Z`, microseconds, missing cells)
renders 3200x1800 in both themes (3200x1864 with the footer strip),
R1–R3 pass, 5.7 s per theme, `exec_deny: on`, 1,014 MiB; the note counts
60 timestamps and comes first in "what changed", status `ok`; two forced
failures summarise with the `ERROR:` line and the working-form line
- [ ] After the merge (owner): the eval matrix on Vertex (`*-makie-*`,
60 cases) and a live test in the admin chat

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants