Skip to content

feat(plugin-list,app-shell): read an absent userActions.editInline as on, the v18 spec default (objectui#12086) - #12092

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-12086-edit-inline-default-on
Oct 10, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-12086-edit-inline-default-on

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #12086

Clause-②: no

The consumer half of objectstack-ai/objectstack#22605 (the v18 default flip, landed as objectstack-ai/objectstack#22629). List views read an absent userActions.editInline as on (!== false): a list view is editable in place by default, under the permission gate that already exists, and userActions: { editInline: false } makes it read-only in place. The inlineEdit fold is unchanged, and so is the gate.

What changed

  • ListView (@object-ui/plugin-list): inlineEditOffered returns false only for an explicit editInline: false; anything else falls through to the unchanged listInlineEdit affordance verdict (the object editable in place, and the principal's update grant). The Gap 2 docblock now states the v18 default and the opt-out.
  • ADR-0047 interface page (@object-ui/app-shell, InterfaceListPage): inlineEdit: userActions.editInline !== false, and the "default off" comment is corrected.
  • Pins (each kept load-bearing by a twin that differs in one input):
    • ListView.permissions.test.tsx: a view that declares nothing is offered the toggle for a principal with update and not for one without it (same schema, permission differs); with no PermissionProvider it is offered (fail-open kept); an absent editInline reads on and the grid opens out of edit mode; the compact popover offers the entry for an absent key, and its control withholds it for editInline: false; editInline: false withholds the toggle from a fully permitted principal. The stored inlineEdit: true case (offered, opens in edit mode) is unchanged and still green.
    • InterfaceListPage.editInlineFold-5144.test.tsx: an absent page editInline, and a page with no userActions block, now read on on both sides of the fold; an explicit editInline: false is the opt-out.
    • normalize-list-view.inlineEditFold-5144.test.ts: the fold's table is unchanged (the fold applies no default); its docblock now says which reader the flip changes.
  • Docs: content/docs/plugins/plugin-view.mdx, the "neither key" row of the inline-editing table now reads "offered | no" (opens out of edit mode), and the prose says on by default, with editInline: false as the opt-out.
  • Changeset: .changeset/12086-edit-inline-default-on.md, minor for @object-ui/plugin-list and @object-ui/app-shell, with the behaviour change in the prose.

Measured before writing (the PM's three mechanism assumptions)

  1. The spec half is on objectstack origin/main. packages/spec/src/ui/view.zod.ts declares editInline: z.boolean().default(true) (read with git show origin/main:; git merge-base --is-ancestor f53f14bb36 origin/main answered exit 0, which self-certifies). The installed @objectstack/spec here is 17.7.0, whose dist still declares editInline: z.boolean().default(false). Does any objectui code read the installed default? No runtime reader does. The quoted-name grep for UserActionsConfigSchema and for ListViewSchema / ViewSchema .parse( / .safeParse( across packages/*/src and apps/ finds the parse calls only in tests and in two FormViewSchema reads (positive control: the same grep finds those two). The one test that parses the installed defaults, normalize-list-view.foldOutputAuthorable-5435.test.ts ("the ON/OFF default asymmetry"), asserts group / hideFields / rowColor only, not editInline, so it does not fight the new read. One display-only reader exists: the metadata-admin View inspector derives its JSON Schema from the installed ViewSchema with z.toJSONSchema. It writes nothing, and its boolean switch renders !!value and ignores a schema default. See Acceptance notes.
  2. The two sites are the only absent-as-off readers. Every editInline reader in packages/*/src outside tests, from the quoted exact-name grep (positive control: the same grep hits the known ListView.tsx and InterfaceListPage.tsx sites): ListView inlineEditOffered (was !== true); InterfaceListPage (was === true); the normalizeListViewSchema fold (typeof === 'boolean', no default); and the @object-ui/plugin-view ObjectView userActions merge (a spread of three folded layers, no default). The other hits are comments, the detail.editInline* i18n keys (a different namespace), and the grid's own userActions comments. The assumption holds. The inlineEdit readers carry the edit MODE (!!schema.inlineEdit, the named-view relay, ObjectGrid's editable); none reads an absent editInline as off.
  3. The cloud window (see below). No example app or fixture in this repo declares nothing and relies on the old default for a read-only list through a ListView-rendered path. The quoted grep for editInline, inlineEdit and userActions over apps/ and examples/ hits 0 (positive control: the same grep finds listViews / object-grid / object-view there). The list views that do exist there (examples/byo-backend-console's object-view with a named grid view, the schema-catalog object-view / object-grid entries, apps/console's dev object-grid) render through ObjectGrid directly, with no host renderListView. On that path ObjectGrid's editable comes from the view's inlineEdit and never from editInline, so this change does not move them.

The cloud window (named, as triage directs)

Cloud consumes objectui main on its frozen v17 framework. There, a list view that declares neither userActions.editInline nor inlineEdit now offers the inline-edit toggle on the console object page. An ADR-0047 interface page that declares nothing now opens its grid editable in place. Both happen before cloud's spec says the default is on. Both stay under the permission gate: a principal without update on the object, or an object that is not editable in place, gets neither. This is the maintainer's chosen posture, so no hold is asked for. The cloud apps are not in this container, so whether any cloud view relied on the v17 default for a read-only list was not measured here. The spec card's own measurement names one cloud interface page that already declares editInline: false explicitly. That is a reading carried from objectstack-ai/objectstack#22605, not re-taken here.

One mechanism note for the seat (the interface page)

The interface page wires no inline-edit toggle: no onInlineEditChange, no compactToolbar. Its userActions.editInline therefore reaches ListView as the grid's edit MODE (inlineEdit), which the fold also turns into the "offered" key. So with this flip, an interface page that declares nothing does not "gain the toggle". It opens its grid editable in place, for a principal the gate admits. That is what the card's !== false orders for this site, and it is what the spec's new describe says ("a user who may update the object edits a cell in place"). A literal toggle on this page would be a new host wiring and is not done here. It is raised in the report.

File surface

Within the claim: ListView.tsx (inlineEditOffered and its docblock), InterfaceListPage.tsx (the read and its comment), ListView.permissions.test.tsx, normalize-list-view.inlineEditFold-5144.test.ts, the interface-page tests (InterfaceListPage.editInlineFold-5144.test.tsx, and the inlineEdit reason string in InterfaceListPage.relayCensus-11572.test.ts), plugin-view.mdx, and one changeset.

In-surface consequences: comments and test titles this flip made false. These are text-only, with no code or assertion change, and they sit outside the claim's file list:

  • packages/core/src/utils/normalize-list-view.ts: two docblocks said the spec default is .default(false) and that ListView reads an absent pair as off.
  • packages/app-shell/src/views/ObjectView.tsx: the keepInlineEditModeForTheSession docblock quoted the v17 describe ("the list is read-only unless the author opts in").
  • packages/app-shell/src/views/ObjectView.inlineEditSessionOnly-5144.test.tsx: one test title said "reads off by the spec default". Its assertion (the fold leaves both keys absent) is unchanged.
  • packages/plugin-list/src/__tests__/ListView.test.tsx: two comments cited the spec's .default(false).
  • packages/plugin-view/src/__tests__/ObjectView.namedViewEditInlineFold-5144.test.tsx: the docblock said ListView offers inline editing "only where that reads true".

Nothing is added to a package entry: no prop, export, type member or locale key.

Verification

All runs below are on this branch. Heavy runs went through the shared verify lock, and each line quotes that run's own VERDICT command-exit line. Test runs use the repo-root form pnpm exec vitest run --maxWorkers=2 PATHS.

  • Targeted pins, on the final head 9cd778d1d (after merging origin/main de302c73): the four touched pin files, the five other InterfaceListPage* tests, ObjectView.inlineEditSessionOnly-5144, the two normalize-list-view fold tests and the plugin-view named-view fold test. Result: Test Files 13 passed (13), Tests 264 passed (264), VERDICT command-exit 0. The same 13 files gave the same counts on efa9e08f1, before the merge.
  • @object-ui/plugin-list, whole package, on efa9e08f1, plus the four app-shell ObjectView tests that render the real ListView with role-based button queries or import the interface page (kanbanLane-8193, storedOptionsBag-10380, listUrlState-11860, viewWriteRefusal-11583). Result: Test Files 129 passed (129), Tests 1444 passed (1444), VERDICT command-exit 0.
  • Ablation (a one-time proof; no test file kept). Each leg was run from the committed head through ablation-replace.mjs, whose anchor hit x1 and went to x0, and whose blob changed. Each was restored to the HEAD blob with git diff HEAD empty, so the restore was proven on disk.
    • Leg A put the v17 read back into inlineEditOffered (?.editInline !== true). ListView.permissions.test.tsx went 4 failed | 19 passed (23). The four red cases are exactly the predicted ones: offered with update on a view that declares nothing; offered with no PermissionProvider; an absent editInline reads on; the compact entry is offered for an absent key. "WITHOUT update loses it" stays green under both reads, as expected.
    • Leg B put inlineEdit: userActions.editInline === true back on the interface page. InterfaceListPage.editInlineFold-5144.test.tsx went 2 failed | 2 passed (4): the two absent cases.
  • Type-check (pnpm --filter PKG type-check, which is tsc --noEmit && tsc -p tsconfig.test.json), after building the dependency closure with turbo run build --filter=PKG^... --concurrency=2 (28 successful, 28 total). @object-ui/core, @object-ui/plugin-list, @object-ui/plugin-view and @object-ui/app-shell all exit 0 with 0 error TS on efa9e08f1. @object-ui/app-shell exits 0 again on 9cd778d1d, since main's two merged PRs touched app-shell source.
  • eslint on the 11 touched .ts / .tsx files (--format json, counted from its output): 0 errors. Every file's error/warning count is identical to its base-blob count (lint run over git show 023f00d46:FILE via --stdin). The repo's eslint.config.js sets no parserOptions / projectService, so linting is not type-aware, and this diff cannot move a verdict on an untouched file.
  • Gates, re-run on 9cd778d1d: check:new-line-citations (0 new citation(s)), check:control-bytes, check-changeset-presence, changeset:check (no major), check-changeset-overwrite, check:changeset-claims, check:pending-changeset-literals, check:doc-fences, check:doc-types and check-doc-links. All exit 0. The four vi.mock / test-path gates exit 0 on efa9e08f1.
  • NOT MEASURED: check:doc-snippets and check:doc-examples. Reason: exit 2, PREREQUISITE NOT MET. Both need a scoped build of more packages than this run built (app-shell, cli, plugin-ai … unbuilt). Their input is unchanged by this diff, measured instead. The fenced blocks of plugin-view.mdx extracted at base and at head are byte-identical (md5 3fd26d2a… both, 18 blocks). The diff touches 0 lines carrying @example or a fence in packages/*/src. Control: ListView.tsx carries one @example, which is untouched.
  • Declared narrowing: @object-ui/app-shell's full suite was not run locally; CI runs it. The local app-shell set is every test that imports InterfaceListPage, the session-only toggle pin, and the ObjectView tests above. This is a declared narrowing, not a proof that nothing else in app-shell observes the toggle.

Acceptance notes

Observations only. Not filed, and not changed here.

  • Metadata-admin View inspector shows default-true booleans as off. SchemaForm's boolean branch renders checked={!!value} and ignores the JSON Schema default. So in the View inspector, an absent userActions.search / sort / filter (default true) already shows OFF while the toolbar reads it ON. userActions.editInline joins that set once objectui installs a spec 18 build. The installed 17.x schema still says default: false, so the switch shows off either way, and after this PR the list reads on. This was read from source; no public door was exercised, so it is not filed. Carrier: none.

  • The direct ObjectGrid path does not read editInline. On an authored object-view with a named grid view and no host renderListView, ObjectGrid's editable is the named view's inlineEdit (or table.editable). userActions.editInline is not read there. So editInline: false does not withhold edit mode from a named view that also says inlineEdit: true, and a view with neither key has no toggle to enter edit mode. This predates and is unchanged by this PR. No named producer declares both keys on such a view, so it is not filed. Carrier: none.

  • The pending objectui#5144 changeset — corrected in this PR (patch round, the seat's answer B; written into this body by the seat, domain:ui seat 3). .changeset/5144-editinline-fold.md is unreleased, and in net it stated the opposite default to this release. This PR's change made it false, so it is corrected here. Its frontmatter is byte-identical (same bump declarations). Before → after:

    1. "List views read userActions.editInline with the spec's default, off." → "… with the spec's default, on since spec: ListView.userActions.editInline defaults to true in v18 and editInline: false is the opt-out; objectui reads an absent key as on (maintainer ruling 2026-10-10, after objectui#5144) objectstack#22605 (editInline: z.boolean().default(true)), and editInline: false is the opt-out."
    2. "Breaking for a view that relied on the old default." → "The spec's default, read as declared."
    3. "The spec declares userActions.editInline with .default(false): the list is read-only unless the author opts in." → "… with .default(true) (spec: ListView.userActions.editInline defaults to true in v18 and editInline: false is the opt-out; objectui reads an absent key as on (maintainer ruling 2026-10-10, after objectui#5144) objectstack#22605): a list view is editable in place by default, under the permission gate, and editInline: false is the opt-out."
    4. "The interface page already read it that way." → deleted. The paragraph now closes with "The flip of the default, and the interface page that reads it, are the objectui#12086 entry of this release."
    5. "The object-list toolbar did not: it read …" → "The object-list toolbar used to read …". Only the lead-in changed, because it leaned on the deleted sentence 4.
    6. "A grid view that declares neither … no longer offers the inline-edit toggle … and never opens in edit mode." → "… offers the inline-edit toggle, on the wide toolbar and in the compact settings popover, and opens out of edit mode."
    7. "- a view with neither key reads off." → "- a view with neither key reads on, the spec's default."
    8. "What to do. A view that should offer inline editing declares userActions.editInline: true. The toggle then stays offered whatever the user does with it." → "What to do. A list whose records are read-only by nature declares userActions.editInline: false. A view that declares userActions.editInline: true keeps the toggle offered whatever the user does with it."

    Unchanged: the other fold bullets, the session-only toggle, the named-view precedence, the two costs and the no-export line. This PR's own .changeset/12086-edit-inline-default-on.md was corrected in the same round, because its quote of the deleted 5144 sentence became false. It now says the previous release (17.7.0) also offered the toggle for an undeclared view, measured from the parent of objectui#12036, and the interface-page heading carries the behaviour change.


Generated by Claude Code

… on, the v18 spec default (objectui#12086)

ListView's inlineEditOffered and the ADR-0047 interface page now read an
absent `userActions.editInline` as on (`!== false`), the consumer half of
objectstack#22605. The permission gate and the inlineEdit fold are
unchanged. Pins flip to "declares nothing + update grant -> offered",
"declares nothing + no update grant -> not offered" and
"`editInline: false` -> not offered"; comments and test titles the flip
made false are corrected.

Claude-Session: https://claude.ai/code/session_01B1gHb9baeX7oioD5sHVm7z
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 290 chunks) 3169.6 KB 3204.6 KB
Main entry chunk (gzip) 73.7 KB 350 KB
Entry file index-C470nIv6.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) 19.75KB 7.29KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
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.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
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) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
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.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 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) 587.83KB 141.44KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 240.39KB 67.09KB
fields (index.js) 269.55KB 68.24KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
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.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.26KB 11.71KB
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) 14.32KB 5.17KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
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.04KB 3.92KB
plugin-calendar (index.js) 53.43KB 15.54KB
plugin-charts (index.js) 84.72KB 23.27KB
plugin-chatbot (index.js) 201.52KB 47.99KB
plugin-dashboard (index.js) 144.20KB 38.95KB
plugin-designer (index.js) 233.53KB 49.80KB
plugin-detail (index.js) 249.19KB 65.68KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.30KB 45.92KB
plugin-gantt (index.js) 179.17KB 45.07KB
plugin-grid (index.js) 249.43KB 69.15KB
plugin-kanban (index.js) 52.77KB 16.56KB
plugin-list (index.js) 120.09KB 30.25KB
plugin-map (index.js) 27.24KB 9.03KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
plugin-timeline (index.js) 39.06KB 11.80KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.93KB 23.24KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
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) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
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) 1.13KB 0.65KB
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) 5.78KB 2.70KB
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 (node-slots.js) 7.18KB 2.34KB
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) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
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

…ctui#5144 entry (objectui#12086)

The pending objectui#5144 changeset stated the absent-key default as off.
With objectui#12086 in the same release that is false in net, so its
default sentences now read on (objectstack-ai/objectstack#22605), with
`editInline: false` as the opt-out, and point to the objectui#12086 entry
for the flip. Frontmatter unchanged. This PR's own changeset drops its
quote of the old 5144 sentence and says the previous release already
offered the toggle for an undeclared view.

Claude-Session: https://claude.ai/code/session_01B1gHb9baeX7oioD5sHVm7z
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 290 chunks) 3169.6 KB 3204.6 KB
Main entry chunk (gzip) 73.7 KB 350 KB
Entry file index-C470nIv6.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) 19.75KB 7.29KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
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.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
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) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
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.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 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) 587.83KB 141.44KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 240.39KB 67.09KB
fields (index.js) 269.55KB 68.24KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
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.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.26KB 11.71KB
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) 14.32KB 5.17KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
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.04KB 3.92KB
plugin-calendar (index.js) 53.43KB 15.54KB
plugin-charts (index.js) 84.72KB 23.27KB
plugin-chatbot (index.js) 201.52KB 47.99KB
plugin-dashboard (index.js) 144.20KB 38.95KB
plugin-designer (index.js) 233.53KB 49.80KB
plugin-detail (index.js) 249.19KB 65.68KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.30KB 45.92KB
plugin-gantt (index.js) 179.17KB 45.07KB
plugin-grid (index.js) 249.43KB 69.15KB
plugin-kanban (index.js) 52.77KB 16.56KB
plugin-list (index.js) 120.09KB 30.25KB
plugin-map (index.js) 27.24KB 9.03KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
plugin-timeline (index.js) 39.06KB 11.80KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.93KB 23.24KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
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) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
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) 1.13KB 0.65KB
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) 5.78KB 2.70KB
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 (node-slots.js) 7.18KB 2.34KB
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) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
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

Spec Main Shape Gate red on 018710d6a5 is not this PR's · domain:ui seat 3, session_01B1gHb9baeX7oioD5sHVm7z, 2026-10-10T13:15Z

  • The failing check: Spec Main Shape Gate, check run 114220114102. It compiles objectui's tests against objectstack main's spec.
  • Why it is not this PR's:
    • The annotation set is identical, file and line, to the one anchored on objectui#12093: page-variables.test.tsx:213, record-picker-label-association.test.tsx:170, authoring-nodes-11364.test.ts:131/:143, element-repeater-data-source-11880.test.ts:242/:247, and grid-default-filters-gantt-map-filter-round10-6152.test.ts:219/:220/:234/:235.
    • None of those files is in this PR.
    • Each writes a flat element binding key or object-grid.defaultFilters, which objectstack PR #22421 (317cddd40d) retired. The gate is red for every objectui PR.
  • The fix: anchored on objectui#12093 and folded into objectui#12085's in-flight dispatch. It is not on main yet, so there is nothing to port. No re-run is spent: the gate would fail the same way.
  • This PR: ACCEPT 6097843854 stands. It stays a draft. When objectui#12093's fix is on main, it merges main and lands through the queue once every check is green.

Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 290 chunks) 3169.3 KB 3204.6 KB
Main entry chunk (gzip) 73.7 KB 350 KB
Entry file index-0g1kPOBC.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) 19.75KB 7.29KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
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.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
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) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
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.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 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) 586.66KB 141.23KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 240.39KB 67.09KB
fields (index.js) 269.55KB 68.24KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
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.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.26KB 11.71KB
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) 14.32KB 5.17KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
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.04KB 3.92KB
plugin-calendar (index.js) 53.43KB 15.54KB
plugin-charts (index.js) 84.72KB 23.27KB
plugin-chatbot (index.js) 201.52KB 47.99KB
plugin-dashboard (index.js) 144.20KB 38.95KB
plugin-designer (index.js) 233.53KB 49.80KB
plugin-detail (index.js) 249.19KB 65.68KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.30KB 45.92KB
plugin-gantt (index.js) 179.17KB 45.07KB
plugin-grid (index.js) 249.43KB 69.15KB
plugin-kanban (index.js) 52.77KB 16.56KB
plugin-list (index.js) 120.09KB 30.25KB
plugin-map (index.js) 27.24KB 9.03KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
plugin-timeline (index.js) 39.06KB 11.80KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.97KB 23.24KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
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) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
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) 1.13KB 0.65KB
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) 5.78KB 2.70KB
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 (node-slots.js) 7.18KB 2.34KB
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) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
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

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: a733363767b43f2a33074da2b1dcc3e855ce1a01
Local-runs: none

① Derived judgments

Read against the card (body and all five comments), the PR body and its 14-file net diff against main at the head, and the 43 check-runs on the head. Nothing was built or run; the tree was read with git show, git grep and git diff.

The default flip — right.

  • The spec on objectstack main declares editInline: z.boolean().default(true) in view.zod.ts (UserActionsConfigSchema), with the describe text the PR quotes ("a user who may update the object edits a cell in place … Declare editInline: false to make the list read-only in place"); f53f14bb36 (objectstack#22629) is an ancestor of objectstack origin/main. The maintainer's ruling on the card is the same sentence.
  • ListView.inlineEditOffered at the head returns false only for userActions.editInline === false; every other input falls through to the unchanged listInlineEdit affordance ({ crud: 'edit', grant: 'update' } in affordanceGrants.ts). The one moved token is the early-out predicate, !== true → === false. The edit mode still seeds from !!schema.inlineEdit, grid editable is still inlineEdit && inlineEditOffered, the wide toggle still needs the host's onInlineEditChange and no compactToolbar, and the compact entry needs inlineEditOffered alone.
  • InterfaceListPage at the head sets inlineEdit: userActions.editInline !== false; the userActions block it builds carries no editInline, and the page wires neither onInlineEditChange nor compactToolbar. So on that page the value is the grid's edit mode, not a toggle: a page that declares nothing opens editable in place for a principal the gate admits. That is the card's literal instruction for that line and the ruling's reading; the card's gloss "gains the toggle" was the filer's wording, and the gap is the dev's open question 1 (③).
  • The fold is unchanged: foldsInlineEditIntoEditInline applies no default (a boolean inlineEdit carries over only when editInline is not a boolean; inlineEdit survives), and the spec's view-level inlineEdit is .optional() with no default.
  • The two sites are the only non-test readers of editInline at the head (grep over packages and apps: ListView === false, InterfaceListPage !== false, the fold; the rest are comments and the unrelated i18n label key). No runtime path parses a list view through the installed 17.7.0 spec (the only non-test .parse / .safeParse hits are the two FormViewSchema reads the dev cited), so the installed .default(false) never reaches ListView; the console-path control pin (ObjectView.inlineEditSessionOnly-5144: a served view with no overlay folds to { editInline: undefined, inlineEdit: undefined }) is green on the head.
  • The card's acceptance is pinned with twins that differ in one input: declares nothing + update → offered; the same schema without update → not offered; editInline: false → withheld from a fully permitted principal; the stored inlineEdit: true case (offered, opens editable) is untouched and green.

.changeset/12086-edit-inline-default-on.md — every sentence true at this head.

  • "reads an absent editInline as on (!== false)": the code's === false early-out is the same predicate.
  • "offers the inline-edit toggle, on the wide toolbar and in the compact settings popover, and opens out of edit mode": wide toggle = onInlineEditChange && !compactToolbar && inlineEditOffered (the console object page wires onInlineEditChange to the session-only no-op keepInlineEditModeForTheSession); compact entry = showInlineEdit from inlineEditOffered; the mode seeds from an absent inlineEdit → out of edit mode. The host-channel precondition for the wide toggle predates both changesets and is unchanged.
  • "The previous release offered it there too … objectui#5144 read it off on unreleased main only": at tag @object-ui/plugin-list@17.7.0 (2026-10-04) inlineEditOffered early-outs on === false and an absent key falls through to the gate; objectui#5144 landed as 3c3115e38 (PR objectui#12036) on 2026-10-09, after the tag, with !== true; plugin-list is still 17.7.0 on main; the published 17.7.0 CHANGELOG itself says "the absent case of userActions.editInline defers to the host".
  • The interface-page paragraph, the three "Unchanged" bullets (gate, fold, session-only console toggle) and "What to do" (inlineEdit: false with no editInline folds to off; an explicit editInline: true skips the fold and wins) all match the code above.
  • "Nothing is added to a package entry": the diff adds no export, prop, type member or locale key.

.changeset/5144-editinline-fold.md edit — right. The eight amended sentences state the on-default, the opt-out, the toolbar's history ("used to read … defer to the host"), the neither-key row (offered, opens out of edit mode) and the pointer to the objectui#12086 entry; each holds at this head. The unchanged fold bullets, the session-only paragraph, the named-view precedence paragraph, the two costs and the no-export line remain true. The frontmatter (core: minor, plugin-list: minor, app-shell: minor, plugin-view: patch) is byte-identical: the diff's first hunk starts after it. check-changeset-overwrite is report-only by its own header, guarding against a lost release declaration; that hazard is absent here, and the Changeset Overwrite Report run on the head is success.

content/docs/plugins/plugin-view.mdx — right. The section is the renderListView → list-view node path, which is the ListView path. All five table rows hold there: neither key → offered / no; inlineEdit: true → offered / yes; inlineEdit: false → not offered / no; userActions.editInline: true → offered / only with inlineEdit: true; userActions.editInline: false → not offered / no whatever inlineEdit says (editable: inlineEdit && inlineEditOffered). The prose (on by default since objectstack#22605, editInline: false withdraws it, a stored inlineEdit: false still reads off and editInline: true brings the toggle back, neither key opens editing past the object's editability or the update grant) matches. The card said the table "gains" the neither-key row; the row pre-existed and its verdict flipped, which is the outcome the card asked for. No other doc, README or skill sentence at the head states the old default (grep for editInline and for the old-default phrasings outside CHANGELOGs, .changeset and tests: the one hit is this table's editInline: false row, which is correct).

The merge — clean. The head is a merge commit with parents 018710d6a5 (the accepted head) and ce991bd70 (origin/main, which carries objectui#12100). git diff 018710d6a5 a733363 restricted to the 14 PR files is empty (blob-identical); main touched none of the 14 in the whole fork window 023f00d46..ce991bd70, so blob-identity hides no dropped change; git diff --stat origin/main a733363 is exactly the 14 files, +163/−117, and the merge-base of origin/main and the head is origin/main itself. The merge carried no conflict resolution and nothing beyond main's own 22-file delta.

Public surface. One behavioural default flips for every consumer whose list view declares neither userActions.editInline nor inlineEdit: the console object page offers the toggle, the ADR-0047 interface page opens its grid editable in place, both only where listInlineEdit admits the principal. No accept set moves: editInline accepts the same booleans, and no key, export, prop or locale key is added or removed. The cloud window is named in the PR as triage directed, stated as not measured here (the cloud apps are not in the repo), and carries the spec card's reading of one cloud page that already declares editInline: false; the posture is the maintainer's, and no hold is asked for.

Check-runs on the head. 43 runs: 40 success, 3 skipped (two coverage shards and dependabot, the expected skips). Spec Main Shape Gate is success on this head (the objectui#12093 fix is in via objectui#12100), as are all eight Test shards, Test (dist pins), Type Check, Lint, Build & E2E, Build Docs, Doc Snippet Type Check and Doc Example Id Check (which answer the dev's two NOT MEASURED gates), and the five changeset gates (Declaration, Bump Policy, Claim Re-read, Overwrite Report, Fixed Group). Annotations: Lint's eleven are no-explicit-any warnings in e2e/live/*, none in this diff; Build & E2E's one failure annotation is a toast-under-modal harness flake that retried to success; the rest are the runner-image notice.

② Semver level

  • The diff publishes from @object-ui/plugin-list (ListView.tsx) and @object-ui/app-shell (InterfaceListPage.tsx; ObjectView.tsx docblock only), plus comment-only docblocks in @object-ui/core and a test in @object-ui/plugin-view. All four are in the fixed group, which bumps together.
  • The new changeset declares minor for plugin-list and app-shell, the two packages whose behaviour moves; core's change is comment-only and the pending objectui#5144 changeset already declares core: minor in the same release. Right.
  • The level is minor by objectui's version-alignment rule: the behaviour change (a view that declares nothing now offers the toggle; an interface page that declares nothing now opens editable in place) is breaking in semantics for a consumer that relied on the unreleased objectui#5144 default or on a 17.7.0 interface page reading absent as off, and the changeset prose states it with the opt-out. Neither changeset declares major; Changeset Bump Policy is success.
  • Clause-②: no is right. The diff adds and removes nothing an author can write: no spec key, export, prop, type member or locale key; the accept set of editInline is unchanged, so neither (widening) nor (narrowing) applies. The line sits at the start of a line in the PR body, as the readers require.
  • No model identifier appears in either changeset, the doc or the PR body.

③ Boundary flags

From the dev's os-dev-report (card comment 6097777181) and the seat's ACCEPT (6097843854):

Deviations (five) — each answered.

  1. File-surface increment: five text-only files outside the claim's list (normalize-list-view.ts docblocks, ObjectView.tsx docblock, one test title, two test comments, one test docblock). Verified against the diff: no code or assertion changed in any of them; each is a sentence the flip made false. The seat named them in-surface consequences. Answered.
  2. Test command form: the repo-root pnpm exec vitest run was used instead of the dispatch's package-cwd spelling, as objectui AGENTS.md mandates. Answered.
  3. Declared narrowing: the full app-shell suite was not run locally. The head's eight Test shards and Test (dist pins) are success. Answered by the check-runs.
  4. The shared checkout received only the rule-1 recipe writes (fetch, worktree add), later removed. Reporting only. Answered.
  5. Lock exit 99 and an HTTP 429 resume; verdicts re-read from logs and re-run on the merged head 9cd778d1d. Reporting only, and superseded by the check-runs on this head. Answered.

Open questions (two) — each answered by the seat, and the answer holds against the code.

  1. The interface page wires no toggle, so !== false opens an undeclared grid editable in place rather than adding a toggle. Seat: A, keep as landed. Consistent with the maintainer's ruling, the spec's describe text and the card's literal line for that site; option B (a session toggle on the page) stays available as a separate card. The changeset and the interface-page pin state the mode semantics plainly.
  2. The pending objectui#5144 changeset announced the opposite default for the same release. Seat: B, corrected in this PR (018710d6a5). Verified above: eight sentences amended, frontmatter byte-identical, before/after recorded in the PR body.

Out-of-scope findings (three) — each dispositioned.

  1. The 5144 release-text contradiction: resolved in this PR (the same matter as open question 2). Closed.
  2. The metadata-admin View inspector's boolean switch renders checked={!!value} and ignores a JSON Schema default (already true for search / sort / filter; editInline joins once a spec 18 build is installed). Pre-existing, display-only, read from source with no public door exercised; the seat recorded it as noted, not filed (carrier none). Answered.
  3. On the direct ObjectGrid path (no host renderListView) userActions.editInline is not read, so editInline: false does not withhold edit mode from a named view that also says inlineEdit: true. Pre-existing and unchanged; no in-repo producer declares both; the seat recorded it as noted, not filed (carrier none). Answered.

Other flags. The two NOT MEASURED local gates (check:doc-snippets, check:doc-examples) are answered by the head's Doc Snippet Type Check and Doc Example Id Check, both success. The cloud window (triage 6094438902) is stated in the PR and not measured here; the maintainer's posture stands. The seat's Spec Main Shape Gate note (6097890890) is moot on this head: the gate is success.

Implemented-by: claude/issue-12086-edit-inline-default-on
Reviewed-by: session_01B1gHb9baeX7oioD5sHVm7z

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 10, 2026 19:58
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 10, 2026 19:58
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 10, 2026
Merged via the queue into main with commit 5330afd Oct 10, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-12086-edit-inline-default-on branch October 10, 2026 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants