Skip to content

feat: sankey diagrams — branching flow ribbons - #198

Merged
ethenotethan merged 2 commits into
mainfrom
feat/sankey-diagram
Jul 22, 2026
Merged

feat: sankey diagrams — branching flow ribbons#198
ethenotethan merged 2 commits into
mainfrom
feat/sankey-diagram

Conversation

@ethenotethan

Copy link
Copy Markdown
Contributor

What

The other half of the flow-shaped gap from the chart-type audit — waterfall (#196) covered sequential where-did-it-go; sankey covers branching flows: budget allocation, token/traffic routing, funnels.

```sankey
{"title": "Q2 Budget", "links": [
  {"from": "Revenue", "to": "Engineering", "value": 400},
  {"from": "Revenue", "to": "Marketing", "value": 150},
  {"from": "Engineering", "to": "Salaries", "value": 320}
]}
```
  • Nodes implicit from links — the lowest-friction contract for a model to emit. Optional nodes array adds groups for coloring. Self-loops and non-positive values drop at parse.
  • Pure layout engine (SankeyLayout, unit-tested): cycle-safe longest-path column assignment (bounded passes — a cyclic link renders adjacent instead of hanging), node bars sized by throughput on a global scale so heights compare across columns, ribbons stacked without overlap down each node edge.
  • Rendering: Canvas cubic ribbons (thickness ∝ value) under node bars, native-text labels (last column leans left). Click a node → its flows light and a summary shows in/out totals per link, with an unbalanced-flow Δ warning when outflow ≠ inflow.
  • Routes as a chat fence, captures as a living artifact (renders in the Artifacts pane + iOS sheet), prompt documents the contract. PDF-safe by construction (Canvas + text, no representables).
  • No collision with mermaid's sankey (that arrives as ```mermaid/sankey-beta and keeps its route).

Testing

3 suites-worth: parse hygiene (self-loops/zero/negative dropped), layout invariants (topological columns, global-scale proportional spans, no-overlap ribbon stacking), cycle termination. Both targets build, swiftlint --strict clean.

Built in an isolated worktree off main.

🤖 Generated with Claude Code

ethenotethan added a commit to researchoors/hermes-agent that referenced this pull request Jul 22, 2026
HermesNative renders ```sankey (researchoors/hermes-native#198) and
```timeline (researchoors/hermes-native#199) blocks natively and
captures id-bearing ones as living artifacts. Both kinds replace
wholesale on merge (no per-kind merge needed), so only the agent
tool's allowlist and schema enum need to know about them — the store
already handles unknown kinds by replacement.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
ethenotethan and others added 2 commits July 23, 2026 03:07
The other half of the flow-shaped gap (waterfall covered sequential
where-did-it-go; sankey covers BRANCHING flows): budget allocation,
token/traffic routing, funnels, as a native ```sankey fence.

- SankeySpec: nodes implicit from links [{from, to, value}]; optional
  nodes array adds groups for coloring. Self-loops and non-positive
  values drop at parse.
- SankeyLayout (pure, tested): cycle-safe longest-path column
  assignment (bounded passes — a cyclic link renders adjacent instead
  of hanging), node bars sized by throughput on a GLOBAL scale so
  heights compare across columns, ribbons stacked without overlap
  down each node edge in link order.
- SankeyBlockView: Canvas ribbons (cubic curves, thickness ∝ value)
  under node bars, labels as native text (last column leans left).
  Click a node → its flows light, rest dim, and a summary shows
  in/out totals per link plus an unbalanced-flow Δ warning. Colors
  from the shared categorical palette by group (or column).
- Fence routes in chat, captures as a living artifact, renders in the
  Artifacts pane and iOS sheet; formatting prompt documents the
  contract. PDF-safe by construction (no representables/scroll views).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…outing

```sankey collides with mermaid's sankey diagram language (it's in
diagramLanguages). Route by content instead: JSON objects go to the
native SankeyBlockView, CSV lines fall through to mermaid. Also wire
the PDF exporter — sankey blocks render live (Canvas + native text,
no representables) instead of being pre-rendered as mermaid images.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ethenotethan
ethenotethan force-pushed the feat/sankey-diagram branch from 6bad450 to f3a965d Compare July 22, 2026 20:13
@ethenotethan
ethenotethan merged commit 95b707d into main Jul 22, 2026
4 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant