Chart suggestions rank the catalog for a dataset. Two further surfaces go beyond picking a component: variant discovery proposes and scores alternative configurations of a chart (beyond its hand-curatedcapability.variants), and repair critiques a chart choice and returns safer alternatives. Both keep the framework's generate-then-admit split: a proposer (heuristic or model) suggests; the scorer decides whether the suggestion is coherent, safe, and useful.
Proposing variants
proposeVariant(component, capability, context) returnsVariantProposal[]: the chart's registered variants as explicit proposals, a few conservative heuristic transforms, and same-intent cross-family alternatives when the data supports them.
TS
import { proposeVariant, getCapability, profileData } from "semiotic/ai" const data = [ /* … */ ] const profile = profileData(data) const capability = getCapability("BarChart") const proposals = proposeVariant("BarChart", capability, { profile, intent: "rank", // existingVariants defaults to capability.variants }) // → [{ id, baseComponent, label?, intentDeltas?, rubricDeltas?, // buildProps?, rationale?, source, variantKey?, tags? }, …]
A VariantProposal carries explicit provenance viasource ("manual" for registered variants,"heuristic" for built-in transforms, "model"for proposers you register). The optional buildProps(profile, audience?) closure lets a proposal construct its own props without registering a full capability.
Scoring a proposal
evaluateVariantProposal(proposal, profile, audience?, options?)scores a proposal against the same ingredients the recommender uses — the fits() gate, intent scores, rubric deltas, and audience bias — and adds discovery-specific novelty andrisk channels.
TS
import { evaluateVariantProposal } from "semiotic/ai" const score = evaluateVariantProposal(proposal, profile, audience, { intent: "rank", baselineComponent: "BarChart", }) // → { proposalId, fit (0–5), novelty (0–1), risk (0–1), reasons: string[] }
When the audience declares a non-visualreceptionModality (e.g. "screen-reader"), scoring audits the proposal's props and folds a receivability penalty into fit — so a variant whose meaning can't survive the declared channel is ranked down, consistent withsuggestCharts.
Registering a proposer
The built-in heuristics are a floor, not a ceiling.registerVariantDiscovery(fn) plugs an external heuristic- or model-driven proposer into proposeVariant, which dispatches through every registered function and de-duplicates byproposal.id. It returns an unregister callback.
TS
import { registerVariantDiscovery, getRegisteredVariantDiscovery, clearVariantDiscovery, } from "semiotic/ai" const unregister = registerVariantDiscovery((component, capability, context) => { // propose from your own model / rules return [{ id: `${component}:my-variant`, baseComponent: component, source: "model" }] }) getRegisteredVariantDiscovery() // inspect registered proposers unregister() // or clearVariantDiscovery() to reset all
This preserves the split between generation andadmission: a model proposes freely, andevaluateVariantProposal decides whether the proposal earns a place in the ranking. The same path backs the MCPproposeChartVariants tool (seeCLI & MCP); its structured output strips the non-serializable buildProps function while keeping the computed props.
Repairing a chart choice
repairChartConfig(component, data, options?) validates that a chosen component is a sensible fit for a dataset and, when it isn't, returns alternatives that do fit — ranked by intent. The contract: a caller can always render alternatives[0] and get something useful, and reason is suitable for verbatim display.
TS
import { repairChartConfig } from "semiotic/ai" repairChartConfig("PieChart", productData, { intent: "rank" }) // → { status: "alternative", // component: "PieChart", // reason: "9 slices is too many for a pie chart", // alternatives: [ /* BarChart, DotPlot, … as Suggestions */ ] }
status is one of:
"ok" — the chart fits; ship it."alternative" — the chart doesn't fit; reason says why and alternatives are charts that do."unknown" — no capability is registered for that component name; alternatives are best-effort defaults.
options accepts intent (ranks the alternatives), maxAlternatives (default 3), anaudience profile, and a precomputed profile. Repair is also exposed as the MCP repairChartConfig tool for agent retry loops — propose a chart, repair it, render the survivor.