This repository was archived by the owner on Oct 26, 2026. It is now read-only.
Repository navigation
Commit b13ea3c
feat(types)!: ObjectGridSchema.defaultFilters and the flat gantt / map filter follow their @objectstack/spec rows by reference (objectui#6152, round 10) (#11993)
Part of #6152 (round 10). Round 11 (the list VIEW's per-view-type
blocks) is still to come, so #6152 remains open.
Clause-②: yes — it widens: the flat `ObjectGridSchema.defaultFilters`
mirror, and through it an `object-view`'s `table.defaultFilters`, now
ACCEPTS the `ViewFilterRule` array the `object-grid` row declares (the
old `z.record(z.string(), z.any())` refused it). It narrows: the record
form of `defaultFilters` is refused on both faces, and the flat
`ObjectGanttSchema` / `ObjectMapSchema` `filter` refuse the AST tuple
array they took as `any[]`.
## What changed
Three flat members now take their `@objectstack/spec` 17.7.0 row's own
member by reference, on the TypeScript interface
(`packages/types/src/objectql.ts`) and on the zod mirror
(`packages/types/src/zod/objectql.zod.ts`):
| member | was | now |
|---|---|---|
| `ObjectGridSchema.defaultFilters` | `Record` (string keys, any values)
/ `z.record(z.string(), z.any())` | `ObjectGridProps['defaultFilters']`
/ `ObjectGridPropsSchema.shape.defaultFilters` |
| `ObjectGanttSchema.filter` | `any[]` / `z.array(z.any())` |
`ObjectGanttProps['filter']` / `ObjectGanttPropsSchema.shape.filter` |
| `ObjectMapSchema.filter` | `any[]` / `z.array(z.any())` |
`ObjectMapProps['filter']` / `ObjectMapPropsSchema.shape.filter` |
Each is the `ViewFilterRule` array `[{ field, operator, value }, ...]`.
The zod members are the rows' own objects (identity is pinned), so a
record is refused with the protocol's own `ruleArrayFilterError`
message, which computes the rule array from the author's keys.
`defaultFilters` keeps its `@deprecated` tag: the row's own description
still says "Prefer `filter`".
**Doors.** The flat grid mirror is the source of the `object-view`
`table` slot, so `table.defaultFilters` (objectui's own door) moves with
it on the tolerant face, the strict face and `safeValidateSchema`. The
authored `object-grid` node's `properties` bag is the row itself and
already gave these verdicts (pinned as a control). The flat gantt / map
mirrors are not authoring arms (objectui#10859): their authored nodes'
bags are the rows, which already refused the tuple array, so no authored
door moves there.
**No reader changed.** `ObjectGrid` already lowers `defaultFilters`
through the same `toFilterNode` sink as `filter` (objectui#4082), so the
spec's shape was already honoured; this was a declaration gap, not an
implementation gap.
**Sentences this head would have made false, repaired** (each called the
key `Record` typed): the `defaultFilters` comment in `ObjectGrid.tsx`'s
load effect; the `toFilterNode` docblock in
`packages/core/src/utils/filter-converter.ts`; the `mergeFilterNodes`
comment in `packages/plugin-view/src/ObjectView.tsx` (outside the
claim's listed surface: a one-comment repair, stated here as the round-9
ACCEPT treated its two doc sentences); and the "write this / not this"
row in `content/docs/plugins/plugin-view.mdx` and
`packages/plugin-view/README.md`, which taught `defaultFilters` as a
record of field to value (equality-only).
## Measurement first
**1. The spec's shape** (installed `@objectstack/spec` 17.7.0,
`ui/component.zod.ts`): the `object-grid` row's `defaultFilters` is
`z.array(ViewFilterRuleSchema, { error: ruleArrayFilterError(...)
}).optional()`, the same wrapper chain as `filter`, described "Legacy
base-filter fallback, read only when `filter` is absent ... Prefer
`filter`" (narrowed, not retired, by the row's own note). The gantt and
map rows' `filter` are the same rule-array member. The pin re-reads all
three on every run.
**2. The reader (H2 holds).** Measured through the registered
`object-grid` renderer and a `ValueDataSource` that applies the
`$filter` it receives: `defaultFilters: [{ field: 'status', operator:
'equals', value: 'open' }]` sends `[['status', 'equals', 'open']]` and
draws the two open rows of three; the same array written as `filter`
sends the same `$filter` and draws the same rows. Lit control: a
`closed` rule moves both readings (one row). Controls: no key draws all
three and sends no `$filter`; written both ways, `filter` wins. New pin:
`packages/plugin-grid/src/__tests__/ObjectGrid.defaultFiltersRuleArray-6152.test.tsx`.
**3. Corpus census, before any edit.** A TypeScript-AST census over the
authored corpus (`examples/` with the schema catalog, `content/`,
`skills/`, `docs/`, `apps/`, the root README and every package README;
tests and CHANGELOGs excluded): 941 files. Controls: the extractor saw
53 `object-grid`, 46 `object-view`, 27 `object-gantt` and 22
`object-map` node literals, and 11 `filter` keys on typed nodes.
| looked for | authored occurrences |
|---|---|
| a `defaultFilters` key on any node (flat, in a bag, or in an
`object-view` `table`), either shape | **0** |
| a `filter` on an `object-gantt` / `object-map` node, flat or in its
bag, any shape | **0** |
| prose naming `defaultFilters` | 9 lines in 2 documents
(`plugin-view.mdx`, `plugin-view` README); 2 of them taught the record
shape, corrected here |
objectstack (read-only): no authored `defaultFilters` outside tests and
the spec package; the spec ships its own migration
(`object-grid-default-filters-rule-array`).
**Test fixtures, classified separately.** Re-spelled to the rule array
because a typed fixture became a `tsc` error:
`ObjectGrid.filterContextTokens-10607` (2 cells),
`ObjectView.tableSlotRelay-10976` (1, now a value distinct from
`filter`'s so a swap cannot read as arrival),
`ObjectMap.schemaAlignment` (1), `gantt-flat-config-declared-keys` (the
`GOOD` value and the `_FilterIsDeclared` row);
`object-gallery-filter-9309`'s source census updated for the two new
spellings. Left as written: 18 record-valued cells in 5 untyped runtime
tests (`gridDefaultFiltersLowering`, `ObjectGrid.malformedFilter-9050`,
`ObjectView.canonicalTableKeys`, `ObjectView.filterSources`,
`ObjectView.namedViewContextTokens-10506`). They pin the READ, which did
not narrow (the objectui#10199 split, as round 8 left its AST fixtures);
`gridDefaultFiltersLowering`'s two comments that called the record "the
declared shape" now say "declared until this round".
**H1** holds for authored nodes (zero) and is falsified in prose: two
documentation rows taught the record. **H3** holds: the flat gantt / map
`filter` readers are `ObjectGantt` and `ObjectMap` (each
`useResolvedFilter(schema.filter, …)` onto `$filter`), plus
`ObjectMap`'s legacy `filter.map` probe, which reads the value as
`unknown`, warns, and was already outside `any[]` for a record.
`ElementDataSourceGate` writes a merged AST to `filter` at runtime, and
`ListView` writes its effective filter onto a gantt node from an
`unknown`-typed value. `tsc` on all of them stays green; no renderer
changed.
**Not by reference, stated:** the tuple-array refusal is the row's
element-level message (`expected object, received array` at `filter.0`),
which does not name the rule array; only the record refusal carries the
conversion. Changing that would mean a local copy of the member, so it
is left to the spec.
## Tests
On head `e2fe94285`, under `os-verify-lock`:
- `pnpm exec vitest run --maxWorkers=2 packages/types/
packages/plugin-grid/ packages/plugin-gantt/ packages/plugin-map/
packages/plugin-view/ packages/core/
apps/console/src/__tests__/registry-inputs-spec-parity.test.ts`: `Test
Files 962 passed | 1 skipped (963)`, `Tests 17511 passed | 141 skipped
(17652)`.
- `pnpm exec vitest run --maxWorkers=2 scripts/__tests__/`: `Test Files
179 passed | 2 skipped (181)`, `Tests 5452 passed | 2 skipped (5454)`.
- The lock held 26m07s for both and the doc gates' build closure (35/35
turbo tasks), on a shared box.
- The two new pins alone: the `@object-ui/types` round-10 pin
(`grid-default-filters-gantt-map-filter-round10-6152.test.ts`) 84 tests;
the `plugin-grid` H2 pin 5 tests.
**`type-check`** (script name echoed on every row) after `turbo run
build --filter='@object-ui/console^...'
--filter='@object-ui/example-schema-catalog^...'` (34/34 tasks):
`types`, `core`, `app-shell`, `plugin-calendar`, `plugin-dashboard`,
`plugin-designer`, `plugin-gantt`, `plugin-grid`, `plugin-kanban`,
`plugin-list`, `plugin-map`, `plugin-tree`, `plugin-view`, `console`,
`example-schema-catalog`: every package whose source names
`ObjectGridSchema`, `ObjectGanttSchema`, `ObjectMapSchema` or
`ObjectViewSchema` (the consumers, downstream of `@object-ui/types`).
The first sweep was red only on the three typed fixtures above
(`plugin-grid`, `plugin-map`, `plugin-view` test configs; every
package's `src` compiled); green after the re-spelling, against a
rebuilt `types` dist.
**Gates**, all exit 0, on the same head after that build:
- `pnpm check:doc-snippets` (784 of 784 blocks judged, 0 failed),
`check:doc-examples`, `check:skill-examples`, `check:doc-types`,
`check:readme-exports`
- `check:spec-symbols`; `check:component-surface-parity` (report-only,
no row for these members)
- `node scripts/check-changeset-presence.mjs` (13 source files of 5
released packages, 1 changeset), `node
scripts/check-changeset-no-major.mjs`, `check:changeset-claims`,
`check:pending-changeset-literals`
- `check:new-line-citations` (0 new), `check:control-bytes`
- `node scripts/check-governed-queue-guard.mjs --test` over the 16
paths: NOT GOVERNED
**ESLint** over the 13 changed TS files: 0 errors (warnings pre-existing
`no-explicit-any` / react-hooks).
## Ablations (one-shot, through `ablation-replace.mjs`; each mutation
proven on disk, each restore to the `HEAD` blob with an empty `git diff
HEAD`)
Predictions were written before the runs; every observed direction
matched.
- **A.** `defaultFilters` mirror back to `z.record(z.string(),
z.any()).optional()`: the round-10 pin goes **27 red / 57 green**,
exactly the predicted set (member identity; the grid `defaultFilters`
verdict rows for the rule array, the empty array, the record and the
empty record; on each of the three doors the rule-array, record and
tuple rows and the same four verdict rows; the `object-view` mirror's
slot). Green: the precondition, the gantt / map rows, the grid `filter`
lit control, the door lit controls, the authored-bag control.
- **B.** gantt mirror `filter` back to `z.array(z.any()).optional()`:
**4 red** (the gantt / map identity test; the gantt tuple, AST and
unknown-operator verdict rows); `gantt-flat-config-declared-keys` stays
green (its refused value is a string).
- **C.** a consumer literal in `plugin-grid/src/ObjectGrid.tsx`, typed
`ObjectGridSchema`, with `defaultFilters: { status: 'open' }`:
`plugin-grid` `tsc` **red** (`TS2353`, `status` not in the rule type);
control leg with the rule array **green**. This proves the consumer
reads the rebuilt `.d.ts`.
- **D.** the same in `plugin-gantt/src/ObjectGantt.tsx` with `filter:
[['status', '=', 'open']]`: **red** (`TS2322`); control leg **green**.
- The first C/D attempt was a no-op: `ablation-replace` refused it
because the replacement re-contained the anchor, ran nothing, and
restored. Re-run with an anchor-altering replacement; the numbers above
are the second attempt's.
## Acceptance notes
- `packages/plugin-list/src/ListView.tsx`'s `buildEffectiveFilter`
docblock still says `table.defaultFilters` is "declared `Record`".
Fenced from this round (objectui#11860 is in flight on that file).
Carrier: objectui#11860's PR, or the next PR that touches
`ListView.tsx`.
- `ObjectView.tsx`'s `gridSchema` memo comment says `ObjectGrid`
"raw-assigns the legacy" `defaultFilters` slot. That has been false
since objectui#4082 (it is lowered through the same sink), not made
false here. Carrier: the next PR that touches that memo.
- The gantt and map `Schema API` blocks in
`content/docs/plugins/plugin-gantt.mdx` / `plugin-map.mdx` spell the
bag's `filter` as an array of `any`. Not false (the row takes an array),
only imprecise. Carrier: none.
Implemented by the dispatched `os-dev` run (mode subagent) in session
`https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw`, claim
`6063790756`.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent d21bd08 commit b13ea3c
16 files changed
Lines changed: 542 additions & 47 deletions
File tree
- .changeset
- content/docs/plugins
- packages
- core/src/utils
- plugin-grid/src
- __tests__
- plugin-map/src
- plugin-view
- src
- __tests__
- types/src
- __tests__
- zod
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
171 | 171 | | |
172 | 172 | | |
173 | 173 | | |
174 | | - | |
| 174 | + | |
175 | 175 | | |
176 | 176 | | |
177 | 177 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1397 | 1397 | | |
1398 | 1398 | | |
1399 | 1399 | | |
1400 | | - | |
1401 | | - | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + | |
| 1404 | + | |
| 1405 | + | |
1402 | 1406 | | |
1403 | 1407 | | |
1404 | 1408 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2629 | 2629 | | |
2630 | 2630 | | |
2631 | 2631 | | |
2632 | | - | |
2633 | | - | |
2634 | | - | |
2635 | | - | |
2636 | | - | |
2637 | | - | |
2638 | | - | |
| 2632 | + | |
| 2633 | + | |
| 2634 | + | |
| 2635 | + | |
| 2636 | + | |
| 2637 | + | |
| 2638 | + | |
| 2639 | + | |
2639 | 2640 | | |
2640 | 2641 | | |
2641 | 2642 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
122 | 122 | | |
123 | 123 | | |
124 | 124 | | |
125 | | - | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
126 | 128 | | |
127 | 129 | | |
128 | 130 | | |
| |||
156 | 158 | | |
157 | 159 | | |
158 | 160 | | |
159 | | - | |
| 161 | + | |
160 | 162 | | |
161 | 163 | | |
162 | 164 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
32 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
33 | 35 | | |
34 | 36 | | |
35 | 37 | | |
| |||
129 | 131 | | |
130 | 132 | | |
131 | 133 | | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
136 | 139 | | |
137 | 140 | | |
138 | 141 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
99 | | - | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
100 | 102 | | |
101 | 103 | | |
102 | 104 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
246 | 246 | | |
247 | 247 | | |
248 | 248 | | |
249 | | - | |
| 249 | + | |
250 | 250 | | |
251 | 251 | | |
252 | 252 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1392 | 1392 | | |
1393 | 1393 | | |
1394 | 1394 | | |
1395 | | - | |
1396 | | - | |
1397 | | - | |
| 1395 | + | |
| 1396 | + | |
| 1397 | + | |
| 1398 | + | |
1398 | 1399 | | |
1399 | 1400 | | |
1400 | 1401 | | |
| |||
0 commit comments