docs: define workbench sealed final response
This commit is contained in:
@@ -13,6 +13,7 @@ description: UniDesk Web 开发与浏览器验证技能。用户处理 UniDesk/H
|
||||
- 防分叉原则:Web/Workbench 修复必须先确定唯一 authority、唯一 API 契约和唯一状态投影入口;不得写成“当字段缺失/请求失败/状态不符/超时/刷新后,再改走另一个 endpoint、旧 workspace/conversation 模型、localStorage、trace polling、result polling、GET read-through repair、内部 manager、legacy route 或测试专用后门”。字段缺失、状态滞后或投影不完整时,修 schema、projector、read model 或正式 mutation 源头;代码里只能保留单一路径内的输入规范化、校验和错误暴露,不能用 `A ?? B`、`if missing then fallback`、兼容分支或双写双读把缺口遮住。
|
||||
- 禁止状态竞争行为:不得在代码、API、reducer、read model、fake-server 或测试中保留两个事实源,再用“覆盖、压过、override、优先级、优先采用、以 A 为准否则 B、A 赢过 B”等仲裁规则决定展示状态;这就是条件分叉和竞争投影。必须先定义唯一投影对象、唯一归属字段和唯一生成时机,让 UI/API 只消费该投影对象的单一状态;其他原始字段只能作为审计输入、诊断字段或待收敛数据,不能参与展示状态仲裁。
|
||||
- 严禁读侧推理:REST GET、SSE consumer、compat wrapper、CLI renderer、Web reducer/selectors、Trace renderer、fake-server 和测试断言都不能从 trace tail、message text、tool event、result cache、session summary、list row、workspace snapshot 或 localStorage 推断 turn/session/message 的 lifecycle、terminal、final response 或 running 状态。读侧只能读取唯一投影对象已经写好的字段;字段缺失、投影滞后或多字段矛盾时必须暴露 diagnostic/blocker 并修 projection writer/finalizer/schema,不得用 `result?.status ?? trace?.status`、最后一条 event `completed`、message fallback、session fallback、elapsed timeout 或 UI heuristic 补造事实。
|
||||
- Sealed final response 不可被读侧诊断覆盖:assistant final response 一旦由唯一 durable projection 写入 terminal/sealed 字段,主消息正文、finalResponse、message status 和 turn terminal 就是 sealed 用户结果;turn polling、trace hydration、SSE gap、realtime timeout、transport close、compat wrapper error 或 read model lag 只能进入 trace detail、transport diagnostics、projection diagnostics、session health 或消息详情入口,不能替换主 timeline 正文。
|
||||
- 无多路径、无 fallback:这是本技能的核心原则。Web、CLI、fake-server 和线上 web-probe 必须复用同一套 API 契约、同一 route/session/conversation/trace authority 和同一状态投影;不得为了让测试通过增加第二套 dispatcher、localStorage 真相、workspace snapshot 真相、内部 manager 调用、旧 lane 端口、raw request、临时兼容路径或“测试专用后门”。
|
||||
- 严禁事后 repair / 0repair:Web、Workbench、fake-server 和 web-probe 不得通过 reload、切换 session、realign、`sessionRepair`、workspace selection repair、active tab repair、GET read-through、SSE gap repair、localStorage truth 或测试 helper 自动点击,把已经分裂的 route/session/message/trace 状态补成看起来正确。合法页面必须在首次进入、刷新、deep link、session 切换和 SSE 重连时按同一权威自然收敛;不一致必须暴露为 blocker/diagnostic,并修 schema、projector、read model、reducer 或 route authority 源头。允许 session-bound hydrate/gap-fill 只写目标 session 自己的 cache/read model,不得改变 active selection、URL 或当前消息区。
|
||||
- Workbench GET 纯读投影:`GET /v1/workbench/*` 只能读取已持久化的 Workbench 投影事实并组装摘要;不得在 GET 中调用 AgentRun、Code Agent 或其他上游执行面做同步、补事件、修 trace、finalize terminal、改 running/completed 或写 message/session。投影滞后必须显式暴露 `projectionStatus`、`lastProjectedSeq`、`sourceRunId`、`blocker` 或等价诊断字段,并由后台 projector/finalizer 或显式受控 mutation 处理;刷新页面、切换 session 或打开详情不能成为事实推进入口。
|
||||
@@ -114,6 +115,7 @@ Workbench 至少覆盖:
|
||||
- 刷新页面后以同一 message/turn/trace 标识还原 timeline;
|
||||
- SSE 断线、丢事件或重连后通过 REST snapshot 与 trace page 补洞;
|
||||
- session tab、workspace card、message card、composer 主按钮、Trace detail 的 `running`/`completed`/`failed`/`canceled` 一致性;
|
||||
- completed assistant 已 sealed 后,turn snapshot、trace event page、SSE 或 realtime diagnostic 失败不覆盖主消息正文,诊断只进入详情/感叹号/transport health;
|
||||
- Trace 阅读按事件顺序渲染可读 row,正确处理分页、终态、失败、自动展开和终态折叠;
|
||||
- deep link 与普通点击 session 走同一 authority path;
|
||||
- Performance 页的摘要、错误态、刷新、移动端表格可达性和低基数脱敏展示。
|
||||
@@ -130,6 +132,7 @@ Workbench 至少覆盖:
|
||||
|
||||
- Workbench API 的 GET 路径不是修复入口。若 session/messages/turn/trace 出现状态不一致,应登记为投影唯一性或投影延迟问题,修 backend projector/read model;不得用前端轮询、session 切换、reload、read-through sync 或 GET 内部修复把问题掩盖。
|
||||
- Workbench 读侧不得推理生命周期。`turn.status`、`message.status`、`session.running`、`trace terminal`、`finalResponse`、`projectionStatus` 只能来自唯一 durable projection;trace event row 的 `completed` 只表示该 event/tool row 完成,不能终结 turn;message 文本为空只表示无可展示正文,不能生成占位 final response;list summary、session detail、turn snapshot、trace page 之间的差异只能作为 diagnostic,不得用优先级函数在读侧“选一个看起来合理的状态”。
|
||||
- Workbench sealed final response 必须与读侧诊断分仓。`messageProjection` 承载 role/status/text/finalResponse/sealedAt,`traceDetail` 承载 events/page hydration/trace diagnostics,`sessionStatus` 承载 rail/card 运行摘要,`transportDiagnostics` 承载 SSE/poll/hydration timeout 等可见性诊断;等价结构可以使用不同命名,但主消息投影和 diagnostic 不能竞争同一字段。`showMessageText()`、message diagnostic selector 和组件模板不得让 diagnostic 压过 sealed final response。
|
||||
- Workbench durable projection 验收必须覆盖同一 session/trace 的 list、detail、messages、turn、trace events 和 DOM session tab/message card;尤其要用 fresh browser 或 runtime 重启后的历史 terminal 样本证明 read model 能从 durable trace events 恢复终态。若内存 trace 仍显示 running 而 durable trace 已 terminal,应修唯一 read model 的投影对象,不得在 GET handler、前端 reducer 或 probe 脚本里做临时状态仲裁。
|
||||
- HWLAB #1585/#1596 是 Workbench 投影禁令的固定判例:AgentRun 已 terminal 但 Workbench 停在旧 seq 时,不得用 GET/read-side 补 result;turn/card completed 但 TraceEventPage seq/range 不合法时,不得用 completed 状态压过 trace 不可读事实。合法修复是后台 projector/resumer 补 durable projection,或在同一 trace event 快照内修正分页输出契约;不得推断 lifecycle、补写 GET、切 session/reload 修页面或添加多来源优先级。
|
||||
- Session rail 会话集合只消费 `/v1/workbench/sessions`;当前 session detail 只消费 `/v1/workbench/sessions/{sessionId}`;消息本体只消费 `/v1/workbench/sessions/{sessionId}/messages`;turn 状态只消费 `/v1/workbench/turns/{traceId}`;trace 阅读只消费 `/v1/workbench/traces/{traceId}/events` 或正式 trace event page。不要让 workspace snapshot、列表摘要、localStorage、trace polling 或 result polling 互相覆盖。
|
||||
@@ -139,6 +142,7 @@ Workbench 至少覆盖:
|
||||
- 显式新建或选择 session 是 active selection 的 mutation authority;`POST /v1/agent/sessions` 返回 201 或用户点击目标 session 后,URL、active tab、当前消息区和 composer 必须立即归属目标 session。目标 session detail/messages 慢只能表现为该目标 session 的 loading/empty 态;旧 session 的 list refresh、detail、turn、trace、SSE 迟到事件只能更新旧 session 自己的 cache/status,不得继续占据或夺回 active route、message area、composer/cancel 状态。
|
||||
- 读侧没有破坏性投影权。`GET /v1/workbench/sessions`、session detail、messages、SSE、route hydrate 或 refreshSessions 的失败、404、空列表、网络错误和迟到响应,只能显示 loading/degraded/unknown/blocker 或保留上一份成功投影;不得 `forgetSession()`、`replaceActiveSessionSelection(null)`、清空 messages/tabs,或把 composer 改成 `session_required`。deleted/archived/not-found 必须来自后端 canonical lifecycle projection,或来自用户显式 DELETE mutation 成功后的展示更新。
|
||||
- terminal failure、blocked、canceled 都是最终结果;若 API 返回可读 error/blocker,final response 展示区必须直接显示,不能只放在 trace rows 或详情面板中。
|
||||
- completed、failed、canceled、blocked 的 sealed final result 一旦显示,后续 polling/hydration/SSE/realtime 的 timeout、500、gap、close 和 lag 只能改变诊断区,不得把已显示 final response 闪回 `Code Agent 代理暂时无法连接上游`、`turn 超时无新活动`、`projection-resume:sync-failed` 或同类读侧错误态。
|
||||
- session 切换验收必须覆盖点击态和持久化恢复态:选择目标 session、确认 route/session list/detail/messages 归属同一 `sessionId`、刷新后同一 session 仍 active。
|
||||
- completed turn / Trace 重放 / deep link 验收必须用 fresh browser context 或等价 fresh login 直接打开 `/workbench/sessions/<sessionId>`,不能只用同页 reload。
|
||||
- 0repair 验收必须用 fresh context 直达 session/deep link,或从当前 session 显式切换到目标 session;不得依赖测试 helper 选择、reload、切走再切回、`sessionRepair` 或 `realignFreshSession` 修正页面后再判通过。旧 session 的延迟 detail、turn、trace、SSE 或 refreshSessions 晚到,只能更新该 session cache/list,不能改变 active URL、active tab、current messages 或 composer。
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
| 短名 | Web工作台 |
|
||||
| 层级 | L2 课题 |
|
||||
| 状态 | 已生效 |
|
||||
| 实现引用版本 | draft-2026-06-18-r1; PJ2026-0104010803 唯一投影 draft-2026-06-18-p0-zero-repair |
|
||||
| 实现引用版本 | draft-2026-06-18-r1; PJ2026-0104010803 唯一投影 draft-2026-06-19-p2-terminal-sealed-final-response |
|
||||
| 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) |
|
||||
| 上级规格 | [PJ2026-0104 客户端](PJ2026-0104-client.md) |
|
||||
| 规格治理索引 | [规格治理](spec-governance.md) |
|
||||
@@ -77,6 +77,7 @@ Web工作台负责 HWLAB 登录后的浏览器主入口,使用户能够在同
|
||||
| Workbench Server State | Web 工作台从 REST snapshot、SSE event、trace page 和 submit optimistic 归一化得到的服务端事实缓存。 |
|
||||
| Timeline Projection | 只从 messages、parts、turn status 和 trace events 派生用户可见 timeline row 的渲染投影,不发请求也不写事实状态。 |
|
||||
| 唯一投影 | [PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 定义的状态链路:AgentRun 执行事实只经 HWLAB projection writer/finalizer 写入 durable Workbench facts,REST、SSE、CLI、fake-server 和 Web 前端只消费该投影。 |
|
||||
| sealed final response | 唯一投影 terminal commit 写入的 assistant 主正文、finalResponse、message/turn terminal status 和 sealed 标记;它是主消息区用户结果的唯一权威,不被后续读侧诊断、trace hydration 失败、turn polling 失败或 SSE gap 覆盖。 |
|
||||
| 破坏性投影权 | 删除 session、清空 active session、清空当前消息页、把 composer 改为无 session 或把 session lifecycle 改写为 not-found/archived/deleted 的权力。Web 前端 reducer、selectors、route hydrate、GET/list/detail/messages/SSE consumer 和测试 helper 没有破坏性投影权;只有显式用户 mutation 成功或后端 canonical lifecycle projection 可以改变这些事实。 |
|
||||
| 读侧推理 | Web、API、CLI、fake-server 或测试根据 trace tail、message text、tool event、result cache、session summary、list row、workspace snapshot、localStorage 或 elapsed timeout 推断 lifecycle、terminal、running 或 final response 的行为;Web工作台禁止该模式。 |
|
||||
| 0repair | Web 工作台在首次进入、刷新、deep link、session 切换、SSE 重连和 trace 补洞时必须按同一 authority 自然收敛;不得通过 reload、切走再切回、`sessionRepair`、`realignFreshSession`、workspace selection repair、active tab repair、GET read-through、localStorage truth 或测试 helper 自动点击,把已经分裂的 route/session/message/trace 状态补成看起来正确。 |
|
||||
@@ -207,7 +208,7 @@ flowchart LR
|
||||
|
||||
### 5.4 PJ2026-0104010803 Workbench唯一投影专项
|
||||
|
||||
[PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 是 Workbench 状态投影的唯一专项规格,集中定义 durable facts schema、`WorkbenchProjectionWriter`、`WorkbenchProjectionFinalizer`、`WorkbenchFactsStore`、`WorkbenchReadModel`、terminal commit、cloud-api 重启恢复、GET 纯读和代码引用规则。
|
||||
[PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 是 Workbench 状态投影的唯一专项规格,集中定义 durable facts schema、`WorkbenchProjectionWriter`、`WorkbenchProjectionFinalizer`、`WorkbenchFactsStore`、`WorkbenchReadModel`、terminal commit、sealed final response、cloud-api 重启恢复、GET 纯读和代码引用规则。
|
||||
|
||||
Web工作台在本规格中只保留前端消费边界:Cloud Web reducer、selectors、session rail、timeline、composer 和 Trace detail 只能消费该专项定义的 durable projection;SSE 只是 projection commit 后的通知和加速;fake-server fixture 只重放同一 REST/SSE 合同。Web reducer/selectors、Trace renderer、CLI renderer、fake-server 和测试断言不得从 trace tail、message text、tool event、result cache、session summary、list row、workspace snapshot、localStorage 或 elapsed timeout 推断 lifecycle、terminal、running 或 final response。详细架构图、数据流图、关键时序图、0repair 和严禁读侧推理约束以专项规格为准,本文不再维护第二份投影架构正文。
|
||||
|
||||
@@ -331,6 +332,8 @@ Timeline Projection 只能从 messages、parts、turn status 和 trace events
|
||||
|
||||
Web 工作台严禁读侧推理。`turn.status`、`message.status`、`session.running`、`trace terminal`、`finalResponse` 和 `projectionStatus` 只能来自唯一 durable projection。Trace event row 的 `completed` 只表示该事件或工具行完成,不能终结 turn;message text 为空只表示无可展示正文,不能生成占位 final response;session list summary、workspace selected state、localStorage mirror、轮询耗时或 elapsed timeout 不能改写 running/terminal。若 API 返回缺字段、投影滞后或多字段矛盾,Web 只能展示 loading、degraded、unknown 或 blocker,并把问题暴露给投影层修复,不得在 reducer、selector、组件或测试 helper 中合成“看起来正确”的状态。
|
||||
|
||||
Web 工作台必须把主消息投影、trace detail、session status 和 transport diagnostics 分仓保存。对已经带有 `sealedAt` 或等价 sealed 标记的 assistant message/turn,turn polling 失败、trace hydration 失败、SSE gap、realtime timeout、late compat wrapper error 或 elapsed timeout 只能更新诊断 bucket 或消息详情入口,不得替换主 timeline 的正文、finalResponse、message status 或 turn terminal。`showMessageText()`、message diagnostic selector、Trace 面板和组件模板不得让读侧诊断文案压过 sealed final response;需要修改 sealed 主正文时只能来自同一 durable projection 的新 revision、受控 replay/reprojection 或明确用户 mutation。
|
||||
|
||||
Web reducer/selectors 必须同时遵守无破坏性投影权。读侧路径中的 `forgetSession`、`replaceActiveSessionSelection(null)`、清空 messages、清空 tabs、把 composer 降级为 `session_required` 或把 route session 标记为 not-found/archived/deleted,都是 lifecycle mutation,不能由 GET/list/detail/messages/SSE 失败、空响应、404、route hydrate、refreshSessions 或 late response 触发。读侧只能把目标 session 的 loading、degraded、unknown、blocker 或 canonical lifecycle projection 展示出来;若需要删除、归档或失活,必须走后端 lifecycle projection 或用户显式 mutation 的成功结果。
|
||||
|
||||
初发刷新一致性是 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 状态不得因此退化为“思考中”。
|
||||
@@ -339,6 +342,8 @@ OpenCode 的参照边界是职责结构,不是技术栈照搬。可借鉴的
|
||||
|
||||
状态投影正确性必须能被独立浏览器回归验证覆盖。测试应在同一 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 状态作为通过条件。
|
||||
|
||||
状态投影回归还必须覆盖 sealed final response:completed assistant 正文已经显示后,turn snapshot、trace event page、SSE 或 realtime diagnostic 返回 timeout/500/gap/close 时,主消息正文和终态保持不变,诊断只进入 trace detail、transport diagnostic、session health 或消息详情入口。测试必须用用户可见 DOM 断言,不通过内部 store 或 localStorage 判定通过。
|
||||
|
||||
浏览器回归验证必须先覆盖 0repair 红灯:fresh context 直达 session、普通点击切换 session、A session 延迟 detail/turn/trace/SSE 晚到、B session active、无用户新消息时,都不得让 A 的 user/agent 消息、running 状态或 trace 出现在 B。Playwright 和 web-probe 只能观察、连续截图和断言;不得用 reload、切换 session、`sessionRepair`、`realignFreshSession` 或 localStorage 修改把页面修正后再判通过。
|
||||
|
||||
### 6.9 CLIENT-WB-REQ-009 前端模块
|
||||
@@ -367,6 +372,8 @@ mock 数据应优先来自目标 node/lane 的真实受控样本,而不是从
|
||||
|
||||
状态投影回归必须覆盖新建 session 后读侧失败的负向用例:用户显式 create mutation 成功并进入新 session 后,即使随后的 session detail、messages、list refresh、SSE 或 route hydrate 返回失败、404、空列表或网络错误,URL、active tab、当前消息区和 composer 仍归属新 session;页面可以展示该 session 的 loading/degraded/blocker,但不得回退到旧 session、清空 active selection、清空 tabs/messages 或显示 `session_required`。这类用例必须作为 fake-server Playwright 红灯保留,线上 web-probe 只做同一 public origin 的原入口验收,不用 repair helper 修正页面后判通过。
|
||||
|
||||
状态投影回归还必须覆盖 completed assistant 已 sealed 后的读侧失败负向用例:fixture 中 session messages API 返回 completed final response,随后 turn snapshot、trace event page、SSE 或 realtime diagnostic 失败。主 timeline 的 sealed final response 不变,诊断只显示在详情/感叹号/transport health 区域;Trace detail 延迟返回或分页缺口不得 remount 主消息卡片,也不得重置用户展开/折叠控制。
|
||||
|
||||
测试实现应优先使用用户可见文本、ARIA role 和稳定 DOM 标识断言,不通过内部 store、localStorage 或后端数据库直接判定通过。失败时必须保留 Playwright screenshot、trace 或等价 artifact;关键路径可以生成命名截图用于人工审阅。远程执行默认在目标 node/lane 上通过 UniDesk Playwright route 运行,截图和报告应回传到调用端,但这些 artifact 只是验证证据,不进入业务事实或监控指标。
|
||||
|
||||
## 7. 过程控制
|
||||
|
||||
+24
-7
@@ -19,7 +19,7 @@
|
||||
| 短名 | Workbench唯一投影 |
|
||||
| 层级 | L4 专项规格切片 |
|
||||
| 状态 | 已生效 |
|
||||
| 实现引用版本 | draft-2026-06-19-p1-agentrun-incremental-cursor |
|
||||
| 实现引用版本 | draft-2026-06-19-p2-terminal-sealed-final-response |
|
||||
| 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) |
|
||||
| 上级规格 | [PJ2026-010401 Web工作台](PJ2026-010401-web-workbench.md) |
|
||||
| 关联规格 | [PJ2026-010403 API契约](PJ2026-010403-api-contract.md)、[PJ2026-010205 HWLAB接入](PJ2026-010205-hwlab-dispatch.md)、[PJ2026-0102 Agent编排](PJ2026-0102-agent-orchestration.md) |
|
||||
@@ -35,6 +35,8 @@ Workbench唯一投影负责把 AgentRun 执行事实收敛成 HWLAB 自有的 du
|
||||
|
||||
本专项的目标状态是:AgentRun run、command、event 和 result 只作为执行事实输入;HWLAB 只有 `WorkbenchProjectionWriter`、`WorkbenchProjectionFinalizer` 写入 Workbench facts;cloud-api boot/background scheduler 是 startup/resume 的 authority,负责扫描 durable open checkpoint 和 running/projecting turn 并恢复追平;所有 `GET /v1/workbench/*` 和兼容读路径都只通过 `WorkbenchReadModel` 读取,不在读取时调用 AgentRun、Code Agent manager、trace polling、result polling 或 workspace repair 推进事实。Workbench 必须满足 0repair:页面、GET、SSE、fake-server 和 web-probe 都不得通过 reload、切换 session、`sessionRepair`、`realignFreshSession`、localStorage truth 或 read-through repair 把已经分裂的 route/session/message/trace 状态补成看起来正确。
|
||||
|
||||
Terminal final response 是 Workbench 投影的 sealed 用户结果。Projection writer/finalizer 一旦把 assistant final text、terminal status 和 `sealedAt` 或等价 sealed 标记写入同一 durable terminal commit,主消息区的正文、finalResponse 和 terminal status 就只能由后续同一写侧投影的受控 replay/reprojection 修正;turn polling、trace hydration、SSE gap、realtime timeout、transport close、read model lag 或 compat wrapper 失败只能写入 trace detail、transport diagnostic、projection diagnostic 或 session health,不能覆盖 sealed 主正文。
|
||||
|
||||
### 2.2 范围内
|
||||
|
||||
- AgentRun facts 到 Workbench facts 的标准映射、幂等写入和 terminal commit 语义。
|
||||
@@ -42,6 +44,7 @@ Workbench唯一投影负责把 AgentRun 执行事实收敛成 HWLAB 自有的 du
|
||||
- `WorkbenchFactsStore`、`WorkbenchProjectionWriter`、`WorkbenchProjectionFinalizer` 和 `WorkbenchReadModel` 的组件边界。
|
||||
- AgentRun events 增量拉取 cursor、projection state、result sync state 和 cloud-api 重启后按 durable cursor 继续投影的语义。
|
||||
- cloud-api 进程重启、进程内后台任务丢失、慢任务超过短轮询预算后的 durable finalizer 追平语义。
|
||||
- Terminal final response 的 sealed 字段、diagnostic 分仓和 sealed 后不可被读侧失败覆盖的显示语义。
|
||||
- `GET /v1/workbench/*` 纯读、`/v1/agent/*` compat wrapper 降级和 projection diagnostics 输出要求。
|
||||
- Web reducer、CLI renderer、fake-server fixture 和 Playwright 回归对同一 durable projection 的消费规则。
|
||||
- 本专项范围内新增或重构源码文件的 SPEC 头部引用规则。
|
||||
@@ -68,6 +71,7 @@ Workbench唯一投影负责把 AgentRun 执行事实收敛成 HWLAB 自有的 du
|
||||
| checkpoint replay/reprojection | 受控管理入口按已持久化 sourceRun/sourceCommand/checkpoint 重放投影逻辑,用于恢复投影 lag 或阻塞;它只能调用同一 finalizer/writer,不由 GET、Web 页面、SSE 订阅或测试 helper 触发,也不得改变 active session 或 route。 |
|
||||
| projection commit | writer/finalizer 对一组 message、part、turn、trace、session summary 和 checkpoint 的一次幂等持久化提交;terminal commit 必须保持用户可见事实一致。 |
|
||||
| terminal commit | 标记同一 turn 结束的 projection commit,必须原子更新 assistant final text、message/part status、turn terminal、trace terminal event、session running=false、summary 和 SSE cursor。 |
|
||||
| sealed final response | terminal commit 写入的 assistant 主正文、finalResponse、message/turn terminal status 和 `sealedAt` 或等价 sealed 标记;它是主消息区用户结果的唯一权威,不参与后续读侧 diagnostic 竞争。 |
|
||||
| projectedSeq | HWLAB trace event 和 projection commit 的单调序列,用于 REST 分页、SSE replay、fake-server fixture 和审计;不得与 AgentRun `sourceSeq` 混用。 |
|
||||
| sourceSeq/sourceEventId | AgentRun event/result 的来源序列或来源事件标识,只作为映射审计字段和幂等输入,不作为 Workbench trace page cursor。 |
|
||||
| checkpoint | finalizer 已成功投影到某个 sourceRunId/sourceCommandId/sourceSeq 的 durable 位置记录,用于 cloud-api 重启或后台任务丢失后继续追平。 |
|
||||
@@ -75,6 +79,7 @@ Workbench唯一投影负责把 AgentRun 执行事实收敛成 HWLAB 自有的 du
|
||||
| result sync state | AgentRun `/result` 归档或终态补全的低优先级状态;它不得阻塞运行中 events projection。 |
|
||||
| sourceLatestSeq | finalizer 在本次或最近一次拉取中观察到的 AgentRun command 最新 sourceSeq,用于诊断投影 lag;它不得替代 lastSourceSeq 成为已提交事实。 |
|
||||
| projection diagnostic | 暴露 projection lag、blocker、lastProjectedSeq、sourceRunId、sourceCommandId、updatedAt 和恢复状态的可诊断字段。 |
|
||||
| transport diagnostic | SSE、turn polling、trace hydration、result sync、realtime timeout 或浏览器网络层观察到的可见性诊断;它只能描述传输或读侧健康,不拥有 message text、finalResponse 或 terminal status 写权。 |
|
||||
| projection health | 对 projection diagnostic 的只读解释,状态至少区分 `projecting`、`caught-up`、`degraded` 和 `stalled`;它不推进 facts,也不得把 stale projecting 标为 caught-up。 |
|
||||
| TraceEventPage | 由 WorkbenchReadModel 返回的 trace 分页事实,必须按 `projectedSeq` 单调排序,并保持 `range.fromSeq <= range.toSeq`;空页用显式 empty range 表达,不生成非法区间。 |
|
||||
| compat wrapper | 旧 `/v1/agent/*` 或 conversation path 的兼容包装层;只能调用 `WorkbenchReadModel` 或正式 mutation,不拥有第二套事实写入或 read-through repair。 |
|
||||
@@ -91,7 +96,7 @@ Workbench唯一投影负责把 AgentRun 执行事实收敛成 HWLAB 自有的 du
|
||||
| 外部使用者 | Cloud Web、HWLAB CLI、Cloud API route、AgentRun adapter、fake-server 回归和运维诊断。 |
|
||||
| 外部输入 | AgentRun run/command/event/result facts、turn admission metadata、owner/session visibility、显式 checkpoint replay/reprojection 请求、REST/SSE 查询参数。 |
|
||||
| 受控资源 | Workbench facts、projection checkpoint、diagnostic、projectedSeq、session/message/part/turn/trace 查询模型和 SSE projection commit notification。 |
|
||||
| 外部输出 | session rail、session detail、message/part page、turn snapshot、trace event page、projection diagnostics、SSE events 和 compat wrapper envelope。 |
|
||||
| 外部输出 | session rail、session detail、message/part page、turn snapshot、trace event page、sealed final response、projection/transport diagnostics、SSE events 和 compat wrapper envelope。 |
|
||||
| 用户接口 | Cloud Web `/workbench`、同源 `/v1/workbench/*` REST/SSE、HWLAB CLI 的同源 Workbench/API 入口。 |
|
||||
| 系统边界 | 本专项只定义 Workbench 用户态事实的唯一写入和读取链路;它不定义 AgentRun 执行合同、用户权限策略、Web UI 布局或平台发布机制。 |
|
||||
|
||||
@@ -104,7 +109,7 @@ Workbench唯一投影负责把 AgentRun 执行事实收敛成 HWLAB 自有的 du
|
||||
| PJ2026-010401080303 | ProjectionFinalizer | 本规格 6.3 | checkpoint 驱动追平、重启恢复和显式 checkpoint replay/reprojection 的同一幂等入口 | FactsStore、AgentRun facts source | Writer、diagnostics |
|
||||
| PJ2026-010401080304 | ReadModel | 本规格 6.4 | session/message/turn/trace/projection diagnostics 的唯一读模型 | FactsStore、用户管理 visibility | REST GET、compat wrapper、CLI、fake-server |
|
||||
| PJ2026-010401080305 | CompatWrapper | 本规格 6.5 | 旧 `/v1/agent/*` 和 conversation path 到 ReadModel 或正式 mutation 的兼容映射 | API契约、ReadModel | Web/CLI 迁移期兼容 |
|
||||
| PJ2026-010401080306 | WebServerState | 本规格 6.6 | Web reducer/selectors 只消费 REST/SSE projection,不补写事实 | Web工作台、API契约 | session rail、timeline、composer、trace detail |
|
||||
| PJ2026-010401080306 | WebServerState | 本规格 6.6 | Web reducer/selectors 只消费 REST/SSE projection,分仓保存 sealed message projection、trace detail、session status 和 transport diagnostics | Web工作台、API契约 | session rail、timeline、composer、trace detail |
|
||||
| PJ2026-010401080307 | Regression | 本规格 6.7 | 后端红灯、fake-server Playwright、D601 web-probe 和分叉清零验收 | 平台运维、Web工作台 | issue 收口和防回归 |
|
||||
| PJ2026-010401080308 | CodeReference | 本规格 6.8 | 源码文件头部 SPEC 引用和实现版本追溯 | 规格治理 | 后续实现审计 |
|
||||
|
||||
@@ -242,9 +247,9 @@ Facts schema 至少包含以下事实:
|
||||
| fact | 必需字段 | 职责边界 |
|
||||
| --- | --- | --- |
|
||||
| session | sessionId/conversationId/threadId/projectId/workspaceId/owner/status/running/currentTurnId/summary/updatedAt | 会话可见性、rail 摘要和当前 turn 指针;不保存 provider Secret 或完整 prompt 原文之外的敏感负载。 |
|
||||
| message | messageId/sessionId/role/status/turnId/createdAt/updatedAt | timeline message 事实;assistant final text 通过 part 表达。 |
|
||||
| part | partId/messageId/type/status/text/tool/error/traceRef/order | 文本、工具、错误和 trace 摘要的可组合展示事实。 |
|
||||
| turn | turnId/sessionId/traceId/status/terminal/failureKind/sourceRunId/sourceCommandId/messageIds/startedAt/finishedAt | 一次用户提交、steer、retry 或 cancel 的生命周期事实。 |
|
||||
| message | messageId/sessionId/role/status/turnId/sealedAt/createdAt/updatedAt | timeline message 事实;assistant final text 通过 part 表达,sealedAt 或等价字段表示主消息结果已封存。 |
|
||||
| part | partId/messageId/type/status/text/tool/error/finalResponse/sealedAt/traceRef/order | 文本、工具、错误、final response 和 trace 摘要的可组合展示事实;final response part sealed 后不得被读侧 diagnostic 覆盖。 |
|
||||
| turn | turnId/sessionId/traceId/status/terminal/sealedAt/failureKind/sourceRunId/sourceCommandId/messageIds/startedAt/finishedAt | 一次用户提交、steer、retry 或 cancel 的生命周期事实。 |
|
||||
| trace event | traceId/projectedSeq/sourceSeq/sourceEventId/type/status/timestamp/redactedPayload | Workbench trace page 的分页事实;projectedSeq 是唯一 cursor。 |
|
||||
| checkpoint | turnId/traceId/sourceRunId/sourceCommandId/lastSourceSeq/lastProjectedSeq/sourceLatestSeq/status/attempt/lastAttemptAt/lastError/blocker/updatedAt | finalizer 追平位置、幂等边界、恢复状态和退避诊断。 |
|
||||
| diagnostic | sessionId/turnId/traceId/projectionStatus/health/lag/blocker/sourceRunId/sourceCommandId/lastSourceSeq/lastProjectedSeq/sourceLatestSeq/updatedAt | GET 和运维可见的 projection 状态,不推进事实。 |
|
||||
@@ -265,6 +270,8 @@ WorkbenchProjectionWriter 应作为唯一写入口,把 admission facts 和 nor
|
||||
|
||||
Writer 必须使用稳定幂等键写入 messageId、partId、turnId、traceId、sourceRunId、sourceCommandId、sourceSeq/sourceEventId 和 projectedSeq。重复 event、重放 result、重启恢复或 checkpoint replay/reprojection 不得创建重复 assistant message、重复 terminal event 或冲突 session summary。
|
||||
|
||||
Writer 的 terminal commit 必须同时写入 assistant final text、finalResponse part、message/turn terminal status、trace terminal fact、session running=false、checkpoint 和 `sealedAt` 或等价 sealed 标记。Completed、failed、canceled、blocked 都是 terminal result;若 AgentRun 或 projection 给出可读 final error/blocker,它必须作为 sealed final response 的一种结果写入,而不是作为后续 transport diagnostic 写入主正文。
|
||||
|
||||
### 6.3 WB-PROJ-REQ-003 projection finalizer
|
||||
|
||||
| 编号 | 短名 | 主责模块 | 关联模块 |
|
||||
@@ -281,6 +288,8 @@ Finalizer 的 cursor 必须以 command 和 checkpoint 为边界追平。对同
|
||||
|
||||
运行中投影必须以 AgentRun events 增量接口为主读源:finalizer/resume loop 使用 durable `lastSourceSeq` 调用上游 `events?afterSeq=<lastSourceSeq>&limit=<boundedPage>`,再按 commandId 和 seq window 过滤并提交 Workbench facts。running loop 不得为了恢复或刷新进度同步等待 `/result`,也不得在每次拉取时从 run seq 0、长 trace、result envelope 或历史 events 数组重新扫描。发现 terminal evidence 后,finalizer 可以把 projection 标记为 terminal/pending-result,并把 `/result` 同步交给后台低优先级归档;`/result` timeout 只能更新 `resultSyncState`、`lastError/blocker` 和 retry/backoff,不得阻止 events cursor 继续推进。
|
||||
|
||||
Finalizer 对 sealed turn 的后续重试只能推进 trace detail completeness、result archive、diagnostic health 或受控 replay/reprojection;不得把 `/result` timeout、events gap、provider transport error、poll idle timeout 或 hydration failure 映射成新的 assistant 主正文、finalResponse、message status 或 turn terminal status。
|
||||
|
||||
### 6.4 WB-PROJ-REQ-004 read model and pure GET
|
||||
|
||||
| 编号 | 短名 | 主责模块 | 关联模块 |
|
||||
@@ -293,6 +302,8 @@ WorkbenchReadModel 应作为唯一读模型,从 durable facts 组装 session l
|
||||
|
||||
Read model 严禁读侧推理。它不得从 `result?.status ?? trace?.status`、最后一条 trace event `status=completed`、message text 是否为空、part/tool row 状态、session list summary、workspace selected state、localStorage mirror、轮询耗时或 elapsed timeout 推断 turn terminal、message terminal、trace terminal、session running、final response 或 projection caught-up。若 durable facts 中唯一投影对象缺少这些字段,Read model 必须返回未知、投影中、degraded 或 blocker 等显式 diagnostic,由 projection writer/finalizer 修复源头;不得在读取时临时合成“看起来正确”的状态。
|
||||
|
||||
Read model 读取到 sealed final response 时,必须把主消息正文、finalResponse、message status 和 turn terminal 从 sealed projection 输出;projection diagnostic、trace hydration diagnostic、transport diagnostic、result sync diagnostic 和 session health 只能作为独立字段或详情区数据输出。读取链路不得因为后续 turn snapshot 失败、trace event page 失败、SSE gap、realtime timeout 或 compat wrapper 失败而替换 sealed 主正文。
|
||||
|
||||
Projection health 必须只解释 durable diagnostic。`projectionStatus=projecting` 且 `lastProjectedSeq < sourceLatestSeq`、checkpoint stale 超过受控阈值、存在 `lastError/blocker` 或 attempt 正在退避时,不得返回 `caught-up`;应返回 `projecting`、`degraded` 或 `stalled`,并暴露 `blocker`、`lastProjectedSeq`、`sourceRunId`、`sourceCommandId` 和更新时间。`caught-up` 只能表示对应 command checkpoint 已追平可见 source facts,或 source 明确仍 running 且无新可投影 facts。
|
||||
|
||||
Trace event page 必须按 `projectedSeq` 单调返回,响应范围必须合法。非空页满足 `range.fromSeq <= range.toSeq`;空页必须用明确空集合和空 range/null range 表达,禁止出现 `fromSeq=5/toSeq=4` 这类非法区间。`projectedSeq` 是 Workbench 读取 cursor,`sourceSeq` 只作为来源审计字段;二者不得混用。
|
||||
@@ -315,10 +326,14 @@ Trace event page 必须按 `projectedSeq` 单调返回,响应范围必须合
|
||||
|
||||
Cloud Web 应把 REST snapshot、SSE projection commit、trace event page 和 submit optimistic ids 归一化到同一 server-state/reducer/selectors。UI 组件只消费 selectors;组件、trace polling、result polling、localStorage、workspace snapshot 或 session list summary 不得直接写 final response、message terminal、turn terminal 或 trace authority。
|
||||
|
||||
Web server-state 必须分仓表达 `messageProjection`、`traceDetail`、`sessionStatus` 和 `transportDiagnostics`,或采用等价结构保证主消息投影与读侧诊断不会竞争同一字段。`messageProjection` 承载 role、status、text、finalResponse、turnId、traceId 和 sealedAt;`traceDetail` 承载 events、pagination、hydration 状态和 trace diagnostics;`sessionStatus` 承载 rail/card 运行摘要;`transportDiagnostics` 承载 SSE、poll、hydration timeout 或 realtime gap。Selectors 可以在消息详情入口汇总诊断,但主 timeline 的 sealed final response 不得被 diagnostic 文案替换。
|
||||
|
||||
active session 只能由 route sessionId 或用户显式选择产生。REST detail、session list、workspace summary、SSE event、trace page 或 turn snapshot 晚到时,只能更新其声明 sessionId 对应的 server-state bucket;不得重新选择 session、替换 URL、覆盖当前消息区、改变 composer 或把另一个 session 的 running/terminal 状态投射到当前页面。缺少 sessionId 或 session/trace 不匹配的 event 必须进入 authority mismatch diagnostic,不得猜测、fallback 或应用到当前 active session。
|
||||
|
||||
SSE 只作为 projection commit 后的通知和加速,不是事实来源。SSE 断线、丢事件或重连后,Web 只能通过同一 REST snapshot 与 trace page 补洞。running trace 在 terminal 前 `hasMore=false` 只表示当前页追平,不得设置永久 `fullTraceLoaded=true`。
|
||||
|
||||
Web reducer 必须提供 sealed guard:对已经有 `sealedAt` 或等价 sealed 标记的 assistant message/turn,turn polling、trace hydration、SSE gap、late realtime diagnostic、compat wrapper error 或 elapsed timeout 只能更新所属 trace/session 的 diagnostic bucket,不得写回 message text、finalResponse、message status 或 turn terminal。需要主动修改 sealed 主正文时,必须来自同一 durable projection 的新 revision、受控 replay/reprojection 或明确用户 mutation,而不是读侧失败。
|
||||
|
||||
### 6.7 WB-PROJ-REQ-007 regression and validation
|
||||
|
||||
| 编号 | 短名 | 主责模块 | 关联模块 |
|
||||
@@ -335,6 +350,8 @@ Durable recovery 红灯必须覆盖长 run、多 command 和大量旧事件场
|
||||
|
||||
fake-server Playwright 应使用目标 node/lane 的真实采集脱敏 fixture,覆盖 session 切换、刷新、SSE 断线重连、REST 补洞、trace 分页和 terminal final response。D601 v0.3 public origin web-probe 应验证不切 session、不刷新页面、fresh deep link 和多观察者场景都通过同一 read model 收敛。
|
||||
|
||||
Sealed final response 回归必须构造 completed assistant 主正文已经展示后,`/v1/workbench/turns/{traceId}`、`/v1/workbench/traces/{traceId}/events`、SSE 或 realtime diagnostic 发生 timeout/500/gap/close 的样本,断言主消息正文、finalResponse、message status 和 turn terminal 保持 sealed 不变,诊断只出现在 trace detail、transport diagnostic、session health 或消息详情入口。回归还必须覆盖 trace detail 延迟返回、分页缺口和用户手动展开/折叠状态,确保 late update 不 remount 主消息卡片、不重置用户控制状态。
|
||||
|
||||
0repair 验收必须先在 fake-server + Playwright 中形成红灯:fresh context 直达 session A、普通点击切到 session B、A 的 delayed detail/turn/trace/SSE 晚到、用户没有提交 B 的新消息时,B 的 URL、active tab、message card、composer 和 trace detail 不得出现 A 的 user/agent 文本、running 状态或 terminal trace。web-probe 必须连续截图观察提交前、running、中间态、terminal 和晚到事件;不得用 reload、切换 session、`sessionRepair`、`realignFreshSession`、localStorage 修改或 helper 自动点击修正页面后再判通过。
|
||||
|
||||
### 6.8 WB-PROJ-REQ-008 code reference rule
|
||||
@@ -346,7 +363,7 @@ fake-server Playwright 应使用目标 node/lane 的真实采集脱敏 fixture
|
||||
本专项范围内新增或重构的核心源码文件,文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如:
|
||||
|
||||
```text
|
||||
SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-19-p1-agentrun-incremental-cursor
|
||||
SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-19-p2-terminal-sealed-final-response
|
||||
```
|
||||
|
||||
同一文件同时承载 API契约、HWLAB接入、Web工作台或 Agent编排职责时,应在同一头部追加对应 SPEC 编号与实现引用版本。实现文件不得只写 issue 编号、`latest` 或 `current`。自动生成文件、第三方 vendored 文件、纯配置、锁文件和无法承载注释头的二进制产物可例外,但对应生成器、渲染器或配置入口必须能追溯到本 SPEC。
|
||||
|
||||
Reference in New Issue
Block a user