Skip to content

fix(react): usePageAssignment opens the object's default record page (objectui#12195) - #12431

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-12195-record-page-isdefault
Oct 15, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-12195-record-page-isdefault

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #12195

Clause-②: no

What changes

usePageAssignment (@object-ui/react, the record-page pick behind RecordDetailView) now opens the object's default record page. Among the served pages with type: 'record' and the requested object, the one the spec reads as the object's default wins; with no default, declaration order decides as before; an explicit pageName still wins outright.

  • The rule it follows. Maintainer ruling A on spec(page): no stated rule decides between two isDefault record pages for one object, so the renderer cannot honour isDefault without inventing precedence (the spec half of objectui#12195) objectstack#23015 (record 6134056653), landed as objectstack 5f37d36ce3 and installed here through @objectstack/spec 18.0.0-next.1: at most one isDefault: true record page may exist for an object in a deployment, and a second is refused, naming both pages, by defineStack / composeStacks (so os validate and a source boot), at package registration and at metadata save. The ruling's renderer half, verbatim: "The renderer then honours isDefault with no tie-break." This hook adds no tie-break, option, key or precedence rung.
  • One reading, not a second spelling. The hook asks defaultRecordPageObject from @objectstack/spec/ui, the function every refusing door asks. Inside the candidate set (already type: 'record' and the requested object), that answer is exactly isDefault === true. @objectstack/spec is already a runtime dependency of the package, and src/SchemaRenderer.tsx already imports values from @objectstack/spec/ui.
  • Placement. The preference runs after the filter, so the type discriminator, the object match and matchesAssignment keep their meaning (pinned: another object's default, and a list page flagged default for the same object, do not displace the record page).
  • The stated boundary. One path still delivers two defaults: at a cold boot every package registers before the environment's stored pages hydrate, so a stored default saved while no package held that object's default and a package that adds one later both reach the registry unrefused (finding(objectql): a cold boot does not judge a stored default record page against a package's, so a hot install and a restart answer differently for one composition (the boundary PR #23206 states for #23015) objectstack#23213, closed not_planned; the objectql module doc of default-record-page.ts states it). The hook's comment names this case. For that pair the hook invents no rung: served order stays its only order, so the first default served wins. A pin holds that, so a precedence rule cannot be added here unannounced.

Who sees a different page

An app or an environment that authors a record page without isDefault: true, for an object that also has a served default record page, where that page came first in the served list. It used to open; the default opens now. Ruling A keeps two ways to replace a platform record page: an ADR-0005 overlay saved under the platform page's own name (the same page, not a second default), and host composition (composing the stack without the platform's page). Shipping a second default is not one: the platform refuses it.

Census (dispatch assumption A4), objectstack origin/main f3fd209b3, objectui 7c13d30527:

  • objectstack: the record pages authored in non-test source are six, each isDefault: true and the only record page for its object: sys_user_detail and sys_organization_detail (packages/platform-objects), sys_approval_request_detail (plugin-approvals), and the showcase's showcase_project_detail, showcase_task_detail and showcase_settings (showcase_preference). sys_position_detail retired with the sys_position object. Shipped apps and examples authoring a non-default record page for any of those objects: 0. objectstack's own server tests that author record pages do not feed this hook.
  • objectui: no app, example or doc fixture serves a record page into this hook beside a default. Of the 58 RecordDetailView* suites, 16 serve a type: 'record' page, each from a single record-page literal; one of them (recordOpenRequests-11699) flags it isDefault: true, alone. Non-default competitors: 0.

Measurements of the dispatch's assumptions

  • A1: holds. At 7c13d30527 (main moved past fc528c3eb; the hook was unchanged) the hook filtered to type === 'record', the matching object and matchesAssignment, then returned candidates[0], and its comment recorded that isDefault was not consulted. The change sits after that filter; the pageName branch is untouched.
  • A2: holds, with one correction. The three pins "isDefault on a later candidate does NOT promote it", "the app page wins when it is declared first" and "isDefault: true on the platform page does not make it win from second place" are rewritten to the ruled behaviour, each naming ruling A, none deleted. The third now also carries a control (same two pages, same order, the flag removed: the app page wins again), so the flag is the variable. The two pure-order pins stay as they were. Correction: "the platform page wins when IT is declared first" is not an order-among-non-defaults pin, since that page is the default; its assertion stays true, but its old name ("nothing authored breaks the tie") became false and is renamed.
  • A3: holds. The spec's own module (default-record-page.ts in @objectstack/spec/ui) says the renderer opens the default "with no tie-break between two defaults: registration order, package order and declaration order decide nothing", and the platform refuses the pair at every door except the cold-boot boundary above. No ordinary path delivering two defaults was found, so no open question; the triage pin "two isDefault record pages resolve the same way whatever the registry order" is read as superseded by ruling A, as the dispatch directs.
  • A4: 0, see the census above.
  • A5: holds. recordPageEnvelope in runtime-metadata-persistence.ts still mints a record page with no isDefault and still has no non-test caller (its callers are its own test file and the ADR-0034 prose). Not in this diff; see Acceptance notes.

Tests (all at e72618f400)

  • pnpm --filter @object-ui/react type-check (tsc --noEmit && tsc -p tsconfig.test.json): exit 0. tsc -p tsconfig.test.json --listFiles lists all three usePageAssignment.*.test.tsx files, so the new suite is type-checked.
  • The three usePageAssignment suites, pnpm exec vitest run --maxWorkers=2 ...: Test Files 3 passed (3), Tests 27 passed (27).
  • The whole package, pnpm exec vitest run --maxWorkers=2 packages/react/: Test Files 111 passed (111), Tests 1420 passed (1420).
  • All 58 RecordDetailView* suites in packages/app-shell (the hook's only caller), in two batches of 29: Test Files 29 passed (29) / Tests 210 passed (210) and Test Files 29 passed (29) / Tests 168 passed (168). vitest.config.mts aliases @object-ui/react to packages/react/src, so they ran the edited hook, not a stale dist/. The 16 that serve a record page: authoredActivityThreading-12249, commentWriteFailure-10899, discussionExplicitComposition-7298, discussionFallbackPipeline-8983, feedCommentEditDelete-12268, feedGrant-12082, feedLoading, feedRecordScope, oneProvenanceFooter-12307, printAction-11958, reactionKeepIds-11019, reactionRecords-12078, reactionWriteFailure-10899, reactionsCommentRowsOnly-11035, recordOpenRequests-11699, replyCountOnRead-12144.
  • Build closure pnpm --workspace-concurrency=2 --filter '@object-ui/react^...' build: exit 0; pnpm --filter @object-ui/react build: exit 0.

Ablation (one-time, not kept). The fix was committed first. scripts/ablation-replace.mjs (objectstack's copy, run from this worktree) replaced the candidates.find(...defaultRecordPageObject...) ?? candidates[0] return with return candidates[0]; (anchor 1 to 0, marker 0 to 1 on disk, blob 685e6ad301c1 to fff84703902a) and ran the 7298 and 12195 suites: Tests 7 failed | 13 passed (20), exit 1. Red, the predicted direction: the three rewritten 7298 pins and four new rule pins (default declared second, default from any depth, slotted default, two defaults in served order). The controls, the pageName pin and the after-the-filter pin stayed green, as they should under that mutation. Restore proven, not assumed: blob after restore 685e6ad301c1 equals the HEAD blob, git diff HEAD empty, marker count 0, anchor count 1. The suites import the hook by relative source path, so no dist/ sits in the path.

Gates

Local subset for these paths (derived by hand from objectui's package.json check:* scripts and .github/workflows/lint.yml, ci.yml, changeset-guard.yml, changeset-presence.yml; exit codes captured before any pipe), at e72618f400:

  • node scripts/check-changeset-presence.mjs 0 ("3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)"); check-changeset-no-major.mjs 0; check-changeset-fixed.mjs 0; check-changeset-overwrite.mjs 0; pnpm check:changeset-claims 0; pnpm check:pending-changeset-literals 0.
  • pnpm check:control-bytes 0; pnpm check:new-line-citations 0 ("0 new citation(s)").
  • pnpm check:spec-symbols 0; pnpm check:test-path-roots 0; pnpm check:vi-mock-specifiers 0; node scripts/check-vi-mock-override-shape.mjs 0; pnpm check:phantom-deps 0; pnpm check:esm-specifiers 0; pnpm check:unreferenced-sources 0.
  • pnpm exec eslint on the three changed TypeScript files: exit 0, 0 errors; its 10 warnings all sit on lines this diff does not add.
  • pnpm check:spec-floors: exit 1, every finding no-artifact (an unbuilt workspace, the gate's prerequisite). After building @object-ui/react, its row left the findings (the package that imports defaultRecordPageObject, judged against the declared floor ^18.0.0-next.1); the other 18 packages remain unbuilt: NOT MEASURED locally, left to CI's spec-range-floors.yml.
  • node scripts/check-governed-queue-guard.mjs --test on the four paths: NOT GOVERNED.

Everything else (repo-wide pnpm lint, the test shards, the performance budget) is CI's.

Acceptance notes

  • recordPageEnvelope (A5). It mints a kind: 'full' record page with no isDefault. Now that the flag decides, a page it mints for an object that also has a served default would not open. It has no non-test caller, so nothing reaches that today; the first caller decides whether it writes isDefault.
  • A census header made stale. scripts/page-key-read-census.mjs, boundary 4 of its header, says "isDefault is declared and nothing consults it". That stops being true with this change. It is outside this card's file surface (a script edit adds that script's own suite), so it is not touched here.
  • A README sentence made true. packages/plugin-gantt/README.md already told authors to "let isDefault pick the one that opens". Before this change nothing did.
  • Observed, not measured for reach. The hook's candidate filter requires type === 'record' literally, while the spec's reading counts a page with no type as a record page (PAGE_TYPE_DEFAULT, which PageSchema's type default also reads). Whether GET /meta/page can serve a page with no type was not measured. This diff leaves the filter alone.

Session: https://claude.ai/code/session_01JZnppgHRp4sREcouhkQYDB (dispatched by the domain:ui seat 1, claim 6184497895).


Generated by Claude Code

…(objectui#12195)

The record-page pick returned the first matching page in served order and
never read the declared `PageSchema.isDefault`. The spec now allows one
default record page per object per deployment and refuses a second at every
door (ruling A on objectstack#23015, in @objectstack/spec 18.0.0-next.1), so
the hook returns the default through the spec's `defaultRecordPageObject`
with no tie-break, and keeps declaration order for the pages that are not
the default. The cold-boot boundary the platform states is named in the
hook's comment; no precedence rung is added for it.

Three objectui#7298 pins that said the flag was inert now pin the ruled
behaviour; a new suite carries the rule's pins and controls.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 69 chunks) 3076.1 KB 3119.4 KB
Main entry chunk (gzip) 73.9 KB 350 KB
Entry file index-D7vmaHwy.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) 20.90KB 7.67KB
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.62KB 0.83KB
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.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
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) 591.88KB 142.76KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 251.19KB 70.38KB
fields (index.js) 282.89KB 72.11KB
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) 15.35KB 5.51KB
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) 54.94KB 16.05KB
plugin-charts (index.js) 84.97KB 23.36KB
plugin-chatbot (index.js) 201.72KB 48.07KB
plugin-dashboard (index.js) 143.88KB 38.88KB
plugin-designer (index.js) 233.95KB 50.08KB
plugin-detail (index.js) 262.05KB 69.25KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 179.38KB 46.59KB
plugin-gantt (index.js) 178.36KB 45.08KB
plugin-grid (index.js) 261.69KB 72.58KB
plugin-kanban (index.js) 53.23KB 16.71KB
plugin-list (index.js) 123.37KB 31.61KB
plugin-map (index.js) 27.07KB 8.96KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 46.66KB 13.13KB
plugin-timeline (index.js) 39.21KB 11.85KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.99KB 23.23KB
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.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
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-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.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

Seat ACCEPT: objectui PR #12431 at e72618f400 · domain:ui seat 1 · session_01JZnppgHRp4sREcouhkQYDB · 2026-10-15T05:18Z

Verdict: ACCEPT. I reviewed on GitHub against the claim 6184497895 on objectui#12195 and the dev's report on that card, not on the report's own account.

No contract-review face applies: Clause-②: no, there is no published schema and no governed path. The review of record is this seat's own reading plus CI. The PR lands once CI on this head is green.

  • Shape:
    • Draft, base main, assignee sunhaolin.
    • Line 1 is Fixes #12195, the body's only closing keyword. Line 2 is Clause-②: no.
    • 4 files, +260/−40.
  • The fix, read in the diff:
  • Pins:
    • The three objectui#7298 pins the ruling inverts are rewritten to it, naming ruling A, and none is deleted. The third now carries a same-list control with the flag removed.
    • The new suite has 10 cases: a default wins from second place and from any depth; CONTROLs for no flag, a single default, and no default; a slotted default; pageName over the default; the default chosen after the filter; and the two-default boundary on served order.
    • Ablation: with the preference dropped, 7 failed and 13 passed, as predicted. The restore is blob-proven.
  • Census (A4): 0. On objectstack f3fd209b3, six record pages ship, each the only one for its object and each isDefault: true. No app, example or fixture in objectui serves a non-default competitor beside a default.
  • Tests on this head:
    • the three hook suites: 27 passed;
    • packages/react: 1,420 passed;
    • all 58 RecordDetailView* suites in app-shell, the hook's only caller: 378 passed;
    • @object-ui/react type-check: exit 0.
  • Changeset, checked sentence by sentence: @object-ui/react patch.
    • It names who sees a different page: an app's non-default record page that used to win by position.
    • It names the two override paths ruling A keeps: an ADR-0005 overlay by name, and host composition.
    • Its "no type, option or export changes" is checked above.
  • Deviations, accepted:
    • Based on 7c13d30527, not fc528c3eb. main moved, and the hook's directory is byte-identical between the two.
    • Correction to the PR body's Gates bullet: spec-range-floors.yml does not run on pull requests. The react row judged locally against ^18.0.0-next.1 is this PR's evidence for that gate.
  • Out of scope, one line each:
    • recordPageEnvelope (runtime-metadata-persistence.ts) mints a record page with no isDefault and has no non-test caller. → Acceptance notes.
    • scripts/page-key-read-census.mjs:134 uses isDefault as its example of a declared key nothing honours, and that example goes stale here. It is script-header prose, and no gate or reader acts on it. → Acceptance notes.
    • The liveness row and NAVIGATION_VIEW_RETIRED's "let isDefault pick the one that opens", which the earlier dev carried, become true with this PR. No card is owed.
  • Writes: two relay strokes (pr_create and the report), and 0 MCP calls.

Landing: ready and auto-merge through the queue once every check on this head is green or an expected skip. Its merge closes objectui#12195.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Spec Main Shape Gate red on e72618f400: objectui#12422's build-order race, not this diff · domain:ui seat 1 · session_01JZnppgHRp4sREcouhkQYDB · 2026-10-15T05:25Z

What fails: Spec Main Shape Gate (check-run 116259532829). It is advisory, not in the required set. @object-ui/plugin-list#type-check exited 2, and every diagnostic is in a file this PR does not touch:

  • packages/plugin-grid/src/ObjectGrid.tsx:71, TS2307: cannot find @object-ui/plugin-detail;
  • :5575 and :5628, TS2345, which cascade from it.

Why it is not this PR's:

  • plugin-list's test ListView.gridRowColorSelect-12393.test.tsx imports plugin-grid's ObjectGrid source by relative path. plugin-list does not declare the dependency, so turbo never builds plugin-detail first.
  • This PR changes @object-ui/react, so plugin-detail#build re-executes in the same run, and the race fires.
  • The same gate is red on this PR's merge base, main 7c13d30527 (scheduled check-run 116254139467), at the same ObjectGrid.tsx:71. Its first line is TS7016 there and TS2307 here: the same race, caught at a different moment of the rebuild.
  • That is the cause objectui#12422 records (p2, pm:queue, routed by triage to the seat that landed PR fix(plugin-grid): ObjectGrid projects the row colour's field (objectui#12393) #12408). No fix exists yet, so nothing is ported.

Next: the one failed-job re-run on this head, once that run has finished. The PR goes to the queue only when every check on its head is green or an expected skip.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 15, 2026 05:38
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 15, 2026 05:38
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 15, 2026
Merged via the queue into main with commit 92f979d Oct 15, 2026
38 of 39 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-12195-record-page-isdefault branch October 15, 2026 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants