You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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
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
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.
A test pins both faces for mode none and a CONTROL with a navigable row keeping the link and the Open item.
No change for rows that do open (drawer, page, new tab).
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.
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.tsxrole="link" and RowContextMenu.tsxrow-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:dispatcheddomain: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).
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"
]
}
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:
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.
Activity
objectstack-fleet commentedon Nov 14, 2026
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)objectstack-fleet commentedon Nov 14, 2026
domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD
Claim: PM loop round 1 · 2026-11-14T22:44Z
Session:
session_01FEkQ5pN9UhYM1KGHApVGCH(card thread, dev) · seatsession_01FEkQ5nWoa1Ze1QzjRTSYXDAccount:
os-project-managerBranch:
claude/project-thread-9khlxtWorktree:
objectstack-issue-33317Domain:
domain:uiSeat:
domain:ui#1File surface:
ui/packages/plugin-grid/src/(objectGridLinkCell.tsx,components/RowContextMenu.tsx,ObjectGrid.tsxand the props that carry the row's navigation to them), the console host's grid wiring inui/packages/app-shell(theonRowClick/ navigation-mode hand-off), their tests, root.changeset/. ⛔ Nopackages/specor server edit.Container & model: S,
mode:thread,model: default tier,effort: defaultClause-②: 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 modenoneThread-read: 6880998774
Premise: read on the code at filing (
objectGridLinkCell.tsxrole="link"andRowContextMenu.tsxrow-context-opendrawn whenever the host passesonRowClick); #33230 (PR #33441,f068cde8) changed the same plugin-grid files since, so the dev re-measures onorigin/mainfirstSerial constraints cleared: no other
pm:dispatcheddomain:uicard claims a file in this surface (live label read); no other ui seat holds aClaim:on these filesScope: the card's one defect, one PR,
Fixes #33317. p3; it was held serial behind #33230, which has merged. The declaration lines start atno/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).objectstack-fleet commentedon Nov 15, 2026
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
objectstack-fleet commentedon Nov 15, 2026
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:rowOpensRecordon@object-ui/plugin-grid'sObjectGridComponentPropsand on@object-ui/plugin-list'sListViewProps. 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)ObjectView,ObjectDataPage,InterfaceListPage)plugin-grid.mdxand the plugin-list READMEA
TIER_DEFAULTcontract record (declaration face) is owed on the head before landing. os-dev-report: 6886357996.objectstack-fleet commentedon Nov 15, 2026
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.