Skip to content

v0.0.1

Choose a tag to compare

@github-actions github-actions released this 12 Nov 14:32
· 4 commits to master since this release
1693a7b

[0.0.1] - 2026-11-12

The tool contract moves from 1.0.0 to 1.1.0 (CONTRACT_VERSION); the change is additive. Every 1.0.0 call keeps its
meaning, apart from the refusals under Security and Fixed that correct defects, and new warnings. The chart document
introduced here is version 1.

Security

  • Interactive HTML could run script from an ECharts tooltip. In 0.0.0, and in the npm releases 0.0.2 and 0.0.3
    before it, the page's CSP allowed 'unsafe-inline' scripts, and ECharts writes a tooltip formatter string into the page as HTML, so a formatter such as
    <img src=x onerror=…> in an option (the option can come from data or a model) ran its handler when the tooltip
    opened. Three layers now stop it: the page's script-src is the SHA-256 hashes of exactly its own two scripts
    (with base-uri, form-action and object-src 'none'), so no inline handler, javascript: URL or injected
    script runs; every ECharts tooltip in an option is checked against an allow-list of attribute-free tags (<br>,
    <b>, <span>, <table>…), and anything else, an attribute, a comment or an encoded < is refused with
    ECHARTS_MARKUP_REFUSED at its JSON path; and the same check runs inside the page before ECharts starts, so an
    edited page fails to its static chart rather than inserting markup. {b}<br/>{c} still draws two lines. Regenerate
    any interactive HTML made with 0.0.0, 0.0.2 or 0.0.3 from untrusted options.

Added

  • Chart documents (ChartDocumentV1, version 1): a typed recipe or a raw engine spec, its data, and its
    appearance, layout and interactions, checked strictly with a JSON path for every problem. charts_quick takes
    document (the recommended path for the 14 standard types); charts_render and charts_validate take
    document or a saved documentPath (with an optional expectedRevision); document is a new output format. A
    call takes exactly one input arm (INPUT_CONFLICT otherwise). See docs/documents.md.
  • 14 typed recipes (bar, horizontal_bar, grouped_bar, stacked_bar, line, area, stacked_area,
    scatter, bubble, pie, donut, histogram, box_plot, heatmap) from one registry that owns each recipe's
    schemas, compiler, examples, data requirements and interaction and layout support. Aggregation is explicit:
    repeated groups without options.aggregate are AGGREGATION_REQUIRED, count counts rows and takes no measure,
    and a missing measure is left out and reported (VALUE_MISSING), never read as zero.
  • The saved artifact <name>.chart.json (opencode-charts-artifact, version 1): the canonical document with its
    rows captured before the transform, the captured theme base, defaults, custom-font digests and colour domain, and a
    sha256: revision. Replaying it uses what it captured, not today's defaults. A result also carries a render
    fingerprint, and never the captured rows.
  • charts_update: a presentation patch (title, alt text, theme and token overrides, category colours, layout,
    interactions) to a saved artifact at a known revision, published as a new immutable generation. Data, bindings,
    aggregation, sorting, transforms, locale, currency and seed cannot change. A stale or edited revision is
    DOCUMENT_REVISION_MISMATCH, and a custom font whose bytes changed is DOCUMENT_DEPENDENCY_CHANGED, before
    anything is drawn. It is an export tool on every surface: registration, tools RPC, Jelly (ask), permissions and
    docs/tool-parity.md.
  • Immutable generations: a document call's files are staged whole and published as one folder
    <outDir>/<name>-<digest>/ named by its file manifest; an identical existing folder is verified and reused, a
    different one is refused, and a failure publishes nothing.
  • Recipe layout: width and height are the outer canvas, exact in SVG and in PNG pixels × scale. Five targets
    (inline 720 × 420 responsive, analysis and report 900 × 540, presentation 1280 × 720 with 18 px labels,
    paper 1000 × 650). A pure three-candidate planner, shared with the HTML page, wraps or turns labels, moves the
    legend and thins ticks, and never drops data or shrinks text below the floor: LAYOUT_UNSATISFIABLE lists the
    conflicts instead. Engine documents keep native layout (LAYOUT_UNSUPPORTED otherwise).
  • Interaction presets in HTML: tooltip (with a keyboard-reachable values table), legend: "highlight",
    zoom: "x" (temporal line and area) and brush: "interval" (scatter and bubble), with the documented combinations,
    accessible Clear/Reset controls, and responsive re-planning at the container's width. An unsupported preset or
    combination is INTERACTION_UNSUPPORTED; an explicit format list without html for an explicit interaction is
    INTERACTION_FORMAT_MISMATCH.
  • Typed appearance: appearance.overrides and charts_theme_save's theme are strict projections of the
    canonical theme tokens (an unknown token is refused at its path). Recipe charts get a stable colour domain by typed
    category identity (1 and "1" differ), and categoryColors pins colours by category.
  • Interactive HTML status: <html data-chart-status> is initializing, ready or failed; the live chart starts
    off-screen after the embedded fonts load and replaces the static SVG only once it started. A failure keeps the
    static chart with a visible notice and an HTML_RUNTIME_FAILED diagnostic.
  • Discovery from the registry: charts_capabilities reports document versions, the recipe contracts, the layout
    profiles and the interaction presets; charts_catalogue marks the recipe types and returns each one's contract and
    exact charts_quick document calls; charts_recommend adds a document draft on the caller's own columns, with an
    explicit medium as its layout target, and withholds it with a warning when the aggregate would have to be guessed.
  • SIZE_OVERRIDE_IGNORED: a raw spec's own width or height beats the tool's, as before, and now says so, naming
    both values and the path.
  • New codes: INPUT_CONFLICT, DOCUMENT_INVALID, DOCUMENT_VERSION_UNSUPPORTED, DOCUMENT_REVISION_MISMATCH,
    DOCUMENT_DEPENDENCY_CHANGED, ARTIFACT_INVALID, AGGREGATION_REQUIRED, POSITION_MISSING, LAYOUT_UNSUPPORTED,
    LAYOUT_UNSATISFIABLE, INTERACTION_UNSUPPORTED, INTERACTION_FORMAT_MISMATCH, VALUE_MISSING,
    CATEGORY_COLOR_UNUSED, SIZE_OVERRIDE_IGNORED, ECHARTS_COMPONENT_UNSUPPORTED, ECHARTS_MARKUP_REFUSED,
    HTML_RUNTIME_FAILED, OUTPUT_WRITE_FAILED. The README's and docs/configuration.md's tables list them.
  • A browser check stage: playwright-core's headless Chromium (pinned in the lockfile) opens pages made by the
    built plugin, under their CSP, with violation, console and request listeners, and exercises every advertised
    interaction. A missing browser fails the stage.
  • docs/documents.md; the cookbook skill now leads with a generated recipe-document section, and
    test/generated.test.ts fails when the cookbook or the recipe table in docs/documents.md is stale.

