Repository navigation
Console home: search in the top bar, a greeting with a work summary, compact builder actions and 56 px app tiles #12601
Description
Source
Measured on objectui main 1b3b5b102, /home at 1280 px, light and dark, zh-CN, signed in as an admin with HotCRM installed (packages/app-shell/src/console/home/HomePage.tsx, HomeRail.tsx, RecentApps.tsx). The top bar has no search entry (the Studio landing has one); the hero is a 30 px greeting and the tagline "从上次离开的地方继续,或者探索新的内容。"; below it two full-width bordered cards "构建应用 / 从模板开始" take the first screen although only an admin sees them; "我的应用 2" is a row of 48 px icons where "系统设置" counts as an app; everything on the page is a bordered white card of the same weight.
Target
Sections ① and ② of the artboard "系统首页 · 四段式" (1280 × 1040), in numbers; sections ③ and ④ are the two sibling cards.
- Top bar, 48 px, grid
1fr auto 1fr: left the product mark (28 px tile on--primary, 14 px / 600 name, the existing preview chip); centre a 420 × 32 px search field "搜索应用、记录、页面…" with a⌘Kkbd that opens the console's command palette; right bell with its count, help, 28 px avatar. - Content column 1120 px centred, 28 px top padding, 28 px between sections.
- Greeting 24 px / 600 with the name in
--primary; under it one 13 px muted line that summarises the work section: "今天有 N 项待审批、M 项分配给你的任务" (both counts from the same sources the work section reads; the line reads "今天没有待办" when both are 0). - Admin actions sit at the right of the greeting as two 32 px chips: "从模板开始" outline, "构建应用" on
--primary-softwith the primary-coloured icon. The two cover cards retire; their gate reasons (objectui#5521's visible reason) move to the chips' tooltip wrapper (objectui#12303 pattern) when disabled. A non-admin sees no chips. - "我的应用" heading 15 px / 600 with a count pill; at the right "浏览应用市场" (12 px link, marketplace gated as today) and "系统设置" as a muted 12 px link with the gear icon. Setup leaves the app row.
- Tiles: 112 px wide, 56 px icon on the app's colour (14 px radius), 13 px / 500 name on one line with an ellipsis, 11 px muted "N 小时前打开" from the recent-items store; favourites first; an admin sees a trailing dashed "添加应用" tile that opens the same marketplace route.
- No bordered card around sections ① and ②.
File surface
packages/app-shell/src/console/home/HomePage.tsx, HomeRail.tsx (apps strip), RecentApps.tsx, the console top bar in packages/app-shell/src/layout/AppHeader.tsx (search entry on /home), packages/i18n/src/locales/*.ts, tests beside each.
Acceptance
- Tests: the search field opens the command palette; a non-admin renders no builder chips; a disabled chip explains itself through the tooltip wrapper; Setup is not among the tiles; a tile shows the last-opened time from the store.
- Screenshots at 1280 px, light and dark, admin and non-admin, as measurements in the PR text.
pnpm --filter @object-ui/app-shell testgreen;pnpm check:i18ngreen.
Constraints
- Existing
data-testids (home-build-app,home-start-template,home-authoring-gate-reason,home-marketplace-disabled-reason) keep their names on the new elements. - Tailwind utilities and theme tokens only.
- Lands before the two sibling cards (same file); they rebase on it.
Evidence
The artboards, as static HTML and 1280 px PNG renders, live on the temporary branch claude/console-home-login-design-20261016 of objectstack-ai/objectui (commit c4dfb417a, never merged; the maintainer ruled that design files and screenshots do not enter main). Files: Home.png · Home.html.
Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-16 review of the console login page and home page with the maintainer, on objectui main 1b3b5b102 and HotCRM 63db83e2. The maintainer approved the artboards in that session, verbatim: 「同意设计稿,创建任务」.
Activity
objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 1 (
priority:p2; sections ① and ② of the artboard "系统首页 · 四段式", approved by the maintainer in the epic PM sessionsession_cdb7a717-def7-4e71-9988-f089fbaa18ff)Session:
session_01JZnppgHRp4sREcouhkQYDBAccount:
sunhaolinBranch:
claude/issue-12601-home-top-and-appsWorktree:
objectui-issue-12601Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/app-shell/src/console/home/HomePage.tsx,HomeRail.tsx(the apps strip),RecentApps.tsx,packages/app-shell/src/layout/AppHeader.tsx(the search entry on/homeonly),packages/i18n/src/locales/*.ts, tests beside each, and one@object-ui/app-shellchangeset (plus@object-ui/i18nif touched) (stop on breach; explain in the report).Container & model:
M,mode:subagent,model: opus(default tier)Clause-②: yes
Clause-② reason:
AppHeaderandHomePageare exported from@object-ui/app-shell. A search entry shown on/homeonly may need a newAppHeaderprop, and the route is not chosen yet («拿不准 ⇒ 按 yes»). The seat'sTIER_DEFAULTreview comes before ready.Responsibility: n/a — not a defect card
Thread-read: none
Serial constraints cleared: no open PR touches
packages/app-shell/src/console/home/orpackages/app-shell/src/layout/(scanned every open objectui PR's file list), and no in-flight claim names them. Per the card's own constraint this lands before its siblings objectui#12602 and #12604 (sameHomeRail.tsx/HomePage.tsx). objectui#12605 (AppHeader.tsx) is held until this lands.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 1 · takeover of claim
6207344600(the claimant's session ran out of tokens mid-build)Release: claim
6207344600· sessionsession_01JZnppgHRp4sREcouhkQYDB· accountsunhaolin· reason: the claimant is unreachable (token exhaustion; no PR, noos-dev-report) · destination: this claim, same branch, same declarationsProvenance: the maintainer · in session
session_011K9g23W67dy2zwnyzaoB6o, the/pm-dispatch UI seat 1summons, read 2026-10-16T06:36Z · verbatim: 「前任没有token了,他的任务开发了一半你要接着处理。」Session:
session_011K9g23W67dy2zwnyzaoB6oAccount:
os-teslaBranch:
claude/issue-12601-home-top-and-appsWorktree:
objectui-issue-12601Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/app-shell/src/console/home/(the pushed tip touchesHomePage.tsx,HomeLayout.tsxandHomeAppsStrip.tsx; claim6207344600namedHomeRail.tsxandRecentApps.tsxin the same directory),packages/app-shell/src/layout/AppHeader.tsx(the search entry on/homeonly),packages/i18n/src/locales/*.ts, tests beside each, and one@object-ui/app-shellchangeset (plus@object-ui/i18nif touched) (stop on breach; explain in the report).Container & model:
M,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuiover the tip's 18 paths: no path-derived mandate)Clause-②: yes
Clause-② reason: carried unchanged from
6207344600:AppHeaderandHomePageare exported from@object-ui/app-shell, and a search entry shown on/homeonly may need a newAppHeaderprop («拿不准 ⇒ 按 yes»). The seat'sTIER_DEFAULTreview comes before ready.Responsibility: n/a — not a defect card
Thread-read: 6207344600
Serial constraints cleared: the only open objectui PR besides dependabot and the release PR is #12630 (Studio automations rail), whose files are disjoint; the in-flight branches of objectui#12603, #12611, #12612, #12617, #12620, #12621 and #12626 touch none of this surface. Per the card, this lands before its siblings objectui#12602 and #12604 (same files); objectui#12605 (
AppHeader.tsx) is held until it lands. objectui#12600 also adds keys topackages/i18n/src/locales/*.ts: ordinary concurrency.Resume-from:
claude/issue-12601-home-top-and-apps@3cc9fa19d02b6b5bd028624077b997ca5708b011Handover record. Last pushed sha
3cc9fa19d0(2026-10-16T03:51:28Z), one commit on base33fbc861d2carrying the feature, two new test files, one updated test, the changeset and the locale strings. No PR and no report exist. Everything on the branch is UNVERIFIED: the resuming dev reads the commit hunk by hunk, mergesorigin/main, re-runs every gate and the screenshots the acceptance names, and opens the draft PR.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{ "issue": 12601, "status": "done", "branch": "claude/issue-12601-home-top-and-apps", "pr": "https://github.com/objectstack-ai/objectui/pull/12638", "session": "session_011K9g23W67dy2zwnyzaoB6o", "premise_still_valid": true, "summary": "Resumed from 3cc9fa1 (dead dev, session_01JZnppgHRp4sREcouhkQYDB), merged origin/main 63d00da as f2ef2c1, read every inherited hunk against the card: all kept (HomeLayout mounts the existing CommandPalette scoped to Home's host app; AppHeader centres a 420 px home search only where a palette is mounted, no new prop; 24 px greeting + approvals summary line; two 32 px builder chips with the objectui#12303 tooltip wrapper; 1120 px column; 112 px tiles, Setup moved to a System Settings link, admin Add app tile). Missing piece added in 9aa8059: the tile's 11 px 'Opened 2 hours ago' line from the recent-items store (lastOpenedByApp: newest entry whose /apps/SEGMENT href resolves to the app via matchAppBySegment; new key home.appOpened in ten packs). efe6e9d removes the three keys the retired tagline and cover cards orphaned (home.heroTagline, home.build.subtitle, home.template.subtitle) and corrects the changeset's surface statement; 42e5761 drops a leftover blank line. Coordinator's mid-task input folded in: each of the five acceptance items has its own pin and each pin went red on ablation (table in the PR). Draft PR #12638, assignee os-tesla read back, body read back byte-identical (12475 bytes).", "tests": "At 42e5761, through os-verify-lock: `pnpm exec vitest run packages/app-shell/src/console/home/ packages/app-shell/src/layout/ packages/app-shell/src/console/__tests__/ packages/app-shell/src/__tests__/ packages/app-shell/src/chrome/ (+ views/__tests__/phase1-page-blocks.render.test.tsx, views/metadata-admin/previews/__tests__/exclusion-reason-truthfulness.test.ts) --maxWorkers=2` -> Test Files 171 passed (171), Tests 1476 passed (1476); `pnpm exec vitest run packages/i18n/` -> Test Files 83 passed (83), Tests 1321 passed | 13 skipped (1334); seven apps/console tests mounting DefaultHomeLayout/App -> Test Files 7 passed (7), Tests 277 passed (277). Ablations (source-resolved subjects, no dist; each through objectstack scripts/ablation-replace.mjs WRAP mode: anchor 1->0, blob changed, restored blob == HEAD, git diff HEAD empty; run at 9aa8059, later commits touch none of the anchors): A1 HomeLayout `{hostApp ? (`->`{false ? (` => searchOpensPalette 4 failed/1 passed (CONTROL stays green); A2 `{isAdmin && (`->`{true && (` => 'a non-admin renders no builder chips' failed (1 failed/13 passed); A3 `if (!disabled) return button;`->`return button;` => both tooltip-wrapper cases failed (2/12); A4 launcherApps=activeApps => 'Setup is not among the tiles' + last-opened case failed (2/12); A5 lastOpened={undefined} => 'a tile shows when its app was last opened' failed (1/13). H1 measured by building app-shell at HEAD and with packages/app-shell/src at 63d00da (trap restore, blob == HEAD proven): dist/index.d.ts closure 180 files both sides, same list, 2 differ (HomeLayout.d.ts, AppHeader.d.ts) in doc comments only; HomeAppsStrip.d.ts (+settingsHref, +lastOpened, optional) and new appLastOpened.d.ts are outside the closure.", "gates": "Local, hand-derived from objectui package.json + .github/workflows (objectui has no dispatch-gates.mjs), all at 42e5761, exit captured before any pipe: deps closure build `pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build` exit 0; `pnpm --filter @object-ui/i18n build` 0; `pnpm --filter @object-ui/app-shell type-check` 0 (script echoed: tsc --noEmit && tsc -p tsconfig.test.json); `pnpm --filter @object-ui/i18n type-check` 0; check:i18n-keys 0; check:i18n-drift 0 ('No en value changed in this range', 7 keys added at the earlier reading); check:i18n-dead-keys 0 (report-only; none of the new keys listed, the three removed no longer listed); check:test-path-roots 0; check:changeset-claims 0 (one read request on .changeset/11659-console-record-ux.md naming HomePage.tsx: read, still true); changeset:check 0; check-changeset-presence 0; check-changeset-overwrite 0; check-new-cross-file-line-citations 0 (0 new); check-control-bytes 0; check-vi-mock-inherit/override-shape/specifiers 0/0/0; check:unreferenced-sources 0; check:esm-specifiers 0; check:self-import 0; eslint over the 19 changed .ts/.tsx 0 (0 errors, 33 warnings of existing kinds). `pnpm check:i18n` named on the card does not exist. CI (PR #12638 check-runs at report time, head 42e5761): Changeset Bump Policy success, Changeset Fixed Group Check success, label success; in_progress: Build & E2E, Build Docs, Bundle Analysis, Changeset Claim Re-read, Changeset Declaration, Changeset Overwrite Report, Governed Surface Queue Guard, Line Citation Gate, Lint, Live E2E (informational), Repo Gates, Test (dist pins), Test (shard 1..16/16), Type Check; skipped: Test (coverage), Test (coverage shard), dependabot. NOT MEASURED locally: full app-shell package (1436 files) and full pnpm test -> CI shards; Bundle Analysis (needs full packages + console build) -> CI; screenshots -> the seat's shared browser reading.", "mcp_calls": "0", "api_writes": "2 REST writes, both through objectstack scripts/pm tools: (1) fleet relay POST /repos/objectstack-ai/objectstack/dispatches (run 38872200535, success) executing pr_create = POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/12638/assignees [os-tesla]; (2) this report: post-stamped.mjs -> POST /repos/objectstack-ai/objectui/issues/12601/comments. Zero label writes. git push x4 (merge f2ef2c1, 9aa8059, efe6e9d, 42e5761), not REST.", "open_questions": [ { "question": "The card's Target 1 asks for a 48 px top bar; Home's bar stays 56 px (h-14), the height AppShell, StudioRoute and HomeLayout all draw. Changing Home alone would make the bar jump on entering an app. Who carries the 48 px?", "options": [ "A: fold it into objectui#12605 (holds AppHeader; its AppBar artboard is 48 px too) and change all frames together", "B: a follow-up on HomeLayout only, accepting a height change between Home and apps" ], "recommendation": "A, because the height is one number across four frames and objectui#12605 already owns the bar; B buys the artboard on one route at the cost of a visible jump." } ], "out_of_scope_findings": [ "carrier: objectui#12602 (seat to fold into its scope) · noted, not filed — useSharedPendingApprovalsCount returns the value only, no read status, so the new summary line says 'Nothing is waiting for you today' while the approvals read is in flight or after it fails; HomeActionCenter's 'You're all caught up' on main treats the same count as an answer (it waits for the inbox status only). Not reproduced through a public door (no backend booted), so not a filing. objectui#12602 Target 4 needs that status anyway. Dedupe words: approvals count status, summary zero claim, all caught up approvals failure.", "carrier: the domain:ui seat for objectui#12605 · noted, not filed — Home top bar right side (help, 28 px avatar) and the search trigger's 8 px radius / 13 px label left as the shared AppHeader draws them, because AppHeader edits are limited to the /home search entry while #12605 holds the file.", "carrier: none · noted, not filed — tiles keep the launcher's per-app deterministic gradient (the artboard draws gradients too) and do not read branding.primaryColor; packages/i18n/src/__tests__/makerEmptyState-v1-scope-8329.test.ts keeps a scope comment naming the now-removed home.build.subtitle (comment only)." ], "deviations": [ "The merge commit f2ef2c1 carries no Claude-Session/Co-authored-by trailer pair (git merge -m default); not amended, since the brief forbids amend.", "Ablations ran at 9aa8059, not the final head; efe6e9d (locale keys, changeset) and 42e5761 (one blank line) touch none of the anchors or mocked t() outputs.", "Local tests narrowed from the full app-shell package to 171 files (the directories importing the changed modules plus tests naming them); declared, CI runs the rest.", "Declared file surface widened by one new file inside it: packages/app-shell/src/console/home/appLastOpened.ts (+ its test). No file outside the claim's surface was edited.", "Lock queue: ~55 min waiting behind a full app-shell package run held by objectui-issue-12616 (pid 15496, ~49 min) and two other waiters; acquired on the sixth call." ], "files_changed": "20 vs origin/main 63d00da: .changeset/12601-home-top-and-apps.md; packages/app-shell/src/console/home/{HomeAppsStrip.tsx, HomeLayout.tsx, HomePage.tsx, appLastOpened.ts (new)}; packages/app-shell/src/console/home/__tests__/{HomeLayout.searchOpensPalette-12601.test.tsx (new), HomePage.authoringCapabilityGate.test.tsx, HomePage.greetingAndApps-12601.test.tsx (new), appLastOpened-12601.test.ts (new)}; packages/app-shell/src/layout/AppHeader.tsx; packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts. +1292 / -228 (git diff --stat)." }objectstack-fleet commentedon Oct 16, 2026
REWORK round 1 → PR #12638 ·
domain:uiseat 1 ·session_011K9g23W67dy2zwnyzaoB6o· 2026-10-16T08:19ZReviewed at head
42e5761957. Accepted as reviewed: the inherited hunks, the last-opened line (9aa8059), the key removal, H1 (no widening of the entry's declaration closure), H2 (approvals only; no source onmainfor "assigned to me"), H3–H5 and the five ablations. Patch round on the same claim (6209656150), same dev, same branch:Type Checkfails atpnpm check:spec-symbols: typeAppLikeinpackages/app-shell/src/console/home/appLastOpened.ts:30is a local declaration under a name@objectstack/spec/systemowns.status(packages/app-shell/src/hooks/sharedUserFeeds.ts,SharedFeedSnapshot).packages/app-shell/src/hooks/sharedUserFeeds.ts(an internal, non-exported read of the status; the exported surface of@object-ui/app-shellstays unchanged).Moved out of this card: Target 1's 48 px bar height is now objectui#12639. The height is shared by five bars on
main, and both approved artboards draw 48 px. This card keeps everything else and still closes through PR #12638.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{ "issue": 12601, "round": 2, "status": "done", "branch": "claude/issue-12601-home-top-and-apps", "pr": "https://github.com/objectstack-ai/objectui/pull/12638", "session": "session_011K9g23W67dy2zwnyzaoB6o", "premise_still_valid": true, "summary": "Patch round 1, both items landed, head fc73410. Item 1: `pnpm check:spec-symbols` reproduced red at 42e5761 (type `AppLike` in console/home/appLastOpened.ts, exported by @objectstack/spec/system); lastOpenedByApp now takes `Parameters<typeof matchAppBySegment>[0]` (the resolver's own app-list type) and `ReadonlyArray<Pick<RecentItem, 'href' | 'visitedAt'>>`, no local shape; gate green. Item 2: the summary line speaks only when the approvals count is an answer. sharedUserFeeds.ts gains `useSharedPendingApprovals()` returning the store's SharedFeedSnapshot (not exported from the entry; `useSharedPendingApprovalsCount` now reads `.value` off it, return type unchanged, `useInboxBell` unchanged). On anything but `ready` the line keeps its height (`min-h-5`) and is EMPTY: no claim, no layout jump when the answer lands, nothing read to a screen reader. ROOT CAUSE of the CI red at 042577e (seven home test files, 'Found multiple elements'): 042577e had HomePage call the snapshot hook directly beside `useHomeInbox`; every HomePage harness mocks `useHomeInbox` and routes `fetch`, so the new direct read sent a real `/api/v1/approvals/requests` request, each file's afterEach no-escape assertion (`expected [ Array(1) ] to deeply equal []`) failed before its `cleanup()` ran, and the next case found the previous DOM still mounted. Not a double render, and not the seat's mock-factory hypothesis (those files do not mock sharedUserFeeds at all). Fix fc73410: the status travels the page's one inbox seam, `useHomeInbox` (new `pendingApprovalsStatus`, as it already returns `notificationsStatus`); HomePage reads only `useHomeInbox`; no harness weakened. The 'Nothing is waiting' text in the CI DOM dumps was those harnesses' 404 stub: the store reads a 404 (no approvals plugin) as `markUnavailable`, a ruled `ready` answer of 0. The 'Invalid time value' in the shard logs is a test TITLE in plugin-timeline (timeline-object-bound-gantt-refusal, passing), not a thrown error; the last-opened render path skips an unreadable visitedAt (pinned on HomePage now too). CI at fc73410: all 33 completed check-runs success, 3 skipped.", "tests": "At fc73410 through os-verify-lock: `pnpm exec vitest run packages/app-shell/src/console/home/ packages/app-shell/src/hooks/ packages/app-shell/src/layout/ --maxWorkers=2` -> Test Files 168 passed (168), Tests 1272 passed (1272); population control: `git ls-files` counts 168 test files in those three directories (whole directories, no selection; the seven files red in CI are in console/home/). New pins: HomePage.greetingAndApps-12601 'claims nothing while the approvals read is {in flight | failed | not asked | failed after an earlier answer}' (summary element empty, no home.summary key rendered); hooks/__tests__/useHomeInbox.approvalsStatus-12601.test.tsx (real store, stubbed fetch: loading while in flight, ready+2 on 200, error on 500, ready+0 on 404). Ablations via objectstack scripts/ablation-replace.mjs WRAP mode, restored blob == HEAD and git diff HEAD empty each: S1 HomePage `pendingApprovalsStatus !== 'ready'` -> `false` => 4 failed / 14 passed (the four no-claim cases); S2 useHomeInbox drops `pendingApprovalsStatus,` from its return => 4 failed (4). S2's FIRST attempt was a no-op: the replacement text already occurred once, so the tool saw the replacement count stay x1 -> x1, ran nothing and restored; rerun with a unique replacement, result above. item 1 reproduce: `pnpm check:spec-symbols` EXIT=1 at 42e5761 ('a spec-named symbol is hand-written, not derived: type AppLike'), EXIT=0 at 042577e and fc73410.", "gates": "Local at fc73410, exit captured before any pipe. Type Check job steps after check:spec-symbols (ci.yml order): check:spec-symbols 0, check:action-forward-parity 0, check:designer-field-key-parity 0, check:icon-record-names 0, check:i18n-keys 0, check:i18n-drift 0, check:i18n-designer-parity 0, type-check:scripts 0, type-check:vitest-config 0, scope selector `select-type-check-scope.mjs --base 63d00da` -> scope=affected (35 packages), `turbo run type-check --filter='...[63d00da]' --concurrency=2` 0 (Tasks: 70 successful, 70 total; 28 cached), root builds (components, fields, i18n, plugin-dashboard, plugin-grid) 0, type-check:vitest-setup 0. Steps before it re-run because app-shell changed again: check-type-check-coverage 0, check:phantom-deps 0, check:self-import 0, check:unreferenced-sources 0, check:doc-example-readers 0, check:handler-key-reads 0, check:metadata-write-doors 0, check:published-tsconfig-exclude 0, check:side-effects-array 0, check:element-data-source-declaration 0, check:esm-specifiers 0. Also: `pnpm --filter @object-ui/app-shell type-check` 0, check:i18n-dead-keys 0, vi-mock inherit/override-shape/specifiers 0/0/0, check:test-path-roots 0, check-new-cross-file-line-citations 0, check-control-bytes 0, check:changeset-claims 0, check-changeset-presence 0, changeset:check 0, eslint over the 23 changed .ts/.tsx 0 (0 errors, 34 warnings: the one more than round 1 is a pre-existing `any` in HomeActionCenter.unansweredInbox.test.tsx, newly linted because it is now in the diff). No locale file changed in round 2. CI at fc73410 (PR #12638 check-runs): 33 success (Build & E2E, Build Docs, Bundle Analysis, Changeset Bump Policy, Changeset Claim Re-read, Changeset Declaration, Changeset Fixed Group Check, Changeset Overwrite Report, Governed Surface Queue Guard, Line Citation Gate, Lint, Live E2E (informational), Repo Gates, Test, Test (dist pins), Test (shard 1..16/16), Type Check, label), 3 skipped (coverage x2, dependabot).", "mcp_calls": "2 — mcp__github__get_job_logs x2 (read-only: shard 5/16 and 14/16 job logs at 042577e, to root-cause; the REST log download is refused by the proxy's blob-storage policy). No MCP write.", "api_writes": "1 REST write this round: this report via post-stamped.mjs -> POST /repos/objectstack-ai/objectui/issues/12601/comments (fleet relay). git push x2 (042577e, fc73410), not REST. No PR body PATCH, no label write.", "open_questions": [ { "question": "The patch note says the line must not claim 'nothing waiting' 'when the endpoint is unavailable'. A 404 (no approvals plugin) is, in the shared store's ruled vocabulary (#4235/#4300), `markUnavailable` = a `ready` answer of 0, so the line DOES say 'Nothing is waiting for you today' there; 5xx/403/network failures are `error` and the line is empty. Is that the reading the seat wants?", "options": [ "A: keep it — a deployment without approvals has none waiting; the store's ruled 'missing resource is an answer' reading holds (no further change)", "B: no claim on a 404 either — needs the store to expose `unavailable` beside `status` (a new store field), which the store's #4235 doctrine argues against" ], "recommendation": "A, because the line only names approvals and a deployment with no approvals plugin genuinely has none waiting; B adds a second dialect to the one status vocabulary the store was ruled to speak." } ], "out_of_scope_findings": [], "deviations": [ "File surface widened beyond the seat's grant: `packages/app-shell/src/hooks/useHomeInbox.ts` (additive `pendingApprovalsStatus` on the non-exported HomeInboxData; it now reads the snapshot hook) and its new test `hooks/__tests__/useHomeInbox.approvalsStatus-12601.test.tsx`; plus a one-mock change in `console/home/__tests__/HomeActionCenter.unansweredInbox.test.tsx` (its approvals dial moves from the count hook to the snapshot hook that useHomeInbox now reads). Reason: the root-cause fix for the CI red is one inbox seam for the page; the in-grant alternative (HomePage reading the snapshot hook directly) would have needed a second mock added to seven HomePage harnesses and every future one.", "The worktree was removed after round 1 and recreated for this round from the local branch at 42e5761 == origin; deps rebuilt (`turbo run build --filter='@object-ui/app-shell^...'`). No main merge (no conflict, no main-caused red).", "Ablation S2's first attempt was a refused no-op (replacement text not unique); rerun recorded in tests." ], "files_changed": "Round 2 (42e5761..fc73410, 2 commits): .changeset/12601-home-top-and-apps.md (ready-only line stated); packages/app-shell/src/console/home/{HomePage.tsx, appLastOpened.ts}; packages/app-shell/src/console/home/__tests__/{HomePage.greetingAndApps-12601.test.tsx, HomeActionCenter.unansweredInbox.test.tsx}; packages/app-shell/src/hooks/{sharedUserFeeds.ts, useHomeInbox.ts}; packages/app-shell/src/hooks/__tests__/useHomeInbox.approvalsStatus-12601.test.tsx (new). PR total vs 63d00da: 24 files." }objectstack-fleet commentedon Oct 16, 2026
REWORK round 2 → PR #12638 ·
domain:uiseat 1 ·session_011K9g23W67dy2zwnyzaoB6o· 2026-10-16T09:03ZReviewed round 2 at head
fc73410a8a.Accepted:
check:spec-symbolsgreen, and the summary line now speaks only onready.cleanup()never ran. The fix routes the status throughuseHomeInbox.fc73410: 33 success, 3 skipped.readyanswer of 0, so "Nothing is waiting for you today" stands there.packages/app-shell/src/hooks/useHomeInbox.ts(additivependingApprovalsStatuson the non-exportedHomeInboxData), its new test, and one mock inconsole/home/__tests__/HomeActionCenter.unansweredInbox.test.tsx. This adds to the widening recorded at the round-1 REWORK (sharedUserFeeds.ts). Nothing is exported from@object-ui/app-shell's entry.Live Home reading (cloud reading session
session_01CQVvdrcshAD3iT7azpF5NT; BEFOREmain8ed7e5a8fb, AFTERfc73410; PNGs atclaude/issue-12616-evidencea261e30,evidence/12601/):--primary.GET /api/v1/approvals/requests?status=pending(3). While loading, the line is empty and never says "Nothing is waiting".Not measured live: the admin-gated chips, the Browse marketplace / System Settings links and the Add app tile. On this published-package stack the seeded admin's session reads
role=user,isPlatformAdmin=falseand member rolemember, so no account sees them. Their unit pins and ablations stand as the evidence.Patch round 2 (the last before escalation):
Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{ "issue": 12601, "round": 3, "status": "done", "branch": "claude/issue-12601-home-top-and-apps", "pr": "https://github.com/objectstack-ai/objectui/pull/12638", "session": "session_011K9g23W67dy2zwnyzaoB6o", "premise_still_valid": true, "summary": "Patch round 2, both items landed, head 70bfa2f (commits 6c037e4, 3b80fed, 70bfa2f). Item 1, the tile line: it is now drawn in Intl's compact form, `TILE_OPENED_TIME_FORMAT = { style: 'short', numeric: 'always' }` (en '6 sec. ago', '3 hr. ago', '2 days ago'; zh '6秒前打开', '3小时前打开', '2天前打开'), through each pack's `home.appOpened`, which keeps a verb only where verb and time fit: zh, ko, ar unchanged; ja changed to the time plus 'に起動'; en, de, fr, es, pt, ru are the time alone. Tile stays 112 px, font stays 11 px, no ellipsis. Measured (Chromium, 11 px, this container): the old 'Opened 6 seconds ago' is 118.6 px in Inter against 96 px of text room; every pack's new line, 6 s to 12 y, measures at most 87.0 px (Inter) / 88.2 px (DejaVu Sans, the widest fallback), worst 'فُتح قبل سنة واحدة'. Mechanism: `formatRelativeTime` (@object-ui/i18n) and `timeAgo` (app-shell) take an optional `{ style, numeric }` passed to `Intl.RelativeTimeFormat` unchanged (default output unchanged), so one helper keeps the unit thresholds. Four axes: real need — measured truncation, live and here; long-term — Intl's own options through the one formatter, no second hand-rolled unit table, and the per-pack verb is an ordinary translation decision; AI-error-proofing — every pack's line is held to a derived budget, so a pack that re-adds a verb that does not fit goes red (ablation T2); startup scope — one optional argument, no new key, no tooltip. Why not `narrow`: fr and ru narrow read '-6 s' / '-59 мин'. Why `numeric: 'always'`: the auto phrases ('le mois dernier', 'l’année dernière', Arabic 'last year') are the longest any pack produces; the cost is zh '1天前打开' where the artboard illustrates '昨天打开' (same information). Item 2, the changeset's Greeting bullet now says the count comes from the shared pending-approvals read, the same read the bell uses for the approvals part of its badge, and that the badge adds the unread notification topics, so the two numbers can differ; the Apps bullet and the i18n surface sentence (formatRelativeTime's new optional argument) were corrected in the same pass, each sentence checked against the code.", "tests": "At 70bfa2f through os-verify-lock: `pnpm exec vitest run packages/app-shell/src/console/home/ packages/app-shell/src/hooks/ packages/app-shell/src/layout/ packages/i18n/ --maxWorkers=2` -> Test Files 252 passed (252), Tests 2596 passed | 13 skipped (2609); population control: `git ls-files` counts 252 test files in those four directories (whole directories). New pin `console/home/__tests__/appTileOpenedLine-12601.test.ts`: (1) every one of the ten packs' lines for 14 points (6 s, 45 s, 5 min, 59 min, 3 h, 23 h, 1 d, 2 d, 6 d, 29 d, 1 mo, 11 mo, 1 y, 12 y) within a 93 px budget; (2) en and zh exact at 6 s, 5 min, 3 h, 2 d; (3) CONTROL: the old 'Opened 6 seconds ago' is over budget. Budget derivation (stated in the test): `w-28` 112 px minus `px-2` 2 x 8 px = 96 px of text at 11 px; width estimated per character in em (Han/kana/Hangul/full-width 1.0, space 0.32, Arabic letter 0.53, combining mark 0, any other 0.62), calibrated against Chromium measurements in Inter and DejaVu Sans; over the final 140 lines the estimate fell short of a measured width by at most 2.4 px, so 3 px are reserved: 96 - 3 = 93 px; the estimate's largest final line is 92.2 px. Ablations via objectstack scripts/ablation-replace.mjs WRAP mode at 6c037e4, each restored to blob == HEAD with git diff HEAD empty: T1 `TILE_OPENED_TIME_FORMAT` style 'short' -> 'long' => budget and en/zh cases fail (2 failed / 1 passed; de, fr, es, ru lines over budget, e.g. fr 'il y a 45 secondes' about 109.6 px); T2 en `home.appOpened` back to 'Opened ' plus the time hole => both fail (en 'Opened 45 sec. ago' about 112.9 px). The later commits (3b80fed escape spelling of the same regex, 70bfa2f an allowlist entry) touch neither anchor. The greeting test's tile case now expects '2 hr. ago'.", "gates": "Local at 70bfa2f (exit captured before any pipe): `pnpm exec turbo run build --filter='@object-ui/app-shell^...'` 0 (at 6c037e4, rebuilding i18n with the new argument); `pnpm --filter @object-ui/app-shell type-check` 0; `pnpm --filter @object-ui/i18n type-check` 0; check:i18n-keys 0, check:i18n-drift 0 ('0 en value(s) changed (7 key(s) added, 3 removed)' against merge-base 63d00da; the en value change is inside a key this branch adds), check:i18n-dead-keys 0, check:i18n-designer-parity 0, check:changeset-claims 0, check:spec-symbols 0, check-changeset-presence 0, changeset:check 0, vi-mock inherit/override-shape/specifiers 0/0/0, check:test-path-roots 0, check:unreferenced-sources 0, check:esm-specifiers 0, check-new-cross-file-line-citations 0, check-control-bytes 0; eslint over the 27 changed .ts/.tsx: exit 0, 0 errors, 34 warnings (existing kinds). eslint first read 1 error at 6c037e4 (`no-irregular-whitespace`: the pin's CJK ranges had been written as raw characters, U+3000 among them); fixed in 3b80fed. CI at 70bfa2f at report time: 16 completed success, 3 skipped, 16 in_progress (reported as is; not waited on). At 6c037e4 the aggregate 'Test' failed: `untranslated-identity-4376` flagged ru's bare time hole, fixed in 70bfa2f.", "mcp_calls": "0 this round.", "api_writes": "1 REST write this round: this report via post-stamped.mjs -> POST /repos/objectstack-ai/objectui/issues/12601/comments (fleet relay). git push x3 (6c037e4, 3b80fed, 70bfa2f), not REST. No PR body PATCH, no label write.", "pr_body_changes_for_the_seat": [ "Opening paragraph and 'What the tile's time reads': the line is the locale's compact relative time ('2 hr. ago', zh '2小时前打开'), `TILE_OPENED_TIME_FORMAT` = short/always, verb only where it fits; replace 'Opened 2 hours ago'.", "H1: the @object-ui/i18n half now also has `formatRelativeTime`'s optional third argument `{ style, numeric }` (default output unchanged).", "H2 / Acceptance notes: the 'summary's zero claim' note is obsolete — fixed in round 2 (line empty unless the approvals read is `ready`; a 404 is the store's ready 0, ruled A).", "Verification table: the readings above at 70bfa2f replace the 42e5761 ones; the ablation table gains S1/S2 (round 2) and T1/T2 (round 3)." ], "open_questions": [], "out_of_scope_findings": [], "deviations": [ "File surface widened again, additively: `packages/i18n/src/utils/formatting.ts` (optional `options` on formatRelativeTime), `packages/app-shell/src/utils/relativeTime.ts` (timeAgo passes it), and `packages/i18n/src/__tests__/untranslated-identity-4376.test.ts` (one LEGITIMATE_IDENTITIES entry for `home.appOpened`, the remedy that test names for a pure format string, as `grid.summary.pattern`). Reason: one relative-time formatter instead of a second unit table in console/home.", "zh reads '1天前打开' for a day ago where the artboard illustrates '昨天打开' (numeric 'always'; see summary).", "en, de, fr, es, pt, ru tile lines carry the time without a verb: measured, no verb-plus-time form fits those packs in 96 px.", "Rounds 1 and 2 reported eslint 'EXIT=0' from an `echo` whose own command substitution ran before `$?` was read, so those exit codes were not eslint's; their logs printed '0 errors', so the verdict stands. This round's eslint exit is captured into a variable first.", "The worktree was recreated for this round from the branch at fc73410 == origin and will be removed after this report." ], "files_changed": "Round 3 (fc73410..70bfa2f, 3 commits): .changeset/12601-home-top-and-apps.md; packages/app-shell/src/console/home/{HomeAppsStrip.tsx, appLastOpened.ts}; packages/app-shell/src/console/home/__tests__/{HomePage.greetingAndApps-12601.test.tsx, appTileOpenedLine-12601.test.ts (new)}; packages/app-shell/src/utils/relativeTime.ts; packages/i18n/src/utils/formatting.ts; packages/i18n/src/locales/{en,de,fr,es,pt,ru,ja}.ts; packages/i18n/src/__tests__/untranslated-identity-4376.test.ts." }objectstack-fleet commentedon Oct 16, 2026
ACCEPT → PR #12638 comment 6212643098 · contract review
6212627233(TIER_DEFAULTPASS) ·domain:uiseat 1 ·session_011K9g23W67dy2zwnyzaoB6o· 2026-10-16T09:39ZGenerated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Landed ·
domain:uiseat 1 ·session_011K9g23W67dy2zwnyzaoB6o· 2026-10-16T09:53Zmain6c4d00d. Its one parent is8ed7e5a8fb(objectui#12600's landing), and it is an ancestor oforigin/main.63d00dato the reviewed head70bfa2fe3d, line for line (1498 changed lines, 0 missing, 0 extra). The ten locale packs differ from the head's blobs only because the queue merged them over objectui#12600's locale changes. Positive controls:TILE_OPENED_TIME_FORMATinHomeAppsStrip.tsxandhome.appOpenedin the en and zh packs are present onorigin/main.completedbyFixes #12601. This note precedes the strip ofpm:dispatched.Generated by Claude Code