docs: freeze workbench authority invariants

This commit is contained in:
Codex
2026-06-18 03:36:14 +00:00
parent 384cb9dfb8
commit 3da4533300
2 changed files with 26 additions and 24 deletions
@@ -19,7 +19,7 @@
| 短名 | Web工作台 |
| 层级 | L2 课题 |
| 状态 | 已生效 |
| 实现引用版本 | draft-2026-06-17-r0 |
| 实现引用版本 | draft-2026-06-18-r1 |
| 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) |
| 上级规格 | [PJ2026-0104 客户端](PJ2026-0104-client.md) |
| 规格治理索引 | [规格治理](spec-governance.md) |
@@ -37,7 +37,7 @@ Web工作台负责 HWLAB 登录后的浏览器主入口,使用户能够在同
### 2.2 范围内
- 登录后 Cloud Web shell、topbar、导航、工作台路由、页面切换反馈和同源 API 状态展示。
- 会话列表、当前 conversation、用户消息、Agent 消息、命令输入区、发送、引导、取消、重试和 pending 状态展示。
- 会话列表、当前 session、用户消息、Agent 消息、命令输入区、发送、引导、取消、重试和 pending 状态展示。
- 基本工作台 Agent 调用,包括最小任务输入、发送、短返回执行标识、状态查询入口和失败原因展示。
- 工作台诊断入口、运行状态摘要、probe/build/HWPOD/Agent 状态的低噪声展示方式。
- 桌面多栏布局、侧栏折叠、移动端工作台布局和输入区可达性。
@@ -65,7 +65,8 @@ Web工作台负责 HWLAB 登录后的浏览器主入口,使用户能够在同
| 低噪声展示 | 诊断、trace、状态和辅助信息不抢占主任务区,也不伪装成用户或 Agent 正文。 |
| 响应式工作台 | 同一工作台在桌面和移动端按不同可视空间重排,但仍优先保证任务输入和状态理解。 |
| 同源业务入口 | Cloud Web 与 HWLAB CLI 通过同一 Web origin、相对 REST/JSON API path 和业务标识访问 HWLAB 能力的入口。 |
| Conversation权威入口 | Web 工作台按 conversationId 恢复当前会话消息、session 绑定、thread、lastTraceId 和状态的 RESTful detail API。 |
| 浏览器登录态 | Cloud Web 随同源请求携带的 `hwlab_session` 等 Web session transport;前端只负责传递,不解释权限、project 归属或资源可见性。 |
| Session权威入口 | Web 工作台按 sessionId 或后端认可的 opaque session handle 恢复当前会话消息、turn 摘要、trace 指针和状态的 RESTful detail API。 |
| 共享 trace renderer | Web trace 面板和 HWLAB CLI `trace --render web` 共用的 trace row 转换语义。 |
| Trace阅读视图 | 工作台中面向用户阅读 Code Agent trace 的默认视图,只展示用户可理解的助手消息、工具调用、命令输出、最终结果和真实耗时,把运行身份、隐藏统计和原始事件收束到消息详情入口。 |
| 消息详情入口 | Agent 消息头部右上角的小型详情按钮,用于按需查看 trace id、session、run、command、raw event、隐藏统计和审计控制等调试信息。 |
@@ -223,11 +224,11 @@ Web工作台应让用户在主任务区直接选择或创建会话、阅读用
Web工作台必须使用显式 Agent session:无 session 时先让用户创建或选择 sessionsession failed、stale 或 canceled 时保留失败状态并要求用户显式切换或新建。刷新页面、重新打开工作台或短连接 result 轮询只能恢复已选 session、thread 和 trace 状态;除非用户登出或主动清空对话,不得自动生成新 conversation、替换 session 或用历史 prompt 拼接出续跑表象。
会话列表、当前消息头、composer 主按钮和运行态动效必须先确定唯一权威 API,再由 Web 展示该 API 的结果;不得让 workspace selected conversation、snapshot、stub、localStorage、message 派生状态、trace 快照或浏览器临时缓存与权威 API 并列竞争、互相覆盖或按失败路径 fallback 成另一套数据源。已经定下来的权威 API 绑定如下:session rail 会话集合的唯一入口是 `/v1/agent/conversations`,当前 conversation 消息本体和 session/thread/lastTraceId 绑定的唯一入口是 `/v1/agent/conversations/{conversationId}`session 运行状态的唯一入口是 `sessionId` 绑定的 session 状态 APICode Agent turn/trace 阅读状态的唯一入口是 `traceId` 绑定的 trace/result snapshot API。深链恢复、刷新、从其他 session 切回和 route watcher 应走同一 conversation detail 加显式 select/update 路径,不得先用 workspace selected snapshot、列表摘要或空 stub 覆盖当前 `messages`,再等待另一路请求补齐。
会话列表、当前消息头、composer 主按钮和运行态动效必须先确定唯一权威 API,再由 Web 展示该 API 的结果;不得让 workspace selected conversation、snapshot、stub、localStorage、message 派生状态、trace 快照或浏览器临时缓存与权威 API 并列竞争、互相覆盖或按失败路径 fallback 成另一套数据源。已经定下来的 authority 不变量如下:浏览器登录态只作为请求 transport;资源归属、project 可见性和权限由后端从当前 Web session/AuthPrincipal 判定;session rail 会话集合的入口是 `/v1/workbench/sessions`,当前 session 消息本体的主入口是 `/v1/workbench/sessions/{sessionId}/messages`session metadata 的主入口是 `/v1/workbench/sessions/{sessionId}`turn 状态的主入口是 `TurnSnapshot`Trace 阅读状态的入口是 `TraceEventPage``projectId``workspaceId``conversationId` 可以作为后端返回的上下文字段、显式筛选字段或迁移期 metadata,但不得成为前端鉴权、资源可见性、active session 或 deep link 的 authority。深链恢复、刷新、从其他 session 切回和 route watcher 应走同一 session detail/message page 加显式 select/update 路径,不得先用 workspace selected snapshot、列表摘要或空 stub 覆盖当前 `messages`,再等待另一路请求补齐。
用户切换 session 标签、通过深链进入 conversation 或从其他 session 切回时,若当前主工作区的 conversation detail 尚未返回并应用,Web 工作台必须在主任务区显示明确的加载中转圈或等价 loading state。该状态表示已有会话正在加载,不等同于 Code Agent 已经加载完但尚未产生第一条可读消息的“思考中...”。Web 不得在主工作区尚未就绪时显示空对话、空 Code Agent 卡片、空 Trace 面板或静默留白,使用户无法判断切换是否生效。
用户切换 session 标签、通过深链进入 session 或从其他 session 切回时,若当前主工作区的 session detail/message page 尚未返回并应用,Web 工作台必须在主任务区显示明确的加载中转圈或等价 loading state。该状态表示已有会话正在加载,不等同于 Code Agent 已经加载完但尚未产生第一条可读消息的“思考中...”。Web 不得在主工作区尚未就绪时显示空对话、空 Code Agent 卡片、空 Trace 面板或静默留白,使用户无法判断切换是否生效。
当前 selected conversation 若需要出现在列表中,必须由列表 API 在显式 query/path/body 参数要求下返回,不得由后端隐藏读取 Web workspace selected 状态实现。Workspace API 只提供工作台选择、composer 配置和稳定业务 id,不作为 conversation 消息本体 authority;列表 API 只提供 rail 排序和摘要,不作为当前消息面板 authority。Web 只能把 route、用户显式选择或 workspace API 返回的稳定业务 id 作为权威 API 的显式参数,不得把前端拼接出的 status、final response、markdown、running 动效或 stub 传回后端变成事实。Web 在权威 API 失败时只能保留上一份成功结果或显示未加载/错误态,不得从 workspace selected snapshot、stub 或本地缓存拼出单条 session tab、running 状态或 final response。运行中的 turn 必须同时反映在主任务区和对应 session tab;已进入终态的 turn 不得继续以 `Code Agent 处理中`、running 动效或旧 snapshot 文案呈现。
当前 selected session 若需要出现在列表中,必须由 session list API 在显式 `includeSessionId` 或等价稳定业务 id 参数下返回,不得由后端隐藏读取 Web workspace selected 状态实现。Workspace API 只提供工作台选择、composer 配置和稳定业务 id,不作为 session 消息本体 authority;列表 API 只提供 rail 排序和摘要,不作为当前消息面板 authority。Web 只能把 route、用户显式选择或后端返回的稳定 session/turn/trace id 作为权威 API 的显式参数,不得把前端拼接出的 status、final response、markdown、running 动效或 stub 传回后端变成事实。Web 在权威 API 失败时只能保留上一份成功结果或显示未加载/错误态,不得从 workspace selected snapshot、stub 或本地缓存拼出单条 session tab、running 状态或 final response。运行中的 turn 必须同时反映在主任务区和对应 session tab;已进入终态的 turn 不得继续以 `Code Agent 处理中`、running 动效或旧 snapshot 文案呈现。
Agent 请求应采用短连接 submit 加 result/trace 轮询。`POST /v1/agent/chat` 或等价入口返回执行标识后,工作台通过 result 和 trace path 获取终态与可读过程,不持有一次长 HTTP 请求等待整个模型 turn。后端 result 已完成时,消息卡片必须替换为真实 final response;仍在 pending 或 trace 缺失时应显示明确状态,而不是把“result ready for polling”类中间文本当作最终回复。
@@ -301,15 +302,15 @@ Web工作台的正式浏览器入口必须来自目标 node/lane YAML 声明的
| --- | --- | --- | --- |
| CLIENT-WB-REQ-008 | 状态投影 | PJ2026-01040108 状态投影 | [PJ2026-010403 API契约](PJ2026-010403-api-contract.md)、[Agent编排](PJ2026-0102-agent-orchestration.md) |
Web工作台应把 REST snapshot、SSE event、submit optimistic、trace pagination 和 page refresh hydrate 统一归入 Workbench Server State。Server State 应按 sessionId、conversationId、messageId、partId、turnId 和 traceId 归一化保存服务端事实;UI transient state 只保存 route、显式选择、composer draft、scroll、展开状态和临时交互状态。
Web工作台应把 REST snapshot、SSE event、submit optimistic、trace pagination 和 page refresh hydrate 统一归入 Workbench Server State。Server State 应按 sessionId、messageId、partId、turnId 和 traceId 归一化保存服务端事实;conversationId、projectId 和 workspaceId 只能作为后端 metadata 或兼容映射字段挂接在对应 session/message 上,不得作为 active 对象、权限判断或恢复路径的 authority。UI transient state 只保存 route、显式选择、composer draft、scroll、展开状态和临时交互状态。
Timeline Projection 只能从 messages、parts、turn status 和 trace events 派生用户可见 rows。Trace detail 只消费 TraceEventPagesession rail 只消费 session list 和 turn summarycomposer 只消费当前 route/selected conversation 与明确 running turn。组件、trace polling、submit/cancel 回调不得直接写 messages、final response 或 trace authority。
Timeline Projection 只能从 messages、parts、turn status 和 trace events 派生用户可见 rows。Trace detail 只消费 TraceEventPagesession rail 只消费 session list 和 turn summarycomposer 只消费当前 route/selected session 与明确 running turn。组件、trace polling、submit/cancel 回调不得直接写 messages、final response 或 trace authority。
初发刷新一致性是 Web 工作台的硬约束:同一 prompt 从 admission 开始生成稳定 userMessageId、assistantMessageId、turnId 和 traceId;初发 UI 可以 optimistic 展示这些 ID,但刷新、切换 session、SSE 重连和 REST 补洞必须用同 ID 的 durable message、part、turn 和 trace projection 确认。若 trace events 缺失,只影响 trace detail;主 timeline 的用户消息、assistant final response 和 turn terminal 状态不得因此退化为“思考中”。
OpenCode 的参照边界是职责结构,不是技术栈照搬。可借鉴的边界包括 route/sessionKey 作为当前 session authority、per-session message/part cache、REST message page 与 optimistic message 通过同一 messageID 合并、SSE delta 只作为实时加速、完整 message/part snapshot 可重建刷新结果。HWLAB 不得继续让 workspace snapshot、trace polling、result polling、list summary 和 localStorage 共同竞争当前消息面板。
状态投影正确性必须能被独立浏览器回归验证覆盖。测试应在同一 Web 构建产物上使用 mock server 重放真实采集 fixture,断言 session rail、主 timeline、workspace card、composer、message card 和 trace detail 在 session 切换、刷新页面、SSE 断线重连、REST 补洞和 trace 分页补拉后保持同一组 conversationId、sessionId、turnId、traceId、messageId 与终态语义。测试不得依赖 live AgentRun、Cloud API、HWPOD、数据库或 Kubernetes 状态作为通过条件。
状态投影正确性必须能被独立浏览器回归验证覆盖。测试应在同一 Web 构建产物上使用 mock server 重放真实采集 fixture,断言 session rail、主 timeline、workspace card、composer、message card 和 trace detail 在 session 切换、刷新页面、SSE 断线重连、REST 补洞和 trace 分页补拉后保持同一组 sessionId、turnId、traceId、messageId 与终态语义conversationId/projectId/workspaceId 只可作为 metadata 被展示或调试,不得改变通过条件。测试不得依赖 live AgentRun、Cloud API、HWPOD、数据库或 Kubernetes 状态作为通过条件。
### 6.9 CLIENT-WB-REQ-009 前端模块
@@ -319,7 +320,7 @@ OpenCode 的参照边界是职责结构,不是技术栈照搬。可借鉴的
Web 工作台实现应按职能拆分为 API client、event/SSE client、server-state store、reducer、selectors/projection、trace event projection、composer UI state、session rail UI state 和具体 UI 组件。server-state 模块不得写 UI transient stateUI 组件不得直接合并 REST/SSE 响应;projection 模块不得发请求或写状态。
新增或重构的核心前端文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如 `SPEC: PJ2026-010401 Web工作台 draft-2026-06-17-r0; PJ2026-010403 API契约 draft-2026-06-17-r0`,并简述文件职责。实现文件不得只写 issue 编号、`latest``current` 作为规格引用。
新增或重构的核心前端文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如 `SPEC: PJ2026-010401 Web工作台 draft-2026-06-18-r1; PJ2026-010403 API契约 draft-2026-06-18-r1`,并简述文件职责。实现文件不得只写 issue 编号、`latest``current` 作为规格引用。
### 6.10 CLIENT-WB-REQ-010 浏览器回归
@@ -333,7 +334,7 @@ mock 数据应优先来自目标 node/lane 的真实受控样本,而不是从
合成 fixture 只能补足真实样本难以稳定覆盖的边界条件,例如延迟响应、SSE 断线、分页缺口、列表缺少当前选中项、可选字段格式异常、空集合和特定 HTTP 错误。每个合成 fixture 必须标明 `derivedFrom``syntheticReason`,不得替代可从真实运行面采集的常规会话、完成态、失败态或 Trace 数据。
浏览器回归验证至少覆盖以下用户可见路径:切换 session 后主工作区显示 loading 并恢复目标 conversation;刷新页面后以同一 message、turn 和 trace 标识还原 timelineSSE 事件丢失或重连后通过 REST snapshot 和 trace page 补洞;session 标签、workspace card、message card、composer 主按钮和 Trace 终态显示 running、completed、failed、canceled 等状态时保持一致;Trace 阅读视图按事件顺序渲染可读 row,正确处理分页、终态、失败、自动展开和终态折叠;深链进入 conversation 与普通点击 session 走同一 authority path。
浏览器回归验证至少覆盖以下用户可见路径:切换 session 后主工作区显示 loading 并恢复目标 sessionfresh browser context 深链进入 session 后以同一 message、turn 和 trace 标识还原 timelineSSE 事件丢失或重连后通过 REST snapshot 和 trace page 补洞;session 标签、workspace card、message card、composer 主按钮和 Trace 终态显示 running、completed、failed、canceled 等状态时保持一致;Trace 阅读视图按事件顺序渲染可读 row,正确处理分页、终态、失败、自动展开和终态折叠;深链进入 session 与普通点击 session 走同一 authority path,删除或归档 session 后 deep link 不得复活 archived active tab
测试实现应优先使用用户可见文本、ARIA role 和稳定 DOM 标识断言,不通过内部 store、localStorage 或后端数据库直接判定通过。失败时必须保留 Playwright screenshot、trace 或等价 artifact;关键路径可以生成命名截图用于人工审阅。远程执行默认在目标 node/lane 上通过 UniDesk Playwright route 运行,截图和报告应回传到调用端,但这些 artifact 只是验证证据,不进入业务事实或监控指标。
@@ -19,7 +19,7 @@
| 短名 | API契约 |
| 层级 | L2 课题 |
| 状态 | 已生效 |
| 实现引用版本 | draft-2026-06-17-r0 |
| 实现引用版本 | draft-2026-06-18-r1 |
| 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) |
| 上级规格 | [PJ2026-0104 客户端](PJ2026-0104-client.md) |
| 规格治理索引 | [规格治理](spec-governance.md) |
@@ -57,9 +57,10 @@ API契约负责定义 Cloud Web、HWLAB CLI 和自动化脚本共同使用的 RE
| 同源 API | Cloud Web origin 下的相对 REST/JSON HTTP API path,供浏览器和 HWLAB CLI 使用。 |
| route policy | 哪些 path 可以通过 Cloud Web 代理、哪些只能作为显式 Cloud API 诊断或内部服务调用的边界规则。 |
| AuthPrincipal | 后端根据 Web session 或 API key 恢复出的用户主体摘要。 |
| 业务标识 | sessionId、traceId、runId、commandId、workspaceId、caseId 等用户可继续查询的稳定标识。 |
| 业务标识 | sessionId、turnId、traceId、runId、commandId、caseId 等用户可继续查询的稳定标识projectId、workspaceId 和 conversationId 只能作为筛选、metadata 或兼容映射字段,不作为前端鉴权 authority。 |
| 错误语义 | HTTP status、错误码、blocker、failureKind、route 和下一步提示组成的可定位失败表达。 |
| Conversation detail | `GET /v1/agent/conversations/{conversationId}` 这类按稳定 conversationId 查询当前会话消息和绑定事实的 RESTful detail resource。 |
| Session detail | `GET /v1/workbench/sessions/{sessionId}` 这类按稳定 sessionId 或后端认可 opaque session handle 查询当前会话 metadata、消息指针和状态的 RESTful detail resource。 |
| Conversation detail | 迁移期兼容资源;可返回 conversation metadata、sessionId、threadId 和 message seed,但不得继续作为 Web deep link 或前端 active session authority。 |
| TurnSnapshot | 按 turnId 或 traceId 查询一次用户提交/steer/retry/cancel 生命周期、终态、message 指针和执行引用的 RESTful snapshot。 |
| TraceEventPage | 按 traceId 和 cursor/seq 分页查询 trace events 的 RESTful page;只表达 trace 明细,不决定主 timeline 的 final response。 |
| Message/Part | Web 和 CLI 共同渲染会话 timeline 的持久消息事实;message 表达角色、父子关系和终态摘要,part 表达文本、工具、文件、错误、trace 摘要等可组合内容。 |
@@ -72,7 +73,7 @@ API契约负责定义 Cloud Web、HWLAB CLI 和自动化脚本共同使用的 RE
| 边界项 | 内容 |
| --- | --- |
| 外部使用者 | Cloud Web、HWLAB CLI、自动化脚本、平台管理员和需要同源 API 的浏览器客户端。 |
| 外部输入 | HTTP method、相对 path、JSON body、query、Web session cookie、Authorization header、traceId、sessionId、workspaceId 和业务参数。 |
| 外部输入 | HTTP method、相对 path、JSON body、query、Web session cookie、Authorization header、sessionId、turnId、traceId 和业务参数;projectId、workspaceId、conversationId 只允许作为显式筛选或兼容 metadata 输入。 |
| 受控资源 | API path、schema、route policy、AuthPrincipal 摘要、错误码、响应摘要和兼容性契约。 |
| 外部输出 | JSON 响应、HTTP status、route、actor、业务标识、错误分类、脱敏状态、trace/result 指针和下一步查询提示。 |
| 用户接口 | Cloud Web 同源 API、HWLAB CLI 同源 REST request/client 命令、HTTP API。 |
@@ -104,9 +105,9 @@ API契约应定义 Cloud Web origin 下的相对 REST/JSON path 和 route policy
API契约必须区分同源 API path 与浏览器 history route`/auth*``/v1*``/health*` 等 API path 返回 JSON 语义,`/workbench``/login` 和其他 Cloud Web 页面路由由 Web工作台处理。API/edge 直达入口对页面路由返回 JSON 404 是正确边界,不应被改造成 SPA fallback;反过来,Web正式公开入口必须通过 route policy 把 API path 分流到 API 服务。
RESTful API 必须保持无状态请求语义:在相同 method、path、query、body、auth 主体和相同后端业务事实下,应返回同一语义结果;服务端不得为了补齐某个列表或状态而隐藏读取浏览器 workspace selected、localStorage、Web snapshot、上一次页面状态或其他客户端临时状态。列表窗口需要包含某个当前资源时,必须通过显式 query/path/body 传入稳定业务 id,例如 conversation list 通过显式 include conversation id 请求把当前 conversation 纳入同一列表响应;服务端只能校验该 id 对当前 actor 是否可见并返回后端事实,不得接受客户端拼接出的 status、final response、markdown、running 动效或 stub 作为事实来源。
RESTful API 必须保持无状态请求语义:在相同 method、path、query、body、auth 主体和相同后端业务事实下,应返回同一语义结果;服务端不得为了补齐某个列表或状态而隐藏读取浏览器 workspace selected、localStorage、Web snapshot、上一次页面状态或其他客户端临时状态。列表窗口需要包含某个当前资源时,必须通过显式 query/path/body 传入稳定业务 id,例如 session list 通过显式 include session id 请求把当前 session 纳入同一列表响应;服务端只能从当前 Web session/API key 恢复 AuthPrincipal校验该 id 对当前 actor 是否可见并返回后端事实,不得接受客户端拼接出的 project、workspace、status、final response、markdown、running 动效或 stub 作为事实来源。
当前会话消息恢复必须使用 RESTful detail resource`GET /v1/agent/conversations/{conversationId}` 是 conversation 消息、sessionId、threadId、lastTraceId、messageCount、firstUserMessagePreview 和会话状态的权威入口`GET /v1/workbench/workspace` 可以返回 selected ids、workspace revision 和 composer 配置,但不得成为消息本体 authority;`GET /v1/agent/conversations` 可以返回 rail 摘要和显式 include 的列表项,但不得替代当前 conversation detail。前端恢复、深链、刷新和 session 切换必须以稳定 conversationId 调用同一 detail resource,不得在 detail resource 失败时切到 workspace snapshot、列表摘要、JSON-RPC、内部 manager、浏览器缓存或空 stub 继续构造当前消息面板。
当前会话消息恢复必须使用 session 主路径:`GET /v1/workbench/sessions/{sessionId}` 返回 session metadata 和消息指针,`GET /v1/workbench/sessions/{sessionId}/messages` 返回 message/part pageturn 和 trace 分别由 `TurnSnapshot``TraceEventPage` 补洞`GET /v1/workbench/workspace` 可以返回 selected ids、workspace revision 和 composer 配置,但不得成为消息本体 authority;`GET /v1/workbench/sessions` 可以返回 rail 摘要和显式 include 的列表项,但不得替代当前 session detail/message page。前端恢复、深链、刷新和 session 切换必须以稳定 sessionId 或后端认可 opaque session handle 调用同一 detail/message resource,不得在 detail resource 失败时切到 workspace snapshot、conversation detail、列表摘要、JSON-RPC、内部 manager、浏览器缓存或空 stub 继续构造当前消息面板。
### 6.2 CLIENT-API-REQ-002 鉴权主体
@@ -124,7 +125,7 @@ API契约应以 AuthPrincipal 摘要表达 Web session 和 API key 恢复出的
| --- | --- | --- | --- |
| CLIENT-API-REQ-003 | Agent接口 | PJ2026-01040303 Agent接口 | [Agent编排](PJ2026-0102-agent-orchestration.md)、[用户管理](PJ2026-0105-user-management.md)、[PJ2026-010401 Web工作台](PJ2026-010401-web-workbench.md) |
API契约应定义显式 Agent conversation、session、chat、steer、cancel、result、trace 和 inspect 的用户可见 RESTful HTTP 形态,使 Web 和 HWLAB CLI 能围绕同一 sessionId、conversationId、threadId、traceId、runId 和 commandId 操作。
API契约应定义显式 Agent session、turn、chat、steer、cancel、result、trace 和 inspect 的用户可见 RESTful HTTP 形态,使 Web 和 HWLAB CLI 能围绕同一 sessionId、turnId、traceId、runId 和 commandId 操作。conversationId、threadId 可以作为后端返回的 metadata 或兼容映射字段存在,但不得替代 sessionId 成为 Web deep link 或 active authority。
Agent 接口不得通过 session latest、浏览器历史、旧 cache 或内部 manager 生成第二套 final response。Agent编排提供执行事实,用户管理校验 owner 和权限,客户端只稳定暴露用户入口。
@@ -140,14 +141,14 @@ Trace resource 必须支持按事件位置继续读取,例如 `sinceSeq` / `cu
| --- | --- | --- | --- | --- | --- |
| WorkspaceSelection | `GET /v1/workbench/workspace` | `projectId`, `workspaceId` 可选 | selected ids、workspace revision、composer 配置、public origin 摘要 | 200/401/403 | 只读 selection/config,不返回或修补 message 事实 |
| WorkspaceSelection | `PATCH /v1/workbench/workspace` | 显式 selected project/workspace/conversation ids | 更新后的 selection/config | 200/400/401/403 | 只有显式 mutation 可改变 selection |
| Session list | `GET /v1/workbench/sessions` | `projectId`, `workspaceId`, `cursor`, `limit`, `includeSessionId` | session/conversation rail 摘要 page | 200/401/403 | 列表和排序,不替代 detail |
| Session detail | `GET /v1/workbench/sessions/{sessionId}` | path sessionId | session metadata、当前 conversation 指针 | 200/401/403/404 | session metadata,不拥有 trace events |
| Session list | `GET /v1/workbench/sessions` | `cursor`, `limit`, `includeSessionId`,可选后端认可筛选字段 | session/conversation rail 摘要 page | 200/401/403 | 当前用户可见 session 列表和排序,不替代 detail |
| Session detail | `GET /v1/workbench/sessions/{sessionId}` | path sessionId | session metadata、message page 指针和当前 turn/trace 摘要 | 200/401/403/404 | session metadata,不拥有 trace events |
| Message page | `GET /v1/workbench/sessions/{sessionId}/messages` | `cursor`, `limit`, `before/after` | message + parts page、next cursor | 200/401/403/404 | 会话 timeline 的 message/part 事实 |
| Conversation detail | `GET /v1/agent/conversations/{conversationId}` | path conversationId | conversation metadata、message page seed、sessionId、threadId、lastTraceId、turn summary | 200/401/403/404 | 当前消息面板权威 detail |
| Turn admission | `POST /v1/workbench/sessions/{sessionId}/turns` | prompt/parts、delivery、workspace/project、client message ids | `202 Accepted` + turnId、traceId、userMessageId、assistantMessageId、status URLs | 202/400/401/403/409/422 | 只表示输入已接收,不表示执行完成 |
| Conversation detail | `GET /v1/agent/conversations/{conversationId}` | path conversationId | conversation metadata、message page seed、sessionId、threadId、lastTraceId、turn summary | 200/401/403/404 | 迁移期兼容 detail,不替代 session 主路径 |
| Turn admission | `POST /v1/workbench/sessions/{sessionId}/turns` | prompt/parts、delivery、client message ids、可选 metadata | `202 Accepted` + turnId、traceId、userMessageId、assistantMessageId、status URLs | 202/400/401/403/409/422 | 只表示输入已接收,不表示执行完成 |
| Turn snapshot | `GET /v1/workbench/turns/{turnId}` | path turnId | status、terminal、message ids、traceId、AgentRun refs、failureKind | 200/401/403/404 | turn 状态补洞,不承载 trace events |
| Trace event page | `GET /v1/workbench/traces/{traceId}/events` | `afterSeq/cursor`, `limit` | ordered events、range、hasMore、next cursor | 200/401/403/404/410 | trace 明细分页,不决定主 timeline final response |
| EventStream | `GET /v1/workbench/events` | `projectId`, `workspaceId`, optional session/turn filters | SSE events + heartbeat | 200/401/403 | 实时加速和通知,不替代 REST snapshot |
| EventStream | `GET /v1/workbench/events` | optional sessionId/turnId/traceId filters | SSE events + heartbeat | 200/401/403 | 实时加速和通知,不替代 REST snapshot |
| Cancel turn | `POST /v1/workbench/turns/{turnId}/cancel` | reason 可选 | updated TurnSnapshot | 200/202/401/403/404/409 | 精确取消目标 turn |
| Steer turn | `POST /v1/workbench/turns/{turnId}/steer` | text/parts、delivery | accepted steer TurnSnapshot 或 continuation id | 202/400/401/403/404/409 | 绑定明确 running turn |
| ProviderProfile | `GET /v1/workbench/provider-profiles` | project/workspace 可选 | profile summary list | 200/401/403 | 配置摘要,不输出 Secret |
@@ -155,7 +156,7 @@ Trace resource 必须支持按事件位置继续读取,例如 `sinceSeq` / `cu
所有 GET path 必须无业务副作用。需要 repair、finalize、sync 或 migration 时,应由后台 finalizer、显式 mutation 或持久化投影入口执行,不能隐藏在 workspace、conversation、turn 或 trace GET 中。所有分页响应必须包含稳定 cursor 或 seq 边界;所有错误响应必须包含 route、status、code/blocker、redacted actor、target resource 和下一步建议。
新增或重构的核心后端文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如 `SPEC: PJ2026-010403 API契约 draft-2026-06-17-r0; PJ2026-010205 HWLAB接入 draft-2026-06-17-r0`,并简述文件职责。实现文件不得只写 issue 编号、`latest``current` 作为规格引用。
新增或重构的核心后端文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如 `SPEC: PJ2026-010403 API契约 draft-2026-06-18-r1; PJ2026-010205 HWLAB接入 draft-2026-06-17-r0`,并简述文件职责。实现文件不得只写 issue 编号、`latest``current` 作为规格引用。
### 6.4 CLIENT-API-REQ-004 资源与管理接口