Skip to content

Record highlight strip: chip captions render empty when the highlight fields arrive as bare names and the object has no i18n bundle — every AI-built record page shows 「陈静 | 周明轩」 unlabeled #26417

Closed

Description

@objectstack-fleet

Filing gate ① a reproduced UX defect (class a, public door: a record page). reach: local stack, objectui pin 6f629a7 (cloud main 36b07fdf), zh-CN. Measured 2026-10-25 and re-measured 2026-10-27. On an AI-built app's record drawer (家装项目), the highlight strip under the title shows 「陈静 | 周明轩」 (the owner and the 关联客户 lookup) with no field labels. In the DOM, each chip's label element is rendered empty: <span class="text-xs font-medium text-muted-foreground"></span>. Same on every record of that object, for owner and member alike.

Batch-of: 2 · 2026-10-27 follow-up to the 2026-10-25 desktop E2E (doubtful items re-measured). Filed at the maintainer's request: 「必要的合理的建议都可以立卡」 / 「有疑点的进一步确认」.

Business reason. The strip is the record's at-a-glance summary. Two bare names side by side cannot be read: which is the owner and which is the customer? Every AI-built app, and any object whose fields have no entry in an i18n bundle, shows this on every record page. HotCRM does not, because it ships translations, which is why it went unnoticed.

Reader who acts. The domain:ui seat: ui/packages/plugin-detail (objectui was folded into this repository; objectstack#25854).

Where (measured on objectui pin 6f629a7; still present on objectstack main: ui/packages/plugin-detail/src/HeaderHighlight.tsx:334, ui/packages/plugin-detail/src/renderers/record-highlights.tsx:127)

  • The page builder passes highlight fields as bare names (synth/buildDefaultPageSchema.ts:738, from deriveHighlightFields).
  • renderers/record-highlights.tsx:125-127 normalizes a string to { name }, with no label.
  • HeaderHighlight.tsx:323 renders fieldLabel(objectName, field.name, field.label). Its fallback is field.label, which is undefined here.
  • The object definition's label is in hand two lines up (objectDefField, :137, already merged into enrichedField at :145) but is never used for the caption. With no i18n key for an AI-built object, resolve(…, undefined) yields nothing.

Expected

The caption falls back to the object definition's label: fieldLabel(objectName, field.name, field.label ?? objectDefField?.label ?? enrichedField.label), so it reads 「所有者」 / 「关联客户」. Cover it with a test that mounts the strip from bare names on an object with no translation bundle.

Dedupe

gh api search/issues, repos cloud / objectui, incl. closed:

  • highlight label empty: 10 / 98.
  • HeaderHighlight label: 1 / 57.
  • highlights strip label missing: 3 / 36.

The nearest are objectui#11684 and #12523 (closed, value truncation) and #12498 (closed, approvals page submitter). None is about an empty caption.

Activity

  1. added
    bugSomething isn't working
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    on Oct 27, 2026
  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: audit line · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-27T05:07Z

    ⛔ Not a claim, ⛔ not a dispatch. The filer's labels are read and kept; this is the triage line an execution seat needs before it claims.

    • Triage: lands in the record highlight strip (ui/); rationale: p2 · domain:ui · area:records. When the highlight fields arrive as bare names and the object has no i18n bundle, the chip caption should fall back to the field's declared label, the way the form does. ⛔ No machine-name fallback when a label exists.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 14 · 2026-10-27T05:27Z
    Session: session_01SMps7wq7rBTk53e8KTSEup
    Account: os-steve
    Branch: claude/issue-26417-highlight-chip-caption
    Worktree: objectstack-issue-26417
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: ui/packages/plugin-detail/src/HeaderHighlight.tsx (~:333 chip caption) and ui/packages/plugin-detail/src/renderers/record-highlights.tsx, tests beside them, root .changeset/. ⛔ DetailSection.tsx (#26329, PR #26487). ⛔ locale packs under ui/packages/i18n unless the card needs a new key (then en + zh only, and say so), ui/.github/**, root ci.yml.
    Container & model: M, mode:subagent, model: default tier, effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: a reader of a record's highlight strip on an object with no i18n bundle | the object's field labels from its schema | every record page with highlight fields, AI-built apps above all
    Thread-read: none
    Premise: holds 2026-10-27T05:27Z at origin/main 00a4593ad7: HeaderHighlight.tsx:333 renders the caption span, which the card measured empty when the highlight fields arrive without a translation entry.
    Serial constraints cleared: the pencil change of #26325 in HeaderHighlight.tsx has merged; no open PR touches it.
    Writes: PR only via the relay op pr_create; comments only via the relay write tools; ⛔ no GitHub MCP writes.

    • Seat's route: the caption falls back to the field's schema label (then its name), the same fallback the details body uses, whenever no translation exists or the label arrives late. Pin red-first: a field with no bundle entry shows its schema label. Fixes #26417.
  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26417,
      "status": "done",
      "branch": "claude/issue-26417-highlight-chip-caption",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26564",
      "head": "542908d27b0ba96b56d31592f2621fc451a72bf4",
      "session": "session_01SMps7wq7rBTk53e8KTSEup",
      "premise_still_valid": true,
      "summary": "The highlight strip's chip caption in HeaderHighlight.tsx now climbs the details body's label ladder: bundle key, then the entry's own label, then the object's declared label (pickLocalized in the session language), then the field name. Before, it was fieldLabel(objectName, name, field.label), which rendered an empty caption for every bare-name highlight on an object without a bundle. The ladder sits in HeaderHighlight, not in the record:highlights normaliser, so DetailView's direct highlightFields path gets the same caption, and it is computed per render, so a late object definition replaces the field-name caption. record-highlights.tsx gains only a comment saying where a bare name's caption comes from. DetailSection.tsx and record-details.tsx are untouched. The card's assignee was empty and was left as is; the PR has no assignee.",
      "files_changed": [
        ".changeset/26417-highlight-chip-caption.md",
        "ui/packages/plugin-detail/src/HeaderHighlight.tsx",
        "ui/packages/plugin-detail/src/renderers/record-highlights.tsx",
        "ui/packages/plugin-detail/src/renderers/__tests__/record-highlights.declaredCaption-26417.test.tsx"
      ],
      "line_budget": "250 changed lines (+249 / -1, 4 files) vs merge base d2ca7079b; human-merge threshold 3000: under",
      "tests": "RED at 0729de2e (test only): from ui/ under the lock, pnpm exec vitest run packages/plugin-detail/src/renderers/__tests__/record-highlights.declaredCaption-26417.test.tsx: VERDICT command-exit 1, Tests 7 failed (7). Four legs got an empty caption (received ''), and the bundle-wins and authored-wins legs passed their first assertion before failing on the unbundled sibling's empty caption. The agreement leg failed on a harness issue (the body drops 'owner' as the record title when no name field is declared) and was switched to customer and stage in the fix commit. GREEN at 542908d2 (fix plus origin/main merged; the plugin-detail closure was rebuilt under the lock first): from ui/, pnpm exec vitest run packages/plugin-detail --maxWorkers=2 exited 0 with Test Files 310 passed and 1 skipped (311), Tests 2876 passed and 18 skipped (2894). pnpm --filter @object-ui/plugin-detail type-check (tsc --noEmit && tsc -p tsconfig.test.json) exited 0. The new file alone, verbose: Tests 7 passed (7). No ablation: the red run on the pre-fix tree is the proof.",
      "gates": "At 542908d2: dispatch-gates --commands --repo objectstack-ai/objectstack derived 34 commands, each run with its exit code captured before any pipe. 32 exited 0, among them node scripts/check-sdui-manifest.mjs ('sdui.manifest.json is present and intact ... 106 components'; no registry contract changed, so it was not regenerated) and its --self-test. NOT MEASURED: pnpm check:type-check-debt (exit 3, PREREQUISITE NOT MET; its closure build hit queue-timeout on the shared lock twice). NOT MEASURED: pnpm --dir ui exec vitest run scripts/ (exit 1, but the run was SIGKILLed before its summary; two tests had already timed out at about 18.8 s under contention, check-hand-rolled-comment-mask.test.ts and js-comment-mask-returns-interpolation-9424.test.ts, both testing ui/scripts/, which the diff does not touch; node ui/scripts/check-hand-rolled-comment-mask.mjs run directly exits 0). --ran: '34 derived famil(ies) accounted for — 33 run, 1 NOT-MEASURED', exit 0. The tree was 25 commits behind origin/main at reconciliation. CI check-runs: in_progress at report time, not awaited.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0 — no GitHub MCP calls",
      "api_writes": "2 — relay repository_dispatch (fleet-write) for pr_create, i.e. POST /repos/objectstack-ai/objectstack/pulls (PR 26564, draft, 6566 bytes sent and stored identical); relay repository_dispatch (post-stamped) for this report comment, i.e. POST /repos/objectstack-ai/objectstack/issues/26417/comments. git push is not counted.",
      "deviations": [
        "record-highlights.tsx carries only a comment change. The ladder lives once, in HeaderHighlight, because HeaderHighlight has two callers (record:highlights and DetailView.highlightFields) and filling the label in the normaliser would leave the DetailView path empty.",
        "Two derived gates are NOT MEASURED locally (type-check-debt, the ui/scripts vitest run), as listed under gates. This narrowing is declared and CI is the reading.",
        "Commit trailers are AGENTS.md's model-free pair (Claude-Session plus Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By. AGENTS.md takes precedence over that reminder.",
        "origin/main was merged once before the PR opened (542908d2) so the gates would not run on a tree 22 commits behind."
      ],
      "open_questions": [
        {
          "question": "Should the label ladder become one shared helper used by both record-details.tsx (withDeclaredLabel) and HeaderHighlight?",
          "options": [
            "A: leave both. The agreement leg in the new test pins that the two give the same text",
            "B: a follow-up extracts a helper into plugin-detail and edits record-details.tsx (outside this card's surface)"
          ],
          "recommendation": "A, because the agreement pin already catches drift and record-details.tsx was outside this card's file surface"
        }
      ],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — the caption ladder is spelled in two places (record-details.tsx withDeclaredLabel, HeaderHighlight caption); it is pinned equal by the agreement leg; recorded in the PR's Acceptance notes"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · seat 2 · 2026-10-27T09:25Z

    probe reading
    PR #26564 MERGED 2026-10-27T09:16Z, merge commit 2dd332dd, head 542908d2 (+249/−1, seat record on #26564)
    origin/main contains it (git merge-base --is-ancestor exit 0)
    queue branch gh-readonly-queue/main/pr-26564-*: none left (consumed)
    card closed (completed) by Fixes #26417 on #26564

    Status: the record highlight strip's chip captions show the object's declared field label (or the field name) when no translation exists, the same ladder as the details body. pm:dispatched removed.

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:uipriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions