@taylorwong/ichartjs 2.0.7 → 2.0.9

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.9 - 2026-09-20
4
+
5
+ - Fixed Radar normalization so normalized Specs validate and render without unsupported Cartesian encodings.
6
+ - Added explicit Pie diagnostics for dropped negative values and empty totals, with deduplicated runtime health reporting.
7
+ - Made Gauge a true single-value contract, removed default-option false positives for non-Cartesian charts, and clarified top-level Diagram structure errors.
8
+ - Updated minimal recipes and bilingual Agent/Skill guidance for chart-specific channels and ESM JSON recipe imports.
9
+
10
+ ## 2.0.8 - 2026-09-20
11
+
12
+ - Hardened chart-specific encoding and field validation, including explicit Swimlane requirements and actionable diagnostics for Agents.
13
+ - Added Gauge domain contracts and clamping diagnostics, Heatmap label rendering, locale-aware temporal formatting, semantic Pie labels, and runtime health checkpoints.
14
+ - Added intent fallback suggestions, locale capability metadata, a complete minimal Spec catalog, and synchronized Agent guidance and capability manifests.
15
+
3
16
  ## 2.0.7 - 2026-09-20
4
17
 
5
18
  - Added Architecture and Mindmap chart types with shared diagram contracts, layers, boundaries, parent-child validation, deterministic tree/radial layouts, and Agent-readable schemas and capabilities.
package/README.md CHANGED
@@ -40,7 +40,7 @@ getCapabilities
40
40
  npm install @taylorwong/ichartjs@^2
41
41
  ```
42
42
 
43
- As a fallback for environments without npm access, install directly from GitHub: `npm install github:wanghetommy/ichartjs#v2.0.7`.
43
+ As a fallback for environments without npm access, install directly from GitHub: `npm install github:wanghetommy/ichartjs#v2.0.9`.
44
44
 
45
45
  ### Optional Agent Skill
46
46
 
@@ -62,7 +62,7 @@ For a non-interactive global Codex installation:
62
62
  npx skills add wanghetommy/ichartjs --skill ichartjs --agent codex --global --yes
63
63
  ```
64
64
 
65
- For a release-pinned installation, use `npx skills add https://github.com/wanghetommy/ichartjs/tree/v2.0.7/skills/ichartjs --agent codex --global --yes`. WorkBuddy users can import the same tagged `skills/ichartjs` URL through the host's Skill interface; do not assume a `--agent workbuddy` adapter unless the installed CLI declares it. Package consumers can still copy `node_modules/@taylorwong/ichartjs/skills/ichartjs` as a manual fallback. After installation, invoke `$ichartjs` when named Skill invocation is supported, or select `ichartjs` in the host UI.
65
+ For a release-pinned installation, use `npx skills add https://github.com/wanghetommy/ichartjs/tree/v2.0.9/skills/ichartjs --agent codex --global --yes`. WorkBuddy users can import the same tagged `skills/ichartjs` URL through the host's Skill interface; do not assume a `--agent workbuddy` adapter unless the installed CLI declares it. Package consumers can still copy `node_modules/@taylorwong/ichartjs/skills/ichartjs` as a manual fallback. After installation, invoke `$ichartjs` when named Skill invocation is supported, or select `ichartjs` in the host UI.
66
66
 
67
67
  ### Agent workflow
68
68
 
@@ -0,0 +1,25 @@
1
+ {
2
+ "version": "2.0",
3
+ "name": "minimal-specs",
4
+ "description": "Small validated starting Specs for every public iChart.js chart type.",
5
+ "examples": {
6
+ "line": { "type": "line", "renderer": "svg", "data": [{ "id": "jan", "month": "Jan", "value": 12 }], "encoding": { "x": { "field": "month" }, "y": { "field": "value" } } },
7
+ "area": { "type": "area", "renderer": "svg", "data": [{ "id": "jan", "month": "Jan", "value": 12 }], "encoding": { "x": { "field": "month" }, "y": { "field": "value" } } },
8
+ "bar": { "type": "bar", "renderer": "svg", "data": [{ "id": "a", "name": "A", "value": 12 }], "encoding": { "x": { "field": "name" }, "y": { "field": "value" } } },
9
+ "column": { "type": "column", "renderer": "svg", "data": [{ "id": "a", "name": "A", "value": 12 }], "encoding": { "x": { "field": "name" }, "y": { "field": "value" } } },
10
+ "pie": { "type": "pie", "renderer": "svg", "data": [{ "id": "a", "name": "A", "value": 12 }] },
11
+ "scatter": { "type": "scatter", "renderer": "svg", "data": [{ "id": "a", "x": 1, "y": 12 }], "encoding": { "x": { "field": "x" }, "y": { "field": "y" } } },
12
+ "funnel": { "type": "funnel", "renderer": "svg", "data": [{ "id": "visit", "name": "Visit", "value": 100 }] },
13
+ "gauge": { "type": "gauge", "renderer": "svg", "domain": [0, 100], "data": [{ "id": "completion", "value": 72 }] },
14
+ "heatmap": { "type": "heatmap", "renderer": "svg", "data": [{ "id": "a", "x": "Mon", "y": "AM", "value": 12 }], "encoding": { "x": { "field": "x" }, "y": { "field": "y" }, "color": { "field": "value" } } },
15
+ "radar": { "type": "radar", "renderer": "svg", "indicators": [{ "name": "Quality", "field": "quality", "min": 0, "max": 100 }, { "name": "Speed", "field": "speed", "min": 0, "max": 100 }, { "name": "Coverage", "field": "coverage", "min": 0, "max": 100 }], "data": [{ "id": "team-a", "quality": 80, "speed": 70, "coverage": 90 }] },
16
+ "gantt": { "type": "gantt", "renderer": "svg", "data": [{ "id": "task-a", "name": "Task A", "start": "2026-09-01", "end": "2026-09-03" }] },
17
+ "timeline": { "type": "timeline", "renderer": "svg", "data": [{ "id": "event-a", "date": "2026-09-01", "title": "Kickoff" }] },
18
+ "milestone": { "type": "milestone", "renderer": "svg", "data": [{ "id": "release", "date": "2026-09-19", "title": "Release" }] },
19
+ "burndown": { "type": "burndown", "renderer": "svg", "data": [{ "id": "day-1", "date": "2026-09-01", "remaining": 10 }, { "id": "day-2", "date": "2026-09-02", "remaining": 0 }] },
20
+ "flow": { "type": "flow", "renderer": "svg", "nodes": [{ "id": "start", "label": "Start" }, { "id": "done", "label": "Done" }], "edges": [{ "id": "start-done", "from": "start", "to": "done" }] },
21
+ "swimlane": { "type": "swimlane", "renderer": "svg", "lanes": [{ "id": "team", "label": "Team" }], "nodes": [{ "id": "task", "label": "Task", "laneId": "team" }], "edges": [] },
22
+ "architecture": { "type": "architecture", "renderer": "svg", "nodes": [{ "id": "api", "label": "API" }, { "id": "db", "label": "Database" }], "edges": [{ "id": "api-db", "from": "api", "to": "db" }] },
23
+ "mindmap": { "type": "mindmap", "renderer": "svg", "nodes": [{ "id": "root", "label": "Goal" }, { "id": "child", "label": "Next step", "parentId": "root" }], "edges": [] }
24
+ }
25
+ }
@@ -26,6 +26,47 @@ Agent usage and development guide for generic data analysis and metric visualiza
26
26
  - Heatmap treats missing values separately from numeric zero through `colorScale.missing`.
