Skip to content

docs(plugin-grid,types): state onNavigate as the documented non-author exception - #6209

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-5234-onnavigate-documented-exception
Aug 25, 2026
Merged

docs(plugin-grid,types): state onNavigate as the documented non-author exception#6209
yinlianghui merged 2 commits into
mainfrom
claude/issue-5234-onnavigate-documented-exception

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#5234

Execution of the maintainer ruling of 2026-08-19 (Option C, verbatim 「全部接受」): ObjectGridSchema.onNavigate stays declared, stays read, and is now stated as the explicit, documented exception. Zero behaviour change — every line added to a code file is a comment (proof below); the key is neither removed (option A) nor added to GRID_QUERY_INPUTS (option B).

All gates below were run at head f33928ab3 with a clean tree.

What landed

FileChange
packages/plugin-grid/src/ObjectGrid.tsxexemption comment at the schema read site — +30 / −0, all // lines
packages/types/src/objectql.tsprogrammatic-only note on the declaration — +23 / −0, all doc-comment lines
packages/plugin-grid/src/__tests__/gridNonAuthorKeys.test.tsx+264 / −0 — extended, never rewritten
packages/plugin-grid/README.mdthe one real content correction (see below)
content/docs/plugins/plugin-grid.mdxnames the one callback that is read
.changeset/…mdempty frontmatter — this repo's explicit "releases nothing" declaration

Comment-only, proven mechanically rather than asserted: every + line in the two code files was matched against ^\+\s*// and ^\+\s*\* respectively, with zero offenders and zero deletions. The emitted JS and the public type surface are byte-identical, which is why the 43-package downstream direction is uninteresting on the merits and was still swept (below).

Re-derived line numbers — the card's own history is why

The card went wrong by carrying a grep range into a decision without re-running it, so every site was re-measured on today's origin/main:

SiteCard saysMeasured on origin/main today
onNavigate declaration, objectql.ts:847:847unchanged
ObjectGridSchema span532–888532–888unchanged
schema read, ObjectGrid.tsx:1187:1334stale by 147 lines
GRID_QUERY_INPUTS in index.tsxno hitno hitabsent, as ruled

The two packages/types numbers survived five PRs by coincidence, not by stability. The read-site number did not. On this branch the declaration span becomes 532–911 and the read lands at :1364.

onNavigate also appears twice more in objectql.ts (:1509 on ObjectViewSchema, :1796 on ListViewRuntimeProps) — different interfaces, untouched. The new tests bound their search to the ObjectGridSchema span for exactly that reason.

Serial-contention check, as asked: the read site is a single hunk at 1331–1364. withSortability (PR #6109, now merged and in this branch's base) is at :2465 — about 1,100 lines away. Not adjacent, no overlap.

PR #5241's pattern, as found

Its body specifies four elements at a read site: the verdict in the words "deliberately absent from GRID_QUERY_INPUTS"; the ruling that made it deliberate (maintainer, date, issue); who writes the key, as file:line; and the contract's own verdict plus a pointer to the test. Read back off main, the columnState and hideRowHeightToggle comments carry exactly that, closing on "Both halves — unlisted here, rejected there — are pinned by __tests__/gridNonAuthorKeys.test.tsx … so this exemption cannot decay into a silent drop."

That shape is mirrored, not reinvented. One element is adapted, deliberately: element 3 wants the producer as file:line, and this key has none — nobody writes it, which is the whole ruling. The comment states the honest analogue instead: it is a function value, no document can carry it, and programmatic callers should use ObjectGridComponentProps. A file:line there would have been fiction.

The other difference is stated in the comment itself: the four #5091 keys are cast reads because @object-ui/types does not declare them; this one is a plain read because it is declared. The comment says out loud that this is not index-signature drift — the withdrawn reading — so a later reader cannot re-derive the error the card made.

The docs sentence — the dispatch's assumption was half wrong

The dispatch said the sentence "was already narrowed … if it is already correct, say so and leave it." Measured on main, that is true of one page and false of the other:

  • content/docs/plugins/plugin-grid.mdx:416already narrowed to "never reads any of these nine". Left alone.
  • packages/plugin-grid/README.md:516still carried the un-narrowed universal, "never reads a callback off the schema", which this very key falsifies. Narrowed to match.

That README line is the one factual correction in this PR. Both pages now also name the one callback that is read. (packages/plugin-grid/CHANGELOG.md:415 carries the old wording too; changelog history is not edited.)

The test — extended, and aimed at the thing that can move

gridNonAuthorKeys.test.tsx: 31 → 41 cases, 36 → 57 expect( calls, +264 / −0 lines. Nothing existing was touched except three added node: imports. Counts are from vitest list, not from reading the file.

Which assertions would still pass on a revert — stated plainly

Seven of the ten new cases would still pass if this PR were reverted, and that is by design: not-published, spec-rejects-by-name, parser-says-unknown-prop, the type still declares it, the nine siblings are still props-only, and the renderer still reads it were all true before this card. They are the ledger's premises — they stop the exemption decaying — but on their own they would pin nothing about this card.

Three cases can tell the two states of the world apart, and they are the deliverable:

  1. the read site carries the exemption comment (fails on revert);
  2. the declaration carries the programmatic-only note (fails on revert);
  3. the four ObjectGrid 用 (schema as any) 读的 4 个键不在 GRID_QUERY_INPUTS 里 —— #4648 要消除的「渲染器读得到、声明面否认」在这些键上仍然存在 #5091 exemptions are still present — the control that stops 1 and 2 passing vacuously.

Because the ruling's deliverable is prose, these read the source, the way ObjectGrid.exportOptionsKeys.test.ts in the same directory already does. Each is anchored on text that exists in both states (the read line itself, the declaration line itself), so a red means the comment went missing, never that the anchor moved.

Ablations — four legs, all predicted before running, all matched

Committed first; each mutation proved on disk by grepping the removed text and a separately injected marker; anchor uniqueness asserted before writing; landing site printed; restored under trap … EXIT INT TERM with absolute paths; git diff HEAD --stat empty afterwards.

legmutationpredictedobserved
Adrop the onNavigate exemption comment (30 lines → 1 marker)1 red: the read-site doc case1 failed | 40 passed — exactly that case
Bremove the #5091columnState exemption marker1 red: the control case1 failed | 40 passed — exactly that case
Cdeclare onRowClick on ObjectGridSchema1 red: the nine-siblings case1 failed | 40 passed — exactly that case
Ddelete the onNavigate: schema.onNavigate read2 red: behavioural + the doc case losing its anchor2 failed | 39 passed — exactly those two

No rebuild leg is owed, and this was verified rather than assumed:vitest.config.mts:256+ aliases @object-ui/* to src and the suite imports ../ObjectGrid relatively, so no dist is in the resolution path; @objectstack/spec is the untouched published build in node_modules. Same finding PR #5241 recorded.

Gates — command, exit code, and what a red would have meant

Derived by enumerating each CI job's own step list (ci.yml, lint.yml, changeset-presence.yml, changeset-guard.yml, control-bytes.yml, doc-component-types.yml), not from top-level script names. Exit codes captured by redirecting first, never after a pipe.

gateexita red would have meant
pnpm exec vitest run packages/plugin-grid/src/__tests__/gridNonAuthorKeys.test.tsx --maxWorkers=20 — 41 passedthe pin itself is broken
pnpm exec vitest run packages/plugin-grid/ --maxWorkers=20 — 86 files, 821 testsa comment edit disturbed a contended file
pnpm --filter @object-ui/types type-check0the doc note broke the declaration (incl. tsconfig.examples.json)
pnpm --filter @object-ui/plugin-grid type-check0the read site stopped compiling
pnpm --workspace-concurrency=2 --filter '...@object-ui/types' type-check0 — 42 packages, incl. 3 examples/*a consumer disagreed with the rebuilt types
pnpm --filter @object-ui/plugin-grid lint (eslint .)0 — 0 errors, 679 warningsa new error; the 9 warnings in the test file are all pre-existing lines
pnpm --filter @object-ui/types lint (eslint .)0 — 0 errors, 240 warningssame
node scripts/check-changeset-presence.mjs0the empty-frontmatter declaration was not accepted
node scripts/check-changeset-fixed.mjs / -no-major.mjs0 / 0a bump policy violation
node scripts/check-control-bytes.mjs0 — 5080 filesa raw control byte in the new prose
node scripts/check-doc-component-types.mjs0 — 183 docsthe docs edit named an unregistered type
node scripts/check-lint-coverage.mjs0 — 46/46a package fell out of lint coverage
node scripts/check-type-check-coverage.mjs0 — 45/46same for type-check
node scripts/check-phantom-dependencies.mjs0 — 316 node builtinsthe three new node: imports were undeclared
node scripts/check-package-self-import.mjs0the test named its own package

Non-vacuity: every pnpm --filter run echoed its script name, and the downstream sweep printed 42 type-check: Done lines with zero "No projects matched the filters" — so none of these is the zero-match green that exits 0 having run nothing. @object-ui/types was rebuilt before the plugin-grid type-check, so that green is over rebuilt dist/*.d.ts (the note reaches dist/objectql.d.ts), not yesterday's.

Direction demonstrated for the downstream sweep: prefix '...@object-ui/types' resolves to 43 packages (consumers); suffix '@object-ui/types...' resolves to 1 (upstream deps — types has none). Opposite directions; the prefix form is the one run.

Declared narrowings

  • check-doc-snippet-types.mjs not run locally. It turbo-builds every package the covered snippets import. The docs edits add zero code fences (measured: git diff … | grep -c '^+```' = 0), so no snippet changed. CI runs it.
  • check:published-dist not run locally — it builds every published package and exceeds the budget on a container shared with other agents. The only new file is under packages/plugin-grid/src/__tests__/, which packages/plugin-grid/tsconfig.json already excludes. CI runs it.
  • Repo-wide pnpm lint narrowed to the two affected packages. The population is eslint's own per-package config, not a hand-picked file list; type-aware linting is not enabled (no projectService / parserOptions.project in eslint.config.js), so this diff cannot move the verdict on any untouched file.

Provenance

The branch's implementation commit was pushed by an earlier run of this same claim that died before opening a PR; nothing was force-pushed and no other agent's work was touched. Everything above was re-measured from scratch on this run.

Neighbouring cards referenced for context only, and left open — #5091 (the four ruled keys), #5240 (userActions), #4648 (the prior round), PR #5241 (the pattern). None of them is addressed here.


Generated by Claude Code

…hor exception
Maintainer ruling of 2026-08-19 on objectui#5234, option C. Zero behaviour
change: an exemption comment at the `ObjectGrid.tsx` schema read site in the
shape objectui#5091 / PR #5241 established, a programmatic-only note on the
`@object-ui/types` declaration, the README sentence narrowed to match the docs
page, and `gridNonAuthorKeys.test.tsx` extended rather than rewritten.
The key is a function value and a schema is a serialisable document, so it can
never survive a metadata round-trip whatever declares it. It is deliberately
kept (not option A, a breaking public type change for zero measured harm) and
deliberately not published to `GRID_QUERY_INPUTS` (not option B, an offer no
author can take).
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 52 chunks)3221.3 KB3990.2 KB
Main entry chunk (gzip)153.7 KB350 KB
Entry fileindex-C7xifsvv.js
StatusPASS

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

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)10.38KB3.90KB
app-shell (runtime-config.js)18.10KB6.51KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)505.15KB114.53KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)168.48KB46.47KB
fields (index.js)238.40KB59.89KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)38.95KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.53KB3.38KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.64KB1.50KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)1.93KB0.88KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.66KB18.32KB
plugin-chatbot (index.js)188.21KB44.67KB
plugin-dashboard (index.js)133.35KB34.45KB
plugin-designer (index.js)212.30KB42.80KB
plugin-detail (index.js)244.14KB61.94KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)126.07KB30.78KB
plugin-gantt (index.js)164.15KB39.88KB
plugin-grid (index.js)201.05KB54.38KB
plugin-kanban (index.js)52.89KB14.59KB
plugin-list (index.js)111.86KB27.22KB
plugin-map (index.js)20.11KB6.64KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.49KB11.93KB
plugin-timeline (index.js)26.49KB7.59KB
plugin-tree (index.js)9.26KB3.13KB
plugin-view (index.js)84.57KB20.74KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)54.84KB18.43KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.35KB0.70KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)12.13KB3.65KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)7.54KB2.63KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.49KB2.14KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@yinlianghui
yinlianghui marked this pull request as ready for review August 25, 2026 02:41
@yinlianghui
yinlianghui added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit 737eed9Aug 25, 2026
26 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-5234-onnavigate-documented-exception branch August 25, 2026 02:53
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationpackage: typesplugintests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Decision] schema.onNavigate is a function value read off the grid schema — the fifth key #5091's ruling did not cover

2 participants

@yinlianghui@claude