Skip to content

fix(ui): Setup metadata lists take their title from the sidebar and lead with the label - #28197

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-pz9hl0
Oct 30, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-pz9hl0

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Tesla · project thread

维护者速读

  • 改了什么:Setup 里的元数据列表(岗位、权限集等)标题改用侧栏里打开它的那一项的名字,所以显示「Positions / 岗位」这类侧栏原词,而不是类型的单数名「Position」;每一行先显示标签(如 Sales Director),API 名小字等宽放在下面,不再单独占一列「Label」;描述最多两行,悬停看全文,手机上一行不再撑到 180 px 高。
  • 为什么改:Setup and Studio: suggestions from a full HotCRM browser pass on 18.2.0: user onboarding, packaged automation state, run-now for scheduled flows, admin lists, and Studio entry, field table, flow inspector wording and one designer per item #27356 第 5 行(hotcrm#2320 Setup S4):HotCRM 浏览器走查指出标题是单数、首列是 API 名、手机上行太高。
  • 风险与回滚:只改 Setup 下的列表外观;同一页面在 Setup 之外(元数据目录、Studio 的「在 Setup 中打开」)完全不变;侧栏没有恰好指向本页的入口时标题退回类型名。回滚就是 revert 本 PR。
  • 先看:ResourceListPage.tsx 里 setupTitle / labelColumn(objectstack#27356 注释处)与新文件 navEntryTitle.ts。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/views/metadata-admin/ResourceListPage.setupLabelFirst-27356.test.tsx,应见 5 passed。
  • 需要你做的:无,席位落地。

Part of #27356 (row 5, hotcrm#2320 Setup S4: Setup metadata lists read as admin lists)
Clause-②: no
Metadata-protocol: none

What changes

  • The title is the sidebar's word for the page. Under Setup, ResourceListPage's header now takes the label of the app's own navigation entry that opens exactly this page, through the new navEntryTitle (metadata-admin/navEntryTitle.ts). The entry is elected by @object-ui/layout's resolveActiveNavItem, the one "which menu am I in" matcher, and counts only when its own address (resolveHref) is this page's path; its text goes through resolveNavItemLabel, as the sidebar's does. Setup's Access Control entries are type: 'url' entries (nav_positions labelled "Positions", nav_permission_sets "Permission Sets"), served in the reader's language, so the page reads as the row that opened it in every locale the app's bundle carries. With no such entry, the title falls back to the type's label, as before. No plural table is added to the ui registry and nothing changes in packages/spec.
  • Label first, API name beneath. Under Setup, when a type's first column is its primary key and it also lists label, the two fold into one cell: the label is the row's link, the API name sits under it in small monospace type (metadata-row-api-name), and the separate Label column goes. The folded column's header is the Label column's. An item with no label keeps its API name as the monospace link, as before.
  • Short rows. Under Setup a description cell shows two lines at most (line-clamp-2) with the whole text in its title, so a long description no longer stretches a row at phone width.
  • Outside Setup nothing changes: the directory list and Studio's "Open in Setup" target keep the API name column, the Label column, the type's label as the title and unclamped descriptions.

Tests

  • New ResourceListPage.setupLabelFirst-27356.test.tsx (5 tests), on the real page with the metadata client doubled as ResourceListPage.setupPosture-12606 does and the served Setup app's navigation handed in through the expression context:
    • the header reads "Positions" from the nav_positions entry;
    • with no entry opening exactly this page it reads "Position";
    • a row's link is "Sales Director" (not monospace), its API name sales_director sits beneath, the header has one "Label" column first and no "Name" column; an unlabelled item keeps its monospace API-name link;
    • a long description carries line-clamp-2 and its whole text as title;
    • CONTROL: the same page under studio keeps the monospace API-name link, the Name and Label columns and no clamp.
  • ResourceListPage.setupPosture-12606: its Setup case found the row by the link name everyone; under Setup that link is now the label, so it finds Everyone. Its outside-Setup control is unchanged.
Readings (head 464325f, base origin/main 9f13ee8; app-shell closure built with declarations)
  • New file: 5/5 passed.
  • Every ui test file naming ResourceListPage, MetadataResourceListPage or navEntryTitle (24 files, the AppContent route suites included): 24 passed, 294/294 tests.
  • pnpm --filter @object-ui/app-shell run type-check (both programs): lock VERDICT command-exit 0.
  • Ablation 1, through scripts/ablation-replace.mjs: const labelColumn = inSetup && columns[0] to const labelColumn = false && columns[0]: 4 failed / 1 passed (the control stays green); restored blob = HEAD blob 1abb07375086, git diff HEAD empty.
  • Ablation 2: (inSetup && navEntryTitle( to (false && navEntryTitle(: 1 failed / 4 passed (the nav-entry title case); restored blob = HEAD, git diff HEAD empty.
  • vitest resolves @object-ui/* to source, so neither ablation needed a rebuild leg.

Acceptance notes

  • Per-row status of Setup and Studio: suggestions from a full HotCRM browser pass on 18.2.0: user onboarding, packaged automation state, run-now for scheduled flows, admin lists, and Studio entry, field table, flow inspector wording and one designer per item #27356's Setup rows (re-measured on main 9f13ee8; the Studio rows 12–22 are settled, handoff 6524323618):

    Row Disposition
    5 Taken here.
    11 Taken, next PR from this thread (All reports empty state points to the apps that have reports for the reader).
    10 Will not do on this card. HotCRM saw Export under Display at 1440 px, not only at phone width: the bundled Display panel with Refresh and Export in its footer is the default at every width by objectui#12423's maintainer-approved design ("Refresh and Export leave the bar (they live in the Display footer)"). Moving Export back to the bar or the ⋯ menu reverses that design and needs a maintainer call.
    1 Finding, carrier domain:server: Create User's params are server metadata (create_user on sys_user, platform-objects; permissionSet is an inline type: 'text' param) and the create-user door accepts no position.
    4 Finding, carrier domain:server: POST /automation/:name/trigger refuses a runAs: 'system' schedule flow for anyone but the system principal (flowStartRefusal); all of HotCRM's schedule flows run as system.
    6 Finding, carrier domain:server: the Users row menu is sys_user's server actions; there is no deactivate verb, only Ban.
    7 Finding, carrier domain:server: "Record ID" is sys_approval_request's own field label (plugin-approvals).
    8 Finding, carrier domain:server: plugin-approvals knows a request opened on its fallback approvers but persists no marker a reader can show.

    The seat files the domain:server cards; this PR is Part of, and the row 11 PR closes the card once every row is landed or answered.

  • The title follows the navigation, not a registry plural. A list reached by a URL no Setup entry carries (a typed address, another app's link) still reads the type's singular label. That is the honest fallback: the type registry carries no plural label, and adding one is a spec change this card does not take.

  • The folded column applies only where the type lists label with the primary key first; a type with its own columns (for example the field list, which leads with name then object) keeps its layout.

  • Measured in happy-dom, not in a browser at 390 px: the row height on a phone was not re-measured.

Verification

On head 464325f: dispatch-gates --commands derived 34 families for this diff; all 34 were run locally with stdin closed, each exit 0, and --ran reconciled 34 run, 0 NOT-MEASURED, 0 UNRUN. check:new-line-citations: 0 new (report-only gate). dispatch-gates --tier: no path-derived mandate; 259 changed lines. CI check-runs were in progress when this was opened.

The harness's after-PR assign and review-request step is skipped on the order's word (the seat lands).


Generated by Claude Code

@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling labels Oct 30, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · os-tesla · session_01L9qibwpXbWKjEuA5DF45BL

Test UI (2/16) is red on flow-value-envelope.test.ts:77, the main-red pin from #28185 (the ledger gained connector_action:input.*), not this diff; it clears when its fix #28193 merges and origin/main is merged into this branch.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · os-tesla · session_01L9qibz8HEj53Wx2uphTo2o

维护者速读

席位意见:只动 Setup 下的列表外观,标题复用侧栏的同一套匹配与取名函数,不新增复数表、不碰 spec,两处消融都有测试接住,可直接落地。

席位核对

ACCEPT · seat domain:ui#3 · head 073626e1 · 2026-10-30T17:00Z

  1. Shape: Part of #27356 (row 5), draft, base main; 5 files, +247/−12: new metadata-admin/navEntryTitle.ts (elects the entry with @object-ui/layout's resolveActiveNavItem, counts it only when resolveHref(item).href is this path, names it with resolveNavItemLabel), ResourceListPage.tsx (setupTitle with type-label fallback; label + mono API name fold only when inSetup and the first column is the primary key; line-clamp-2 + title on descriptions under Setup), new suite ResourceListPage.setupLabelFirst-27356.test.tsx (5, incl. a studio CONTROL), one finder tweak in setupPosture-12606, changeset @object-ui/app-shell patch. Seat read of the diff.
  2. Premise measured: the dev re-measured rows 1,4,5,6,7,8,10,11 on main 9f13ee81 (per-row table in the PR body); ablations on labelColumn (4 fail / 1 pass, control green) and on the navEntryTitle call (1 fail / 4 pass), restored blobs = HEAD.
  3. Gates / check-runs: on head 073626e1 (merge of origin/main with test(ui): pin the 19th flow value-ledger entry, connector_action input.* #28193's pin fix) every latest check-run is success or skipped, 0 failure, incl. all 16 Test UI shards, Type Check UI, Lint UI, Live E2E UI, Build & E2E UI, PR-body guards; mergeable_state clean. Dev: 34/34 derived families exit 0, --ran 0 NOT-MEASURED, 0 UNRUN; 18/18 for flow-value-envelope + both ResourceListPage suites after the merge.
  4. Accepted deviations: a merge commit from origin/main instead of a rebase (thread branch, keeps the reviewed commits); row height at 390 px measured in happy-dom only, not a browser (declared in the PR body).
  5. Out of scope: rows 1, 4, 6, 7, 8 (server-side; the seat files the domain:server cards or screens them out), row 10 (will-not-do, objectui#12423 design, maintainer call), row 11 (next PR from this thread, carries Fixes #27356). No registry plural label, no packages/spec change. Skills-docs: none — Metadata-protocol: none.
  6. Landing: check-governed-merges --pr 28197 NOT governed, 259 changed lines ≤ 3000; no contract review owed (Clause-②: no, no packages/spec path); changeset present. The seat readies it and arms auto-merge under the maintainer's 「按 pm-dispatch 审过的pr你可以自主落地」.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 30, 2026 17:01
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 41095303977 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

分类:failure —— 按下面的日志分诊。

失败的 job(日志抽取,best effort):

  • Test UI (13/16) — 失败步骤: Run the ui tests (shard 13/16)

    × the node cell and the Problems list both name the blank expression, in the same words 2671ms
    FAIL   dom  packages/app-shell/src/views/studio-design/AutomationsPillar.problemsAgree-27799.test.tsx > Automations page — Problems and the node agree on a blank expression (objectstack#27799) > the n
      ↳ 失败原因: AssertionError: expected 'flows[0].nodes[1].config.fields.id' to contain 'node \'write\''
    

↳ 失败原因 是判读的关键:超时(Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言(AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

⚠️ 断言这一侧有一类例外,判据是断言在测什么,不是它是不是 AssertionError。 断言的对象是产品行为(一个值、一个形状、一次拒收)⇒ 照上面读:真实的行为改变,去查,⛔ 不要重排掉;
断言的对象是这次实验自身的有效性前提(跑完的耗时、负载下的先后、任何只在时间预算内才成立的条件)⇒ 它跟超时是同一类,同样对负载敏感,重排一次是合法的判别手段。
识别是机械的:断言的消息或它比较的值本身点名了一段时长、一个时间戳、一个耗时计数。实测过的一对 —— AssertionError: SecurityPlugin.init() ran: expected false to be true 测的是产品行为(真回归);
AssertionError: this run took over a second, so second-precision stamps could have differed too: expected 1006 to be less than 1000 测的是实验前提:它守护的那条不变式当时是绿的,同一个 head 原样重排一次即成功。
穿着 AssertionError 外衣的时间测量,仍然是时间测量。(⛔ 这只改「怎么读一次红」,不改「哪些测试可以重排」——后者由别处管。)

跨 PR 相同签名(24h,按失败测试文件聚合):

  • packages/app-shell/src/views/studio-design/AutomationsPillar.problemsAgree-27799.test.tsx — 24h 窗口内只有本 PR 撞到过,暂不汇总(再有一个不同 PR 撞到就会自动开汇总 issue)。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 4 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 30, 2026
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit 39da1bd Oct 30, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-pz9hl0 branch October 30, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant