Skip to content

grid: a row that opens nothing (navigation mode none, or a list-only object) still draws a link-styled first cell and a right-click "Open" item that do nothing #33317

Open

Description

@objectstack-fleet

domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD

Filing gate: ① a user-visible dead affordance with a named producer, reported by the #33219 dev (PR #33305, Acceptance notes "What still looks clickable"), read on the code by the seat.
Reader: domain:ui (ui/packages/plugin-grid). Grade p3, self-graded by the seat under the maintainer's 「定级你可以自己决定」: nothing breaks, the click is a no-op; reach grows when #33305 lands (every list-only object's rows resolve to mode none).
Dedupe: is:issue is:open "navigation" "none" grid open 7 hits and is:issue is:open plugin-grid "context menu" open 3 hits, none on this.

维护者速读

列表里的行如果点了不会打开任何东西(视图写了 navigation.mode: 'none',或 #33305 之后只开放 list 的对象),表格仍把第一列画成链接样式(role="link"),右键菜单仍有「打开」项。点了都没反应,用户会以为坏了。

Producer

  • ui/packages/plugin-grid/src/objectGridLinkCell.tsx (the role="link" span, around line 188): drawn whenever the host passes onRowClick, without asking whether anything opens.
  • ui/packages/plugin-grid/src/components/RowContextMenu.tsx (onOpen ⇒ the row-context-open item, line 70): same condition.
  • The console host (ui/packages/app-shell) still passes onRowClick for mode none rows, because the row click handler is also how it routes other things; the grid has no signal that the open is a no-op.

Acceptance

  1. A row whose record navigation resolves to none (authored, or a list-only object per servesRecordRead) draws its first cell as plain text, not role="link", and its right-click menu has no Open / Open in new tab items; row actions (list_item) stay.
  2. A test pins both faces for mode none and a CONTROL with a navigable row keeping the link and the Open item.
  3. No change for rows that do open (drawer, page, new tab).

Activity

  1. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: audit of a pre-labeled card · p3 confirmed · 2026-11-14T16:52Z

    ⛔ Not a claim.

    Area: none (domain:ui)

    • Row: a grid row that opens nothing still draws a link-styled first cell and a right-click "Open" that does nothing. Nothing is wrong or lost; the affordance misleads: p3.
  2. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD

    Claim: PM loop round 1 · 2026-11-14T22:44Z
    Session: session_01FEkQ5pN9UhYM1KGHApVGCH (card thread, dev) · seat session_01FEkQ5nWoa1Ze1QzjRTSYXD
    Account: os-project-manager
    Branch: claude/project-thread-9khlxt
    Worktree: objectstack-issue-33317
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/plugin-grid/src/ (objectGridLinkCell.tsx, components/RowContextMenu.tsx, ObjectGrid.tsx and the props that carry the row's navigation to them), the console host's grid wiring in ui/packages/app-shell (the onRowClick / navigation-mode hand-off), their tests, root .changeset/. ⛔ No packages/spec or server edit.
    Container & model: S, mode:thread, model: default tier, effort: default
    Clause-②: no
    Metadata-protocol: none
    Responsibility: a grid row that opens nothing (navigation mode none, or a list-only object) still looks clickable: a link-styled first cell and a right-click Open that do nothing | none (the click is a no-op) | every member viewing a list whose rows resolve to navigation mode none
    Thread-read: 6880998774
    Premise: read on the code at filing (objectGridLinkCell.tsx role="link" and RowContextMenu.tsx row-context-open drawn whenever the host passes onRowClick); #33230 (PR #33441, f068cde8) changed the same plugin-grid files since, so the dev re-measures on origin/main first
    Serial constraints cleared: no other pm:dispatched domain:ui card claims a file in this surface (live label read); no other ui seat holds a Claim: on these files

    Scope: the card's one defect, one PR, Fixes #33317. p3; it was held serial behind #33230, which has merged. The declaration lines start at no / none; the dev measures them on the diff, and the seat amends this claim if they differ. Order: /mnt/project-files/pm-orders/ui/order-33317.md. Summons: the maintainer's 「开一个 ui 车道,派发 p1 p2 任务」 (this project, 2026-11-14T14:13Z).

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 14, 2026
  4. objectstack-fleet commented on Nov 15, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-project-manager · session_01FEkQ5pN9UhYM1KGHApVGCH
    os-dev-report
    {
    "issue": 33317,
    "status": "done",
    "branch": "claude/project-thread-9khlxt",
    "pr": "#33544",
    "session": "session_01FEkQ5pN9UhYM1KGHApVGCH",
    "premise_still_valid": true,
    "summary": "Measured on origin/main f068cde through the real ObjectView -> ListView -> ObjectGrid: a view authored navigation.mode none draws the name cell as an a-href anchor and offers row-context-open plus row-context-open-new-tab; a list-only object draws span role=link (primary-field-link) and offers row-context-open. Deciders: LinkCell is wrapped unconditionally in objectGridGenerateColumns.tsx (RecordLink picks anchor vs role=link span), and renderRowContextMenu's const opens = !!onRowClick || ... treats any host handler as Open; the console always passes onRowClick and the grid branch of ListView forwards no navigation, so the grid cannot derive the signal. Fix: one optional prop rowOpensRecord on ObjectGridComponentProps and ListViewProps (absent = unchanged); false => plain-text record-link cells (LinkCell opens=false) and no Open / Open in new tab, row actions and the actions column untouched, onRowClick still passed. Console hosts pass it: ObjectView navOverlay.mode !== 'none', ObjectDataPage recordServed, InterfaceListPage recordAction !== 'none'. Docs in plugin-grid README, plugin-grid.mdx, plugin-list README; changeset 33317-row-opens-nothing-plain.md (plugin-grid, plugin-list, app-shell, console patch).",
    "tests": "New: app-shell ObjectView.rowOpensNothing-33317.test.tsx (7: authored none, list-only, cmd-click still routed, CONTROL drawer, CONTROL page, data page list-only + CONTROL) and InterfaceListPage.rowOpensNothing-33317.test.tsx (2: recordAction none + CONTROL drawer), real hosts, menu via contextmenu event. Red-first: 8 production files restored to base f068cde (0 differ from base) -> 5 failed | 4 passed (9), VERDICT command-exit 1; restored, 0 bytes differ from HEAD. A first base attempt was VOID (a heredoc split the file list, so only InterfaceListPage was restored; its pins read green) and was redone. Ablations via scripts/ablation-replace.mjs (ui vitest aliases @object-ui/* to src, no dist): A LinkCell opens===false -> 4 failed|3 passed; B1 opens condition -> 2 failed (expected ['row-context-open'] to deeply equal []); B2 openHref -> 1 failed (row-context-open-new-tab, authored none only); C1 ObjectView wiring -> 3 failed; C2 ObjectDataPage -> 1 failed; C3 InterfaceListPage -> 1 failed|1 passed; each restored to the HEAD blob, git diff HEAD empty. Head a02d289: 4 pin files (new two + listOnlyRecordPage-33219 + rowContextMenu-28434) 36 passed; plugin-grid 281 files 2436 passed; plugin-list 173 files 1856 passed; app-shell ObjectView*/objectView*/InterfaceListPage*/ObjectDataPage* 111 files 986 passed; type-check plugin-grid, plugin-list, app-shell exit 0 (each tsc --noEmit && tsc -p tsconfig.test.json).",
    "gates": "Local: dispatch-gates --commands --repo objectstack-ai/objectstack on head a02d289: 69 derived, 69 run, all exit 0 (captured before any pipe); --ran reconciliation: 69 accounted, 0 NOT-MEASURED, 0 UNRUN. Record /mnt/project-files/pm-orders/ui/33317-gates-ran.txt and the PR body. check:role-word was red on an earlier head (the docs said role="link" in plugin-grid.mdx), reworded to ARIA link semantics, green on the final run; check:skill-examples exit 3 on the first run (client-react not built), built, exit 0. eslint on touched files 0 errors; check:new-line-citations 0 new. CI check-runs: in_progress at report time (PR just opened), not awaited per os-dev.md.",
    "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
    "mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on #33317; no write tool",
    "api_writes": "2 — relay pr_create (#33544, read back identical, no labels, no assignees); this os-dev-report comment via post-stamped on #33317",
    "open_questions": [],
    "security_findings": "none",
    "deviations": [
    "Clause-② measured yes (widening): new optional rowOpensRecord on ObjectGridComponentProps (@object-ui/plugin-grid) and ListViewProps (@object-ui/plugin-list); the claim says no, the seat said it would amend.",
    "File surface: ui/packages/plugin-list/src/ListView.tsx (forwarding only) plus ui/packages/plugin-grid/README.md, ui/packages/plugin-list/README.md, content/docs/frontend/plugins/plugin-grid.mdx are outside the claim's named files; the ListView hop is the only route from the console to the grid, and ui/AGENTS.md coding standard 2 asks for README + docs page.",
    "os-dev.md rule 2 lists assignees in pr_create; the order and AGENTS.md say none, so none were sent."
    ],
    "out_of_scope_findings": [
    "noted, not filed: the phone card face and gallery/board cards of a none list keep their tap target / pointer; only the grid is handed rowOpensRecord (read, not measured) · dedupe words: navigation none card pointer, list-only gallery click",
    "noted, not filed: the console object list's handleRowClick writes ?recordId= for a drawer view without reading navigation.preventNavigation (read, not measured) · dedupe words: preventNavigation drawer console row click",
    "noted, not filed: cmd-click on a row of a view authored navigation.mode none still opens the record in a new tab (useNavigationOverlay modifier rule, kept by the order's do-not-break-onRowClick ruling and pinned); the context menu no longer offers Open in new tab for that row"
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 15, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD

    Claim amendment · 2026-11-15T00:08Z
    Clause-②: yes (widening), measured by the dev on PR #33544 (head a02d289c). There are two new optional published props: rowOpensRecord on @object-ui/plugin-grid's ObjectGridComponentProps and on @object-ui/plugin-list's ListViewProps. When it is absent, today's behaviour holds, and nothing is removed or narrowed.
    Metadata-protocol: none (unchanged).
    File surface adds:

    • ui/packages/plugin-list/src/ListView.tsx (forwarding only)
    • the hosts that pass the prop (ObjectView, ObjectDataPage, InterfaceListPage)
    • three docs files: the plugin-grid README, plugin-grid.mdx and the plugin-list README

    A TIER_DEFAULT contract record (declaration face) is owed on the head before landing. os-dev-report: 6886357996.

  6. objectstack-fleet commented on Nov 15, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD

    Seat review: PR #33544 ACCEPT on head a02d289c (2026-11-15T00:30Z), contract record PASS 6886428303. K = 8, no sync; landing now (auto-merge). Follow-ups #33548 and #33549 are carded.

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

Metadata

Metadata

Labels

domain:uiDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions