Kaynağa Gözat

docs(ui-workspace): align approval status contracts

ZiyaZhang 2 ay önce
ebeveyn
işleme
285cd60744

+ 11 - 9
apps/web/tests/built-boot.snapshot.ts

@@ -6,10 +6,10 @@
 // layers, per-plugin CSS injection, and a rendered journey reaching chat
 // content from the keyless FixtureApiClient transport.
 //
-// Behavior assertions do NOT belong here: component and wiring behavior is
-// pinned by the per-package suites (SlotTestRuntime benches over src), which
-// this smoke's plugin set cannot influence — bundling, module-table
-// resolution, and boot layering are the only failure modes left to it.
+// Component behavior remains owned by per-package suites (SlotTestRuntime
+// benches over src). This smoke additionally pins the resident approval
+// fixture's cross-plugin projection because only the built connection/runtime/
+// workspace graph can prove that transport-to-row path end to end.
 import { readFileSync } from 'node:fs'
 import { join } from 'node:path'
 import { act, cleanup, fireEvent, screen, waitFor, within } from '@testing-library/react'
@@ -105,13 +105,15 @@ it('boots the built plugin graph and renders a fixture session end to end', asyn
   // The resident approval fixture proves the assembled workspace plugin
   // distinguishes a blocked running session from an ordinarily busy one.
   const waitingTitle = await within(tree).findByText('Fixture 历史会话')
-  const waitingRow = waitingTitle.closest('[role="treeitem"]')
-  expect(waitingRow?.querySelector('[data-state="warning"]')).not.toBeNull()
-  expect(waitingRow?.querySelector('[data-state="ongoing"]')).toBeNull()
-  expect(within(waitingRow as HTMLElement).getByText('Waiting for approval')).not.toBeNull()
+  const waitingRow = waitingTitle.closest<HTMLElement>('[role="treeitem"]')
+  expect(waitingRow).not.toBeNull()
+  if (waitingRow === null) throw new Error('fixture Session title must belong to a tree row')
+  expect(waitingRow.querySelector('[data-state="warning"]')).not.toBeNull()
+  expect(waitingRow.querySelector('[data-state="ongoing"]')).toBeNull()
+  expect(within(waitingRow).getByText('Waiting for approval')).not.toBeNull()
 
   // Opening a session reaches chat content through the fixture transport.
-  fireEvent.click(await within(tree).findByText('Fixture 历史会话'))
+  fireEvent.click(waitingTitle)
   await waitFor(() => {
     expect(document.querySelector('[data-sample="bash-global"]')).not.toBeNull()
   }, { timeout: 10_000 })

+ 2 - 2
packages/client/ui-workspace/README.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write packages/client/ui-workspace/README.md
-README.md: 4ca836e4f1beeb164716e5fc4741253719d2700c
-README.zh.md: 2a5448a12d58184b027c99b5301510370ba63a83
+README.md: 7109de680f98ede4d8374444cf50b439317ce128
+README.zh.md: 874d9e3d190e0488d95362ce1eea260341d6a23e

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
packages/client/ui-workspace/README.md


+ 1 - 1
packages/client/ui-workspace/README.zh.md

@@ -6,7 +6,7 @@
 
 该选择器通过全局 `useWorkspaces` hook 列出真实的 Host Workspace 实体。选择 Workspace 会调用 slot owner 的 `onPick` 回调,重新定位前端 Session 对象。每个注册各自声明一个**目录流子洞**(`single` kind:`conversation.hero.workspace.directoryFlow`/`sidebar.workspaces.directoryFlow`),由组合的选择器包 client half 填入其选取交互——今天是 [`-native`](../../host/directory-picker-native/README.md) 后端的无渲染 OS 选择器驱动,`-browse` 组合下则是应用内浏览对话框。平铺显示的 **打开本地文件夹…** 操作仅在本表层的洞被占用时渲染(每次菜单渲染读取占用状态;洞为空意味着该组合没有选目录能力——seam 文档化的无流程默认行为)。本包持有触发与接纳:占用者经洞的 owner 会话(`open`/`busy`/`onPicked`/`onCancel`/`onError`)每次打开上报一个所选路径,owner 通过对象层接纳它,并等待 Workspace 列表投影刷新后才选中已提交的 Workspace;取消操作不会显示提示,错误落入可重试的文件夹对话框,其 **重新选择** 会重新打开流程。**创建新工作区** 操作保留名称对话框,并禁用列表中已有的名称,而 Host 对并发或非 UI 调用方仍具有最终决定权。运行时 Session 与 Workspace 服务负责物化。Workspace 行内的 Delete 操作会打开确认框,说明保留边界、阻止重复提交,并在失败时保持打开;成功后,该分组会被移除,其 Session 则留在 Ungrouped 下。Session 行内的 Rename 操作打开同款浏览器持有的对话框,并以该行的显示标题预填:客户端不设名称冲突规则(host 负责规范化,可能以 `title-invalid` 拒绝,错误渲染在对话框告警区);确认未修改的标题是有意允许的——这正是把当前自动标题钉住、不再被重新生成覆盖的手势。
 
-Session 行会把 runtime 的实时 `waitingApproval` 状态与原本显示为蓝色的进行中 Session 区分开:琥珀色警告点优先于运行指示器,随附的视觉隐藏标签会向辅助技术公开这一状态,hover 卡片则在请求解决前显示 **Waiting for approval**。没有待审批请求时,运行与空闲展示保持不变。
+Session 行会把 runtime 的实时 `waitingApproval` 审批请求状态与原本显示为蓝色的进行中 Session 区分开:琥珀色警告点优先于运行指示器,hover 卡片则在请求解决前显示 **Waiting for approval**。每种点亮状态都带有面向辅助技术的视觉隐藏标签(`Waiting for approval` 或 `Running`);空闲行会保留空的状态槽位。问题等待由另一套状态跟踪,不会设置 `waitingApproval`。
 
 两个目标 slot 都由其他插件声明,因此 `apply` 通过声明感知的延迟机制完成注册,并在声明该 slot 的插件恢复后重新注册。
 

+ 1 - 1
packages/client/ui-workspace/src/client/tree.ts

@@ -20,7 +20,7 @@ export interface SessionNode {
   /** The session HAS children in the data (the twist renders even while folded). */
   hasChildren: boolean
   expanded: boolean
-  /** A pending approval takes display precedence over the running state. */
+  /** The runtime Session list reports a pending approval request for this Session. */
   waitingApproval: boolean
   running: boolean
   updatedAt: number

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor