Repository navigation
feat(agents): serve ggplot2 in the agent chat (R runtime) - #12448
Merged
Merged
Conversation
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
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
…rompt 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
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Contributor
There was a problem hiding this comment.
🟡 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
RRuntimewith exec-mode rendering, R-specific validation, typedreadrloading, 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
…to the matrix specs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
4 of 5 tasks
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

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).dataset-package, so a working form that keeps gapminder or palmerpenguins is refused) and adaptation targets.agents/cloudbuild.yamladds ggplot2 to the admin deploy's_LIBRARIES; the 80 % eval matrix still gates the public release.adapter.mdis split into shared rules with slots, filled byadapter_python.mdandadapter_r.md(and likewiseadapter_highlights.md). Python's assembled prompts are pinned byte-identical by SHA-256.other_libraryreply (11 languages) were stale since 2026-10-25: they still said only matplotlib and seaborn. They now name the served libraries fromAGENT_LIBRARIESthrough a{{libraries}}slot, so a request for this plot in a served library is in scope.ok.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).Plan
agentic/specs/261024-agent-all-libraries.md, step 2c ("What PR 3b built").Test plan
uv run ruff check .anduv 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.yarn lint,fm:check,type-check,testandyarn buildon Node 24.AGENT_LIBRARIES=matplotlib,ggplot2): after a plot in matplotlib, a switch to ggplot2 and a second plot, version 1 showslanguage-pythonand version 2language-r. The only console errors are the known font CORS errors on port 3002.line-basic-ggplot2-renamedthroughLocalDockerBackendon the renderer image gives 3200x1800 in both themes, R1–R3 pass, andexec_deny: on.ci-image.yml: the YAML block strips the indentation, andbash -npasses on the extracted step;refusals()cache: process-wide, likeget_settings;.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.