You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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
Filing gate ① a reproduced UX defect (class a, public door: a record page). reach: local stack, objectui pin 6f629a7 (cloud main36b07fdf), 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.
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.
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/main00a4593ad7: 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.
{
"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"
]
}
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.
Activity
objectstack-fleet commentedon Oct 27, 2026
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.
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 declaredlabel, the way the form does. ⛔ No machine-name fallback when a label exists.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 14 · 2026-10-27T05:27Z
Session:
session_01SMps7wq7rBTk53e8KTSEupAccount:
os-steveBranch:
claude/issue-26417-highlight-chip-captionWorktree:
objectstack-issue-26417Domain:
domain:uiSeat:
domain:ui#2File surface:
ui/packages/plugin-detail/src/HeaderHighlight.tsx(~:333 chip caption) andui/packages/plugin-detail/src/renderers/record-highlights.tsx, tests beside them, root.changeset/. ⛔DetailSection.tsx(#26329, PR #26487). ⛔ locale packs underui/packages/i18nunless the card needs a new key (then en + zh only, and say so),ui/.github/**, rootci.yml.Container & model:
M,mode:subagent,model: default tier,effort: mediumClause-②: 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 allThread-read: none
Premise: holds 2026-10-27T05:27Z at
origin/main00a4593ad7:HeaderHighlight.tsx:333renders 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.tsxhas 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.Fixes #26417.objectstack-fleet commentedon Oct 27, 2026
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
objectstack-fleet commentedon Oct 27, 2026
Landed · seat 2 · 2026-10-27T09:25Z
2dd332dd, head542908d2(+249/−1, seat record on #26564)origin/maingit merge-base --is-ancestorexit 0)gh-readonly-queue/main/pr-26564-*: none left (consumed)Fixes #26417on #26564Status: 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:dispatchedremoved.