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
ui(plugin-grid): in a record drawer, a related list's right-pinned action column (with an inline primary action) covers the Status column at rest #33230
Found by a downstream app on the published 18.4.0 packages (steedos-labs/os-project-blackcat-crm, the allocation-plan related list of an order).
Symptom
An order opened in a record drawer (from its list, at 1440 / 1280 / 1024 px wide) shows its child related list with a right-pinned actions column. When a row action is promoted inline (a variant: 'primary' custom action, maxInlineActions 1), the pinned column is ~154 px and sits over the last data column (Status) at rest: elementFromPoint at the centre of the Status cell returns the action button, and the Status header is hidden too. Status is revealed only by scrolling the table's scroll box horizontally (753 / 623 px). On the order's full page at 1440 there is no overlap. At 390 px the list renders as cards and the action moves into each card's menu (fine).
Producer (downstream reading, unverified by the PM seat beyond the file reads)
ui/packages/plugin-grid/src/components/RowActionMenu.tsx ~lines 337–343 (inline primary promotion, testid ~529) together with the grid's right-pinned actions column: the pinned column's width grows with the inline button but the scroll box does not reserve it, so a non-overflowing first view is partly covered.
Suggested fix shape (for the lane to judge)
Reserve the pinned column's width in the scroll box (or make the first view overflow-aware), so no data column is covered at rest; or fall back to the menu-only action column when the inline button would cover a data column.
Dedupe words: sticky action column overlaps status · right-pinned action column covers column · related list drawer inline primary.
Row: in a record drawer, a related list's right-pinned action column (with one inline primary action) sits over the Status column at rest. This is a layout defect; scrolling reveals the column, and no data is wrong: p3.
Owner: plugin-gridRowActionMenu.tsx (the pinned column width with an inline action).
Claim: PM loop round 1 · 2026-11-14T19:57Z
Session: session_01FEkQ5osPMA12JX9fGcBzR3 (card thread, dev) · seat session_01FEkQ5nWoa1Ze1QzjRTSYXD
Account: os-project-manager
Branch: claude/project-thread-vbend6
Worktree: objectstack-issue-33230
Domain: domain:ui
Seat: domain:ui#1
File surface: ui/packages/plugin-grid/src/ (the right-pinned actions column, RowActionMenu.tsx's inline row button width, the grid scroll box) and its tests; the related-list host in ui/packages/app-shell only if the producer is measured there; root .changeset/. ⛔ No server or packages/spec edit.
Container & model: S, mode:thread, model: default tier, effort: default
Clause-②: no
Metadata-protocol: none
Responsibility: in a record drawer, a related list whose row has one inline primary action pins an actions column over the last data column at rest | horizontal scroll reveals the column | every user opening a parent record in a drawer whose child list has an inline primary action
Thread-read: 6874039384
Premise: downstream reading on published 18.4.0, unverified by the seat; #33215 (PR #33354, d574341a) changed the inline row button since, so the dev reproduces on origin/main first and closes by a pin if it no longer reproduces
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 #33230. p3; it was held serial behind #33215, 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-33230.md. Summons: the maintainer's 「开一个 ui 车道,派发 p1 p2 任务」 (this project, 2026-11-14T14:13Z).
{
"issue": 33230,
"status": "done",
"branch": "claude/project-thread-vbend6",
"pr": "#33441",
"session": "session_01FEkQ5osPMA12JX9fGcBzR3",
"premise_still_valid": true,
"summary": "Reproduced on origin/main in a real browser: in the enlarged related list at a drawer's width, the right-pinned Actions column with one inline primary button is 139 px (68 px menu-only), and that width alone tips a table whose data columns fit into one that overflows, so the column covers Status at rest (elementFromPoint at Status's centre answered the inline Allocate button; box 900, table 954, Status 735-815 under the column from 761). The producer is the pinned column's width; the scroll box does reserve the column (scrollWidth includes it, scrolling to the end reveals Status). Fix: ObjectGrid draws inline row buttons only while the table fits its scroll box with them; when it overflows with them, each row's primary action moves to the top of its row menu (planner inline budget 0), and the buttons return once the box is as wide as the table was with them. Readings wait for the table size to hold two frames. No export, prop, authored key, server or spec change.",
"tests": "New Playwright pin ui/e2e/related-list-pinned-actions-width.spec.ts (real RelatedList enlarged face, Vite-bundled sources, compiled Tailwind, Chromium): drawer 622 px at 1440/1280/1024 windows folded, inline 0, box 622/622, actions left 554 width 68, statusRight 554, Status cell and header hit, Allocate dispatched from the row menu; CONTROL full page 1184 not folded, inline 3, actions width 139, Status hit, inline click dispatches; CONTROL 390 px card layout, Allocate in the card menu; wide drawer (8 columns) folds and Status is reached by scrolling. 6 passed at ee03c81. Ablation at 3afff0c via scripts/ablation-replace.mjs (decide(true) made a no-op): mutation landed (anchor 1 -> 0, blob 53abf59026e5 -> 4dec1046a3e3); drawer1440/1280/1024 red with 'the pinned Actions column covers part of Status at rest' (box 622/654, actions left 483 width 139, statusRight 515), wide case red, both CONTROLs green (4 failed, 2 passed); restored blob == HEAD, git diff HEAD empty. plugin-grid suite 281 files / 2436 tests passed.",
"gates": "Local: 37 derived families from dispatch-gates --commands plus 4 ui runs outside the derivation, each exit captured before any pipe; dispatch-gates --ran at ee03c81: 37 derived, 37 run, 0 NOT-MEASURED, 0 UNRUN. Record: node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 | node scripts/check-adr-0087-registration.mjs --self-test :: exit 0 | node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0 | node scripts/check-closing-keyword-parity.mjs :: exit 0 | node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 | node scripts/check-comment-mask-corpus.mjs :: exit 0 | node scripts/check-empty-changeset.mjs --base origin/main :: exit 0 | node scripts/check-empty-changeset.mjs --self-test :: exit 0 | node scripts/check-sdui-manifest.mjs :: exit 0 | node scripts/check-sdui-manifest.mjs --self-test :: exit 0 | node scripts/ci/snapshot-next.mjs --self-test :: exit 0 | node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0 | node scripts/release-pending-publish.mjs --self-test :: exit 0 | pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0 | pnpm check:changeset-gate-self-tests :: exit 0 | pnpm check:closed-ceremony-text :: exit 0 | pnpm check:cross-package-test-inputs :: exit 0 | pnpm check:dispatcher-error-vocabulary :: exit 0 | pnpm check:driver-memory-census :: exit 0 | pnpm check:engine-double-contract :: exit 0 | pnpm check:error-status-conformance :: exit 0 | pnpm check:gitlink-declared :: exit 0 | pnpm check:query-options-erasure :: exit 0 | pnpm check:refd-timer-probe :: exit 0 | pnpm check:skill-identifier-liveness :: exit 0 | pnpm check:test-source-alias :: exit 0 | pnpm check:watch-hint-literal :: exit 0 | pnpm --dir ui --filter @object-ui/plugin-grid run type-check :: exit 0 | pnpm --dir ui run type-check:e2e :: exit 0 | pnpm --dir ui run check:new-line-citations :: exit 0 | pnpm check:undeclared-dep-imports :: exit 0 | pnpm check:tier-file-adoption :: exit 0 | pnpm check:registry-log-declared :: exit 0 | pnpm check:rest-log-spy-declared :: exit 0 | pnpm check:nul-bytes :: exit 0 | pnpm check:type-check-coverage :: exit 0 | pnpm check:published-files :: exit 0 | pnpm check:where-matcher :: exit 0 | pnpm check:type-check-debt :: exit 0 | pnpm --dir ui exec vitest run scripts/ :: exit 0 | pnpm --dir ui exec vitest run packages/plugin-grid/ :: exit 0. First ui scripts run exited 1 on e2e-type-check.test.ts (the pin's page entry named @object-ui packages in a source string); fixed in ee03c81, whole suite reran exit 0 (171 passed, 2 skipped) and the gates that read the spec reran. CI check runs on #33441: in_progress at report time (not waited for, per os-dev.md).",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "3 — mcp__github__issue_read x3 (card, comments, claim read-back); no MCP write",
"api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, run 43641810403, read-back identical 9823 bytes, no labels, no assignees) and this os-dev-report comment via post-stamped. Plus git push x3 to claude/project-thread-vbend6 (not REST).",
"line_budget": "589 changed lines (+585 / -4) over 5 files, under the 3000 human-merge threshold",
"files_changed": [
".changeset/33230-related-list-inline-action-fold.md",
"ui/e2e/related-list-pinned-actions-width.spec.ts",
"ui/packages/plugin-grid/src/ObjectGrid.tsx",
"ui/packages/plugin-grid/src/objectGridActionsColumn.tsx",
"ui/packages/plugin-grid/src/objectGridInlineActionFold.ts"
],
"deviations": [
"pr_create carries no assignees: the order says no assignees, while os-dev.md rule 2 says pr_create carries the claim's Account; the order's explicit line was followed.",
"Builds and suites ran outside scripts/pm/os-verify-lock.sh: this card thread is the only agent in its container.",
"The live Console drawer could not show an enlarged related list (the showcase's authored page has no enlarge control), so the drawer width was measured live (720 px pane, 622 px content) and the defect was reproduced and pinned in the browser harness."
],
"open_questions": [
{
"question": "A table that overflows the drawer even menu-only (many columns) still has the folded pinned column over the data at the box's right edge at rest, as the full list page does today. Should the line 'no data column covered at rest' also hold there?",
"status": "needs_decision",
"options": [
"A Keep as is: the fold covers every table the inline button alone tipped over; a table that overflows anyway scrolls sideways under a 68 px pinned menu column, the standard sideways-scroll behaviour (this PR).",
"B Un-pin the Actions column whenever the table overflows, so the last column is visible at rest but the row menu scrolls out of reach until the user scrolls.",
"C Reserve a gutter of the pinned column's width after the last data column, so scrolling to the end shows everything (already true) and at rest the covered column is whichever reaches the edge (no change at rest)."
],
"recommendation": "A. Business need: the card's measured case (drawer, inline button tipping the table) is fixed; no measured report covers the menu-only overflow case, which the list page has always had. Long-term: pinning the action column is the established list contract; B trades action reach for one column. AI-error axis: neutral, no metadata involved. Startup focus: B or C would be a new layout policy with no pull. Leave as is unless a real report arrives."
}
],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · the menu-only overflow regime (on the live Console list page at a 1440 px window, End Date sits under the right-pinned Actions column at rest, origin/main behaviour) is the design question in open_questions and the PR's Acceptance notes, not a filed defect"
]
}
Seat review: PR #33441 ACCEPT on head ee03c81e (2026-11-14T21:37Z), open question ruled A (existing sideways-scroll contract). Base synced (K = 21); it lands after the rerun is green.
MERGED as f068cde8 on main (closes this card via Fixes #33230)
contract record
not owed (Clause-② no)
State: pm:dispatched removed, assignee cleared; card closed by the merge. The open question (menu-only overflow) was ruled A in the ACCEPT, the existing sideways-scroll contract. #33317 (same plugin-grid files) is now free to dispatch.
Activity
objectstack-fleet commentedon Nov 14, 2026
triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH
Path: none
Triage: first touch →
domain:ui· p3 ·pm:queue· 2026-11-14T07:45Z⛔ Not a claim.
plugin-gridRowActionMenu.tsx(the pinned column width with an inline action).objectstack-fleet commentedon Nov 14, 2026
domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD
Claim: PM loop round 1 · 2026-11-14T19:57Z
Session:
session_01FEkQ5osPMA12JX9fGcBzR3(card thread, dev) · seatsession_01FEkQ5nWoa1Ze1QzjRTSYXDAccount:
os-project-managerBranch:
claude/project-thread-vbend6Worktree:
objectstack-issue-33230Domain:
domain:uiSeat:
domain:ui#1File surface:
ui/packages/plugin-grid/src/(the right-pinned actions column,RowActionMenu.tsx's inline row button width, the grid scroll box) and its tests; the related-list host inui/packages/app-shellonly if the producer is measured there; root.changeset/. ⛔ No server orpackages/specedit.Container & model: S,
mode:thread,model: default tier,effort: defaultClause-②: no
Metadata-protocol: none
Responsibility: in a record drawer, a related list whose row has one inline primary action pins an actions column over the last data column at rest | horizontal scroll reveals the column | every user opening a parent record in a drawer whose child list has an inline primary action
Thread-read: 6874039384
Premise: downstream reading on published 18.4.0, unverified by the seat; #33215 (PR #33354,
d574341a) changed the inline row button since, so the dev reproduces onorigin/mainfirst and closes by a pin if it no longer reproducesSerial 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 #33230. p3; it was held serial behind #33215, 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-33230.md. Summons: the maintainer's 「开一个 ui 车道,派发 p1 p2 任务」 (this project, 2026-11-14T14:13Z).objectstack-fleet commentedon Nov 14, 2026
domain:ui#1 · os-project-manager · session_01FEkQ5osPMA12JX9fGcBzR3
os-dev-report
{
"issue": 33230,
"status": "done",
"branch": "claude/project-thread-vbend6",
"pr": "#33441",
"session": "session_01FEkQ5osPMA12JX9fGcBzR3",
"premise_still_valid": true,
"summary": "Reproduced on origin/main in a real browser: in the enlarged related list at a drawer's width, the right-pinned Actions column with one inline primary button is 139 px (68 px menu-only), and that width alone tips a table whose data columns fit into one that overflows, so the column covers Status at rest (elementFromPoint at Status's centre answered the inline Allocate button; box 900, table 954, Status 735-815 under the column from 761). The producer is the pinned column's width; the scroll box does reserve the column (scrollWidth includes it, scrolling to the end reveals Status). Fix: ObjectGrid draws inline row buttons only while the table fits its scroll box with them; when it overflows with them, each row's primary action moves to the top of its row menu (planner inline budget 0), and the buttons return once the box is as wide as the table was with them. Readings wait for the table size to hold two frames. No export, prop, authored key, server or spec change.",
"tests": "New Playwright pin ui/e2e/related-list-pinned-actions-width.spec.ts (real RelatedList enlarged face, Vite-bundled sources, compiled Tailwind, Chromium): drawer 622 px at 1440/1280/1024 windows folded, inline 0, box 622/622, actions left 554 width 68, statusRight 554, Status cell and header hit, Allocate dispatched from the row menu; CONTROL full page 1184 not folded, inline 3, actions width 139, Status hit, inline click dispatches; CONTROL 390 px card layout, Allocate in the card menu; wide drawer (8 columns) folds and Status is reached by scrolling. 6 passed at ee03c81. Ablation at 3afff0c via scripts/ablation-replace.mjs (decide(true) made a no-op): mutation landed (anchor 1 -> 0, blob 53abf59026e5 -> 4dec1046a3e3); drawer1440/1280/1024 red with 'the pinned Actions column covers part of Status at rest' (box 622/654, actions left 483 width 139, statusRight 515), wide case red, both CONTROLs green (4 failed, 2 passed); restored blob == HEAD, git diff HEAD empty. plugin-grid suite 281 files / 2436 tests passed.",
"gates": "Local: 37 derived families from dispatch-gates --commands plus 4 ui runs outside the derivation, each exit captured before any pipe; dispatch-gates --ran at ee03c81: 37 derived, 37 run, 0 NOT-MEASURED, 0 UNRUN. Record: node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 | node scripts/check-adr-0087-registration.mjs --self-test :: exit 0 | node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0 | node scripts/check-closing-keyword-parity.mjs :: exit 0 | node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 | node scripts/check-comment-mask-corpus.mjs :: exit 0 | node scripts/check-empty-changeset.mjs --base origin/main :: exit 0 | node scripts/check-empty-changeset.mjs --self-test :: exit 0 | node scripts/check-sdui-manifest.mjs :: exit 0 | node scripts/check-sdui-manifest.mjs --self-test :: exit 0 | node scripts/ci/snapshot-next.mjs --self-test :: exit 0 | node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0 | node scripts/release-pending-publish.mjs --self-test :: exit 0 | pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0 | pnpm check:changeset-gate-self-tests :: exit 0 | pnpm check:closed-ceremony-text :: exit 0 | pnpm check:cross-package-test-inputs :: exit 0 | pnpm check:dispatcher-error-vocabulary :: exit 0 | pnpm check:driver-memory-census :: exit 0 | pnpm check:engine-double-contract :: exit 0 | pnpm check:error-status-conformance :: exit 0 | pnpm check:gitlink-declared :: exit 0 | pnpm check:query-options-erasure :: exit 0 | pnpm check:refd-timer-probe :: exit 0 | pnpm check:skill-identifier-liveness :: exit 0 | pnpm check:test-source-alias :: exit 0 | pnpm check:watch-hint-literal :: exit 0 | pnpm --dir ui --filter @object-ui/plugin-grid run type-check :: exit 0 | pnpm --dir ui run type-check:e2e :: exit 0 | pnpm --dir ui run check:new-line-citations :: exit 0 | pnpm check:undeclared-dep-imports :: exit 0 | pnpm check:tier-file-adoption :: exit 0 | pnpm check:registry-log-declared :: exit 0 | pnpm check:rest-log-spy-declared :: exit 0 | pnpm check:nul-bytes :: exit 0 | pnpm check:type-check-coverage :: exit 0 | pnpm check:published-files :: exit 0 | pnpm check:where-matcher :: exit 0 | pnpm check:type-check-debt :: exit 0 | pnpm --dir ui exec vitest run scripts/ :: exit 0 | pnpm --dir ui exec vitest run packages/plugin-grid/ :: exit 0. First ui scripts run exited 1 on e2e-type-check.test.ts (the pin's page entry named @object-ui packages in a source string); fixed in ee03c81, whole suite reran exit 0 (171 passed, 2 skipped) and the gates that read the spec reran. CI check runs on #33441: in_progress at report time (not waited for, per os-dev.md).",
"dogfood_battery": "n/a — no
!in the PR title and no (narrowing) arm","mcp_calls": "3 — mcp__github__issue_read x3 (card, comments, claim read-back); no MCP write",
"api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, run 43641810403, read-back identical 9823 bytes, no labels, no assignees) and this os-dev-report comment via post-stamped. Plus git push x3 to claude/project-thread-vbend6 (not REST).",
"line_budget": "589 changed lines (+585 / -4) over 5 files, under the 3000 human-merge threshold",
"files_changed": [
".changeset/33230-related-list-inline-action-fold.md",
"ui/e2e/related-list-pinned-actions-width.spec.ts",
"ui/packages/plugin-grid/src/ObjectGrid.tsx",
"ui/packages/plugin-grid/src/objectGridActionsColumn.tsx",
"ui/packages/plugin-grid/src/objectGridInlineActionFold.ts"
],
"deviations": [
"pr_create carries no assignees: the order says no assignees, while os-dev.md rule 2 says pr_create carries the claim's Account; the order's explicit line was followed.",
"Builds and suites ran outside scripts/pm/os-verify-lock.sh: this card thread is the only agent in its container.",
"The live Console drawer could not show an enlarged related list (the showcase's authored page has no enlarge control), so the drawer width was measured live (720 px pane, 622 px content) and the defect was reproduced and pinned in the browser harness."
],
"open_questions": [
{
"question": "A table that overflows the drawer even menu-only (many columns) still has the folded pinned column over the data at the box's right edge at rest, as the full list page does today. Should the line 'no data column covered at rest' also hold there?",
"status": "needs_decision",
"options": [
"A Keep as is: the fold covers every table the inline button alone tipped over; a table that overflows anyway scrolls sideways under a 68 px pinned menu column, the standard sideways-scroll behaviour (this PR).",
"B Un-pin the Actions column whenever the table overflows, so the last column is visible at rest but the row menu scrolls out of reach until the user scrolls.",
"C Reserve a gutter of the pinned column's width after the last data column, so scrolling to the end shows everything (already true) and at rest the covered column is whichever reaches the edge (no change at rest)."
],
"recommendation": "A. Business need: the card's measured case (drawer, inline button tipping the table) is fixed; no measured report covers the menu-only overflow case, which the list page has always had. Long-term: pinning the action column is the established list contract; B trades action reach for one column. AI-error axis: neutral, no metadata involved. Startup focus: B or C would be a new layout policy with no pull. Leave as is unless a real report arrives."
}
],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · the menu-only overflow regime (on the live Console list page at a 1440 px window, End Date sits under the right-pinned Actions column at rest, origin/main behaviour) is the design question in open_questions and the PR's Acceptance notes, not a filed defect"
]
}
Generated by Claude Code
objectstack-fleet commentedon Nov 14, 2026
domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD
Seat review: PR #33441 ACCEPT on head
ee03c81e(2026-11-14T21:37Z), open question ruled A (existing sideways-scroll contract). Base synced (K = 21); it lands after the rerun is green.objectstack-fleet commentedon Nov 14, 2026
domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD
Landed · 2026-11-14T22:41Z
f068cde8onmain(closes this card viaFixes #33230)State:
pm:dispatchedremoved, assignee cleared; card closed by the merge. The open question (menu-only overflow) was ruled A in the ACCEPT, the existing sideways-scroll contract. #33317 (same plugin-grid files) is now free to dispatch.