ggaction 0.0.22 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +81 -89
  3. package/knowledge/action-card.schema.json +1 -1
  4. package/knowledge/action-cards.json +1 -1
  5. package/knowledge/intent-taxonomy.json +1 -1
  6. package/knowledge/mcp-resources.json +1 -1
  7. package/package.json +6 -3
  8. package/src/actions/charts/interval-regression.js +2 -2
  9. package/src/actions/data/edit.js +1 -1
  10. package/src/actions/data/timeUnit.js +1 -1
  11. package/src/actions/facets/actions.js +1 -1
  12. package/src/actions/guides/legends/categorical/components.js +1 -4
  13. package/src/actions/regression/create.js +6 -1
  14. package/src/actions/regression/edit.js +10 -1
  15. package/src/core/compositionState.js +5 -3
  16. package/src/core/facetAxisPolicy.js +30 -0
  17. package/src/grammar/curveCommands.js +35 -2
  18. package/src/grammar/datasetSchema.js +1 -1
  19. package/src/grammar/facetHeaders.js +1 -1
  20. package/src/grammar/facets/guides.js +7 -5
  21. package/src/grammar/regression/parameters.js +7 -0
  22. package/src/grammar/timeUnit.js +9 -3
  23. package/src/inspectionDescriptors.js +1 -1
  24. package/src/layout/facets.js +1 -1
  25. package/src/layout/guideCollisions.js +9 -3
  26. package/src/materialization/facetContentBounds.js +96 -0
  27. package/src/materialization/facetGuides/layout.js +1 -1
  28. package/src/materialization/facetGuides/placement.js +16 -0
  29. package/src/materialization/facetHeaders.js +1 -1
  30. package/src/materialization/facets.js +1 -1
  31. package/src/materialization/graphicHierarchy.js +25 -1
  32. package/src/persistence/validation.js +6 -0
  33. package/src/version.js +1 -1
  34. package/types/program.d.ts +17 -11
package/CHANGELOG.md CHANGED
@@ -4,6 +4,23 @@ All notable changes to `ggaction` are recorded in this file.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## [0.0.23] - 2026-10-23
8
+
9
+ - Add independent full-content facet packing, view-aware headers and per-channel Cartesian axis policies with unclipped shared footer axes.
10
+ - Avoid false title/legend collisions from floating-point roundoff at touching edges.
11
+
12
+ - Add opt-in `placement: "plot-last"` for regression fits and bands, preserving source attachment by default and retaining placement through edits and restoration.
13
+
14
+ - Add explicit `monotone-steffen` interpolation for lines, areas and interval boundaries while preserving existing monotone output.
15
+
16
+ - Preserve null or absent calendar inputs as null buckets with opt-in `missing: "null"`, including immutable edits and saved programs.
17
+ - Preserve locally moved legend title alignment and reserve four-edge facet parent title lanes.
18
+ - Strengthen test oracles, execution receipts, consumer qualification, source coverage, browser evidence and bounded CI runners.
19
+
20
+ - Correct documentation examples, recovery ordering, conditional defaults, data-refresh guidance, and action-card prerequisites; execute additional examples and pin contextual exceptions.
21
+ - Publish the complete declaration dependency graph, all runtime entry references, and selective LLM page/action/type artifacts with shared identity and hashes.
22
+ - Improve task search, navigation affordances, source editing links, and first-run documentation; replace the README animation with the paper's Nightingale rose sequence.
23
+
7
24
  ## [0.0.22] - 2026-10-23
8
25
 
9
26
  - Add opt-in plot clipping to supported Cartesian mark layers, with native/SVG/PNG/PDF parity and immutable owner replay.
package/README.md CHANGED
@@ -9,77 +9,10 @@ Most visualization grammars describe a finished chart. **ggaction** represents c
9
9
  Build, inspect, select, and revise charts one meaningful action at a time.
10
10
 
11
11
  <p align="left">
12
- <img src="./docs/assets/images/readme-authoring-sequence.gif" width="960" height="540" loading="eager" alt="A ggaction program progressively creates a scatterplot, adds grouped regression fits and confidence bands, highlights the Japan group across chart layers, and finishes with an R-squared annotation.">
12
+ <img src="./docs/assets/images/readme-authoring-sequence.gif" width="960" height="540" loading="eager" alt="The paper Nightingale rose plot is built progressively, then its radial mapping, cause colors, sector spacing, title, and palette are revised.">
13
13
  </p>
14
14
 
