Skip to content

console(record header): a url action placed at record_header on sys_user no longer renders in the 18.3 Console header menu, drawer or full page (18.2 rendered it) #29951

Open

Description

@objectstack-fleet

triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

Ruled: 6624172200 · letter A · 2026-11-04T06:22Z · amended by 6624212682 (no 18.3.x patch; the release note is written with the release that carries A) · 2026-11-04T06:24Z
Ruling-ref: 6624172200, 6624212682

Filing gate ①: a reproduced regression in 18.3.0, split out of #29946 by triage. The #29946 report names it as a second, separate defect ("a url action at record_header on sys_user … no longer renders in the 18.3 console's header menu, in the drawer or on the full page. 18.2 rendered it."). Its evidence is in the objectstack-ai/duly 18.3 browser check (duly-18.3-browser-check/REPORT.md, R1), from duly#185. ⛔ Not a claim.

Reader: domain:ui, the record-page header action menu (ui/packages/app-shell).

What happens

  • Metadata: a type: 'url' action whose locations include record_header, on sys_user (the duly app's member page), is served in the metadata on 18.3.0.
  • 18.3.0 Console: it is absent from the record header's menu, in the drawer and on the full page.
  • 18.2.0 Console: it rendered.

Wanted

  • Measure first. Reproduce on main with a packaged url action at record_header on sys_user, and on a non-system object as the CONTROL. Name the commit that dropped it.
  • The header menu then renders a served record_header url action again, wherever 18.2 rendered it.
  • Pin: the action appears in the header menu on the drawer and on the full page. The pin is red on the dropped commit's parent behaviour.

Graded p1: a shipped regression, for a patch release.

Links: #29946 (the server half from the same report), duly#185.

Activity

  1. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-support-ai · session_01WGufzjDyeFwq6AuFu3vwTd

    Claim: PM loop round 2 · 2026-11-03T17:12Z
    Session: session_01WGufzh8VRbTbBnqwnrXsSL (card thread; dispatching seat session_01WGufzjDyeFwq6AuFu3vwTd)
    Account: os-support-ai
    Branch: claude/project-thread-4y2o5l (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-29951
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/app-shell/src/views/ record-header action paths (DeclaredActionsBar.tsx, RecordDetailView.tsx, recordApprovalActions.ts) and/or ui/packages/components/src/renderers/action/action-bar.tsx, their tests, one root .changeset/ file (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: xhigh
    Clause-②: no
    Metadata-protocol: none
    Responsibility: suspected ui regression between 18.2.0 and 18.3.0 (domain:ui), unless measured to be the server half (#29946) | no platform path covers it | every Console user opening a sys_user record whose app declares a record_header url action (duly#185)
    Thread-read: none
    Premise: unmeasured at claim; the order makes the dev reproduce on origin/main 6a4737ab first and stop on no-repro or a server-side cause (#29946)
    Serial constraints cleared: none (#29897 is in views/metadata-admin/ResourceEditPage.tsx; #29947 and #29949 touch data-objectstack and preview/DraftChangesPanel.tsx)
    Order: /mnt/project-files/ui-orders/29951.md · maintainer scope 「车队可以继续派发了,只派发 p1 p2 ,总并发不超过 20」 (2026-11-03T15:40Z)

  2. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-support-ai · session_01WGufzjDyeFwq6AuFu3vwTd

    待维护者裁决 · #29951 · 2026-11-03T17:45Z

    一句话: 18.3 里 sys_user 记录页不再显示其他包加到记录头的动作,不是前端过滤造成的,而是 #27219 把平台的 sys_user_detail 改成了 kind: 'full' 页面并写死了 11 个动作 id;按现行契约「作者列出的列表就是全集」,别的包后加的动作一律不画。修它就要动这条契约,所以停下来请你裁。

    Governing text: packages/spec/src/ui/component.zod.ts:683、:704(PageHeaderProps.actions:「An authored list is the whole set … omitting the key draws none of the object's actions」),出自 #11592 的裁决(「全部同意」选项 B)。

    实测(dev 读数全文:/mnt/project-files/ui-orders/29951-findings.md;dev 报告评论随后贴本卡):

    选项

    方案 工作量 发版
    A(推荐) spec 在 page:header 上加一个显式开关:「画出绑定对象所有放在 record_header/record_more 的动作,实时读取」;三个平台页改用它。作者写的 id 列表仍然是全集,#11592 的含义不变。 M:spec 一个新键(Metadata-protocol: added,minor)+ ui 读取 + platform-objects 三页 + approvals,各自的钉子 minor,不能进 18.3.x 补丁
    B 改契约语义不加键:作者列表只管本包自己的动作,别的包放到该对象上的动作照常跟在后面。 M–L:需要服务端给每个动作盖来源包戳(代码包折叠进来的动作现在没有),所有作者页行为都变 语义变更
    C(否决) 把 sys_user_detail 改回 slotted。 小 会撤销 #27219 的标签条,slots.tabs 已退役,不可行
    D 不改代码:把 18.3 行为写进文档与发布说明,要加头部动作的包自己发一个 app 级记录页(PageSchema.apps,#29631)。 小:文档 + skills + 发布说明一行 回归保留:Setup 里的抽屉永远看不到这类动作

    四维分析

    • 实际业务需求: 有实测拉动。duly 应用(duly#185)在 sys_user 上加了 url 动作,18.2 显示、18.3 消失,真实部署在用。A、B 恢复它;D 让每个这样的应用多写一个页面才行。
    • 项目长远合理性: A 最干净:「作者列表 = 全集」保持不变,平台页用一个显式声明表达「我要对象的全部动作」,可复用于以后任何想要实时动作集的页面。B 让列表的意义取决于动作来自哪个包,还要服务端补来源戳,长期是一条隐含规则。D 把平台页的限制推给每个应用。
    • 防 AI 写错(尤其写元数据 app): A 是显式、可校验的声明,AI 要么写 id 列表要么写开关,读得懂也查得到。B 的隐式来源规则 AI 很难推断,同一份列表在不同包里含义不同。D 最容易错:AI 在 sys_user 上加了动作、os validate 通过,界面却静默不画,正是「声明而未兑现」。
    • 创业阶段不扩散: A 加一个键,但有真实拉动(荐长远形态一次付清);B 改面更大;D 最省但留下回归和静默丢弃。

    os-decision-facets
    ① 项目长远合理性:A 缩小特例——「作者列表 = 全集」不变,只多一个显式开关;B 让列表含义随动作来源包而变,扩大隐含规则;D 把平台页的限制推给每个应用。
    ② 实际业务拉动:今天就有人撞上——duly 应用(duly#185)在 sys_user 加的 url 动作 18.2 显示、18.3 消失,属发版回归。
    ③ 防 AI 犯错:A 是可校验的显式声明(id 列表或开关二选一);D 让 AI 加的动作通过 os validate 却静默不画,最易犯错;B 的来源规则 AI 难以推断。
    ④ 创业阶段不扩散:A 新增一个永久键,但有实测拉动;D 不增键但保留静默丢弃;B 改面最大。
    Prior rulings read: page:header,record_header,whole set → 0 hits; none; thread: #11592; repo: objectstack-ai/objectstack

    席位推荐:A。 若 18.3.x 补丁不能带 minor:18.3.x 先发 D 的发布说明一行(明说已知限制和临时做法),A 进下一个 minor。A 涉及新 spec 键,裁定后按契约先行由 spec 车道起 spec 半边,本卡的 dev 线程(分支 claude/project-thread-4y2o5l)等裁决,可接 ui 与平台页半边。

    需要你做的: 在 A / B / D 中选一个(以及 18.3.x 是否先发 D 的说明)。

  3. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-support-ai · session_01WGufzh8VRbTbBnqwnrXsSL
    os-dev-report
    Stamp: 2026-11-03T17:48Z

    {
      "issue": 29951,
      "status": "needs_decision",
      "branch": "claude/project-thread-4y2o5l",
      "pr": null,
      "session": "session_01WGufzh8VRbTbBnqwnrXsSL",
      "premise_still_valid": true,
      "summary": "Reproduced on main 6a4737ab. A url action placed at record_header on sys_user by another package is served in GET /meta/object/sys_user but is drawn neither in the header row nor in its overflow menu, in the drawer or on the full page; the same action on showcase_account (CONTROL) is drawn in both. Cause is not a ui filter: 6dbff8e20a (#27219, Fixes #27053) rebuilt the platform page sys_user_detail from kind slotted (synthesized header, which reads the object's placed actions live) to kind full with a page:header naming the 11 platform action ids, and under the ruled page:header.actions contract (#11592, an authored list is the whole set) any action another package adds to sys_user is dropped. Same freeze on sys_organization_detail (4 ids) and sys_approval_request_detail (no ids). What #27219 was for, and must keep: the page owns its curated tab strip after slots.tabs retired. PM mechanism assumption falsified: no sys_ or url-type branch exists in the ui; the renderer follows the spec contract. Every fix touches that contract (a static page cannot name actions other packages add later), so this stops at a decision (os-dev, when to stop): options A to D are in the open question; the seat's analysis is comment 6611296943.",
      "tests": "No code change, so no pin and no ablation. Live: full pnpm build under os-verify-lock (VERDICT command-exit 0, 119/119 tasks), showcase backend pnpm dev --fresh on its own port, Console from ui src via vite with DEV_PROXY_TARGET. A writable package com.qa.hdr stores hdr_user_profile (url, record_header, objectName sys_user) and hdr_account_profile (url, record_header, objectName showcase_account). Served: /meta/object/sys_user lists hdr_user_profile; /meta/page/sys_user_detail is kind full and its header ids are ban_user, unban_user, unlock_user, set_user_password, impersonate_user, set_user_manager, update_my_profile, change_my_password, change_my_email, resend_verification_email, delete_my_account. Playwright readings: sys_user full page row = Update Profile, Ban User, Set Password, Edit, More actions; its menu = Refresh, Impersonate User, Set Manager, Change Password, Change Email, Add to favorites, Share, Delete My Account (QA User Profile absent). sys_user drawer: same row; menu = Impersonate User, Set Manager, Change Password, Change Email, Add to favorites, Share, Open as full page, Delete My Account (absent). showcase_account full page and drawer: row = QA Account Profile, Edit, More actions (present). Unit probe (throwaway, deleted): RecordDetailView with a sys_user def holding ban_user plus a url action at record_header draws Ban User, Edit only under a kind full default page naming ban_user, and Ban User, Open Profile, Edit with no page (the synthesized header the 18.2 slotted page drew); CONTROL non-system object with no page draws Open Profile. Page history: at 6dbff8e20a parent (and at 18.2.0 27f38ada) sys_user_detail is kind slotted with no page:header; at 6dbff8e20a it is kind full with the id list.",
      "gates": "NOT MEASURED: no diff, so no derived gate set and no changeset.",
      "dogfood_battery": "n/a: no PR.",
      "mcp_calls": "6, all reads: issue_read get 29951, issue_read get_comments 29951, issue_read get 29946, list_commits (RecordDetailView path), get_commit 27f38ada, list_commits (sys-user.page path). No MCP writes.",
      "api_writes": "1: this comment via post-stamped.mjs (POST issues/29951/comments).",
      "open_questions": [
        {
          "question": "How does a kind full platform record page draw header actions that other packages place on its object?",
          "options": [
            "A: additive page:header opt-in that draws every action of the bound object placed at record_header or record_more, in declaration order, read live; sys_user_detail, sys_organization_detail and sys_approval_request_detail use it instead of their frozen lists; an authored id list keeps meaning the whole set. Cost: one spec key, Metadata-protocol added, minor bump of the fixed group (not a patch); spec-key ripples, the ui reader in PageHeaderActions, three pages and their pins. Size M across spec, ui, platform-objects, plugin-approvals.",
            "B: amend the contract text, no key: an authored list is the whole set of the page package's own actions, and actions another package places on the object follow it. Needs served provenance: a stored action carries _packageId (measured), a code package's folded action carries objectName only (measured on showcase_task; a cross-package code action not measured), so a server stamp too. Changes every authored page; semantic change to a ruled contract. Size M to L across server, spec, ui.",
            "C (rejected): make sys_user_detail slotted again; the tabs slot is retired, so the curated strip #27219 kept would be lost.",
            "D: no code; declare the 18.3 behaviour and teach that a package adding a header action to a platform object ships an app-scoped record page (PageSchema.apps, #29631) naming it. Docs, skills and a release-notes line; the regression against 18.2 stays."
          ],
          "recommendation": "A, because it restores the 18.2 behaviour on the platform pages, keeps the strip #27219 was for and the #11592 meaning of an authored list, and is an explicit opt-in. If a patch release cannot carry a minor, D's release-notes line in 18.3.x and A in the next minor."
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: this card's ruling covers the same freeze on sys_organization_detail and sys_approval_request_detail · noted, not filed"
      ]
    }

    Generated by Claude Code

  4. os-support-ai commented on Nov 4, 2026

    @os-support-ai
    Collaborator

    decision thread · os-support-ai · session_01WGufzepGFmf3XtoZaZuheq

    Ruling: decision thread "Discuss pending spec rulings" · letter A, plus a 18.3.x release-notes line · maintainer 「以上同意」 2026-11-04T06:22:07Z

    The maintainer was presented the seat's "待维护者裁决" above (6611296943) in the project thread with A recommended, and the attached question whether 18.3.x first ships D's release-notes line with A in the next minor (recommended yes). They answered 「以上同意」 = the recommendation on every item presented, so this card's letter is A, with the release-notes line.

    What the ruling binds (letter A):

    Workload of the letter: M as the seat sized it: one spec key + ui read + three platform pages + approvals, each with its pin; plus one release-notes line in 18.3.x.

    Execution: the ui seat that filed the question dispatches the release-notes line now and the ui half after the spec half, with Ruling-ref: naming this comment; the spec half is filed to domain:spec citing this comment. The needs-user-decision → working-state stroke is the ui seat's. The Ruled: body line is written by this act.


    Generated by Claude Code

  5. os-support-ai commented on Nov 4, 2026

    @os-support-ai
    Collaborator

    decision thread · os-support-ai · session_01WGufzepGFmf3XtoZaZuheq

    Ruling amendment: letter A stands; the 18.3.x release-notes line is withdrawn · maintainer 「18.3.x 不发」「等后续发版的时候再写说明」 2026-11-04T06:24Z

    This amends ruling 6624172200 on one point only. The maintainer's words, verbatim: 「18.3.x 不发」 and 「等后续发版的时候再写说明」. So:

    • No 18.3.x patch carries anything for this card. The release-notes line that 6624172200 ordered into 18.3.x is withdrawn; nothing is dispatched for 18.3.x.
    • Letter A is unchanged: the spec opt-in on page:header, the three platform pages switched to it, spec half first then the ui half, Metadata-protocol: added, spec minor.
    • The release note is written when the release that carries A ships (the next minor), as part of that release's notes, not before.

    The body's Ruled: line is updated by this act to name both comments.


    Generated by Claude Code

  6. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-support-ai · session_01WGufzjDyeFwq6AuFu3vwTd

    Blocked-by: #30018

    Ruled 6624172200 (letter A) with the maintainer's amendment (「18.3.x 不发」「等后续发版的时候再写说明」, 2026-11-04T06:24Z): nothing ships in 18.3.x for this card, and the release note goes with the release that carries A. State: needs-user-decision → pm:blocked in this stroke. The spec half is filed as #30018 (domain:spec, p1, Ruling-ref: 6624172200). The ui half (the reader plus the three platform pages sys_user_detail, sys_organization_detail and sys_approval_request_detail, with the card's pin) stays with this seat and the card thread on claude/project-thread-4y2o5l, under Claim 6610580796. It is re-dispatched when #30018's PR merges. Assignee kept.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions