Repository navigation
Console top bar: 48 px on Home, inside an app and on the organization pages, as both approved artboards draw it #12639
Description
Carries Target 1's bar height (48 px) from objectui#12601; objectui#12601 keeps everything else and lands through PR #12638, which leaves the bar at 56 px on purpose.
Source
objectui#12601's Target 1 asks for a 48 px top bar on /home. The bar height is not Home's alone: on objectui main (read at 63d00da) the same sticky header class with h-14 (56 px) is drawn by
packages/layout/src/AppShell.tsx:302(inside every app),packages/app-shell/src/console/home/HomeLayout.tsx:54(Home),packages/app-shell/src/console/organizations/OrganizationsLayout.tsx:28andorganizations/manage/OrganizationLayout.tsx:82,packages/app-shell/src/console/ai/AiChatPage.tsx:1350.
Changing Home alone makes the bar jump on the way into an app, so PR #12638 kept 56 px and named the gap in its Acceptance notes. Both approved artboards draw the bar at 48 px: Home.html and AppBar.html on the temporary design branch claude/console-home-login-design-20261016 (commit c4dfb417a) each carry header style="height:48px".
Target
- Every console top bar listed above is 48 px (
h-12), one value, so the bar does not move between Home, an app and the organization pages. - Nothing that offsets from the bar's height is left at 56 px: sticky sub-headers,
top-14offsets,calc(100vh - 3.5rem)heights and similar. Census them on the tree (they may use other spellings) and state each one in the PR. - The bar's contents still fit at 48 px: the product mark, the app pill, the preview chip, the search field, the bell, help and the avatar (the artboards draw 28–32 px controls).
File surface
The five files above and every offset the census of Target 2 finds; tests beside; changesets for @object-ui/layout and @object-ui/app-shell.
Acceptance
- A test pins the shared height on every listed bar, so a sixth bar or a revert to
h-14fails. - Screenshots at 1280 px of Home, an app and an organization page, as measurements in the PR text (the files stay out of main).
pnpm exec vitest run packages/layout/ packages/app-shell/green.
Constraints
- Lands after PR feat(app-shell): Home's top bar searches, the greeting sums up approvals, compact builder chips and 56 px app tiles that say when they were last opened (objectui#12601) #12638 (objectui#12601 edits
HomeLayout.tsx) and coordinates with objectui#12605 (seat 2, in flight, the app bar's left group inAppHeader.tsx): whichever lands second mergesmain. - Tailwind utilities and theme tokens only.
Dedupe: objectui issues updated since 2026-10-01, state=all (208 cards), titles and bodies matched for 48 px, top bar, app bar, bar height, h-14, h-12: 16 hits, none asks for the console bar's height (objectui#12447 and #12459 are Studio's own 48 px shell header, closed; objectui#12605 is the app bar's left group). Positive control: objectui#12605 is in the corpus and matched.
Filed by the domain:ui seat 1 PM, session session_011K9g23W67dy2zwnyzaoB6o, from the review of PR #12638 (objectui#12601's dev raised it as an open question). The design it implements is the one the maintainer approved in the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff, verbatim: 「同意设计稿,创建任务」.
Activity
objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 1 (
priority:p2; carries objectui#12601's Target 1 bar height; filed by this seat at its review of PR #12638)Session:
session_011K9g23W67dy2zwnyzaoB6oAccount:
os-teslaBranch:
claude/issue-12639-console-bar-48Worktree:
objectui-issue-12639Domain:
domain:uiSeat:
domain:ui#1File surface: the console top bars' height class, in
packages/layout/src/AppShell.tsx,packages/app-shell/src/console/home/HomeLayout.tsx(the header row only),packages/app-shell/src/console/organizations/OrganizationsLayout.tsx,organizations/manage/OrganizationLayout.tsxandpackages/app-shell/src/console/ai/AiChatPage.tsx; every offset the census finds that depends on the 56 px height; tests beside each; changesets for@object-ui/layoutand@object-ui/app-shell(stop on breach; explain in the report).Container & model:
S,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuiover the planned paths: no path-derived mandate)Clause-②: no
Responsibility: n/a — not a defect card
Thread-read: none
Serial constraints cleared: objectui#12601 landed at
main6c4d00d. objectui#12605 (seat 2) and objectui#12615 (seat 3) editAppHeader.tsx's left group and its Edit-app pencil, not the bar containers named here; the later lander mergesmain. objectui#12602 (this seat) touchesHomeRail.tsxandHomePage.tsx, notHomeLayout.tsx's header.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{
"issue": 12639,
"status": "done",
"branch": "claude/issue-12639-console-bar-48",
"pr": "#12657",
"session": "session_011K9g23W67dy2zwnyzaoB6o",
"premise_still_valid": true,
"summary": "Every console frame now draws its top bar at 48 px (h-12). There are six frames, not five: the census also found the /studio landing (StudioLanding in apps/console/src/components/StudioRoute.tsx). Studio's package builder header (STUDIO_HEADER, sm:h-12) was already 48 px and is unchanged. CONSOLE_TOP_BAR is one internal app-shell module, packages/app-shell/src/layout/consoleTopBar.ts, not exported from the package entry. HomeLayout, OrganizationsLayout, OrganizationLayout and AiChatPage read it. @object-ui/layout's AppShell (upstream of app-shell) and the console's /studio landing keep a literal that the pin holds equal to it, so no export was added and Clause-② stays no as claimed. This departs from the dispatch's preferred route of one constant read by every frame; open_questions gives the trade-off. H2: one offset depended on the 56 px bar, UnifiedSidebar's fixed desktop column (!top-14 !h-[calc(100svh-3.5rem)]). It is now CONSOLE_BELOW_TOP_BAR (!top-12 !h-[calc(100svh-3rem)]), defined beside the bar. Every other candidate is listed in the PR with its decision. H3: every control on the bar is 32 px or shorter and the bar has no vertical padding, so all of them fit. Beyond the claim's five files, the diff also touches StudioRoute.tsx, the new consoleTopBar.ts, the two docs pages that stated h-14 (content/docs/guide/layout.md, content/docs/layout/app-shell.mdx) and the layout guide pin that held h-14. One changeset covers @object-ui/layout, @object-ui/app-shell and @object-ui/console (all minor). The card's assignee is os-tesla and was not touched.",
"tests": "Pin: packages/app-shell/src/layout/tests/consoleTopBar.height-12639.test.ts, a source scan with 12 cases. It checks the height, the offset derived from h-N, a census of every source that mounts AppHeader across the workspace packages depending on @object-ui/app-shell (derived from package.json) plus packages/layout/src, each frame's header, no copy of the bar's sticky top-0 z-30 signature, and no 56 px offset. Positive controls are included. Run on 42985bd: pnpm exec vitest run over the pin and packages/layout/src/tests/guide-layout-sidebar-nav-doc.test.ts gave Test Files 2 passed (2), Tests 26 passed (26). Whole touched directories on 42985bd: pnpm exec vitest run packages/layout/ packages/app-shell/ apps/console/ --maxWorkers=2, through the lock, gave VERDICT command-exit 0, Test Files 1693 passed | 1 skipped (1694), Tests 16235 passed | 9 skipped (16244). Ablation, five legs through objectstack scripts/ablation-replace.mjs in wrap mode, each with the anchor count proven on disk and a restore proven by blob == HEAD and an empty git diff HEAD: (1) OrganizationsLayout reverted to the 56 px literal: 2 red (its frame case, the no-copy case). (2) AppShell literal h-12 to h-14: 2 red (the ConsoleLayout frame case, the layout guide pin). (3) CONSOLE_TOP_BAR h-12 to h-14: 4 red (height, offset, ConsoleLayout frame, /studio frame). (4) AppHeader planted in PreviewBadge.tsx: 1 red (the seventh-frame case). The first attempt was a no-op because the replacement contained its own anchor; the tool refused it with exit 1 and restored the file, and the leg was redone with a non-overlapping anchor. (5) UnifiedSidebar reverted to !top-14 !h-[calc(100svh-3.5rem)]: 2 red (offset, no-56-px-offset). The pin reads source and imports the token through a relative src path, so no dist sits in its resolution path and no rebuild was needed between legs.",
"gates": "Local, all on 42985bd, exit codes captured before any pipe: closure build turbo run build --filter='@object-ui/console^...' --concurrency=2 (the union closure of all three touched packages), through the lock: exit 0, 34/34 tasks; pnpm --filter @object-ui/layout type-check: exit 0; pnpm --filter @object-ui/app-shell type-check: exit 0 (tsc --listFilesOnly on its tsconfig.test.json lists the new test and module); pnpm --filter @object-ui/console type-check: exit 0; pnpm check:changeset-claims, pnpm changeset:check, pnpm check:test-path-roots, pnpm check:spec-symbols, node scripts/check-changeset-presence.mjs and pnpm check:new-line-citations: exit 0 each; eslint --no-inline-config on the 10 changed .ts/.tsx files: exit 0, 0 errors (44 warnings, all on lines this diff does not touch); node scripts/check-governed-queue-guard.mjs --test over the 13 changed paths: NOT GOVERNED. The gate list was derived by hand from the dispatch and objectui's package.json; objectui has no dispatch-gates.mjs, so there is no --ran reconciliation. Cost of the whole-directory vitest run: it held the shared verify lock for 3883 s (1h04m43s), and the lock tool flags a hold that long as holder-side starvation. CI: PR check-runs on head 42985bd when this report was written: 35 total, 29 in_progress, 3 success, 3 skipped, none failing. Convergence belongs to the seat.",
"mcp_calls": "0",
"api_writes": "2 REST writes, plus 2 git pushes, which are not REST. (1) pr_create through the fleet relay: POST /repos/objectstack-ai/objectstack/dispatches, which the relay ran as POST /repos/objectstack-ai/objectui/pulls (draft, PR #12657) and POST /repos//issues/12657/assignees ["os-tesla"]. (2) This os-dev-report comment through post-stamped, also by the relay: POST /repos/objectstack-ai/objectstack/dispatches, which the relay ran as POST /repos//issues/12639/comments. Zero label writes, zero PATCH.",
"open_questions": [
{
"question": "Should the console bar class become a public export, so all six frames read one constant (the dispatch's preferred route), instead of an internal app-shell constant plus two literals held equal by the pin?",
"options": [
"A: export the constant from @object-ui/layout (upstream of app-shell and the console) and have all six frames read it. Clause-② turns yes, because a published package gains a symbol only first-party code reads, and later changes to that symbol become a semver question. The work is small: a 6-file follow-up.",
"B: keep this PR as it is. One internal app-shell constant serves four frames, and the layout AppShell and /studio landing keep literals that the census pin holds character-equal to it. Clause-② stays no."
],
"recommendation": "B. The four axes: (1) Real need: both options give one 48 px bar; only first-party frames read the class, and no external consumer pulls for the constant. (2) Long-term fit: the pin, not the constant, is what stops a seventh frame drifting, because nothing forces a new frame to import a constant, while the census of AppHeader mounts and of the bar signature fails it either way. (3) Preventing AI mistakes: the census turns red on a copy or a new frame with a message that names CONSOLE_TOP_BAR, which guards at least as well as an import. (4) Startup no-sprawl: a published export with no pull is the surface growth the frame defaults against."
}
],
"out_of_scope_findings": [
"carrier: none · noted, not filed · @object-ui/runner LayoutRenderer draws its own h-14 header and the header-bar schema block is h-14 sm:h-16. Neither is a console frame, and both are recorded in the PR census as unchanged.",
"carrier: domain:ui seat 1 PM · noted, not filed · the dispatch's whole-touched-directory vitest run for packages/app-shell held the shared verify lock for 1h04m43s on this 4-core box (1694 files at maxWorkers=2). CI shards the same files 16 ways. Dedupe words: verify lock starvation, whole-directory vitest, app-shell test duration."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
ACCEPT → PR #12657 comment 6216047784 ·
Clause-②: no· live 1280 px reading atclaude/issue-12639-evidence1ddb420f1a·domain:uiseat 1 ·session_011K9g23W67dy2zwnyzaoB6o· 2026-10-16T13:00ZGenerated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Landed ·
domain:uiseat 1 ·session_011K9g23W67dy2zwnyzaoB6o· 2026-10-16T13:13Zmaindcd1041024, with one parent,4be76e0306. It is an ancestor oforigin/main.42985bd75c, line for line: 13 files, +310/−17. Positive control:consoleTopBar.tsat the merge commit carriesh-12.completedbyFixes #12639. This note precedes the strip ofpm:dispatched. The live 1280 px reading is atclaude/issue-12639-evidence1ddb420f1a.mdwere not read live.Generated by Claude Code