Skip to content

Latest commit

 

History

History
666 lines (552 loc) · 30.7 KB

repository.md

File metadata and controls

666 lines (552 loc) · 30.7 KB

Repository structure

Overview

anyplot follows a plot-centric repository pattern where everything for one plot type lives in a single directory:

plots/{specification-id}/
├── specification.md     # Description, Applications, Data, Notes, What a good version looks like
├── specification.yaml   # Spec-level metadata (tags, created, issue, suggested)
├── metadata/            # Per-library metadata (one file per library), grouped by language
│   ├── python/matplotlib.yaml
│   └── ...
└── implementations/     # Library implementations, grouped by language
    ├── python/matplotlib.py
    ├── r/ggplot2.R
    ├── julia/makie.jl
    ├── javascript/d3.js
    └── ...

Key Principle: The repository is the source of truth for all code, specs, and quality data. Preview images are stored in GCS. Database is derived via sync.

Key Benefit: Per-library metadata files eliminate merge conflicts when multiple implementations are generated in parallel.


Directory layout

anyplot/
├── plots/                             # Plot-centric directories
│   ├── scatter-basic/                 # Everything for basic scatter plot
│   │   ├── specification.md           # Library-agnostic specification
│   │   ├── specification.yaml         # Spec-level metadata (tags, created, issue)
│   │   ├── metadata/                  # Per-library metadata, by language
│   │   │   ├── python/                # matplotlib.yaml, seaborn.yaml, …
│   │   │   ├── r/                     # ggplot2.yaml
│   │   │   ├── julia/                 # makie.yaml
│   │   │   └── javascript/            # chartjs.yaml, d3.yaml, …
│   │   └── implementations/           # Library-specific code, by language
│   │       ├── python/                # matplotlib.py, seaborn.py, plotly.py, bokeh.py,
│   │       │                          # altair.py, plotnine.py, pygal.py, letsplot.py
│   │       ├── r/                     # ggplot2.R
│   │       ├── julia/                 # makie.jl
│   │       └── javascript/            # chartjs.js, d3.js, echarts.js, highcharts.js, muix.tsx
│   │
│   ├── bar-basic/
│   │   ├── specification.md
│   │   ├── specification.yaml
│   │   ├── metadata/
│   │   └── implementations/
│   │       └── ...
│   │
│   └── heatmap-correlation/
│       ├── specification.md
│       ├── specification.yaml
│       ├── metadata/
│       └── implementations/
│           └── ...
│
├── prompts/                           # AI agent prompts
│   ├── plot-generator.md              # Base rules for code generation
│   ├── adaptable-code.md              # The Data block convention every implementation follows
│   ├── quality-criteria.md            # Quality evaluation criteria
│   ├── quality-evaluator.md           # AI quality evaluation prompt
│   ├── spec-id-generator.md           # Assigns spec IDs
│   ├── default-style-guide.md         # Default visual style rules
│   ├── library/                       # Library-specific rules (15 files: 8 Python + ggplot2 + makie + 5 JavaScript)
│   │   ├── matplotlib.md
│   │   ├── seaborn.md
│   │   └── ...
│   ├── templates/                     # Templates for new specs
│   │   ├── specification.md
│   │   └── specification.yaml
│   └── workflow-prompts/              # Workflow-specific prompts
│       └── ...
│
├── core/                              # Shared business logic
│   ├── __init__.py
│   ├── adaptability.py                # Adaptability checker (adaptable-code convention)
│   ├── adaptability_mirror.py         # Builds the checker's single-file mirror
│   ├── canvas.py                      # Canvas gate + PNG auto-reject checks
│   ├── config.py                      # Configuration (.env-based)
│   ├── constants.py                   # Library metadata, constants
│   ├── defects.py                     # Review feedback grammar (defect lines)
│   ├── images.py                      # Image processing utilities
│   ├── library_names.py               # The names people write for a library (d3, chart js, mui x)
│   ├── perturbation.py                # Perturbed tables for the smoke run
│   ├── render_identity.py             # Pixel difference between two renders
│   ├── smoke_run.py                   # Perturbation smoke run, render pair, generator self-check
│   ├── spec_roles.py                  # Data roles, data shape and color role of a spec
│   ├── utils.py                       # General utilities
│   ├── database/                      # Database layer
│   │   ├── __init__.py
│   │   ├── connection.py              # Async connection management
│   │   ├── models.py                  # SQLAlchemy ORM models
│   │   ├── repositories.py            # Repository pattern
│   │   └── types.py                   # Custom SQLAlchemy types
│
├── api/                               # FastAPI backend
│   ├── __init__.py
│   ├── main.py                        # Application entry point
│   └── Dockerfile                     # Cloud Run deployment
│
├── agents/                            # Agent network on Google ADK (see concepts/agent-network.md)
│   ├── main.py                        # anyplot-agents service: the private /v1 API around the ADK runner
│   ├── stream.py                      # anyplot/1 SSE translator and output sanitiser
│   ├── Dockerfile                     # anyplot-agents image: agents extra, source tree with prompts and fonts, uid 1000
│   ├── cloudbuild.yaml                # Build, candidate deploy, IAM and /v1/status smoke, promote; owner steps in its header
│   ├── evals/                         # Model-regression harness (see agents/README.md)
│   │   ├── matrix.py                  # Runs eval cases through /v1 in process; report, diff, gallery
│   │   ├── make_fixtures.py           # Generates the synthetic spike-X cases, 10 specs x 6 datasets per library (seeded, rerunnable)
│   │   ├── cases.py                   # Case loading and --cases selection
│   │   ├── pricing.py                 # List prices and the cost of one model call
│   │   ├── report.py                  # Summary, baseline diff, Markdown, galleries; blind two-run gallery
│   │   ├── eligibility.py             # Model-free sweep: which catalogue files can be adapted, and why not
│   │   ├── baselines/                 # Committed baseline reports, one per model
│   │   ├── fixtures/cases/            # Eval cases (case.json + data.csv), also the adk web seed
│   │   └── reports/                   # Run reports, renders and galleries (git-ignored)
│   ├── renderer/                      # anyplot-renderer service: runs the code in Cloud Run sandboxes, no ADK import
│   │   ├── main.py                    # POST /render and GET /status behind the IAM caller check, one render slot
│   │   ├── executor.py                # sandbox do per theme: kill path, byte watchdog, launcher retry, bounded output
│   │   ├── auth.py                    # Caller check on the IAM-forwarded ID-token claims
│   │   ├── settings.py                # RendererSettings (RENDERER_* variables)
│   │   ├── wire.py                    # JSON contract shared with the agents' remote render backend
│   │   ├── Dockerfile                 # Renderer image: plotting venv, Noto fallback fonts, baked font cache, harness
│   │   └── cloudbuild.yaml            # Build, candidate deploy, IAM and render smoke, promote
│   └── anyplot/
│       ├── agent.py                   # Root agent "anyplot", ALL_AGENTS registry, App with plugins
│       ├── models.py                  # The only model and client factory (Claude on Vertex AI, Gemini)
│       ├── policy.py                  # Instructions composed from prompts/ and the catalogue prompts
│       ├── pipeline.py                # plot_pipeline node: adapt, check, render, review, repair
│       ├── prompts/                   # root, adapter, reviewer, scope and dataset judge prompts, refusals
│       ├── sub_agents/                # Per-library adapters and the tool-less reviewer
│       ├── tools/session.py           # Root's session tools and the plot_pipeline NodeTool
│       ├── plugins/                   # ScopeGuard, Budget, ToolSafety and the request ledger
│       ├── render/                    # Render contract, harness, host gates, PNG hardening, render store, backends (remote, local, fake)
│       │   ├── watermark.py           # Footer strip on served PNGs ("made with any.plot()", "anyplot.ai/<spec-id>")
│       │   └── fonts/                 # JetBrains Mono 2.304 Regular + Bold (SIL OFL 1.1, unmodified) and their notice
│       ├── schemas.py                 # Pydantic contracts of the plot pipeline
│       ├── settings.py                # AgentSettings (AGENT_* variables)
│       ├── data/                      # Deterministic data handling, no ADK import
│       │   ├── parse.py               # Pasted text -> canonical data.csv + DatasetProfile
│       │   ├── bindings.py            # Default role-to-column bindings and their checks (roles: core/spec_roles.py)
│       │   └── store.py               # Session-scoped in-memory dataset store
│       └── code/                      # Deterministic code handling, no ADK import
│           ├── validate.py            # Two-profile AST validator: SECURITY and ADAPTATION
│           ├── regions.py             # AST spans: THEME block, palette, placeholder, savefig, canvas
│           ├── normalise.py           # Header, title, sys.path guard, savefig target, exact canvas
│           ├── readiness.py           # blocked / coupled / clean scan with adapter hints
│           ├── edits.py               # Applies an AdaptPlan; protected regions
│           ├── loader.py              # load_user_data() placeholder -> pd.read_csv("data.csv")
│           └── export.py              # Attribution header for the downloaded plot.py
│
├── app/                               # React frontend
│   ├── src/
│   │   ├── components/
│   │   ├── pages/                     # AgentChatPage.tsx: the agent chat (/agent, visitors and admins)
│   │   ├── sections/                  # agent-chat/: data panel, thread, result card; debug/: agent case triage on /debug
│   │   └── lib/                       # api.ts; agent.ts and sse.ts for the agent chat BFF and its case routes
│   ├── scripts/
│   │   └── agent-bff-mock.mjs         # Local mock of the agent chat BFF (no API, no model)
│   ├── package.json
│   └── Dockerfile
│
├── automation/                        # Workflow automation
│   ├── gcp/budget-guard/              # Cloud Run function: disables Vertex AI at its budget
│   └── scripts/                       # Workflow-specific utilities
│       ├── sync_to_postgres.py        # Sync plots/ to database
│       ├── workflow_utils.py          # Utilities for GitHub Actions
│       ├── label_manager.py           # Label operations
│       └── workflow_cli.py            # CLI for workflows
│
├── tests/                             # Test suite
│   ├── conftest.py                    # Shared fixtures
│   ├── unit/                          # Fast, mocked tests
│   │   ├── api/
│   │   ├── core/
│   │   └── ...
│   ├── integration/                   # SQLite in-memory tests
│   └── e2e/                           # Real PostgreSQL tests
│
├── .github/
│   └── workflows/                     # GitHub Actions CI/CD
│       ├── spec-create.yml            # Creates specification (branch → PR → approval)
│       ├── impl-generate.yml          # Generates single library implementation
│       ├── impl-review.yml            # AI quality evaluation
│       ├── impl-repair.yml            # Repairs rejected implementation
│       ├── impl-merge.yml             # Merges approved implementation
│       ├── bulk-generate.yml          # Batch operations (multiple specs/libraries)
│       ├── sync-postgres.yml          # Sync to database on push to main
│       └── ...
│
├── alembic/                           # Database migrations
│   └── versions/
│
├── infra/                             # Infrastructure that lives outside the code
│   └── cloudflare/                    # Source for the apex Worker + its rollout notes
│
├── scripts/                           # One-time and manual scripts
│   ├── site-smoke.mjs                 # Does the site render? After every merge, and in CI
│   ├── evaluate-plot.py               # Manual plot evaluation
│   ├── regenerate-thumbnails.py       # Image processing
│   ├── backfill_review_metadata.py    # One-time migration
│   ├── fix_library_versions.py        # One-time fix
│   ├── migrate_metadata_format.py     # One-time migration
│   └── migrate_to_new_structure.py    # One-time migration
│
├── docs/                              # Documentation
│   ├── concepts/
│   ├── reference/
│   ├── workflows/
│   ├── contributing.md
│   └── index.md
│
├── pyproject.toml                     # Python project config (uv)
├── uv.lock                            # Dependency lock file
├── .env.example                       # Environment variables template
├── CLAUDE.md                          # AI assistant instructions
└── README.md

Key directories explained

plots/{specification-id}/

Purpose: Plot-centric directories containing everything for one plot type

Structure:

plots/{specification-id}/
├── specification.md     # Library-agnostic specification
├── specification.yaml   # Spec-level metadata (tags, created, issue, suggested)
├── metadata/            # Per-library metadata, grouped by language
│   ├── python/matplotlib.yaml  # Quality score, preview URL, generation history
│   └── ...
└── implementations/     # Library-specific implementations, grouped by language
    ├── python/matplotlib.py
    ├── javascript/muix.tsx
    └── ...

Characteristics:

  • ✅ Self-contained (spec + metadata + code + quality reports together)
  • ✅ One folder per plot type keeps navigation predictable
  • ✅ Synced to PostgreSQL via sync-postgres.yml
  • ✅ No merge conflicts (per-library metadata files)
  • ✅ Quality reports in metadata/{language}/{library}.yaml (review section)
  • ❌ NO preview images (stored in GCS)

Example: plots/scatter-basic/ contains everything for the basic scatter plot.


plots/{specification-id}/specification.md

Purpose: Library-agnostic plot specification

Contents:

  • Title and description
  • Data requirements (columns, types)
  • Use cases with domain context
  • Visual requirements

Naming: Always specification.md (consistent across all plots)


plots/{specification-id}/specification.yaml

Purpose: Spec-level metadata synced to PostgreSQL

Contents:

spec_id: scatter-basic
title: Basic Scatter Plot
created: 2025-01-10T08:00:00Z
updated: 2025-01-15T10:30:00Z
issue: 42
suggested: CoolContributor123
tags:
  plot_type: [scatter, point]
  domain: [statistics, general]
  features: [basic, 2d]
  data_type: [numeric]

Key Points:

  • Tags are at spec level (same for all libraries)
  • suggested credits the contributor who proposed the spec
  • updated timestamp set on any change (git history for details)

plots/{specification-id}/metadata/{language}/{library}.yaml

Purpose: Per-library metadata (one file per library, in the folder of its language: python, r, julia, or javascript)

Contents:

library: matplotlib
language: python
specification_id: scatter-basic

# Timestamps
created: 2025-01-10T08:00:00Z
updated: 2025-01-15T10:30:00Z

# Generation. An adopted file names the model that wrote it and its source
# instead, for example:
#   generated_by: gemini-4-argon
#   adopted_from: gemini/muix-9 (<commit sha>)
generated_by: claude-opus-4-7
workflow_run: 12345678
issue: 42

# Versions: the runtime of the implementation's language, and the library
language_version: 3.13.14
library_version: 3.11.0

# Previews, one per theme (the HTML variants only for interactive libraries)
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/matplotlib/plot-light.png
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/matplotlib/plot-dark.png
preview_html_light: null
preview_html_dark: null

# Quality
quality_score: 92

# Review feedback (used by AI for regeneration)
review:
  # AI's visual description of the generated plot
  image_description: |
    The plot shows a scatter plot with 100 data points displaying
    a positive correlation. Points are rendered in blue with 70%
    opacity. Axes are clearly labeled and a subtle grid is visible.

  # Detailed scoring breakdown by category
  criteria_checklist:
    visual_quality:
      score: 36
      max: 40
      items:
        - id: VQ-01
          name: Text Legibility
          score: 10
          max: 10
          passed: true
          comment: "All text readable at full size"
        - id: VQ-02
          name: No Overlap
          score: 8
          max: 8
          passed: true
          comment: "No element overlap detected"
    spec_compliance:
      score: 23
      max: 25
      items: [...]
    data_quality:
      score: 18
      max: 20
      items: [...]
    code_quality:
      score: 10
      max: 10
      items: [...]
    library_features:
      score: 5
      max: 5
      items: [...]

  # Final verdict
  verdict: APPROVED

  # Summary feedback
  strengths:
    - "Clean code structure"
    - "Good use of alpha for overlapping points"
  weaknesses:  # defect lines first, then at most three "Suggestion:" lines
    - "VQ-01 (both): tick labels at 8 pt are hard to read at full size → about 10 pt (+2 pt). Likely cause: tick_params labelsize=8."
    - "Suggestion: a slightly lighter grid would recede further"

  # Provenance of the review (filled by impl-review, not synced to the database)
  model: claude-opus-5-5          # resolved model ID, not the alias
  criteria_version: qc-1f3a9c0b2d.aqr-8e41d7a6c5.sg-0b9d2e7f41.lib-5c6a1e8d93
  rendered_at: "2026-09-27T12:04:31Z"  # creation time of the reviewed render

Key Points:

  • Each library has its own file (no merge conflicts!)
  • Created by impl-generate.yml, updated by impl-review.yml
  • Review feedback persisted for AI to improve on regeneration
  • A kept regeneration replaces quality_score and the review with its re-score of the live implementation, through a review-writeback PR that impl-merge.yml merges; updated, review.rendered_at, and impl_tags stay, because the code didn't change (see Stored review on a keep)
  • Extended review data includes image_description, criteria_checklist, and verdict for targeted fixes
  • review.model, review.criteria_version (git blob IDs of prompts/quality-criteria.md, ai-quality-review.md, default-style-guide.md, and the library prompt), and review.rendered_at record which model and rules produced the review; they aren't synced to the database. A value the review run can't determine is left out (removed if an earlier review wrote it), never filled with the model alias

GCS storage

Preview images are stored in Google Cloud Storage (not in repo):

gs://anyplot-images/
├── plots/{spec-id}/{library}/           # Production (after merge)
│   ├── plot.png                         # Full-size optimized image
│   └── plot.html                        # Optional (interactive libraries)
│
└── staging/{spec-id}/{library}/         # Temp (during review)
    └── plot.png, plot.html

Interactive libraries (.html): plotly, bokeh, altair, highcharts, pygal, letsplot

Image Processing: Images are optimized with pngquant. Branding is included in the plot title itself (e.g., scatter-basic · matplotlib · anyplot.ai).


plots/{spec-id}/implementations/

Purpose: Library-specific implementations, organized by language

Layout:

plots/{spec-id}/implementations/
├── python/       # 8 Python libraries (.py)
├── r/            # ggplot2 (.R)
├── julia/        # Makie.jl (.jl)
└── javascript/   # 5 JavaScript libraries (.js, MUI X as .tsx)

File Naming (by language):

Python (python/, .py):

  • matplotlib.py
  • seaborn.py
  • plotly.py
  • bokeh.py
  • altair.py
  • plotnine.py
  • pygal.py
  • letsplot.py

R (r/, .R):

  • ggplot2.R

Julia (julia/, .jl):

  • makie.jl

JavaScript (javascript/):

  • chartjs.js
  • d3.js
  • echarts.js
  • highcharts.js
  • muix.tsx (MUI X Charts, a React module)

Code Style (KISS):

""" anyplot.ai
scatter-basic: Basic Scatter Plot
Library: matplotlib 3.10.0 | Python 3.14
Quality: 92/100 | Created: 2025-01-10
"""

import matplotlib.pyplot as plt
import numpy as np

# Data
np.random.seed(42)
x = np.random.randn(100)
y = x * 0.8 + np.random.randn(100) * 0.5

# Plot
fig, ax = plt.subplots(figsize=(16, 9))
ax.scatter(x, y, alpha=0.7, s=50)
ax.set_title('Basic Scatter Plot')

plt.tight_layout()
plt.savefig('plot.png', dpi=300)

Header Format (4 lines):

  1. """ anyplot.ai - Branding
  2. {spec-id}: {Title} - Identification
  3. Library: {lib} {version} | Python {version} - Versions
  4. Quality: {score}/100 | Created: {date} - Quality + date

Rules:

  • No functions, no classes
  • No if __name__ == '__main__':
  • Only imports → data → plot → save

prompts/

Purpose: AI agent prompts for code generation and quality evaluation

Subdirectories:

  • library/ - Library-specific rules (15 files: 8 Python + ggplot2 + makie + 5 JavaScript)
  • templates/ - Templates for new specs (specification.md, specification.yaml)
  • workflow-prompts/ - Workflow-specific prompt templates

Files:

  • plot-generator.md - Base rules for all implementations
  • adaptable-code.md - The Data block convention: one replaceable block that ends in df, columns named once, plot code derived from df
  • quality-criteria.md - Definition of quality
  • quality-evaluator.md - AI quality evaluation
  • spec-id-generator.md - Assigns spec IDs
  • default-style-guide.md - Default visual style rules

core/

Purpose: Shared business logic and reusable components

Key Components:

  • database/connection.py - Async database connection
  • database/models.py - SQLAlchemy ORM models
  • database/repositories.py - Repository pattern for data access
  • canvas.py - Canvas gate (3200×1800 or 2400×2400 within ±16 px, the VQ-05 defect line) and the PNG auto-reject checks AR-04 and AR-07; python -m core.canvas <png> runs the gate
  • defects.py - Review feedback grammar: defect and suggestion lines, the criterion IDs, spec characteristics, and format_defect; automation/scripts/regen_gate.py keeps a parity-tested copy
  • spec_roles.py - Data roles from a spec's ## Data bullets, the data shape (table, matrix, network, generated, excluded) and the color-driving role; shared by the agent and the adaptability checker
  • library_names.py - The names people write for each catalogue library (any case, with or without .js or .jl, any separator, the short forms such as ggplot and mui x) and for the tools outside the catalogue; the agent chat's scope guard and its switch_plot tool read library names through it
  • adaptability.py - Adaptability checker for Python implementations (Adaptable catalogue code): the record, the CQ-01 defect lines, and the block and constant substitution; python -m core.adaptability report plots/ prints the catalogue baseline
  • adaptability_mirror.py - Builds automation/scripts/adaptability_check.py, the checker as one standard-library file; uv run python -m core.adaptability_mirror after a change to adaptability.py or spec_roles.py
  • perturbation.py - The perturbation smoke run's tables (renamed, more and fewer categories, one group, fewer and more rows, scaled values, a missing value in the loader's dtypes) and the source to run on each
  • render_identity.py - Share of differing pixels between two renders against a bound (0.5 % per theme); python -m core.render_identity old.png new.png
  • smoke_run.py - Runs an implementation: run executes it on each perturbed table in both themes, pair renders a new source and its predecessor in one environment and compares them, and selfcheck is the generator's Step 3c (static check plus smoke run, logged per attempt); python -m core.smoke_run run plots/{spec}/implementations/python/{library}.py

automation/

Purpose: Workflow-specific automation used by GitHub Actions

Key Components:

  • scripts/sync_to_postgres.py - Database sync (used by sync-postgres.yml)
  • scripts/workflow_utils.py - Parsing and utilities for workflows
  • scripts/label_manager.py - Label operations and transitions
  • scripts/workflow_cli.py - CLI interface for workflow steps
  • scripts/regen_gate.py - Regen gate: keeps or replaces a regeneration (used by impl-review.yml)
  • scripts/adaptability_check.py - The adaptability checker as one generated standard-library file for the workflow runner (impl-review.yml, "Adaptability check (record-only)")
  • scripts/adapt_record.py - Combines the checker mirror's record and the staged smoke run into one adapt record per source (used by impl-review.yml)
  • scripts/regen_writeback.py - Stores a kept regeneration's re-score as the live implementation's review (used by impl-review.yml and impl-merge.yml)
  • gcp/budget-guard/ - Cloud Run function that disables the Vertex AI API when its Cloud Billing budget is reached; a deploy unit, not a Python package (see GCP budget guard)

Principle: Only contains components actively used by workflows or deployed as GCP automation. One-time or manual scripts belong in scripts/.


scripts/

Purpose: One-time migrations and manually-run utilities

Key Components:

  • evaluate-plot.py - Manual plot quality evaluation
  • regenerate-thumbnails.py - Image processing utilities
  • backfill_review_metadata.py - One-time backfill migration
  • migrate_*.py - One-time structure migrations

Principle: Scripts that are not part of automated workflows. Used for maintenance, migrations, and manual operations.


api/

Purpose: FastAPI REST API

Structure:

  • main.py - Application entry point and app factory
  • routers/ - Modular route handlers (specs, plots, analytics, etc.)
  • dependencies.py - Shared FastAPI dependencies
  • schemas.py - Pydantic request/response schemas
  • analytics.py - Server-side Plausible tracking
  • cache.py - Server-side TTL caching layer

app/

Purpose: React frontend (Vite + TypeScript + MUI)

The agent chat ("Use with my data", one page at /agent for visitors and admins since 2026-11-06; /debug/agent only redirects there) lives in src/pages/AgentChatPage.tsx, src/sections/agent-chat/, src/hooks/useAgentSession.ts, src/lib/agent.ts and src/lib/sse.ts; it is built only with VITE_ENABLE_AGENT_CHAT=true. scripts/agent-bff-mock.mjs is a local mock of its backend for driving the page in a browser (see agents/README.md). The triage of the chat's quick-feedback cases is the "agent cases" section of src/pages/DebugPage.tsx, built from src/sections/debug/ in every build; while the API's agent kill switch is off, it shows one line instead of the list.


.github/workflows/

Purpose: CI/CD automation via GitHub Actions

Specification Workflows:

  • spec-create.yml - Creates specification (branch → PR → approval → merge)

Implementation Workflows:

  • impl-generate.yml - Generates single library (generate:{lib} label OR dispatch)
  • impl-review.yml - AI quality evaluation
  • impl-repair.yml - Repairs rejected implementation (max 4 attempts)
  • impl-merge.yml - Merges approved PR, creates per-library metadata
  • bulk-generate.yml - Batch operations (max 3 parallel)

Supporting Workflows:

  • sync-postgres.yml - Syncs plots/ to database on push to main

Naming conventions

Spec IDs

Format: {type}-{variant} or {type}-{variant}-{modifier}

Examples:

  • scatter-basic - Basic scatter plot
  • scatter-color-groups - Scatter with color-coded groups
  • bar-grouped-horizontal - Horizontal grouped bars
  • heatmap-correlation - Correlation matrix heatmap

Rules:

  • All lowercase
  • Hyphens as separators
  • Descriptive names (no numbers needed)

Implementation files

Always named by library, under the language's directory: implementations/{language}/{library}.{ext}

  • python/matplotlib.py, r/ggplot2.R, julia/makie.jl, javascript/d3.js, javascript/muix.tsx

What's not in the repository

Preview images

  • Where: Google Cloud Storage (gs://anyplot-images/plots/...)
  • Why: Binary files bloat git history

Secrets

  • Where: Environment variables, Cloud Secret Manager
  • Why: Security
  • Note: .env.example shows required variables without values

Note: Quality reports ARE stored in the repository in metadata/{language}/{library}.yaml (the review: section with strengths, weaknesses, criteria_checklist, verdict).


Database sync

The sync-postgres.yml workflow syncs plots/ to PostgreSQL on push to main:

What's Synced:

  • Spec content (full markdown from specification.md)
  • Spec metadata (title, description, tags from specification.yaml)
  • Implementation code (full Python source)
  • Implementation metadata (quality score, generation info from metadata/*.yaml)
  • Preview URLs from per-library metadata files
  • Quality review data (strengths, weaknesses, criteria_checklist, verdict)

Source of Truth: The plots/ directory is authoritative. Database is derived.


For contribution guidelines, see contributing.md