From 72aaf17f9eba42e87fd3f29e46fd009a2ca6c249 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Fri, 23 Oct 2026 01:34:48 +0200 Subject: [PATCH 1/4] chore(r): render R implementations on R 4.6.1 with ggplot2 4.0.3 The shared setup-r action installs R 4.6.1 (was 4.4.1) and pins the Posit Package Manager snapshot to 2026-10-20 (was 2025-01-15), which moves ggplot2 from 3.5.1 to 4.0.3. Every package in the list installs as a noble binary for R 4.6.1 from that snapshot. All 325 ggplot2 implementations render in both themes before and after (container run mirroring the action). The ggplot2 generator prompt gains a "ggplot2 4.0 rules" section for the changes that render differently without an error: label borders, binning edges, theme_void() borders, rotated top-axis text, legend order, fatten/draw_quantiles/errorbarh deprecations. core/constants.py shows ggplot2 4.0.3 and R 4.6. Co-Authored-By: Claude Opus 5.5 --- .github/actions/setup-r/action.yml | 12 ++++++--- changelog.d/r-4.6-ggplot2-4.md | 10 +++++++ prompts/library/ggplot2.md | 43 ++++++++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 changelog.d/r-4.6-ggplot2-4.md diff --git a/.github/actions/setup-r/action.yml b/.github/actions/setup-r/action.yml index aabd8132031..197ea928929 100644 --- a/.github/actions/setup-r/action.yml +++ b/.github/actions/setup-r/action.yml @@ -9,7 +9,9 @@ inputs: r-version: description: "R version to install" required: false - default: "4.4.1" + # Bump together with the snapshot date below: Posit Package Manager serves + # noble binaries per R minor version, so a new R needs a snapshot that has them. + default: "4.6.1" runs: using: "composite" @@ -51,13 +53,17 @@ runs: # matches the current ubuntu-latest runner image — update if GitHub moves # the runner OS, and bump the snapshot date deliberately. # - # Snapshot 2025-01-15 ships ggplot2 3.5.1. The repository has no R lock + # Snapshot 2026-10-20 ships ggplot2 4.0.3. The repository has no R lock # file, so this line stands in for one: core/library_versions.py reads # ggplot2's version from it for the database sync, but only while its date # is the one in the URL below. A new snapshot date fails # tests/unit/core/test_version_sources.py until this line names the ggplot2 # version the new snapshot installs (packageVersion("ggplot2") in a run). # + # Every package below installs from this snapshot as a noble binary for + # R 4.6.1. ggplot2 4.0 changes rendering defaults; the changes that matter + # to generated code are listed in prompts/library/ggplot2.md. + # # dependencies is restricted to required types (Depends/Imports/LinkingTo); # the default `NA` is identical but explicit is clearer. `TRUE` would also # pull in Suggests (sf, Hmisc, maps, quantreg, ...) — none of which the @@ -67,7 +73,7 @@ runs: run: | Rscript -e ' options( - repos = c(CRAN = "https://packagemanager.posit.co/cran/__linux__/noble/2025-01-15"), + repos = c(CRAN = "https://packagemanager.posit.co/cran/__linux__/noble/2026-10-20"), Ncpus = parallel::detectCores() ) install.packages( diff --git a/changelog.d/r-4.6-ggplot2-4.md b/changelog.d/r-4.6-ggplot2-4.md new file mode 100644 index 00000000000..d1c2294ff80 --- /dev/null +++ b/changelog.d/r-4.6-ggplot2-4.md @@ -0,0 +1,10 @@ +### Changed + +- **R implementations now render on R 4.6.1 with ggplot2 4.0.3.** The shared R + setup action installs R 4.6.1 and pins the Posit Package Manager snapshot to + 2026-10-20 (was R 4.4.1 and 2025-01-15, ggplot2 3.5.1). The ggplot2 generator + prompt gains a "ggplot2 4.0 rules" section for the changes that render + differently without an error: label borders, binning edges, `theme_void()` + borders, rotated top-axis text and legend order. All 325 ggplot2 + implementations still render in both themes; existing catalogue images stay + as they are until an implementation is regenerated. diff --git a/prompts/library/ggplot2.md b/prompts/library/ggplot2.md index 2476dd02922..59a8b6d7feb 100644 --- a/prompts/library/ggplot2.md +++ b/prompts/library/ggplot2.md @@ -2,7 +2,9 @@ ggplot2 is the canonical implementation of the grammar of graphics in R. This is anyplot's first R-language entry; the file extension is **`.R`** and the -runtime is **Rscript**, not Python. +runtime is **Rscript**, not Python. The CI runtime is **R 4.6 with ggplot2 4.0** +(pinned in `.github/actions/setup-r/action.yml`): write against the 4.0 API in +"ggplot2 4.0 rules" below, not 3.x habits. ## IMPORTANT: No Workarounds @@ -277,7 +279,8 @@ ggsave( ## R-Specific Gotchas - Use `linewidth =` for `geom_line()` and `element_line()` in modern ggplot2 - (≥ 3.4). `size =` triggers a deprecation warning. + (≥ 3.4). `size =` triggers a deprecation warning, and on `geom_bar()` / + `geom_col()` outlines ggplot2 4.0 ignores it entirely. - `theme()` chains compose right-to-left: a later `theme()` overrides an earlier one. Start with `theme_minimal(base_size = ...)`, then layer `anyplot_theme`. @@ -288,3 +291,39 @@ ggsave( removed in dplyr ≥ 1.0; `tibble::tibble` is the correct path. - Avoid `print(p)` at script end — `ggsave()` already renders the plot, and an extra `print()` opens an unused interactive device. + +## ggplot2 4.0 rules + +Each rule below changed between ggplot2 3.5 and 4.0: the old form still runs, +but renders differently or prints a deprecation warning. + +- **Label borders:** set the border width with `linewidth` (`0` for no border) + and its colour with `border.colour`. `label.size` is deprecated, and + `annotate("label", ..., label.size = 0)` is ignored outright ("Ignoring + unknown parameters"), so the label gets the default 0.25 mm border. +- **Horizontal error bars:** `geom_errorbar(aes(y = term, xmin = lo, xmax = hi), + orientation = "y", width = 0.2)`. `geom_errorbarh()` is deprecated. +- **Box, crossbar, pointrange:** `fatten` is deprecated. Style the parts + directly: `geom_boxplot(median.linewidth = , box.linewidth = , + whisker.linewidth = )`, `geom_crossbar(middle.linewidth = )`, and the point + `size` in `geom_pointrange()`. +- **Violin quantiles:** `geom_violin(quantiles = c(0.25, 0.5, 0.75), + quantile.linetype = 1)`. `draw_quantiles` is deprecated, and quantiles are now + computed from the data rather than from the density. +- **Histograms and other binning stats:** pass `boundary` (or explicit `breaks`) + together with `binwidth` or `bins`, for example `binwidth = 5, boundary = 0`. + ggplot2 4.0 moved the default bin edges, so unanchored bins shift between + versions and rarely land on round values. +- **`theme_void()` borders:** its root `rect` now has `linewidth = 0`, so a border + such as `legend.background = element_rect(fill = ELEVATED_BG, color = INK_SOFT)` + disappears. Give every bordered `element_rect()` an explicit `linewidth`. +- **Rotated axis text:** set both `hjust` and `vjust`. On a top axis + (`scale_x_discrete(position = "top")`) use `vjust = 0`; without it ggplot2 4.0 + pushes the labels up into the title. +- **Several legends:** fix their order with `guides(colour = guide_legend(order + = 1), size = guide_legend(order = 2))`. The default order changed in 4.0 and is + not stable across versions. +- **Subtitle and caption** inherit from `text`, no longer from `title`: style + `plot.subtitle` and `plot.caption` explicitly instead of through `title`. +- **Renamed:** `coord_transform()` replaces `coord_trans()`, and + `facet_wrap(dir = )` replaces `as.table`. From f2c9e69b4fb9374baa2b42b0796cc066af54c5b6 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Fri, 23 Oct 2026 01:35:49 +0200 Subject: [PATCH 2/4] docs(changelog): add the PR reference to the R 4.6 fragment Co-Authored-By: Claude Opus 5.5 --- changelog.d/r-4.6-ggplot2-4.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/r-4.6-ggplot2-4.md b/changelog.d/r-4.6-ggplot2-4.md index d1c2294ff80..e85023dff30 100644 --- a/changelog.d/r-4.6-ggplot2-4.md +++ b/changelog.d/r-4.6-ggplot2-4.md @@ -7,4 +7,4 @@ differently without an error: label borders, binning edges, `theme_void()` borders, rotated top-axis text and legend order. All 325 ggplot2 implementations still render in both themes; existing catalogue images stay - as they are until an implementation is regenerated. + as they are until an implementation is regenerated. (#12242) From 7136fb0d339d7f4daf61a97f450a0f4203bbf987 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Fri, 23 Oct 2026 01:43:18 +0200 Subject: [PATCH 3/4] docs(prompts): tighten the ggplot2 4.0 notes after the first review Rename the section to notes so the reviewer, which also reads this file, does not take it as a scoring rubric. Spell out the facet_wrap(dir) layout that replaces as.table = FALSE (checked: identical panel layout), and add the annotation_borders() rename and plot.tag inheritance. Co-Authored-By: Claude Opus 5.5 --- changelog.d/r-4.6-ggplot2-4.md | 2 +- prompts/library/ggplot2.md | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/changelog.d/r-4.6-ggplot2-4.md b/changelog.d/r-4.6-ggplot2-4.md index e85023dff30..691604bcd7b 100644 --- a/changelog.d/r-4.6-ggplot2-4.md +++ b/changelog.d/r-4.6-ggplot2-4.md @@ -3,7 +3,7 @@ - **R implementations now render on R 4.6.1 with ggplot2 4.0.3.** The shared R setup action installs R 4.6.1 and pins the Posit Package Manager snapshot to 2026-10-20 (was R 4.4.1 and 2025-01-15, ggplot2 3.5.1). The ggplot2 generator - prompt gains a "ggplot2 4.0 rules" section for the changes that render + prompt gains a "ggplot2 4.0 notes" section for the changes that render differently without an error: label borders, binning edges, `theme_void()` borders, rotated top-axis text and legend order. All 325 ggplot2 implementations still render in both themes; existing catalogue images stay diff --git a/prompts/library/ggplot2.md b/prompts/library/ggplot2.md index 59a8b6d7feb..05e67d9f0ff 100644 --- a/prompts/library/ggplot2.md +++ b/prompts/library/ggplot2.md @@ -4,7 +4,7 @@ ggplot2 is the canonical implementation of the grammar of graphics in R. This is anyplot's first R-language entry; the file extension is **`.R`** and the runtime is **Rscript**, not Python. The CI runtime is **R 4.6 with ggplot2 4.0** (pinned in `.github/actions/setup-r/action.yml`): write against the 4.0 API in -"ggplot2 4.0 rules" below, not 3.x habits. +"ggplot2 4.0 notes" below, not 3.x habits. ## IMPORTANT: No Workarounds @@ -292,9 +292,9 @@ ggsave( - Avoid `print(p)` at script end — `ggsave()` already renders the plot, and an extra `print()` opens an unused interactive device. -## ggplot2 4.0 rules +## ggplot2 4.0 notes -Each rule below changed between ggplot2 3.5 and 4.0: the old form still runs, +Each item below changed between ggplot2 3.5 and 4.0: the old form still runs, but renders differently or prints a deprecation warning. - **Label borders:** set the border width with `linewidth` (`0` for no border) @@ -323,7 +323,12 @@ but renders differently or prints a deprecation warning. - **Several legends:** fix their order with `guides(colour = guide_legend(order = 1), size = guide_legend(order = 2))`. The default order changed in 4.0 and is not stable across versions. -- **Subtitle and caption** inherit from `text`, no longer from `title`: style - `plot.subtitle` and `plot.caption` explicitly instead of through `title`. +- **Subtitle, caption and tag** inherit from `text`, no longer from `title`: + style `plot.subtitle`, `plot.caption` and `plot.tag` explicitly instead of + through `title`. - **Renamed:** `coord_transform()` replaces `coord_trans()`, and - `facet_wrap(dir = )` replaces `as.table`. + `annotation_borders()` replaces `borders()`. +- **Facet panel order:** `facet_wrap(as.table = )` is deprecated. Set the order + with a two-letter `dir` instead: the letters name the starting corner and the + first one the filling direction, so `dir = "lb"` starts bottom-left and fills + left to right, as `as.table = FALSE` did. From 8e503430153d8534dfa08c653e44651fb42aee86 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Fri, 23 Oct 2026 12:03:02 +0200 Subject: [PATCH 4/4] docs(prompts): state the ggplot2 API level like the other library prompts After #12240 every locked library's prompt names the major it writes against; tests/unit/core/test_version_sources.py holds ggplot2's line to the snapshot note in the setup-r action (4.0.3, so API level 4). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_0175hA62juZoajMcqKxWFGza --- prompts/library/ggplot2.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/prompts/library/ggplot2.md b/prompts/library/ggplot2.md index 05e67d9f0ff..f1589a65ec2 100644 --- a/prompts/library/ggplot2.md +++ b/prompts/library/ggplot2.md @@ -2,9 +2,11 @@ ggplot2 is the canonical implementation of the grammar of graphics in R. This is anyplot's first R-language entry; the file extension is **`.R`** and the -runtime is **Rscript**, not Python. The CI runtime is **R 4.6 with ggplot2 4.0** -(pinned in `.github/actions/setup-r/action.yml`): write against the 4.0 API in -"ggplot2 4.0 notes" below, not 3.x habits. +runtime is **Rscript**, not Python. + +**API level:** ggplot2 4. The Posit snapshot in `.github/actions/setup-r/action.yml` +pins this major; write against its API, with the changes in "ggplot2 4.0 notes" +below, not 3.x habits. ## IMPORTANT: No Workarounds