Fixed

  • Catalogue examples that could not be read. The funnel's labels sat inside segments narrower than the label, some
    at under 4.5:1 contrast, and printed 10000: they now sit outside the segments with grouped counts (10,000). The
    waterfall hid four of its six step names and laid two change labels over their bars: it is wider, names every step
    and puts each change above its bar, with the total labelled. The radial chart had no month labels or legend: each
    wedge now names its month and value, beside a titled colour legend. The world choropleth drew only the countries
    with data: every country is now drawn, those without data in a no-data fill with its own legend entry. Smaller
    fixes: human axis and legend titles (lollipop, dumbbell, brushable scatter, line with band), padded scales (dumbbell,
    dot plot), a dumbbell row with two distinct points, 0% rather than +0% (diverging bar), year labels (connected
    scatter), no gridlines through the end labels (slope), and labelled ends on the calendar heatmap's legend. These
    change the examples only, not how any chart type renders a call.
  • Vega and Vega-Lite HTML did not start in a browser. Vega's default expression evaluator builds functions from
    strings, which the page's CSP (no unsafe-eval) refuses. Pages now parse with {ast: true} and run with
    vega-interpreter 2.3.2; the network-denying loader stays.
  • charts_catalogue's example call left out the example's width, height and locale (the calendar heatmap is
    820 × 220). One function now builds the exact tested call for the catalogue, the cookbook, the gallery, the goldens
    and the evals.
  • The compiler's fit and autosize warnings were filtered out; they now reach the result as VEGA_LITE_WARNING.
  • ECharts options that used dataZoom, brush, toolbox, timeline, matrix or thumbnail were drawn without
    them; they are refused with ECHARTS_COMPONENT_UNSUPPORTED at their path. One module table feeds the server and
    browser runtimes and the capability report.
  • Partial output: every requested file and the preview are now made before anything is written, an invalid PNG
    scale is a finding up front, and legacy flat files are staged and moved into place with a best-effort rollback
    (OUTPUT_WRITE_FAILED names any file it could not restore). charts_validate creates no folder.
  • Custom fonts in exports: a theme's own .ttf or .otf is embedded in HTML and embedded-font SVG with its own
    data URI and format(), from the same approved resource list as metrics and the PNG.
  • A label containing markup (<img onerror=…>) in a drawn SVG is data, not a refused event handler.
  • Layout fitting is monotonic in size: a recipe chart that fits at one size fits at every larger one. Axes keep
    room for every label (Vega's default maxExtent had capped it), turned labels' reach is counted, a refusal names
    sizes that draw and suggests horizontal_bar only where it fits, and a plot its guides leave small is reported as
    an adjustment at /layout.
  • An empty recipe dataset is DATA_EMPTY at /document/chart/data, and charts_validate reports it as
    valid: false.
  • Recipe charts from the gallery review. A time axis takes one calendar unit and one format from the data's span
    (months as Jan…Dec, the year only when the span crosses one), ticks on calendar boundaries and keeps a gap between
    labels; ISO date categories (as in stacked_bar) are written as dates. A bubble's size key is drawn in the theme's
    muted text colour, so it shows on dark. A box plot keeps the layout plan's signals and no longer warns. A pie or donut
    lists its legend in slice order. The dark theme's sequential ramp is the light theme's blue family, turned round. A
    layout refusal first offers the same-family recipe that fits the size asked, names only sizes that draw, and counts
    a bubble's size key.

Changed

  • CONTRACT_VERSION is 1.1.0.
  • The cookbook and the charts skill describe the document workflow first (recipe, typed document, inspect, update)
    and the raw spec as the advanced path.

Known limits

  • No PDF output, and no Plotly or Mermaid input. docs/status.md says what does not work and why, and charts_capabilities reports what this build supports.
  • Bundled fonts cover Latin, Greek and Cyrillic. A label beyond them gets FONT_GLYPH_MISSING; the fix is a font file with theme.font.files.
  • Built-in themes are neutral. Brand themes are not in the plugin. Save one with charts_theme_save, or set it in the plugin's options, and use it by name.
  • Nothing is loaded from the network. A remote data file or image is not fetched.
  • Recipes cover the 14 standard types. The other 39 catalogue types are raw specs; an engine document keeps its
    native layout (no outer-size fitting or responsive reflow) and its own interaction syntax.
  • Four interaction presets. Tooltip, legend highlight, temporal x zoom and scatter/bubble brush, in the documented
    combinations; no series hiding, no ECharts zoom or brush, and SVG/PNG always show the initial view.
  • PNG and HTML need the packaged runtime. A missing runtime is reported as PNG_UNAVAILABLE or HTML_UNAVAILABLE; reinstalling the plugin restores it.
  • Some catalogue examples and the light ramp have rough edges. The candlestick example's date labels, close-set
    ticks in the histogram and binned heatmap examples, and treemap labels cut short in small cells; the light theme's
    sequential ramp starts near white, so the lowest values in a light heatmap or choropleth sit close to the canvas.
  • Package size. The package is about 8 MB unpacked, and dist/index.js is 2.3 MB: Vega, ECharts and the PNG rasteriser are bundled, so a render needs no network.
  • Host range. OpenCode >=2.2.3 <2.3.0, tested on 2.2.3, 2.2.4, 2.2.5 and 2.2.6.
  • Updates are not automatic for a Git install, and opencode plugin update and opencode plugin check do not work on one: to move to a newer release, remove the old entry and add the new tag.