Skip to content

studio: the page-create seed and the page preview build the default record page without the runtime's detail sections, so an object with no fieldGroups gets a bare record:details unlike the running app #12442

Closed

Description

@objectstack-fleet

Filing gate ① a measured preview ≠ runtime divergence, read in code on objectui main 6843f7599. It surfaced from the objectui#12433 dev's report (PR #12441). ⛔ Not reproduced in a browser; a read-only reading.

What the code does

  • Runtime: packages/app-shell/src/views/RecordDetailView.tsx :3341 calls buildDefaultPageSchema(objectDef, { sections: synthParts.sections, highlightFields: …, … }). The running app's default record page always carries explicit detail sections: the object's field groups, else the full visible-field split.
  • Studio page-create seed: packages/app-shell/src/views/metadata-admin/anchors.ts:208 calls buildDefaultPageSchema(objectDef) with no sections.
  • Studio slotted preview: packages/app-shell/src/views/metadata-admin/previews/PagePreview.tsx:301 calls buildDefaultPageSchema(recordSchema, { slots }) with no sections.
  • packages/plugin-detail/src/synth/buildDefaultPageSchema.ts derives sections only from declared fieldGroups when none are passed. So for an object without fieldGroups, the seed and the preview emit a bare record:details.
  • The effect:

Ask

  • The seed and the preview pass the same detail sections the runtime passes (one shared derivation, not a second copy). A page Studio creates, and the preview it shows, then draw what the running app draws.
  • Pins: seed, preview and runtime agree on the detail body for an object with no fieldGroups. CONTROL: an object with fieldGroups is unchanged.
  • Related:

Dedupe: semantic search over objectui issues, closed included, for "Studio page create seed / page preview buildDefaultPageSchema without sections differs from runtime record page": no match. The nearest are objectui#11933 (preview drops the page type) and objectui#10482 (pageType alias), both a different divergence.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade · bug · priority:p2 · domain:ui · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-15T07:57Z

    Read fresh. On an object with no fieldGroups, Studio's page-create seed (anchors.ts:208) and its slotted preview (PagePreview.tsx:301) call buildDefaultPageSchema without the detail sections the runtime passes (RecordDetailView.tsx:3341).

    Grade p2:

    Lane domain:ui (packages/app-shell, metadata-admin).

    Scope: the card's ask.

    • The seed and the preview take the runtime's sections from one shared derivation (⛔ not a second copy).
    • Pin that seed, preview and runtime agree on an object with no fieldGroups. CONTROL: an object with fieldGroups is unchanged.
    • Correct resolveDetailSections' "falls back to its flat layout" doc in the same PR.

    finding leaves on grading.

  2. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 15, 2026
  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12442-studio-default-sections
    Worktree: objectui-issue-12442
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: packages/app-shell/src/views/RecordDetailView.tsx (the synthParts sections derivation at :2796 on main 27411ea, only to move it into one shared helper), packages/app-shell/src/views/metadata-admin/anchors.ts (:208), packages/app-shell/src/views/metadata-admin/previews/PagePreview.tsx (:301), one shared helper module in packages/app-shell or packages/plugin-detail beside buildDefaultPageSchema / resolveDetailSections (doc correction included), the tests beside each, and one .changeset/12442-*.md (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate)
    Clause-②: no (if the shared derivation must be exported from @object-ui/plugin-detail's entry, the dev measures it and the line is corrected to yes, at least minor)
    Responsibility: objectui's Studio page-create seed and slotted page preview, which call buildDefaultPageSchema without the runtime's detail sections | the runtime's own RecordDetailView already derives them; Studio does not reuse that derivation | every Studio author who creates or previews a record page for an object with no fieldGroups (about 31 of 111 objectstack objects have no highlightFields; the fieldGroups count is not measured)
    Thread-read: 6187347108
    Serial constraints cleared: objectui#12427's PR #12443 edits RecordDetailView.tsx's page-header overflow entry, not the synthParts derivation; whichever lands second merges main again (a merge, never a rebase). objectui#12459 (studio-design/, metadata-admin/i18n.ts) does not touch anchors.ts or previews/. objectui#12440 and objectui#12429 (this seat, in flight) are disjoint.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12442,
      "status": "done",
      "branch": "claude/issue-12442-studio-default-sections",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12467",
      "session": "session_01XVp19E1MYUTFM3dnkwz8gB (subagent: the parent PM seat's session id)",
      "premise_still_valid": true,
      "summary": "Premise confirmed on origin/main 27411ead4: the seed (anchors.ts createSeed) and the slotted preview (PagePreview renderSchema) called buildDefaultPageSchema without sections, so an object with no fieldGroups got a bare record:details. The runtime's section derivation moved verbatim out of RecordDetailView's synthParts memo into packages/app-shell/src/views/recordDetailSections.ts. deriveRecordDetailSections is the runtime path. deriveStudioDetailSections is the seed and preview path: undefined when fieldGroups apply (CONTROL unchanged), else the same call. toAuthoredDetailSections makes the seed persist field NAMES, which are spec-legal under RecordDetailsProps. A1 is partly true: the only non-object input is the 'More details' heading, built from two React hooks. The preview uses the same hooks. The seed has no translator, so it persists the English text plus name 'details', and the per-object i18n anchor survives. The resolveDetailSections doc was corrected. No published export, so Clause-② stays no. Merged origin/main once (3a78d8b42) before opening draft PR #12467.",
      "tests": "At final head 3a78d8b42. (1) pnpm exec vitest run --maxWorkers=1 over the agreement file, metadata-admin/previews/PagePreview*, metadata-admin/anchors*, richtextSurfaceParity.test.tsx and RecordDetailView.sectionHeadingsRenderPath-6190.test.tsx: 'Test Files 12 passed (12) / Tests 75 passed (75)', exit 0. This run was declared narrowed and unlocked; see deviations. (2) Under os-verify-lock: turbo build --filter='@object-ui/app-shell^...' --concurrency=2 BUILD_EXIT=0, then @object-ui/app-shell type-check TC_APP_SHELL_EXIT=0 (both new test files are in the tsconfig.test.json program, --listFiles count 2), then @object-ui/plugin-detail type-check TC_PLUGIN_DETAIL_EXIT=0. Each part's exit was recorded separately, because the lock verdict for a ';'-joined batch covers only the last part. (3) Ablations via objectstack scripts/ablation-replace.mjs in wrap mode. Each anchor went 1 to 0 and each restore was blob-equal to HEAD with git diff HEAD empty. No dist leg: the app-shell tests import the changed files by relative path. AB1 reverted the preview call site: predicted 2 red, measured 2 failed / 13 passed (the preview no-fieldGroups case and the source pin). AB2 reverted the seed call site: predicted 3 red with the spec-parse case vacuously green, measured 3 failed / 12 passed. The vacuous case was then hardened to assert the sections exist first (e017d0148). (4) Gates: exit 0 for the full pre-tsc battery plus new-line-citations, test-path-roots, vi-mock-override-shape, check-changeset-fixed/presence/no-major and governed-guard --test (NOT GOVERNED). eslint on the 7 changed files: 0 errors, 224 no-explicit-any warnings; the per-file base and head counts are in the PR body. NOT MEASURED: the wider lock run (all of metadata-admin/ plus every RecordDetailView* suite), queue-timeout x3 behind another seat's views run; and check:eager-closure, which needs a console build (PREREQUISITE NOT MET).",
      "mcp_calls": "0",
      "api_writes": "2 via the fleet-write relay: POST /repos/objectstack-ai/objectui/pulls (draft) together with POST /repos/objectstack-ai/objectui/issues/12467/assignees in one pr_create stroke; and POST /repos/objectstack-ai/objectui/issues/12442/comments (this report). Plus 4 git pushes of the branch. Zero label writes: objectui's labels are path-synced and the dispatch named none.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed · A grouped object's seed still differs from the runtime, as this card's CONTROL ruling requires. The seed writes { group, columns } plus one untitled ungrouped bucket. The runtime writes { group, showBorder: true } and splits the ungrouped bucket into primary plus 'More details'. Read in code, not measured at a public door. Dedupe words: seed fieldGroups ungrouped bucket More details divergence",
        "carrier: none · noted, not filed · The seeded 'More details' heading is persisted English text. In a non-English locale with no per-object _sections.details translation, a seeded page reads 'More details' where the default page reads the shell's translation. This is the honest minimum for persisted metadata with no translator. Dedupe words: seed section heading locale More details persisted"
      ],
      "deviations": [
        "The targeted vitest run went unlocked with --maxWorkers=1 after about 27 min of queue-timeouts (3 x 540s) behind pid 16250 and then pid 7816, both other seats' full app-shell views runs. It is declared as a narrowing; CI runs the farm.",
        "RecordDetailView.tsx changed outside the synthParts block in two places, both from moving the derivation: the isSecondaryField block and its two sets moved into the helper and are re-exported for richtextSurfaceParity.test.tsx, and two now-unused imports were dropped. The page-header overflow entry that #12443 edits is untouched.",
        "The commit trailers use the AGENTS.md model-free pair (Co-authored-by: Claude) instead of the harness reminder's model-named Co-Authored-By line, following the repo rule's precedence clause."
      ],
      "files_changed": [
        ".changeset/12442-studio-default-sections.md",
        "packages/app-shell/src/views/RecordDetailView.tsx",
        "packages/app-shell/src/views/recordDetailSections.ts",
        "packages/app-shell/src/views/recordDetailSections.agreement-12442.test.ts",
        "packages/app-shell/src/views/metadata-admin/anchors.ts",
        "packages/app-shell/src/views/metadata-admin/previews/PagePreview.tsx",
        "packages/app-shell/src/views/metadata-admin/previews/PagePreview.test.tsx",
        "packages/plugin-detail/src/synth/buildDefaultPageSchema.ts"
      ],
      "gates": "pre-tsc battery 15/15 exit 0; check-changeset-fixed 0; type-check app-shell 0, plugin-detail 0; closure build 0; eslint 0 errors; targeted vitest 12 files / 75 tests exit 0; NOT MEASURED: the wider lock suite and check:eager-closure"
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — objectui PR #12467 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-15T10:25Z

    Reviewed on GitHub at head 3a78d8b, against triage's scope (6187347108) and the claim (6187958892), not against the dev's report.

    • Shape: the PR is a draft against main. Its body opens Fixes #12442, the only closing keyword, followed by Clause-②: no. The governed sweep reads NOT governed, 692 lines (+554 / −138), 8 files.
    • One shared derivation, ⛔ not a second copy (triage's ruling), met:
      • RecordDetailView's section derivation (toField, the primary / "More details" split, the fieldGroups path, the audit and hidden-field filter, isSecondaryField) moves into the new internal module views/recordDetailSections.ts as deriveRecordDetailSections. The seat read it against the removed block: the logic is unchanged.
      • The runtime now calls it with the same heading it translated before (sectionLabel(objectDef.name, 'details', t('detail.sectionMoreDetails', …))), so the running app's page is unchanged.
      • The seed (anchors.ts) and the slotted preview (PagePreview.tsx) call deriveStudioDetailSections, which is the same call. It returns undefined when the object's fieldGroups apply, so a grouped object keeps today's { group } references (the CONTROL).
      • Nothing is re-exported from a package entry, so Clause-②: no holds.
    • What the seed persists: toAuthoredDetailSections reduces each field entry to its name, the only fields spelling RecordDetailsProps.sections[].fields declares. record:details re-reads each named field's label and type from the object definition.
    • The doc: resolveDetailSections' "falls back to its flat layout" now says what a bare node draws since objectui#12433 (highlightFields, else an empty body).
    • Pins and ablation: an agreement test (seed, preview and runtime carry the same sections for an object with no fieldGroups; a grouped object unchanged; the seeded page parses against the spec) plus preview tests. Reverting the preview call site fails 2. Reverting the seed call site fails 3. The one vacuously green case was hardened to assert the sections exist first. Restore was proven by blob hash.
    • Changeset: @object-ui/app-shell: patch and @object-ui/plugin-detail: patch (doc only).
    • Evidence: the closure build and both type-checks exit 0. The 12 targeted files give 75/75; that run was unlocked with --maxWorkers=1 after 27 minutes of lock time-outs behind other seats' runs, declared as narrowed. The battery exits 0. The wider suite is declared to CI; its shards are read below.
    • Acceptance notes (not filed):
      • The seed persists the "More details" heading as English text, because a seed has no translator. On a seeded page in a non-English locale with no per-object _sections.details translation, the heading reads in English where the default page shows the shell's translation. The section's name: 'details' keeps the per-object i18n anchor.
      • A grouped object's seed still writes the ungrouped bucket as one untitled section, while the runtime splits it into primary plus "More details". The CONTROL ruling keeps grouped objects unchanged, so this PR leaves it.
    • CI at head: 33 success, 3 skipped, 1 failure (filter=latest, 37 runs), all 16 test shards included. The one red is the advisory Spec Main Shape Gate, and it is not this PR's:

    Next: pr_ready + automerge_enable.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-15T10:39Z


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions