# @dsh-yzj/ui-yzj Yunzhijia browser surface, dual-face package (`dsh.client`, `platform: web`). **Product law (v2.0):** 1 Yunzhijia group = 1 group room + N topic sessions — see `docs/spec/group-room-topics.md`. "挑群" opens the group-room host (`yzj-home-*`). Agent work lives on `yzj-topic-*`. Switching rooms paints cache first and never flashes the private-chat hint. The 会话 tab is a picker (no second IM composer). ## Node half Registers the `/yzj` Connection RPC channel over `ctx.yzjBridge` (authority `loopback`). Endpoints include: `workspaces`, `docs`, `events`, `groups`, `messages`, `whoami`, `auth-status` / `auth-login` (probe CLI login; user-clicked `yzj-cli auth login` opens the system browser — tokens stay in the OS keychain), `search`, `doc-get`, `doc-blocks`, `sheet-get`, `workspace-get`, `event-get`, `contact-get`, `write-list`, `write-decide`, `home-open` / `home-binding` / `home-log` / `home-fused` / `home-nav` / `home-topic-open` / `home-topic-lens` / `home-topic-ask` / `home-backfill` / `home-send` / `home-digest` / `home-handoff` (bound DSH home + plugin message log ①②; topic drawer lens + ask-assistant), the panel write face `im-send` / `file-upload` / `file-data` (user-direct writes; `im-send` also appends ② when the group is bound), the todo face over `ctx.yzjTodo`, the advance face over `ctx.yzjAdvance` (`advance-state` / `advance-get` / `advance-create` / `advance-judge` / `advance-ensure` / `advance-feed` / `advance-scan-state` / `advance-source-add` / `advance-source-remove`; `advance-feed` is the user-direct 事元 write and refuses stage/goal fields; the source endpoints are the user-direct 上下文来源 (context source) subscription writes, and the subscribed source list folds into the `advance-get` response as `contextSources`), the robot face over `ctx.yzjRobot`, the memory face over `ctx.yzjMemory`, and the model face over `ctx.yzjModels`. Only lossless CLI-parsed JSON crosses the channel. ## Browser half Does **not** register `conversation.view` or `sidebar.footer.action` (R27). The 云之家 dock is DOM-injected under New Session as a single 「云之家」button (R31); click opens the center-column cover and does not switch domains or focus a hanger. The workbench is a cover (`data-dsh-yzj-view`) that does not create a session. Opening a topic closes the cover and `sessions.open`s the real `yzj-topic-*`. Still registers `conversation.input.dock` (topic 「回群聊」 / unbound 丢进群), `conversation.session.header.actions` (leftover room pill), and `tool.call.toolview` (keyed cards). **Does not** register `shell.overlay`. - **Tool cards** — one keyed view per yzj tool name (51, incl the `yzj_advance_*` family) plus the five `memory_*` tools: pending calls render the family title from args; settled calls render the structured `meta` payload with the digest text as fallback, and an error summary on failure. Card 查看 jumps switch the workbench domain. - **Workbench domains** — top underline tabs 对话 / 待办 / 日程 / 知识库 / 推进 (R31; v1.18 adds the AI推进 board). 对话 is the session list + group-room timeline; 待办 / 知识库 embed the former panel. 日程 is day/week/month/year (`.cal` toolbar + time grid). Memory UI is deferred. The sidebar has one 「云之家」entry; it does not switch domains. - **推进 board** (`advance-pane.tsx`, ai-advance-design §7 / §11 / §12 / §14 / §15) — lgap17-prototype information architecture: left 「我的推进」 queue (patrol status line + 待我决定 / 待我验收 / 我关注的推进 with count badges + tone dots), main detail (kicker + stage pill + 「现在反馈」/「请 AI 验收」, metric cards, current goal, stage-aware decision area, 推进时间旅程 with three-tone marks / source jumps / 查看全部 paging), right 订阅渠道 + 信息来源 + 已有产物 column. RPC: `advance-state / advance-get / advance-create / advance-judge / advance-ensure / advance-feed / advance-scan-state / advance-source-add / advance-source-remove`. Judge verbs, the start modal, `advance-feed` (群房间/话题「喂给推进」、事项卡一句话), and the source 关联/解除 writes are user-direct writes (D9, no confirmation card), each landing as one `操作者=user` 事元 where applicable; `advance-feed` refuses `stageTo` / goal fields (决策 10). Context sources (spec §15, v1.8 rename): the 上下文来源 column tops with subscribed source chips (kind icon + 你关联/AI 关联 + × 解除), the 「关联来源」 modal offers a recent-group picker plus a manual `im:/doc:/todo:/event:/file:` token input; a single-document source association lands one 备注 事元, unlinking touches the registry only. The decision area parses the latest 决策请求 事元's `选项N` rows into option buttons (click = `confirm_advance` with note = the option text; `影响` row rendered separately) above the classic verbs, which stay unchanged when no options exist. Agent writes go through `yzj_advance_create/feed` with the standard card. 「现在反馈」 switches the workbench to 对话 and injects a non-modal item card via a module-level bus. 「请 AI 验收」 switches to 对话 and pre-fills the topic 问助手 draft (does not auto-send). `yzj_advance_inspect` is the read-only 比对材料 tool (host does not judge). `yzj_advance_scan` is the read-only incremental IM scan (groups optional → subscription aggregation). - **Group room** — workbench two-pane (conversation list + timeline). Clicking a list row switches `groupId` only (R24) — it does not create or focus a DSH session. Overlay mode paints without a hanger. Canvas layout (self right / others left; same-sender merge; date rules; in-bubble 「N 条回复」 chips; assistant file artifact cards), directory names (never 「群消息」; list rows prefer the CLI group name over the 「群房间」 title placeholder), hover text links 「回复 / 交给助手 / 喂给推进」 open the topic drawer (native Chat via 原生会话 ↗) or the advancement picker (`/yzj advance-feed`, refs=`msgId`). The drawer lens is a bubble stream plus 「问助手」 (`home-topic-lens` / `home-topic-ask`); this-turn `write`/`edit` files render as cards under the assistant bubble (R30). Asking followups a user turn and does not focus native Chat. Lens origin / 问助手栏 also expose 「喂给推进」 (legacy-host is never a msg ref). The first ask plants the summon window once as a plugin inject (`yzj-summon-window`); memory stays on the runtime snapshot (pitfall-031). Topic agents mount the host default preset (`standard`) so bash/files sit next to `yzj_*` (R28 / pitfall-030). **Job-done delivery (R29):** when a topic turn goes idle, the node half posts a bounded summary back onto the Yunzhijia reply chain as the logged-in user (CLI identity, no confirm card) and still uploads/`im message send`s that turn's artifacts (images in the reply, other files on the group timeline). The lens cards do not replace that send. Opening a host that still has pre-v2.0 ③④ mints a 「历史对话」 topic (`rootMsgId=legacy-host`). Composer takeover covering CLI send (reply / @ / @all / emoji / image / file), portaled into the timeline column. L2 badges: accent count = 待确认 topics, dot = 进行中. DMs have no drawer. New yzj sessions use `~/.dsh-yzj/workspace` as `meta.cwd`. Only `yzj-topic-*` attach to Host Workspace 「云之家」; room hosts (`yzj-home-*`) share the cwd but are not listed in that sidebar group. Plugin ensure detaches leftover `yzj-home-*` membership from an earlier attach-everything pass. - **设置 → 云之家** — CLI login status + 「打开登录页」 (R26) above robot-channel management (NOT a workspace tab). Memory vault UI is deferred (R21 v1.6); `memory-yzj` and `memory_*` tools stay mounted. - **未登录** — the workbench session list (and non-IM domain top bar) shows a login card. The button starts `yzj-cli auth login` on the host; after the browser OAuth the user clicks 「我已登录」. DSH never stores tokens. - **@ trigger sources** — 云之家·同事 / 云之家·会话 / 云之家·文档 (plus the codec carrier source for leftover chips). Drag-to-chip (floating-panel drop overlay) is retired. Styling uses the GUI's `--dsw-*` semantic tokens with local fallbacks; product copy is Chinese. ## Model Experience The node half posts a topic-turn summary back onto the Yunzhijia reply chain when the agent goes idle (R29). It does not add prompt text. The browser half renders already-logged tool results plus panel data fetched through RPC. ## Known Limitations and Deferred Work - **User-direct writes are un-gated by design** — DSH「发进群」and todo checkboxes act as the user's own hand; only agent-initiated writes pass the confirmation card. Product law D9 / R6. Topic job-done delivery (R29) is the contracted post-back of 「问助手」, also un-gated, CLI identity. - **CLI file messages cannot join a reply chain** — `msg-type file` rejects `--reply-msg-id` (pitfall-033). Job-done images ride the richText reply; other files follow on the group timeline. The topic-drawer lens still shows those files as local cards (R30). Do not lift the `parseImSend` / `yzj_im_message_send` gate until CLI supports it. - **`file download` card is text-only** — the CLI returns no structured path metadata for downloads. - **Locale namespace not registered** — cards use Chinese literals; a `locale` namespace can be added when i18n is needed. - **`panel.tsx` is a large module** — the floating overlay is gone; the same tabs now embed in the workbench. Split before further panel growth. - **Calendar month fetch is two-pointer-scanned on the host** — `/yzj` `events` week-stripes the month and walks each stripe (pitfall-032). The browser still sends a single start/end.