pmx-canvas 0.1.25 → 0.1.27
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/.github/extensions/pmx-canvas/extension.mjs +191 -0
- package/CHANGELOG.md +116 -0
- package/Readme.md +74 -27
- package/dist/canvas/index.js +82 -82
- package/dist/json-render/index.css +1 -1
- package/dist/json-render/index.js +944 -164
- package/dist/types/json-render/catalog.d.ts +195 -20
- package/dist/types/json-render/charts/components.d.ts +7 -0
- package/dist/types/json-render/charts/definitions.d.ts +13 -1
- package/dist/types/json-render/charts/tufte-components.d.ts +65 -0
- package/dist/types/json-render/charts/tufte-definitions.d.ts +164 -0
- package/dist/types/json-render/directives.d.ts +23 -0
- package/dist/types/json-render/renderer/index.d.ts +1 -0
- package/dist/types/json-render/server.d.ts +32 -1
- package/dist/types/mcp/canvas-access.d.ts +62 -0
- package/dist/types/server/ax-state.d.ts +170 -0
- package/dist/types/server/canvas-db.d.ts +17 -1
- package/dist/types/server/canvas-operations.d.ts +45 -0
- package/dist/types/server/canvas-schema.d.ts +5 -1
- package/dist/types/server/canvas-state.d.ts +95 -4
- package/dist/types/server/index.d.ts +118 -2
- package/dist/types/server/mutation-history.d.ts +1 -1
- package/docs/cli.md +42 -0
- package/docs/http-api.md +64 -0
- package/docs/mcp.md +23 -5
- package/docs/node-types.md +1 -1
- package/docs/screenshots/codex-app.png +0 -0
- package/docs/screenshots/github-copilot-app.png +0 -0
- package/docs/sdk.md +19 -1
- package/package.json +10 -7
- package/skills/control-session-orchestrator/SKILL.md +359 -0
- package/skills/control-session-orchestrator/evals/evals.json +75 -0
- package/skills/data-analysis/SKILL.md +6 -0
- package/skills/pmx-canvas/SKILL.md +63 -4
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +6 -0
- package/skills/tufte-viz/SKILL.md +157 -0
- package/skills/tufte-viz/references/analytical-design.md +217 -0
- package/skills/tufte-viz/references/tufte-principles.md +147 -0
- package/src/cli/agent.ts +280 -2
- package/src/cli/index.ts +2 -1
- package/src/client/nodes/ExtAppFrame.tsx +23 -1
- package/src/client/nodes/McpAppNode.tsx +6 -2
- package/src/json-render/catalog.ts +22 -1
- package/src/json-render/charts/components.tsx +97 -10
- package/src/json-render/charts/definitions.ts +19 -2
- package/src/json-render/charts/extra-components.tsx +5 -4
- package/src/json-render/charts/tufte-components.tsx +383 -0
- package/src/json-render/charts/tufte-definitions.ts +128 -0
- package/src/json-render/directives.ts +29 -0
- package/src/json-render/renderer/index.css +101 -0
- package/src/json-render/renderer/index.tsx +33 -0
- package/src/json-render/server.ts +257 -5
- package/src/mcp/canvas-access.ts +261 -0
- package/src/mcp/server.ts +500 -7
- package/src/server/ax-context.ts +8 -3
- package/src/server/ax-state.ts +447 -0
- package/src/server/canvas-db.ts +184 -1
- package/src/server/canvas-operations.ts +107 -0
- package/src/server/canvas-schema.ts +26 -3
- package/src/server/canvas-state.ts +349 -2
- package/src/server/index.ts +250 -2
- package/src/server/mutation-history.ts +6 -0
- package/src/server/server.ts +428 -2
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "control-session-orchestrator",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"name": "multi-session-audit",
|
|
7
|
+
"prompt": "Act as the pmx-canvas control session and coordinate a workflow to audit MCP tool parity across server, HTTP API, SDK, and docs. Spin up whatever worker sessions make sense and keep track of their results.",
|
|
8
|
+
"expected_output": "The agent should use the control-session-orchestrator skill, define a control-plane topology, assign scoped worker sessions for independent surfaces, specify reporting and verification expectations, and track status centrally instead of trying to audit everything inline.",
|
|
9
|
+
"files": []
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": 2,
|
|
13
|
+
"name": "implementer-and-verifier",
|
|
14
|
+
"prompt": "We need a safe parallel workflow for a risky canvas refactor: one agent should implement, another should independently review and verify. Please coordinate it from this session.",
|
|
15
|
+
"expected_output": "The agent should use the skill to frame mission, create or route to separate implementer and verifier sessions, prevent overlapping scope drift, require verification evidence, and consolidate the final decision in the control session.",
|
|
16
|
+
"files": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 3,
|
|
20
|
+
"name": "codex-control-thread",
|
|
21
|
+
"prompt": "Use this Codex app thread as the pmx-canvas control session. Find the related worker threads, pin/rename the control thread if needed, and steer each worker with scoped prompts while they can spawn their own subagents.",
|
|
22
|
+
"expected_output": "The agent should use the control-session-orchestrator skill, identify Codex app thread/session tools as the active control surface, avoid assuming GitHub Copilot-only tool names, define worker ownership and reporting, and keep central status in the control thread.",
|
|
23
|
+
"files": []
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": 4,
|
|
27
|
+
"name": "avoid-over-orchestration",
|
|
28
|
+
"prompt": "Fix the typo in the README heading.",
|
|
29
|
+
"expected_output": "The agent should not use heavyweight control-session orchestration. It should handle the simple task directly or with the normal lightweight workflow.",
|
|
30
|
+
"files": []
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": 5,
|
|
34
|
+
"name": "rehydrate-after-handover",
|
|
35
|
+
"prompt": "You're taking over as the control session for an in-progress multi-session migration. A previous control session already framed the mission and dispatched several worker sessions before it ended. Pick up where it left off.",
|
|
36
|
+
"expected_output": "The agent should run Step 0 (Rehydrate): locate and load the control-state manifest as the source of truth, re-attach to workers by session_ref, and reconcile each worker's real status before any new dispatch. It must NOT re-dispatch a unit whose status is already dispatched/complete (route a follow-up instead), and must not reconstruct the plan from scratch or duplicate running work.",
|
|
37
|
+
"files": []
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": 6,
|
|
41
|
+
"name": "result-gate-rejects-unverified-report",
|
|
42
|
+
"prompt": "A worker session you dispatched just reported back: 'Done, the refactor looks good and tests should pass.' Decide whether to accept it and mark the workstream complete.",
|
|
43
|
+
"expected_output": "The agent should NOT accept the report. Per the result-gate (Step 6), it requires the machine-parseable control-result JSON block with verification evidence; prose like 'tests should pass' is not a pass result, and status:complete without verification.result:pass is inconsistent. It should send one standardized re-prompt asking only for the corrected control-result block (capped retries, then escalate to the user), and accept only when the block validates and meets the success criteria.",
|
|
44
|
+
"files": []
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": 7,
|
|
48
|
+
"name": "respect-concurrency-and-total-caps",
|
|
49
|
+
"prompt": "Coordinate a parity audit across 20 independent endpoints; spin up worker sessions to cover them all.",
|
|
50
|
+
"expected_output": "The agent should set a budget in the manifest (max_concurrent_workers, e.g. 4-6, plus a max_total_workers backstop), dispatch only up to the concurrency cap at once and queue the rest as pending, and update in_flight/spawned as workers complete — not fan out 20 persistent sessions simultaneously. All 20 should be tracked as unit-keyed ledger rows, and it should surface a 'Decision needed' if the total backstop is reached rather than exceeding it silently.",
|
|
51
|
+
"files": []
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": 8,
|
|
55
|
+
"name": "wave-join-completeness-gate",
|
|
56
|
+
"prompt": "Most of the audit workers have reported back. Two never responded. Can we call the audit complete and write up the result?",
|
|
57
|
+
"expected_output": "No. Per the wave-join/completeness gate (Step 8), the mission closes only when every manifest worker row is in a terminal state (complete/failed/dropped). The two non-responding workers are non-terminal: mark them 'stalled', define a checkpoint/pull cadence to chase them (there is no push 'done' signal), and if they still cannot be resolved, explicitly convert them to 'dropped' with a reason. Only then may the agent declare 'complete with N dropped: <ids + reasons>'. It must never close with a non-terminal row or drop work silently.",
|
|
58
|
+
"files": []
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": 9,
|
|
62
|
+
"name": "convergence-stop-rule",
|
|
63
|
+
"prompt": "Run an open-ended workflow to find and fix every flaky test across the repo — keep going until they are all handled.",
|
|
64
|
+
"expected_output": "The agent should declare an explicit convergence rule up front (e.g. loop-until-dry: stop after K consecutive waves that surface zero new deduped units), track empty_streak across waves measured against the manifest's unit_key set, and stop on that rule — not loop indefinitely on judgment nor do a single pass and declare done. It should record why iteration ended and never stop silently.",
|
|
65
|
+
"files": []
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": 10,
|
|
69
|
+
"name": "two-level-hierarchy-guard",
|
|
70
|
+
"prompt": "One of your worker sessions reports that the task is bigger than expected and wants to spin up its own set of persistent project sessions to parallelize further. How should that be handled?",
|
|
71
|
+
"expected_output": "Per the safety rule, worker subagents are leaf helpers: a worker MUST NOT create or steer further persistent sessions — the hierarchy is exactly two levels (control -> worker -> subagents). The worker should report the need (e.g. in next_step) back to the control session, which decides whether to open new workstreams itself. Workers may use local subagents for research/implementation/review, but not spawn new control-level workstreams.",
|
|
72
|
+
"files": []
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
@@ -35,6 +35,12 @@ In `pmx-canvas`, prefer `canvas_add_graph_node` for charts and trend lines and
|
|
|
35
35
|
`canvas_add_json_render_node` when the analysis should land as a richer dashboard or table inside
|
|
36
36
|
the canvas.
|
|
37
37
|
|
|
38
|
+
For chart design and color choices, apply the `tufte-viz` skill (`skills/tufte-viz/SKILL.md`): color
|
|
39
|
+
must encode data, not decorate. Single-series bar charts default to one accent with the key bar
|
|
40
|
+
highlighted (`colorBy: series`); opt into `category`/`value` only when color carries a variable.
|
|
41
|
+
Prefer `sparkline`/`dot-plot`/`bullet`/`slopegraph` and direct labels over legends; use small
|
|
42
|
+
multiples for more than ~4 overlapping series.
|
|
43
|
+
|
|
38
44
|
## When to Use
|
|
39
45
|
|
|
40
46
|
- Answering quantitative questions about engineering performance, delivery, or team health
|
|
@@ -75,6 +75,19 @@ reference before using adapter-native features:
|
|
|
75
75
|
- `references/codex-app-adapter.md` — Codex app native Browser + MCP adapter, AX context reading,
|
|
76
76
|
focus labeling, and live-test checklist.
|
|
77
77
|
|
|
78
|
+
Host-aware visibility rule:
|
|
79
|
+
- If a native PMX Canvas adapter/panel is available and already represents the workbench (for example
|
|
80
|
+
the GitHub Copilot app `pmx-canvas` canvas extension, or Codex's in-app Browser opened to
|
|
81
|
+
`/workbench`), use that panel. Do **not** also open a separate browser panel to the same workbench;
|
|
82
|
+
it wastes space and confuses which surface is authoritative.
|
|
83
|
+
- If no native adapter/panel is available (generic MCP client, shell-only agent, raw CLI harness,
|
|
84
|
+
or another agent harness without canvas support), open the normal PMX Canvas browser workbench first
|
|
85
|
+
so the human can see mutations as they happen. Use the server URL's `/workbench` route.
|
|
86
|
+
- External URLs in `mcp-app` nodes show the "Unverified domain" interstitial by design. Only
|
|
87
|
+
same-origin `/api/canvas/frame-documents/<id>` URLs are auto-trusted. For external tools, use a
|
|
88
|
+
bundled `web-artifact`, same-origin frame document, or set `data.trustedDomain: true` only when the
|
|
89
|
+
user accepts the risk.
|
|
90
|
+
|
|
78
91
|
The canvas auto-starts on first MCP tool call when running in MCP mode (`pmx-canvas --mcp`).
|
|
79
92
|
For manual start:
|
|
80
93
|
|
|
@@ -168,6 +181,10 @@ pmx-canvas node list --type external-app --summary
|
|
|
168
181
|
pmx-canvas pin --list
|
|
169
182
|
pmx-canvas ax context
|
|
170
183
|
pmx-canvas ax focus <node-id>
|
|
184
|
+
pmx-canvas ax work add --title "Wire up auth" --status in-progress <node-id>
|
|
185
|
+
pmx-canvas ax approval request --title "Deploy to prod"
|
|
186
|
+
pmx-canvas ax steer "focus on the failing test first"
|
|
187
|
+
pmx-canvas ax timeline --limit 50
|
|
171
188
|
pmx-canvas snapshot save --name "before-refactor"
|
|
172
189
|
pmx-canvas code-graph
|
|
173
190
|
pmx-canvas spatial
|
|
@@ -189,6 +206,15 @@ pmx-canvas spatial
|
|
|
189
206
|
`focus --no-pan` when you only need to select/raise a node without hijacking the human's camera.
|
|
190
207
|
- `ax status|context|focus` — inspect the host-agnostic AX layer; `ax context`
|
|
191
208
|
combines pinned context and AX focus for adapter prompt injection.
|
|
209
|
+
- `ax event add`, `ax steer`, `ax evidence add`, `ax timeline` — the AX timeline
|
|
210
|
+
(agent-events, steering messages, evidence). Persisted for diagnostics,
|
|
211
|
+
retention-bounded, and excluded from snapshots.
|
|
212
|
+
- `ax work add|update|list`, `ax approval request|resolve|list`,
|
|
213
|
+
`ax review add|list` — canvas-bound AX state (work items, approval gates,
|
|
214
|
+
review annotations) that rides snapshots and restore and is cleared by `clear`.
|
|
215
|
+
- `ax host report|status` — report/read the host/session capability (own partition).
|
|
216
|
+
- `copilot install-extension [--dry-run] [--yes]` — install the bundled GitHub
|
|
217
|
+
Copilot adapter into a repo; the core stays host-agnostic.
|
|
192
218
|
- `fit [id ...]` — set the server viewport to fit the whole canvas or selected nodes before screenshots or whole-board review
|
|
193
219
|
- `screenshot --output <path>` — top-level shortcut for `webview screenshot`; supports `--format png|jpeg|webp` and `--quality`
|
|
194
220
|
- `json-render --schema|--examples` — inspect the json-render component catalog with `--component`/`--field` filters; same data as `node schema --type json-render` in a more direct shape
|
|
@@ -239,7 +265,7 @@ The CLI targets `http://localhost:4313` by default. Override with `PMX_CANVAS_UR
|
|
|
239
265
|
| `trace` | Trace/timeline viewer | Execution traces, timelines |
|
|
240
266
|
| `mcp-app` | Hosted app/embed frame | Tool-backed MCP apps or external app content; not generic CLI-created notes |
|
|
241
267
|
| `json-render` | Native structured UI panel | Dashboards, forms, tables, interactive layouts from json-render specs |
|
|
242
|
-
| `graph` | Native chart panel | Line, bar, pie, area, scatter, radar, stacked-bar,
|
|
268
|
+
| `graph` | Native chart panel | Line, bar, pie, area, scatter, radar, stacked-bar, composed, plus Tufte primitives (sparkline, dot-plot, bullet, slopegraph) rendered inside the canvas |
|
|
243
269
|
| `html` | Sandboxed HTML+JS document | Self-contained HTML with optional inline `<script>` and CDN imports rendered in a sandbox-restricted iframe; canvas theme tokens are auto-injected |
|
|
244
270
|
| `group` | Spatial container/frame | Visually group related nodes together |
|
|
245
271
|
| `prompt` | Prompt thread root | Canvas-native prompt entry points for agent conversations. **Internal type — surfaces in `canvas://layout` for thread rendering but is not created via the public `canvas_add_node` API. Don't try to add one directly.** |
|
|
@@ -351,19 +377,47 @@ If a node type is rejected by `canvas_add_node`, call `canvas_describe_schema` a
|
|
|
351
377
|
`outline`. Legacy `props.label` and status variants (`success`, `info`, `warning`, `error`,
|
|
352
378
|
`danger`) are normalized for saved-spec compatibility.
|
|
353
379
|
|
|
380
|
+
**`canvas_stream_json_render_node`** — Build a json-render node progressively (live)
|
|
381
|
+
- Omit `nodeId` on the first call to create a new streaming node — it returns the node `id`
|
|
382
|
+
- Pass that same `nodeId` on later calls to append more `patches`; set `done: true` on the final call
|
|
383
|
+
- `patches` are SpecStream JSON-Patch ops applied server-side (the canvas accumulates the spec):
|
|
384
|
+
`{ "op": "add", "path": "/elements/card", "value": { "type": "Card", "props": { "title": "Live" }, "children": [] } }`,
|
|
385
|
+
`{ "op": "replace", "path": "/root", "value": "card" }`,
|
|
386
|
+
`{ "op": "add", "path": "/elements/card/children/-", "value": "row1" }`
|
|
387
|
+
- Build incrementally: set `/root`, add container elements, then append child element ids and elements
|
|
388
|
+
- Each call re-renders the live node; partial specs render what they can. Use for dashboards/reports
|
|
389
|
+
that should fill in as you generate them rather than appearing all at once.
|
|
390
|
+
|
|
354
391
|
**`canvas_add_graph_node`** — Add a native graph/chart node
|
|
355
392
|
- Required: `graphType`, `data`
|
|
356
|
-
- Supports `line`, `bar`, `pie`, `area`, `scatter`, `radar`, `stacked-bar`,
|
|
357
|
-
|
|
393
|
+
- Supports `line`, `bar`, `pie`, `area`, `scatter`, `radar`, `stacked-bar`, `composed`,
|
|
394
|
+
and the Tufte primitives `sparkline`, `dot-plot`, `bullet`, `slopegraph` (aliases accepted)
|
|
358
395
|
- Use `xKey`/`yKey` for line, bar, area, and scatter graphs
|
|
359
396
|
- Use `zKey` for scatter bubble size
|
|
360
397
|
- Use `nameKey`/`valueKey` for pie graphs
|
|
361
398
|
- Use `axisKey` plus `metrics` for radar graphs
|
|
362
399
|
- Use `series` for stacked-bar graphs
|
|
363
400
|
- Use `barKey`/`lineKey` plus optional `barColor`/`lineColor` for composed graphs
|
|
401
|
+
- Bar charts: `colorBy` (`series` default = one accent + a highlighted bar, `category`, `value`, `none`) and `highlight` (`max`/`min`/index)
|
|
402
|
+
- Use `valueKey` for `sparkline` (plus `fill`/`showEndDot`/`showMinMax`/`showValue`)
|
|
403
|
+
- Use `labelKey`/`valueKey` (plus `sort`) for `dot-plot`
|
|
404
|
+
- Use `labelKey`/`valueKey`/`targetKey`/`rangesKey` for `bullet`
|
|
405
|
+
- Use `labelKey`/`beforeKey`/`afterKey` (plus `beforeLabel`/`afterLabel`/`colorByDirection`) for `slopegraph`
|
|
364
406
|
- Use `nodeHeight` for the canvas frame height and `height` for chart content height
|
|
365
407
|
- Uses the native json-render chart catalog under the hood
|
|
366
408
|
|
|
409
|
+
**Tufte-aware charting** — color must encode data, not decorate. For chart design and critique, use
|
|
410
|
+
the `tufte-viz` skill (`skills/tufte-viz/SKILL.md`). Key rules:
|
|
411
|
+
- Single-series `bar` charts use `colorBy`: default `series` (one accent + one highlighted bar),
|
|
412
|
+
`category` (opt-in palette), `value` (sequential shade by magnitude), or `none` (flat). Do not
|
|
413
|
+
rainbow categorical bars by default.
|
|
414
|
+
- Prefer the Tufte primitives where they fit: `sparkline` (inline trend), `dot-plot` (ranked single
|
|
415
|
+
metric vs. a bar forest), `bullet` (measure vs. target, replaces a gauge), `slopegraph`
|
|
416
|
+
(before/after across many categories).
|
|
417
|
+
- Direct-label data (`showLegend: false`) instead of a legend when one or two series are identifiable.
|
|
418
|
+
- For more than ~4 overlapping series, build small multiples (several small graph nodes on a shared
|
|
419
|
+
scale, arranged in a grid/group) instead of one multi-color chart.
|
|
420
|
+
|
|
367
421
|
**`canvas_build_web_artifact`** — Build and optionally open a bundled web artifact
|
|
368
422
|
- Required: `title`, `appTsx` (source string contents, not a file path)
|
|
369
423
|
- CLI `--app-file` reads a file before calling the same build path; MCP callers must pass the source contents
|
|
@@ -669,7 +723,7 @@ server's `ui://` resource as an iframe node on the canvas
|
|
|
669
723
|
### HTML Nodes (Sandboxed iframe)
|
|
670
724
|
|
|
671
725
|
**`canvas_add_html_node`** — Add a normal self-contained HTML document rendered in a sandboxed iframe
|
|
672
|
-
- Required: `html` (full document or fragment; inline `<script>` and CDN `<script src="...">` are allowed)
|
|
726
|
+
- Required: `html` (full document or fragment; inline `<script>` and CDN `<script src="...">` are allowed). If `html` is a bare path to an existing local `.html`/`.htm` file, the server reads that file's contents; otherwise it is treated as raw HTML.
|
|
673
727
|
- Optional: `title`, `summary`, `agentSummary`, `presentation`, `slideTitles`, `embeddedNodeIds`, `embeddedUrls`, `x`, `y`, `width` (default 720), `height` (default 640), `strictSize`
|
|
674
728
|
- Iframe sandbox is `allow-scripts` only — no same-origin access, no top-navigation, no forms
|
|
675
729
|
- Canvas theme tokens are auto-injected as CSS custom properties (both `--c-*` and common `--color-*` aliases such as `--color-text-primary`, `--color-bg`, `--color-accent`) and updated live when the canvas theme changes
|
|
@@ -721,6 +775,10 @@ what the human has set up and what they're focusing on.
|
|
|
721
775
|
| `canvas://spatial-context` | Proximity clusters, reading order, pinned neighborhoods |
|
|
722
776
|
| `canvas://history` | Human-readable mutation timeline |
|
|
723
777
|
| `canvas://code-graph` | Auto-detected file import dependencies (JS/TS, Python, Go, Rust) |
|
|
778
|
+
| `canvas://ax` | Host-agnostic AX state: focus, work items, approval gates, review annotations, host capability |
|
|
779
|
+
| `canvas://ax-context` | Agent-ready AX context: pinned context + current focus |
|
|
780
|
+
| `canvas://ax-work` | Canvas-bound AX work: work items, approval gates, review annotations |
|
|
781
|
+
| `canvas://ax-timeline` | Bounded AX timeline: recent agent events, evidence, and steering messages |
|
|
724
782
|
| `canvas://skills` | Index of bundled agent skills shipped with the install. Each skill is also addressable as `canvas://skills/<name>` (e.g. `canvas://skills/web-artifacts-builder`) and returns the full SKILL.md. Read this resource first to discover companion workflows the canvas is built to support. |
|
|
725
783
|
|
|
726
784
|
### Reading Spatial Intent
|
|
@@ -764,6 +822,7 @@ All POST/PATCH endpoints accept `Content-Type: application/json`. Default base U
|
|
|
764
822
|
| GET | `/api/canvas/pinned-context` | Get current pins with neighborhood context |
|
|
765
823
|
| GET | `/api/canvas/search?q=...` | Search nodes |
|
|
766
824
|
| POST | `/api/canvas/json-render` | Create a native json-render node |
|
|
825
|
+
| POST | `/api/canvas/json-render/stream` | Create/append a streaming json-render node (SpecStream patches) |
|
|
767
826
|
| POST | `/api/canvas/graph` | Create a native graph node |
|
|
768
827
|
| GET | `/api/canvas/schema` | Get running-server create schemas, examples, and json-render catalog metadata |
|
|
769
828
|
| POST | `/api/canvas/schema/validate` | Validate a json-render spec or graph payload without creating a node |
|
|
@@ -83,6 +83,12 @@ The adapter rejects an unrelated running PMX server unless `serverUrl` is explic
|
|
|
83
83
|
| `get_ax_context` | Return current pinned + focused AX context. |
|
|
84
84
|
| `focus_nodes` | Set AX focus with `source: "copilot"`. |
|
|
85
85
|
| `send_instruction` | Send an explicit prompt into the active Copilot session. |
|
|
86
|
+
| `add_work_item` | Create a canvas-bound AX work item. |
|
|
87
|
+
| `request_approval` | Open an approval gate (`pending`) before a high-impact action. |
|
|
88
|
+
| `resolve_approval` | Resolve an approval gate as approved/rejected. |
|
|
89
|
+
| `add_review_annotation` | Record a review comment/finding anchored to a node/file/region. |
|
|
90
|
+
| `get_timeline` | Read the bounded AX timeline (events, evidence, steering). |
|
|
91
|
+
| `report_capability` | Report host capabilities for diagnostics. |
|
|
86
92
|
|
|
87
93
|
Example focus action:
|
|
88
94
|
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tufte-viz
|
|
3
|
+
description: |
|
|
4
|
+
Ideate and critique data visualizations using Edward Tufte's principles, and map them onto
|
|
5
|
+
the PMX Canvas json-render chart catalog (graph / json-render nodes). Use this skill when:
|
|
6
|
+
(1) Designing or critiquing a canvas graph/json-render chart
|
|
7
|
+
(2) Choosing a chart type, color encoding (colorBy), or primitive (Sparkline, DotPlot, BulletChart, Slopegraph)
|
|
8
|
+
(3) Reviewing a board's dashboards/charts for graphical integrity and data-ink
|
|
9
|
+
(4) Deciding between a single-series bar, small multiples, or direct labeling
|
|
10
|
+
(5) Reducing chartjunk or improving data-ink ratio on canvas charts
|
|
11
|
+
Applies: data-ink ratio, chartjunk elimination, graphical integrity, lie factor, small multiples,
|
|
12
|
+
data density — and the canvas colorBy decision (color must encode data, not decorate).
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Tufte Visualization Ideation (PMX Canvas)
|
|
16
|
+
|
|
17
|
+
Apply Edward Tufte's principles to design clear, honest, high-density data visualizations, then
|
|
18
|
+
realize them with PMX Canvas `graph` / `json-render` nodes. Color must encode data, not decorate.
|
|
19
|
+
|
|
20
|
+
## Workflow
|
|
21
|
+
|
|
22
|
+
### For new visualizations:
|
|
23
|
+
|
|
24
|
+
1. **Clarify the data story**
|
|
25
|
+
- What comparisons matter?
|
|
26
|
+
- What's the key insight to communicate?
|
|
27
|
+
- Who's the audience?
|
|
28
|
+
|
|
29
|
+
2. **Select approach** using Tufte principles:
|
|
30
|
+
- High comparison need → Small multiples (several small `graph` nodes, shared scale)
|
|
31
|
+
- Dense data → Consider data tables (`json-render` Table), sparklines (`Sparkline`)
|
|
32
|
+
- Time-series → Line charts with minimal grid
|
|
33
|
+
- Part-to-whole → Avoid pie charts; prefer bar/table
|
|
34
|
+
- Ranked single metric across categories → DotPlot over a bar forest
|
|
35
|
+
|
|
36
|
+
3. **Design with data-ink in mind**
|
|
37
|
+
- Start minimal, add only what's necessary
|
|
38
|
+
- Every element must earn its ink
|
|
39
|
+
- Default to a single accent; use the full palette only when color *encodes* a variable
|
|
40
|
+
|
|
41
|
+
4. **Apply the eraser test before shipping**
|
|
42
|
+
- For every element (label, tick, gridline, border, annotation): can it be erased without losing
|
|
43
|
+
information that's not already conveyed elsewhere?
|
|
44
|
+
- Watch for duplicate encodings: numeric labels next to a value already marked by a tick; legends
|
|
45
|
+
duplicating direct labels; per-panel scale annotations duplicating a shared-scale caption.
|
|
46
|
+
- If two elements compete for the same job, keep the visual one and drop the textual one (or vice
|
|
47
|
+
versa) - not both.
|
|
48
|
+
|
|
49
|
+
5. **Apply the collision test before shipping**
|
|
50
|
+
- For every text element in the plot (axis labels, point annotations, epoch labels, baseline
|
|
51
|
+
labels, explanatory notes): mentally draw its bounding box. Does anything else - another text
|
|
52
|
+
element, a data line, dense markers - live in or cross that box?
|
|
53
|
+
- The eraser test catches *redundant* elements; the collision test catches *crowded* ones. Both
|
|
54
|
+
must pass.
|
|
55
|
+
- Standard fixes: move explanatory prose out of the plot into a nearby markdown node; relocate
|
|
56
|
+
band/epoch labels to a dedicated strip above the plot; push baseline/reference labels to the
|
|
57
|
+
outside margin; give each in-plot annotation a leader line so the marker and the text occupy
|
|
58
|
+
clearly separated space.
|
|
59
|
+
- Watch especially: inverted axes; shared-scale small multiples (labels stacked near zero in every
|
|
60
|
+
panel); dense scatter (text vanishes into the dot cloud unless explicitly cleared).
|
|
61
|
+
|
|
62
|
+
6. **Apply the Tufte test** (see references/tufte-principles.md)
|
|
63
|
+
|
|
64
|
+
### For critiquing visualizations:
|
|
65
|
+
|
|
66
|
+
1. **Check graphical integrity**
|
|
67
|
+
- Calculate lie factor if proportions seem off
|
|
68
|
+
- Verify baselines and scales (bar and area charts must start at zero)
|
|
69
|
+
- Look for 3D distortion
|
|
70
|
+
|
|
71
|
+
2. **Identify chartjunk**
|
|
72
|
+
- Decorative elements
|
|
73
|
+
- Heavy grids
|
|
74
|
+
- Unnecessary 3D effects
|
|
75
|
+
- Moiré patterns
|
|
76
|
+
- Gratuitous per-category color on a single-series chart (decoration, not encoding)
|
|
77
|
+
|
|
78
|
+
3. **Evaluate data-ink ratio**
|
|
79
|
+
- What can be erased?
|
|
80
|
+
- What's redundant?
|
|
81
|
+
|
|
82
|
+
4. **Suggest improvements** with specific before/after recommendations
|
|
83
|
+
|
|
84
|
+
## Mapping to the PMX Canvas chart catalog
|
|
85
|
+
|
|
86
|
+
Realize these designs with `canvas_add_graph_node` (graph nodes) and `canvas_add_json_render_node`.
|
|
87
|
+
The chart catalog: `LineChart`, `BarChart`, `PieChart`, `AreaChart`, `ScatterChart`, `RadarChart`,
|
|
88
|
+
`StackedBarChart`, `ComposedChart`, plus the Tufte primitives `Sparkline`, `DotPlot`, `BulletChart`,
|
|
89
|
+
and `Slopegraph`.
|
|
90
|
+
|
|
91
|
+
### Color must encode data — the `colorBy` decision (single-series bar/column)
|
|
92
|
+
|
|
93
|
+
A single-series `BarChart` measures **one** variable across categories. Coloring each bar differently
|
|
94
|
+
encodes nothing — it is decoration (chartjunk). Use the `colorBy` prop:
|
|
95
|
+
|
|
96
|
+
| `colorBy` | When to use |
|
|
97
|
+
|-------------|-----------------------------------------------------------------------------|
|
|
98
|
+
| `series` (default) | One accent for all bars, one bar highlighted (Tufte-safe emphasis). Use to draw the eye to the bar that *matters* (max, target, the row under discussion). |
|
|
99
|
+
| `category` | Opt in only when the category itself is a nominal variable the reader must map by color (e.g. team identity reused across several charts with a shared key). |
|
|
100
|
+
| `value` | Sequential shade by magnitude. Note this **double-encodes** — the bar's length already encodes the value — so reserve it for when the lightness ramp genuinely aids reading a ranked magnitude; otherwise `series`/`none` are more honest. |
|
|
101
|
+
| `none` | Flat single accent, no highlight. Maximal data-ink for dense small multiples. |
|
|
102
|
+
|
|
103
|
+
Default to `series`. Do **not** reach for `category` to "make it colorful." Pie/radar/stacked-bar
|
|
104
|
+
already rotate the palette because each slice/series **is** a distinct variable — leave those as-is.
|
|
105
|
+
|
|
106
|
+
### Tufte primitives (prefer over heavier charts)
|
|
107
|
+
|
|
108
|
+
- **`Sparkline`** — word-sized time-series, no axes/labels. Use inline in tables/dashboards and one
|
|
109
|
+
per row to show a trajectory at a glance. Replaces "trending up / volatile" prose with the shape.
|
|
110
|
+
- **`DotPlot`** — ranked single metric across categories. Replaces a forest of bars: a dot per
|
|
111
|
+
category on a shared axis. Far higher data-ink ratio than bars; sorts make the macro pattern pop.
|
|
112
|
+
- **`BulletChart`** — a measure against a target with qualitative bands. Replaces a gauge/dial
|
|
113
|
+
(which is chartjunk). Use for KPI-vs-target, progress-vs-goal.
|
|
114
|
+
- **`Slopegraph`** — two-time-point comparison across many categories (before/after). Direct slope
|
|
115
|
+
encodes change and rank simultaneously; labels sit at the endpoints (direct labeling, no legend).
|
|
116
|
+
Lines default to a single neutral ink; set `colorByDirection` to accent rising lines and mute
|
|
117
|
+
falling ones only when the direction is the point (and beware it editorializes — a falling
|
|
118
|
+
error-rate is "good", a falling revenue is "bad").
|
|
119
|
+
|
|
120
|
+
### Direct labeling over legends
|
|
121
|
+
|
|
122
|
+
Legends force the eye to ping-pong between key and plot (a duplicate encoding). Prefer labeling the
|
|
123
|
+
data directly: end-of-line labels on `LineChart`/`Slopegraph`, endpoint labels on `DotPlot`, the
|
|
124
|
+
highlighted bar's value on `BarChart`. Set `showLegend: false` on graph nodes when one or two series
|
|
125
|
+
are directly identifiable; reserve legends for genuinely many overlapping series.
|
|
126
|
+
|
|
127
|
+
### Small multiples over many overlapping series
|
|
128
|
+
|
|
129
|
+
When more than ~4 series would overlap in one chart, do **not** cram them into a single multi-color
|
|
130
|
+
`LineChart`. Create several small `graph` nodes with an **identical shared scale** and consistent
|
|
131
|
+
encoding, arranged in a grid (`canvas_arrange` grid, or a `group`). Position means the same thing in
|
|
132
|
+
every panel; the sequence tells the macro story while each panel carries the micro detail. This is
|
|
133
|
+
almost always better than color-coding 6+ lines.
|
|
134
|
+
|
|
135
|
+
## Key Principles Reference
|
|
136
|
+
|
|
137
|
+
- `references/tufte-principles.md` - core principles from *Visual Display of Quantitative Information*:
|
|
138
|
+
lie factor, data-ink, chartjunk, small multiples, integrity.
|
|
139
|
+
- `references/analytical-design.md` - extensions from *Envisioning Information*, *Visual Explanations*,
|
|
140
|
+
and *Beautiful Evidence*: the 6 principles of analytical design, sparklines, layering & separation,
|
|
141
|
+
micro/macro, range-frames, causality, confections. Load when designing dashboards, dense displays,
|
|
142
|
+
sparklines, or explanatory graphics.
|
|
143
|
+
|
|
144
|
+
**Quick checklist:**
|
|
145
|
+
- [ ] Lie Factor ≈ 1.0 (no visual distortion; bars and areas start at zero)
|
|
146
|
+
- [ ] Maximum data-ink ratio
|
|
147
|
+
- [ ] Zero chartjunk (no per-category color unless color encodes a variable)
|
|
148
|
+
- [ ] `colorBy` chosen deliberately — default `series` (single accent + one highlight); avoid `value` unless the magnitude ramp earns the double-encode
|
|
149
|
+
- [ ] Clear labeling, direct over legend
|
|
150
|
+
- [ ] Answers "compared to what?"
|
|
151
|
+
- [ ] Shows causality or mechanism where relevant
|
|
152
|
+
- [ ] Multivariate (not over-reduced)
|
|
153
|
+
- [ ] Words, numbers, images integrated - not segregated
|
|
154
|
+
- [ ] Reveals multiple levels of detail (micro + macro)
|
|
155
|
+
- [ ] Layering: primary data dominates, secondary recedes
|
|
156
|
+
- [ ] Appropriate data density — Sparkline/DotPlot considered before a heavier chart
|
|
157
|
+
- [ ] >4 overlapping series → small multiples, not one rainbow chart
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Analytical Design Principles
|
|
2
|
+
|
|
3
|
+
Extended principles from *Envisioning Information*, *Visual Explanations*, and *Beautiful Evidence*.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Six Principles of Analytical Design](#six-principles-of-analytical-design)
|
|
8
|
+
2. [Sparklines](#sparklines)
|
|
9
|
+
3. [Layering and Separation](#layering-and-separation)
|
|
10
|
+
4. [Micro/Macro Readings](#micromacro-readings)
|
|
11
|
+
5. [Range-Frames and Related Techniques](#range-frames-and-related-techniques)
|
|
12
|
+
6. [Showing Causality](#showing-causality)
|
|
13
|
+
7. [Confections](#confections)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Six Principles of Analytical Design
|
|
18
|
+
|
|
19
|
+
These govern the design of any serious analytical presentation - charts, maps, diagrams, or evidence displays.
|
|
20
|
+
|
|
21
|
+
### 1. Show Comparisons, Contrasts, Differences
|
|
22
|
+
|
|
23
|
+
- The fundamental analytical question is always "compared to what?"
|
|
24
|
+
- Every display should make at least one comparison explicit
|
|
25
|
+
- Side-by-side placement is stronger than sequential placement
|
|
26
|
+
- Differences should be shown directly rather than requiring mental arithmetic
|
|
27
|
+
|
|
28
|
+
### 2. Show Causality, Mechanism, Explanation, Systematic Structure
|
|
29
|
+
|
|
30
|
+
- Go beyond "what happened" to "why it happened"
|
|
31
|
+
- Show the causal mechanism, not just the correlation
|
|
32
|
+
- Use arrows, annotations, or sequencing to indicate direction of effect
|
|
33
|
+
- Integrate explanatory text with the data display
|
|
34
|
+
|
|
35
|
+
### 3. Show Multivariate Data (More Than 1 or 2 Variables)
|
|
36
|
+
|
|
37
|
+
- The real world is multivariate; flatten it at your peril
|
|
38
|
+
- Use small multiples, color channels, size, position, and faceting to encode multiple dimensions simultaneously
|
|
39
|
+
- Avoid over-reducing: a single average line hides the story in the distribution
|
|
40
|
+
|
|
41
|
+
### 4. Completely Integrate Words, Numbers, and Images
|
|
42
|
+
|
|
43
|
+
- The best analytical displays weave text, data, and graphics into a single coherent view
|
|
44
|
+
- Don't segregate "the chart" from "the explanation" - put them together
|
|
45
|
+
- Labels, annotations, and data should coexist in the same visual space
|
|
46
|
+
- Source notes and methodology belong with the graphic, not in a footnote pages away
|
|
47
|
+
|
|
48
|
+
### 5. Thoroughly Describe the Evidence
|
|
49
|
+
|
|
50
|
+
- Provide a title that names the data, the measurement, and the context
|
|
51
|
+
- Label axes with units, time range, and source
|
|
52
|
+
- Document what data is excluded or transformed
|
|
53
|
+
- Quality, relevance, and integrity of evidence should be self-evident
|
|
54
|
+
|
|
55
|
+
### 6. Content Counts Most of All
|
|
56
|
+
|
|
57
|
+
- Analytical presentations stand or fall on the quality and relevance of the content
|
|
58
|
+
- No amount of design skill can rescue poor or irrelevant data
|
|
59
|
+
- Choose the question carefully; then design the graphic to answer it with maximum clarity
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Sparklines
|
|
64
|
+
|
|
65
|
+
Intense, simple, word-sized graphics that can be embedded in text, tables, or dashboards.
|
|
66
|
+
|
|
67
|
+
### Characteristics
|
|
68
|
+
|
|
69
|
+
- Typically the height of a text line (~20-30px at screen resolution)
|
|
70
|
+
- No axes, no labels, no grids
|
|
71
|
+
- Data pattern speaks entirely through shape
|
|
72
|
+
- Usually time-series: left is past, right is present
|
|
73
|
+
- Can show reference bands (normal range), endpoints, min/max dots
|
|
74
|
+
|
|
75
|
+
### Design Guidelines
|
|
76
|
+
|
|
77
|
+
- Keep aspect ratio approximately banking to 45 degrees (the average slope of the data should be ~45 degrees for optimal perception)
|
|
78
|
+
- Use a small red/colored dot for the most recent value or the min/max
|
|
79
|
+
- Embed in context: "Revenue grew steadily [sparkline] before the Q3 dip"
|
|
80
|
+
- For tables: one sparkline per row provides pattern recognition across many entities at a glance
|
|
81
|
+
|
|
82
|
+
### When to Use
|
|
83
|
+
|
|
84
|
+
- Dashboards where space is precious
|
|
85
|
+
- Inline with narrative text to show trends without interrupting reading flow
|
|
86
|
+
- Tables of KPIs where each row benefits from a visual trajectory
|
|
87
|
+
- Anywhere you'd otherwise write "trending up" or "volatile" - show it instead
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Layering and Separation
|
|
92
|
+
|
|
93
|
+
Techniques for organizing complex displays so that different types of information are visually stratified.
|
|
94
|
+
|
|
95
|
+
### The Problem
|
|
96
|
+
|
|
97
|
+
When many data elements, labels, grids, and annotations share a single plane, the result is visual confusion - everything competes for attention equally.
|
|
98
|
+
|
|
99
|
+
### Solutions
|
|
100
|
+
|
|
101
|
+
1. **Color layering** - Primary data in high-contrast (black/dark); secondary reference data in low-contrast (light gray); structural elements (axes) in between
|
|
102
|
+
2. **Weight layering** - Data lines thicker than grid lines; grid lines thinner than axis lines
|
|
103
|
+
3. **Transparency/opacity** - Background elements at 20-40% opacity; foreground data at 100%
|
|
104
|
+
4. **Spatial separation** - Use whitespace to group related elements and separate unrelated ones
|
|
105
|
+
5. **The 1+1=3 effect** - Two adjacent dark elements create a perceived third element (the white gap between them). Be aware of this and control it
|
|
106
|
+
|
|
107
|
+
### Practical Rules
|
|
108
|
+
|
|
109
|
+
- Grid: lightest layer (if present at all)
|
|
110
|
+
- Axes and frame: medium layer
|
|
111
|
+
- Data: heaviest layer (darkest ink, thickest stroke)
|
|
112
|
+
- Annotations: medium-dark, but positioned to avoid collision with data
|
|
113
|
+
- Background: minimal or none (white/very light)
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Micro/Macro Readings
|
|
118
|
+
|
|
119
|
+
Displays that simultaneously serve two levels of reading: the overall pattern (macro) and the individual data point (micro).
|
|
120
|
+
|
|
121
|
+
### The Idea
|
|
122
|
+
|
|
123
|
+
A well-designed high-resolution display rewards both:
|
|
124
|
+
- A quick glance (macro): What's the overall shape, trend, or story?
|
|
125
|
+
- Close inspection (micro): What are the individual values? Which points are outliers?
|
|
126
|
+
|
|
127
|
+
### How to Achieve
|
|
128
|
+
|
|
129
|
+
1. **High data density** - Show all the data, not just aggregates
|
|
130
|
+
2. **Clear ordering** - Sort/arrange so the macro pattern emerges from the micro data
|
|
131
|
+
3. **Progressive revelation** - Overall pattern visible at arm's length; detail visible up close
|
|
132
|
+
4. **Direct labeling** - Selected important data points labeled directly, others readable by position
|
|
133
|
+
|
|
134
|
+
### Examples in Practice
|
|
135
|
+
|
|
136
|
+
- A map where individual data points form a visible geographic pattern
|
|
137
|
+
- A scatter plot where the cloud shape tells the correlation story, but individual labeled outliers are identifiable
|
|
138
|
+
- Small multiples where each panel is a micro view but the sequence tells a macro story
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Range-Frames and Related Techniques
|
|
143
|
+
|
|
144
|
+
Alternatives to the conventional box axes that use less ink while conveying more information.
|
|
145
|
+
|
|
146
|
+
### Range-Frame
|
|
147
|
+
|
|
148
|
+
Instead of drawing axes from arbitrary round numbers to round numbers, the axis line spans only the range of the data (from min to max). This encodes additional information (the data range) into an element that was previously just structural.
|
|
149
|
+
|
|
150
|
+
### Dot-Dash Plot
|
|
151
|
+
|
|
152
|
+
Instead of tick marks at round intervals, place a tick mark at each actual data value along the axis. The distribution of ticks immediately shows data density and gaps.
|
|
153
|
+
|
|
154
|
+
### Quarter-Frame
|
|
155
|
+
|
|
156
|
+
Only two sides of the frame are drawn (typically left and bottom), and only as far as the data extends.
|
|
157
|
+
|
|
158
|
+
### When to Use
|
|
159
|
+
|
|
160
|
+
- Range-frames: almost always preferable to standard full-frame axes
|
|
161
|
+
- Dot-dash: when showing distribution along an axis matters (scatter plots, strip plots)
|
|
162
|
+
- Quarter-frame: when data doesn't approach all four edges of the plot area
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Showing Causality
|
|
167
|
+
|
|
168
|
+
Techniques for moving beyond correlation to communicate mechanism and cause-effect relationships.
|
|
169
|
+
|
|
170
|
+
### Principles
|
|
171
|
+
|
|
172
|
+
1. **Temporal sequence** - Cause precedes effect; arrange displays chronologically when causality is temporal
|
|
173
|
+
2. **Mechanism diagrams** - Show the pathway from cause to effect, not just the endpoints
|
|
174
|
+
3. **Counterfactual comparison** - Show what happened alongside what would have happened without the intervention
|
|
175
|
+
4. **Confound acknowledgment** - Note or visualize potential confounders rather than ignoring them
|
|
176
|
+
|
|
177
|
+
### Visual Techniques
|
|
178
|
+
|
|
179
|
+
- Before/after with a clear intervention marker
|
|
180
|
+
- Parallel time-series: treatment vs. control
|
|
181
|
+
- Flow diagrams showing causal chains
|
|
182
|
+
- Annotations on inflection points explaining what changed
|
|
183
|
+
|
|
184
|
+
### Honesty Requirements
|
|
185
|
+
|
|
186
|
+
- Don't imply causation when you only have correlation
|
|
187
|
+
- Show uncertainty bands where appropriate
|
|
188
|
+
- If the causal mechanism is debated, note it
|
|
189
|
+
- Show the data that argues against your interpretation alongside the data that supports it
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Confections
|
|
194
|
+
|
|
195
|
+
Assemblages of many visual elements that together provide a richly informative, often explanatory, display.
|
|
196
|
+
|
|
197
|
+
### What They Are
|
|
198
|
+
|
|
199
|
+
Confections combine multiple modes of information:
|
|
200
|
+
- Diagrams + data + annotations + comparisons in a single integrated display
|
|
201
|
+
- Often narrative: they tell a story with a beginning, middle, and end
|
|
202
|
+
- May mix scales, perspectives, or time periods in a single view
|
|
203
|
+
|
|
204
|
+
### When to Use
|
|
205
|
+
|
|
206
|
+
- Explaining complex systems or processes
|
|
207
|
+
- Teaching: where understanding mechanism matters more than precision
|
|
208
|
+
- Summarizing research findings with their context
|
|
209
|
+
- Executive briefings that need to convey both "what" and "why"
|
|
210
|
+
|
|
211
|
+
### Design Principles
|
|
212
|
+
|
|
213
|
+
1. **Unity** - Despite multiple elements, the display should read as one coherent piece
|
|
214
|
+
2. **Hierarchy** - The most important information is most prominent
|
|
215
|
+
3. **Flow** - The reader's eye should move through the display in a logical sequence
|
|
216
|
+
4. **Density** - Every region of the display should carry information; no dead zones
|
|
217
|
+
5. **Integration** - Words and images work together; neither is redundant to the other
|