# Agent Sidecar 第三阶段 Management Portal 产品设计

创建日期：2026-09-02

状态：Draft

阶段：第三阶段

产品范围：Management Portal 的 Agent Workspace 文件管理体验

依赖文档：

- `docs/design/2026-09-02-agent-codex-workspace-sidecar-prd.md`
- `docs/design/2026-09-02-agent-sidecar-phase-1-technical-design.md`
- `docs/design/2026-09-02-agent-sidecar-phase-2-agent-gateway-technical-design.md`

## 1. 文档目标

本文定义 Workspace 管理员在 Management Portal 中管理 Agent Codex Workspace 文件的
页面、视觉样式、操作流程和交互反馈，作为第三阶段前端设计与产品验收依据。

本文重点回答：

- 管理员从哪里进入 Agent 文件管理页面；
- 页面如何组织 Agent、Projects、Global、目录树和文件编辑器；
- 创建、编辑、移动和永久删除分别如何操作；
- 未保存内容、并发冲突和 Sidecar 不可用时如何保护用户工作；
- 各类加载、空态、失败和受限状态如何呈现。

本文不描述接口、前端组件拆分、状态管理、缓存、路由实现、生成客户端或后端技术方案。
本文中的界面文案使用英文，以保持与 Management Portal 当前界面一致；产品说明使用中文。

## 2. 产品边界

### 2.1 本阶段包含

- Admin 菜单下的 `Agents` 管理页面；
- 静态 Agent 实例选择和管理能力标识；
- Project 列表、创建和永久删除；
- Project 内文件和目录的查看、新建、重命名、移动和永久删除；
- Global 中 `skills` 和 `AGENTS.md` 的受限管理；
- UTF-8 文本文件的在线查看与编辑；
- 未保存内容保护、并发修改冲突处理和操作结果反馈；
- 目录按需展开和分页加载；
- 加载、空态、不可管理、不可编辑、无权限和服务不可用状态。

### 2.2 本阶段不包含

- Git clone、remote、pull、push、commit、branch、tag 或凭证管理；
- Project 重命名或跨 Project 移动；
- Projects 与 Global 之间移动；
- 文件上传、下载、二进制预览或 Base64 展示；
- 全文搜索、跨目录搜索或文件内容替换；
- 自动保存、强制覆盖、自动合并或多人协同编辑；
- 文件历史、版本对比、回收站、软删除或删除恢复；
- Agent Task 状态展示，或 Agent 执行期间的文件操作限制；
- Sidecar 在线状态探测或实时文件系统变化提示；
- 移动端专用布局。

## 3. 用户与权限体验

目标用户是具有 Management Portal admin 权限的内部 Workspace 管理员。

- admin 用户在侧边栏 `Admin` 分组中看到 `Agents` 菜单；
- 非 admin 用户看不到菜单；
- 非 admin 用户直接访问页面时，沿用 Portal 现有的无权限处理，不短暂展示页面内容；
- MVP 不展示或配置实例级、Project 级、只读等更细粒度角色；
- 页面不展示认证信息、内部 endpoint、PVC 路径或任何 Secret。

## 4. 信息架构与入口

导航层级固定为：

```text
Management Portal
└── Admin
    └── Agents
        ├── Projects
        │   ├── Project selector
        │   ├── Project actions
        │   └── File tree + File editor
        └── Global
            ├── skills
            ├── AGENTS.md（可选）
            └── File tree + File editor
```

页面只使用一个主路由。选择 Agent、Project、页签或文件不会打开新的浏览器页面，也不会
把内部路径写入可分享链接。刷新页面后按照首次进入规则重新选择 Agent 和 Project。

## 5. 页面总体结构

### 5.1 主页面

```text
+--------------------------------------------------------------------------------+
| Agents                                                                         |
| Manage Projects, Skills, and global instructions for an Agent instance.        |
|                                                                                |
| Agent instance  [ codex-a                         v ] [Default] [Managed]        |
+--------------------------------------------------------------------------------+
| [ Projects ] [ Global ]                                                        |
+--------------------------------+-----------------------------------------------+
| Project                        | demo / README.md                  [Editable]   |
| [ demo                    v ]  | 1.8 KB  ·  Modified Sep 2, 2026 14:30 CST     |
| [Create project] [More ...]    |                             Unsaved changes ● |
|--------------------------------|-----------------------------------------------|
| [Refresh] [New v]              |                                               |
| v src                          |  # Demo                                       |
|   > components                 |                                               |
|   - index.ts                   |  Project description...                       |
| - README.md                 •  |                                               |
| > docs                         |                                               |
|                                |                                               |
|                                |                                               |
|                                |                                               |
|                                |                         [Cancel] [Save]        |
+--------------------------------+-----------------------------------------------+
```

页面由三层组成：

1. 页面头部：标题、用途说明和 Agent 实例选择；
2. Workspace 页签：`Projects` 和 `Global`；
3. 工作区：左侧资源浏览器和右侧文件信息/编辑区域。

### 5.2 尺寸与滚动

- 页面按桌面管理后台设计，建议可用内容宽度不小于 1024px；
- 左侧资源浏览器固定约 320px，保证长目录名仍有可辨识空间；
- 右侧区域占据剩余宽度；
- 工作区至少占据浏览器当前可视高度减去 Portal Header、面包屑和页面头部的空间；
- 左侧目录树与右侧编辑器分别滚动，页面头部、Agent 选择器和页签保持可见；
- 窄窗口不切换为移动端上下布局，允许内容区域出现必要的横向滚动；
- 弹窗最大高度不超过当前视口，目录选择等长内容在弹窗内部滚动。

## 6. 视觉样式

### 6.1 总体风格

页面延续 Management Portal 现有的简洁后台风格：

- 页面内容使用白色背景；
- 分栏、工具栏和信息区之间使用浅色单像素边框；
- 一级区域使用 16px 至 24px 间距，紧密关联的控件使用 8px 间距；
- 标题和主要名称使用较高字重，路径、大小和修改时间使用次级文字颜色；
- 图标以辅助识别为目的，不单独承担含义；
- 不使用渐变、大面积品牌色、装饰插图或重阴影；
- 编辑器使用等宽字体，其他区域沿用 Portal 默认字体。

### 6.2 状态色

| 类型 | 使用方式 |
| --- | --- |
| Primary | 创建、保存、重试等明确的下一步动作 |
| Neutral | 取消、刷新、普通标签和辅助操作 |
| Warning | 未初始化 Git、未保存内容、服务状态未知等需注意但不阻断的状态 |
| Error | 操作失败、并发冲突、服务不可用和永久删除 |
| Success | 创建、保存、移动和删除完成后的短暂反馈 |

危险操作统一使用红色文字或按钮，并与普通操作保持足够间距，避免误触。状态不能只靠颜色
表达，必须同时显示文字或图标说明。

### 6.3 文件与目录图标

- 目录使用文件夹图标，展开和收起状态应明显；
- 文件使用普通文件图标；
- 可根据已支持的文本类型使用轻量差异化图标，但不能暗示未提供的预览能力；
- 当前选中节点使用浅色背景和左侧高亮；
- 当前节点存在可用操作时，在 hover 和键盘聚焦状态显示 `More` 按钮；
- `.git`、denylist 目录和符号链接不显示占位符，也不提示其磁盘存在。

## 7. Agent 实例选择

### 7.1 选择器内容

Agent 选择器显示所有静态配置的 Agent，并保持按 `agent_id` 升序排列。每个选项包含：

- `agent_id`，作为主文字；
- Provider，作为次级文字；
- 默认实例显示 `Default` 标签；
- 支持本产品文件管理能力的实例显示 `Managed` 标签；
- 不支持的实例显示 `Not managed` 标签。

页面不显示 `Online`、`Offline` 或健康百分比。Sidecar 是否可用只在用户实际加载或操作时
根据结果体现，避免把静态列表误解为实时监控页面。

### 7.2 首次选择规则

首次进入页面时按以下顺序自动选择：

1. 默认 Agent 支持文件管理时，选择默认 Agent；
2. 默认 Agent 不支持时，选择第一个 `Managed` Agent；
3. 没有任何 `Managed` Agent 时，选择默认 Agent；
4. 没有默认 Agent 时，选择列表中的第一个 Agent；
5. Agent 列表为空时，展示无实例空态。

选择 Managed Agent 后默认进入 `Projects` 页签。Project 列表加载完成且存在 Project 时，
自动选择名称排序后的第一个 Project，但不自动打开文件。

### 7.3 切换 Agent

- 没有未保存内容时，选择新 Agent 后立即清空旧 Agent 的 Project、目录树和文件区域，并
  展示新 Agent 的加载状态；
- 禁止在加载期间继续展示旧实例的目录或文件，避免造成跨实例错觉；
- 有未保存内容时，切换前先显示离开确认；
- 用户确认放弃修改后再切换；用户选择留下时维持原 Agent 和当前编辑内容；
- 切换后重新应用该 Agent 的默认页签和 Project 选择规则；
- 新 Agent 加载失败时保留选择器中的选中值，但工作区只显示该 Agent 的错误状态和重试
  入口。

## 8. 不可管理与无实例状态

### 8.1 Not managed Agent

选择 `Not managed` Agent 时，不请求、不推测也不显示 Project 或 Global 内容。

```text
+--------------------------------------------------------------------------------+
| Agents                                                                         |
|                                                                                |
| Agent instance  [ legacy-agent                    v ] [Not managed]             |
+--------------------------------------------------------------------------------+
|                                                                                |
|                         Agent is not managed                                   |
|       Project management is not enabled for this Agent instance.               |
|                                                                                |
+--------------------------------------------------------------------------------+
```

- `Projects / Global` 页签和文件操作区不显示；
- 不提供“启用”按钮，因为配置变更不属于本页面能力；
- 用户仍可打开选择器切换到其他 Agent。

### 8.2 没有 Agent

列表为空时显示：

```text
No Agent instances configured
Agent instances will appear here after they are configured.
```

不显示 Create Agent，因为动态注册不在本阶段范围内。

## 9. Projects 页签

### 9.1 左侧 Project 区域

左侧顶部包含：

- `Project` 标题；
- Project 选择器；
- `Create project` 主操作；
- 当前 Project 的 `More` 菜单；
- 文件树工具栏和目录树。

Project 选择器中的每项显示名称，并在名称后展示 Git 状态：

- `Git initialized`：存在有效 Git metadata；
- `Git not initialized`：既有目录没有 Git metadata。

`Git not initialized` 只用于说明，不提供补做 Git 初始化的操作。Project 名称较长时单行
截断，hover 后显示完整名称。Project 列表超过当前页时，在选择器末尾提供 `Load more
projects`，追加加载而不改变当前选择。

### 9.2 无 Project 空态

```text
+--------------------------------+-----------------------------------------------+
| Project                        |                                               |
| [ No projects             v ]  |                                               |
| [Create project]               |             No Project selected               |
|--------------------------------|    Create a Project to start managing files.  |
|                                |                                               |
|      No Projects yet           |                                               |
|                                |                                               |
+--------------------------------+-----------------------------------------------+
```

- `Create project` 是唯一主操作；
- 右侧不显示编辑器或文件元信息；
- 空态不暗示可从 Git clone 或上传创建 Project。

### 9.3 创建 Project

点击 `Create project` 打开弹窗：

```text
Create Project

Project name  [ demo-agent-workspace                     ]
Use letters, numbers, dots, underscores, and hyphens.
The name must start with a letter or number and contain at most 128 characters.

                                           [Cancel] [Create]
```

交互规则：

- 弹窗打开后输入框自动聚焦；
- 输入过程中即时展示明显的格式问题；
- `Create` 在名称为空、格式不合法或请求进行中时禁用；
- Enter 提交合法表单，Esc 或 `Cancel` 关闭弹窗；
- 创建期间禁止重复提交，关闭按钮暂时不可用；
- 同名文件或目录已存在时，在输入框下显示 `A Project with this name already exists.`；
- 创建成功后关闭弹窗，显示成功反馈，刷新 Project 列表并自动选中新 Project；
- 新 Project 的目录树显示空态，右侧显示 `Select a file to view or edit.`；
- 创建失败时保留已输入名称，用户可修正后重试。

### 9.4 删除 Project

当前 Project 的 `More` 菜单只包含 `Delete project`。点击后打开高风险确认弹窗：

```text
Permanently delete Project?

This will permanently delete "demo", including all files and Git metadata.
This action cannot be undone.

Type demo to confirm
[                                                        ]

                                  [Cancel] [Delete permanently]
```

交互规则：

- `Delete permanently` 使用危险样式；
- 只有输入值与完整 Project 名称完全相同时才能提交；
- 不自动去除输入首尾空格，也不忽略大小写；
- 删除期间禁止关闭弹窗或重复提交；
- 删除失败时保留确认输入，并在弹窗内显示可行动错误；
- 删除成功后关闭弹窗、清空编辑器、刷新 Project 列表；
- 仍有 Project 时选择排序后的第一个 Project，但不自动打开文件；
- 已无 Project 时进入无 Project 空态。

## 10. Global 页签

Global 是受限虚拟根，不代表整个 CODEX_HOME。

```text
+--------------------------------+-----------------------------------------------+
| Global                         | skills/example/SKILL.md          [Editable]   |
|--------------------------------| 2.4 KB  ·  Modified Sep 2, 2026 15:10 CST     |
| [Refresh] [New v]              |-----------------------------------------------|
| v skills                       |                                               |
|   v example                    |  # Example Skill                              |
|     - SKILL.md              •  |                                               |
| - AGENTS.md                    |  Instructions...                              |
|                                |                                               |
|                                |                         [Cancel] [Save]        |
+--------------------------------+-----------------------------------------------+
```

规则：

- `skills` 始终作为第一个根节点显示；
- `skills` 根不能删除、移动或重命名，其操作菜单只提供新建文件和新建目录；
- `skills` 内部内容使用与普通 Project 相同的管理体验；
- `AGENTS.md` 存在时显示为第二个根节点，可查看、编辑和删除；
- `AGENTS.md` 不存在时，在树中显示 `Create AGENTS.md` 操作入口；
- Global 根不提供任意名称的新建操作；
- Global 根不能出现第三个根级条目；
- 页面不显示 CODEX_HOME、`auth.json`、`config.toml`、history、sessions 或其他文件名；
- 用户从 Projects 切换到 Global 时，先执行未保存内容检查，再清空 Project 文件区并加载
  Global；切回 Projects 时重新加载当前 Project。

创建 `AGENTS.md` 成功后，页面自动选中并打开空文件，将编辑焦点放入编辑器。空文件已经
完成创建，因此初始不标记为未保存；用户输入首个字符后进入 dirty 状态。

## 11. 目录树

### 11.1 展开与加载

- Project 目录树从 Project 根内容开始，不额外显示可操作的 Project 根节点；
- Global 目录树显示固定的 `skills` 和可选 `AGENTS.md`；
- 目录默认收起，点击展开箭头时加载当前目录的直接子项；
- 加载中的目录在节点下方显示小型 loading，不阻塞其他已加载目录；
- 目录在文件之前，同类型按名称升序；
- 空目录展开后显示不可选的 `Empty folder`；
- 刷新某个目录后，保留该目录的展开状态；已删除的子节点从树中移除；
- 顶部 `Refresh` 刷新当前 Workspace 的 Project 列表或 Global 根，并重新加载已选目录；
- 刷新不会替用户丢弃 dirty editor，存在未保存内容时先确认。

### 11.2 分页

目录存在更多内容时，在已加载节点末尾显示：

```text
  Load more...
```

- 点击后追加下一页，不折叠目录、不滚回顶部；
- 加载期间该行显示 `Loading...` 并禁止重复点击；
- 加载失败时行内显示 `Failed to load. Retry`；
- 若目录内容变化导致当前分页无法继续，提示 `This folder changed. Refreshing its
  contents.`，随后从第一页刷新该目录；
- 刷新后若当前选中文件已不存在，清空右侧文件区域并提示文件已被移除。

### 11.3 选择与操作入口

- 单击目录名称只选中目录；单击展开箭头只控制展开/收起；
- 单击文件名称加载文件；
- 当前选中节点保持高亮；
- 节点 hover 或键盘聚焦时显示 `More`；
- 顶部 `New` 菜单用于在当前选中目录创建文件或目录；未选中目录时，在 Workspace 根创建；
- Project 根允许新建文件和目录；Global 根只允许创建 `AGENTS.md`；
- 除顶部菜单外，目录的 `More` 菜单也提供 `New file` 和 `New folder`；
- 不依赖右键菜单，所有操作均可通过可见按钮和键盘访问。

### 11.4 节点操作菜单

| 节点 | 可用操作 |
| --- | --- |
| Project 内文件 | Rename、Move、Delete |
| Project 内目录 | New file、New folder、Rename、Move、Delete |
| `skills` 根 | New file、New folder |
| `skills` 内文件 | Rename、Move、Delete |
| `skills` 内目录 | New file、New folder、Rename、Move、Delete |
| `AGENTS.md` | Delete |

Project 根、Global 根和 `skills` 根不出现不允许的操作。`AGENTS.md` 不提供 Rename 或 Move。

## 12. 文件查看与编辑

### 12.1 未选择文件

选择 Project 或目录但未选择文件时，右侧显示轻量空态：

```text
Select a file to view or edit.
```

不显示空白编辑器，避免用户误以为正在创建新文件。

### 12.2 可编辑文本文件

```text
+-------------------------------------------------------------------------------+
| src/config.yaml                                                   [Editable]  |
| 864 B  ·  Modified Sep 2, 2026 16:24 CST                  Unsaved changes ●  |
|-------------------------------------------------------------------------------|
| 1  service:                                                                  |
| 2    name: demo                                                              |
| 3    enabled: true                                                           |
|                                                                               |
|                                                                               |
|                                                       [Cancel] [Save]         |
+-------------------------------------------------------------------------------+
```

文件头部展示：

- 相对当前 Project 或 Global 的完整 path；
- 文件大小；
- 最后修改时间和明确时区；
- `Editable` 状态；
- 内容变化后显示 `Unsaved changes` 和状态点。

编辑规则：

- 文本文件在代码编辑器中打开；
- 已支持的文件类型显示对应语法高亮，未知扩展名使用 plain text；
- 编辑器显示行号，并支持常规选择、复制、粘贴、撤销和重做；
- 不自动保存；
- 内容未变化时 `Save` 和 `Cancel` 禁用；
- 内容变化后两者启用；
- `Save` 或 `Ctrl+S` / `Cmd+S` 保存；
- 保存期间编辑器暂时只读，按钮显示 loading，避免连续提交不同内容；
- 保存成功后更新文件大小、修改时间和当前版本，清除 dirty 状态并显示成功反馈；
- `Cancel` 恢复本次打开文件时读取到的服务端正文，并清除 dirty 状态；
- 新建空文件成功后自动打开，并将焦点放入编辑器。

### 12.3 不可编辑文件

```text
+-------------------------------------------------------------------------------+
| assets/archive.bin                                           [Not editable]  |
| 4.8 MB  ·  Modified Sep 2, 2026 16:40 CST                                   |
|-------------------------------------------------------------------------------|
|                                                                               |
|                       This file cannot be edited                              |
|       Binary files and files larger than 1 MiB are not available here.       |
|                                                                               |
+-------------------------------------------------------------------------------+
```

不可编辑原因按实际结果显示为：

- `This is not a UTF-8 text file.`；
- `This file contains binary content.`；
- `This file is larger than the 1 MiB editing limit.`。

不可编辑状态只显示元信息和原因：

- 不显示部分正文；
- 不显示乱码、十六进制、Base64 或 binary preview；
- 不显示 `Save`、`Cancel`、`Download` 或强制打开入口；
- 仍可从目录树对文件执行 Rename、Move 和 Delete。

## 13. 新建、重命名与移动 Entry

### 13.1 新建文件或目录

选择 `New file` 或 `New folder` 后打开小型弹窗。弹窗标题和主按钮随类型变化，并显示创建
位置：

```text
New file

Location      demo/src
File name     [ handler.go                              ]

                                              [Cancel] [Create]
```

- 名称只能是单个名称，不能包含 `/`，也不能使用 `.` 或 `..`；
- 名称命中受保护目录时显示明确错误；
- 同名目标存在时不覆盖，并在输入框下提示；
- 创建成功后刷新父目录并选中新节点；
- 新建文件自动在右侧打开；
- 新建目录自动展开；
- 失败时保留名称和创建位置。

### 13.2 重命名

点击 `Rename` 打开弹窗，默认填入当前名称并全选文件名：

- 弹窗显示当前所在目录，但目录不可修改；
- 新名称遵循单个名称规则；
- 目标已存在时不覆盖；
- 成功后刷新父目录并保持新节点选中；
- 被重命名文件正在右侧打开时，文件 path 同步更新，正文和 dirty 状态保持不变；
- 操作过程中检测到文件已经变化时，进入冲突处理，不自动重试或覆盖。

### 13.3 移动

点击 `Move` 打开目录选择弹窗：

```text
Move "handler.go"

Move to
o demo/
  o src/
    o api/
  o test/

Current location: demo/src

                                                [Cancel] [Move]
```

- 只能选择当前 Workspace 内的目录；
- Project 之间以及 Projects/Global 之间不能移动；
- 移动目录时，自身和自身后代不能作为目标；
- `AGENTS.md` 和 `skills` 根不提供移动入口；
- 目标目录存在同名 Entry 时不覆盖；
- 成功后刷新源目录和目标目录，并保持移动后的节点选中；
- 被移动文件正在右侧打开时更新 path，正文和 dirty 状态保持不变；
- 移动不同时承担改名，改名使用独立的 `Rename` 操作。

## 14. 删除 Entry

所有 Entry 删除都是永久删除，必须二次确认。

### 14.1 删除文件

```text
Permanently delete file?

"src/handler.go" will be permanently deleted.
This action cannot be undone.

                                      [Cancel] [Delete permanently]
```

### 14.2 删除目录

```text
Permanently delete folder and its contents?

"src/generated" and everything inside it will be permanently deleted.
This action cannot be undone.

                                      [Cancel] [Delete permanently]
```

规则：

- 目录无论当前是否为空，确认文案都明确可能递归删除其全部内容；
- Project、Global 和 `skills` 根不提供删除入口；
- `AGENTS.md` 使用文件删除确认；
- 删除按钮使用危险样式；
- 删除期间禁止重复提交；
- 删除成功后刷新父目录；
- 删除当前打开文件或包含当前文件的目录时，清空右侧区域；
- 当前文件存在未保存内容时，先显示未保存内容确认，再进入删除确认；
- 文件版本已经变化时不继续删除，进入冲突处理。

## 15. 未保存内容保护

编辑器内容与本次读取的服务端正文不同时进入 dirty 状态。

以下动作发生前必须检查 dirty 状态：

- 选择其他文件；
- 选择其他 Project；
- 切换 Projects/Global；
- 切换 Agent；
- 刷新目录或页面；
- 删除、移动或重命名当前文件及其父目录；
- 通过侧边栏、浏览器返回或关闭页面离开当前页面。

Portal 内操作使用统一确认弹窗：

```text
Discard unsaved changes?

Your changes to "README.md" have not been saved.

                                    [Stay] [Discard changes]
```

- `Stay` 是默认安全操作，并保持当前文件和编辑内容；
- `Discard changes` 使用警告样式，确认后继续原动作；
- 弹窗不提供 `Save and continue`，用户应先返回编辑器显式保存；
- 浏览器关闭或刷新使用浏览器提供的离开确认，具体文案可能由浏览器决定；
- 保存失败后继续保持 dirty，不允许失败反馈清空本地内容。

## 16. 并发修改与冲突处理

### 16.1 保存冲突

当文件在本次读取后被其他管理员或 Agent 修改，保存必须停止，并显示：

```text
File changed on the server

"README.md" was modified after you opened it. Your local changes have not
been saved. Reload the server version or copy your current content first.

                      [Copy current content] [Reload server version]
```

处理规则：

- 本地编辑内容始终保留在当前页面，直到用户明确 reload 或离开；
- `Copy current content` 将完整本地正文复制到剪贴板，成功后显示 `Content copied.`；
- 复制失败时提示用户手动从编辑器复制，不关闭冲突提示；
- `Reload server version` 重新读取服务端内容并替换编辑器正文，同时清除 dirty 状态；
- 关闭冲突提示后可继续查看和复制本地内容，但再次保存仍基于旧版本，预计继续冲突；
- 不提供 `Overwrite anyway`、忽略冲突或自动合并。

### 16.2 Move/Delete 冲突

