diff --git a/CHANGELOG.md b/CHANGELOG.md index a066cda43d..cf9a083bd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,17 @@ aggregate instead: an italic *Catalog* line at the end of the version section an ## [Unreleased] +## [3.2.0] — 2026-08-29 — Findable by assistants + +anyplot 3.2 makes the catalogue findable by assistants, not only legible to them. The sister +project showed that an assistant's fetch tool often follows only URLs it has already seen in +fetched text, so the machine guide and one complete, callable example per surface now stand +wherever an agent actually reads — the SPA shell, both `robots.txt` files, every bot page. The +whole catalogue is one fetch (`llms-full.txt`), the MCP server tells the truth for all fifteen +libraries, and the bot site finally counts the crawler reads Plausible had been discarding. +Behind that: a generation retry cap that had parked 87 library pairs for good, a frontend deploy +that had failed silently, and a masthead that had claimed v1.0 through two releases. + ### Added - **LLM discoverability sync from kurrentschrift** — the sister project's @@ -62,6 +73,12 @@ aggregate instead: an italic *Catalog* line at the end of the version section an ### Fixed +- **`uv.lock` was unparseable after three Dependabot merges landed in sequence** — #10614, + #10615 and #10616 each carried the new `httpx2` and `httpx2-jsfetch` package blocks, and the + three squash merges kept every copy, so `uv lock` and every `uv run` on `main` failed with + "Dependency `httpx2` has missing `source` field but has more than one matching package". The + duplicate blocks are removed and the lock re-validated; found by this release's version bump, + the first Python-touching change after the three merges (#10811). - **Crawler reads on the bot site were mostly dropped by Plausible** — on the prerender path (Cloud Run app → Cloudflare → API) `cf-connecting-ip` is the app container's Google egress address, exactly the "hosting provider IP" Plausible discards, and `visitor_ip` preferred @@ -275,6 +292,9 @@ aggregate instead: an italic *Catalog* line at the end of the version section an pipeline story, the operator/privacy/transparency facts, and the actual palette hex values (straight from `core/palette.py`) — each derived from its single source of truth so the pages cannot drift (#10491). +- **Dependencies:** 10 Dependabot PRs — `mcp` 1.28.1 → 2.0.0 (#10615), `anthropic` 0.122.0 → + 1.0.0 (#10616), jsdom 29.1.1 → 30.0.1 (#10183), the MUI group (#8820), plus the grouped + python-minor (#10315, #10614), npm-minor (#10312, #10612) and actions (#10313, #10613) bumps. ### Removed @@ -283,6 +303,10 @@ aggregate instead: an italic *Catalog* line at the end of the version section an 2026-08-17 license audit, removal approved 2026-08-20); the served previews come from GCS and are unaffected (#10503). +*Catalog: 302 new implementations across 82 specs — the JavaScript backfill (MUI X Charts 71, +Highcharts 67, D3 47, ECharts 46, Chart.js 45) plus Makie 9, ggplot2 7 and 10 across the Python +libraries; no new specs; 3,704 implementations over 324 specs.* + ## [3.1.0] — 2026-08-19 — Legible to machines anyplot 3.1 makes the catalogue readable by machines. An assistant asked about a plot can now find @@ -1180,7 +1204,8 @@ interactive HTML previews. Actions workflows (spec creation, impl generation, AI review, auto-merge); Cloud Run + Cloud SQL + GCS; 1,081 unit tests. -[Unreleased]: https://github.com/MarkusNeusinger/anyplot/compare/v3.1.0...HEAD +[Unreleased]: https://github.com/MarkusNeusinger/anyplot/compare/v3.2.0...HEAD +[3.2.0]: https://github.com/MarkusNeusinger/anyplot/compare/v3.1.0...v3.2.0 [3.1.0]: https://github.com/MarkusNeusinger/anyplot/compare/v3.0.0...v3.1.0 [3.0.0]: https://github.com/MarkusNeusinger/anyplot/compare/v2.4.0...v3.0.0 [2.4.0]: https://github.com/MarkusNeusinger/anyplot/compare/v2.3.0...v2.4.0 diff --git a/app/package.json b/app/package.json index b04950a51f..930ec3ae7a 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "anyplot-website", - "version": "3.1.0", + "version": "3.2.0", "description": "anyplot Frontend - AI-powered plotting examples", "private": true, "type": "module", diff --git a/pyproject.toml b/pyproject.toml index bd0f446475..3e79305d73 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ # pyproject.toml [project] name = "anyplot" -version = "3.1.0" +version = "3.2.0" description = "AI-powered plotting examples" authors = [{ name = "Markus Neusinger", email = "admin@anyplot.ai" }] requires-python = ">=3.13" diff --git a/uv.lock b/uv.lock index 5262566b58..7f50721c31 100644 --- a/uv.lock +++ b/uv.lock @@ -226,7 +226,7 @@ wheels = [ [[package]] name = "anyplot" -version = "3.1.0" +version = "3.2.0" source = { editable = "." } dependencies = [ { name = "alembic" }, @@ -1546,8 +1546,8 @@ name = "httpcore2" version = "2.12.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "h11" }, - { name = "truststore" }, + { name = "h11", marker = "sys_platform != 'emscripten'" }, + { name = "truststore", marker = "sys_platform != 'emscripten'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/be/ad/f4f0e57345f1870f3e8cb624e058d7eca6e5a27d33bcc3311d9b618734cd/httpcore2-2.12.0.tar.gz", hash = "sha256:9293522bba0aa7c4c8e9e3f040c16575bd8868e155a77fa30c7a9085a5eae648", size = 67548, upload-time = "2026-08-18T13:22:08.211Z" } wheels = [ @@ -1623,31 +1623,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9b/43/832f631d32e4f1211caa2ba368317739fe71f0b8530e4c9d15dc454bac2a/httpx2_jsfetch-1.0-py3-none-any.whl", hash = "sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32", size = 6382, upload-time = "2026-08-07T00:13:06.567Z" }, ] -[[package]] -name = "httpx2" -version = "2.12.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio", marker = "sys_platform != 'emscripten'" }, - { name = "httpcore2", marker = "sys_platform != 'emscripten'" }, - { name = "httpx2-jsfetch", marker = "sys_platform == 'emscripten'" }, - { name = "idna" }, - { name = "truststore", marker = "sys_platform != 'emscripten'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7f/f8/579a8b51e42e38ee32647df9f08aa25643ae788e275cc625b199829c4671/httpx2-2.12.0.tar.gz", hash = "sha256:7631fe9887a8a2275f4a2540e053aa670fcc50742864a9ae7c66e609fdcf12cf", size = 100040, upload-time = "2026-08-18T13:22:09.086Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/95/411ba65569158e862368917aaf56597f3e5fa3b91b0502919638465a08f3/httpx2-2.12.0-py3-none-any.whl", hash = "sha256:cc8b6eecb8661c146b8f89a60e97456ee086e91a784ed31ac450c3a9e613dd36", size = 95427, upload-time = "2026-08-18T13:22:06.834Z" }, -] - -[[package]] -name = "httpx2-jsfetch" -version = "1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cd/c4/0e5636363151a2a1795e0a77617168b9ca438e1748ec05fc9b5687f93d64/httpx2_jsfetch-1.0.tar.gz", hash = "sha256:70a0e3eabfef7cce5ad9c629f7d01ca05e418f586646f4ddf14782e4c1454c60", size = 6872, upload-time = "2026-08-07T00:13:07.492Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/43/832f631d32e4f1211caa2ba368317739fe71f0b8530e4c9d15dc454bac2a/httpx2_jsfetch-1.0-py3-none-any.whl", hash = "sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32", size = 6382, upload-time = "2026-08-07T00:13:06.567Z" }, -] - [[package]] name = "identify" version = "2.6.15" @@ -2745,12 +2720,12 @@ resolution-markers = [ "python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "matplotlib" }, - { name = "mizani" }, - { name = "numpy" }, - { name = "pandas" }, - { name = "scipy" }, - { name = "statsmodels" }, + { name = "matplotlib", marker = "sys_platform != 'emscripten'" }, + { name = "mizani", marker = "sys_platform != 'emscripten'" }, + { name = "numpy", marker = "sys_platform != 'emscripten'" }, + { name = "pandas", marker = "sys_platform != 'emscripten'" }, + { name = "scipy", marker = "sys_platform != 'emscripten'" }, + { name = "statsmodels", marker = "sys_platform != 'emscripten'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/70/f4/c06a16b4ec540ff6af22e32144704f7e86dee18cd56eef14d66f9615cbf2/plotnine-0.15.7.tar.gz", hash = "sha256:6e578bdd93c7ba12ce495dcdeaf8651f8e4ccdceb0c85b94c8195566d709c2a0", size = 6855478, upload-time = "2026-06-13T10:47:14.277Z" } wheels = [ @@ -2766,12 +2741,12 @@ resolution-markers = [ "python_full_version == '3.14.*' and sys_platform == 'emscripten'", ] dependencies = [ - { name = "matplotlib" }, - { name = "mizani" }, - { name = "numpy" }, - { name = "pandas" }, - { name = "scipy" }, - { name = "statsmodels" }, + { name = "matplotlib", marker = "python_full_version >= '3.14' and sys_platform == 'emscripten'" }, + { name = "mizani", marker = "python_full_version >= '3.14' and sys_platform == 'emscripten'" }, + { name = "numpy", marker = "python_full_version >= '3.14' and sys_platform == 'emscripten'" }, + { name = "pandas", marker = "python_full_version >= '3.14' and sys_platform == 'emscripten'" }, + { name = "scipy", marker = "python_full_version >= '3.14' and sys_platform == 'emscripten'" }, + { name = "statsmodels", marker = "python_full_version >= '3.14' and sys_platform == 'emscripten'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9f/5d/3471689cf15cf2b6ebb6ebdebc7e33831fb35d85e2323875b5a0e150505d/plotnine-0.15.8.tar.gz", hash = "sha256:d3859997c3abd6edff6dee376d912716e75bbe0b0099b7054176d84fe11e8e20", size = 6863148, upload-time = "2026-08-14T16:27:49.399Z" } wheels = [ @@ -2786,12 +2761,12 @@ resolution-markers = [ "python_full_version < '3.14' and sys_platform == 'emscripten'", ] dependencies = [ - { name = "matplotlib" }, - { name = "mizani" }, - { name = "numpy" }, - { name = "pandas" }, - { name = "scipy" }, - { name = "statsmodels" }, + { name = "matplotlib", marker = "python_full_version < '3.14' and sys_platform == 'emscripten'" }, + { name = "mizani", marker = "python_full_version < '3.14' and sys_platform == 'emscripten'" }, + { name = "numpy", marker = "python_full_version < '3.14' and sys_platform == 'emscripten'" }, + { name = "pandas", marker = "python_full_version < '3.14' and sys_platform == 'emscripten'" }, + { name = "scipy", marker = "python_full_version < '3.14' and sys_platform == 'emscripten'" }, + { name = "statsmodels", marker = "python_full_version < '3.14' and sys_platform == 'emscripten'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2e/e8/d28be1fee4b1c7ef05f76bfb5a137ebc9b214f80b06b2771c73903d421e0/plotnine-0.16.0a12.tar.gz", hash = "sha256:e95565d9ae16ed60bfa16bcea2cb3c862e4b3165b8c257b8a96498f39bb8b17d", size = 7464639, upload-time = "2026-08-15T12:05:51.042Z" } wheels = [ @@ -3583,8 +3558,8 @@ name = "secretstorage" version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography" }, - { name = "jeepney" }, + { name = "cryptography", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "jeepney", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [