Filed from the hotcrm exemplar (objectstack-ai/hotcrm#1213), per the lane charter: a platform gap found while building the showcase app is filed upstream rather than papered over there. hotcrm has already fixed its own metadata, so nothing here is blocking that repo — what is left is a question this repo's seat owns.
I cannot see the renderer from where this was measured, so this card reports what was measured and what was read, and does not claim a cause. See "What I could not check" below.
What was measured
hotcrm's service dashboard shipped a gauge widget that plotted the SLA violation rate and asked for it to be flipped for display:
id: 'sla_compliance_gauge',title: 'SLA Compliance',type: 'gauge',dataset: 'case_metrics',values: ['avg_sla_violated'],// AVG(is_sla_violated)options: {format: '0%',invert: true,// value is sla_violated rate; gauge shows compliance = 1 - ratethresholds: [{value: 0.95,color: 'success'},…],},Driven in a browser against a fresh pnpm dev on 17.1.0, on a seeded org whose 8 closed cases are all within SLA (violation rate 0, compliance 100%), the widget rendered:
SLA 达成率
本期 SLA 内解决工单的占比
0.0%
SLA Violation Rate ← the measure's own label, printed under the number
That is the raw measure value, formatted by format: '0%', with no inversion applied. The complement (100%) was not rendered anywhere. The same page simultaneously showed violation rates of 40–70% in other tiles, so the gauge was the only reading that disagreed with the rest of the page.
What was read, in @objectstack/spec @ 17.1.0
packages/spec/src/ui/dashboard.zod.ts:217 — DashboardWidgetOptionsSchema ends in .passthrough(), described as "declared query keys + open renderer extras". invert is not among the declared keys. It therefore parses, validates and lints cleanly on the way through, and no validator, lint rule or gate in either repo is able to tell an author that the key does nothing — and none did. The comment beside it shows the author believed it was doing something.
The question this raises
Two coherent answers, and picking between them is this repo's call:
- The renderer should honour it —
invert is a reasonable request for a gauge whose measure is stored as a complement, and the key should become declared and implemented. - An undeclared key that does nothing should be refused, not accepted in silence — if
invert is not a thing, the failure mode above (metadata that reads as correct, renders as wrong, and cannot be linted) is the cost of .passthrough() accepting arbitrary renderer extras. Some way for an author to learn that a key reached nothing would have caught this at authoring time instead of in a browser.
The second is the more general issue: invert is one key, and .passthrough() accepts any other.
Possibly the mechanism — for this repo's seat to confirm, not a claim
#4295 (closed, not_planned) measured that gauge / solid-gauge / bullet / kpi are all routed by construction to the single-value / metric path (METRIC_TYPES, METRIC_LIKE_TYPES, SINGLE_VALUE_CHART_TYPES), because no dial/arc/target renderer exists yet — a gauge renders as a plain number, deliberately. The observation above is consistent with that: what rendered was a plain formatted number. If a gauge never reaches a gauge renderer, then gauge-specific options plausibly have nowhere to be applied. Whether that is actually why invert had no effect is exactly what I cannot verify.
What I could not check
The console renderer package is not installed in either the hotcrm or the objectstack checkout this was worked from, so I did not read the gauge/metric render path at all. I am not asserting that the console ignores invert; I am reporting a rendered value that matches the un-inverted measure, plus the schema fact that the key is undeclared. The cause determination belongs here.
Context
Generated by Claude Code
Filed from the hotcrm exemplar (objectstack-ai/hotcrm#1213), per the lane charter: a platform gap found while building the showcase app is filed upstream rather than papered over there. hotcrm has already fixed its own metadata, so nothing here is blocking that repo — what is left is a question this repo's seat owns.
I cannot see the renderer from where this was measured, so this card reports what was measured and what was read, and does not claim a cause. See "What I could not check" below.
What was measured
hotcrm's service dashboard shipped agaugewidget that plotted the SLA violation rate and asked for it to be flipped for display:Driven in a browser against a fresh
pnpm devon17.1.0, on a seeded org whose 8 closed cases are all within SLA (violation rate0, compliance100%), the widget rendered:That is the raw measure value, formatted by
format: '0%', with no inversion applied. The complement (100%) was not rendered anywhere. The same page simultaneously showed violation rates of 40–70% in other tiles, so the gauge was the only reading that disagreed with the rest of the page.What was read, in
@objectstack/spec@ 17.1.0packages/spec/src/ui/dashboard.zod.ts:217—DashboardWidgetOptionsSchemaends in.passthrough(), described as "declared query keys + open renderer extras".invertis not among the declared keys. It therefore parses, validates and lints cleanly on the way through, and no validator, lint rule or gate in either repo is able to tell an author that the key does nothing — and none did. The comment beside it shows the author believed it was doing something.The question this raises
Two coherent answers, and picking between them is this repo's call:
invertis a reasonable request for a gauge whose measure is stored as a complement, and the key should become declared and implemented.invertis not a thing, the failure mode above (metadata that reads as correct, renders as wrong, and cannot be linted) is the cost of.passthrough()accepting arbitrary renderer extras. Some way for an author to learn that a key reached nothing would have caught this at authoring time instead of in a browser.The second is the more general issue:
invertis one key, and.passthrough()accepts any other.Possibly the mechanism — for this repo's seat to confirm, not a claim
#4295 (closed,
not_planned) measured thatgauge/solid-gauge/bullet/kpiare all routed by construction to the single-value / metric path (METRIC_TYPES,METRIC_LIKE_TYPES,SINGLE_VALUE_CHART_TYPES), because no dial/arc/target renderer exists yet — a gauge renders as a plain number, deliberately. The observation above is consistent with that: what rendered was a plain formatted number. If a gauge never reaches a gauge renderer, then gauge-specific options plausibly have nowhere to be applied. Whether that is actually whyinverthad no effect is exactly what I cannot verify.What I could not check
The console renderer package is not installed in either the
hotcrmor theobjectstackcheckout this was worked from, so I did not read the gauge/metric render path at all. I am not asserting that the console ignoresinvert; I am reporting a rendered value that matches the un-inverted measure, plus the schema fact that the key is undeclared. The cause determination belongs here.Context
0.0%on a 100%-compliant org).derived: { op: 'ratio', … }) to its dataset, pointed the gauge at it, and removedoptions.invertrather than leave a key that pretends to work.Generated by Claude Code