移动或删除前发现目标已经变化时：

- 终止操作，不自动重试；
- 显示 `This item changed before the operation could be completed.`；
- 提供 `Refresh`，刷新相关目录；
- 若右侧仍有 dirty 内容，继续保留，不被目录刷新覆盖；
- 刷新后由用户重新确认目标和操作。

## 17. 加载、错误与反馈

### 17.1 加载状态

| 场景 | 展示方式 |
| --- | --- |
| Agent 列表首次加载 | 页面头部和选择器 skeleton |
| Project 列表加载 | 左侧 Project 区域 loading，右侧空白占位 |
| 目录首次加载 | 目录节点下的小型 loading |
| 文件读取 | 右侧文件信息和编辑区 skeleton |
| mutation 进行中 | 对应主按钮 loading，阻止重复提交 |

加载新 Agent、Project 或文件时不得继续显示上一个目标的内容。刷新当前目录时可以保留已加载
内容并显示局部 loading，但必须避免把旧内容表现为已刷新完成。

### 17.2 Sidecar 不可用

```text
+--------------------------------------------------------------------------------+
| Agents                                                                         |
|                                                                                |
| Agent instance  [ codex-b                         v ] [Managed]                 |
+--------------------------------------------------------------------------------+
| [ Projects ] [ Global ]                                                        |
|                                                                                |
|                       Workspace files are unavailable                          |
|          The Agent file service could not be reached. Try again later.         |
|                                                                                |
|                                  [Retry]                                       |
+--------------------------------------------------------------------------------+
```

- Agent 仍保留在选择器中，不改成 `Not managed`；
- 不展示内部 endpoint、物理路径、超时细节或调用栈；
- 首次加载失败时，不展示上一个 Agent 的任何内容；
- `Retry` 重试当前页签的加载，不重置 Agent 选择；
- 用户仍可切换其他 Agent；
- 保存时遇到服务不可用，编辑器保留正文和 dirty 状态，页面顶部显示错误并提供重试保存；
- 服务不可用不会触发 Project 创建、目录初始化或页面本地清空动作。

### 17.3 常见错误反馈

| 场景 | 产品反馈 |
| --- | --- |
| 名称或路径不合法 | 在对应输入下说明规则，保留用户输入 |
| 目标已经存在 | 明确提示同名目标，不覆盖 |
| 文件或目录已不存在 | 提示目标已移除，并刷新父目录 |
| 受保护内容或符号链接 | 提示该位置不能通过 Portal 管理，不显示磁盘细节 |
| 文件超过限制 | 展示不可编辑或大小限制说明 |
| 非空目录删除未确认 | 返回删除确认并明确递归删除影响 |
| 并发版本冲突 | 保留本地内容并进入冲突处理 |
| 未分类操作失败 | 显示 `Operation failed. Try again.` 并保留当前上下文 |

成功的创建、保存、移动和删除使用短暂全局反馈。需要用户修正输入的错误显示在弹窗内；影响
整个工作区的错误显示在工作区顶部；目录分页错误显示在对应目录节点内。

所有错误文案都不得包含：

- Sidecar endpoint；
- Projects Root 或 CODEX_HOME 物理路径；
- 文件正文；
- Secret、token 或认证 header；
- 服务端调用栈。

## 18. 页面状态转换

```text
Enter Agents
    |
    +-- No agents ------------------------> No Agent empty state
    |
    +-- Select Not managed Agent ---------> Not managed empty state
    |
    +-- Select Managed Agent
            |
            +-- Load failed -------------> Unavailable + Retry
            |
            +-- Projects
            |     |
            |     +-- No Project --------> Create Project empty state
            |     +-- Project selected --> File tree
            |
            +-- Global ------------------> skills + optional AGENTS.md

File tree
    |
    +-- Select editable file ------------> Editor
    +-- Select non-editable file --------> Metadata-only state
    +-- Mutate entry --------------------> Refresh affected folder
    +-- Save conflict -------------------> Preserve local content + conflict actions
```

任何从 Editor 离开的状态转换都先经过 dirty 检查。任何 Agent 切换都先清空旧实例可见内容，
再进入新实例加载状态。

## 19. 键盘与可访问性

- 所有按钮、页签、选择器、目录节点和菜单都支持键盘聚焦；
- 聚焦状态必须可见，不能只依赖 hover 显示操作入口；
- 目录使用左右方向键展开/收起，上下方向键移动选择；
- `Ctrl+S` 和 `Cmd+S` 只在可编辑文件中触发保存，并阻止浏览器保存网页；
- 图标按钮提供可读名称和 tooltip；
- loading 状态、错误和成功反馈应能被辅助技术感知；
- 状态标签同时使用文字，不只依赖红、黄、绿颜色；
- 危险确认弹窗默认焦点放在安全操作，不默认聚焦永久删除按钮；
- 长文件名或路径截断后可通过 tooltip 查看完整值。

## 20. 产品验收场景

### 20.1 权限与 Agent

- admin 能看到并进入 `Admin > Agents`，非 admin 看不到入口且不能直接访问；
- Agent 选择器展示全部静态 Agent、Provider、Default 和 Managed 状态；
- 默认 Agent 不可管理时自动选择第一个 Managed Agent；
- 选择 Not managed Agent 时只显示说明，不出现文件操作；
- 两个 Managed Agent 之间切换时不显示另一个实例的 Project、目录树或文件；
- Sidecar 不可用时 Agent 仍可见，页面显示 Retry 且其他 Agent 不受影响。

### 20.2 Projects

- 无 Project 时显示创建空态；
- 合法名称创建成功后自动选中 Project，`.git` 不出现在目录树；
- 非法名称和同名目标在弹窗内明确提示且不覆盖已有内容；
- 既有非 Git 目录显示 `Git not initialized`，仍可正常管理内容；
- 删除 Project 必须输入完整名称，并明确包含文件和 Git metadata 且不可恢复；
- 删除成功后清空原文件编辑区并刷新 Project 列表。

### 20.3 Global

- Global 始终只展示 `skills` 和可选 `AGENTS.md`；
- `skills` 根不能删除、移动或重命名；
- `skills` 内可以完成文件和目录管理；
- `AGENTS.md` 不存在时可以创建，存在时可以编辑和删除；
- 页面没有访问或提示其他 CODEX_HOME 内容的入口。

### 20.4 文件与目录

- 目录按需展开，目录在文件前，同类型名称升序；
- `Load more` 追加内容，目录变化导致分页失效时自动刷新该目录；
- 文件和目录可新建、重命名、在同一 Workspace 移动和永久删除；
- Project、Workspace 或 `skills` 根不会出现非法操作入口；
- denylist 目录、`.git` 和符号链接不显示且不能通过页面操作；
- UTF-8 文本可编辑，二进制、非法 UTF-8 和超过 1 MiB 文件只显示元信息；
- 页面没有上传、下载、binary preview 或强制编辑入口。

### 20.5 编辑安全

- 编辑后出现 dirty 状态，Save/Cancel 和保存快捷键符合预期；
- 切换文件、Project、页签、Agent 或离开页面前均提示未保存内容；
- 保存失败或 Sidecar 不可用时本地正文不丢失；
- 两个客户端基于同一旧版本保存时，第二个客户端保留本地内容并显示冲突；
- 冲突提示提供重新加载和复制本地内容，不提供强制覆盖；
- Move/Delete 遇到并发变化时终止操作并要求刷新后重新确认。

## 21. 第三阶段完成标准

第三阶段前端产品体验满足以下条件即视为完成：

1. 管理员可以从一个页面选择 Agent，并在 Projects 与 Global 间完成规定范围内的文件管理；
2. 页面清晰区分 Managed、Not managed 和实际请求失败，不伪造实时在线状态；
3. Project、Global allowlist、受保护根节点和永久删除边界在页面中清晰可见；
4. 文本编辑包含显式保存、取消、dirty 防丢失和并发冲突处理；
5. 多实例切换不会在视觉上或操作上串用另一个 Agent 的内容；
6. 不可编辑文件、空态、分页失效和 Sidecar 不可用都有明确且可恢复的反馈；
7. 页面不暴露 endpoint、物理路径、Secret 或文件正文到错误信息；
8. 产品中没有引入 PRD 非目标内的 Git 操作、上传下载、搜索、历史版本、协同编辑或 Task
   联动能力。
