Skip to content

List views: readers can hide and show columns by default — flip the userActions.hideFields default, so a generated app has the control without having to declare it #28912

Closed

Description

@objectstack-fleet

epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff

Filed by the record-page epic seat from a second console review under epic #26676. An independent reviewer walked the console on main bdb19ca6d9, with examples/app-crm as the backend, at 1440 and 390 px. The seat then re-read the evidence. The maintainer approved the seat's checked list: 「Fable 评估(核对后) 同意立卡」 (2026-11-02). Code readings below are on main 5e1b9b0a77. No domain:* label is set: triage routes this card.

Observed

The list's Display menu offers open mode, grouping, density, row numbers and inline edit. Nothing there or on a column header hides a column. A reader cannot remove a column they do not need, and examples/app-crm and generated apps do not turn the control on.

Reading

  • ui/packages/plugin-list/src/ListView.tsx:1847: showHideFields: ua?.hideFields === true.
  • packages/spec/src/ui/view.zod.ts:1921: hideFields defaults to false.
  • The comment at view.zod.ts:1882-1888 records this as copied from the renderer's legacy reads, not as a product choice.

The seat recommended flipping the default, and the maintainer's approval above is that decision.

Target

  1. hideFields defaults on in the schema and in the renderer: ua?.hideFields !== false. An app can still set false.
  2. No new key.
  3. Record the changed default the way packages/spec/scripts/lib/default-changes.ts requires, and update the comment at view.zod.ts:1882-1888.

Premise to verify first

The control that hideFields: true draws today works end to end: it hides a column, and on a view that stores the choice (see the acceptance below), the choice survives a reload. If it does not, report that first. Flipping the default would otherwise put a broken control on every list.

Acceptance

  • A view that does not declare hideFields offers the control.
  • A view that declares false does not.
  • On a view that declares columns, or a saved view, a hidden column stays hidden after a reload, for that reader only.
  • On a system view that declares no columns, hiding lasts for the session only, under the objectui#10694 ruling (persistHiddenFields, ui/packages/app-shell/src/views/objectViewListRenderer.tsx, around line 373). This card does not change that.
  • The spec default, the renderer read and the default-change record agree.

Acceptance narrowed by the epic seat. The maintainer: 「把「恢复默认清除偏好」、「账号偏好字段校验」、「个性化标记与统一重置」立卡,并收窄 #28912 的验收。」 (2026-11-02). The earlier text said every hidden column survives a reload, which the seat had read too widely.

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff

    Ruling confirmed · 2026-11-02T04:13Z. The seat asked the maintainer to confirm that the approval quoted in the body was a decision on this card's product question. The maintainer: 「#28911 和 #28912 都保留,按卡上写的做。」 The Target stands as written.

  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: priority:p2 · domain:spec · pm:queue · 2026-11-02T05:10Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Claim: PM loop round 1 · 2026-11-02T05:20Z
    Session: session_01ADHkmPi25XXKx92Xmg4viS (seat); dev = card thread session_01ADHkmRSwH9oAqN1JrZZVoR
    Account: os-steve
    Branch: claude/project-thread-fnij1c
    Worktree: the card thread's own checkout of objectstack-ai/objectstack
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/spec/src/ui/view.zod.ts (the userActions.hideFields default, its describe and the ≈L1882–1888 comment) and its tests; packages/spec/scripts/lib/default-changes.ts (the record); ui/packages/plugin-list/src/ListView.tsx (the showHideFields read and its comment) and plugin-list / app-shell tests that pin the default or prove the premise; regenerated content/docs/references/**; root .changeset/; not persistHiddenFields in objectViewListRenderer.tsx, not the record-details hideFields (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (a changed default) before landing, effort: high
    Clause-②: yes (widening)
    Metadata-protocol: semantic
    Responsibility: n/a — not a defect card
    Thread-read: 6569585145
    Premise: unverified — the card's premise check (the control hideFields: true draws hides a column and, on a view with columns or a saved view, survives a reload) runs first; on FAIL the dev stops at needs_decision
    Serial constraints cleared: none (the seat's other in-flight cards #28864, #28934, #28914, #28912, #28896 hold disjoint files)

    Ruling-ref: maintainer 「Fable 评估(核对后) 同意立卡」 and 「#28911 和 #28912 都保留,按卡上写的做。」 (6568880403). No new key.

    Amended: the file surface adds a new semantic migration entry packages/spec/src/migrations/entries/semantic/18.list-view-hide-fields-default-on.ts (and the template or registry inputs it needs; the generated registry.ts is not edited), following the editInline, pageSize and nav-group precedents. It also adds the stale "hideFields default OFF" comment in ui/packages/core/src/**/normalize-list-view.ts (≈L400, comment only). These are the dev's open questions in report 6571189003; the seat takes option A on both. No other in-flight claim holds either file.

  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmRSwH9oAqN1JrZZVoR
    os-dev-report

    {
      "issue": 28912,
      "status": "done",
      "branch": "claude/project-thread-fnij1c",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29083",
      "session": "session_01ADHkmRSwH9oAqN1JrZZVoR",
      "premise_still_valid": true,
      "summary": "Premise PASS first: on main 135054eb with ListView.tsx at main's === true read, ObjectView.emptyColumnsNoProjection-10694 + ObjectView.userListState-12418 ran 43/43 green; they drive the real Display popover Hide Fields checkbox: the column goes, on a view with columns and on a saved view the choice is stored on the user's own list state and survives a remount, on a system view with no columns it is session-only. Then: UserActionsConfigSchema.hideFields default(false) to default(true) with describe and block comment; ListView showHideFields reads ua?.hideFields !== false; ledger row ui/UserActionsConfig:hideFields false to true in default-changes.ts (check:authorable-surface accepts it, the build prints the reason); references + authorable-defaults/ui.json regenerated; changeset spec + plugin-list minor. Interface pages keep their own closed-by-default read (InterfaceListPage, out of surface), and the ledger reason and changeset say so.",
      "tests": "head d9c8c4e8 (5e51cfd4 later rewords only the ledger reason and the changeset): spec test VERDICT exit 0, Test Files 789 passed, Tests 23328 passed 1 todo; cd ui vitest packages/plugin-list VERDICT exit 0, 179 files 1729 tests passed. head 5e51cfd4: 34 app-shell files that read hideFields/hiddenFields/userActions VERDICT exit 0, 34 files 344 tests passed; full app-shell (2065 files) stopped after 64 min locally, left to CI Test UI. spec typecheck exit 0. Forced edits: view.test.ts default-values hideFields true; view.test.ts asymmetry pin renamed and expects true; ListView.test.tsx legacy show* fold test now pins showHideFields false. New: view.test.ts hideFields defaults ON (3 cases), ListView.test.tsx omit to drawn / false to absent. Ablation: not run (one-operator flip pinned by the new absent/false pair on both sides).",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 5e51cfd4: 108 commands, all exit 0; --ran: 108 derived, 108 run, 0 NOT-MEASURED, 0 UNRUN. check:generated 14/14 after gen:docs. check-changeset-no-major --event on the PR body exit 0 (LEVEL AXIS yes (widening) + semantic). check-empty-changeset exit 0, check-adr-0087-registration exit 0 (non-breaking). plugin-list type-check NOT MEASURED locally, reason: ui package closure unbuilt (TS2307 on @object-ui/components); CI Type Check UI carries it. CI check-runs: in_progress at report time.",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "5 — issue_read x4 (get, get_comments x3), pull_request_read get x1; no write tools",
      "api_writes": "2 — relay pr_create (#29083, run 41403642138, 6387 bytes sent = stored), relay comment os-dev-report on #28912 (this comment)",
      "files_changed": [
        ".changeset/28912-hide-fields-default-on.md",
        "content/docs/references/ui/page.mdx",
        "content/docs/references/ui/view.mdx",
        "packages/spec/authorable-defaults/ui.json",
        "packages/spec/scripts/lib/default-changes.ts",
        "packages/spec/src/ui/view.test.ts",
        "packages/spec/src/ui/view.zod.ts",
        "ui/packages/plugin-list/src/ListView.tsx",
        "ui/packages/plugin-list/src/__tests__/ListView.test.tsx"
      ],
      "line_budget": "+151 / -28 over 9 files, no governed path",
      "deviations": [
        "Local app-shell run narrowed to the 34 files that read hideFields/hiddenFields/userActions (the delta's ObjectView / list renderer tests); the full 2065-file suite is left to CI Test UI.",
        "plugin-list type-check not measured locally (unbuilt ui closure)."
      ],
      "open_questions": [
        {
          "question": "Add an ADR-0087 D3 semantic migration entry (18.list-view-hide-fields-default-on) so os migrate meta and the upgrade guide carry the flip? default-changes.ts says a flip that warrants a TODO should get one, and editInline, pageSize and nav-group expanded each did. It is outside the claimed file surface, so it was not added.",
          "options": [
            "A: seat amends the claim to add packages/spec/src/migrations/entries/semantic/18.list-view-hide-fields-default-on.ts; one more commit and a spec test round",
            "B: no entry: the flip only adds a control whose effect is per-reader and never writes the shared view, so no upgrade TODO is owed"
          ],
          "recommendation": "A, because the three earlier UI default flips all carry one and the upgrade guide is where an author who wanted columns fixed would look"
        },
        {
          "question": "ui/packages/core/src/utils/normalize-list-view.ts around L400 still says hideFields/rowColor default OFF in a comment. Fix it here?",
          "options": [
            "A: seat amends the surface; one-line comment fix in this PR",
            "B: leave it for a later ui card"
          ],
          "recommendation": "A, because it is a stale statement about the exact default this PR changes"
        },
        {
          "question": "Claim lines: does Clause-②: yes (widening) + Metadata-protocol: semantic fit a default flip?",
          "options": [
            "A: keep as claimed",
            "B: other"
          ],
          "recommendation": "A: check-changeset-no-major --event reads both lines and grades the level axis green; semantic matches AGENTS (a changed default is semantic)"
        }
      ],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed: InterfaceListPage keeps hideFields === true while the spec default is now true for interfaceConfig.userActions too; the same pre-existing pattern as filter/rowHeight/group (interface mode closed by default by design), disclosed in the ledger reason and changeset"
      ]
    }

    Stamped 2026-11-02T07:03Z.


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmRSwH9oAqN1JrZZVoR
    os-dev-report

    {
      "issue": 28912,
      "status": "done",
      "branch": "claude/project-thread-fnij1c",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29083",
      "session": "session_01ADHkmRSwH9oAqN1JrZZVoR",
      "premise_still_valid": true,
      "summary": "Round 2 on the amended claim (seat took A/A). Added the D3 semantic entry 18.list-view-hide-fields-default-on (modelled on list-view-edit-inline-default-on / view-pagination-page-size-default-50; no D2 conversion, no tombstone; registry.ts.template unchanged, step 18 needs no rationale fragment for a default flip, as for both models). The ledger row, the view.zod.ts comment and the changeset Upgrade path line name it. Fixed the stale hideFields default OFF comment in ui core normalize-list-view.ts (comment only). Round 1 had not run ui core: its foldOutputAuthorable-5435 polarity pin reddened on the flip (the pin exists to do that), and is updated as a forced edit. Round 1 (premise PASS 43/43 on main, the flip itself) stands.",
      "tests": "Round 2. 94456732: spec build exit 0 (prints the ledger row naming the D3 entry); check:generated 14/14; spec test VERDICT exit 0, 789 files, 23328 passed 1 todo. 5e1742ee: cd ui vitest packages/core packages/types VERDICT exit 0, 614 files, 14682 passed 27 skipped (before the test edit: 1 failed, the 5435 polarity pin, expected true to be false); 32 other ui test files naming userActions/UserActionsConfig VERDICT exit 0, 742 passed. Round 1 readings unchanged: plugin-list 1729 at d9c8c4e8, app-shell 34-file set 344 at 5e51cfd4; plugin-list and app-shell sources did not move since. Forced edits now 4: view.test.ts x2, ListView.test.tsx legacy fold, normalize-list-view.foldOutputAuthorable-5435.test.ts polarity pin.",
      "gates": "dispatch-gates at 5e1742ee: 110 commands (round 1's 108 + check:spec-changes + check:upgrade-guide), all exit 0; --ran: 110 derived, 110 run, 0 NOT-MEASURED, 0 UNRUN. check-changeset-no-major --event on the round-2 body exit 0; check-empty-changeset exit 0; check-adr-0087-registration exit 0 (non-breaking). plugin-list type-check still NOT MEASURED locally (unbuilt ui closure). CI check-runs: not read at report time.",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "5 — unchanged since round 1 (issue_read x4, pull_request_read get x1); no write tools",
      "api_writes": "3 total — relay pr_create #29083, relay comment 6571189003 (round 1 report), relay comment on #28912 (this round-2 report). PR body NOT patched: os-dev.md says the dev writes the PR body once and the seat writes later edits; the round-2 body is in the project files at spec-seat1/29083-pr-body-r2.md for the seat to apply.",
      "files_changed": [
        ".changeset/28912-hide-fields-default-on.md",
        "content/docs/references/ui/page.mdx",
        "content/docs/references/ui/view.mdx",
        "packages/spec/authorable-defaults/ui.json",
        "packages/spec/scripts/lib/default-changes.ts",
        "packages/spec/src/migrations/entries/semantic/18.list-view-hide-fields-default-on.ts",
        "packages/spec/src/ui/view.test.ts",
        "packages/spec/src/ui/view.zod.ts",
        "ui/packages/core/src/utils/__tests__/normalize-list-view.foldOutputAuthorable-5435.test.ts",
        "ui/packages/core/src/utils/normalize-list-view.ts",
        "ui/packages/plugin-list/src/ListView.tsx",
        "ui/packages/plugin-list/src/__tests__/ListView.test.tsx"
      ],
      "line_budget": "see the PR diff at 5e1742ee; 12 files, no governed path",
      "deviations": [
        "Local app-shell run narrowed to the 34 files that read hideFields/hiddenFields/userActions (the delta's ObjectView / list renderer tests); the full 2065-file suite is left to CI Test UI.",
        "plugin-list type-check not measured locally (unbuilt ui closure).",
        "ui core test normalize-list-view.foldOutputAuthorable-5435.test.ts edited: it is not named in the amended surface but pins the old default in the package whose comment the amendment added; the same class as the claimed forced edits, and leaving it would red Test UI.",
        "PR body not patched by the dev (os-dev.md one-write rule wins over the standard order's issue_patch line); the seat applies spec-seat1/29083-pr-body-r2.md."
      ],
      "open_questions": [
        {
          "question": "The standard order allows issue_patch on your own PR body; os-dev.md says the dev writes it once and the seat writes later edits. Which binds for round-2 bodies?",
          "options": [
            "A: os-dev.md (seat applies the prepared body)",
            "B: the standard order (dev patches with a signature line)"
          ],
          "recommendation": "A, because os-dev.md binds over the order and the relay's signed-edit rule would force a signature line above Fixes #28912"
        }
      ],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed: InterfaceListPage keeps hideFields === true while the spec default is now true for interfaceConfig.userActions too; the same pre-existing pattern as filter/rowHeight/group (interface mode closed by default by design), disclosed in the ledger reason and changeset"
      ]
    }

    Stamped 2026-11-02T07:52Z.


    Generated by Claude Code

  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Landed · 2026-11-02T09:34Z

    Probe Reading
    PR #29083 MERGED 2026-11-02T09:27Z, merge commit 104cd1a58d, through the merge queue
    #28912 closed completed by Fixes #28912

    pm:dispatched is removed. Seat record on PR #29083: ACCEPT 6571977447. Contract review: PASS 6572308637. Landing note 6572352290. userActions.hideFields now defaults to true: list views draw Hide Fields unless an app writes hideFields: false. The D3 semantic entry is 18.list-view-hide-fields-default-on. The interface-page === true toggles are in finding #29144, and the PR-body process gap is in #29145. view.zod.ts is free for the next card (#29012 is in flight; #29037 follows it).

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:specenhancementNew feature or requestpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions