Skip to content

Setup: one page header and one list shell for sys_* lists, metadata-type pages and settings pages #12606

Closed

Description

@objectstack-fleet

Source

Walked on objectui main 8415d9f11, the Setup app at 1024 px and 1280 px. Four page shells sit side by side in one sidebar:

  1. sys_* record lists (Users, Teams, Invitations, Sharing Rules, Sessions, API Keys, Approval Requests, Audit Logs, Notification Preferences…): the console page header (icon, title, a kind chip such as "Identity" / "System-managed" / "Platform schema" / "Admin config", a one-line description) over the list chrome with view tabs, "N more", Filter / Sort / Display, the # column and an Actions column.
  2. Metadata-type pages (Positions, Capabilities, Permission Sets at /apps/setup/metadata/position?scope=environment and its siblings, packages/app-shell/src/views/metadata-admin/ResourceListPage.tsx): a breadcrumb "All Metadata Types › Position", the type name with chips (position · SECURITY · create-only), two stat tiles ITEMS 18 / FILTERED 18, a search box, an "All sources (18)" select, a NAME / LABEL / DESCRIPTION / ACTIVE / SOURCE table whose every row carries an "Artifact" chip, and New at the right.
  3. Settings pages (/apps/setup/system/settings/mail, storage, ai, knowledge, feature_flags): a page header, a "← All settings" link, section headings with a muted sentence, fields and toggles.
  4. Component pages (Packages, Packaged automation, Approvals Inbox, Audit Log Browser, Datasources, Connect an Agent, App Marketplace): each with its own header (some with a top-right pencil, some with Refresh in the header, some with none).

Positions and Users are two rows apart in the sidebar and share nothing but the sidebar.

Target

  1. One Setup page header for all four kinds: 32 px icon tile, 18 px / 600 title, the kind chip, a 13 px muted description, the primary action at the right (New / Invite / Register…), Refresh as an icon button where a page has it. The header the console pages already draw (objectui#12553) is the base.
  2. Metadata-type pages inside Setup drop the "All Metadata Types" breadcrumb and the ITEMS / FILTERED tiles; the count becomes "18 items" in the header's description line; the source select stays as a filter chip; the table takes the console list's row height and typography; the "Artifact" chip is a tooltip on the source column, not a chip per row.
  3. Record lists inside Setup drop the # row-number column and nothing else. The Display control and the view-tab strip stay as they are on every list: the strip already folds what its width does not hold into "N more" (objectui#12440), and Display holds the view's own presentation (group, hide fields, density, row numbers, export; a Layout row only when the object offers more than one), which an admin uses on Audit Logs and Approval Requests. No view-count gate. Maintainer ruling 2026-10-16, after the PM's read of the fold rule and of what Display holds, verbatim: 「可以」; the smaller icon-only form of Filter / Sort / Display for every list is objectui#12695.
  4. Settings pages keep their form but take the same header; "← All settings" becomes the breadcrumb's first crumb.

File surface

packages/app-shell/src/layout/PageHeader.tsx, packages/app-shell/src/views/metadata-admin/ResourceListPage.tsx (Setup posture), the settings hub pages under system/settings/* in packages/app-shell/src/console/, the Setup component pages under packages/app-shell/src/views/setup/ and apps/console/src/registerSystemComponents.tsx, tests beside each.

Acceptance

  1. Screenshots at 1280 px, light and dark, of Users, Positions, Mail Delivery and Packages: the title sits at the same x and y on all four; one header component in the tree.
  2. Tests: the metadata-type page under the Setup route renders no breadcrumb and no stat tiles; the record list under Setup renders no # column.
  3. pnpm --filter @object-ui/app-shell test green.

Constraints

  • The metadata-type page outside Setup (the Studio "Open in Setup" target and the directory) keeps today's shape; the change is a posture for the Setup route.
  • Existing data-testids stay.

Evidence

Screenshots on the temporary branch claude/console-home-login-design-20261016 of objectstack-ai/objectui (commit 01244b886, never merged): setup-positions-metadata-page.png · setup-invitations-empty.png · setup-packaged-automation.png.

Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-16 second review pass: objectui main 8415d9f11, HotCRM 63db83e2, the vite console on :5180 against objectstack serve --dev on :4001, the Studio pillars and all 43 Setup pages walked in the maintainer's browser pane at 1024 × 768 (en) with a 1280 × 900 re-check (zh). The maintainer asked for every finding to be filed, verbatim: 「全部立卡」.

Body refreshed 2026-10-16T13:53Z: Target 3 rewritten per the maintainer's 2026-10-16 ruling (no view-count gate on Display or "N more"; only the # column goes; icon-only toolbar is objectui#12695); the rest unchanged.

Activity

  1. added
    enhancementNew feature or request
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    and removed on Oct 16, 2026
  2. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 (priority:p2; the epic PM session's 2026-10-16 second review pass, 「全部立卡」)
    Session: session_01SJn1GEkrbbBQkhGC26wEDw
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12606-setup-page-header
    Worktree: objectui-issue-12606 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: packages/app-shell/src/layout/PageHeader.tsx, packages/app-shell/src/views/metadata-admin/ResourceListPage.tsx (a Setup-route posture only), apps/console/src/pages/settings/SettingsHub.tsx and SettingsView.tsx (the header and the "All settings" link only), the header row of each Setup component page (under packages/app-shell/src/views/setup/, packages/app-shell/src/console/ and apps/console/src/pages/system/, and apps/console/src/registerSystemComponents.tsx), the Setup posture of the sys_* record list (the # column and the list chrome), packages/i18n/src/locales/*.ts (new keys only), tests beside each, one .changeset/12606-*.md (stop on breach; explain in the report)
    Container & model: L, mode:cloud, model: opus (cloud on the maintainer's stance 「可以的话,ui 后续开发尽量用云 session,并且要求截图给我看」; lane scope on 「你也可以接ui车道的卡」; batch 5 on 「上限提到 5,提速」, this session's chat, 2026-10-15; slots refilled on the maintainer's 「补」, 2026-10-16)
    Clause-②: yes
    Clause-② reason: ConsolePageHeaderProps is exported from @object-ui/app-shell (as ConsolePageHeader), and one header for four page kinds very likely adds members (the kind chip, the primary action, Refresh). «拿不准 ⇒ 按 yes». The seat's TIER_DEFAULT review comes before ready.
    Responsibility: n/a — a design pass over shipped Setup pages
    Thread-read: none
    Serial constraints cleared: #12637 (objectui#12616, another seat) edits the Marketplace cards in MarketplacePage.tsx. This card touches only that page's header row, so they run in parallel by region and the later lander merges main. objectui#12610 (settings action rows) and objectui#12609 (packaged automation rows) are unclaimed and narrowed by triage to their rows. This card owns only the headers of those pages; the later lander merges main. objectui#12607 (empty states) is not in this surface.

  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12606,
      "status": "done",
      "branch": "claude/issue-12606-setup-page-header",
      "pr": 12662,
      "session": "session_01XvN7kN2b8z5CLTwmJJhhJF",
      "premise_still_valid": true,
      "summary": "ConsolePageHeader (packages/app-shell/src/layout/PageHeader.tsx) is extended once. It now has a Setup posture (32px tile, 18px/600 title, kind chip after the title, 13px muted description under the title, Refresh icon button, primary action at the right) and three new optional props: badge, breadcrumb and refresh. The header reads the posture from the route's :appName through a new useInSetupApp hook. Users, Positions, Mail Delivery and Packages all draw through this one component. Measured in the DOM with HotCRM, the title sits at x=324, y=68 on all four pages, at 1280 px light and dark and at 1024 px. Each page has exactly one header component and one h1. The metadata-type page under Setup has no breadcrumb and no Items/Filtered tiles, shows the count as '18 items', shows the source select as a chip, and shows the source as text with a tooltip; outside Setup it keeps its old shell. sys_* lists under Setup have no # column, and show Display only when the object has more than four views. Settings pages show 'All settings' as the first crumb. Packages, Packaged automation, Approvals Inbox, Audit Log Browser and Marketplace draw their title row through the same header. Mechanism assumptions measured: 1 true (settings live in apps/console/src/pages/settings and are routed at system/settings[/:namespace]). 2 true (no chip slot and no stacked posture before this change). 3 partly false: Approvals Inbox and Audit Log Browser already used ConsolePageHeader (objectui#12553); Packages, Packaged automation and Marketplace drew their own header; Datasources is the metadata:resource component, so it gets the ResourceListPage posture; Connect an Agent is an authored page:header node (see deviations). PM override: os-dev.md says the dev opens the PR and posts the report comment; I followed the dispatch's degraded channel instead (git push only, no PR, no comment), because this container's write relay answers 403.",
      "tests": "All runs at the final head 877cc8b (the merge of origin/main 8614705), from the repo root. (1) Full @object-ui/app-shell suite, `pnpm exec vitest run packages/app-shell/ --shard=K/8` for K=1..8, each in the foreground under os-verify-lock, every shard exit 0: Test Files 1449 passed, 1 skipped (1450); Tests 13671 passed, 9 skipped. The same 8 shards were also green at pre-merge 8cac811: 1440 files passed, 1 skipped; 13606 tests passed, 9 skipped. (2) `pnpm exec vitest run packages/plugin-list/ apps/console/src/pages/settings apps/console/src/pages/system apps/console/src/__tests__/AppContent.systemHubRoutes.test.tsx`: exit 0, 187 files, 1801 tests passed. New pins: PageHeader.setupPosture-12606 (4 tests: chip and primary action draw, description under the title, row-posture control), ResourceListPage.setupPosture-12606 (2 tests: under Setup no breadcrumb and no tiles; outside Setup both still draw), ObjectView.setupListChrome-12606 (4 tests: no row-number cell under setup and com.objectstack.setup, Display kept at more than four views, crm control), ListView.setupChrome-12606 (3 tests). SettingsView.pageHeader-12553 was updated because 'All settings' moved from the body into the header. Ablations, each run once with objectstack scripts/ablation-replace.mjs (mutation confirmed on disk, then restored: blob equals HEAD and `git diff HEAD` empty): A PageHeader `const setup = useInSetupApp();`→`false`: 3 failed, 1 passed. B ResourceListPage `if (inSetup) {`→`if (false) {`: 1 failed, 1 passed. C ObjectView `defaultRowNumbers={!inSetup}`→`{true}`: 3 failed, 1 passed. E ObjectView `showDisplayControl={...}`→`{true}`: 2 failed, 2 passed. D ListView `useState(defaultRowNumbers)`→`useState(true)`: 2 failed, 1 passed. G ListView `&& showDisplayControl &&` removed: 1 failed, 2 passed. F SettingsView `breadcrumb={`→`actions={`: 2 failed, 2 passed. Every ablation turned its pins red, as expected.",
      "gates": "All at 877cc8b, exit codes captured before any pipe. `pnpm --filter @object-ui/app-shell type-check` 0; `pnpm --filter @object-ui/plugin-list type-check` 0; `pnpm --filter @object-ui/console type-check` 0 (after building `@object-ui/console^...` under the lock, exit 0). Builds: `pnpm --filter @object-ui/plugin-list --filter @object-ui/app-shell build` 0 (at 8cac811; rebuilt at 877cc8b inside `@object-ui/console^...` build, exit 0); `pnpm --filter @object-ui/console build` 0. `pnpm exec eslint` on the changed .ts/.tsx files 0 (0 errors, 452 warnings, all from existing patterns in the large files). `pnpm check:i18n-keys` 0; `pnpm check:i18n-drift` 0; `pnpm check:i18n-designer-parity` 0 ('Every en row has a zh row'); `pnpm check:new-line-citations` 0; `node scripts/check-changeset-presence.mjs` 0 ('19 source file(s) of 3 released package(s) changed, and this change declares 1 changeset(s)'). Control-byte scan of changed files: no hits. Not run: check:i18n-dead-keys (no key retired); the repo-wide `pnpm lint` and full `pnpm test` belong to CI. There is no PR yet, so no CI check-runs to cite (NOT MEASURED: CI, reason: the PM opens the PR).",
      "mcp_calls": "9. claude-code-remote add_repo ×2 (read; both answered read_available, nothing attached); ToolSearch ×1; mcp__github__issue_read ×4 (get 12606, get_comments 12606, get 12553, get 12423); Read on PNGs is local. No GitHub write tool was used.",
      "api_writes": "0 REST writes. Git pushes only: claude/issue-12606-setup-page-header (empty branch, a0cd961, 8cac811, 877cc8b) and claude/issue-12606-evidence (d049687).",
      "pr_title_draft": "feat(app-shell): one page header for every Setup page — sys_* lists, metadata types, settings and component pages (objectui#12606)",
      "pr_body_draft": "(elided: it is the body of objectstack-ai/objectui#12662, opened from it verbatim by the seat)",
      "files_changed": [
        ".changeset/12606-setup-page-header.md",
        "packages/app-shell/src/console/setupApp.ts (new)",
        "packages/app-shell/src/console/ConsoleShell.tsx",
        "packages/app-shell/src/layout/PageHeader.tsx",
        "packages/app-shell/src/layout/__tests__/PageHeader.setupPosture-12606.test.tsx (new)",
        "packages/app-shell/src/views/ObjectView.tsx",
        "packages/app-shell/src/views/ObjectView.setupListChrome-12606.test.tsx (new)",
        "packages/app-shell/src/views/metadata-admin/ResourceListPage.tsx",
        "packages/app-shell/src/views/metadata-admin/ResourceListPage.setupPosture-12606.test.tsx (new)",
        "packages/app-shell/src/views/metadata-admin/PageShell.tsx",
        "packages/app-shell/src/views/metadata-admin/i18n.ts",
        "packages/app-shell/src/views/metadata-admin/PackagesPage.tsx",
        "packages/app-shell/src/views/setup/PackagedAutomationPage.tsx",
        "packages/app-shell/src/console/marketplace/MarketplacePage.tsx",
        "packages/plugin-list/src/ListView.tsx",
        "packages/plugin-list/src/__tests__/ListView.setupChrome-12606.test.tsx (new)",
        "apps/console/src/pages/settings/SettingsView.tsx",
        "apps/console/src/pages/settings/__tests__/SettingsView.pageHeader-12553.test.tsx",
        "apps/console/src/pages/system/ApprovalsInboxPage.tsx",
        "apps/console/src/pages/system/AuditLogPage.tsx"
      ],
      "screenshots": [
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-users-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-users-1280-dark.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-users-1024-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-positions-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-positions-1280-dark.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-positions-1024-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-mail-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-mail-1280-dark.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-packages-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/d049687f2d1e79953ecfb947450a0c6d31fef23b/docs/design/findings/12606/setup-packages-1280-dark.png?raw=true"
      ],
      "deviations": [
        "File surface: console/ConsoleShell.tsx (the two Setup constants moved to the new console/setupApp.ts and are re-exported, so the package root is unchanged), metadata-admin/PageShell.tsx (`export` added to WritabilityBadge), metadata-admin/i18n.ts (two engine keys, en and zh), plugin-list/src/ListView.tsx (the claim covers this region but does not name the file), metadata-admin/PackagesPage.tsx (where the Packages page lives).",
        "Connect an Agent is not converted. It is an authored `page:header` node (objectstack packages/mcp connect-ui.ts) drawn by packages/components, which is outside the file surface. No carrier exists for it.",
        "The full app-shell suite ran as 8 foreground `--shard=K/8` calls from the repo root (the same file set that `pnpm --filter @object-ui/app-shell test` runs). One unsharded call ran past the container's foreground limit, was moved to the background and was stopped there with no result.",
        "The screenshots were taken on the 8cac811 tree. The merge 877cc8b only brought in origin/main; its one conflict (an import line in PackagedAutomationPage) was resolved by keeping both icons.",
        "The merge commit 877cc8b has git's default message and no trailer pair (it is pushed and will not be rewritten).",
        "The shared /home/user/objectui checkout was left on a detached HEAD. It had been on a local claude/issue-12606-setup-page-header with no commits of its own; that local branch was deleted to create the worktree, as ordered. The worktree /home/user/objectui-issue-12606 is kept for the PM. Both dev servers I started (backend :4126, console :5226) are stopped."
      ],
      "line_budget": "n/a",
      "open_questions": [
        {
          "question": "How does a page know it is under Setup?",
          "options": [
            "A: the route's own `:appName` (setup or com.objectstack.setup), read by the header itself and once by ObjectView, which passes two ListView host props (the plugin cannot read the route)",
            "B: a new authored view key or object key",
            "C: a context provider threaded from AppContent"
          ],
          "recommendation": "A, chosen. Business need: the measured Setup URLs use both segments (/apps/setup and /apps/com.objectstack.setup), and A matches both. Long-term fit: one existing signal, and the posture stays a console posture, not metadata. AI-proofing: no authored key that an app could declare and the runtime then fail to honour. Startup scope: no new contract or provider. The two ListView props are React host props, like toolbarLeading."
        },
        {
          "question": "Does description-under-title apply everywhere, or only in Setup?",
          "options": [
            "A: Setup posture only; console pages elsewhere keep the objectui#12423 row",
            "B: change the header globally"
          ],
          "recommendation": "A, per the ruling. On the four axes: Setup is the only measured need; the posture lives inside the one header, so there is no second component; and it keeps the merged objectui#12423 design for object lists."
        },
        {
          "question": "What is the kind chip on a metadata-type page, which has no managedBy bucket?",
          "options": [
            "A: the existing WritabilityBadge (create-only / read-only / writable) in the header's badge slot",
            "B: invent a ManagedByBadge bucket for metadata types"
          ],
          "recommendation": "A, chosen. B would declare a bucket the spec does not define, which is contract drift. Under Setup the domain chip and the type code are no longer shown; outside Setup they still are."
        },
        {
          "question": "Where does the settings crumb sit, given that the title must keep the same x and y?",
          "options": [
            "A: the first item on the description line",
            "B: a row above the title (moves y, so acceptance 1 fails)"
          ],
          "recommendation": "A, chosen. The title stays at x=324, y=68 on all four pages."
        },
        {
          "question": "Hiding Display for lists with four views or fewer under Setup also hides Refresh and Export, which live in the Display footer (for example, Audit Logs' 'Use Export' hint becomes unreachable if that object has four views or fewer). Keep the ruling as written?",
          "options": [
            "A: keep the ruling (implemented)",
            "B: draw Display under Setup whenever the list offers Export"
          ],
          "recommendation": "A was implemented because the ruling cannot be reopened. This is flagged for the maintainer: B costs one condition and keeps Export reachable."
        }
      ],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · Connect an Agent's header is an authored `page:header` node drawn by packages/components, so it does not align with the Setup title. Noted, not filed. Not read: objectui#12607, #12609, #12610 and #12637 bodies. They are out of scope; only their header rows were in reach, and those were left alone except Marketplace's header row."
      ]
    }

    Relayed verbatim by the PM seat domain:ui#4 from the cloud session session_01XvN7kN2b8z5CLTwmJJhhJF (degraded channel: the container cannot write GitHub). Only pr was set and pr_body_draft elided.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Decision — Setup 列表隐藏 Display 时,刷新和导出一起消失 · 2026-10-16T13:11Z

    维护者速读: 本卡目标 3 要求:Setup 里的记录列表,只有对象声明了 4 个以上视图时才显示 Display 控件。PR #12662 照此实现了。但 Display 面板里同时装着「刷新」和「导出」,所以 Setup 里视图不超过 4 个的列表(会话、API Key、邀请、团队、审批请求、共享规则、Webhook 等)会同时失去刷新和导出。这是卡片没有预料到的副作用。席位推荐 B:刷新移到页头本 PR 新增的刷新位,能导出的列表保留 Display,其余照卡片隐藏。

    Background. PR #12662 (head 877cc8b; CI green except Live E2E (informational), which is objectui#12649) implements target 3 literally. In the compact toolbar the Display panel is the only home of Refresh and Export, and the Setup page header of a sys_* list receives no refresh prop. Measured on objectstack main b9dbc3d895 (count of listViews entries per object file): only sys_user (5), sys_business_unit (5), sys_audit_log (6) and sys_record_share (6) declare more than four. Four or fewer: sys_session (3), sys_api_key (4), sys_invitation (4), sys_team (2), sys_approval_request (4), sys_approval_action (3), sys_sharing_rule (4), sys_webhook (4), sys_oauth_application (4), sys_share_link (4), sys_setting (4), sys_notification (2), and every object with one view. The dev flagged this in its report (open_questions 5, on this card).

    Governing text.

    • This card, target 3: "the "Display" control and the "N more" view overflow stay only when the object declares more than four views".
    • This card, target 1: "Refresh as an icon button where a page has it".
    • AGENTS.md / ADR: none found (git grep -il 'display control\|showDisplayControl' f78efdd1e -- docs/adr → 0; control ListView → 2).

    Protocol: no packages/spec change, and no metadata key in any option. The posture stays a host prop.

    Premises, with re-check (the PR head is the subject; its hunk is recorded below):

    • git grep -n "showDisplayControl={!inSetup || views.length > 4}" 877cc8b29 -- packages/app-shell/src/views/ObjectView.tsx → 1 hit (control: toolbarLeading, 2 hits, same file).
    • git grep -n "toolbarFlags.compactToolbar && showDisplayControl" 877cc8b29 -- packages/plugin-list/src/ListView.tsx → 1 hit (control: Refresh and Export live in it, same file).
    • The hunk: ObjectView passes defaultRowNumbers={!inSetup} and showDisplayControl={!inSetup || views.length > 4}; ListView wraps the Display panel in {toolbarFlags.compactToolbar && showDisplayControl && (.
    选项 做什么 管理员看到什么 工作量
    A 保持现状,完全照卡片 视图 ≤4 的 Setup 列表没有刷新、导出、隐藏列、密度 无
    B Setup 下刷新进页头的刷新位(本 PR 已新增);列表提供导出时保留 Display;其余照卡片隐藏 每个 Setup 页的刷新都在页头同一位置(和 Positions 一致);能导出的照样导出;其余不常用的设置仍隐藏 domain:ui · PR #12662 上一轮修补 · 先例:同 PR 的 showDisplayControl 接线(ObjectView +2 行,ListView +18 行)
    C 取消 Display 隐藏规则,只去掉 # 列 工具条与 Setup 外一致,只少行号 domain:ui · PR #12662 上一轮修补(删属性和对应测试)· 先例同上

    业务含义:

    • A 等于把 Excel 的「刷新」和「另存为」藏掉:管理员在会话列表上看不到最新登录,审批请求导不出来。
    • B 等于只收起不常用的显示设置,刷新永远在页头同一个位置,能导出的列表照样导出。
    • C 等于 Setup 列表和普通列表一样,只是没有行号。

    四轴(业务立场):

    • 项目长远合理性(读数领起): B 让所有 Setup 页面共用一个页头刷新位:元数据类型页(如 Positions)今天已经用它,记录列表也接进来,形态统一。A 留下一个特例:元数据页能刷新,记录列表不能。C 没有特例,但放弃了卡片要的「收起管理员不用的工具」。两年后的管理后台应当是:刷新在固定位置,导出跟着数据走。微软 365 管理中心的用户列表就是这样,刷新和导出都是常驻入口。
    • 实际业务需求: 有实测拉动。HotCRM 种子里有 53 条待审批请求,审批请求列表只有 4 个视图。会话列表(3 个视图)是安全场景:查看和吊销在线会话需要刷新。
    • 防 AI 犯错: 三项都不新增元数据键。出错时谁看到什么:A 的问题是静默的,管理员只是找不到导出,没有任何报错;B 和 C 没有这个问题。
    • 创业阶段不扩散: C 删掉一个公开宿主属性(showDisplayControl),面最小;B 不加新属性,只改一个条件;A 什么都不改。

    推荐: B;回退: C。 置信缺口:席位没有逐个实测哪些 Setup 列表真的开启了导出(导出取决于列表的导出配置和权限),只确认了刷新一定在 Display 面板里。
    自检:只看①选 B;②③④ 是否翻转:④ 偏 C(少一个公开属性),不翻字母。

    os-decision-facets

    • ① 项目长远合理性:B 让所有 Setup 页共用页头刷新位,去掉「元数据页能刷新、记录列表不能」的特例;A 保留该特例。
    • ② 实际业务拉动:今天就有人撞上,审批请求(53 条待审)和会话列表都在 4 个视图以内,失去刷新和导出。
    • ③ 防 AI 犯错:三项都不加元数据键;A 的失败是静默的(找不到导出),B、C 无此问题。
    • ④ 创业阶段不扩散:C 删一个公开属性最省;B 只改一个条件不加属性;都不新增契约。

    Prior rulings read: "Display control" / "showDisplayControl" in docs/adr → 0 hits; this card's thread (claim 6211302311, the relayed report) → no ruling on Export; ADR none.

    After the ruling:

    • B: the seat sends a fix round on PR feat(app-shell): one page header for every Setup page — sys_* lists, metadata types, settings and component pages (objectui#12606) #12662 to the dev session (same branch, merge main, full app-shell suite; new pins: a Setup list with four or fewer views shows the header Refresh, and keeps Display when Export is offered). Then ACCEPT, the TIER_DEFAULT contract review at the final head, and landing.
    • C: the same fix round removes showDisplayControl and its pins; the rest is the same.
    • A: the seat ACCEPTs as is, lands it, and records the Refresh/Export loss in the landing note.
    • In every case this card goes back from needs-user-decision to pm:dispatched in the same write as the ruling record.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    席位意见(增量)· director seat (summon #43 continuation 2, session_01QJC7i981TSs9L1CGJK59Ax), read as batch #357 item 1, 2026-10-16T13:29Z

    On the domain:ui seat 4's decision 6216244614 (B recommended, C the fallback), raised from PR #12662's report (open_questions 5) while this card is in flight; the card left pm:dispatched for the box on this one question.

    Premises, read in this act. The seat's two greps are on the PR head 877cc8b29f (showDisplayControl={!inSetup || views.length > 4} in packages/app-shell/src/views/ObjectView.tsx; toolbarFlags.compactToolbar && showDisplayControl in packages/plugin-list/src/ListView.tsx); the director reads them from the seat's record, since neither line exists on origin/main f78efdd1e3 yet — the premise is about the PR. The view counts per sys_* object are the seat's reading of objectstack main b9dbc3d895. PR #12662 at this read: draft, +1,014/−263, 20 files, CI green except the informational Live E2E (objectui #12649).

    • Governing text: this card's targets 1 (Refresh as an icon button in the header 「where a page has it」) and 3 (Display only when the object declares more than four views). No ADR names the Display control (the seat's grep, 0 hits).

    Facets: ① agree — B puts every Setup page's Refresh in the one header slot the metadata-type pages already use, and keeps Export with the data; A leaves the special case 「metadata pages refresh, record lists cannot」; C gives up the card's own target 3 · ② agree — measured: approval requests (53 pending in the HotCRM seed) and the sessions list (a security list) sit at or under four views · ③ agree — A fails silently (an admin cannot find Export and nothing says why); B and C do not · ④ leans C (one public host prop fewer), as the seat says; it does not flip the letter, since B adds no prop and changes one condition.

    Recommend B; fallback C. Not A. 口径 for the executor, binding with the letter:

    1. Under Setup, a sys_* record list passes the header's refresh prop (the slot PR feat(app-shell): one page header for every Setup page — sys_* lists, metadata types, settings and component pages (objectui#12606) #12662 added), so Refresh sits where Positions has it; the Display panel stays when the list offers Export and is hidden otherwise per target 3; above four views nothing changes.
    2. Which lists offer Export is measured in the fix round (the seat's confidence gap), not assumed: the condition reads the list's export capability, never a hard-coded object list.
    3. Pins: a Setup list with four or fewer views shows the header Refresh; one that offers Export keeps Display; one with no Export and four or fewer views hides Display; outside Setup nothing changes.
    4. One fix round on PR feat(app-shell): one page header for every Setup page — sys_* lists, metadata types, settings and component pages (objectui#12606) #12662 (same branch, main merged, the full app-shell suite), then ACCEPT, the TIER_DEFAULT review at the final head, and the landing; Clause-②: yes stays as the claim says (the exported header props grew).

    Workload: B = domain:ui · one fix round on PR #12662 (precedent: the same PR's showDisplayControl wiring, about 20 lines). C = the same round, deleting the prop and its pins. A = none.

    os-decision-facets

    • ① 项目长远合理性:同意 —— B 让所有 Setup 页共用页头刷新位、导出跟着数据走;A 留「元数据页能刷新、记录列表不能」的特例;C 放弃卡片目标 3。
    • ② 实际业务拉动:同意 —— 审批请求(53 条待审)与会话列表都在 4 个视图以内,今天就失去刷新与导出。
    • ③ 防 AI 犯错:同意 —— A 的失败是静默的;B、C 无此问题。
    • ④ 创业阶段不扩散:④ 偏 C(少一个公开属性),不翻字母;B 只改一个条件、不加属性。

    自检:只看①选 B;②③④ 是否翻转:否(④ 偏 C,不足以翻)。

  6. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling on decision 6216244614 — option C · recorded 2026-10-16T13:53Z

    Who, where, verbatim. The maintainer, in the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff (direct chat, 2026-10-16), asked about this card's target 3:

    看一下这个问题:12606只在对象声明 4 个以上视图时才显示 Display 控件, 这个有必要吗?或者 Display 控件 可以缩小为显示图标?

    The PM's read, given in that chat: the "N more" fold is already width-driven (objectui#12440's test: the strip folds what its width does not hold), so a view-count gate is a second rule fighting the first; Display holds the view's own presentation (group, hide fields, density, row numbers, Refresh and Export; a Layout row only when the object offers more than one), which an admin uses on Audit Logs and Approval Requests, so the premise "list chrome an admin does not use here" was the PM's error when the card was written. The PM proposed: target 3 keeps only the # column removal, no gate on Display or "N more"; and a separate card makes Filter / Sort / Display icon-only together on every list. The maintainer's reply, verbatim:

    可以

    Ruling: C — the Display hide rule is withdrawn; a Setup record list drops only the # row-number column. Not A, not B.

    口径 for the executor (domain:ui seat 4, PR #12662):

    1. Remove showDisplayControl (ObjectView's !inSetup || views.length > 4 and ListView's toolbarFlags.compactToolbar && showDisplayControl wrap) and its pins; the Display panel renders on every list as before the PR. defaultRowNumbers={!inSetup} stays (that is the # column rule).
    2. The header Refresh slot the PR added stays as target 1 says ("Refresh as an icon button where a page has it"); nothing moves out of the Display panel.
    3. One fix round on PR feat(app-shell): one page header for every Setup page — sys_* lists, metadata types, settings and component pages (objectui#12606) #12662 (same branch, main merged, the full app-shell suite), then ACCEPT, the TIER_DEFAULT review at the final head, and the landing, as the decision comment's "After the ruling: C" line sets out.
    4. The icon-only form of Filter / Sort / Display for every list is List toolbar: Filter, Sort and Display as icon buttons with count badges, one shape on every list #12695 (filed 2026-10-16, pm:queue); it is not part of this PR.

    The card body's target 3 is refreshed in the same act (the "Body refreshed" line at its foot); this card returns from needs-user-decision to pm:dispatched in the same write.

  7. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12606,
      "status": "done",
      "branch": "claude/issue-12606-setup-page-header",
      "pr": 12662,
      "session": "session_01XvN7kN2b8z5CLTwmJJhhJF",
      "premise_still_valid": true,
      "summary": "Fix round on PR #12662 for ruling C (comment 6217025861 on objectui#12606, read in full before the first edit). I removed `showDisplayControl` completely: the ListView prop and its docblock, the wrap on the Display panel (now `toolbarFlags.compactToolbar && (` as on main), ObjectView's `!inSetup || views.length > 4` and its `views.length` dependency, and every pin that asserted it. The Display panel renders on every list again, under Setup too. Three things stay. `defaultRowNumbers={!inSetup}` keeps the `#` column off under Setup. The header `refresh` slot stays, with the pages that already pass it. Nothing moved out of the Display panel, and the sys_* list gets no header Refresh. The changeset no longer mentions the Display rule. I merged origin/main 023087f (no conflicts). That merge brought a 48px app bar, so every title now sits at y=60, still identical on Users, Positions, Mail Delivery and Packages. New screenshot: Sessions under Setup (3 views, 3 rows) shows Display and no `#` column.",
      "tests": "At head 4803770, from the repo root. (1) Full @object-ui/app-shell suite as 8 foreground shards, `pnpm exec vitest run packages/app-shell/ --shard=K/8` under os-verify-lock. Every shard exited 0. Test Files: 1458 passed, 1 skipped (1459). Tests: 13740 passed, 9 skipped. (2) `pnpm exec vitest run packages/plugin-list/`: exit 0, 141 files, 1464 tests passed. (3) `pnpm exec vitest run apps/console/src/pages/settings apps/console/src/pages/system apps/console/src/__tests__/AppContent.systemHubRoutes.test.tsx`: exit 0, 47 files, 339 tests passed. Changed pins: ObjectView.setupListChrome-12606 now has 3 cases: no `#` column and Display present under setup and under com.objectstack.setup, plus the crm control. The case 'keeps Display at more than four views' was removed. ListView.setupChrome-12606 now has 2 cases: defaultRowNumbers=false gives no row numbers, Display drawn and no count chip; plus the control. The `showDisplayControl` case was removed. Ablations, once each, run with objectstack scripts/ablation-replace.mjs. Each mutation was confirmed on disk and restored: blob == HEAD and `git diff HEAD` empty. H: ObjectView `defaultRowNumbers={!inSetup}`→`{true}` gave 2 failed, 1 passed. I: ListView `useState(defaultRowNumbers)`→`useState(true)` gave 1 failed, 1 passed. J: ListView Display wrap `{toolbarFlags.compactToolbar && (`→`&& false && (` gave 5 failed (5) across both pin files. That also shows the ObjectView pin reads plugin-list source. All three ablations turned red, as expected.",
      "gates": "At 4803770. Exit codes were captured before any pipe. `pnpm --filter @object-ui/app-shell type-check` 0. `pnpm --filter @object-ui/plugin-list type-check` 0. `pnpm --filter @object-ui/console type-check` 0. `pnpm --filter '@object-ui/console^...' build` (includes plugin-list and app-shell) 0. `pnpm --filter @object-ui/console build` 0. `pnpm exec eslint` on the branch's changed .ts/.tsx files 0 (0 errors; the 452 warnings are pre-existing patterns). `node scripts/check-changeset-presence.mjs` 0 ('19 source file(s) of 3 released package(s) changed, and this change declares 1 changeset(s)'). `pnpm check:i18n-keys` 0. `pnpm check:i18n-designer-parity` 0. `pnpm check:new-line-citations` 0. CI check-runs on PR #12662 for the new head were not read (NOT MEASURED: CI, reason: report delivered at end of local verification).",
      "mcp_calls": "This round: 1. mcp__github__issue_read get_comments 12606, to read ruling 6217025861. ReadNotifications ×1 is not GitHub. No GitHub write tool was used.",
      "api_writes": "0 REST writes. Git pushes only: claude/issue-12606-setup-page-header (e89a40e, merge 4803770) and claude/issue-12606-evidence (66df45d).",
      "pr_title_draft": "feat(app-shell): one page header for every Setup page — sys_* lists, metadata types, settings and component pages (objectui#12606)",
      "pr_body_draft": "(elided: it is the revised body of objectstack-ai/objectui#12662; the seat replaced the PR body with it verbatim)",
      "files_changed": [
        "this round: packages/plugin-list/src/ListView.tsx",
        "this round: packages/plugin-list/src/__tests__/ListView.setupChrome-12606.test.tsx",
        "this round: packages/app-shell/src/views/ObjectView.tsx",
        "this round: packages/app-shell/src/views/ObjectView.setupListChrome-12606.test.tsx",
        "this round: .changeset/12606-setup-page-header.md",
        "branch total: the same 20 files as round 1 (no file added or removed)"
      ],
      "screenshots": [
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-sessions-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-users-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-users-1280-dark.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-users-1024-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-positions-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-positions-1280-dark.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-positions-1024-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-mail-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-mail-1280-dark.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-packages-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/66df45dd0301e35d429aff89442b82da4c164759/docs/design/findings/12606/round2-4803770/setup-packages-1280-dark.png?raw=true"
      ],
      "deviations": [
        "The order asked for one new screenshot. Because main's app bar changed from 56px to 48px (a merged origin/main change), every title moved from y=68 to y=60. I therefore also recaptured the ten acceptance shots on the new head, so the x/y evidence matches 4803770. They are under round2-4803770/ on the evidence branch. The round-1 shots at d049687 stay as history.",
        "I used Sessions (3 views, 3 seeded rows) for the new shot instead of Teams. Teams is empty in a fresh HotCRM, so its 'no # column' would hold trivially.",
        "The full app-shell suite again ran as 8 foreground shards. The container stops a single foreground run at about 10 minutes.",
        "Merge commit 4803770 has git's default message and no trailer pair.",
        "Both dev servers started this round (:4126, :5226) are stopped. The worktree /home/user/objectui-issue-12606 is kept."
      ],
      "line_budget": "n/a",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · Connect an Agent's header is an authored `page:header` node drawn by packages/components, so its title does not align with the other Setup titles. Noted, not filed (unchanged from round 1)."
      ]
    }

    Relayed by seat domain:ui#4 (session_01SJn1GEkrbbBQkhGC26wEDw) from the cloud session's final message: the fix round on PR #12662 for ruling C (6217025861). The seat replaced the PR body with the revised pr_body_draft.


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #12662 merged as c41ce3f on main · read 2026-10-16T16:06Z

    probe on origin/main c41ce3f reading control
    useInSetupApp in packages/app-shell/src/layout/PageHeader.tsx 3 mentions the Setup posture, read off the route
    badge? / breadcrumb? / refresh? on ConsolePageHeaderProps 3 members the one header, extended once
    showDisplayControl under packages/ 0 ruling C (6217025861): Display stays on every list
    defaultRowNumbers={!inSetup} in packages/app-shell/src/views/ObjectView.tsx 1 no # column under Setup
    packages/app-shell/src/console/setupApp.ts present the Setup identity, re-exported unchanged from the package root
    *12606* test files 4 the header, metadata-page, list-chrome and ListView pins
    .changeset/12606-setup-page-header.md present —

    State change: the card closed as completed through Fixes #12606, and pm:dispatched is removed in this act. The cloud session session_01XvN7kN2b8z5CLTwmJJhhJF is archived. The contract review of record is TIER_DEFAULT PASS at 4803770 (6219257725).

    Unblocked by this landing: objectui#12705 (the Setup header at 1024 px) and objectui#12695 (the icon-only Filter / Sort / Display) can now build on this header and list chrome. Not filed: Connect an Agent's authored page:header does not take the Setup posture (no carrier, as the dev reported).


    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

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions