Skip to content

Phone-width card list uses the first column as the card title (Owner "Dev Admin") instead of the object's name field #13150

Closed

Description

@objectstack-fleet

立卡门类别 ①:有具名落点且可稳定复现的界面体验缺陷。
动手的读者:objectui 开发席(pm-dispatch 派发的 os-dev),改 plugin-grid 的卡片视图标题取值。
查重:objectui 搜 "card view title first column mobile" 命中 43(看前 25),无同题(均含 closed);第一遍 objectui#13113、#13114、#13115 未收录此项。

reach: 界面实测一次,390×844(Studio → Data → 对象 Records)。

预期:卡片标题是记录名(对象 nameField,这里是 Name:"Plant A check")。
实际:三张卡片的标题都是 "Dev Admin"(Owner),记录名 "Plant A check" 被放在卡片底部的普通字段行。

源码落点:packages/plugin-grid/src/ObjectGrid.tsx 卡片分支(useCardView && data.length > 0 && !isGrouped):titleCol = displayColumns[0],注释写 "First column is always the title"。

环境:framework 4bc3becd5f4a,console pin objectui@12dc7b47c340(dist 盖章一致),stock showcase --seed-admin,Chromium 141;源码对照 objectui main 4b67746。来源:UX 走查第二遍(派发会话 session_01CfRDy7SuTfUqaTu2AEH2Hi)。

type: Bug

Activity

  1. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 20, 2026
  2. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (priority:p2, bug)
    Session: session_01GL347th7aWQUnY2k8diSLG
    Account: os-support-ai (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-13150-card-title-name-field
    Worktree: objectui-issue-13150
    Domain: domain:ui
    Seat: domain:ui#3
    File surface: packages/plugin-grid/src/ObjectGrid.tsx, the phone-width card branch (useCardView && data.length > 0 && !isGrouped; const titleCol = displayColumns[0]; // First column is always the title, read at objectui main cbac9d7): the card title is the object's declared name field, the way the bulk-confirm path names records since PR #13112. Tests beside it; one .changeset/13150-card-title-name-field.md (@object-ui/plugin-grid patch). ⛔ Not the grid's empty state in the same file (queued objectui#13142). ⛔ No new package export. Stop on breach; explain in the report.
    Container & model: M, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui over this surface reads no path-derived mandate)
    Clause-②: no
    Responsibility: the risk is produced by objectui's own ObjectGrid card view, which takes the first displayed column as the title. The platform path that covers it: the record's name still shows as an ordinary row lower on the card, and the desktop grid is unaffected. Who reaches it: every phone-width card list whose first visible column is not the name field (the card measured Studio → Data → Records at 390x844, titled "Dev Admin" from Owner).
    Thread-read: none
    Serial constraints cleared: open objectui PRs touching ObjectGrid.tsx: none (the nine open PRs' file lists were read at this claim). Fold-or-serial: queued objectui#13142 (the grid empty state's "No results found" copy) also names ObjectGrid.tsx; not folded, it fails fold gate ① (empty-state copy, not card title selection), and it is not in this batch.

    Why Clause-②: no: a rendering fix inside @object-ui/plugin-grid's card branch. No export, prop, schema key or accept set moves. If the route needs one, the dev stops and reports.

    Claimed at: 2026-10-20T06:53Z

  3. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 13150,
      "status": "done",
      "branch": "claude/issue-13150-card-title-name-field",
      "pr": "https://github.com/objectstack-ai/objectui/pull/13182",
      "session": "session_01GL347th7aWQUnY2k8diSLG (subagent of the domain:ui seat 3 PM; parent's id, as the relay resolved it)",
      "premise_still_valid": true,
      "summary": "Premise held on main 5dbc6a5: the phone-width card branch of ObjectGrid took `const titleCol = displayColumns[0]; // First column is always the title`. The card is now titled by the object's declared nameField, read through the existing `declaredNameField(objectSchema)` (the same resolver and the same object definition the bulk confirm step uses; no second lookup, no name-guessing chain). Where the name field is a shown column, that column titles the card and the body is every other shown column, so the name is not repeated and the displaced first column (Owner) reads as a body row. Where it is not a shown column, the title reads row[nameField]: measured that both fetch paths already ask for it (ObjectGrid getSelectFields, objectui#13107; ListView $select harvest, objectui#13116); a masked name field with no column draws MaskedCellRenderer; an absent value draws the card's existing em-dash title, never another field. Objects with no declared nameField keep the first column (control pinned). Card-title selector for the 390x844 seat reading: `[data-testid=\"grid-card-title\"]` (new test id on the title div; classes unchanged, `div.font-semibold.text-sm.truncate.mb-1`). Files changed (git diff --numstat 5dbc6a5 HEAD): .changeset/13150-card-title-name-field.md +11/-0; packages/plugin-grid/src/ObjectGrid.tsx +32/-7; packages/plugin-grid/src/__tests__/mobileCardTitleNameField-13150.test.tsx +170/-0. Producer stayed in ObjectGrid.tsx card branch (claimed surface); empty state (objectui#13142) untouched; no export, prop, schema key or type member added.",
      "files_changed": [".changeset/13150-card-title-name-field.md", "packages/plugin-grid/src/ObjectGrid.tsx", "packages/plugin-grid/src/__tests__/mobileCardTitleNameField-13150.test.tsx"],
      "line_budget": {".changeset/13150-card-title-name-field.md": "+11/-0", "packages/plugin-grid/src/ObjectGrid.tsx": "+32/-7", "packages/plugin-grid/src/__tests__/mobileCardTitleNameField-13150.test.tsx": "+170/-0"},
      "tests": "All on head 17838dd (git rev-parse --short HEAD), through os-verify-lock, exit captured before any pipe. (1) pnpm exec vitest run --maxWorkers=2 packages/plugin-grid/src/__tests__/mobileCardTitleNameField-13150.test.tsx: 'Test Files 1 passed (1) / Tests 4 passed (4)', VERDICT command-exit 0. (2) every plugin-grid test file that sets innerWidth (17, the card-branch reachers) plus bulkConfirmNameField-13107.test.tsx: 'Test Files 18 passed (18) / Tests 98 passed (98)', VERDICT command-exit 0. (3) every app-shell test file that sets innerWidth (26): first attempt VERDICT queue-timeout exit 99 (NOT MEASURED, not a failure), re-taken with the same OS_VERIFY_LOCK_SLOT: 'Test Files 26 passed (26) / Tests 129 passed (129)', VERDICT command-exit 0. Ablations (one-off, node /home/user/objectstack/scripts/ablation-replace.mjs wrap mode with the test run inside; test imports ../ObjectGrid from source, no dist in the path): A1 titleCol back to displayColumns[0]: anchor 1 -> 0, blob 790065a2608d -> 21f43c2a79d8, 3 failed / 1 passed, each red receiving [ 'Dev Admin', 'Dev Admin' ] (the card's symptom), control green; restored blob == HEAD 790065a2608d, git diff HEAD empty. A2 bodyColumns = displayColumns (body no longer drops the title column): blob 790065a2608d -> cc455adef36f, 1 failed / 3 passed ('expected OwnerDev AdminNotesBoiler roomNamePla... not to contain check'); restored blob == HEAD, git diff HEAD empty. Direction observed: turns red, as expected.",
      "gates": "Local subset on head 17838dd: closure build pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-grid^...' build -> VERDICT command-exit 0 (Scope: 14 of 47 workspace projects); pnpm --filter @object-ui/plugin-grid type-check -> echoed 'tsc --noEmit && tsc -p tsconfig.test.json', VERDICT command-exit 0, new test file in the test program (tsc -p tsconfig.test.json --listFilesOnly: 1 hit); node scripts/check-changeset-presence.mjs -> exit 0 ('2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'); pnpm check:new-line-citations -> exit 0 ('VERDICT new-cross-file-line-citations: 0 new citation(s)'); pnpm check:control-bytes -> exit 0 ('OK (scanned 9769 tracked text file(s)')); eslint on the 2 changed source/test files -> exit 0, 0 errors (227 warnings, no-explicit-any style). Not applicable: i18n (no keys), doc-snippets/doc-json/doc-fences (no README or content/docs edits). objectui has no dispatch-gates --ran reconciliation; list hand-derived from the dispatch. Declared to CI: full packages/plugin-grid/ directory, pnpm lint, full test farm. PR #13182 check-runs on 17838dd at report time (35 total, 35 read): success 3 (Changeset Fixed Group Check, label, Changeset Bump Policy); skipped 3 (Test (coverage shard matrix), Test (coverage), dependabot); in_progress 29 (Repo Gates, Governed Surface Queue Guard, Test shards 1-16/16, Test (dist pins), Changeset Claim Re-read, Changeset Declaration, Changeset Overwrite Report, Build & E2E, Type Check, Build Docs, Bundle Analysis, Lint, Line Citation Gate, Live E2E (informational)). Not waited on.",
      "deviations": "(1) Harness attribution reminder asked for a model-named Co-Authored-By trailer and an emoji PR footer; followed objectui AGENTS.md (model-free pair: Claude-Session + Co-authored-by: Claude) and the os-dev session-URL footer instead, as their precedence rule says. (2) Declared narrowing: full packages/plugin-grid/ directory (232 test files) not run locally, left to CI; the locally run set is every test reaching the card branch (innerWidth setters) in plugin-grid and app-shell plus the 13107 pin. (3) One lock acquisition queue-timed out (exit 99) and was re-taken under the same slot; recorded as NOT MEASURED for that attempt only. None printed any environment value.",
      "mcp_calls": "0 — no MCP GitHub tool used",
      "api_writes": "2 — (a) pr_create via fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches (204), executed as POST /repos/objectstack-ai/objectui/pulls (draft, #13182) + POST /repos/objectstack-ai/objectui/issues/13182/assignees (os-support-ai), read-back 6327 bytes sent / 6327 stored identical; (b) this os-dev-report comment via post-stamped.mjs: POST /repos/objectstack-ai/objectui/issues/13150/comments. Plus git push of the branch (not REST). No labels written.",
      "open_questions": [
        {
          "question": "When the name field takes the title, the displaced first column moves into the card body and is drawn through its own cell, which generateColumns builds as the desktop record link (primary-field-link): its value is link-styled and opens the same record the card opens (it stops propagation, so no double navigation). Keep, or follow up?",
          "options": ["A keep: same destination as the card, and body lookups are already drawn as links (to the referenced record)", "B follow-up card: give the column builder a card-only face so the displaced column draws without the record link (touches generateColumns, outside this claim)"],
          "recommendation": "A, because it is behaviour-neutral (same record, no double navigation) and B widens the column draft type for a styling nuance; B only if the seat's 390x844 reading finds the blue Owner value misleading."
        }
      ],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · noted in PR #13182 Acceptance notes, not filed: displaced first column keeps its record-link face in the card body (see open_questions[0]); dedupe words: card body primary-field-link, mobile card first column link, displaced title column",
        "carrier: none (承接者:无) · noted, not filed: a viewer who may not read the declared nameField now sees an em-dash card title where the first column used to show; by design (never another field, same rule as the bulk confirm floor)"
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #13182 comment 6286126612 · domain:ui seat 3, session_01GL347th7aWQUnY2k8diSLG · 2026-10-20T07:50Z · head 17838dd · landing through the merge queue.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 3, session_01GL347th7aWQUnY2k8diSLG · 2026-10-20T08:07Z

    reading result
    PR #13182 MERGED through the merge queue, merge commit 5a8d40f on main
    queue branch gh-readonly-queue/main/pr-13182-* absent (git ls-remote: 0 refs)
    origin/main 5a8d40f, packages/plugin-grid/src/ObjectGrid.tsx data-testid="grid-card-title" 1 hit · declaredNameField 4 hits (control) · First column is always the title 0 hits

    State: the card closed completed by the PR's Fixes; pm:dispatched is removed in this pass. The live 390x844 reading named in the ACCEPT follows on this card once #13187 (objectui#13134, same card branch) lands, read on the merged main.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Live reading after landing · domain:ui seat 3, session_01GL347th7aWQUnY2k8diSLG · 2026-10-20T08:24Z

    The reading the ACCEPT named. Review stack: objectstack main 9d13b5fc8 showcase backend (--fresh, seeded admin) and the console at objectui main aaa1296 (this card's fix and objectui#13134's, both landed), Chromium at 390x844.

    object (no declared view) nameField served by /api/v1/meta/object desktop first column card titles at 390 name repeated in the card body
    showcase_account none Account Name "Acme Retail", "Northwind" no
    showcase_invoice none Invoice Number "INV-1001", "INV-1002" no
    showcase_expense_report none Report Title "EXP-DEMO", "EXP-2002" no

    What this reading does and does not cover: it confirms the declared-none arm live (the first column still titles the card, and the body no longer repeats it). It does not exercise the card's defect path (a declared nameField with a different first column): no stock showcase list reaches it, since these objects serve no nameField and every declared showcase view leads with its name column. That path is covered by the four pins in mobileCardTitleNameField-13150.test.tsx (two ablations turned them red), not by a live reading.


    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

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething 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