Skip to content

observation: UnifiedSidebar 的 nav-order/pin 存储键在 home 上下文解析成「第一个 app」,|| 'home' 兜底实际不可达 #3631

Closed as not planned

Description

@yinlianghui

越界发现,记录于 #3609 / PR #3630(把 /home 的 Administration 组改由 NavigationRenderer 渲染)期间。按纪律只报不改,单独立单,未认领。

观察类(observation-class):今天没有用户会碰到,是休眠代码 + 一处不可达兜底。标 finding,不入队,留给 PM 分诊定级。

实测基线:origin/main @ 8d5418e59。

观察

packages/app-shell/src/layout/UnifiedSidebar.tsx:

const activeApp = matchAppBySegment(apps.filter(a => a.active !== false), activeAppName || currentAppName) || activeApps[0];
…
const { applyOrder, handleReorder } = useNavOrder(activeApp?.name || 'home');

useNavOrder(appName) 把顺序存进 objectui-nav-order-${appName}。两点:

  1. || 'home' 这个兜底不可达(对结果的消费者而言)。 applyOrder/applyPins 的产物只经 processedNavigation 流向 app 分支的 NavigationRenderer。而 app 分支的渲染条件正是 context === 'app' && activeApp —— activeApp 为空时这条分支根本不渲染。所以凡是用到排序结果的时刻,activeApp?.name 必然有值,字面量 'home' 永远不会成为存储键。它读起来像「home 上下文有自己的一套排序」,其实没有。

  2. 真要用起来,键是错的。 home 上下文里 activeApp 会解析成 activeApps[0] —— 部署里第一个 app,而不是 home。所以一旦有人给 home 分支接上 enablePinning / enableReorder(PR fix(app-shell): /home 的 Administration 组改由 NavigationRenderer 渲染,9 个系统管理入口恢复可达 (#3609) #3630 特意没有接,理由写在调用点注释里),home 导航就会去吃那个 app 存下的 __root__ 根排序;换个 app 排到第一位,home 侧栏的顺序跟着变。

换句话说:当前是「不可达的兜底」,接通之后是「跨上下文串键」。两种状态都不对,只是前者没有症状。

为什么现在只记录

/home 的导航是内建的固定簇(Home / Documentation + 管理员的 9 项 Administration 组),不是用户可编排的元数据;要不要让它可拖排、可 pin,是独立的产品决定,不属于 #3609「把组展开」的范围。#3630 因此维持现状并把理由写进注释,避免下一个人以为是遗漏而顺手接上。

可能的方向(留给分诊)

  • 若结论是 home 导航不该可排序/可 pin:把 useNavOrder(...) 的调用挪进只有 app 分支才求值的位置,删掉误导性的 || 'home',让「app 专属」在代码里显形;
  • 若结论是该可排序:存储键必须按上下文取(context === 'app' ? activeApp?.name : 'home'),而不是按 activeApp,否则就是上面第 2 条。

关联

已就关键词(useNavOrder / objectui-nav-order / UnifiedSidebar + storage key / sidebar nav order pin)搜过本仓开放 issue 与 PR,无同源单。


Generated by Claude Code

Activity

  1. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Findings triage (#4949 discipline) — first grading of this card. Verdict: HOLD. finding retained.

    Stale-premise check — re-measured on origin/main (0cf8f0f) from the fetched ref, not the shared worktree. The card was filed against 8d5418e59 and both halves still hold:

    • packages/app-shell/src/layout/UnifiedSidebar.tsx:201 — const { applyOrder, handleReorder } = useNavOrder(activeApp?.name || 'home'); — present verbatim;
    • the app-branch render condition context === 'app' && activeApp is at :452, with the same pairing at :370 / :371, so the unreachability argument is intact: every consumer of the ordering result is inside a branch that requires activeApp to be truthy, therefore the 'home' literal can never become a storage key;
    • enablePinning={!isMobile} sits at :524, inside that same app branch — the home branch still does not wire it, as fix(app-shell): /home 的 Administration 组改由 NavigationRenderer 渲染,9 个系统管理入口恢复可达 (#3609) #3630 intended;
    • and the reasoning survives in-tree at :638 / :644, where the comment quotes both useNavOrder(activeApp?.name || 'home') and the branch condition. That comment is the reason this card is a finding rather than a trap: the next reader is warned in the file itself.

    Why hold rather than promote. The card's two repair directions are not two ways to do one thing — they are the two outcomes of an unmade product decision (should /home navigation be user-reorderable and pinnable at all?), and they point in opposite directions in the same file. Direction 1 deletes the fallback and moves the hook inside the app branch; direction 2 keeps it and makes the key context-derived (context === 'app' ? activeApp?.name : 'home'). Queueing this today would hand a dev a card whose acceptance criteria depend on an answer nobody has given, and the tempting "just delete the dead fallback" reading is the one that quietly forecloses direction 2.

    Why not needs-user-decision either. Nothing is broken and nothing is asked of the maintainer yet: today's state is symptom-free dormant code behind an accurate comment. Escalating a question whose answer only matters if someone decides to build the feature would put a null decision in the inbox. The moment that changes is written into the restart conditions.

    Why not close as not-planned. The second half is a real latent defect, not cosmetics: in the home context activeApp resolves to activeApps[0] — whichever app happens to sort first in the deployment — so wiring pin/reorder onto the home branch makes home navigation read and write another app's __root__ ordering, and re-ordering the app list silently changes the home sidebar. That is cross-context key bleed with a user-visible symptom, and it is one line of wiring away.

    Restart conditions — any one promotes this to pm:queue:

    1. Anyone wires enablePinning / enableReorder onto the home branch — at that instant the dormant bug becomes live, and the storage key must be fixed in the same PR, not after it. This is the condition to watch: it is a one-line change that looks like an obvious omission, which is exactly why fix(app-shell): /home 的 Administration 组改由 NavigationRenderer 渲染,9 个系统管理入口恢复可达 (#3609) #3630 left a comment at :638–:644 instead of a silence.
    2. A ruling that home navigation stays fixed (not user-orderable) — then direction 1 is unambiguous and this promotes as a small cleanup: move useNavOrder(...) where only the app branch evaluates it and drop the misleading || 'home', so "app-only" is visible in the code rather than only in a comment.
    3. A second context gains a sidebar with the same hook shape — the bug generalises beyond home and the ceiling argument for holding disappears.

    No domain:* — objectui is a whole-repo seat. Not a transfer: single file in packages/app-shell, no packages/spec face, not cross-repo.

    Dedup — this repo and both siblings, open issues and PRs, on useNavOrder, objectui-nav-order, UnifiedSidebar storage key, sidebar nav order / pin. No duplicate; #3609 / PR #3630 is the discovery site and the only related card.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. os-zhuang commented on Aug 9, 2026

    @os-zhuang
    Contributor

    Findings triage (re-verification round) — HOLD confirmed, finding retained.

    Premise re-checked on origin/main @ cdc0e44: useNavOrder(activeApp?.name || 'home') still at packages/app-shell/src/layout/UnifiedSidebar.tsx:201; enablePinning={!isMobile} has drifted to :534 but remains inside the context === 'app' && activeApp branch (conditional read in context) — the home branch is still not wired, exactly as PR #3630 intended, and the warning comment survives at :653-654. None of the three restart conditions has fired (no home-branch wiring, no fixed-navigation ruling, no second sidebar context). Hold stands unchanged.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  3. claude commented on Aug 10, 2026

    @claude
    Contributor

    Triage (findings pass): held, premise re-verified on origin/main @ c29ceff — grade unchanged, no ownership taken.

    • Both anchors live: UnifiedSidebar.tsx:198 (… || activeApps[0]) and :201 (useNavOrder(activeApp?.name || 'home')); the in-file comment at :654 still documents the deliberate non-wiring of the home branch.
    • State unchanged: unreachable fallback today, cross-context key collision only if someone wires enablePinning/enableReorder into the home branch.
    • Restart condition unchanged: any card that connects pinning/reorder to the home context must fix the storage key first — flag it against this issue at that moment.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  4. claude commented on Aug 10, 2026

    @claude
    Contributor

    Findings triage: HOLD.

    Re-verified @ objectui origin/main 564252c: the fallback is live at packages/app-shell/src/layout/UnifiedSidebar.tsx:201 (useNavOrder(activeApp?.name || 'home')) and the PR #3630 comment documenting the deliberate non-wiring is at :654. Both halves unchanged: the 'home' literal is unreachable for any consumer of the ordering result, and wiring home pin/reorder as-is would key on the deployment's first app. Held because the exit is a product call — whether home navigation should be sortable/pinnable at all — not a mechanical fix.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  5. claude commented on Aug 11, 2026

    @claude
    Contributor

    Findings round (quota re-verification): HOLD maintained (finding unchanged). Re-checked @ origin/main a9a67ec: the fallback drifted to UnifiedSidebar.tsx:205 (useNavOrder(activeApp?.name || 'home')) and the deliberate-non-wiring comment to :664 — both live, both halves unchanged ('home' literal unreachable for ordering consumers; wiring as-is would key on the first app). Exit remains a product call on home-nav sortability; held.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  6. os-zhuang commented on Aug 11, 2026

    @os-zhuang
    Contributor

    Findings cadence (triage seat): HOLD — premise re-verified on origin/main @ 6d01319: useNavOrder(activeApp?.name || 'home') still resolves the storage key from the first app in the home context (packages/app-shell/src/layout/UnifiedSidebar.tsx:206, second site :306; note the file moved from console/ to layout/ since filing — content unchanged, and the inline comment at :665 now discusses exactly this fallback). The || 'home' arm remains effectively unreachable as filed. Held: observation on storage-key semantics, no user-visible wrongness beyond pin/order following the first app; exit rides the next nav-persistence rework.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  7. os-zhuang commented on Aug 11, 2026

    @os-zhuang
    Contributor

    Findings cadence (triage seat): HOLD — re-verified @ origin/main 6044d13: UnifiedSidebar.tsx still keys nav-order/pin storage on activeApp?.name || 'home' (:206, :306), so in the home context the key still resolves to the first app and the 'home' fallback remains unreachable — the file's own comment at :665 documents the shape. Cosmetic/latent (a user's home-context reorder rides on the first app's key); nothing newly user-visible. finding stands. Restart unchanged: any home-surface nav rework, or a user-visible mis-scoped reorder report.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  8. os-project-manager commented on Aug 17, 2026

    @os-project-manager
    Collaborator

    Triage (batch first-touch round, 2026-08-17): finding → pm:on-hold — state transition of the standing 2026-08-08 HOLD (latent cross-context key-bleed; live only if pin/reorder gets wired onto the home branch, which PR #3630 deliberately did not do). Premise re-verified this round: UnifiedSidebar.tsx:206 fallback intact, home branch still unwired (:545/:547 inside the app branch, deliberate-non-wiring comment at :664). Note a second useNavOrder call site now exists (:306) — include it in any fix.

    Restart-when: enablePinning/enableReorder appear outside the context === 'app' branch of UnifiedSidebar.tsx, or a product ruling on /home reorderability lands


    Generated by Claude Code

  9. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Aug 23, 2026
  10. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    Contributor

    Triage: domain:ui (lane only — pm:on-hold untouched). Landing: packages/app-shell — UnifiedSidebar's nav-order/pin storage-key resolution in the home context.

    Routed via the maintainer direct-dispatch channel, this session, verbatim: 「然后 批 4–5」. PM session session_0124Qg8rLvpXnQDwCmpKUmaJ. objectui three-stream split (maintainer 2026-08-21); not a Routine triage fire — the triage seat may re-grade.


    Generated by Claude Code

  11. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    关闭 not_planned —— 维护者同意:今天没有任何症状,提醒已经写在代码里

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ,objectstack 座位贴 #6015),2026-09-24T11:00Z。objectui 清理第七批(#8587 的挂起卡一次性清点):本席读完了卡面和评论(9 条,全部读到),并在本地 main(62597c5)上重新测量,把建议报给维护者。维护者答:「objectui 第⑦批 同意」。

    本卡说的是什么

    UnifiedSidebar 用 useNavOrder(activeApp?.name || 'home') 生成导航排序和置顶的存储键。|| 'home' 这个兜底不可达。如果将来有人给 /home 的导航接上置顶或排序,首页就会读写"第一个 app"的键,两处设置会互相串用。

    本席实测(本地 main 62597c5)

    • 兜底仍在 packages/app-shell/src/layout/UnifiedSidebar.tsx:210。
    • enablePinning(:549)和 enableReorder(:551)仍只在 app 分支里(:471),首页分支没有接。⇒ 5310785683 的重启条件没有发生。
    • :657-663 有一段注释,专门提醒下一个想接这个功能的人:存储键会落到第一个 app 上。

    为什么关

    今天没有任何用户可见的症状。真正会出问题的那一行改动旁边已经有注释提醒,比挂着一张卡更能拦住人。要不要让首页导航可排序,是一个还没提出的产品问题。

    什么时候重开

    首页导航接上置顶或排序时,或者有了"首页导航是否可排序"的产品裁定时重开。届时按卡面两个方向中对应的一个处理(5223733036 已写明)。

    标签:摘 pm:on-hold;以 not_planned 关闭。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions