@taylorwong/ichartjs 2.0.6 → 2.0.8

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 (53) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +2 -2
  3. package/agent-recipes/minimal-specs.json +25 -0
  4. package/docs/agent/README.md +3 -1
  5. package/docs/agent/charting-scenario.md +46 -1
  6. package/docs/agent/coding-agent-integration.md +1 -1
  7. package/docs/agent/development/iteration-12.md +101 -0
  8. package/docs/agent/development/roadmap.md +2 -1
  9. package/docs/agent/development-guide.md +1 -1
  10. package/docs/agent/diagram-scenario.md +39 -11
  11. package/docs/agent/editing-contract.md +5 -0
  12. package/docs/agent/frontend-integration.md +1 -1
  13. package/docs/agent/project-scenario.md +1 -0
  14. package/docs/agent/quickstart.md +30 -0
  15. package/docs/agent/runtime-contract.md +19 -2
  16. package/docs/agent/theme-guide.md +33 -1
  17. package/docs/agent/usage-scenarios.md +3 -1
  18. package/docs/agent/zh-CN/README.md +1 -1
  19. package/docs/agent/zh-CN/charting-scenario.md +31 -1
  20. package/docs/agent/zh-CN/coding-agent-integration.md +1 -1
  21. package/docs/agent/zh-CN/diagram-scenario.md +32 -3
  22. package/docs/agent/zh-CN/editing-contract.md +2 -0
  23. package/docs/agent/zh-CN/frontend-integration.md +1 -1
  24. package/docs/agent/zh-CN/iteration-12.md +98 -0
  25. package/docs/agent/zh-CN/quickstart.md +30 -0
  26. package/docs/agent/zh-CN/runtime-contract.md +7 -1
  27. package/docs/agent/zh-CN/theme-guide.md +33 -1
  28. package/docs/agent/zh-CN/usage-scenarios.md +3 -1
  29. package/docs/manifests/capabilities.json +42 -3
  30. package/docs/manifests/commands.json +10 -9
  31. package/docs/manifests/schemas.json +5 -2
  32. package/examples/agent-workflow.mjs +2 -1
  33. package/package.json +1 -1
  34. package/skills/ichartjs/SKILL.md +19 -9
  35. package/skills/ichartjs/references/agent-contract.md +5 -2
  36. package/skills/ichartjs/references/chart-selection.md +2 -0
  37. package/src/capabilities.mjs +83 -13
  38. package/src/charts.mjs +202 -58
  39. package/src/command.mjs +4 -3
  40. package/src/diagram-interaction.mjs +55 -11
  41. package/src/diagram.mjs +149 -36
  42. package/src/edit-controller.mjs +6 -3
  43. package/src/edit.mjs +17 -7
  44. package/src/index.mjs +44 -17
  45. package/src/layout.mjs +39 -0
  46. package/src/preferences-ui.mjs +73 -24
  47. package/src/project.mjs +64 -24
  48. package/src/renderer.mjs +2 -2
  49. package/src/scene.mjs +32 -1
  50. package/src/schema.mjs +7 -2
  51. package/src/spec.mjs +88 -6
  52. package/src/theme.mjs +1 -1
  53. package/types/index.d.ts +28 -7
@@ -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、Gauge 使用 `encoding.category`/`encoding.value`;Heatmap 使用 `encoding.x`/`encoding.y`/`encoding.color`;Radar 使用 `indicators[].field`。字段不存在或通道不支持会成为校验错误,不应静默改名。Gauge 必须提供 `domain: [min, max]`;超出范围时弧形会限制在范围内,并产生 `VALUE_CLAMPED`。全部图表的最小可执行 Spec 见 `@taylorwong/ichartjs/recipes/minimal-specs`。
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.6/skills/ichartjs`。WorkBuddy 可通过自身 Skill 界面导入该带 Tag 的目录;只有当前 CLI 明确声明对应适配器时才使用宿主专用 `--agent` 参数。
25
+ Codex 全局无交互安装可追加 `--agent codex --global --yes`。需要固定发布版本时,安装 `https://github.com/wanghetommy/ichartjs/tree/v2.0.8/skills/ichartjs`。WorkBuddy 可通过自身 Skill 界面导入该带 Tag 的目录;只有当前 CLI 明确声明对应适配器时才使用宿主专用 `--agent` 参数。
26
26
 
27
27
  使用 `npx skills add wanghetommy/ichartjs --list` 验证发现结果,其中应包含 `ichartjs`。
28
28
 
@@ -6,10 +6,39 @@
6
6
 
7
7
  - `flow`:节点和边组成的流程图。
8
8
  - `swimlane`:带责任泳道的流程图。
9
+ - `architecture`:带可选层和边界的业务、数据或技术架构图。
10
+ - `mindmap`:以树形或放射布局呈现想法层级的思维导图。
11
+
12
+ 架构图和思维导图都属于结构化图,但不能混用:架构图表达明确的领域或系统关系,思维导图表达想法层级。
13
+
14
+ 思维导图建议使用简洁的父子数据:
15
+
16
+ ```js
17
+ {
18
+ type: 'mindmap',
19
+ nodes: [
20
+ { id: 'root', label: '发布计划' },
21
+ { id: 'scope', label: '范围', parentId: 'root' },
22
+ { id: 'risk', label: '风险', parentId: 'root' }
23
+ ],
24
+ diagram: { mode: 'mindmap', layout: 'tree', routing: 'curved', curveTension: 0.4 }
25
+ }
26
+ ```
9
27
 
10
28
  ## 当前能力
11
29
 
12
- 已支持节点、边、泳道、Group、Port、四种布局、三种路由、节点拖动、多选、对齐、网格吸附、键盘移动、Copy/Paste、Group 折叠展开、Port 键盘连线和 Undo/Redo。
30
+ 已支持节点、边、泳道、Group、Port、四种布局、三种路由、Mindmap 三次贝塞尔曲线、节点拖动、多选、对齐、网格吸附、键盘移动、Copy/Paste、Group 折叠展开、Port 键盘连线、边选择、折点/正交线段手柄、持久化 `waypoints`、边删除和 Undo/Redo。
31
+
32
+ 导航和编辑能力默认关闭。普通图表保持静态,缩放、平移、框选、节点拖动、线段拖动、Port 连线和结构编辑必须由宿主显式开启:
33
+
34
+ ```js
35
+ interaction: { zoom: true, pan: true, drag: true, edgeDrag: true, portConnect: true },
36
+ editing: { enabled: true, allowDelete: true, allowStructuralChanges: true }
37
+ ```
38
+
39
+ Canvas 与 SVG 共用 Scene Graph 命中、`waypoints`、命令、历史和交互行为,不提供渲染器专属编辑能力。
40
+
41
+ Mindmap 默认使用曲线父子连线。`diagram.curveTension` 支持 `0.2` 到 `0.8`;显式边可以覆盖 `routing` 或 `curveTension`。存在 `waypoints` 时优先使用人工折线,当前不支持直接拖动贝塞尔控制点。
13
42
 
14
43
  当前限制:
15
44
 
@@ -22,7 +51,7 @@
22
51
  1. 为节点和边分配稳定 ID。
23
52
  2. 使用 `validateDiagram(spec)` 检查端点、Port、Group、Lane 和布局。
24
53
  3. 使用 `createChart(spec)` 创建图表。
25
- 4. 使用 `moveNodes`、`alignNodes`、`snapNodes` 等命令编辑。
54
+ 4. 使用 `moveNodes`、`alignNodes`、`snapNodes`、`updateEdge`、`removeEdge` 等命令编辑。
26
55
  5. 编辑遵循 `editing-contract.md` 的 Preview/Confirm/Commit 流程。
27
56
 
28
57
  ## 开发位置与验收
@@ -34,4 +63,4 @@
34
63
  - 专用 Demo:`playground/diagram-editor.html`
35
64
  - 全量 Gallery:`playground/project-gallery.html`
36
65
 
37
- 节点移动后必须验证边、箭头和标签跟随;同时检查 Canvas 与 SVG 的一致性。
66
+ 节点移动后必须验证边、箭头和标签跟随;同时检查 Canvas 与 SVG 的边命中、手柄拖动、waypoint 持久化、键盘和导出一致性。
@@ -23,5 +23,7 @@ const result = chart.applyEdit(command, { preview, confirmed: true, source: 'age
23
23
  - 默认需要 Host 确认;确认不等同于授权。
24
24
  - 成功提交产生 ChangeSet、审计信息、revision 和 Undo 历史。
25
25
  - 外部持久化、权限和认证由 Host 应用负责。
26
+ - 指针导航和编辑默认关闭。`editing.enabled` 授权编辑事务;`interaction.drag`、`interaction.edgeDrag`、`interaction.portConnect` 分别控制直接操作 UI。
27
+ - Diagram 边通过 JSON-safe 的 `waypoints` 持久化;路径更新使用 `updateEdge`,删除使用 `removeEdge`,并要求结构编辑权限。
26
28
 
27
29
  Schema、命令、Preview/Commit、事务和历史的实现分别位于 `src/schema.mjs`、`src/command.mjs`、`src/edit.mjs`、`src/edit-controller.mjs` 和 `src/history.mjs`。
@@ -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.6`。
9
+ 无法访问 npm Registry 的环境请用 GitHub 源作为后备:`npm install github:wanghetommy/ichartjs#v2.0.8`。
10
10
 
11
11
  ```js
12
12
  import { createChart } from '@taylorwong/ichartjs';
@@ -0,0 +1,98 @@
1
+ # Iteration 12:结构化图——架构图与思维导图
2
+
3
+ Iteration 12 在 Flow/Swimlane 现有 Diagram Runtime 上增加两种结构化图模式。架构图和思维导图共用节点、边、布局、交互、导出和 Agent 契约,不新增第二套渲染器。
4
+
5
+ ## 12A:共享结构化图模型
6
+
7
+ - 复用稳定节点 ID、边、Group、Port、位置、尺寸、路由、选择、键盘导航、历史、Canvas/SVG 渲染以及 JSON/SVG/PNG 导出。
8
+ - 将 `diagram.mode` 归一化为 `process`、`architecture` 或 `mindmap`。
9
+ - 思维导图可以从 `node.parentId` 推导父子边,同时保留显式边。
10
+ - 校验缺失父节点、自引用、重复 ID、无效层引用和思维导图循环。
11
+ - Agent 统一使用 `validateDiagram()` 作为校验入口。
12
+
13
+ ## 12B:架构图模式
14
+
15
+ - 使用 `type: 'architecture'` 表达业务架构、数据架构和技术架构。
16
+ - 使用 `layers` 表达稳定的架构分层。
17
+ - 使用 `boundaries` 表达领域、系统、平台或上下文边界,并支持 `nodeIds`、标签、边距和颜色。
18
+ - 普通边表达依赖、实现、持久化、发布等关系;Runtime 不擅自推断业务语义。
19
+ - 有明确位置时保留手工布局,否则使用确定性的分层布局。
20
+
21
+ ## 12C:思维导图模式
22
+
23
+ - 使用 `type: 'mindmap'` 和 `parentId` 表达简洁的 Agent 友好层级。
24
+ - 支持确定性的 `tree` 和 `radial` 布局。
25
+ - 使用现有 Diagram 模型表达根节点和分支强调,不新增独立编辑模型。
26
+ - 保留稳定 ID 和父引用,Agent 可以只更新一个分支。
27
+
28
+ ## 12D:Agent 契约与 Schema
29
+
30
+ - 在 `getCapabilities()`、`planChart()`、图表能力、TypeScript 声明和 manifest 中暴露 `architecture`、`mindmap`。
31
+ - 增加 `architecture-node`、`architecture-edge`、`mindmap-node` Schema。
32
+ - 对层、边界和父节点语义返回 assumptions 与结构化诊断,不静默猜测。
33
+ - 两者都归入 `diagram` 家族,仅在 architecture、hierarchy、brainstorm 等意图下推荐。
34
+
35
+ ## 12E:Playground 与文档
36
+
37
+ - 在 `playground/project-gallery.html` 增加 Architecture 和 Mindmap 示例。
38
+ - 要区分:架构图表达领域/系统结构,思维导图表达想法层级;思维导图不默认等同于架构图。
39
+ - 执行 `npm run playground`,打开 `http://localhost:3000/playground/project-gallery.html`,搜索 `Architecture` 或 `Mindmap`。
40
+
41
+ ## 12F:Canvas/SVG 一致的线段编辑
42
+
43
+ 线段直接编辑必须是与渲染器无关的 Diagram 能力。可以先用 SVG 验证交互体验,但 Canvas 与 SVG 必须提供相同的公共操作、编辑语义、持久化数据、键盘行为和最终验收状态。只要任一渲染器仍为只读或能力缩水,12F 就不算完成。
44
+
45
+ Runtime 默认状态必须静态、安全,不产生意外的视图或结构变化。缩放、平移、框选、节点拖动、线段拖动、端口连线和结构命令默认全部关闭,必须由宿主显式开启。Agent 编辑继续使用经过校验的预览/提交契约,不得隐式开启页面中的指针编辑能力。
46
+
47
+ ### 第一阶段:边命中与选择
48
+
49
+ - 增加基于几何距离的边命中算法和宽容的交互容差,不再依赖 Scene Node 的矩形 `bounds`。
50
+ - Flow、Swimlane、Architecture、Mindmap 中的边都可选择,但不影响普通 Line 等数据图表的折线交互。
51
+ - Canvas 与 SVG 一致支持选中、Hover、焦点、删除、Escape 和键盘遍历状态。
52
+ - 命中检测放在共享 Scene Graph 中;SVG 可以使用透明粗描边优化 DOM 交互,但不能以 SVG DOM 作为唯一事实来源。
53
+ - 通过 `getCapabilities()` 明确暴露边选择和边编辑能力。
54
+ - 默认图表 Spec 必须关闭导航与编辑;Gallery 和只读嵌入页面不能隐式开启这些能力。
55
+
56
+ ### 第二阶段:折点与线段手柄
57
+
58
+ - 仅在编辑模式选中边后显示折点手柄和线段中点手柄。
59
+ - 拖动折点只更新一个 waypoint;拖动正交线段中点只移动对应的水平或垂直线段。
60
+ - 使用不可见的扩大命中区域和最小触控尺寸,让细线易于操作,同时不改变可见线宽。
61
+ - 复用共享编辑控制器的预览、确认、提交、撤销、重做和审计能力。
62
+ - 可以先在 SVG 中验证交互,但不能发布渲染器特有的公共行为。
63
+
64
+ ### 第三阶段:人工路由持久化
65
+
66
+ - 在边契约中增加 JSON-safe 的 `waypoints`,继续使用稳定 edge ID。
67
+ - Canvas、SVG、JSON 导出、SVG/PNG 导出、复制粘贴、复制和 Agent 编辑均使用同一 waypoint 模型。
68
+ - 路由优先级定义为:存在显式 waypoints 时优先使用,否则执行自动避障路由。
69
+ - 节点移动后尽量保留有效人工线段,修复无效的端点线段;人工路径不可用时回退到确定性的自动路由。
70
+ - Agent 通过经过校验的 `updateEdge` 操作更新路径,不增加渲染器专属命令。
71
+
72
+ ### 12F 验收
73
+
74
+ - Canvas 与 SVG 通过同一套边命中、选择、手柄拖动、持久化、撤销/重做、键盘和导出测试。
75
+ - Flow、Swimlane、Architecture、Mindmap 共用同一套边编辑契约和交互实现。
76
+ - 细线在不改变可见宽度的情况下仍容易选择。
77
+ - 人工 waypoints 在重绘、切换渲染器、序列化、导出和重新创建图表后保持不变。
78
+ - 节点移动后边不能穿过节点;无效人工路径必须被修复或确定性地重新路由。
79
+ - 在双渲染器一致性全部通过前,Capabilities 应报告线段拖动不可用,而不是只声明 SVG 支持。
80
+ - 默认图表保持静态:缩放、平移、框选、节点拖动、线段拖动、端口连线和结构编辑只有在宿主显式配置后才启用。
81
+
82
+ ## 12G:Mindmap 贝塞尔曲线
83
+
84
+ - Mindmap 父子连线默认使用 `routing: 'curved'`;Flow、Swimlane、Architecture 继续默认使用正交路由。
85
+ - `curved` 在 Canvas 与 SVG 中都渲染为一段真实三次贝塞尔曲线,不再是四点折线。
86
+ - `diagram.curveTension` 和单边 `curveTension` 支持 `0.2` 到 `0.8`,默认值为 `0.4`。
87
+ - 标签位于贝塞尔中点,箭头根据终点切线定向;共享 Scene Graph 通过曲线采样保持 Canvas/SVG 命中一致。
88
+ - 曲线穿过其他节点时,确定性回退到具备避障能力的正交路由。
89
+ - 显式 `waypoints` 优先并继续使用人工折线。暂不提供贝塞尔控制点拖动;节点移动后自动重新计算曲线。
90
+
91
+ ## 验收
92
+
93
+ - `npm run agent:check` 通过,公开图表类型为 18 个,业务 Schema 为 10 个。
94
+ - Architecture 在 SVG 和 Canvas 下均能显示层、边界、节点和依赖边。
95
+ - Mindmap 能校验父引用与循环,生成稳定父子边,并确定性渲染 tree/radial 布局。
96
+ - 既有 Flow、Swimlane 测试和预览不回归。
97
+ - Iteration 12F 只有在 Canvas 与 SVG 具备一致的线段编辑能力后才通过验收。
98
+ - Iteration 12G 只有在 Canvas、浏览器 SVG 与 Headless SVG 都输出真实三次贝塞尔路径,并保持默认静态交互时才通过验收。
@@ -36,6 +36,34 @@ 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/Gauge 使用 `category`/`value`,Heatmap 使用 `x`/`y`/`color`,Radar 使用 `indicators[].field`。缺失字段或不支持的通道会校验失败;Gauge 必须声明 `domain`。新建图表可直接使用 `@taylorwong/ichartjs/recipes/minimal-specs` 中的最小目录。
64
+
65
+ Agent 自检使用 `chart.getState().health` 和 `chart.explain().health`,其中包含 `ready`、`degraded`、`empty`、警告数、隐藏标签数、限制值数和已渲染标记数。`locale` 默认 `en-US`,需要中文输出时设置 `locale: "zh-CN"`,输入日期仍使用 ISO-8601。
66
+
39
67
  ## 品牌署名(Branding)默认行为
40
68
 
41
69
  - 默认 `branding: true`:在画面与所有导出产物(PNG/SVG/JSON)右下角同步出现 `Powered by iChart.js` 低对比度署名。
@@ -73,6 +101,8 @@ const headlessPng = await chart.exportAsync({ type: 'png' });
73
101
 
74
102
  不要虚构字段、单位、日期、依赖关系、日历规则或预测置信度。Radar 使用混合单位时必须提供显式 domain;Heatmap 必须区分缺失值和零;高基数占比数据优先使用 Bar 而不是 Pie。
75
103
 
104
+ 为了让 lineage 自检和联动更新稳定,建议每条输入记录提供稳定字符串 `id`。没有 `id` 时 Runtime 会使用 `record-0` 这类位置后备值,只适合本地展示,不应当视为持久业务身份。
105
+
76
106
  ## 完整示例
77
107
 
78
108
  ```bash
@@ -10,10 +10,14 @@ getCapabilities → inspectData → planChart → 创建 Spec → validateSpec
10
10
 
11
11
  Agent 应优先使用 `getCapabilities()`,不要硬编码未声明的图表类型或操作。
12
12
 
13
+ 图表创建后的视觉设置使用 `getPreferenceCapabilities(chartType, { locale }) → chart.getPreferences() → validatePreferences(patch) → chart.setPreferences(patch, { source: 'agent' }) → chart.getState().preferences`。这样 Agent 与内置设置菜单始终使用同一份白名单契约。
14
+
13
15
  Iteration 8 通过 `getChartCapability(type)` 提供逐图表能力档案,包括必需数据角色、支持的交互、Renderer、功能状态、导出和建议限制。Agent 不应猜测未声明能力。
14
16
 
15
17
  `planChart(data, { intent, renderer })` 返回版本化规划结果:主选图表、备选项、置信度、原因、缺失字段、建议编码、假设、警告、不支持请求和安全下一步。规划不会虚构业务含义、单位、日期或缺失字段。
16
18
 
19
+ 未知 intent 还会返回 `intentKnown`、`intentSuggestions` 和 `fallbackUsed`。Spec 的通道按图表类型约束:笛卡尔图表是 `x`/`y`,Pie/Funnel/Gauge 是 `category`/`value`,Heatmap 是 `x`/`y`/`color`,Radar 字段位于 `indicators`。`validateSpec()` 会拒绝不支持的通道和缺失字段。Gauge 必须显式声明 `domain`,超出范围时会报告 `VALUE_CLAMPED`。
20
+
17
21
  `validateSpec()` 分开返回 `errors`、`warnings` 和 `normalizations`;诊断包含稳定代码、JSON 路径、期望值和修复建议。`chart.explain()` 返回编码、转换、交互、假设、警告、稳定记录血缘和无障碍摘要。
18
22
 
19
23
  ## 关键规则
@@ -23,6 +27,8 @@ Iteration 8 通过 `getChartCapability(type)` 提供逐图表能力档案,包
23
27
  - 布局和数据语义不依赖 Renderer。
24
28
  - 通用图表使用 `data.values`;Flow/Swimlane 使用 `nodes/edges/lanes`。
25
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 字符串。
26
32
 
27
33
  ## 品牌署名(Branding)
28
34
 
@@ -80,6 +86,6 @@ iChart.js 导出采用**双底层单源架构**,所有产物共享 `buildScene
80
86
  - `DOWNLOAD_HEADLESS`:`chart.download*()` 仅在浏览器有 DOM 时可用,无头用 `export`。
81
87
  - `EXPORT_TYPE_UNSUPPORTED`:不支持的导出类型。
82
88
 
83
- 公共 API:`inspectData`、`normalizeData`、`planChart`、`recommend`、`validateSpec`、`createChart`、`getCapabilities`、`getChartCapability`、`chart.describe`、`chart.explain`、`chart.getState`、`chart.export`、`chart.exportAsync`、`chart.toDataURL`、`chart.toBlob`、`chart.download`、`chart.downloadPNG`、`chart.downloadSVG`、`chart.downloadJSON`。
89
+ 公共 API:`inspectData`、`normalizeData`、`planChart`、`recommend`、`validateSpec`、`createChart`、`getCapabilities`、`getChartCapability`、`getPreferenceCapabilities`、`validatePreferences`、`chart.describe`、`chart.explain`、`chart.getState`、`chart.getPreferences`、`chart.setPreferences`、`chart.resetPreferences`、`chart.selectEdges`、`chart.getSelectedEdgeIds`、`chart.deleteSelectedEdges`、`chart.export`、`chart.exportAsync`、`chart.toDataURL`、`chart.toBlob`、`chart.download`、`chart.downloadPNG`、`chart.downloadSVG`、`chart.downloadJSON`。
84
90
 
85
91
  实现位置:`src/index.mjs`、`src/spec.mjs`、`src/scene.mjs`、`src/renderer.mjs`、`src/plugin.mjs`、`src/scale.mjs`、`src/charts.mjs`、`src/capabilities.mjs`。
@@ -66,7 +66,11 @@ const chart = createChart({
66
66
  data: { values: rows },
67
67
  preferences: pagePreferences
68
68
  });
69
- mountChartSettings(chart, { locale: 'zh-CN' });
69
+ const settings = mountChartSettings(chart, {
70
+ locale: 'zh-CN',
71
+ placement: 'auto',
72
+ preferredPlacements: ['right', 'top', 'bottom']
73
+ });
70
74
 
71
75
  // Agent 对话也使用同一套 API。
72
76
  chart.setPreferences({
@@ -74,8 +78,36 @@ chart.setPreferences({
74
78
  typography: { scale: 1.15 },
75
79
  components: { grid: false }
76
80
  }, { source: 'agent' });
81
+
82
+ // 宿主永久移除图表时同步销毁快捷设置浮层。
83
+ settings.destroy();
84
+ ```
85
+
86
+ 快捷设置面板会通过 Portal 放到图表裁剪区域之外。自动定位优先使用按钮右侧,其次上侧、下侧;都无法完整容纳时限制在浏览器视口内。滚动时保持已经选定的方位并跟随按钮,不再被视口约束拉回;图表或菜单按钮离开视口时直接关闭。窗口缩放和内容变化时可以重新计算方位。
87
+
88
+ ### Agent 配置发现与验证
89
+
90
+ Agent 不应硬编码菜单选项,应先调用 `getPreferenceCapabilities(chartType, { locale })`。该接口会返回每个偏好字段的类型、默认值、候选值、作用域、当前图表适用性和 `menu.visible` 状态;对话调整和宿主自定义设置页应使用同一份契约。
91
+
92
+ ```js
93
+ import { getPreferenceCapabilities, validatePreferences } from '@taylorwong/ichartjs';
94
+
95
+ const capabilities = getPreferenceCapabilities(chart.getSpec().type, { locale: 'zh-CN' });
96
+ const menuFields = capabilities.fields.filter(field => field.menu.visible);
97
+ const current = chart.getPreferences();
98
+ const patch = {
99
+ theme: { preset: 'dashboard', palette: 'status' },
100
+ typography: { scale: 1.15 },
101
+ components: { grid: false }
102
+ };
103
+ const checked = validatePreferences(patch, { partial: true });
104
+ if (!checked.valid) throw new Error(JSON.stringify(checked.errors));
105
+ chart.setPreferences(checked.value, { scope: 'chart', source: 'agent' });
106
+ const applied = chart.getState().preferences;
77
107
  ```
78
108
 
109
+ 快捷菜单字段为 `theme.mode`、`theme.palette`、`typography.scale`,以及当前图表支持的 `components.legend`、`components.labels`、`components.grid`。完整白名单另外包含 `theme.preset`、`density`、`branding.enabled` 和 `motion`。无法识别语言时默认返回英文。
110
+
79
111
  单图表快捷菜单使用紧凑的汉堡图标,只保留高频操作:主题模式、配色、字号,以及当前图表真正支持的图例、数据标签和网格线。能力检测会自动隐藏无效设置;修改即时生效,并支持 `zh-CN`、`en` 和按文档语言自动识别。
80
112
 
81
113
  低频选项和页面级配置应放在图表弹出菜单之外的独立设置页。页面内图表共享同一个 store,并使用 `store.setGlobal()` 或 `chart.setPreferences(patch, { scope: 'global' })` 更新全局。完整设置页可提供 preset、密度、署名等白名单能力,而不挤占每张图表。Node/SSR 默认使用内存,浏览器需要显式选择 `localStorage` 或宿主存储适配器。快捷菜单验收地址:`http://localhost:3000/playground/project-gallery.html`;完整页面设置验收地址:`http://localhost:3000/playground/preferences-lab.html`。
@@ -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.6/skills/ichartjs \
119
+ npx skills add https://github.com/wanghetommy/ichartjs/tree/v2.0.8/skills/ichartjs \
120
120
  --agent codex --global --yes
121
121
  ```
122
122
 
@@ -150,6 +150,8 @@ Agent 可以创建一个 ESM 脚本或独立 HTML 页面,输出:
150
150
  - `gantt`、`timeline`、`milestone`、`burndown`:项目进度和交付计划;
151
151
  - 项目分析:capacity、velocity、release forecast、risk、issue aging;
152
152
  - `flow`、`swimlane`:流程、责任、分组、Port 和受控编辑。
153
+ - `architecture`:业务、数据或技术架构,使用明确的层、边界和关系。
154
+ - `mindmap`:想法层级,以 `parentId` 为事实来源,支持树形或放射布局。
153
155
 
154
156
  保留稳定的 record、node、edge、lane、group、port ID。业务编辑先返回 preview,确认后再 commit,并返回审计结果。
155
157
 
@@ -8,15 +8,45 @@
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"],
14
15
  "project": ["gantt", "timeline", "milestone", "burndown"],
15
- "diagram": ["flow", "swimlane"]
16
+ "diagram": ["flow", "swimlane", "architecture", "mindmap"]
16
17
  },
17
18
  "projectIntelligence": ["variance", "capacity", "release", "risk", "aging"],
18
- "chartModes": ["stacked", "percent-stacked", "donut", "mixed-line-column", "bin"],
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
+ },
32
+ "interactionDefaults": { "zoom": false, "pan": false, "brush": false, "drag": false, "edgeDrag": false, "portConnect": false, "editing": false },
33
+ "diagramEditing": {
34
+ "renderers": ["canvas", "svg"],
35
+ "edgeSelection": true,
36
+ "waypointDrag": true,
37
+ "segmentDrag": true,
38
+ "persistentWaypoints": true,
39
+ "enabledByDefault": false,
40
+ "activation": ["editing.enabled", "interaction.edgeDrag"]
41
+ },
42
+ "diagramCurves": {
43
+ "renderers": ["canvas", "svg"],
44
+ "type": "cubic-bezier",
45
+ "mindmapDefault": true,
46
+ "curveTension": { "minimum": 0.2, "maximum": 0.8, "default": 0.4 },
47
+ "obstacleFallback": "orthogonal",
48
+ "controlPointEditing": false
49
+ },
20
50
  "excluded": ["map", "3d"],
21
51
  "exports": ["png", "svg", "json"],
22
52
  "headless": {
@@ -65,8 +95,17 @@
65
95
  "version": "1.0",
66
96
  "scopes": ["global", "chart"],
67
97
  "persistence": ["memory", "localStorage", "adapter"],
98
+ "fields": ["theme.mode", "theme.preset", "theme.palette", "typography.scale", "density", "components.legend", "components.labels", "components.grid", "branding.enabled", "motion"],
68
99
  "agentAdjustable": true,
69
- "interactiveSettingsUI": true
100
+ "interactiveSettingsUI": true,
101
+ "precedence": ["defaults", "global", "chart", "temporary-agent-patch"],
102
+ "discovery": {
103
+ "capabilities": "getPreferenceCapabilities(chartType?, { locale? })",
104
+ "current": "chart.getPreferences()",
105
+ "validate": "validatePreferences(patch, { partial: true })",
106
+ "apply": "chart.setPreferences(patch, { scope, source: 'agent' })",
107
+ "verify": "chart.getState().preferences"
108
+ }
70
109
  },
71
110
  "styleSystem": {
72
111
  "modes": ["auto", "light", "dark", "contrast"],
@@ -2,27 +2,28 @@
2
2
  "version": "1.0",
3
3
  "source": "src/command.mjs#operationTypes",
4
4
  "commands": {
5
- "updateField": { "models": ["project-task", "timeline-event", "milestone", "burndown-sample", "flow-node", "flow-edge", "swimlane"], "previewRequired": true, "undoable": true },
6
- "updateRecord": { "models": ["project-task", "timeline-event", "milestone", "burndown-sample", "flow-node", "flow-edge", "swimlane"], "previewRequired": true, "undoable": true },
5
+ "updateField": { "models": ["project-task", "timeline-event", "milestone", "burndown-sample", "flow-node", "flow-edge", "swimlane", "architecture-node", "architecture-edge", "mindmap-node"], "previewRequired": true, "undoable": true },
6
+ "updateRecord": { "models": ["project-task", "timeline-event", "milestone", "burndown-sample", "flow-node", "flow-edge", "swimlane", "architecture-node", "architecture-edge", "mindmap-node"], "previewRequired": true, "undoable": true },
7
7
  "updateTask": { "models": ["project-task"], "previewRequired": true, "undoable": true },
8
8
  "shiftTask": { "models": ["project-task"], "required": ["taskId", "days"], "previewRequired": true, "undoable": true },
9
9
  "updateProgress": { "models": ["project-task"], "required": ["taskId", "progress"], "previewRequired": true, "undoable": true },
10
10
  "addDependency": { "models": ["project-task"], "required": ["taskId", "dependencyId"], "previewRequired": true, "undoable": true },
11
11
  "removeDependency": { "models": ["project-task"], "required": ["taskId", "dependencyId"], "previewRequired": true, "undoable": true },
12
12
  "updateMilestone": { "models": ["milestone"], "required": ["recordId"], "previewRequired": true, "undoable": true },
13
- "moveNode": { "models": ["flow-node"], "required": ["nodeId", "position"], "previewRequired": true, "undoable": true },
14
- "moveNodes": { "models": ["flow-node"], "required": ["nodeIds", "delta"], "previewRequired": true, "undoable": true },
13
+ "moveNode": { "models": ["flow-node", "architecture-node", "mindmap-node"], "required": ["nodeId", "position"], "previewRequired": true, "undoable": true },
14
+ "moveNodes": { "models": ["flow-node", "architecture-node", "mindmap-node"], "required": ["nodeIds", "delta"], "previewRequired": true, "undoable": true },
15
15
  "moveNodeToLane": { "models": ["flow-node"], "required": ["nodeId", "laneId"], "previewRequired": true, "undoable": true },
16
- "resizeNode": { "models": ["flow-node"], "required": ["nodeId", "size"], "previewRequired": true, "undoable": true },
17
- "alignNodes": { "models": ["flow-node"], "required": ["nodeIds", "alignment"], "previewRequired": true, "undoable": true },
18
- "snapNodes": { "models": ["flow-node"], "required": ["nodeIds"], "previewRequired": true, "undoable": true },
16
+ "resizeNode": { "models": ["flow-node", "architecture-node", "mindmap-node"], "required": ["nodeId", "size"], "previewRequired": true, "undoable": true },
17
+ "alignNodes": { "models": ["flow-node", "architecture-node", "mindmap-node"], "required": ["nodeIds", "alignment"], "previewRequired": true, "undoable": true },
18
+ "snapNodes": { "models": ["flow-node", "architecture-node", "mindmap-node"], "required": ["nodeIds"], "previewRequired": true, "undoable": true },
19
19
  "moveGroup": { "models": ["flow-node"], "required": ["groupId", "delta"], "previewRequired": true, "undoable": true },
20
20
  "resizeGroup": { "models": ["flow-node"], "required": ["groupId", "size"], "previewRequired": true, "undoable": true },
21
21
  "assignNodesToGroup": { "models": ["flow-node"], "required": ["nodeIds", "groupId"], "previewRequired": true, "confirmationRequired": true, "undoable": true },
22
22
  "duplicateGroup": { "models": ["flow-node", "flow-edge"], "required": ["groupId"], "previewRequired": true, "confirmationRequired": true, "undoable": true },
23
23
  "deleteGroup": { "models": ["flow-node", "flow-edge"], "required": ["groupId", "policy"], "previewRequired": true, "confirmationRequired": true, "undoable": true },
24
- "updateEdge": { "models": ["flow-edge"], "required": ["edgeId", "changes"], "previewRequired": true, "undoable": true },
25
- "addEdge": { "models": ["flow-edge"], "required": ["from", "to"], "previewRequired": true, "confirmationRequired": true, "undoable": true },
24
+ "updateEdge": { "models": ["flow-edge", "architecture-edge"], "required": ["edgeId", "changes"], "previewRequired": true, "undoable": true },
25
+ "removeEdge": { "models": ["flow-edge", "architecture-edge"], "required": ["edgeId"], "previewRequired": true, "confirmationRequired": true, "undoable": true },
26
+ "addEdge": { "models": ["flow-edge", "architecture-edge"], "required": ["from", "to"], "previewRequired": true, "confirmationRequired": true, "undoable": true },
26
27
  "toggleGroupCollapse": { "models": ["flow-node"], "required": ["groupId"], "previewRequired": true, "confirmationRequired": true, "undoable": true },
27
28
  "duplicateSelection": { "models": ["flow-node", "flow-edge"], "required": ["nodeIds"], "previewRequired": true, "confirmationRequired": true, "undoable": true },
28
29
  "pasteSelection": { "models": ["flow-node", "flow-edge"], "required": ["nodes"], "previewRequired": true, "confirmationRequired": true, "undoable": true }
@@ -7,7 +7,10 @@
7
7
  "milestone": { "key": "id", "required": ["id", "title", "date"], "editable": ["title", "date", "status"] },
8
8
  "burndown-sample": { "key": "id", "required": ["id", "date", "remaining"], "editable": ["date", "remaining", "scopeChange"] },
9
9
  "flow-node": { "key": "id", "required": ["id", "label"], "editable": ["label", "position", "size", "laneId", "description", "status"] },
10
- "flow-edge": { "key": "id", "required": ["id", "from", "to"], "editable": ["from", "to", "label"] },
11
- "swimlane": { "key": "id", "required": ["id", "label"], "editable": ["label"] }
10
+ "flow-edge": { "key": "id", "required": ["id", "from", "to"], "editable": ["from", "to", "fromPort", "toPort", "label", "status", "routing", "curveTension", "waypoints"] },
11
+ "swimlane": { "key": "id", "required": ["id", "label"], "editable": ["label"] },
12
+ "architecture-node": { "key": "id", "required": ["id", "label"], "editable": ["label", "layerId", "boundaryId", "position", "size", "description", "status"] },
13
+ "architecture-edge": { "key": "id", "required": ["id", "from", "to"], "editable": ["from", "to", "label", "relation", "routing", "curveTension", "waypoints", "status"] },
14
+ "mindmap-node": { "key": "id", "required": ["id", "label"], "editable": ["label", "parentId", "position", "size", "branch", "description", "status"] }
12
15
  }
13
16
  }
@@ -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.6",
3
+ "version": "2.0.8",
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.6/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.8/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,14 +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.
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/Gauge `category`/`value`, Heatmap `x`/`y`/`color`, and Radar `indicators[].field`. Start from `@taylorwong/ichartjs/recipes/minimal-specs` when a type is unfamiliar.
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`, 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`.
47
51
 
48
52
  Use `@taylorwong/ichartjs` for package imports. Use `examples/agent-workflow.mjs` as the executable baseline when working in the repository.
49
53
 
@@ -68,9 +72,15 @@ Route by requested output:
68
72
 
69
73
  - Never invent fields, units, dates, dependencies, calendar rules, domains, or forecast confidence.
70
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.
71
80
  - Avoid Pie for high-cardinality categories; prefer Bar for comparison.
72
81
  - Require explicit Radar domains when units differ.
73
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.
74
84
  - Use categorical, sequential, diverging, or status palettes by data semantics; do not invent arbitrary color sets or rely on color alone.
75
85
  - Surface theme contrast diagnostics and high-cardinality color warnings.
76
86
  - Do not generate Map or 3D Specs unless capabilities explicitly add them.