Skip to content

fix(plugin-list): resolve context tokens in a directly authored object-gallery filter (objectui#10666) - #10705

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-10666-filter-token-closure
Sep 25, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-10666-filter-token-closure

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #10666
Clause-②: no. The documented context tokens now resolve on one more host, through the one shared resolver. No schema, export or accept set moves.

This PR fixes the node the card names, object-gallery. The census the triage ordered found eleven more nodes that send their own filter unresolved. The seat decides how to close them (see Census and The fork), so this PR uses Part of and does not close the card.

What changed

A directly authored object-gallery node, with no list-view or object-view above it, sent filter: [['owner', '=', '{current_user_id}']] on $filter as the literal token. ObjectGallery now resolves its own filter once, through @object-ui/core's shared resolveFilterPlaceholders, against useFilterScope() from @object-ui/react. The resolved value is held by structure, in the shape PR objectui#10656 gave list-view.

  • No second resolver and no copy. The hold is useResolvedAuthoredFilter with its comparator isSameAuthoredFilter. PR objectui#10656 added it as a function local to ListView.tsx. It now moves, unchanged, into the package-internal module packages/plugin-list/src/useResolvedAuthoredFilter.ts. ListView and ObjectGallery both import it. index.tsx does not re-export it, so the package's export set does not move.
  • ObjectGallery. The query's $filter and the fetch effect's dependency list now read the held authoredFilter. After this change the only raw schema.filter read is the hold's own input.
  • Changeset: .changeset/10666-gallery-filter-context-tokens.md, '@object-ui/plugin-list': patch.
file change
packages/plugin-list/src/ObjectGallery.tsx reads the held filter; +21 / −5
packages/plugin-list/src/useResolvedAuthoredFilter.ts new: the hold, moved from ListView.tsx
packages/plugin-list/src/ListView.tsx the hold moved out; the import added
packages/plugin-list/src/__tests__/ObjectGallery.filterContextTokens-10666.test.tsx new pin, 8 cells
.changeset/10666-gallery-filter-context-tokens.md new

Measured

The measurement is the pin's first run, on the unfixed code (commit 8f38562, pins only). The node was mounted through the real SchemaRenderer and this package's own registrations, under FilterScopeProvider (user usr_42, org org_7), over a data source that records every find().

node (directly authored) $filter sent on base
list-view (lit control) [["owner","=","usr_42"]]: resolved, the cell passes
object-gallery [["owner","=","{current_user_id}"]]: the literal token
object-gallery with {current_org_id} [["org","=","{current_org_id}"]]: the literal token

The pin has 8 cells. It checks the list-view lit control, {current_user_id} and {current_org_id}, and a token-free CONTROL. It checks that with no scope the token stays literal and the shared resolver warns (no fallback). It checks that a user change re-queries. It checks that the same node issues exactly one query across three re-renders. It checks that no query is added across re-renders that rebuild an equal token filter.

run result
8f38562 (pins only, base code) 5 failed, 3 passed (exit 1). The token cells read the literal (expected [ [ 'org', '=', '{current_org_id}' ] ] to deeply equal [ [ 'org', '=', 'org_7' ] ]). The cells that pass are the lit control, the CONTROL and the same-node count.
head 59d06fc 8 passed; with both objectui#10607 pins in the same run, 3 files, 27 passed, exit 0

The hold, by ablation. ablation-replace.mjs replaced the hook's return held.resolved as T; with a bare per-render resolveFilterPlaceholders(authored, scope) return. The anchor hit once, and the blob went from 9d7fa15 to 62871c1. The result was 3 failed and 5 passed. The same-node cell reads expected 0 to be greater than 0: no find() landed inside the 1000ms wait while the gallery kept re-rendering. The user-change and equal-rebuild cells time out at 15000ms, because a copy minted every render re-queries without end. The token cells stay green. The restore was checked: the blob after restore equals the blob at HEAD, and git diff HEAD is empty. The pin imports the subject through ../index (from src/), so there is no dist/ leg.

Suites and gates at 59d06fc. Heavy runs went through the shared verify lock.

  • turbo run build --filter='@object-ui/plugin-list^...' --concurrency=2: 12 tasks successful.
  • plugin-list type-check (tsc --noEmit && tsc -p tsconfig.test.json): exit 0. --listFilesOnly lists the new pin (1 hit).
  • pnpm exec vitest run packages/plugin-list/: 102 files, 1169 tests passed, exit 0.
  • pnpm exec vitest run packages/i18n/src/__tests__/machineLocaleCensus-9909.test.ts: 7 passed.
  • Each of these exited 0: check:changeset-claims, check:pending-changeset-literals, check:new-line-citations (0 new), check:control-bytes, check-changeset-presence (4 source files of 1 released package, 1 changeset), check-changeset-no-major, check-changeset-overwrite, check-changeset-fixed, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:test-path-roots, check:unreferenced-sources, check:phantom-deps, check:self-import and check-type-check-coverage.
  • check:changeset-claims is report-only. It lists 7 pending paragraphs that name ListView.tsx. Each was re-read, and none concerns the filter read. They cover the gantt branch, kanban groupField and groupBy, userActions, and comment corrections.
  • eslint, plain form, on the four changed source and test files: exit 0, 0 errors. Warnings per rule, base 69a6fc1 against head, are unchanged: ObjectGallery.tsx 17 → 17 and ListView.tsx 184 → 184, with 0 rules differing. The new module and the pin have 0 findings.

NOT MEASURED: check:eager-closure and check:sdui-registration-pins. Both need a console production build. The only new import is useFilterScope from @object-ui/react, which the package already loads. Repo-wide pnpm lint and the full test farm belong to CI.

Census: nodes that send their OWN filter into a data-source query

Read on origin/main 69a6fc1, in plugin-* and components, over every source that calls find / aggregate or builds a $filter. "Reachable" means the node type is registered and the filter comes from its own schema or props. For the unresolved rows this is a source reading. Only object-gallery and the list-view control were measured.

node file resolves? reachable when directly authored
object-grid plugin-grid/src/ObjectGrid.tsx yes (objectui#10607) yes
list-view plugin-list/src/ListView.tsx yes (objectui#10607), measured as the lit control yes
object-view plugin-view/src/ObjectView.tsx yes (objectui#10506) yes
object-chart plugin-charts/src/ObjectChart.tsx yes yes
dashboard widgets (dataset, metric, pivot, data table) plugin-dashboard/src/{DatasetWidget,ObjectMetricWidget,ObjectPivotTable,ObjectDataTable}.tsx yes yes
object-gallery plugin-list/src/ObjectGallery.tsx fixed here yes (measured)
object-calendar plugin-calendar/src/ObjectCalendar.tsx no: $filter: schema.filter (object and inline paths) yes
object-gantt plugin-gantt/src/ObjectGantt.tsx no: $filter: schema.filter yes
object-kanban plugin-kanban/src/ObjectKanban.tsx no: $filter: schema.filter yes
object-map plugin-map/src/ObjectMap.tsx no: $filter: schema.filter (object and inline paths) yes
object-timeline plugin-timeline/src/ObjectTimeline.tsx no: $filter: schema.filter (already keyed by content, filterKey) yes
object-tree plugin-tree/src/ObjectTree.tsx no: $filter: schema.filter (object and inline paths) yes
related_list / related-list plugin-detail/src/RelatedList.tsx no: the list's own filter is merged into the parent scope unresolved yes, on a record page
line_items plugin-form/src/LineItemsPanel.tsx no: schema.filter is merged into the parent scope unresolved yes, on a record form
repeater components/src/renderers/basic/data-list.tsx no: query.$filter = props.filter yes (page element)
number (element) components/src/renderers/basic/elements.tsx no: the aggregate filter and the find fallback's $filter yes (page element)
record_picker components/src/renderers/basic/record-picker.tsx no: composed?.filter ?? props.filter yes (page element)
tabs count badge components/src/renderers/layout/containers.tsx no, but it is not its own filter: it probes a child related list's filter for a count only through a child related list

Filters that are not authored were left out: parent-scope and $in id lookups in plugin-detail, the history and activity feeds, the reference rail, and the filter builder's option lookups. plugin-report's DatasetReportRenderer refuses a node-level filter, so it is not a hit. No hit was found outside the renderer packages: the app-shell callers (views/ObjectView.tsx, ObjectDataPage.tsx, useOpenRecordList.ts) all resolve.

The fork (for the seat, not decided here)

Eleven unresolved nodes remain, in nine packages: plugin-calendar, plugin-gantt, plugin-kanban, plugin-map, plugin-timeline, plugin-tree, plugin-detail, plugin-form and components. In the ruled shape, each package would need its own copy of the structural hold, since no shared hold is exported. That means nine copies of the ~90-line hook and comparator. PR objectui#10656 accepted two copies on the grounds that "a shared export would move an export set", and the dispatch lists a new export as a STOP condition. The options:

  • A. Copy the hold into each package (PR objectui#10656's precedent): no export moves, but nine verbatim copies.
  • B. Export one useResolvedFilter hold from @object-ui/react, next to useFilterScope, then sweep. There is one copy, but it is a new export (Clause-② yes). It needs a decision.
  • C. Resolve inside each fetch effect and key the effect on the raw filter plus the scope's primitive members. There is no hold, no copy and no export, and a token-free filter's fetch keys do not move at all. This departs from the ruled "held by structure" mechanism.

Acceptance notes

  • Date macros ({today} and the rest) in a directly authored gallery's filter are now resolved on the client in the browser's local time, the same as list-view, object-grid and object-view. Before, they reached the server as literals, which resolves them in the tenant's time zone.
  • Fewer queries, by design. The gallery's fetch effect keyed on the filter's identity, so a host that rebuilt an equal filter inline re-queried on every render. The structural hold drops those redundant queries, and the equal-rebuild cell pins this. A structurally different filter, or a new scope member, still re-queries.
  • Against ObjectStack, the server also expands {current_user_id} for a signed-in request and refuses the request otherwise. There, this is defence in depth.
  • Prose elsewhere. The ObjectGallerySchema.filter docblock in @object-ui/types says the filter is "forwarded verbatim as $filter". That is now true only for a filter with no placeholders; ObjectChartSchema carries the same wording and resolves as well. It is not edited here, because it is out of this PR's file surface.
  • The objectui#10607 pins for ObjectGrid and ListView stay green (19 passed, in the same run as this pin).

The session behind this change is https://claude.ai/code/session_01D486C1axmXnrkJMNUfz2eb (domain:ui seat 3, dispatched dev).


Generated by Claude Code

…d object-gallery filter (objectui#10666)

RED against the unfixed ObjectGallery: the node sends `{current_user_id}`
and `{current_org_id}` literally on `$filter`. The list-view cell in the
same harness is the lit control and passes.

Co-Authored-By: Claude <noreply@anthropic.com>
…t-gallery filter (objectui#10666)

ObjectGallery sent its own `filter` on `$filter` with `{current_user_id}`
left literal. It now resolves the filter once through core's shared
`resolveFilterPlaceholders` against `useFilterScope()`, held by structure
with the same hook ListView has used since objectui#10607. That hook moves
unchanged from ListView.tsx into a package-internal module so both nodes
share it; the package export set does not move.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 7 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/7070-no-invented-gantt-date-fields.md

  • names plugin-list/src/ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    • app-shell/src/views/ObjectView.tsx — the console object page. The inline branch becomes ganttViewOptions, the sibling of calendarViewOptions and timelineViewOptions: the declared block spread whole, title floored at 'name', no date field invented. - plugin-list/src/ListView.tsx — the render branch AND the capability gate. - plugin-view/src/ObjectView.tsx — generateViewSchema, the authored object-view element route, which bypasses ListView entirely.

.changeset/7499-gantt-non-axis-floors-omitted.md

  • names plugin-list/src/ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    • plugin-list/src/ListView.tsx — the object-gantt render branch. - plugin-view/src/ObjectView.tsx — generateViewSchema, the authored object-view element route, which bypasses ListView entirely.

.changeset/7773-kanban-adapter-groupfield-write.md

  • names ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    Who is NOT affected — the boundary is node-local. Every VIEW-LEVEL groupField read is untouched and still live: it is a legacy alias of the spec's groupByField on the kanban view config, mapped by normalize-list-view.ts, and both adapters still resolve lanes through it (ObjectView.tsx's kanbanCfg.groupField ||, ListView.tsx's groupByField || groupField). Authoring options.kanban.groupField on a list-view or object-view keeps working exactly as documented in packages/plugin-list/README.md. groupField is dead only on the generated object-kanban NODE.

.changeset/7780-object-kanban-record-source.md

.changeset/8990-object-kanban-groupby-optional.md

  • names packages/plugin-list/src/ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    • packages/plugin-list/src/ListView.tsx generates the node as groupBy: laneField. objectDef loads asynchronously, so laneField is undefined on every load until it lands, and stays undefined whenever the object offers no stageField hint and none of status / stage / state / phase. The renderer serves that node; both published faces refused it. - content/docs/utilities/data-objectstack.mdx documents an object-kanban node that is exactly { type, dataSource }, with no groupBy. ⚠️ This one is weaker and is cited for what it is: that fragment is still refused after this change, at RECORD_SOURCE_REQUIRED, because dataSource is not a rung of the record-source ladder. It shows a lane-less board is a documented authoring; it is not a document this change admits.

.changeset/list-user-actions-collision-5398.md

  • names ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    The harvest now reads the object block only. Both userActions read sites in ListView.tsx carry a comment naming the collision, and __tests__/ListView.userActionsCollision.test.tsx pins each clause of it: the two shapes, a producer that manufactures the view one, the harvest's blindness to it, and the projection that must keep the object's operand with a toolbar block — or an empty block — present on the view.

.changeset/listview-comment-pair-4559.md

  • names ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    Two comment corrections in ListView.tsx (objectui#4559, objectui#4966). No runtime behaviour changes and the emitted bundle is byte-identical; the published .d.ts does change, which is why this is a patch rather than an empty frontmatter.

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Compared the checked-out tree with bc97f9247 (merge-base with origin/main): 4 file(s) changed outside .changeset/, read against 1534 pending declaration(s) that publish a body (2120 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3060.6 KB 3104.5 KB
Main entry chunk (gzip) 148.3 KB 350 KB
Entry file index-DUex3T82.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.57KB 6.15KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.17KB 10.58KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 547.33KB 130.98KB
core (index.js) 9.52KB 3.79KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 223.91KB 62.28KB
fields (index.js) 259.18KB 65.61KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.28KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.52KB 14.64KB
plugin-charts (index.js) 80.42KB 22.22KB
plugin-chatbot (index.js) 198.40KB 47.22KB
plugin-dashboard (index.js) 133.85KB 35.54KB
plugin-designer (index.js) 216.25KB 44.39KB
plugin-detail (index.js) 232.85KB 61.58KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 152.55KB 39.16KB
plugin-gantt (index.js) 169.71KB 41.93KB
plugin-grid (index.js) 216.70KB 59.29KB
plugin-kanban (index.js) 48.36KB 15.09KB
plugin-list (index.js) 115.91KB 28.80KB
plugin-map (index.js) 22.85KB 7.58KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.55KB 11.99KB
plugin-timeline (index.js) 30.84KB 9.01KB
plugin-tree (index.js) 10.52KB 3.69KB
plugin-view (index.js) 87.83KB 22.01KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 116.21KB 38.14KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.78KB 2.56KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.20KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

✅ ACCEPTED — PR objectui#10705 at 59d06fcbf (objectui#10666, the measured object-gallery node)

domain:ui seat 3, session_01D486C1axmXnrkJMNUfz2eb, 2026-09-25T19:31Z. Clause-②: no: nothing is exported, and the hook is package-internal.

Reviewed: the diff was read at the head.

  • ObjectGallery resolves its own filter through core's resolveFilterPlaceholders with useFilterScope(). The resolved value is held by structure in useResolvedAuthoredFilter, which is PR objectui#10656's hold moved unchanged out of ListView.tsx into a package-internal module.
  • ListView now imports that hook. There is no second resolver and no copy.
  • The query and the fetch effect's dependency list read the held value, never the raw schema.filter.

Measured (the real SchemaRenderer, under a FilterScopeProvider with user usr_42 and org org_7):

  • Before the fix, object-gallery sent {current_user_id} and {current_org_id} literally, while the list-view control sent usr_42.
  • After the fix, it sends the resolved values.

Pins:

  • RED at 8f38562d8: 5 of 8 failed.
  • GREEN: this pin plus both objectui#10607 pins pass 27/27.
  • The ablation, a per-render bare resolve, makes 3 cells fail: no fetch for the same node, plus timeouts. The restore was verified by blob hash.
  • The full plugin-list suite passes 1169 tests.

Gates:

  • plugin-list type-check exits 0.
  • Lint: rule counts are the same as on the base.
  • These all exit 0: changeset claims, literals, citations, control bytes, presence, no-major, overwrite, fixed; the vi-mock trio; test-path roots; unreferenced sources; phantom deps; self-import; type-check coverage.
  • The census passes 7/7.
  • Trailers are model-free.

The PR says Part of #10666, and it keeps that. The card is the family's closure card, and 11 nodes remain. See the seat answer on the card.

Next: ready + auto-merge once CI is green on this head.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 25, 2026 19:42
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 25, 2026
Merged via the queue into main with commit c610990 Sep 25, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-10666-filter-token-closure branch September 25, 2026 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant