From 362926118a14f60773e17e1000e9aa7be100a8cc Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 18 Jun 2026 14:50:35 +0000 Subject: [PATCH] docs: add Workbench projection SPEC --- .../specs/PJ2026-0102-agent-orchestration.md | 2 +- .../specs/PJ2026-010205-hwlab-dispatch.md | 4 +- .../specs/PJ2026-010401-web-workbench.md | 68 +--- ...-0104010803-workbench-unique-projection.md | 321 ++++++++++++++++++ .../specs/PJ2026-010403-api-contract.md | 39 +-- 5 files changed, 334 insertions(+), 100 deletions(-) create mode 100644 project-management/PJ2026-01/specs/PJ2026-0104010803-workbench-unique-projection.md diff --git a/project-management/PJ2026-01/specs/PJ2026-0102-agent-orchestration.md b/project-management/PJ2026-01/specs/PJ2026-0102-agent-orchestration.md index 5b21a469..864825ea 100644 --- a/project-management/PJ2026-01/specs/PJ2026-0102-agent-orchestration.md +++ b/project-management/PJ2026-01/specs/PJ2026-0102-agent-orchestration.md @@ -140,4 +140,4 @@ Agent编排应原样消费 AgentRun 的 run、command、runner job、event、ter HWLAB 不应在客户端、adapter 或 prompt 中推断或补造 AgentRun 没有发出的事实。AgentRun 已正确输出时,HWLAB 负责消费和业务映射;AgentRun 合同缺失或行为错误时,应回到 AgentRun 实现与对应 OA 规格修复。 -PJ2026-0104010803 唯一投影切片要求 Agent编排只把 AgentRun run、command、event、terminal status、failureKind 和 result envelope 交给 HWLAB接入的 projection writer/finalizer。Agent编排不得让 Web、CLI、Workbench GET、trace polling 或 legacy conversation path 分别读取 AgentRun 并各自推断 session running、assistant final response、turn terminal 或 trace terminal;同一 AgentRun 事实只能形成一份 HWLAB Workbench durable projection。 +[PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 要求 Agent编排只把 AgentRun run、command、event、terminal status、failureKind 和 result envelope 交给 HWLAB接入的 projection writer/finalizer。Agent编排不得让 Web、CLI、Workbench GET、trace polling 或 legacy conversation path 分别读取 AgentRun 并各自推断 session running、assistant final response、turn terminal 或 trace terminal;同一 AgentRun 事实只能形成一份 HWLAB Workbench durable projection。 diff --git a/project-management/PJ2026-01/specs/PJ2026-010205-hwlab-dispatch.md b/project-management/PJ2026-01/specs/PJ2026-010205-hwlab-dispatch.md index 2be7fb5f..4c6627d9 100644 --- a/project-management/PJ2026-01/specs/PJ2026-010205-hwlab-dispatch.md +++ b/project-management/PJ2026-01/specs/PJ2026-010205-hwlab-dispatch.md @@ -56,7 +56,7 @@ HWLAB接入负责把 HWLAB Cloud API、Workbench、CLI、HWPOD 运行上下文 | 手动调度 API | AgentRun 为已存在 run/command 显式创建 runner Job 的短返回 API。 | | HWLAB canary | HWLAB v0.2 通过 AgentRun 执行真实 Code Agent turn 的最小接入闭环。 | | result envelope | AgentRun command result 的结构化输出,包含 status、terminalStatus、reply、failureKind、events 和 artifact 摘要。 | -| Workbench projection writer | HWLAB接入中唯一把 AgentRun result envelope 和 events 写成 Workbench session、message、part、turn 和 trace facts 的组件。 | +| Workbench projection writer | [PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 定义的唯一写入组件,在 HWLAB接入中把 AgentRun result envelope 和 events 写成 Workbench session、message、part、turn 和 trace facts。 | | HWPOD runtime context | HWLAB dispatcher 为单次 runner job 提供的 owner-scoped 硬件运行上下文。 | | transientEnv | 单次 runner job 的短期 env 上下文,由 AgentRun 转为短期 Secret 投影并脱敏输出。 | | 自然语言单一路由 | `/v1/agent/chat` 中自然语言请求统一进入 AgentRun Code Agent turn,不由 Cloud API 做关键词分流或文本 fallback。 | @@ -119,7 +119,7 @@ HWLAB 不得用 partial assistant、stdout、transport close、idle timeout 或 HWLAB接入应把 AgentRun result 和 events 投影为 HWLAB 自己的 Turn、Message、Part 和 TraceEvent 事实。AgentRun 是 execution backend,Web Workbench 的会话事实由 HWLAB 的 session/turn/message/trace model 承担;Web、CLI 和 REST snapshot 只能重放该投影,不能分别从 runnerTrace、terminalEvidence、workspace snapshot 或 result polling 生成多套 final response。 -PJ2026-0104010803 唯一投影切片要求 HWLAB接入把 projection writer/finalizer 作为 AgentRun -> Workbench facts 的唯一写入口。dispatcher、adapter、compat wrapper、Workbench GET、result polling 和 trace polling 都不能直接写 session summary、assistant message、turn terminal、trace terminal 或 final response。AgentRun terminal result 到达时,HWLAB接入必须以幂等 projection commit 同步更新 assistant message/part final text、turn terminal、trace terminal event、session running=false 和 session summary;若暂时不能提交,必须暴露 projection lag/blocker,而不是让不同 read path 各自显示 completed 或 running。 +[PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 是 HWLAB接入中 AgentRun -> Workbench facts 的唯一专项规格。dispatcher、adapter、compat wrapper、Workbench GET、result polling 和 trace polling 都不能直接写 session summary、assistant message、turn terminal、trace terminal 或 final response;它们只能把 normalized facts 交给 projection writer/finalizer,或通过 read model 重放 durable projection。AgentRun terminal result 到达时,终态提交、checkpoint、diagnostic 和重启恢复语义以专项 SPEC 为准。 同一次用户提交、steer 或 retry 应在 admission 时生成稳定 turnId、traceId、userMessageId 和 assistantMessageId。初发 UI 可以基于这些标识做 optimistic 展示;AgentRun events/result 到达后必须用同 ID 确认或更新对应 message/part/turn/trace,而不是创建另一条会话消息。页面刷新、session 切换、SSE 重连和 CLI inspect/result 都必须恢复同一组标识和同一语义结果。 diff --git a/project-management/PJ2026-01/specs/PJ2026-010401-web-workbench.md b/project-management/PJ2026-01/specs/PJ2026-010401-web-workbench.md index 60d16e4b..6ebde1c8 100644 --- a/project-management/PJ2026-01/specs/PJ2026-010401-web-workbench.md +++ b/project-management/PJ2026-01/specs/PJ2026-010401-web-workbench.md @@ -75,7 +75,7 @@ Web工作台负责 HWLAB 登录后的浏览器主入口,使用户能够在同 | 正式公开入口 | 目标 node/lane 在 YAML 中声明的 Cloud Web public URL,用作用户访问、Playwright 验收、文档说明和故障复现入口。 | | 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 状态链路:AgentRun 执行事实只经 HWLAB projection writer/finalizer 写入 durable Workbench facts,REST、SSE、CLI、fake-server 和 Web 前端只消费该投影。 | +| 唯一投影 | [PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 定义的状态链路:AgentRun 执行事实只经 HWLAB projection writer/finalizer 写入 durable Workbench facts,REST、SSE、CLI、fake-server 和 Web 前端只消费该投影。 | | 初发刷新一致性 | 同一 prompt 在初次发送、切换 session 后回到该 session、刷新页面和 SSE 重连后,都以同一 userMessageId、assistantMessageId、turnId 和 traceId 还原同一语义结果。 | | 浏览器回归验证 | 使用 Playwright 在真实浏览器中验证 Workbench 用户可见行为、状态投影和 Trace 阅读正确性的前端端到端单元测试;测试过程使用本地 mock server,不依赖实时 Cloud API、AgentRun、HWPOD 或其他运行组件。 | | 真实采集 fixture | 从目标 node/lane 的受控样本采集 Workbench REST、SSE、conversation、session、turn 和 trace 响应,经稳定伪 ID 映射与敏感字段脱敏后,用于浏览器回归验证的数据集。 | @@ -201,69 +201,11 @@ flowchart LR 浏览器回归验证的数据流必须保证:fixture 优先来自目标 node/lane 的真实受控样本;脱敏后保留 conversationId、sessionId、turnId、traceId、messageId 和 sourceSeq 之间的关系;mock server 只重放和变形这些事实,不成为新的业务事实来源;D601 远程 Playwright route 只负责执行与截图 artifact 回传,功能正确性仍由 Web工作台规格定义。 -### 5.4 PJ2026-0104010803 唯一投影切片 +### 5.4 PJ2026-0104010803 Workbench唯一投影专项 -```mermaid -flowchart LR - subgraph AgentRun[AgentRun 执行事实] - RUN[run] - CMD[command] - EV[events/result] - RUN --> CMD - CMD --> EV - end - subgraph HWLAB[HWLAB durable projection] - WR[WorkbenchProjectionWriter] - FIN[WorkbenchTurnFinalizer] - FACT[(session / message / part / turn / trace facts)] - RM[WorkbenchReadModel] - BUS[projection commit event] - WR --> FACT - FIN --> FACT - FACT --> RM - FACT --> BUS - end - subgraph Clients[Workbench consumers] - REST[REST GET snapshot] - SSE[SSE /v1/workbench/events] - RED[Web reducer] - CLI[CLI renderer] - FAKE[fake-server fixture] - RM --> REST - BUS --> SSE - REST --> RED - SSE --> RED - REST --> CLI - REST --> FAKE - end - EV --> WR -``` +[PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 是 Workbench 状态投影的唯一专项规格,集中定义 durable facts schema、`WorkbenchProjectionWriter`、`WorkbenchProjectionFinalizer`、`WorkbenchFactsStore`、`WorkbenchReadModel`、terminal commit、cloud-api 重启恢复、GET 纯读和代码引用规则。 -PJ2026-0104010803 的唯一投影边界是:AgentRun run、command、events 和 result 是执行事实;HWLAB `WorkbenchProjectionWriter` / `WorkbenchTurnFinalizer` 是唯一写入者;`WorkbenchReadModel` 是唯一读模型;SSE 是 projection commit 后的实时通知;Web reducer、CLI render 和 fake-server fixture 都只消费同一 durable projection。GET 路径只能读取 projection 并暴露 `projectionStatus`、`lastProjectedSeq`、`sourceRunId`、`blocker` 或等价诊断字段,不得隐藏调用 AgentRun、Code Agent 或内部 manager 做 sync、repair、finalize 或补事件。 - -```mermaid -sequenceDiagram - participant User - participant Web as Cloud Web - participant API as HWLAB API - participant AR as AgentRun - participant Writer as WorkbenchProjectionWriter - participant Read as WorkbenchReadModel - participant SSE as Workbench SSE - User->>Web: submit prompt - Web->>API: POST turn admission - API-->>Web: 202 turnId/traceId/messageIds - API->>AR: create run/command - AR-->>Writer: event/result facts - Writer->>Writer: commit message/part/turn/trace/session facts atomically - Writer-->>SSE: projection commit event - Web->>Read: GET session/messages/turn/trace snapshot - SSE-->>Web: message.updated / turn.updated / trace.events.appended - Read-->>Web: same durable facts - Web->>Web: reducer merges by sessionId/messageId/partId/turnId/traceId -``` - -该时序要求 terminal commit 原子更新 assistant final text/status、turn terminal、trace terminal event、session running=false、summary updated 和 SSE cursor;若写入需重试,必须按幂等键、`projectedSeq`、`sourceSeq/sourceEventId` 合并,不能让 session rail、message page、turn snapshot 和 trace page 分别推断终态。 +Web工作台在本规格中只保留前端消费边界:Cloud Web reducer、selectors、session rail、timeline、composer 和 Trace detail 只能消费该专项定义的 durable projection;SSE 只是 projection commit 后的通知和加速;fake-server fixture 只重放同一 REST/SSE 合同。详细架构图、数据流图和关键时序图以专项规格为准,本文不再维护第二份投影架构正文。 ## 6. 原子需求 @@ -371,7 +313,7 @@ Web工作台应把 REST snapshot、SSE event、submit optimistic、trace paginat Timeline Projection 只能从 messages、parts、turn status 和 trace events 派生用户可见 rows。Trace detail 只消费 TraceEventPage;session rail 只消费 session list 和 turn summary;composer 只消费当前 route/selected session 与明确 running turn。组件、trace polling、submit/cancel 回调不得直接写 messages、final response 或 trace authority。 -PJ2026-0104010803 唯一投影切片要求 Web 工作台把 `sessionId`、`messageId`、`partId`、`turnId` 和 `traceId` 作为 reducer 合并键。REST snapshot、SSE event、submit optimistic 和 trace pagination 的任何 late response 都只能更新其自身 key 对应的事实,不得清空当前 selected session、覆盖已存在 message page、或用 list summary/localStorage/workspace snapshot 重建当前 timeline。running trace 在 terminal 前收到 `hasMore=false` 只表示当前 trace page 暂时追平,不表示 `fullTraceLoaded=true`;后续 SSE 或 REST catch-up 仍必须能追加 terminal event 和 final response。 +[PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 要求 Web 工作台把 `sessionId`、`messageId`、`partId`、`turnId` 和 `traceId` 作为 reducer 合并键。REST snapshot、SSE event、submit optimistic 和 trace pagination 的任何 late response 都只能更新其自身 key 对应的事实,不得清空当前 selected session、覆盖已存在 message page、或用 list summary/localStorage/workspace snapshot 重建当前 timeline。running trace 在 terminal 前收到 `hasMore=false` 只表示当前 trace page 暂时追平,不表示 `fullTraceLoaded=true`;后续 SSE 或 REST catch-up 仍必须能追加 terminal event 和 final response。 初发刷新一致性是 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 状态不得因此退化为“思考中”。 diff --git a/project-management/PJ2026-01/specs/PJ2026-0104010803-workbench-unique-projection.md b/project-management/PJ2026-01/specs/PJ2026-0104010803-workbench-unique-projection.md new file mode 100644 index 00000000..d5dfda75 --- /dev/null +++ b/project-management/PJ2026-01/specs/PJ2026-0104010803-workbench-unique-projection.md @@ -0,0 +1,321 @@ +# PJ2026-0104010803 Workbench唯一投影 + +## 修改历史 + +| 版本 | 对应 commit id | 更新日期 | 变更说明 | +| --- | --- | --- | --- | + +当前正文仍在规格治理草稿中;未定稿前不新增版本号,不为单次编辑追加 `待提交` 版本。 + +## 正文 + +## PJ2026-0104010803 Workbench唯一投影需求规格 + +## 1. 文档控制 + +| 字段 | 内容 | +| --- | --- | +| 编号 | PJ2026-0104010803 | +| 短名 | Workbench唯一投影 | +| 层级 | L4 专项规格切片 | +| 状态 | 已生效 | +| 实现引用版本 | draft-2026-06-18-p0-unique-projection | +| 需求规格模板 | [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) | +| 规格治理索引 | [规格治理](spec-governance.md) | + +本文采用 ISO/IEC/IEEE 29148 需求规格模板的项目裁剪版:正文只保留 Workbench 唯一投影的稳定使命、范围、术语、系统边界、内部分工和原子需求。 + +## 2. 目的和范围 + +### 2.1 目的 + +Workbench唯一投影负责把 AgentRun 执行事实收敛成 HWLAB 自有的 durable Workbench facts,使 Web、CLI、REST、SSE、fake-server 和浏览器回归都消费同一份可恢复、可分页、可诊断的用户态会话事实。 + +本专项的目标状态是:AgentRun run、command、event 和 result 只作为执行事实输入;HWLAB 只有 `WorkbenchProjectionWriter`、`WorkbenchProjectionFinalizer` 写入 Workbench facts;所有 `GET /v1/workbench/*` 和兼容读路径都只通过 `WorkbenchReadModel` 读取,不在读取时调用 AgentRun、Code Agent manager、trace polling、result polling 或 workspace repair 推进事实。 + +### 2.2 范围内 + +- AgentRun facts 到 Workbench facts 的标准映射、幂等写入和 terminal commit 语义。 +- `session`、`message`、`part`、`turn`、`trace event`、`projection checkpoint` 和 `projection diagnostic` 的 durable facts schema。 +- `WorkbenchFactsStore`、`WorkbenchProjectionWriter`、`WorkbenchProjectionFinalizer` 和 `WorkbenchReadModel` 的组件边界。 +- cloud-api 进程重启、进程内后台任务丢失、慢任务超过短轮询预算后的 durable finalizer 追平语义。 +- `GET /v1/workbench/*` 纯读、`/v1/agent/*` compat wrapper 降级和 projection diagnostics 输出要求。 +- Web reducer、CLI renderer、fake-server fixture 和 Playwright 回归对同一 durable projection 的消费规则。 +- 本专项范围内新增或重构源码文件的 SPEC 头部引用规则。 + +### 2.3 范围外 + +- AgentRun run/command/runner job 的执行生命周期事实归 [PJ2026-0102 Agent编排](PJ2026-0102-agent-orchestration.md)。 +- HWLAB 到 AgentRun 的 dispatcher、runtime assembly、manual dispatch 和 provider profile 归 [PJ2026-010205 HWLAB接入](PJ2026-010205-hwlab-dispatch.md) 及 Agent编排下级规格。 +- API path、HTTP schema、错误 envelope 和 route policy 归 [PJ2026-010403 API契约](PJ2026-010403-api-contract.md)。 +- Web 布局、组件、浏览器交互和可见 UX 归 [PJ2026-010401 Web工作台](PJ2026-010401-web-workbench.md)。 +- 用户身份、权限、额度、账本和 owner visibility 归 [PJ2026-0105 用户管理](PJ2026-0105-user-management.md)。 +- CI/CD、GitOps、公开入口、Prometheus 和运行面运维归 [PJ2026-0106 平台运维](PJ2026-0106-platform-ops.md)。 + +## 3. 术语表 + +| 术语 | 定义 | +| --- | --- | +| AgentRun facts | AgentRun 产生的 run、command、runner job、event、result、terminalStatus、failureKind、sourceSeq 和 sourceEventId 等执行事实。 | +| Workbench facts | HWLAB 自有的 session、message、part、turn、trace event、checkpoint 和 diagnostic 持久事实,用于用户态 Workbench 展示。 | +| WorkbenchProjectionWriter | 唯一把 normalized AgentRun facts 写成 Workbench facts 的组件;它不处理 HTTP route、鉴权、UI transient state 或兼容 API 输出。 | +| WorkbenchProjectionFinalizer | 以 checkpoint 为驱动的幂等追平组件;可由 submit 后、event 到达、后台恢复或显式 repair mutation 触发,但所有入口调用同一 finalization 逻辑。 | +| WorkbenchFactsStore | durable facts 存储接口,负责幂等 upsert、terminal commit、checkpoint、diagnostic、分页查询和 owner visibility 过滤所需的持久化读写。 | +| WorkbenchReadModel | 唯一读取 Workbench facts 并组装 session rail、session detail、message page、turn snapshot、trace event page 和 projection diagnostics 的读模型。 | +| 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。 | +| 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 重启或后台任务丢失后继续追平。 | +| projection diagnostic | 暴露 projection lag、blocker、lastProjectedSeq、sourceRunId、sourceCommandId、updatedAt 和恢复状态的可诊断字段。 | +| compat wrapper | 旧 `/v1/agent/*` 或 conversation path 的兼容包装层;只能调用 `WorkbenchReadModel` 或正式 mutation,不拥有第二套事实写入或 read-through repair。 | +| read-through repair | GET 路径为了让页面“看起来正确”而同步调用 AgentRun、Code Agent manager、workspace repair、trace/result polling 或 billing finalizer 推进事实;本专项禁止该模式。 | + +## 4. 系统边界和接口 + +本规格把 Workbench唯一投影作为客户端、API契约、HWLAB接入和Agent编排之间的状态边界看待;本章只描述输入、输出和责任边界。 + +| 边界项 | 内容 | +| --- | --- | +| 外部使用者 | Cloud Web、HWLAB CLI、Cloud API route、AgentRun adapter、fake-server 回归和运维诊断。 | +| 外部输入 | AgentRun run/command/event/result facts、turn admission metadata、owner/session visibility、显式 repair mutation、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。 | +| 用户接口 | Cloud Web `/workbench`、同源 `/v1/workbench/*` REST/SSE、HWLAB CLI 的同源 Workbench/API 入口。 | +| 系统边界 | 本专项只定义 Workbench 用户态事实的唯一写入和读取链路;它不定义 AgentRun 执行合同、用户权限策略、Web UI 布局或平台发布机制。 | + +## 5. 内部分工与规格索引 + +| 编号 | 内部模块 | 规格文档 | 主责边界 | 上游依赖 | 下游支撑 | +| --- | --- | --- | --- | --- | --- | +| PJ2026-010401080301 | FactsStore | 本规格 6.1 | durable facts schema、幂等 upsert、terminal commit、checkpoint 和分页读取 | 数据库/runtimeStore、用户管理 visibility | Writer、Finalizer、ReadModel | +| PJ2026-010401080302 | ProjectionWriter | 本规格 6.2 | normalized AgentRun facts 到 Workbench facts 的唯一写入 | HWLAB接入、Agent编排 | ReadModel、SSE、CLI/Web | +| PJ2026-010401080303 | ProjectionFinalizer | 本规格 6.3 | checkpoint 驱动追平、重启恢复和显式 repair mutation 的同一幂等入口 | 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-010401080307 | Regression | 本规格 6.7 | 后端红灯、fake-server Playwright、D601 web-probe 和分叉清零验收 | 平台运维、Web工作台 | issue 收口和防回归 | +| PJ2026-010401080308 | CodeReference | 本规格 6.8 | 源码文件头部 SPEC 引用和实现版本追溯 | 规格治理 | 后续实现审计 | + +### 5.1 目标架构图 + +```mermaid +flowchart LR + subgraph AgentRun[AgentRun execution backend] + RUN[run] + CMD[command] + SRC[events / result / sourceSeq] + RUN --> CMD + CMD --> SRC + end + subgraph CloudAPI[HWLAB Cloud API] + AD[AgentRun Adapter: normalize facts] + WR[WorkbenchProjectionWriter] + FIN[WorkbenchProjectionFinalizer] + FS[(WorkbenchFactsStore)] + RM[WorkbenchReadModel] + SSE[SSE publisher] + COMP[Compat wrappers] + AD --> WR + FIN --> WR + WR --> FS + FS --> RM + FS --> SSE + RM --> COMP + end + subgraph Consumers[Projection consumers] + REST[GET /v1/workbench/*] + WEB[Cloud Web reducer/selectors] + CLI[HWLAB CLI renderer] + FAKE[fake-server fixture] + SSEOUT[/v1/workbench/events] + RM --> REST + REST --> WEB + REST --> CLI + REST --> FAKE + SSE --> SSEOUT + SSEOUT --> WEB + end + SRC --> AD +``` + +目标架构要求 route/auth、adapter、projection writer/finalizer、facts store、read model、SSE publisher 和 compat wrapper 分工清晰。任何 route、GET handler、trace polling、result polling、workspace snapshot 或 front-end reducer 都不能绕过 writer/finalizer 直接改变 Workbench facts。 + +### 5.2 目标数据流图 + +```mermaid +flowchart TD + USER[用户 prompt/steer/retry/cancel] --> ADMISSION[Turn admission] + ADMISSION --> IDS[stable turnId traceId userMessageId assistantMessageId] + ADMISSION --> AR[AgentRun run/command] + IDS --> WR0[ProjectionWriter: admission facts] + AR --> EV[AgentRun events/result] + EV --> NORM[normalize AgentRun facts] + NORM --> FIN[ProjectionFinalizer] + FIN --> WR[ProjectionWriter] + WR0 --> TX[projection commit] + WR --> TX + TX --> FACTS[(Workbench facts + checkpoint + diagnostics)] + FACTS --> RM[WorkbenchReadModel] + FACTS --> BUS[SSE projection commit] + RM --> SNAP[REST snapshot / pages] + BUS --> STREAM[SSE events] + SNAP --> RED[Web reducer / CLI / fake-server] + STREAM --> RED +``` + +数据流必须保证:admission 只生成稳定标识和初始 facts;AgentRun facts 必须先归一化,再由 writer/finalizer 进入 projection commit;REST snapshot 和 SSE event 只能重放 durable facts;diagnostic 明确表达 lag/blocker,不能让读取路径隐式修复事实。 + +### 5.3 terminal commit 关键时序图 + +```mermaid +sequenceDiagram + participant AR as AgentRun + participant Adapter as AgentRun Adapter + participant Finalizer as ProjectionFinalizer + participant Writer as ProjectionWriter + participant Store as FactsStore + participant SSE as SSE Publisher + participant Read as ReadModel + participant Web as Web/CLI/fake-server + AR-->>Adapter: terminal result + events + sourceSeq + Adapter-->>Finalizer: normalized facts + Finalizer->>Writer: finalize sourceRunId/sourceCommandId + Writer->>Store: atomic terminal commit + Store-->>Writer: projectedSeq + checkpoint + Writer-->>SSE: projection commit notification + Web->>Read: GET session/messages/turn/trace + Read->>Store: read only + Read-->>Web: same terminal facts + diagnostics +``` + +terminal commit 必须在同一幂等提交内更新 assistant final text、message/part terminal status、turn terminal、trace terminal event、session running=false、summary updated、projection checkpoint 和 SSE cursor。若提交失败或暂时无法完成,只能暴露 projection lag/blocker;不得让 session rail 显示 completed、message page 显示 running、turn snapshot 显示 failed 或 trace page 缺 terminal 这类互相矛盾状态。 + +### 5.4 cloud-api 重启恢复时序图 + +```mermaid +sequenceDiagram + participant Boot as cloud-api boot/background scheduler + participant Store as FactsStore + participant AR as AgentRun facts source + participant Finalizer as ProjectionFinalizer + participant Writer as ProjectionWriter + participant Read as ReadModel + Boot->>Store: load open checkpoints / lagging commands + Store-->>Boot: sourceRunId/sourceCommandId/lastProjectedSeq + Boot->>Finalizer: resume checkpoint + Finalizer->>AR: fetch events/result after source checkpoint + AR-->>Finalizer: source facts or still-running status + Finalizer->>Writer: idempotent catch-up commit + Writer->>Store: update facts/checkpoint/diagnostic + Read->>Store: read only snapshots + Store-->>Read: caught-up facts or explicit lag/blocker +``` + +重启恢复要求 finalizer 不依赖进程内 90s 轮询作为唯一推进机制。进程内任务丢失、cloud-api 重启或慢任务超过短轮询预算后,finalizer 必须能从 durable checkpoint 找回需要追平的 sourceRun/sourceCommand,并以同一 writer 逻辑提交或记录 blocker。 + +## 6. 原子需求 + +### 6.1 WB-PROJ-REQ-001 durable facts store + +| 编号 | 短名 | 主责模块 | 关联模块 | +| --- | --- | --- | --- | +| WB-PROJ-REQ-001 | FactsStore | PJ2026-010401080301 FactsStore | [用户管理](PJ2026-0105-user-management.md)、[API契约](PJ2026-010403-api-contract.md) | + +Workbench facts store 应持久化 session、message、part、turn、trace event、projection checkpoint 和 projection diagnostic,使 Workbench 用户态事实可在 cloud-api 重启、进程内任务丢失或后台 finalizer 重跑后恢复。 + +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 的生命周期事实。 | +| trace event | traceId/projectedSeq/sourceSeq/sourceEventId/type/status/timestamp/redactedPayload | Workbench trace page 的分页事实;projectedSeq 是唯一 cursor。 | +| checkpoint | sourceRunId/sourceCommandId/lastSourceSeq/lastProjectedSeq/status/updatedAt | finalizer 追平位置和幂等边界。 | +| diagnostic | sessionId/turnId/traceId/projectionStatus/lag/blocker/sourceRunId/sourceCommandId/updatedAt | GET 和运维可见的 projection 状态,不推进事实。 | + +Facts store 必须支持幂等 upsert、terminal commit、projection checkpoint、diagnostic update 和按 owner visibility 过滤的分页查询。`agent_sessions.session_json` 可作为迁移期 metadata 来源,但不得继续承载业务 projection 真相。 + +### 6.2 WB-PROJ-REQ-002 projection writer + +| 编号 | 短名 | 主责模块 | 关联模块 | +| --- | --- | --- | --- | +| WB-PROJ-REQ-002 | Writer | PJ2026-010401080302 ProjectionWriter | [HWLAB接入](PJ2026-010205-hwlab-dispatch.md)、[Agent编排](PJ2026-0102-agent-orchestration.md) | + +WorkbenchProjectionWriter 应作为唯一写入口,把 admission facts 和 normalized AgentRun facts 转换为 durable Workbench facts。Writer 不负责 HTTP route、鉴权、AgentRun fetch、UI transient state、旧 API envelope 或测试 fixture。 + +Writer 必须使用稳定幂等键写入 messageId、partId、turnId、traceId、sourceRunId、sourceCommandId、sourceSeq/sourceEventId 和 projectedSeq。重复 event、重放 result、重启恢复或 repair mutation 不得创建重复 assistant message、重复 terminal event 或冲突 session summary。 + +### 6.3 WB-PROJ-REQ-003 projection finalizer + +| 编号 | 短名 | 主责模块 | 关联模块 | +| --- | --- | --- | --- | +| WB-PROJ-REQ-003 | Finalizer | PJ2026-010401080303 ProjectionFinalizer | [HWLAB接入](PJ2026-010205-hwlab-dispatch.md)、[AgentRun核心](PJ2026-010201-agentrun-core.md) | + +WorkbenchProjectionFinalizer 应以 checkpoint 为驱动追平 AgentRun facts。submit 后、event arrival 后、后台恢复和显式 repair mutation 可以触发 finalizer,但这些入口必须调用同一幂等 finalization 逻辑。 + +Finalizer 不得伪造 terminal、不取消 AgentRun、不用日志尾部推断 completed,也不得让 GET route 临时同步执行 finalization。若 AgentRun 事实暂不可取或映射失败,finalizer 应写入 diagnostic blocker,保留 retry 所需 sourceRun/sourceCommand/checkpoint。 + +### 6.4 WB-PROJ-REQ-004 read model and pure GET + +| 编号 | 短名 | 主责模块 | 关联模块 | +| --- | --- | --- | --- | +| WB-PROJ-REQ-004 | ReadModel | PJ2026-010401080304 ReadModel | [API契约](PJ2026-010403-api-contract.md)、[Web工作台](PJ2026-010401-web-workbench.md) | + +WorkbenchReadModel 应作为唯一读模型,从 durable facts 组装 session list、session detail、message page、turn snapshot、trace event page 和 projection diagnostics。Read model 只读 facts store,不调用 AgentRun、Code Agent manager、legacy conversation manager、billing finalizer、workspace repair 或 trace/result polling。 + +`GET /v1/workbench/*` 必须纯读。若 projection 滞后,响应应输出 `projectionStatus`、`lastProjectedSeq`、`sourceRunId`、`sourceCommandId`、`blocker` 或等价 diagnostic 字段,不能在 GET 内做 read-through repair。 + +### 6.5 WB-PROJ-REQ-005 compat wrapper + +| 编号 | 短名 | 主责模块 | 关联模块 | +| --- | --- | --- | --- | +| WB-PROJ-REQ-005 | CompatWrapper | PJ2026-010401080305 CompatWrapper | [API契约](PJ2026-010403-api-contract.md)、[HWLAB接入](PJ2026-010205-hwlab-dispatch.md) | + +迁移期 `/v1/agent/turns/*`、`/v1/agent/traces/*`、conversation detail、result polling 和 legacy conversation path 可以作为 compat wrapper 暂存,但只能调用 WorkbenchReadModel 或正式 mutation。Compat wrapper 不得拥有第二套 session/message/turn/trace 写入逻辑,不得在读取时同步 finalizer,也不得用 result cache 或 trace tail 组装另一份 final response。 + +旧路径返回的 envelope 可以保留 legacy 字段名,但字段值必须来自同一 Workbench facts。若无法映射,应返回结构化 incompatibility/blocker,而不是回退到旧 manager 或空 stub。 + +### 6.6 WB-PROJ-REQ-006 Web server-state single path + +| 编号 | 短名 | 主责模块 | 关联模块 | +| --- | --- | --- | --- | +| WB-PROJ-REQ-006 | Web单路径 | PJ2026-010401080306 WebServerState | [Web工作台](PJ2026-010401-web-workbench.md)、[API契约](PJ2026-010403-api-contract.md) | + +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。 + +SSE 只作为 projection commit 后的通知和加速,不是事实来源。SSE 断线、丢事件或重连后,Web 只能通过同一 REST snapshot 与 trace page 补洞。running trace 在 terminal 前 `hasMore=false` 只表示当前页追平,不得设置永久 `fullTraceLoaded=true`。 + +### 6.7 WB-PROJ-REQ-007 regression and validation + +| 编号 | 短名 | 主责模块 | 关联模块 | +| --- | --- | --- | --- | +| WB-PROJ-REQ-007 | 回归验收 | PJ2026-010401080307 Regression | [Web工作台](PJ2026-010401-web-workbench.md)、[平台运维](PJ2026-0106-platform-ops.md) | + +Workbench唯一投影必须有后端和浏览器两层回归:后端用 Workbench-only HTTP 用例证明 submit 后不访问旧 `/v1/agent/turns` 或 result polling 也能自然 completed;durable recovery 用例证明进程内 sync 丢失或 cloud-api 重启后 finalizer 能从 checkpoint 追平;terminal atomicity 用例证明 session rail、session detail、messages、turn snapshot 和 trace event page 不出现 running/completed 组合矛盾。 + +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 收敛。 + +### 6.8 WB-PROJ-REQ-008 code reference rule + +| 编号 | 短名 | 主责模块 | 关联模块 | +| --- | --- | --- | --- | +| WB-PROJ-REQ-008 | 代码引用 | PJ2026-010401080308 CodeReference | [规格治理](spec-governance.md) | + +本专项范围内新增或重构的核心源码文件,文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如: + +```text +SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-18-p0-unique-projection +``` + +同一文件同时承载 API契约、HWLAB接入、Web工作台或 Agent编排职责时,应在同一头部追加对应 SPEC 编号与实现引用版本。实现文件不得只写 issue 编号、`latest` 或 `current`。自动生成文件、第三方 vendored 文件、纯配置、锁文件和无法承载注释头的二进制产物可例外,但对应生成器、渲染器或配置入口必须能追溯到本 SPEC。 + +## 7. 过程控制 + +本规格的执行证据保留在对应 GitHub 执行 issue、PR、web-probe 报告和 Playwright artifact 中;规格正文不承载长证据、运行日志或一次性排障流水。 + +本专项关闭前,执行 issue 必须回写以下证据:专项 SPEC commit、后端写点/读点清单、旧路径最终状态、PR、D601 v0.3 发布证据、fake-server Playwright 结果、public origin web-probe 的 script SHA/runDir/report SHA/截图 SHA,以及父级 Web/API/HWLAB接入/Agent编排规格是否仍与实现一致。 diff --git a/project-management/PJ2026-01/specs/PJ2026-010403-api-contract.md b/project-management/PJ2026-01/specs/PJ2026-010403-api-contract.md index b02e27e9..b9d3a335 100644 --- a/project-management/PJ2026-01/specs/PJ2026-010403-api-contract.md +++ b/project-management/PJ2026-01/specs/PJ2026-010403-api-contract.md @@ -65,8 +65,8 @@ API契约负责定义 Cloud Web、HWLAB CLI 和自动化脚本共同使用的 RE | TraceEventPage | 按 traceId 和 cursor/seq 分页查询 trace events 的 RESTful page;只表达 trace 明细,不决定主 timeline 的 final response。 | | Message/Part | Web 和 CLI 共同渲染会话 timeline 的持久消息事实;message 表达角色、父子关系和终态摘要,part 表达文本、工具、文件、错误、trace 摘要等可组合内容。 | | EventStream | Cloud Web origin 下的 SSE 实时入口,用于推送 server.connected、session、turn、message、part、trace 和 workspace lifecycle 事件。 | -| WorkbenchProjectionWriter | 把 AgentRun run、command、event 和 result 转换为 HWLAB durable Workbench facts 的唯一写入组件。 | -| WorkbenchReadModel | 从 durable Workbench facts 组装 session detail、message page、turn snapshot、trace event page 和 session rail summary 的唯一读模型。 | +| WorkbenchProjectionWriter | [PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 定义的唯一写入组件,把 AgentRun run、command、event 和 result 转换为 HWLAB durable Workbench facts。 | +| WorkbenchReadModel | [PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 定义的唯一读模型,从 durable Workbench facts 组装 session detail、message page、turn snapshot、trace event page 和 session rail summary。 | | projection commit | projection writer/finalizer 对 message、part、turn、trace 和 session summary 的一次幂等持久化提交;终态 commit 必须保持这些事实语义一致。 | | projectedSeq | HWLAB durable trace event 的单调分页游标;与 AgentRun `sourceSeq` / `sourceEventId` 分离,用于 Workbench trace page、SSE replay 和 fake-server fixture。 | @@ -95,40 +95,11 @@ API契约负责定义 Cloud Web、HWLAB CLI 和自动化脚本共同使用的 RE 目标后端模块应至少拆分为 route/handler、schema/contract、read model、persistence/projection、AgentRun adapter、trace event pager、SSE/event publisher 和 compat wrapper。route 文件只负责 HTTP 入口、鉴权桥接和错误映射;schema/contract 只负责类型和字段;read model 只组装查询模型;adapter 只转换外部执行事实;projection 只写 durable facts;compat wrapper 只提供旧 path 到新资源的兼容映射,不拥有第二套业务事实。 -### 5.1 AgentRun 到 Workbench 唯一投影数据流 +### 5.1 Workbench唯一投影 API 边界 -```mermaid -flowchart LR - AR[AgentRun run/command/events/result] --> AD[AgentRun adapter] - AD --> PW[WorkbenchProjectionWriter] - PW --> FACT[(Workbench durable facts)] - FACT --> RM[WorkbenchReadModel] - FACT --> SSE[SSE event publisher] - RM --> GET[REST GET /v1/workbench/*] - SSE --> ES[GET /v1/workbench/events] - GET --> WEB[Web/CLI/fake-server consumers] - ES --> WEB -``` +[PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 集中定义 AgentRun facts 到 Workbench durable facts 的目标架构、数据流、terminal commit 时序和 cloud-api 重启恢复时序。API契约在本文只保留接口边界:`GET /v1/workbench/*` 只读取 `WorkbenchReadModel`;SSE 只发布 projection commit notification;compat wrapper 只能调用同一 read model 或正式 mutation。 -API契约要求 `GET /v1/workbench/*` 只读取 `WorkbenchReadModel`。若 AgentRun 事实已经 terminal 但 Workbench projection 尚未追平,GET 响应应暴露 `projectionStatus`、`lastProjectedSeq`、`sourceRunId`、`sourceCommandId`、`blocker` 或等价诊断字段;不得在 GET 中同步调用 AgentRun、Code Agent manager、legacy conversation manager、billing finalizer 或 workspace repair 来推进事实。 - -```mermaid -sequenceDiagram - participant AR as AgentRun - participant Writer as ProjectionWriter - participant DB as Durable Facts - participant RM as ReadModel - participant GET as REST GET - participant SSE as SSE - AR-->>Writer: sourceEventId/sourceSeq/result - Writer->>DB: idempotent commit projectedSeq - Writer-->>SSE: projection commit notification - GET->>RM: query session/messages/turn/trace - RM->>DB: read only - RM-->>GET: snapshot + projection diagnostics -``` - -该时序是 PJ2026-0104010803 的后端不变量。读模型、SSE publisher、compat wrapper 和 CLI render 都不能各自解释 terminal、running、final response 或 trace pagination;它们只能重放 durable projection。 +若 AgentRun 事实已经 terminal 但 Workbench projection 尚未追平,GET 响应应暴露 `projectionStatus`、`lastProjectedSeq`、`sourceRunId`、`sourceCommandId`、`blocker` 或等价诊断字段;不得在 GET 中同步调用 AgentRun、Code Agent manager、legacy conversation manager、billing finalizer、workspace repair、trace polling 或 result polling 来推进事实。读模型、SSE publisher、compat wrapper 和 CLI render 都不能各自解释 terminal、running、final response 或 trace pagination;它们只能重放 durable projection。 ## 6. 原子需求