15
- Every frame is rendered from an immutable `ChartProgram`. The final R² label is a traceable action built from public extension primitives.
16
-
17
- ## A grammar of graphical action
18
-
19
- An action expresses a design operation on a chart element. In
20
- `editLineMark({ strokeWidth: 4 })`, `edit` is the operation, `LineMark` names
21
- the target concept, and the option supplies the design choice.
22
-
23
- The grammar has two units: **graphical actions** and **chart programs**.
24
- A program composes action calls in authoring order and retains their resulting
25
- immutable state. Authors read a linear sequence of decisions; an action may
26
- delegate to smaller actions recorded in its nested execution trace.
27
-
28
- The following fragment assumes `cars` is an array of row objects:
29
-
30
- ```javascript
31
- import { chart } from "ggaction";
32
-
33
- const program = chart()
34
- .createCanvas({
35
- width: 760,
36
- height: 480,
37
- margin: { top: 40, right: 190, bottom: 70, left: 80 }
38
- })
39
- .createData({ values: cars })
40
- .createScatterPlot({
41
- id: "points",
42
- x: "Displacement",
43
- y: "Acceleration",
44
- color: "Origin",
45
- guides: false
46
- })
47
- .createRegression()
48
- .createGuides();
49
- ```
50
-
51
- Here `createRegression()` infers groups from the point layer, uses a linear
52
- model, and includes a 95% mean-response interval band. The right margin reserves
53
- space for the resulting legend. The [regression recipe](https://ggaction.github.io/ggaction/recipes/regression-scatterplot/)
54
- provides data and rendering setup; [regression options](https://ggaction.github.io/ggaction/api/regression/)
55
- control grouping, model, interval, and whether a band is drawn.
56
-
57
- ## Why actions?
58
-
59
- - **Progressive** — build and revise a chart one meaningful operation at a time.
60
- - **Traceable** — retain high-level actions and the wrapped actions they invoke.
61
- - **Materialized** — actions create concrete backend-neutral graphics; rendering does not perform hidden semantic compilation.
62
-
63
- ## MCP server for LLM
64
-
65
- ggaction includes a local, read-only MCP server that gives coding assistants
66
- current action names, syntax-valid call templates, explicit placeholders, and
67
- task-specific authoring steps
68
- without loading the complete documentation.
69
-
70
- <p align="left">
71
- <img src="./docs/assets/images/readme-mcp-benefits.svg" width="960" loading="lazy" alt="Across 576 fixed task runs, MCP with bounded fallback improved strict success and reduced tokens and model calls compared with public-documentation browsing for Terra, Luna, and Nano.">
72
- </p>
73
-
74
- Across a fixed 576-run evaluation, MCP-first authoring with bounded fallback
75
- improved strict task success while using fewer tokens and model calls for all
76
- three model sizes. The server runs locally over stdio and does not execute chart
77
- code, access arbitrary files, make network requests, require an account, or
78
- collect telemetry.
79
-
80
- [Set up the local MCP server](https://ggaction.github.io/ggaction/mcp/) ·
81
- [Inspect the benchmark record](./benchmarks/llm-authoring-v1/) ·
82
- [Read the complete evaluation report](./agent_docs/impl/roadmap5.4/phase6/ATTEMPT11.md)
15
+ Every frame is rendered from an immutable `ChartProgram`. This is the paper’s Nightingale rose-plot authoring sequence: create the chart, encode mortality and cause, adjust sector spacing, add the title, and change the palette.
83
16
 
84
17
  ## Quick start
85
18
 
@@ -177,21 +110,79 @@ children. Import from
177
110
  coordinates, or statistical layers. See the
178
111
  [Basic Charts API](https://ggaction.github.io/ggaction/api/basic-charts/).
179
112
 
180
- Use `createParallelCoordinates({ dimensions })` to connect each source row
181
- across ordered, dimension-local scales and axes. See the
182
- [Parallel Coordinates API](https://ggaction.github.io/ggaction/api/parallel-coordinates/)
183
- or the [runnable Cars example](./examples/cars-parallel-coordinates/).
184
-
185
- For an advanced layered example, follow the [regression recipe](https://ggaction.github.io/ggaction/recipes/regression-scatterplot/)
186
- or open the [runnable regression example](./examples/cars-regression-scatterplot/).
187
- To compare category distributions with density-filled strips, read the
188
- [gradient-plot guide](https://ggaction.github.io/ggaction/api/gradient-plots/)
189
- or open the [runnable example](./examples/cars-gradient-plot/).
190
- For symmetric or split density shapes centered on categories, use the
191
- [violin-plot API](https://ggaction.github.io/ggaction/api/violin-plots/) or the
192
- [runnable Cars example](./examples/cars-acceleration-violins/).
193
- For compact signed time-series bands, use `encodeHorizon` on an area mark and
194
- open the [runnable Gapminder example](./examples/gapminder-horizon/).
113
+ Explore [parallel coordinates](https://ggaction.github.io/ggaction/api/parallel-coordinates/),
114
+ [gradient plots](https://ggaction.github.io/ggaction/api/gradient-plots/),
115
+ [violin plots](https://ggaction.github.io/ggaction/api/violin-plots/), and
116
+ [Horizon charts](./examples/gapminder-horizon/) in the [runnable examples](./examples/README.md).
117
+
118
+ ## A grammar of graphical action
119
+
120
+ An action expresses a design operation on a chart element. In
121
+ `editLineMark({ strokeWidth: 4 })`, `edit` is the operation, `LineMark` names
122
+ the target concept, and the option supplies the design choice.
123
+
124
+ The grammar has two units: **graphical actions** and **chart programs**.
125
+ A program composes action calls in authoring order and retains their resulting
126
+ immutable state. Authors read a linear sequence of decisions; an action may
127
+ delegate to smaller actions recorded in its nested execution trace.
128
+
129
+ The following fragment assumes `cars` is an array of row objects:
130
+
131
+ ```javascript
132
+ import { chart } from "ggaction";
133
+
134
+ const program = chart()
135
+ .createCanvas({
136
+ width: 760,
137
+ height: 480,
138
+ margin: { top: 40, right: 190, bottom: 70, left: 80 }
139
+ })
140
+ .createData({ values: cars })
141
+ .createScatterPlot({
142
+ id: "points",
143
+ x: "Displacement",
144
+ y: "Acceleration",
145
+ color: "Origin",
146
+ guides: false
147
+ })
148
+ .createRegression()
149
+ .createGuides();
150
+ ```
151
+
152
+ Here `createRegression()` infers groups from the point layer, uses a linear
153
+ model, and includes a 95% mean-response interval band. The right margin reserves
154
+ space for the resulting legend. The [regression recipe](https://ggaction.github.io/ggaction/recipes/regression-scatterplot/)
155
+ provides data and rendering setup ([source](./examples/cars-regression-scatterplot/)); [regression options](https://ggaction.github.io/ggaction/api/regression/)
156
+ control grouping, model, interval, and whether a band is drawn.
157
+
158
+ ## Why actions?
159
+
160
+ - **Progressive** — build and revise a chart one meaningful operation at a time.
161
+ - **Traceable** — retain high-level actions and the wrapped actions they invoke.
162
+ - **Materialized** — actions create concrete backend-neutral graphics; rendering does not perform hidden semantic compilation.
163
+
164
+ ## MCP server for LLM
165
+
166
+ ggaction includes a local, read-only MCP server that gives coding assistants
167
+ current action names, syntax-valid call templates, explicit placeholders, and
168
+ task-specific authoring steps
169
+ without loading the complete documentation.
170
+
171
+ <p align="left">
172
+ <img src="./docs/assets/images/readme-mcp-benefits.svg" width="960" loading="lazy" alt="Across 576 fixed task runs, MCP with bounded fallback improved strict success and reduced tokens and model calls compared with public-documentation browsing for Terra, Luna, and Nano.">
173
+ </p>
174
+
175
+ In the fixed 576-run evaluation completed on 2026-08-10 (24 tasks × 2 repetitions ×
176
+ `gpt-5.6-terra`, `gpt-5.6-luna`, and `gpt-5.4-nano` × 4 conditions;
177
+ product candidate `4e211ba418cd437d7c66c4fb986fcc714cf579ea`), MCP-first authoring with bounded fallback
178
+ improved strict task success while using fewer tokens and model calls for all
179
+ three model sizes. The server runs locally over stdio and does not execute chart
180
+ code, access arbitrary files, make network requests, require an account, or
181
+ collect telemetry.
182
+
183
+ [Set up the local MCP server](https://ggaction.github.io/ggaction/mcp/) ·
184
+ [Inspect the benchmark record](./benchmarks/llm-authoring-v1/) ·
185
+ [Read the complete evaluation report](./agent_docs/impl/roadmap5.4/phase6/ATTEMPT11.md)
195
186
 
196
187
  ## What it supports
197
188
 
@@ -227,9 +218,6 @@ All module entries include TypeScript declarations. The default, basic,
227
218
  extension, diagnostics, accessibility, and SVG entries are browser-safe; the PNG and PDF adapters are
228
219
  Node-only.
229
220
 
230
- The installed package also includes the Node-only `ggaction-mcp` executable. It
231
- provides one local, read-only chart-authoring search tool and stays outside every
232
- browser entry. See the [local MCP guide](https://ggaction.github.io/ggaction/mcp/).
233
221
 
234
222
  ## Documentation
235
223
 
@@ -249,7 +237,7 @@ the extra discussion required before public API or architecture changes.
249
237
 
250
238
  ## Status and development
251
239
 
252
- > **Status:** `0.0.22` is the current experimental public release. APIs may change before `1.0.0`; changes are recorded in the [changelog](./CHANGELOG.md).
240
+ > **Status:** `0.0.23` is the current experimental public release. APIs may change before `1.0.0`; changes are recorded in the [changelog](./CHANGELOG.md).
253
241
 
254
242
  ```bash
255
243
  npm install
@@ -263,6 +251,9 @@ The renderer development suite also needs Poppler's `pdftoppm` on `PATH` for
263
251
  independent PDF pixel checks. The CI and protected release jobs install
264
252
  `poppler-utils` explicitly; this is not a runtime package dependency.
265
253
 
254
+
255
+ For extension authors, the installed package includes `node_modules/ggaction/knowledge/extension-authoring.md`. Read that file alongside the installed declarations; it is a guide file, not an importable package entry.
256
+
266
257
  ## Related Links
267
258
 
268
259
  - Action-trace demo: [Link](https://ggactionbot.github.io/action-trace-demo/)
@@ -270,7 +261,8 @@ independent PDF pixel checks. The CI and protected release jobs install
270
261
  ### Prepare a release
271
262
 
272
263
  Record changes under `Unreleased` in `CHANGELOG.md` and commit the reviewed work.
273
- Run `npm run release:prepare -- 0.0.16 --dry-run` to preview version updates.
264
+ Set `NEXT_VERSION` to the agreed next release version (at least the current package version).
265
+ Run `npm run release:prepare -- "$NEXT_VERSION" --dry-run` to preview version updates.
274
266
  Omit `--dry-run` to update versions, promote notes, and generate the release
275
267
  contract, documentation, and local notes. Review the Git diff. After committing
276
268
  runtime changes, rerun the command to refresh source provenance; existing notes
@@ -1 +1 @@
1
- {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://ggaction.github.io/ggaction/schemas/action-card.schema.json","title":"ggaction compact action card","type":"object","additionalProperties":false,"required":["schemaVersion","name","layer","domain","summary","signature","intents","lifecycle","resources","authoringRoles","wraps","editableVia","supports","units","inference","completionRequirements","options","callPatterns","snippet","errors","route"],"properties":{"schemaVersion":{"const":3},"name":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9]*$"},"layer":{"enum":["user-facing","advanced","primitive"]},"domain":{"type":"string","minLength":1},"summary":{"type":"string","minLength":20,"maxLength":420},"signature":{"type":"string","minLength":10},"intents":{"type":"array","minItems":3,"maxItems":7,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":80}},"lifecycle":{"type":"string","minLength":3},"resources":{"type":"object","additionalProperties":false,"required":["prerequisites","owns","idOptions"],"properties":{"prerequisites":{"type":"array","maxItems":4,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":100}},"owns":{"type":"array","maxItems":3,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":80}},"idOptions":{"type":"array","maxItems":10,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":30}}}},"authoringRoles":{"type":"array","minItems":1,"maxItems":5,"uniqueItems":true,"items":{"enum":["H0","H1","H2","H3","H4"]}},"wraps":{"type":"array","maxItems":20,"uniqueItems":true,"items":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9]*$"}},"editableVia":{"type":"array","maxItems":20,"uniqueItems":true,"items":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9]*$"}},"supports":{"type":"object","additionalProperties":false,"required":["entryPoints"],"properties":{"entryPoints":{"type":"array","minItems":1,"maxItems":2,"uniqueItems":true,"items":{"enum":["default","basic"]}}}},"units":{"type":"array","maxItems":16,"items":{"type":"object","additionalProperties":false,"required":["path","unit"],"properties":{"path":{"type":"string","minLength":1,"maxLength":80},"unit":{"enum":["logical-pixel","degree","angle","ratio","probability","count","calendar-unit","temporal-input","data-value","band-fraction"]}}}},"inference":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["input","strategy"],"properties":{"input":{"type":"string","minLength":1,"maxLength":80},"strategy":{"enum":["explicit","explicit-or-current","explicit-current-unique-or-error","documented-auto","documented-default"]}}}},"completionRequirements":{"type":"object","additionalProperties":false,"required":["state","requires","allowsEmpty"],"properties":{"state":{"enum":["complete","deferred","contextual","not-applicable"]},"requires":{"type":"array","maxItems":4,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":100}},"allowsEmpty":{"type":"boolean"}}},"options":{"type":"array","maxItems":40,"items":{"type":"object","additionalProperties":false,"required":["name","required","type"],"properties":{"name":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9]*$"},"required":{"type":"boolean"},"type":{"type":"string","minLength":1,"maxLength":500}}}},"callPatterns":{"type":"array","minItems":1,"maxItems":3,"uniqueItems":true,"items":{"type":"string","minLength":3,"maxLength":260}},"snippet":{"type":"string","minLength":3,"maxLength":700},"errors":{"type":"array","maxItems":2,"items":{"type":"object","additionalProperties":false,"required":["error","fix"],"properties":{"error":{"type":"string","minLength":5,"maxLength":220},"fix":{"type":"string","minLength":5,"maxLength":220}}}},"route":{"type":"string","pattern":"^/reference/"}}}
1
+ {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://ggaction.github.io/ggaction/schemas/action-card.schema.json","title":"ggaction compact action card","type":"object","additionalProperties":false,"required":["schemaVersion","name","layer","domain","summary","signature","intents","lifecycle","resources","authoringRoles","wraps","editableVia","supports","units","inference","completionRequirements","options","callPatterns","snippet","errors","route"],"properties":{"schemaVersion":{"const":3},"name":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9]*$"},"layer":{"enum":["user-facing","advanced","primitive"]},"domain":{"type":"string","minLength":1},"summary":{"type":"string","minLength":20,"maxLength":420},"signature":{"type":"string","minLength":10},"intents":{"type":"array","minItems":3,"maxItems":7,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":80}},"lifecycle":{"type":"string","minLength":3},"resources":{"type":"object","additionalProperties":false,"required":["prerequisites","owns","idOptions"],"properties":{"prerequisites":{"type":"array","maxItems":4,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":100}},"owns":{"type":"array","maxItems":3,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":80}},"idOptions":{"type":"array","maxItems":10,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":30}}}},"authoringRoles":{"type":"array","minItems":1,"maxItems":5,"uniqueItems":true,"items":{"enum":["H0","H1","H2","H3","H4"]}},"wraps":{"type":"array","maxItems":20,"uniqueItems":true,"items":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9]*$"}},"editableVia":{"type":"array","maxItems":20,"uniqueItems":true,"items":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9]*$"}},"supports":{"type":"object","additionalProperties":false,"required":["entryPoints"],"properties":{"entryPoints":{"type":"array","minItems":1,"maxItems":2,"uniqueItems":true,"items":{"enum":["default","basic"]}}}},"units":{"type":"array","maxItems":16,"items":{"type":"object","additionalProperties":false,"required":["path","unit"],"properties":{"path":{"type":"string","minLength":1,"maxLength":80},"unit":{"enum":["logical-pixel","degree","angle","ratio","probability","count","calendar-unit","temporal-input","data-value","band-fraction"]}}}},"inference":{"type":"array","maxItems":20,"items":{"type":"object","additionalProperties":false,"required":["input","strategy"],"properties":{"input":{"type":"string","minLength":1,"maxLength":80},"strategy":{"enum":["explicit","explicit-or-current","explicit-current-unique-or-error","documented-auto","documented-default"]}}}},"completionRequirements":{"type":"object","additionalProperties":false,"required":["state","requires","allowsEmpty"],"properties":{"state":{"enum":["complete","deferred","contextual","not-applicable"]},"requires":{"type":"array","maxItems":4,"uniqueItems":true,"items":{"type":"string","minLength":2,"maxLength":100}},"allowsEmpty":{"type":"boolean","description":"Whether this action permits an empty result. This does not promise that subsequent actions can infer domains from empty data or that geometry is complete."}}},"options":{"type":"array","maxItems":40,"items":{"type":"object","additionalProperties":false,"required":["name","required","type"],"properties":{"name":{"type":"string","pattern":"^[A-Za-z][A-Za-z0-9]*$"},"required":{"type":"boolean"},"type":{"type":"string","minLength":1,"maxLength":500}}}},"callPatterns":{"type":"array","minItems":1,"maxItems":3,"uniqueItems":true,"items":{"type":"string","minLength":3,"maxLength":260}},"snippet":{"type":"string","minLength":3,"maxLength":700},"errors":{"type":"array","maxItems":2,"items":{"type":"object","additionalProperties":false,"required":["error","fix"],"properties":{"error":{"type":"string","minLength":5,"maxLength":220},"fix":{"type":"string","minLength":5,"maxLength":220}}}},"route":{"type":"string","pattern":"^/reference/"}}}