27
27
  - Radar should declare `min` and `max` for every indicator; omitted or mixed-unit domains produce warnings.
28
28
 
29
+ ## Configuration Placement
30
+
31
+ `encoding` describes field roles and series semantics. Keep these options at the Spec level:
32
+
33
+ | Concern | Correct location | Applies to |
34
+ | --- | --- | --- |
35
+ | Axis title and format | `xAxis.title/format`, `yAxis.title/format` | Line, Area, Bar, Column, Scatter |
36
+ | Readable numeric domain | `yAxis.nice`, `yAxis.ticks`, `yAxis.domain` | Line, Area, Bar, Column, Scatter |
37
+ | Data labels | `labels.enabled/format` | Charts that declare `labels` in capabilities |
38
+ | Legend | `legend.visible/position` | Multi-series Cartesian, Pie, and Radar |
39
+ | Gauge domain | `domain: [min, max]` | Gauge |
40
+ | Heatmap color domain | `colorScale.domain` | Heatmap |
41
+ | Radar indicator domain | `indicators[].min/max` | Radar |
42
+
43
+ Do not put `title`, `format`, `labels`, or `legend` under `encoding`; `validateSpec()` reports those placements as warnings. Numeric y-axes use readable domains by default (`nice: true`, `ticks: "auto"`). Use `yAxis.domain: [min, max]` for an explicit range, or `yAxis.nice: false` to retain the raw boundary. `xAxis.min/max` and `xAxis.domain` are unsupported for categorical/time layouts and produce a structured warning.
44
+
45
+ ## Encoding Contracts
46
+
47
+ Use only the channels declared for the selected chart: Cartesian charts use `encoding.x` and `encoding.y`; Pie and Funnel use `encoding.category` and `encoding.value`; Gauge uses only `encoding.value`; Heatmap uses `encoding.x`, `encoding.y`, and `encoding.color`; Radar uses `indicators[].field`. `validateSpec()` reports `UNSUPPORTED_ENCODING_CHANNEL` for an unused channel and `MISSING_ENCODING_FIELD` when a referenced field is absent. Gauge additionally requires `domain: [min, max]`; values outside the domain are clamped for the rendered arc and report `VALUE_CLAMPED`. Pie reports `NEGATIVE_VALUE_DROPPED` instead of silently treating negative values as valid shares, and reports `ZERO_TOTAL` for an empty result.
48
+
49
+ The complete set of small starting Specs is available at `@taylorwong/ichartjs/recipes/minimal-specs`. Import the JSON catalog with `with { type: 'json' }`, then select `catalog.examples[type]`.
50
+
51
+ ## Intent Vocabulary
52
+
53
+ Pass an exact value from `getCapabilities().intents` to `planChart()`. Common mappings are:
54
+
55
+ | User need | Registered intent | Primary chart |
56
+ | --- | --- | --- |
57
+ | Trend over time | `trend` or `time-series` | Line |
58
+ | Compare categories | `comparison` | Bar |
59
+ | Rank categories | `ranking` | Bar |
60
+ | Distribution or histogram | `distribution` | Column with `bin` transform |
61
+ | Relationship or correlation | `relationship` or `correlation` | Scatter |
62
+ | Composition | `composition` | Column or Area |
63
+ | Matrix intensity | `matrix` or `correlation-grid` | Heatmap |
64
+ | Profile across measures | `multidimensional` or `profile` | Radar |
65
+
66
+ Natural-language prose such as `trend over time` is not an intent token. Map it to `trend` first. An unknown token returns `UNKNOWN_INTENT` plus a fallback plan; never ignore that warning.
67
+
68
+ Unknown intent plans expose `intentKnown: false`, `fallbackUsed: true`, and deterministic `intentSuggestions`. Use those fields to remap the request or ask for confirmation instead of silently accepting the fallback chart.
69
+
29
70
  ## Agent Workflow
30
71
 
31
72
  1. Call `inspectData(data)` to identify fields and missing values.
@@ -33,6 +74,10 @@ Agent usage and development guide for generic data analysis and metric visualiza
33
74
  3. Create a JSON-serializable Chart Spec.
34
75
  4. Call `validateSpec(spec)` before `createChart(spec)`.
35
76
  5. Inspect the result with `chart.describe()` and `chart.getState()`.
77
+ 6. Add stable string `id` values to rows when lineage checks, linked selection, or later updates matter.
78
+ 7. Check `chart.getState().health.renderable`, `health.status`, and `warnings` before presenting the result. `ready` means no material diagnostic is active; `degraded` means the chart rendered with a material warning; `empty` means it has no meaningful result.
79
+
80
+ `locale` defaults to `en-US` and controls axis, label, tooltip, and export formatting. Set `locale: "zh-CN"` for Chinese output. Input dates should remain ISO-8601 strings; natural-language date parsing is not part of the runtime contract.
36
81
 
37
82
  ## Minimal Spec
38
83
 
@@ -41,7 +86,7 @@ Agent usage and development guide for generic data analysis and metric visualiza
41
86
  type: 'line',
42
87
  renderer: 'svg',
43
88
  container: '#chart',
44
- data: { values: [{ month: 'Jan', sales: 120 }] },
89
+ data: { values: [{ id: 'jan', month: 'Jan', sales: 120 }] },
45
90
  encoding: {
46
91
  x: { field: 'month', type: 'category' },
47
92
  y: { field: 'sales', type: 'quantitative' }
@@ -33,7 +33,7 @@ Install the official Skill with the standard Agent Skills CLI:
33
33
  npx skills add wanghetommy/ichartjs --skill ichartjs
34
34
  ```
35
35
 
36
- For global non-interactive Codex setup, append `--agent codex --global --yes`. To pin the released workflow, install `https://github.com/wanghetommy/ichartjs/tree/v2.0.7/skills/ichartjs`. WorkBuddy can import that tagged directory through its Skill interface; only use a host-specific `--agent` value when the installed CLI declares it.
36
+ For global non-interactive Codex setup, append `--agent codex --global --yes`. To pin the released workflow, install `https://github.com/wanghetommy/ichartjs/tree/v2.0.9/skills/ichartjs`. WorkBuddy can import that tagged directory through its Skill interface; only use a host-specific `--agent` value when the installed CLI declares it.
37
37
 
38
38
  Verify discovery with `npx skills add wanghetommy/ichartjs --list`; the result should include `ichartjs`.
39
39
 
@@ -1,6 +1,6 @@
1
1
  # iChart.js 2.0 Roadmap
2
2
 
3
- > Roadmap baseline: 2026-09-14. Current release status: `v2.0.7` includes the completed Iteration 12 structured-diagram work and follow-up chart/menu fixes. Geographic charts and 3D rendering remain out of scope until explicitly reintroduced.
3
+ > Roadmap baseline: 2026-09-14. Current release status: `v2.0.9` includes the completed Iteration 12 structured-diagram work, follow-up chart/menu fixes, and hardened Agent chart contracts. Geographic charts and 3D rendering remain out of scope until explicitly reintroduced.
4
4
 
5
5
  ## Current Status
6
6
 
@@ -10,7 +10,7 @@ This is the production component path. For one-off files or Agent-led repository
10
10
  npm install @taylorwong/ichartjs@^2
11
11
  ```
12
12
 
13
- For environments without npm registry access, install from GitHub as a fallback: `npm install github:wanghetommy/ichartjs#v2.0.7`.
13
+ For environments without npm registry access, install from GitHub as a fallback: `npm install github:wanghetommy/ichartjs#v2.0.9`.
14
14
 
15
15
  Use the package through a bundler or another environment that resolves npm ESM imports:
16
16
 
@@ -24,6 +24,7 @@ Agent usage and development guide for project planning, delivery tracking, and p
24
24
  - Keep derived values separate from source rows. State and tooltips may expose variance, float, warnings, and assumptions, but transforms must not mutate source data.
25
25
  - Linked filters and linked selection must use stable record IDs, not array positions.
26
26
  - Forecasts, risk scores, and aging buckets are inspectable heuristics. They are not commitments, causal claims, or hidden inference.
27
+ - Project chart date axes are derived from `date`, `start`, and `end` records in the current contract; generic `xAxis.title/format` and `xAxis.min/max` settings do not customize them.
27
28
 
28
29
  ## Agent Workflow
29
30
 
@@ -67,6 +67,12 @@ Call `planChart(rows, { intent, renderer })`. Read the full result rather than o
67
67
 
68
68
  Stop before rendering when `requiredFields` is not empty. Ask for the missing information or choose a supported alternative without fabricating data.
69
69
 
70
+ #### Use registered intents only
71
+
72
+ `intent` is an exact machine token, not a natural-language sentence. Discover the allowlist from `getCapabilities().intents`, then pass values such as `trend`, `time-series`, `comparison`, `ranking`, `distribution`, `relationship`, `matrix`, `multidimensional`, `schedule`, `architecture`, or `mindmap`. Do not pass `trend over time` or `show a sales trend` directly. If an unknown token is passed, `planChart()` returns an `UNKNOWN_INTENT` warning and a safe fallback, which may select the wrong chart if the warning is ignored.
73
+
74
+ If the user gives prose, map it to a registered token before calling `planChart()` and preserve the original prose separately as user intent.
75
+
70
76
  ### 4. Build a JSON-Friendly Spec
71
77
 
72
78
  For a trend or comparison with one dimension and one or more measures:
@@ -97,6 +103,34 @@ const spec = {
97
103
 
98
104
  Use the selected capability and recipes for Pie, Gauge, Heatmap, Radar, project views, and diagrams because their required encodings differ.
99
105
 
106
+ #### Put options at the contract level
107
+
108
+ Keep `encoding` for field roles and series semantics. Put presentation and axis options at the Spec level:
109
+
110
+ | Need | Correct location | Common mistake |
111
+ | --- | --- | --- |
112
+ | Axis title | `xAxis.title`, `yAxis.title` | `encoding.x.title`, `encoding.y.title` |
113
+ | Axis number/date format | `xAxis.format`, `yAxis.format` | `encoding.x.format`, `encoding.y.format` |
114
+ | Data labels | `labels.enabled`, `labels.format` | `encoding.labels` |
115
+ | Legend | `legend.visible` | `encoding.legend` |
116
+ | Theme and palette | `theme.mode`, `theme.preset`, `theme.palette` | series or encoding color guesses |
117
+
118
+ `validateSpec()` reports these misplaced options as structured warnings. Repair them before presenting the chart. A single-series Cartesian chart shows the encoded field name in the legend by default; set `legend: { visible: false }` when that label adds no value.
119
+
120
+ #### Know the domain contract
121
+
122
+ Numeric Cartesian charts use a readable y-axis domain by default: `yAxis.nice` is `true`, and `yAxis.ticks` is `"auto"`. For an explicit range, use `yAxis.domain: [min, max]`; for example, `{ domain: [0, 2000], ticks: 5 }` produces a stable five-label scale. Set `yAxis.nice: false` to retain the raw data boundary. `yAxis.format` only changes display formatting. `chart.getState().axes` and `chart.explain().axes` expose `rawDomain`, resolved `domain`, `ticks`, `step`, and `policy` for Agent self-checks. `yAxis.right` accepts the same controls for a secondary numeric axis. `xAxis.min/max` and `xAxis.domain` remain unsupported because categorical/time x-axis ranges are derived from records. The other supported domain controls are chart-specific: `gauge.domain`, `heatmap.colorScale.domain`, and `radar.indicators[].min/max`. Project chart date ranges are derived from their records in the current version.
123
+
124
+ Chart-specific encoding is strict: Cartesian charts use `x`/`y`, Pie/Funnel use `category`/`value`, Gauge uses `value`, Heatmap uses `x`/`y`/`color`, and Radar uses `indicators[].field`. Missing or unsupported fields are validation errors, not silent fallbacks. Gauge Specs must declare `domain`; inspect `VALUE_CLAMPED` when a value falls outside it. Pie reports `NEGATIVE_VALUE_DROPPED` for signed values and `ZERO_TOTAL` for an empty part-to-whole result. Use the complete minimal catalog at `@taylorwong/ichartjs/recipes/minimal-specs` when starting a new chart:
125
+
126
+ ```js
127
+ import catalog from '@taylorwong/ichartjs/recipes/minimal-specs' with { type: 'json' };
128
+
129
+ const spec = structuredClone(catalog.examples.radar);
130
+ ```
131
+
132
+ For Agent self-checks, `chart.getState().health` and `chart.explain().health` expose `ready`, `degraded`, or `empty`, plus warning, suppressed-label, clamped-value, and rendered-mark metrics. `locale` defaults to `en-US`; use `locale: "zh-CN"` for localized number/date output while keeping input dates in ISO-8601 form.
133
+
100
134
  ### 5. Validate
101
135
 
102
136
  ```js
@@ -177,6 +211,8 @@ Before returning a result, verify:
177
211
  - the branding on/off state is documented so live view and exports stay consistent;
178
212
  - the preview URL or output artifact (JSON/SVG/PNG/JPEG) is provided to the user.
179
213
 
214
+ For deterministic lineage checks and linked updates, give every input row a stable string `id`. Without one, the runtime uses a positional fallback such as `record-0`; that is sufficient for a local render but should not be treated as a durable business identity.
215
+
180
216
  ## Branding (Signature) Defaults
181
217
 
182
218
  - Default `branding: true`: a low-contrast `Powered by iChart.js` signature appears in the bottom-right corner, synchronized across live rendering, PNG/SVG raster export, and JSON state persistence.
@@ -14,14 +14,19 @@ For post-creation visual settings, use `getPreferenceCapabilities(chartType, { l
14
14
 
15
15
  Iteration 8 adds per-chart profiles through `getChartCapability(type)`. Each profile declares required data roles, supported interactions, renderers, feature status, exports, and practical limits. Unsupported behavior must be handled from this profile or from validation diagnostics rather than guessed.
16
16
 
17
- `planChart(data, { intent, renderer })` returns a versioned planning result with a primary chart, alternatives, confidence, reasons, required fields, suggested encodings, assumptions, warnings, unsupported requests, safe next actions, and the selected capability profile. Planning never invents business meaning, units, dates, or missing fields.
17
+ `planChart(data, { intent, renderer })` returns a versioned planning result with a primary chart, alternatives, confidence, reasons, required fields, suggested encodings, assumptions, warnings, unsupported requests, safe next actions, and the selected capability profile. `intent` must be one exact token from `getCapabilities().intents`; natural-language prose must be mapped before planning. An unknown token returns `UNKNOWN_INTENT` and a fallback plan, so Agents must inspect warnings before accepting `primary`. Planning never invents business meaning, units, dates, or missing fields.
18
+
19
+ Unknown intent results also include `intentKnown`, `intentSuggestions`, and `fallbackUsed`. A chart Spec is chart-specific: Cartesian channels are `x`/`y`, Pie/Funnel channels are `category`/`value`, Gauge uses `value`, Heatmap channels are `x`/`y`/`color`, and Radar fields live in `indicators`. `validateSpec()` rejects unsupported channels and missing fields. Gauge requires an explicit `domain` and reports `VALUE_CLAMPED` when the rendered value exceeds it. Pie reports `NEGATIVE_VALUE_DROPPED` for negative input values and `ZERO_TOTAL` when no positive share can render.
18
20
 
19
21
  ## Spec Rules
20
22
 
21
23
  - Specs must be JSON-serializable.
22
24
  - Call `validateSpec()` before rendering.
23
25
  - Chart layout and data semantics are renderer-independent.
24
- - `flow` and `swimlane` use `nodes/edges/lanes`; `architecture` uses `nodes/edges/layers/boundaries`; `mindmap` uses `nodes` with `parentId` and optional `edges`; generic charts use `data.values`.
26
+ - Keep axis titles/formats on `xAxis`/`yAxis`, labels on `labels`, and legend settings on `legend`; misplaced options return structured warnings.
27
+ - Numeric y-axes use readable domains by default (`yAxis.nice: true`, `yAxis.ticks: "auto"`). Use `yAxis.domain: [min, max]` for an explicit range, `yAxis.nice: false` to retain the raw boundary, and `yAxis.right` for a secondary numeric axis. `chart.getState().axes` and `chart.explain().axes` expose the raw domain, resolved domain, ticks, step, and policy for Agent verification. `xAxis.min/max` and `xAxis.domain` remain unsupported for categorical/time layouts. Chart-specific domains remain available through `gauge.domain`, `heatmap.colorScale.domain`, and `radar.indicators[].min/max`.
28
+ - Diagram structure is always top-level: `flow` and `swimlane` use `nodes/edges/lanes`; `architecture` uses `nodes/edges/layers/boundaries`; `mindmap` uses `nodes` with `parentId` and optional `edges`. Do not put these fields under `data`; generic charts use `data.values`.
29
+ - `chart.getState().health` and `chart.explain().health` expose `ready`, `degraded`, or `empty`, with renderability and warning, suppressed-label, clamped-value, and rendered-mark metrics. `locale` defaults to `en-US`; set `locale: "zh-CN"` for output formatting and keep input dates as ISO-8601 strings.
25
30
 
26
31
  ## Renderer
27
32
 
@@ -119,6 +124,8 @@ chart.downloadJSON()
119
124
 
120
125
  Validation results contain separate `errors`, `warnings`, and `normalizations`. Diagnostics use stable codes, JSON-oriented paths, expected values where useful, and actionable suggestions. `chart.explain()` returns encodings, transforms, interactions, assumptions, warnings, stable record lineage, and an accessibility summary.
121
126
 
127
+ For lineage checks and linked updates, provide stable string `id` values on input rows. Without one, the runtime uses deterministic positional IDs such as `record-0`; these are suitable for a local self-check but not for durable business identity.
128
+
122
129
  ## Interaction
123
130
 
124
131
  Common interactions include Tooltip, Hover, Click, Selection, Zoom, Pan, Drag, Touch, and Keyboard; each chart's enabled interactions are controlled by its Spec and capability declaration.
@@ -121,7 +121,7 @@ npx skills add wanghetommy/ichartjs --skill ichartjs --agent codex --global --ye
121
121
  For reproducible installation, pin the released Skill directory:
122
122
 
123
123
  ```bash
124
- npx skills add https://github.com/wanghetommy/ichartjs/tree/v2.0.7/skills/ichartjs \
124
+ npx skills add https://github.com/wanghetommy/ichartjs/tree/v2.0.9/skills/ichartjs \
125
125
  --agent codex --global --yes
126
126
  ```
127
127
 
@@ -26,6 +26,32 @@
26
26
  - Heatmap 通过 `colorScale.missing` 区分缺失值和数值零。
27
27
  - Radar 应为每个指标声明 `min` 和 `max`;缺失域或混合单位会产生告警。
28
28
 
29
+ ## 配置项位置
30
+
31
+ `encoding` 只描述字段角色和 Series 语义。以下配置应放在 Spec 顶层:
32
+
33
+ | 配置 | 正确位置 | 适用范围 |
34
+ | --- | --- | --- |
35
+ | 坐标轴标题和格式 | `xAxis.title/format`、`yAxis.title/format` | Line、Area、Bar、Column、Scatter |
36
+ | 易读数值域 | `yAxis.nice`、`yAxis.ticks`、`yAxis.domain` | Line、Area、Bar、Column、Scatter |
37
+ | 数据标签 | `labels.enabled/format` | 能力清单声明支持 labels 的图表 |
38
+ | 图例 | `legend.visible/position` | 多系列笛卡尔图、Pie、Radar |
39
+ | Gauge 坐标域 | `domain: [min, max]` | Gauge |
40
+ | Heatmap 颜色域 | `colorScale.domain` | Heatmap |
41
+ | Radar 指标域 | `indicators[].min/max` | Radar |
42
+
43
+ 不要把 `title`、`format`、`labels` 或 `legend` 放在 `encoding` 中;`validateSpec()` 会报告结构化警告。数值纵轴默认使用易读域(`nice: true`、`ticks: "auto"`);需要固定范围时使用 `yAxis.domain: [min, max]`,需要保留原始边界时使用 `yAxis.nice: false`。分类/时间横轴的 `min/max` 和 `domain` 不支持。
44
+
45
+ ## Encoding 契约
46
+
47
+ 不同图表只接受对应的数据通道:笛卡尔图表使用 `encoding.x`/`encoding.y`;Pie、Funnel 使用 `encoding.category`/`encoding.value`;Gauge 只使用 `encoding.value`;Heatmap 使用 `encoding.x`/`encoding.y`/`encoding.color`;Radar 使用 `indicators[].field`。字段不存在或通道不支持会成为校验错误,不应静默改名。Gauge 必须提供 `domain: [min, max]`;超出范围时弧形会限制在范围内,并产生 `VALUE_CLAMPED`。Pie 遇到负值会报告 `NEGATIVE_VALUE_DROPPED`,没有正数占比时会报告 `ZERO_TOTAL`。全部图表的最小可执行 Spec 见 `@taylorwong/ichartjs/recipes/minimal-specs`;ESM 中用 `with { type: 'json' }` 导入,并从 `catalog.examples[type]` 取模板。
48
+
49
+ ## 意图注册词
50
+
51
+ 传给 `planChart()` 的 `intent` 必须是 `getCapabilities().intents` 中的精确值,而不是用户原句。比如把“展示销售随时间变化”映射为 `trend`;未知词会返回 `UNKNOWN_INTENT` 和降级方案,不能忽略该警告。
52
+
53
+ 未知词的规划结果还会给出 `intentKnown: false`、`fallbackUsed: true` 和 `intentSuggestions`,应据此重新映射或请求确认。
54
+
29
55
  ## Agent 流程
30
56
 
31
57
  1. 使用 `inspectData(data)` 检查字段和缺失值。
@@ -33,6 +59,10 @@
33
59
  3. 生成 JSON-serializable Chart Spec。
34
60
  4. 先调用 `validateSpec(spec)`,再调用 `createChart(spec)`。
35
61
  5. 使用 `chart.describe()` 和 `chart.getState()` 检查结果。
62
+ 6. 如果需要 lineage、联动筛选或后续更新,为每条记录提供稳定字符串 `id`;没有 `id` 时 Runtime 会使用 `record-0` 这类确定性后备值。
63
+ 7. 展示前检查 `chart.getState().health.renderable`、`health.status` 和 `warnings`。`ready` 表示没有阻止渲染的问题,`degraded` 表示带诊断继续渲染,`empty` 表示结果没有可用内容。
64
+
65
+ `locale` 默认是 `en-US`,需要中文数字/日期输出时设置 `locale: "zh-CN"`。输入日期保持 ISO-8601 字符串;运行时不负责自然语言日期解析。
36
66
 
37
67
  ## 最小 Spec
38
68
 
@@ -40,7 +70,7 @@
40
70
  {
41
71
  type: 'line',
42
72
  renderer: 'svg',
43
- data: { values: [{ month: 'Jan', sales: 120 }] },
73
+ data: { values: [{ id: 'jan', month: 'Jan', sales: 120 }] },
44
74
  encoding: {
45
75
  x: { field: 'month', type: 'category' },
46
76
  y: { field: 'sales', type: 'quantitative' }
@@ -22,7 +22,7 @@ npm Registry 中无作用域的 `ichartjs` 是安全占位包,并非本项目
22
22
  npx skills add wanghetommy/ichartjs --skill ichartjs
23
23
  ```
24
24
 
25
- Codex 全局无交互安装可追加 `--agent codex --global --yes`。需要固定发布版本时,安装 `https://github.com/wanghetommy/ichartjs/tree/v2.0.7/skills/ichartjs`。WorkBuddy 可通过自身 Skill 界面导入该带 Tag 的目录;只有当前 CLI 明确声明对应适配器时才使用宿主专用 `--agent` 参数。
25
+ Codex 全局无交互安装可追加 `--agent codex --global --yes`。需要固定发布版本时,安装 `https://github.com/wanghetommy/ichartjs/tree/v2.0.9/skills/ichartjs`。WorkBuddy 可通过自身 Skill 界面导入该带 Tag 的目录;只有当前 CLI 明确声明对应适配器时才使用宿主专用 `--agent` 参数。
26
26
 
27
27
  使用 `npx skills add wanghetommy/ichartjs --list` 验证发现结果,其中应包含 `ichartjs`。
28
28
 
@@ -6,7 +6,7 @@ iChart.js 应作为普通 JavaScript UI 组件运行在浏览器应用中。数
6
6
  npm install @taylorwong/ichartjs@^2
7
7
  ```
8
8
 
9
- 无法访问 npm Registry 的环境请用 GitHub 源作为后备:`npm install github:wanghetommy/ichartjs#v2.0.7`。
9
+ 无法访问 npm Registry 的环境请用 GitHub 源作为后备:`npm install github:wanghetommy/ichartjs#v2.0.9`。
10
10
 
11
11
  ```js
12
12
  import { createChart } from '@taylorwong/ichartjs';
@@ -36,6 +36,40 @@ Agent 与开发者使用同一个 ESM 入口。编码 Agent 的完整方式见 [
36
36
  6. 仅在 `validation.valid` 为 `true` 时调用 `createChart()`。
37
37
  7. 用 `chart.explain()`、`chart.getState()`、JSON/SVG/PNG export 完成自检。需要持久化或附件生成时使用 `chart.export({type:'json'|'svg'|'png'})`,在浏览器环境可调用 `chart.downloadPNG()` / `chart.downloadSVG()` / `chart.downloadJSON()` 触发保存,最后调用 `chart.destroy()`。
38
38
 
39
+ ### 意图必须使用注册词
40
+
41
+ `intent` 是精确的机器词,不是自然语言句子。先从 `getCapabilities().intents` 获取允许值,再传入 `trend`、`time-series`、`comparison`、`ranking`、`distribution`、`relationship`、`matrix`、`multidimensional`、`schedule`、`architecture` 或 `mindmap` 等值。不要直接传入 `trend over time` 或 `展示销售趋势`。未知词会返回 `UNKNOWN_INTENT` 警告并安全降级;如果忽略警告,可能选错图表。
42
+
43
+ 如果用户输入的是自然语言,先映射为注册词,再调用 `planChart()`,同时保留原始用户意图用于展示。
44
+
45
+ ### 配置项放在 Spec 正确层级
46
+
47
+ `encoding` 只描述字段角色和 Series 语义,标题、格式和显示组件放在 Spec 顶层:
48
+
49
+ | 需求 | 正确位置 | 常见错误 |
50
+ | --- | --- | --- |
51
+ | 坐标轴标题 | `xAxis.title`、`yAxis.title` | `encoding.x.title`、`encoding.y.title` |
52
+ | 坐标轴格式 | `xAxis.format`、`yAxis.format` | `encoding.x.format`、`encoding.y.format` |
53
+ | 数据标签 | `labels.enabled`、`labels.format` | `encoding.labels` |
54
+ | 图例 | `legend.visible` | `encoding.legend` |
55
+ | 主题和配色 | `theme.mode`、`theme.preset`、`theme.palette` | 随意猜测 Series 颜色 |
56
+
57
+ `validateSpec()` 会把这些错误位置报告为结构化警告,应先修复再展示。单系列笛卡尔图默认会把字段名作为图例;不需要时使用 `legend: { visible: false }`。
58
+
59
+ ### 当前坐标域限制
60
+
61
+ 数值型笛卡尔图表默认使用易读的纵轴域:`yAxis.nice` 默认为 `true`,`yAxis.ticks` 默认为 `"auto"`。需要固定范围时使用 `yAxis.domain: [min, max]`,例如 `{ domain: [0, 2000], ticks: 5 }` 可稳定生成五个标签;使用 `yAxis.nice: false` 可保留原始数据边界。`yAxis.format` 只负责格式化刻度显示,`yAxis.right` 支持同样的配置。Agent 可通过 `chart.getState().axes` 或 `chart.explain().axes` 获取原始域、计算域、刻度、步长和策略进行自检。分类/时间横轴的范围仍由数据记录推导,因此 `xAxis.min/max` 和 `xAxis.domain` 不支持。图表专用域配置仍包括:`gauge.domain`、`heatmap.colorScale.domain`、`radar.indicators[].min/max`;项目图表的日期范围当前由数据记录自动计算。
62
+
63
+ 图表通道是严格按类型定义的:笛卡尔图表使用 `x`/`y`,Pie/Funnel 使用 `category`/`value`,Gauge 只使用 `value`,Heatmap 使用 `x`/`y`/`color`,Radar 使用 `indicators[].field`。缺失字段或不支持的通道会校验失败;Gauge 必须声明 `domain`。Pie 遇到负数会报告 `NEGATIVE_VALUE_DROPPED`,没有正数占比时会报告 `ZERO_TOTAL`。新建图表可直接使用 `@taylorwong/ichartjs/recipes/minimal-specs` 中的最小目录:
64
+
65
+ ```js
66
+ import catalog from '@taylorwong/ichartjs/recipes/minimal-specs' with { type: 'json' };
67
+
68
+ const spec = structuredClone(catalog.examples.radar);
69
+ ```
70
+
71
+ Agent 自检使用 `chart.getState().health` 和 `chart.explain().health`,其中包含 `ready`、`degraded`、`empty`、警告数、隐藏标签数、限制值数和已渲染标记数。`locale` 默认 `en-US`,需要中文输出时设置 `locale: "zh-CN"`,输入日期仍使用 ISO-8601。
72
+
39
73
  ## 品牌署名(Branding)默认行为
40
74
 
41
75
  - 默认 `branding: true`:在画面与所有导出产物(PNG/SVG/JSON)右下角同步出现 `Powered by iChart.js` 低对比度署名。
@@ -73,6 +107,8 @@ const headlessPng = await chart.exportAsync({ type: 'png' });
73
107
 
74
108
  不要虚构字段、单位、日期、依赖关系、日历规则或预测置信度。Radar 使用混合单位时必须提供显式 domain;Heatmap 必须区分缺失值和零;高基数占比数据优先使用 Bar 而不是 Pie。
75
109
 
110
+ 为了让 lineage 自检和联动更新稳定,建议每条输入记录提供稳定字符串 `id`。没有 `id` 时 Runtime 会使用 `record-0` 这类位置后备值,只适合本地展示,不应当视为持久业务身份。
111
+
76
112
  ## 完整示例
77
113
 
78
114
  ```bash
@@ -16,6 +16,8 @@ Iteration 8 通过 `getChartCapability(type)` 提供逐图表能力档案,包
16
16
 
17
17
  `planChart(data, { intent, renderer })` 返回版本化规划结果:主选图表、备选项、置信度、原因、缺失字段、建议编码、假设、警告、不支持请求和安全下一步。规划不会虚构业务含义、单位、日期或缺失字段。
18
18
 
19
+ 未知 intent 还会返回 `intentKnown`、`intentSuggestions` 和 `fallbackUsed`。Spec 的通道按图表类型约束:笛卡尔图表是 `x`/`y`,Pie/Funnel 是 `category`/`value`,Gauge 只使用 `value`,Heatmap 是 `x`/`y`/`color`,Radar 字段位于 `indicators`。`validateSpec()` 会拒绝不支持的通道和缺失字段。Gauge 必须显式声明 `domain`,超出范围时会报告 `VALUE_CLAMPED`;Pie 的负值和空占比分别报告 `NEGATIVE_VALUE_DROPPED`、`ZERO_TOTAL`。
20
+
19
21
  `validateSpec()` 分开返回 `errors`、`warnings` 和 `normalizations`;诊断包含稳定代码、JSON 路径、期望值和修复建议。`chart.explain()` 返回编码、转换、交互、假设、警告、稳定记录血缘和无障碍摘要。
20
22
 
21
23
  ## 关键规则
@@ -23,8 +25,10 @@ Iteration 8 通过 `getChartCapability(type)` 提供逐图表能力档案,包
23
25
  - Spec 必须是 JSON-serializable。
24
26
  - 渲染前调用 `validateSpec()`。
25
27
  - 布局和数据语义不依赖 Renderer。
26
- - 通用图表使用 `data.values`;Flow/Swimlane 使用 `nodes/edges/lanes`。
28
+ - Diagram 结构字段必须位于 Spec 顶层:通用图表使用 `data.values`;Flow/Swimlane 使用 `nodes/edges/lanes`,Architecture 使用 `nodes/edges/layers/boundaries`,Mindmap 使用带 `parentId` 的 `nodes` 和可选 `edges`。不要将这些字段放在 `data` 内。
27
29
  - `svg` 适合 DOM 交互和可访问性;`canvas` 适合大量图元和绘制性能。
30
+ - 数值纵轴默认使用易读域(`yAxis.nice: true`、`yAxis.ticks: "auto"`);使用 `yAxis.domain: [min, max]` 固定范围,或使用 `yAxis.nice: false` 保留原始边界。Agent 可通过 `chart.getState().axes` 或 `chart.explain().axes` 自检原始域、计算域、刻度、步长和策略。分类/时间横轴的 `min/max` 和 `domain` 不支持,范围由数据确定。
31
+ - `chart.getState().health` 和 `chart.explain().health` 提供 `ready`、`degraded` 或 `empty`,以及可渲染性、问题代码、警告数、隐藏标签数、限制值数和已渲染标记数。`locale` 默认 `en-US`,可设置 `zh-CN` 影响输出格式;输入日期应使用 ISO-8601 字符串。
28
32
 
29
33
  ## 品牌署名(Branding)
30
34
 
@@ -116,7 +116,7 @@ npx skills add wanghetommy/ichartjs --skill ichartjs --agent codex --global --ye
116
116
  需要固定发布版本时,直接安装已发布的 Skill 目录:
117
117
 
118
118
  ```bash
119
- npx skills add https://github.com/wanghetommy/ichartjs/tree/v2.0.7/skills/ichartjs \
119
+ npx skills add https://github.com/wanghetommy/ichartjs/tree/v2.0.9/skills/ichartjs \
120
120
  --agent codex --global --yes
121
121
  ```
122
122
 
@@ -8,6 +8,7 @@
8
8
  "agentQuickstart": "docs/agent/quickstart.md",
9
9
  "usageScenarios": "docs/agent/usage-scenarios.md",
10
10
  "agentWorkflowExample": "examples/agent-workflow.mjs",
11
+ "minimalSpecs": "@taylorwong/ichartjs/recipes/minimal-specs",
11
12
  "officialSkill": "skills/ichartjs/SKILL.md",
12
13
  "scenarios": {
13
14
  "charting": ["line", "area", "bar", "column", "pie", "scatter", "funnel", "gauge", "heatmap", "radar"],
@@ -17,6 +18,17 @@
17
18
  "projectIntelligence": ["variance", "capacity", "release", "risk", "aging"],
18
19
  "chartModes": ["stacked", "percent-stacked", "donut", "mixed-line-column", "bin", "architecture-layers", "architecture-boundaries", "mindmap-tree", "mindmap-radial", "mindmap-curved-edges"],
19
20
  "renderers": ["canvas", "svg"],
21
+ "locale": {
22
+ "default": "en-US",
23
+ "recommended": ["en-US", "zh-CN"],
24
+ "appliesTo": ["axis", "labels", "tooltip", "export"],
25
+ "inputDates": "ISO-8601 strings; natural-language date parsing is not supported."
26
+ },
27
+ "health": {
28
+ "state": ["ready", "degraded", "empty"],
29
+ "apis": ["chart.getState().health", "chart.explain().health"],
30
+ "metrics": ["warnings", "suppressedLabels", "clampedValues", "renderedMarks"]
31
+ },
20
32
  "interactionDefaults": { "zoom": false, "pan": false, "brush": false, "drag": false, "edgeDrag": false, "portConnect": false, "editing": false },
21
33
  "diagramEditing": {
22
34
  "renderers": ["canvas", "svg"],
@@ -57,6 +57,7 @@ export function runAgentWorkflow(rows, options = {}) {
57
57
  try {
58
58
  const explanation = chart.explain();
59
59
  const state = chart.getState();
60
+ const expectedRecordIds = rows.map((row, index) => String(row.id ?? row.key ?? `record-${index}`));
60
61
  return {
61
62
  ok: true,
62
63
  stage: 'complete',
@@ -69,7 +70,7 @@ export function runAgentWorkflow(rows, options = {}) {
69
70
  state,
70
71
  selfCheck: {
71
72
  chartDeclared: capabilities.chartTypes.includes(plan.primary),
72
- recordIdsPreserved: rows.every(row => explanation.lineage.recordIds.includes(row.id)),
73
+ recordIdsPreserved: expectedRecordIds.every(recordId => explanation.lineage.recordIds.includes(recordId)),
73
74
  warningsVisible: plan.warnings.every(warning => state.warnings.some(item => item.code === warning.code)),
74
75
  styleExplained: explanation.style?.preset === plan.styleRecommendation.preset
75
76
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taylorwong/ichartjs",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
4
4
  "description": "Agent-first, renderer-independent charting and project visualization runtime",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
@@ -21,7 +21,7 @@ Recommended installation:
21
21
  npx skills add wanghetommy/ichartjs --skill ichartjs
22
22
  ```
23
23
 
24
- Use `--agent codex --global --yes` for global non-interactive Codex installation. Use the tagged directory `https://github.com/wanghetommy/ichartjs/tree/v2.0.7/skills/ichartjs` when reproducibility matters. WorkBuddy can import the same directory through its Skill interface; do not assume a `--agent workbuddy` adapter unless the installed CLI declares it.
24
+ Use `--agent codex --global --yes` for global non-interactive Codex installation. Use the tagged directory `https://github.com/wanghetommy/ichartjs/tree/v2.0.9/skills/ichartjs` when reproducibility matters. WorkBuddy can import the same directory through its Skill interface; do not assume a `--agent workbuddy` adapter unless the installed CLI declares it.
25
25
 
26
26
  The Skill is a workflow adapter, not the chart runtime. If the current JavaScript or TypeScript project does not already depend on iChart.js, install the matching runtime from GitHub:
27
27
 
@@ -36,15 +36,18 @@ Do not install the unscoped npm registry package named `ichartjs`; it is current
36
36
  1. Locate the package or repository root. Read `docs/agent/quickstart.md` when available.
37
37
  2. Call `getCapabilities()` before selecting a chart or interaction.
38
38
  3. Call `inspectData()` and preserve stable record IDs.
39
- 4. Call `planChart(data, { intent, renderer, context })` and inspect the complete result, including `styleRecommendation`.
40
- 5. Stop when `requiredFields` is non-empty; request data or explain a supported alternative.
41
- 6. Build a JSON-serializable Spec using `suggestedEncodings`, the selected capability, and an applicable recipe.
42
- 7. Call `validateSpec()` before rendering. Repair only from structured diagnostics.
43
- 8. Call `createChart()` only after validation succeeds.
44
- 9. Self-check with `chart.explain()`, `chart.getState()`, and JSON export.
45
- 10. Provide an exact preview URL or artifact path and report assumptions, warnings, and deferred checks.
46
- 11. Prefer `theme: { mode: 'auto', preset, palette }`; preserve explicit user style choices and use `chart.setTheme()` for live switching.
47
- 12. For post-creation visual changes, call `getPreferenceCapabilities(chartType, { locale })`, validate the patch with `validatePreferences()`, apply it with `chart.setPreferences(..., { source: 'agent' })`, and verify `chart.getState().preferences`.
39
+ 4. Discover `getCapabilities().intents`; map natural-language requests to an exact registered token before calling `planChart(data, { intent, renderer, context })`.
40
+ 5. Inspect the complete planning result, including `styleRecommendation`, warnings, and fallback status.
41
+ 6. Stop when `requiredFields` is non-empty; request data or explain a supported alternative.
42
+ 7. Build a JSON-serializable Spec using `suggestedEncodings`, the selected capability, and an applicable recipe.
43
+ 8. Use chart-specific channels: Cartesian `x`/`y`, Pie/Funnel `category`/`value`, Gauge `value`, Heatmap `x`/`y`/`color`, and Radar `indicators[].field`. To load a recipe, use `import catalog from '@taylorwong/ichartjs/recipes/minimal-specs' with { type: 'json' }` and select `catalog.examples[type]`.
44
+ 9. Keep titles/formats under `xAxis`/`yAxis`, labels under `labels`, and legend under `legend`; do not place them inside `encoding`.
45
+ 10. Call `validateSpec()` before rendering. Repair `UNSUPPORTED_ENCODING_CHANNEL`, `MISSING_ENCODING_FIELD`, `MISSING_GAUGE_DOMAIN`, `UNKNOWN_INTENT`, misplaced-option, and unsupported-axis warnings before presenting the chart.
46
+ 11. Call `createChart()` only after validation succeeds. Gauge Specs must declare a meaningful `domain`.
47
+ 12. Self-check with `chart.explain()`, `chart.getState()`, `health.renderable`, and JSON export. Treat `VALUE_CLAMPED`, `LABELS_SUPPRESSED`, `NEGATIVE_VALUE_DROPPED`, and `ZERO_TOTAL` as material diagnostics to report.
48
+ 12. Provide an exact preview URL or artifact path and report assumptions, warnings, and deferred checks.
49
+ 13. Prefer `theme: { mode: 'auto', preset, palette }`; preserve explicit user style choices and use `chart.setTheme()` for live switching.
50
+ 14. For post-creation visual changes, call `getPreferenceCapabilities(chartType, { locale })`, validate the patch with `validatePreferences()`, apply it with `chart.setPreferences(..., { source: 'agent' })`, and verify `chart.getState().preferences`.
48
51
 
49
52
  Use `@taylorwong/ichartjs` for package imports. Use `examples/agent-workflow.mjs` as the executable baseline when working in the repository.
50
53
 
@@ -69,9 +72,15 @@ Route by requested output:
69
72
 
70
73
  - Never invent fields, units, dates, dependencies, calendar rules, domains, or forecast confidence.
71
74
  - Never silently drop validation errors, warnings, assumptions, normalizations, or unsupported requests.
75
+ - Treat `getCapabilities().intents` as an allowlist; never pass a natural-language sentence as `planChart().intent`.
76
+ - If planning returns `fallbackUsed: true`, use `intentSuggestions` to remap or ask for confirmation; never silently accept the fallback chart.
77
+ - Keep axis titles/formats under `xAxis`/`yAxis`, labels under `labels`, and legend settings under `legend`.
78
+ - Repair `UNKNOWN_INTENT`, misplaced-option, and unsupported-axis warnings before presenting a chart. For numeric y-axes, prefer the default readable domain; use `yAxis.domain: [min, max]` for an explicit range, `yAxis.nice: false` for raw boundaries, and `yAxis.ticks` for a stable label count.
79
+ - Add stable string `id` values to tabular rows when lineage or linked updates are part of the deliverable.
72
80
  - Avoid Pie for high-cardinality categories; prefer Bar for comparison.
73
81
  - Require explicit Radar domains when units differ.
74
82
  - Distinguish missing Heatmap values from zero.
83
+ - Set `locale` explicitly when output needs localization; the default is `en-US`, and input dates must be ISO-8601 strings.
75
84
  - Use categorical, sequential, diverging, or status palettes by data semantics; do not invent arbitrary color sets or rely on color alone.
76
85
  - Surface theme contrast diagnostics and high-cardinality color warnings.
77
86
  - Do not generate Map or 3D Specs unless capabilities explicitly add them.
@@ -11,11 +11,11 @@ getCapabilities → inspectData → planChart → build Spec → validateSpec
11
11
  - `getCapabilities()`: global and per-chart discoverability.
12
12
  - `getChartCapability(type)`: required roles, interactions, renderers, features, exports, and limits.
13
13
  - `inspectData(input)`: field roles, identifiers, cardinality, missingness, temporal coverage, and warnings.
14
- - `planChart(input, options)`: primary type, alternatives, confidence, reasons, required fields, suggested encodings, assumptions, warnings, unsupported requests, and next actions.
14
+ - `planChart(input, options)`: primary type, alternatives, confidence, reasons, required fields, suggested encodings, assumptions, warnings, unsupported requests, next actions, and `intentKnown`/`intentSuggestions`/`fallbackUsed` metadata.
15
15
  - `validateSpec(spec)`: errors, warnings, normalizations, and normalized Spec.
16
16
  - `createChart(spec)`: headless or mounted chart lifecycle.
17
17
  - `chart.explain()`: semantics, encodings, interactions, lineage, warnings, and accessibility summary.
18
- - `chart.getState()`: renderer, dimensions, warnings, assumptions, selection, view, project analytics, and linked state.
18
+ - `chart.getState()`: renderer, dimensions, warnings, assumptions, selection, view, project analytics, linked state, and `health`.
19
19
  - `chart.export({ type: 'json' })`: JSON-safe Spec and state.
20
20
 
21
21
  ## Stop conditions
@@ -24,6 +24,8 @@ Do not render when:
24
24
 
25
25
  - `plan.requiredFields` is non-empty;
26
26
  - `validateSpec().valid` is false;
27
+ - chart-specific encoding channels are unsupported or reference missing fields;
28
+ - a Gauge has no explicit `domain`;
27
29
  - the requested chart, renderer, interaction, or export is not declared;
28
30
  - required project dates, diagram endpoints, ports, lanes, or business schema rules are invalid.
29
31
 
@@ -35,5 +37,6 @@ Verify that:
35
37
  - validation passed without ignored errors;
36
38
  - explanation lineage preserves stable source IDs;
37
39
  - warnings and assumptions are visible in the response;
40
+ - `health.renderable` is true and `health.status` is reported; `VALUE_CLAMPED`, `LABELS_SUPPRESSED`, `NEGATIVE_VALUE_DROPPED`, and `ZERO_TOTAL` are not hidden;
38
41
  - the preview uses a maintained URL;
39
42
  - replaced charts are destroyed.
@@ -20,3 +20,5 @@
20
20
  | Responsibility | Swimlane | Require valid lane membership. |
21
21
 
22
22
  Always prefer `planChart()` over this table when runtime capability output is available. Treat alternatives as tradeoffs, not automatic fallbacks.
23
+
24
+ `planChart()` accepts the exact registered intent token, not the user's full sentence. For example, map “show the sales trend over time” to `trend`; if an unknown token is passed, inspect and surface the returned `UNKNOWN_INTENT` warning instead of accepting the fallback silently.