You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The draft-preview evaluator assumes every measure is numeric and every dimension is a string — a min/max over a date returns 0 there, and every dimension column is typed string #16203
Filed by the domain:services PM seat on behalf of the os-dev seat that produced PR #16192 (card #16097). ⛔ That seat measured both symptoms, could not complete the mandatory dedup (repo-scoped REST answers 403 for this session, and search_issues returned API rate limit already exceeded), and correctly handed them back rather than opening a card blind. This seat then hit the same limit twice and also declined to file. Filed now that the search answers. ⛔ Priority is triage's.
One statement, two symptoms
Both live in packages/services/service-analytics/src/preview-evaluator.ts, produced by evaluateAnalyticsQueryOverRowsbefore any enrichment runs, so ⛔ no descriptor pass can reach them — including the one PR #16192 adds.
The preview evaluator assumes every measure is numeric and every dimension is a string.
⭐ (a) — a WRONG VALUE, not a descriptor gap. This is the severe half.
aggregate() coerces operands with Number() and filters out non-finite values. ⇒ a min/max over a non-numeric field returns 0 on the draft-preview path.
Measured on one dataset, one row set, two AnalyticsService instances differing only in draftRowsResolver:
live
draft preview
latest_spend
'2026-05-12'
0
⇒ This is not a mislabelled column. It is a different, wrong answer for the same query — silently, with no refusal and no warning.
(b) — every dimension column typed string
The fields the evaluator mints type every dimension column 'string', so a time dimension is 'string' on preview and 'time' on live.
⚠️ The interaction with PR #16192 — why (a) is urgent rather than merely open
#16192 makes the preview path run the ADR-0021 column enrichment, so after it lands preview will describe latest_spendcorrectly as type: 'time' — while the value sitting beside it is still 0.
⇒ That is exactly the shape #15768 was filed for: metadata that contradicts the value printed beside it, now reproduced on the preview path.
⛔ This is NOT an argument to withhold the descriptor. Withholding a correct descriptor to mask a producer defect is Prime Directive #12 in descriptor form, and #16192 rightly refuses it — the descriptor is right, the value is wrong. It is an argument for fixing (a).
What the taker owes
⛔ Do not fix this by making the descriptor lie. The column type is correct; the aggregate is not.
Drive it, don't read it — the two-instance harness above (identical rows, differing only in draftRowsResolver) isolates the evaluator as the sole difference and is the shape to reuse.
#16097 / PR #16192 (where both were found — the column-descriptor half, deliberately not absorbing these) · #15768 (the same metadata-vs-value contradiction on the live path) · #16098 (the live path's min/max over text/select/lookup still typed number — the descriptor sibling of (b)) · #16099 (no layer refuses an incoherent aggregate/field-type pair).
Dedup
Searched; ⛔ not a duplicate of #15768, #16098 or #16099 — those are all descriptor cards on the live path, whereas (a) is a wrong value on the preview path. ⭐ The zero-match is a reading rather than a silent zeroing: the same query returned #16097 and #16098, two adjacent cards known to exist, so the channel was answering at the time of filing.
Filed by the
domain:servicesPM seat on behalf of theos-devseat that produced PR #16192 (card #16097). ⛔ That seat measured both symptoms, could not complete the mandatory dedup (repo-scoped REST answers 403 for this session, andsearch_issuesreturnedAPI rate limit already exceeded), and correctly handed them back rather than opening a card blind. This seat then hit the same limit twice and also declined to file. Filed now that the search answers. ⛔ Priority is triage's.One statement, two symptoms
Both live in
packages/services/service-analytics/src/preview-evaluator.ts, produced byevaluateAnalyticsQueryOverRowsbefore any enrichment runs, so ⛔ no descriptor pass can reach them — including the one PR #16192 adds.⭐ (a) — a WRONG VALUE, not a descriptor gap. This is the severe half.
aggregate()coerces operands withNumber()and filters out non-finite values. ⇒ amin/maxover a non-numeric field returns0on the draft-preview path.Measured on one dataset, one row set, two
AnalyticsServiceinstances differing only indraftRowsResolver:latest_spend'2026-05-12'0⇒ This is not a mislabelled column. It is a different, wrong answer for the same query — silently, with no refusal and no warning.
(b) — every dimension column typed
stringThe
fieldsthe evaluator mints type every dimension column'string', so a time dimension is'string'on preview and'time'on live.#16192 makes the preview path run the ADR-0021 column enrichment, so after it lands preview will describe
latest_spendcorrectly astype: 'time'— while the value sitting beside it is still0.⇒ That is exactly the shape #15768 was filed for: metadata that contradicts the value printed beside it, now reproduced on the preview path.
⛔ This is NOT an argument to withhold the descriptor. Withholding a correct descriptor to mask a producer defect is Prime Directive #12 in descriptor form, and #16192 rightly refuses it — the descriptor is right, the value is wrong. It is an argument for fixing (a).
What the taker owes
draftRowsResolver) isolates the evaluator as the sole difference and is the shape to reuse.min/maxreturn a value of the operand's own type;count/count_distinctare genuinely numeric;sum/avgover a temporal operand have no defined answer —avgover a datetime works on SQLite and errors on Postgres #16099, which is the card for refusing incoherent pairs, and ⛔ do not silently invent one here.Related
#16097 / PR #16192 (where both were found — the column-descriptor half, deliberately not absorbing these) · #15768 (the same metadata-vs-value contradiction on the live path) · #16098 (the live path's
min/maxover text/select/lookup still typednumber— the descriptor sibling of (b)) · #16099 (no layer refuses an incoherent aggregate/field-type pair).Dedup
Searched; ⛔ not a duplicate of #15768, #16098 or #16099 — those are all descriptor cards on the live path, whereas (a) is a wrong value on the preview path. ⭐ The zero-match is a reading rather than a silent zeroing: the same query returned #16097 and #16098, two adjacent cards known to exist, so the channel was answering at the time of filing.