Skip to content

fix(plugin-list): read userActions.editInline with the spec default, folding a stored inlineEdit into it (objectui#5144) - #12036

Merged
objectstack-fleet[bot] merged 8 commits into
mainfrom
claude/issue-5144-editinline-fold
Oct 9, 2026
Merged

objectstack-fleet[bot] merged 8 commits into
mainfrom
claude/issue-5144-editinline-fold

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #5144

Clause-②: no (narrowing)

The maintainer's B-fold (hold record 5328162879, released and graded by triage in 6075214383). The accepted input set is unchanged: a stored inlineEdit is still accepted, and now folds into the spec key. What narrows is the object-list toolbar's reading of a view that carries no editInline: it was "defer to the host", and it is now off, the spec's .default(false).

Landing waits for the owning seat's contract-tier review of record on this PR. This PR is a dispatched draft; it is not mine to mark ready or queue.

What changes

  • The fold (@object-ui/core, normalizeListViewSchema). A boolean inlineEdit folds into userActions.editInline: the value carries over, and an explicit userActions.editInline wins in both directions. It sits beside SHOW_FLAG_TO_USER_ACTION and shares its fold block, the one-vocabulary pattern from Migrate the remaining ListView legacy vocabulary to spec-canonical keys, and audit ObjectView/DetailView (#2231 phases 4–5) #2890. A view with nothing to fold is still returned by reference.
  • inlineEdit is kept, not deleted. Every show* flag is deleted after it folds. inlineEdit cannot be: it is the spec's own ListView.inlineEdit, and ListView seeds the grid's edit mode from it, which the toolbar toggle then flips and the console persists. Deleting it would open every stored inline-edit view out of edit mode. This is the departure the file already documents for data to objectName ("Every other fold deletes because the legacy key has one meaning and one home"), and the new docblock foldsInlineEditIntoEditInline says so.
  • The reading (@object-ui/plugin-list, ListView). inlineEditOffered now reads userActions.editInline === true, which was !== false. The "Gap 2" docblock is rewritten to say what is true now. The edit mode is still the inlineEdit state, seeded from the view's inlineEdit.
  • InterfaceListPage is not edited. Its userActions.editInline === true reading is not made redundant by the fold. It supplies the edit mode as inlineEdit, and the page forwards no editInline of its own, so the fold is what gives ListView the page's off/on. Pinned below.
  • Docs. content/docs/plugins/plugin-view.mdx, the page that describes a list view's inlineEdit: a paragraph and a table under "On a host's renderListView" for the spec default and the fold.
  • Changeset. .changeset/5144-editinline-fold.md: @object-ui/plugin-list minor and @object-ui/core minor. The rule followed is objectui AGENTS.md section 9, version policy: a breaking change in this repo is marked minor, never major, with the breaking meaning written in the body. Core is minor because the fold changes the published function's output for every view that carries inlineEdit, and both in-repo relays merge that output. The changeset names the remedy: declare userActions.editInline: true, or keep the stored inlineEdit: true.

H1: the fold, per stored shape (measured)

The toggle is offered only to a principal who may update the object, as before. Rows are pinned in normalize-list-view.inlineEditFold-5144.test.ts (the fold) and ListView.permissions.test.tsx (the toolbar).

The view declares main: toggle / edit mode this PR: toggle / edit mode
neither key offered / off not offered / off (the ruled narrowing)
inlineEdit: true offered / on offered / on
inlineEdit: false offered / off not offered / off
userActions.editInline: true offered / off offered / off
userActions.editInline: false not offered / off not offered / off
editInline: false, inlineEdit: true not offered / off not offered / off
editInline: true, inlineEdit: false offered / off offered / off

H1's last clause does not hold as hypothesised: two rows narrow, not one. A stored inlineEdit: false reads off too, which is what a value-preserving fold means. The next section says who writes that value.

H2: the host channel (measured)

  • Write path. The toolbar toggle calls onInlineEditChange(next). @object-ui/app-shell's ObjectView persists it with persistViewPatch(viewDef.id, viewDef, { inlineEdit: next }), which is debounced and does not re-feed the schema in the session. Pinned: switching off reports false and leaves edit mode in the same interaction.
  • Read path. The console relay builds the node's userActions from normalizeListViewSchema(listSchema) and normalizeListViewSchema(viewDef), merged view over list, and passes inlineEdit: viewDef.inlineEdit ?? listSchema.inlineEdit. Both now carry the fold, with the same view-over-list precedence. ListView folds again; an explicit key is left alone.
  • A view whose stored inlineEdit is true still offers inline editing and opens in edit mode. Pinned.
  • ⚠️ The toggle is one-way on a view that declares no editInline. Switching it off stores inlineEdit: false. From the next load that view reads off and the toggle is gone. Nothing in the console UI writes userActions.editInline or inlineEdit back: ViewConfigPanel has no inline-edit control (measured by grep). With userActions.editInline: true declared, the toggle stays two-way and the stored inlineEdit only sets the mode. That is the remedy the changeset and the docs table state. Raised as an open question in the report, not changed here.

H3: every reader after the fold

Reader Reads After this PR
ListView inlineEditOffered folded userActions.editInline === true (was !== false)
ListView edit-mode state schema.inlineEdit unchanged (the fold keeps it)
ListView grid editable mode AND offered unchanged formula
ViewSettingsPopover showInlineEdit and inlineEdit props from ListView follows inlineEditOffered
InterfaceListPage page userActions.editInline === true, as inlineEdit unchanged; ListView now agrees with it
app-shell ObjectView relay each layer's userActions through the fold; inlineEdit view over list now carries editInline per layer, same precedence
app-shell ObjectView toggle writer writes inlineEdit unchanged
app-shell ObjectView activeViewUserActions search / filter / sort only unaffected
plugin-view ObjectView renderListView relay node and host-view userActions through the fold, named view's raw; inlineEdit named first see Acceptance notes: a lower layer can now outrank the named view
plugin-view ObjectView registered grid path named view inlineEdit as editable unchanged; never reads editInline (pre-existing)
app-shell StudioDesignSurface passes inlineEdit: true folds to on, as before
data-objectstack inlineEdit in the toolbar-owned config keys (write routing) unchanged

Other inlineEdit keys are different properties (field-level master-detail, record details, gantt, detail view). The fold only runs on list-view schemas.

H4: first-load bytes

apps/console, CI=true pnpm exec vite build, under the verify lock, eagerGzipBytes from dist/eager-closure.json:

  • base 8f815f4fe: 3,238,404 B, 289 eager chunks;
  • head f9e4b5b5d: 3,238,492 B, 289 eager chunks;
  • delta: +88 B gzip (threshold +1,024 B).

pnpm check:eager-closure on the head build: "Console eager closure is 3162.6 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB, headroom: 42.0 KB)". The budget script is untouched.

Reverse leg

main's blobs of normalize-list-view.ts and ListView.tsx checked out under the new pins (tests at head). The mutation was proven on disk by blob hash, the restore was git checkout HEAD, and a trap fired on exit. Direction predicted before the run: 12 red.

  • On main's blobs: Tests 12 failed | 26 passed (38). Red: 5 in the core fold file (true row, false row, other toggles kept, same pass as show*, spec-valid document), 3 in ListView.permissions.test.tsx (absent reads off, compact entry absent reads off, stored inlineEdit: false reads off), 4 in the interface-page pin.
  • Restore proven: both paths' git hash-object equal their HEAD blobs, and git diff HEAD is empty.
  • On head: Tests 38 passed (38).

Fixture triage

Gates, at f9e4b5b5d

  • Union, after the last commit: column-identity ratchet, one-authority-per-exported-name-6273, all six normalize-list-view suites, ListView.permissions, ListView, ListView.userActionsCollision, and the interface-page pin: Test Files 12 passed (12), Tests 331 passed (331).
  • The wide run: every normalize-list-view suite, every ListView* suite in plugin-list, every suite that references InterfaceListPage, and every suite that references normalizeListViewSchema, inlineEdit or editInline, 170 files in three runs. Run A: 84/84 files, 1712 passed, 9 skipped. Run B: 43/43 files, 316 passed. Run C: 2 failures, the fixture triage above, then green on re-run (ListView.test.tsx and the interface pin: 152 passed).
  • pnpm --filter @object-ui/core type-check and pnpm --filter @object-ui/plugin-list type-check: exit 0, with the plugin-list closure built first. --listFiles shows both test projects compile the edited and new test files. The app-shell test project compiles the new interface pin with 0 errors, after the app-shell closure build.
  • Changeset gates: check-changeset-presence ✅ "6 source file(s) of 3 released package(s) changed, and this change declares 1 changeset(s)"; check-changeset-no-major ✅; check-changeset-claims ✅; check-changeset-fixed ✅; check-changeset-overwrite ✅.
  • pnpm check:new-line-citations: "0 new citation(s)". pnpm check:control-bytes ✅. pnpm docs:check-links: "Links are valid across 17 scan roots". pnpm check:spec-symbols ✅.
  • check-vi-mock-specifiers / -inherit / -override-shape ✅. check-test-path-roots ✅. check:unreferenced-sources ✅. check-doc-fence-languages, -component-types, -example-ids and -expression-carriage ✅.
  • pnpm exec eslint on the 6 touched source and test files: 0 errors, 6 files in its JSON output, none ignored. This is a narrowed run, and the narrowing is safe: eslint.config.js enables no type-aware linting (no parserOptions.project or projectService), and no rule in eslint-rules/ reads the filesystem, so this diff cannot move a verdict on an untouched file. Whole-repo lint is CI's.
  • NOT MEASURED: check-doc-snippet-types and check-doc-example-types exit 2, "PRECONDITION NOT MET", because they need a 34-package build. The docs change adds no fenced code for them to type.

Acceptance notes

  • plugin-view renderListView relay: a lower layer can outrank the named view. Measured with a throwaway probe, not committed. The relay spreads normalizeListViewSchema(node).userActions, then the host view's, then the named view's userActions RAW. inlineEdit takes the named view first. After the fold, a node's or host view's inlineEdit becomes a folded editInline, and that outranks a named view's own inlineEdit for the offer. Named true with host false reads off; named false with host true reads offered. No in-repo host reaches it: the console passes views and no listViews, and Studio passes neither. The likely remedy is one line, folding the named layer like the other two. It is not made here, because packages/plugin-view/src/ObjectView.tsx is outside the claim's file surface.
  • plugin-view's registered grid path never reads editInline (pre-existing on main). It hands the named view's inlineEdit to ObjectGrid as editable, so editInline: false with inlineEdit: true is editable there and not on ListView.
  • editInline: true means two things (pre-existing). The interface page opens cells editable. ListView offers the toggle and opens out of edit mode unless inlineEdit is true.
  • plugin-list's README has no inline-editing section. The docs change is the one page named above.

Generated by Claude Code

claude added 2 commits October 9, 2026 06:46
…folding a stored inlineEdit into it (objectui#5144)

The maintainer's B-fold. normalizeListViewSchema folds a boolean
inlineEdit into userActions.editInline: the value carries over, and an
explicit editInline wins. inlineEdit stays on the result, because ListView
seeds the grid's edit mode from it and the toolbar toggle writes it.

ListView's inlineEditOffered now reads editInline === true, the spec's
.default(false). A grid view with neither key no longer offers the
inline-edit toggle. A stored inlineEdit: true still offers it, and a stored
inlineEdit: false reads off.

The interim pin "an ABSENT editInline defers to the host channel" flips.
New pins cover the fold's table in core, the toolbar's reading of the
folded key, the toggle's write path, and the interface page's composed
schema through the fold.

Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU
Co-authored-by: Claude <noreply@anthropic.com>
…(objectui#5144)

Two ListView.test.tsx cases exercise the toggle's mechanics on a view that
declared neither userActions.editInline nor inlineEdit. They relied on the
old absent default, which now reads off, so they declare the opt-in.

The interface-page pin's opt-in case was labelled CONTROL, but it goes red
with the fold removed like the others, so it is a positive case and is
named as one.

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

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 289 chunks) 3162.6 KB 3204.6 KB
Main entry chunk (gzip) 71.6 KB 350 KB
Entry file index-B7hsAhSK.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.52KB 7.19KB
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.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 240.39KB 67.09KB
fields (index.js) 268.74KB 68.04KB
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) 41.50KB 11.82KB
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.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
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.71KB 23.25KB
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) 248.57KB 65.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.11KB 45.88KB
plugin-gantt (index.js) 179.17KB 45.07KB
plugin-grid (index.js) 249.62KB 69.16KB
plugin-kanban (index.js) 52.77KB 16.56KB
plugin-list (index.js) 120.25KB 30.26KB
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.10KB 11.81KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.20KB 23.04KB
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.81KB 3.58KB
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.25KB
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

claude added 4 commits October 9, 2026 08:26
…iew's inlineEdit keeps its precedence (objectui#5144)

Triage's ruling E. The view's inlineEdit and userActions.editInline are
the author's permission keys, and the fold reads the first as the second.
The console's toolbar toggle persisted a user's edit mode into inlineEdit
through persistViewPatch, so switching it off stored inlineEdit: false
and the toggle was gone from the next load. ObjectView now wires
onInlineEditChange to a callback that writes nothing. ListView keeps the
edit mode for the session, seeded from the view's inlineEdit on each load.
The callback stays wired because ListView offers the wide toolbar toggle
only to a host that wires one.

The seat's decision on the named layer. plugin-view's renderListView relay
folded the node's and the host view's userActions but spread the named
view's raw, so a host-layer inlineEdit outranked the named view's own for
the offer. The named layer now goes through the same fold.

Texts that described a persisted toggle are rewritten: ListView's Gap 2
docblock, the prop and mode comments, the fold docblock, the changeset
(app-shell minor, plugin-view patch) and the plugin-view docs table.

Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU
Co-authored-by: Claude <noreply@anthropic.com>
…nce the toggle stopped persisting (objectui#5144)

The objectui#5233 ratchet's anti-vacuity floor counted five distinct keys
written through persistViewPatch. Ruling E removed the inline-edit write,
so the floor is four, and the ratchet now also states that inlineEdit is
not written. The adapter still lists inlineEdit as an owned key, so an
overlay an earlier console wrote is still read.

Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU
Co-authored-by: Claude <noreply@anthropic.com>
…ers by name (objectui#5144)

The fence's read census (objectViewHostSurface.test.tsx) pins the
named-view members the renderListView relay reads, by name. Passing the
whole named view to normalizeListViewSchema hid the userActions read from
it. The fold is now handed the two members it reads into userActions on a
named view, userActions and inlineEdit. A named view's strict record
refuses the show* flags, so nothing else feeds that block. Same output.

Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Fix round: ruling E and the named-layer fold. What this supersedes in the PR body

Head ba0b03c12; main ea79b7777 is merged in (merge, no rebase or force-push). Two rulings on the card: triage's E (comment 6076826085) and the seat's decision on the named layer (comment 6076433894). Clause-②: no (narrowing) is unchanged. Landing still waits for the owning seat's contract-tier review of record. The PR stays draft.

Superseded sections of the body, and what replaces them:

  • What changes. Two items are added.
    • @object-ui/app-shell ObjectView: onInlineEditChange is wired to keepInlineEditModeForTheSession, which writes nothing. The persistViewPatch(viewDef.id, viewDef, { inlineEdit: next }) write is gone. The callback stays wired because ListView offers the wide toolbar toggle only to a host that wires one; dropping it would have removed the toggle. The edit mode is ListView session state, seeded from the view's inlineEdit on each load. The read side, inlineEdit: viewDef.inlineEdit ?? listSchema.inlineEdit, is unchanged.
    • @object-ui/plugin-view ObjectView: the renderListView relay folds the named view's userActions like the node and host-view layers. The fold is handed userActions and inlineEdit by name, so the fence's read census in objectViewHostSurface.test.tsx still sees both.
  • H1 table. The rows stand. The stored inlineEdit: false row ("not offered") is now one of triage's recorded costs: it is existing data, written by the old toggle, and it is not migrated. The pin's comment says so.
  • H2. Replaced. The toggle no longer writes, so it is no longer one-way. On a view that declares userActions.editInline: true, the toggle is still offered after it is switched off and the view remounts. The recorded costs are that the edit mode is not remembered across loads, and that a view or overlay already holding inlineEdit: false still reads off.
  • H3. Two rows change. "app-shell ObjectView toggle writer: writes inlineEdit" now writes nothing. "plugin-view renderListView relay: a lower layer can outrank the named view" is fixed: the named layer is folded.
  • H4. Re-measured against the new main: ea79b7777 3,238,406 B, head ba0b03c12 3,238,506 B, delta +100 B gzip, 289 eager chunks on both. pnpm check:eager-closure on head: "Console eager closure is 3162.6 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB, headroom: 42.0 KB)".
  • Reverse leg. A second leg covers the new pins. The pre-round blobs of the two ObjectView.tsx files, which equal main's, were put under head tests. Predicted 5 red and observed Tests 5 failed | 4 passed (9): three app-shell cases (a served view's toggle writes nothing, the two-way remount, a saved view's toggle writes nothing) and both plugin-view precedence cases. Restore was proven by blob hash and an empty git diff HEAD. On head: Tests 9 passed (9). The two-way case reddens on its no-write assertion; its "still offered after remount" reading holds on both trees, because an explicit editInline wins, which is what makes it the remedy's control.
  • Fixture triage. One addition: the objectui#5233 owned-key ratchet in ObjectView.overlayPatchOnly.test.ts counted at least five keys written through persistViewPatch. It now counts four and states that inlineEdit is not written. The adapter's VIEW_OVERLAY_OWNED_KEYS keeps inlineEdit unedited, so existing overlays still read.
  • Changeset. It now has four entries: @object-ui/core minor, @object-ui/plugin-list minor, @object-ui/app-shell minor (a behaviour narrowing, AGENTS.md section 9) and @object-ui/plugin-view patch. "What to do" is rewritten: the toggle is session-only, the remedy is userActions.editInline: true, and the two costs are named.
  • Docs. In content/docs/plugins/plugin-view.mdx, the paragraph under the table is rewritten for the session-only toggle and names the named view's precedence. The table rows are unchanged.
  • Gates, at ba0b03c12.
    • Closing union: ratchets, every normalize-list-view suite, the touched ListView suites, the new pins, the overlay ratchet, fallbackTabSessionOnly-11643, writeRefusalCensus-11583, relayRungCensus-7559, objectViewHostSurface and namedViewProtocolKeys-8980: Test Files 20 passed (20), Tests 449 passed (449).
    • Wider runs: every plugin-view test plus the 26 app-shell suites that read ObjectView.tsx off disk, 97 files and 1149 passed; every app-shell suite that mounts ObjectView or names onInlineEditChange or persistViewPatch, 63 files, green after the ratchet change; the four data-objectstack overlay suites, 37 passed.
    • Type-check exit 0 with 0 errors for @object-ui/core, @object-ui/plugin-list, @object-ui/plugin-view and @object-ui/app-shell, and --listFiles shows the new pins compiled.
    • The changeset checks pass ("12 source file(s) of 4 released package(s) changed"), as do check:new-line-citations (0 new), check:control-bytes, docs:check-links and check:spec-symbols. Eslint on the 12 touched TypeScript files: 0 errors.
  • Acceptance notes. The first bullet (the relay inversion) is resolved. Two new notes:
    • @object-ui/data-objectstack's docblocks still say updateViewConfig's caller is invoked for an "inlineEdit toggle", and that each owned key pairs with a persistViewPatch call site. Both are stale for inlineEdit now. The file is outside the claim and is not edited.
    • ViewSettingsPopover.tsx's prop comment still says the toggle "persists inlineEdit on the view". That file is outside the claim and is not edited.

Generated by Claude Code

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 289 chunks) 3162.8 KB 3204.6 KB
Main entry chunk (gzip) 71.7 KB 350 KB
Entry file index-B4W5k7-B.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.52KB 7.19KB
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.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 240.39KB 67.09KB
fields (index.js) 268.74KB 68.04KB
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) 41.50KB 11.82KB
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.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
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.71KB 23.25KB
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) 248.57KB 65.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.11KB 45.88KB
plugin-gantt (index.js) 179.17KB 45.07KB
plugin-grid (index.js) 249.62KB 69.16KB
plugin-kanban (index.js) 52.77KB 16.56KB
plugin-list (index.js) 120.25KB 30.26KB
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.10KB 11.81KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.27KB 23.06KB
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.81KB 3.58KB
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.25KB
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

claude added 2 commits October 9, 2026 09:13
…e-edit toggle persists inlineEdit (objectui#5144)

Comment-only. Since ruling E the console's inline-edit toggle is session
state, so three comments this PR made false are rewritten:

- data-objectstack: the updateViewConfig production-caller note no longer
  lists inlineEdit among the persistViewPatch toggles.
- data-objectstack: the VIEW_OVERLAY_OWNED_KEYS docblock says inlineEdit
  stays an owned key so overlays the old toggle wrote are still read, but no
  console call site writes it. The key list is unchanged.
- plugin-list: ViewSettingsPopover's prop comment says the host decides what
  the callback does, and the console keeps it session-only.

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

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 289 chunks) 3162.8 KB 3204.6 KB
Main entry chunk (gzip) 71.7 KB 350 KB
Entry file index-B4W5k7-B.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.52KB 7.19KB
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.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 240.39KB 67.09KB
fields (index.js) 268.74KB 68.04KB
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) 41.50KB 11.82KB
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.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
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.71KB 23.25KB
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) 248.57KB 65.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.11KB 45.88KB
plugin-gantt (index.js) 179.17KB 45.07KB
plugin-grid (index.js) 249.62KB 69.16KB
plugin-kanban (index.js) 52.77KB 16.56KB
plugin-list (index.js) 120.25KB 30.26KB
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.10KB 11.81KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.27KB 23.06KB
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.81KB 3.58KB
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.25KB
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

Contract-tier review of record — PR objectui#12036 (objectui#5144) · PASS on head ee65d03a6

Reviewer: domain:ui seat 2, the owning seat (os-bill, session_01MgfduSkFrfM3eorB3UGfAU), 2026-10-09T09:23Z. Owed by triage's grade 6075214383 and the claim 6075621980. Read against the PR's diff on GitHub at ee65d03a6, not against the dev reports (6076349697, 6077955793, 6078128244).

Rulings this head executes:

  • the maintainer's B-fold (5328162879): normalizeListViewSchema folds a boolean inlineEdit into userActions.editInline. An explicit editInline wins. inlineEdit is kept, as the grid's edit-mode seed;
  • triage's E (6076826085): the console toolbar no longer persists the permission key. The app-shell ObjectView wires onInlineEditChange to a function that writes nothing, and the edit mode is ListView session state;
  • the seat's decision on the named layer (6076433894): plugin-view renderListView folds the named view's userActions like the node and host-view layers.

Contract reading (Clause-②: no (narrowing)):

  • Accept set: unchanged. No key, prop, export or packages/i18n key is added or refused. @objectstack/spec is untouched. A stored inlineEdit is still accepted, and it is folded.
  • What narrows, against main. Each row is pinned, and each is stated in the changeset and in content/docs/plugins/plugin-view.mdx:
    1. a view with neither userActions.editInline nor inlineEdit no longer offers the inline-edit toggle. This is triage's graded row, and the spec's .default(false) is now what the object-list toolbar reads;
    2. a view or overlay that already stores inlineEdit: false reads off. This is existing data written by the old toggle. It is recorded as a cost in 6076826085, and not migrated, per 5328162879;
    3. the grid's edit mode is no longer remembered across loads. This is recorded as a cost in 6076826085.
  • What no longer happens: the one-way trap measured in round 1, where switching the toggle off once removed it for good. It is pinned gone: on a view declaring userActions.editInline: true, the toggle is still offered after it is switched off and the view remounts, and the switch writes nothing.
  • The remedy is named in the changeset and the docs: a view that should offer inline editing declares userActions.editInline: true.
  • Changeset: @object-ui/core minor, @object-ui/plugin-list minor, @object-ui/app-shell minor, @object-ui/plugin-view patch. A breaking narrowing is marked minor, never major (objectui AGENTS.md §9), and its meaning is stated in the body.

Checklist:

  • Shape: draft. The first line is Fixes #5144, with no closing keyword beside another number. Clause-②: no (narrowing) is at the start of a line. The assignee is os-bill. Commit trailers carry no model name. Merges from main are merges (2a50985, 43cc4b0).

  • Surface: 16 files. All are in the claim as amended by 6076826085 and 6076433894, plus two comment blocks the PR made false: the @object-ui/data-objectstack overlay docblocks and the ViewSettingsPopover prop comment. Round 3 changed comment lines only, which the seat checked in the diff. VIEW_OVERLAY_OWNED_KEYS keeps inlineEdit, so old overlays are still read. InterfaceListPage.tsx is unedited. Not governed (check-governed-queue-guard: NOT GOVERNED).

  • Reverse legs:

    • round 1: 12 red on main's blobs;
    • round 2: 5 red, namely the three app-shell no-write and two-way cases and the two plugin-view precedence cases.

    Each was restored to blob == HEAD.

  • Evidence:

    • round 2's closing union: 20 files and 449 tests;
    • wider runs: 97 files and 1,149 tests over plugin-view and the suites that read ObjectView.tsx off disk;
    • round 3: 19 files and 406 tests;
    • type-checks for core, plugin-list, plugin-view, app-shell and data-objectstack;
    • both repo-wide ratchets, the changeset checks, docs:check-links and check:spec-symbols.
  • First-load bytes: +100 B gzip against ea79b77. The budget bot reads 3162.8 KB against 3204.6 KB on ee65d03a6, a PASS.

  • Noted, not filed (carrier: none): plugin-view's registered grid path reads the named inlineEdit as editable and never reads userActions.editInline; and editInline: true means edit mode on the interface page but only an offered toggle on ListView. Both are pre-existing on main.

Landing: through the merge queue once every check on ee65d03a6 is green and Bundle Analysis reads success. objectui#6152's round 14 waits on this merge for its normalize-list-view.ts leg (6077535247).


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 9, 2026 09:37
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 9, 2026 09:37
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit 3c3115e Oct 9, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-5144-editinline-fold branch October 9, 2026 09:57
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.

[finding] userActions.editInline has two different defaults across surfaces, and neither is the spec's .default(false)

2 participants