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
Console at phone width: Navigation flow audit and fixes at 375 and 390 px #29075
Filing gate: ④ coordination node, a per-flow child of maintainer card #29040, split as its triage comment orders ("the ui lane splits it when it claims, one child card per flow, each with Part of #29040") · filed by domain:ui#4 · ⛔ Not a claim.
Business reason (from #29040).objectstack-ai/mobile 2.0 hosts the Console in a WebView (objectstack-ai/mobile#144), so phone users get the Console's responsive layout and nothing else. This child covers the Navigation flow: the app switcher, nav groups, and back behaviour.
Ask. Drive the flow in a real browser at 375×812 and 390×844 against the showcase and CRM examples. Record what breaks and fix it. Check each of these:
no horizontal page scroll;
touch targets of at least 44 px;
dialogs and drawers fit the viewport;
the virtual keyboard does not cover the focused field;
long lists stay responsive on a mid-range Android device profile (CPU throttling 4×).
Acceptance.
A run record for this flow in the PR body: each check, pass or fail, at both widths, with the page and example it ran on.
A fix for every failure, or a filed card for each failure this PR does not fix.
Screenshots before and after each fix stay in the project folder, not on GitHub.
Reader.domain:ui#1 (the ui lane split #29040 per flow: domain:ui#4 takes Approvals, Record and Forms; domain:ui#1 takes Lists, Navigation, Notifications, Dashboards and Auth). Size M.
Dedupe. Searched 375 in:title (0), phone in:title is:open (3: #29040, #28911, #29057), mobile width in:title (1: #29040), Part of #29040 (1: #29040). No per-flow child existed.
Claim: PM loop round 18 · 2026-11-02T07:01Z
Session: session_01QsR2jRQob8nVK5owwvNtfr (card thread, os-dev); dispatched by seat session session_01QsR2jUJ19MstFvFhjgiYTu
Account: zhuangjianguo
Branch: claude/project-thread-dnpnnb (platform-assigned to the card thread; it can push only this branch)
Worktree: objectstack-issue-29075
Domain: domain:ui
Seat: domain:ui#1
File surface: Console files read only for the phone-width audit, plus a root .changeset. The fix surface is declared by a claim amendment after the audit, before any code (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: medium
Clause-②: no
Metadata-protocol: none
Responsibility: the Navigation flow of the #29040 phone-width audit (375 and 390 px) and its fixes
Thread-read: none
Premise: holds (at origin/main6b3ba82c: no PR or run record exists for the Navigation flow; #29040 split comment 6571123115 names this child for domain:ui#1)
Serial constraints cleared: the other #29040 children hold no shared-layout file; this card is the only one allowed to plan edits to ConsoleLayout, AppShell and UnifiedSidebar (each fix list is checked before its amendment).
Claim amended · 2026-11-02T07:44Z · after the dev's audit (run record /mnt/project-files/issue-29075/run-record-before.md, origin/main6b3ba82c, real Console at /_console on CRM and the showcase, 375 and 390 px). This sets the fix surface and adds to the round 19 claim 6571165367 on this card. Branch, session and size are unchanged.
Measured: no page scrolls sideways, overlays fit, drawer rows are 44 px, and the keyboard keeps the search field visible. FAIL at both widths: the nav drawer stays open after an entry is tapped (all four runs); app bar targets are 28 to 34 px (sidebar toggle, home mark, app chip, search, Studio, inbox, account); app-switcher rows are 38 px; account menu rows, theme and language are 32 px; ConsolePageHeader's Refresh is 32 px.
File surface (set): under ui/packages/app-shell/src/layout/: UnifiedSidebar.tsx (the drawer closes on route change), AppHeader.tsx, LocalizedSidebarTrigger.tsx, AppSwitcher.tsx, ModeToggle.tsx, LocaleSwitcher.tsx and PageHeader.tsx; new tests layout/__tests__/UnifiedSidebar.phoneDrawerCloses-29075.test.tsx and layout/__tests__/AppHeader.phoneTargets-29075.test.tsx; and a root .changeset (patch, app-shell). Targets go to 44 px below sm only, so desktop is unchanged. To fit 375 px, the Studio eye and the home mark drop below sm. Both stay one tap away in the app-switcher menu (Back to home, Open APP in Studio).
Claim amended · 2026-11-02T07:57Z · adds one file to the fix surface set by amendment 6571821121 (claim 6571165367). Everything else is unchanged.
File surface (added):ui/packages/app-shell/src/layout/InboxPopover.tsx, one class on the inbox bell trigger only (44 px below md). The audit found the bell's 32 px button drawn there, not in AppHeader.tsx.
{
"issue": 29075,
"status": "done",
"branch": "claude/project-thread-dnpnnb",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29168",
"head": "05647568",
"session": "session_01QsR2jRQob8nVK5owwvNtfr",
"premise_still_valid": true,
"summary": "Audit first, at main 6b3ba82c, on the production Console (/_console) of examples/app-crm and examples/app-showcase at 375x812 and 390x844 (Chromium, isMobile + touch, DPR 2; run record and before/after screenshots in issue-29075/). Pass: no horizontal scroll in any state, overlays fit, drawer rows 44 px, nav groups toggle, Back after a drawer navigation returns, search field stays visible with a 40% keyboard. Fixed here (claim 6571165367, amendments 6571821121 and 6572041449): N1 the phone drawer stayed open over the page after a tapped entry; UnifiedSidebar now closes it when pathname+search changes (route-keyed, so favorites, recents and outside navigations close it too; mobile form only). N2-N5 top-bar controls were 28-34 px and menu rows 32/38 px: max-md:size-11 on the trigger, product mark, search, Studio, AI, avatar, inbox bell, theme, language and PageHeader Refresh; app pill min 44 px; app switcher, account, theme and language menus carry max-md:[&_[role=menuitem]]:min-h-11. To fit a 375 px bar, below sm an app's bar drops the product mark (and its rule) and the Studio button; both stay one tap away in the app switcher menu, and the drawer's All apps goes home. 768 px and up unchanged (1280 measured equal to main).",
"files_changed": [
".changeset/29075-phone-navigation.md",
"ui/packages/app-shell/src/layout/AppHeader.tsx",
"ui/packages/app-shell/src/layout/AppSwitcher.tsx",
"ui/packages/app-shell/src/layout/InboxPopover.tsx",
"ui/packages/app-shell/src/layout/LocaleSwitcher.tsx",
"ui/packages/app-shell/src/layout/ModeToggle.tsx",
"ui/packages/app-shell/src/layout/PageHeader.tsx",
"ui/packages/app-shell/src/layout/UnifiedSidebar.tsx",
"ui/packages/app-shell/src/layout/__tests__/AppHeader.phoneTargets-29075.test.tsx",
"ui/packages/app-shell/src/layout/__tests__/UnifiedSidebar.phoneDrawerCloses-29075.test.tsx"
],
"line_budget": "under the 3000 threshold (552 changed lines at 7a92e5de, 10 files, plus a test-only lint commit); inside the amended file surface. LocalizedSidebarTrigger.tsx was in the surface and needed no edit.",
"tests": "From ui/ under os-verify-lock. At 05647568: the two new files (UnifiedSidebar.phoneDrawerCloses-29075 4 tests, AppHeader.phoneTargets-29075 8 tests) exit 0, 12 passed. At 7a92e5de: the 79 existing layout/__tests__ files for AppHeader, AppSwitcher, UnifiedSidebar, PageHeader, ConsolePageHeader, InboxPopover, LocaleSwitcher (incl. AppHeader.homeMark-12605) exit 0, 512 tests; 05647568 changes only the two new test files. Ablation via scripts/ablation-replace.mjs at 05647568: 'if (isMobile) setOpenMobile(false);' -> 'if (isMobile && Date.now() < 0) setOpenMobile(false);' reds 2 of 4 (both navigation cases); restored blob == HEAD acf40396, git diff HEAD empty. turbo run type-check --filter=@object-ui/app-shell at 05647568: 65/65, exit 0. eslint on the ten files: 0 errors (2 react-hooks/globals errors and 1 unused helper in the new tests fixed in 05647568); remaining warnings pre-existing.",
"gates": "dispatch-gates derived 34; 30 commands plus pnpm --dir ui exec vitest run scripts/ (169 passed / 2 skipped files) at 7a92e5de, each exit 0; the three PR-body gates on the exact body: check-changeset-no-major --base origin/main, check-adr-0087-registration --base origin/main, check-closing-keyword-parity exit 0, plus check-partof-closing-keyword exit 0. --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. check-sdui-manifest exit 0. First vitest run scripts/ was OOM-killed beside the audit servers; re-run after stopping them, green.",
"dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
"mcp_calls": "mcp__github__issue_read (card body and comments); mcp__claude-code-remote__subscribe_pr_activity on #29168; no GitHub MCP write",
"api_writes": "2: (1) fleet-write relay dispatch carrying one pr_create (draft, no labels, no assignees; read-back 11484 bytes sent = stored, #29168); (2) this os-dev-report comment via post-stamped. git push x2 are not REST writes.",
"deviations": [
"The PR body opens with the harness-required attribution comment and Requested-by line, then Fixes #29075.",
"Subscribed this session to #29168 activity (the harness requires it after a PR opens); re-runs and landing stay with the seat.",
"Gates and the 79-file sweep ran at 7a92e5de; 05647568 changes only the two new test files, which were re-run with type-check and the ablation at 05647568.",
"Performance was measured on the production build (pnpm console:build, backends restarted); the first Vite-dev CPU 4x numbers were discarded."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: #29131 · N6 Back with the phone drawer open leaves the page instead of closing the drawer (all four runs).",
"carrier: #29141 · N8 drawer open at CPU 4x: app-showcase (46 entries) 294-576 ms click to first paint, over a 200 ms budget; app-crm 107-253 ms.",
"carrier: seat 4 (Record) · N7 record page phone back control is a link that pushes a history entry, so Back after it reopens the record; back control 92x28 and Next 28x28.",
"carrier: seat 4 (Overlay, dialog.tsx) · N9 search palette Close is 16x16.",
"carrier: #29074 · list toolbar controls under 44 px at 375/390.",
"carrier: #29076 · account menu notification switches 44x24.",
"carrier: seat (card in its write queue) · home page body launcher links 16-32 px tall · reach: /home at 375 and 390 on both examples · dedupe words: home launcher links touch target, home page phone 44px"
]
}
Fixes #29075 closed this card. pm:dispatched comes off in the same stroke as this note. #29024 (seat 3), and #29131 and #29141 (seat 4), waited on this PR and can now be ordered on origin/main.
Activity
objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim: PM loop round 18 · 2026-11-02T07:01Z
Session:
session_01QsR2jRQob8nVK5owwvNtfr(card thread, os-dev); dispatched by seat sessionsession_01QsR2jUJ19MstFvFhjgiYTuAccount:
zhuangjianguoBranch:
claude/project-thread-dnpnnb(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-29075Domain:
domain:uiSeat:
domain:ui#1File surface: Console files read only for the phone-width audit, plus a root
.changeset. The fix surface is declared by a claim amendment after the audit, before any code (stop on breach; explain in the report)Container & model: M,
mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate),effort: mediumClause-②: no
Metadata-protocol: none
Responsibility: the Navigation flow of the #29040 phone-width audit (375 and 390 px) and its fixes
Thread-read: none
Premise: holds (at
origin/main6b3ba82c: no PR or run record exists for the Navigation flow; #29040 split comment 6571123115 names this child fordomain:ui#1)Serial constraints cleared: the other #29040 children hold no shared-layout file; this card is the only one allowed to plan edits to ConsoleLayout, AppShell and UnifiedSidebar (each fix list is checked before its amendment).
objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim amended · 2026-11-02T07:44Z · after the dev's audit (run record
/mnt/project-files/issue-29075/run-record-before.md,origin/main6b3ba82c, real Console at/_consoleon CRM and the showcase, 375 and 390 px). This sets the fix surface and adds to the round 19 claim 6571165367 on this card. Branch, session and size are unchanged.ui/packages/app-shell/src/layout/:UnifiedSidebar.tsx(the drawer closes on route change),AppHeader.tsx,LocalizedSidebarTrigger.tsx,AppSwitcher.tsx,ModeToggle.tsx,LocaleSwitcher.tsxandPageHeader.tsx; new testslayout/__tests__/UnifiedSidebar.phoneDrawerCloses-29075.test.tsxandlayout/__tests__/AppHeader.phoneTargets-29075.test.tsx; and a root.changeset(patch, app-shell). Targets go to 44 px belowsmonly, so desktop is unchanged. To fit 375 px, the Studio eye and the home mark drop belowsm. Both stay one tap away in the app-switcher menu (Back to home, Open APP in Studio).sheet.tsxbelongs to Console at phone width: Dashboards flow audit and fixes at 375 and 390 px #29078 anddialog.tsx(including the palette's 16 px Close) to Dialog close button at phone width: the X in the shared Dialog is a 16x16 px target, below the 44 px minimum, in every modal the mobile app shows #29107. This card leaves both alone.<and Next targets to seat 4's Record flow.objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim amended · 2026-11-02T07:57Z · adds one file to the fix surface set by amendment 6571821121 (claim 6571165367). Everything else is unchanged.
ui/packages/app-shell/src/layout/InboxPopover.tsx, one class on the inbox bell trigger only (44 px belowmd). The audit found the bell's 32 px button drawn there, not inAppHeader.tsx.InboxPopover.tsx, it merges main after this PR lands.objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jRQob8nVK5owwvNtfr
os-dev-report
{ "issue": 29075, "status": "done", "branch": "claude/project-thread-dnpnnb", "pr": "https://github.com/objectstack-ai/objectstack/pull/29168", "head": "05647568", "session": "session_01QsR2jRQob8nVK5owwvNtfr", "premise_still_valid": true, "summary": "Audit first, at main 6b3ba82c, on the production Console (/_console) of examples/app-crm and examples/app-showcase at 375x812 and 390x844 (Chromium, isMobile + touch, DPR 2; run record and before/after screenshots in issue-29075/). Pass: no horizontal scroll in any state, overlays fit, drawer rows 44 px, nav groups toggle, Back after a drawer navigation returns, search field stays visible with a 40% keyboard. Fixed here (claim 6571165367, amendments 6571821121 and 6572041449): N1 the phone drawer stayed open over the page after a tapped entry; UnifiedSidebar now closes it when pathname+search changes (route-keyed, so favorites, recents and outside navigations close it too; mobile form only). N2-N5 top-bar controls were 28-34 px and menu rows 32/38 px: max-md:size-11 on the trigger, product mark, search, Studio, AI, avatar, inbox bell, theme, language and PageHeader Refresh; app pill min 44 px; app switcher, account, theme and language menus carry max-md:[&_[role=menuitem]]:min-h-11. To fit a 375 px bar, below sm an app's bar drops the product mark (and its rule) and the Studio button; both stay one tap away in the app switcher menu, and the drawer's All apps goes home. 768 px and up unchanged (1280 measured equal to main).", "files_changed": [ ".changeset/29075-phone-navigation.md", "ui/packages/app-shell/src/layout/AppHeader.tsx", "ui/packages/app-shell/src/layout/AppSwitcher.tsx", "ui/packages/app-shell/src/layout/InboxPopover.tsx", "ui/packages/app-shell/src/layout/LocaleSwitcher.tsx", "ui/packages/app-shell/src/layout/ModeToggle.tsx", "ui/packages/app-shell/src/layout/PageHeader.tsx", "ui/packages/app-shell/src/layout/UnifiedSidebar.tsx", "ui/packages/app-shell/src/layout/__tests__/AppHeader.phoneTargets-29075.test.tsx", "ui/packages/app-shell/src/layout/__tests__/UnifiedSidebar.phoneDrawerCloses-29075.test.tsx" ], "line_budget": "under the 3000 threshold (552 changed lines at 7a92e5de, 10 files, plus a test-only lint commit); inside the amended file surface. LocalizedSidebarTrigger.tsx was in the surface and needed no edit.", "tests": "From ui/ under os-verify-lock. At 05647568: the two new files (UnifiedSidebar.phoneDrawerCloses-29075 4 tests, AppHeader.phoneTargets-29075 8 tests) exit 0, 12 passed. At 7a92e5de: the 79 existing layout/__tests__ files for AppHeader, AppSwitcher, UnifiedSidebar, PageHeader, ConsolePageHeader, InboxPopover, LocaleSwitcher (incl. AppHeader.homeMark-12605) exit 0, 512 tests; 05647568 changes only the two new test files. Ablation via scripts/ablation-replace.mjs at 05647568: 'if (isMobile) setOpenMobile(false);' -> 'if (isMobile && Date.now() < 0) setOpenMobile(false);' reds 2 of 4 (both navigation cases); restored blob == HEAD acf40396, git diff HEAD empty. turbo run type-check --filter=@object-ui/app-shell at 05647568: 65/65, exit 0. eslint on the ten files: 0 errors (2 react-hooks/globals errors and 1 unused helper in the new tests fixed in 05647568); remaining warnings pre-existing.", "gates": "dispatch-gates derived 34; 30 commands plus pnpm --dir ui exec vitest run scripts/ (169 passed / 2 skipped files) at 7a92e5de, each exit 0; the three PR-body gates on the exact body: check-changeset-no-major --base origin/main, check-adr-0087-registration --base origin/main, check-closing-keyword-parity exit 0, plus check-partof-closing-keyword exit 0. --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. check-sdui-manifest exit 0. First vitest run scripts/ was OOM-killed beside the audit servers; re-run after stopping them, green.", "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm", "mcp_calls": "mcp__github__issue_read (card body and comments); mcp__claude-code-remote__subscribe_pr_activity on #29168; no GitHub MCP write", "api_writes": "2: (1) fleet-write relay dispatch carrying one pr_create (draft, no labels, no assignees; read-back 11484 bytes sent = stored, #29168); (2) this os-dev-report comment via post-stamped. git push x2 are not REST writes.", "deviations": [ "The PR body opens with the harness-required attribution comment and Requested-by line, then Fixes #29075.", "Subscribed this session to #29168 activity (the harness requires it after a PR opens); re-runs and landing stay with the seat.", "Gates and the 79-file sweep ran at 7a92e5de; 05647568 changes only the two new test files, which were re-run with type-check and the ablation at 05647568.", "Performance was measured on the production build (pnpm console:build, backends restarted); the first Vite-dev CPU 4x numbers were discarded." ], "open_questions": [], "out_of_scope_findings": [ "carrier: #29131 · N6 Back with the phone drawer open leaves the page instead of closing the drawer (all four runs).", "carrier: #29141 · N8 drawer open at CPU 4x: app-showcase (46 entries) 294-576 ms click to first paint, over a 200 ms budget; app-crm 107-253 ms.", "carrier: seat 4 (Record) · N7 record page phone back control is a link that pushes a history entry, so Back after it reopens the record; back control 92x28 and Next 28x28.", "carrier: seat 4 (Overlay, dialog.tsx) · N9 search palette Close is 16x16.", "carrier: #29074 · list toolbar controls under 44 px at 375/390.", "carrier: #29076 · account menu notification switches 44x24.", "carrier: seat (card in its write queue) · home page body launcher links 16-32 px tall · reach: /home at 375 and 390 on both examples · dedupe words: home launcher links touch target, home page phone 44px" ] }objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Landed · 2026-11-02T10:19Z · PR #29168 merged through the merge queue as
07eaec2dat 2026-11-02T10:18Z (GitHub's clock). ACCEPT 6573218408.07eaec2d~1)origin/main)min-h-11,size-11,44px) inui/packages/app-shell/src/layout/AppHeader.tsxUnifiedSidebar.phoneDrawerCloses-29075.test.tsxexistsFixes #29075closed this card.pm:dispatchedcomes off in the same stroke as this note. #29024 (seat 3), and #29131 and #29141 (seat 4), waited on this PR and can now be ordered onorigin/main.