microsoft / microsoft/flint-chart
Rank semantic type: Bar Table encodes the ordinal as a bar length, inverting the ranking (Bar Chart handles it correctly)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 4.2k
- Forks
- 235
- Avg merge
- 17h 45m
- Merged PRs (30d)
- 11
Description
What happens
The Rank semantic type's documented behaviour is honoured by the Bar Chart template but ignored by Bar Table, which encodes the ordinal as a bar length and a sequential colour ramp. The result is a chart that reads as the inverse of the data: rank 1 gets the shortest, palest bar and the last-placed item gets the longest, darkest one.
The agent skill documents (flint://agent-skill):
Rank→ reversed axis (1 on top), discrete color
Neither template emits a reverse, and Bar Table additionally applies a sequential colour scale rather than a discrete one.
validate_chart returns valid: true with zero warnings in both cases, so nothing in the toolchain flags it.
Reproduction
flint-chart-mcp@0.4.1, backend vegalite.
{
"data": { "values": [
{ "Engine": "Inworld TTS-2", "Rank": 1 },
{ "Engine": "xAI leo", "Rank": 2 },
{ "Engine": "Kokoro am_michael", "Rank": 3 },
{ "Engine": "Gemini", "Rank": 4 },
{ "Engine": "Inworld 1.5-max", "Rank": 5 }
]},
"semantic_types": { "Engine": "Name", "Rank": "Rank" },
"chart_spec": {
"chartType": "Bar Table",
"encodings": { "y": { "field": "Engine" }, "x": { "field": "Rank" } },
"baseSize": { "width": 560, "height": 280 }
}
}
Swapping chartType to "Bar Chart" with everything else identical produces a sensible ordinal rendering — equal-sized marks positioned by rank, correct row order, no magnitude encoding. That contrast is what makes this look like a template gap rather than intended behaviour.
Inspecting the compiled Vega-Lite:
sort |
reverse |
|
|---|---|---|
| Bar Table | null |
absent |
| Bar Chart | null, "ascending" |
absent |
Why it matters
An ordinal is not a magnitude — "how much better is 1st than 2nd" has no answer, so any length encoding of it is unfounded. This is the failure mode that is hardest to catch downstream, because the output is well-formed, passes validation, and is confidently wrong in a direction a reader will not question.
Suggested fix
Either honour the documented Rank behaviour in the Bar Table template (discrete colour, no length encoding, 1 first), or have validate_chart warn when an ordinal semantic type (Rank, and arguably ID) is bound to a length-encoding channel.
A validator warning would be the more valuable of the two, since it generalises to any template that adds a magnitude encoding later.
Two smaller observations from the same session
Bar Tableappears to apply no number formatting at all. Compiling identical data asBar Chartemits"format": ",.12~g"; asBar Tableno format string is emitted, soPriceproduces no currency symbol andPercentageproduces no percent sign. Both are documented as formatting behaviours of those types.- Long field names are altered in
Bar Tableheaders: a field namedHits across 6 clipsrenders asHits_across 6_clipswhen the header wraps.
Thanks for open-sourcing this — the compact-spec-plus-compiler split is the right shape, and the Bar Table template in particular is excellent for dense label+value data once the type behaves.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the Bar Table and Bar Chart template entry points, then trace the validate_chart path and the compiled Vega-Lite output for Rank fields. Compare the templates against the documented Rank behavior and reproduce the reported formatting and header cases; done means the selected fix is reflected in the output and covered by validation or template behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- data-visualization
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100