Repository navigation
feat(types)!: ObjectGridSchema.defaultFilters and the flat gantt / map filter follow their @objectstack/spec rows by reference (objectui#6152, round 10) - #11993
Conversation
…p filter follow their @objectstack/spec rows by reference (objectui#6152, round 10) ObjectGridSchema.defaultFilters takes the object-grid row's own member, the ViewFilterRule array (was Record<string, any> / z.record), so the object-view table slot accepts the rule array and refuses the record. ObjectGanttSchema.filter and ObjectMapSchema.filter take their rows' rule array (was any[] / z.array(z.any())). No reader changes: ObjectGrid lowers defaultFilters through the same toFilterNode sink as filter. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw
…objectui#6152, round 10) ObjectGrid.filterContextTokens-10607 and ObjectView.tableSlotRelay-10976 wrote a record defaultFilters, and ObjectMap.schemaAlignment a tuple filter, on typed nodes; each now writes the rows' ViewFilterRule array. The defaultFilters JSDoc keeps the "Use filter instead" wording the console parity exemption quotes. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw
… (objectui#6152, round 10) Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: PR objectui#11993, round 10 of card objectui#6152 (draft, base ① Derived judgmentsPublished TypeScript face (
Zod accept sets (
Readers (no code moved):
Test fixtures and censuses:
Docs and prose:
File surface against the claim ② Semver level
③ Boundary flagsDev-declared deviations (report
Out-of-scope findings (the report's five), each with its carrier:
Noted, not flagged:
Escalations: none. No maintainer decision is needed for this head to land. Round 11 (the list VIEW's per-view-type blocks) stays booked on the card as Implemented-by: VERDICT: PASS Rendered 2026-10-08T17:41Z · a read-only contract review of PR objectui#11993 on the head named above; the newest record naming this head governs, and any push after it voids it. Generated by Claude Code |
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.defaultFiltersmirror, and through it anobject-view'stable.defaultFilters, now ACCEPTS theViewFilterRulearray theobject-gridrow declares (the oldz.record(z.string(), z.any())refused it). It narrows: the record form ofdefaultFiltersis refused on both faces, and the flatObjectGanttSchema/ObjectMapSchemafilterrefuse the AST tuple array they took asany[].What changed
Three flat members now take their
@objectstack/spec17.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):ObjectGridSchema.defaultFiltersRecord(string keys, any values) /z.record(z.string(), z.any())ObjectGridProps['defaultFilters']/ObjectGridPropsSchema.shape.defaultFiltersObjectGanttSchema.filterany[]/z.array(z.any())ObjectGanttProps['filter']/ObjectGanttPropsSchema.shape.filterObjectMapSchema.filterany[]/z.array(z.any())ObjectMapProps['filter']/ObjectMapPropsSchema.shape.filterEach is the
ViewFilterRulearray[{ field, operator, value }, ...]. The zod members are the rows' own objects (identity is pinned), so a record is refused with the protocol's ownruleArrayFilterErrormessage, which computes the rule array from the author's keys.defaultFilterskeeps its@deprecatedtag: the row's own description still says "Preferfilter".Doors. The flat grid mirror is the source of the
object-viewtableslot, sotable.defaultFilters(objectui's own door) moves with it on the tolerant face, the strict face andsafeValidateSchema. The authoredobject-gridnode'spropertiesbag 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.
ObjectGridalready lowersdefaultFiltersthrough the sametoFilterNodesink asfilter(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
Recordtyped): thedefaultFilterscomment inObjectGrid.tsx's load effect; thetoFilterNodedocblock inpackages/core/src/utils/filter-converter.ts; themergeFilterNodescomment inpackages/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 incontent/docs/plugins/plugin-view.mdxandpackages/plugin-view/README.md, which taughtdefaultFiltersas a record of field to value (equality-only).Measurement first
1. The spec's shape (installed
@objectstack/spec17.7.0,ui/component.zod.ts): theobject-gridrow'sdefaultFiltersisz.array(ViewFilterRuleSchema, { error: ruleArrayFilterError(...) }).optional(), the same wrapper chain asfilter, described "Legacy base-filter fallback, read only whenfilteris absent ... Preferfilter" (narrowed, not retired, by the row's own note). The gantt and map rows'filterare the same rule-array member. The pin re-reads all three on every run.2. The reader (H2 holds). Measured through the registered
object-gridrenderer and aValueDataSourcethat applies the$filterit receives:defaultFilters: [{ field: 'status', operator: 'equals', value: 'open' }]sends[['status', 'equals', 'open']]and draws the two open rows of three; the same array written asfiltersends the same$filterand draws the same rows. Lit control: aclosedrule moves both readings (one row). Controls: no key draws all three and sends no$filter; written both ways,filterwins. 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 53object-grid, 46object-view, 27object-ganttand 22object-mapnode literals, and 11filterkeys on typed nodes.defaultFilterskey on any node (flat, in a bag, or in anobject-viewtable), either shapefilteron anobject-gantt/object-mapnode, flat or in its bag, any shapedefaultFiltersplugin-view.mdx,plugin-viewREADME); 2 of them taught the record shape, corrected hereobjectstack (read-only): no authored
defaultFiltersoutside 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
tscerror:ObjectGrid.filterContextTokens-10607(2 cells),ObjectView.tableSlotRelay-10976(1, now a value distinct fromfilter's so a swap cannot read as arrival),ObjectMap.schemaAlignment(1),gantt-flat-config-declared-keys(theGOODvalue and the_FilterIsDeclaredrow);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
filterreaders areObjectGanttandObjectMap(eachuseResolvedFilter(schema.filter, …)onto$filter), plusObjectMap's legacyfilter.mapprobe, which reads the value asunknown, warns, and was already outsideany[]for a record.ElementDataSourceGatewrites a merged AST tofilterat runtime, andListViewwrites its effective filter onto a gantt node from anunknown-typed value.tscon 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 arrayatfilter.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, underos-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).@object-ui/typesround-10 pin (grid-default-filters-gantt-map-filter-round10-6152.test.ts) 84 tests; theplugin-gridH2 pin 5 tests.type-check(script name echoed on every row) afterturbo 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 namesObjectGridSchema,ObjectGanttSchema,ObjectMapSchemaorObjectViewSchema(the consumers, downstream of@object-ui/types). The first sweep was red only on the three typed fixtures above (plugin-grid,plugin-map,plugin-viewtest configs; every package'ssrccompiled); green after the re-spelling, against a rebuilttypesdist.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-exportscheck: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-literalscheck:new-line-citations(0 new),check:control-bytesnode scripts/check-governed-queue-guard.mjs --testover the 16 paths: NOT GOVERNEDESLint 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 theHEADblob with an emptygit diff HEAD)Predictions were written before the runs; every observed direction matched.
defaultFiltersmirror back toz.record(z.string(), z.any()).optional(): the round-10 pin goes 27 red / 57 green, exactly the predicted set (member identity; the griddefaultFiltersverdict 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; theobject-viewmirror's slot). Green: the precondition, the gantt / map rows, the gridfilterlit control, the door lit controls, the authored-bag control.filterback toz.array(z.any()).optional(): 4 red (the gantt / map identity test; the gantt tuple, AST and unknown-operator verdict rows);gantt-flat-config-declared-keysstays green (its refused value is a string).plugin-grid/src/ObjectGrid.tsx, typedObjectGridSchema, withdefaultFilters: { status: 'open' }:plugin-gridtscred (TS2353,statusnot in the rule type); control leg with the rule array green. This proves the consumer reads the rebuilt.d.ts.plugin-gantt/src/ObjectGantt.tsxwithfilter: [['status', '=', 'open']]: red (TS2322); control leg green.ablation-replacerefused 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'sbuildEffectiveFilterdocblock still saystable.defaultFiltersis "declaredRecord". Fenced from this round (objectui#11860 is in flight on that file). Carrier: objectui#11860's PR, or the next PR that touchesListView.tsx.ObjectView.tsx'sgridSchemamemo comment saysObjectGrid"raw-assigns the legacy"defaultFiltersslot. 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.Schema APIblocks incontent/docs/plugins/plugin-gantt.mdx/plugin-map.mdxspell the bag'sfilteras an array ofany. Not false (the row takes an array), only imprecise. Carrier: none.Implemented by the dispatched
os-devrun (mode subagent) in sessionhttps://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw, claim6063790756.Generated by Claude Code