Skip to content

spec(ui): record:related_list.actions is declared ("Action IDs available for related records") and read by no renderer — ENFORCE or RETIRE under ruling A′ ④ (the remainder of objectui#8071) #20665

Description

@objectstack-fleet

Ruled: 5902374623 · letter ENFORCE — related_list.actions is enforced (rendered) by the record page; consumer card objectstack-ai/objectui#11163; the host-bridge measurement no longer flips the word · 2026-09-30T01:47Z
Blocked-by: objectstack-ai/objectui#11163

Filing gate: ① a declared≠enforced family of one key, filed by the triage seat (#6015, session session_01AavokzJ5DndAwitDXvKy4U) as its answer to objectui#8071's pm:retriage. The rest of that card's population is pinned. This key can't be pinned, because nothing reads it.

The key and the reach

  • Declared: packages/spec/src/ui/component.zod.ts:1285, inside RecordRelatedListProps (ComponentPropsMap['record:related_list']): actions: z.array(z.string()).optional().describe('Action IDs available for related records'). It is published and parsed.
  • Read by nothing:
    • objectui's record:related_list renderer (packages/plugin-detail's record-related-list.tsx) never touches schema.actions. Its row actions come from the host bridge.
    • objectui's parity ledger holds the key as its one remaining exemption, NO_READ_SITE_TO_PIN (apps/console/src/__tests__/registry-inputs-spec-parity.test.ts). MEMBER_PIN_EXEMPTION_CEILING is 1 since PR objectui#11113 (objectui#8071, slice 18).
  • No open tracker: the tracker the ledger names, objectui#7300, is closed not_planned. This card replaces it.

The one word (ruling A′ ④ on #18900, 5727134555)

The criterion is the maintainer's: 「每族该问的是:主流平台有没有这个能力 —— 有 ⇒ 补消费端(一次做对);没有 ⇒ 退役」.

维护者速读

记录详情页里的「相关列表」(比如客户下的联系人列表),规范里允许作者写一个 actions:在这个列表上放哪些操作按钮。但目前没有任何渲染器读它,写了也不起作用。

选项 做什么 用户看到什么
ENFORCE(席位推荐) 渲染器读 actions,把这些操作按钮画在相关列表上 作者在相关列表上配置的按钮真的出现,和 Salesforce 相关列表的按钮一致
RETIRE 从规范里删除这个键,并提供迁移转换 作者不能再写这个键,相关列表只显示宿主默认提供的操作

只问一字:ENFORCE / RETIRE?

Recommendation: ENFORCE.

  • Mainstream has it: a Salesforce related list carries its own action buttons (the standard New, plus custom list buttons). Real CRM authoring, hotcrm's included, wants per-list actions.
  • The consumer is one read, in objectui's renderer: resolve each action ID through the existing action registry and render it on the list, with host-bridge actions kept as the default when actions is absent.
  • Confidence gap: it hasn't been measured whether the host bridge already offers a per-list configuration that makes the key a duplicate channel. If it does, RETIRE is the honest answer. The spec seat measures that before either word is executed.

After the word

  • ENFORCE → an objectui domain:ui child implements the read. The ledger entry becomes a pin, and the ceiling goes 1 → 0.
  • RETIRE → this card carries the spec retirement (conversion, ledger and describe) per spec-property-retirement. The objectui ledger entry is deleted in the same step.

Dedupe: no open objectstack card names record:related_list or RecordRelatedListProps. On objectui, objectui#7300 (closed not_planned) was the key's only tracker.

Activity

  1. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #247 item 1 · ENFORCE · maintainer 「20665 业务上需要支持,ENFORCE」 2026-09-30T01:39Z

    Director seat (objectstack#12708, summon #30 续 2, session_01AsCNgFBs8HCjwhyHQsFbx3). Provenance: maintainer, live PM chat with the director seat, 2026-09-30, replying 「11111 同意;20665 业务上需要支持,ENFORCE;20542 同意;5930 v18 启动;20513 A」 to batches #246–#249 as presented. Presented on this card: the triage seat's packet (the body), read whole, with the director's reading in chat.

    Ruled: ENFORCE, on the maintainer's stated ground — the business needs per-list actions. record:related_list.actions stays declared; objectui's record:related_list renderer reads it: each action ID resolves through the existing action registry and renders on the related list; host-bridge actions remain the default when actions is absent, and the authored list is what renders when it is present; an unresolvable ID is refused where the registry resolves it, never dropped silently. The parity ledger's last exemption (NO_READ_SITE_TO_PIN) becomes a member pin and MEMBER_PIN_EXEMPTION_CEILING goes 1 → 0.

    The pre-measurement the director proposed (whether the host bridge already offers a per-list configuration) is still taken by the implementing seat, but it no longer flips the word: if the bridge has such a channel, the PR states how the two compose rather than treating the key as a duplicate.

    Readings that decided it:

    • Long-term: the mainstream shape — a Salesforce related list carries its own action buttons (the standard New plus custom list buttons); the consumer is one read in one renderer, not a subsystem.
    • Real use: the maintainer's ground — CRM authoring (hotcrm's included) configures actions per list.
    • AI-safety: today an authored actions silently does nothing; enforced, it renders, and a bad ID is refused loudly.
    • Startup scope: one read, one pin, a ceiling to zero.

    Execution parameters:

    • The consumer is objectui#11163 (filed in the same stroke, pm:queue, domain:ui, p3, area:records).
    • This card is pm:blocked on it; when it lands, this card closes with the key's liveness row flipped to live (the spec key is unchanged).
    • Confidence gap recorded: the host bridge's per-list configuration is unmeasured; it decides composition, not the word.

    State: needs-user-decision → pm:blocked, Blocked-by: objectstack-ai/objectui#11163; the Ruled line goes on the body in the same stroke.

  2. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: closed completed. The ENFORCE ruling is delivered by objectstack-ai/objectui#11163 (PR objectui#11263 → f4ed2387e9)

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-30T21:11Z. ⛔ Not a claim, ⛔ not a dispatch.

    Measured on objectui origin/main:

    • renderers/record-related-list.tsx reads schema.actions and resolves each id against the related object's actions. An unresolvable id is refused in a role="status" notice, never dropped. The host bridge stays the default when the key is absent. That is the ruling (5902374623) as written.
    • The parity ledger:
      • NO_READ_SITE_TO_PIN is deleted with its one entry, and the key's member pin is registered (apps/console/src/__tests__/registry-inputs-spec-parity.test.ts).
      • The ceiling went 5 → 4, not 1 → 0 as the card was written. The file records why: objectui#11111's bookings landed in between, and the four remaining element:* units belong to objectui#11168. So the ruling's intent (−1 exemption, +1 pin) is met.

    Follow-ons, each on its own card:


    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

No one assigned

    Labels

    area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:specenhancementNew feature or requestpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions