Found while reworking PR objectui#8884 (card objectui#7946), and named as a successor by that PR's
contract review. Filed rather than fixed there: it is a behaviour change to the drill-down query, not
part of the ruled declaration work.
The defect
ObjectChartSchema.filter admits BOTH arms — a spec FilterArray and the ObjectQL $filter object
— because both are read. The drill-down composition in
packages/plugin-charts/src/ObjectChart.tsx handles only one of them:
const drillFilter = useMemo(() => {
if (!drillEvent) return undefined;
return {
...(schema.filter || {}),
...computeDrillFilter(drillDown, drillEvent, { groupByField }),
};
}, [...]);
Spreading an ARRAY into an object literal does not produce conditions — it produces index keys.
An author who writes the arm @objectstack/spec publishes for this prop, and whom this component's
own registry inputs advertise ({ name: 'filter', type: 'array' }):
drills with
The widget's own filter is silently lost — the "0" key means nothing to the query layer — so the
drilled list is scoped by the clicked category ALONE and shows records the chart itself excludes.
Nothing errors; the drawer opens and looks right.
The record arm works, which is why this survived: the in-repo corpus authors the object form, and the
array arm is the one the protocol advertises.
Why this blocks something else
ObjectChartSchema.filter is the only object-* widget filter on packages/types/src/objectql.ts
carrying a record arm — the six siblings are already array-only. Narrowing this node to the spec's
array-only FilterArray would make the declaration match the protocol and the palette, and it is
blocked on exactly this composition: narrow first and every live chart that authors the object form
stops compiling; fix this first and the narrowing becomes a normal deprecation.
So this card is the prerequisite for closing that divergence, and objectui#8884's filter docblock
names it as such.
Acceptance
- A drill-down on a chart whose
filter is the ARRAY arm produces a filter that still carries the
widget's own conditions, in whatever spelling the query layer takes.
- Both arms pinned at runtime, including the
target: 'navigate' path (openRecordList receives the
composed filter) — the drawer and the navigate arm share one drillFilter memo, so one pin covers
both if it asserts the composed value rather than the rendered rows.
- The pin fails on the current code. A test that only exercises the record arm is green today and
measures nothing.
Generated by Claude Code
Found while reworking PR objectui#8884 (card objectui#7946), and named as a successor by that PR's
contract review. Filed rather than fixed there: it is a behaviour change to the drill-down query, not
part of the ruled declaration work.
The defect
ObjectChartSchema.filteradmits BOTH arms — a specFilterArrayand the ObjectQL$filterobject— because both are read. The drill-down composition in
packages/plugin-charts/src/ObjectChart.tsxhandles only one of them:Spreading an ARRAY into an object literal does not produce conditions — it produces index keys.
An author who writes the arm
@objectstack/specpublishes for this prop, and whom this component'sown registry
inputsadvertise ({ name: 'filter', type: 'array' }):{ "filter": [["stage", "=", "won"]] }drills with
{ "0": ["stage", "=", "won"], "stage": "won" }The widget's own filter is silently lost — the
"0"key means nothing to the query layer — so thedrilled list is scoped by the clicked category ALONE and shows records the chart itself excludes.
Nothing errors; the drawer opens and looks right.
The record arm works, which is why this survived: the in-repo corpus authors the object form, and the
array arm is the one the protocol advertises.
Why this blocks something else
ObjectChartSchema.filteris the onlyobject-*widgetfilteronpackages/types/src/objectql.tscarrying a record arm — the six siblings are already array-only. Narrowing this node to the spec's
array-only
FilterArraywould make the declaration match the protocol and the palette, and it isblocked on exactly this composition: narrow first and every live chart that authors the object form
stops compiling; fix this first and the narrowing becomes a normal deprecation.
So this card is the prerequisite for closing that divergence, and objectui#8884's
filterdocblocknames it as such.
Acceptance
filteris the ARRAY arm produces a filter that still carries thewidget's own conditions, in whatever spelling the query layer takes.
target: 'navigate'path (openRecordListreceives thecomposed filter) — the drawer and the navigate arm share one
drillFiltermemo, so one pin coversboth if it asserts the composed value rather than the rendered rows.
measures nothing.
Generated by Claude Code