From 511006ae9b4a60d35ca5c0c83e4173fdf97da350 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 18 Jun 2026 11:04:41 +0000 Subject: [PATCH] docs: freeze workbench unique projection spec --- .../specs/PJ2026-0102-agent-orchestration.md | 2 + .../specs/PJ2026-010205-hwlab-dispatch.md | 5 +- .../specs/PJ2026-010401-web-workbench.md | 71 ++++++++++++++++++- .../specs/PJ2026-010403-api-contract.md | 45 +++++++++++- 4 files changed, 117 insertions(+), 6 deletions(-) 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 e7baedb4..5b21a469 100644 --- a/project-management/PJ2026-01/specs/PJ2026-0102-agent-orchestration.md +++ b/project-management/PJ2026-01/specs/PJ2026-0102-agent-orchestration.md @@ -139,3 +139,5 @@ Backend Profile 不承担 HWLAB 用户鉴权,不保存 Secret value,不因 Agent编排应原样消费 AgentRun 的 run、command、runner job、event、terminal status、liveness 和 failure kind 合同,并把这些事实映射为 HWLAB 可消费的执行语义。 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。 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 95bfa365..2be7fb5f 100644 --- a/project-management/PJ2026-01/specs/PJ2026-010205-hwlab-dispatch.md +++ b/project-management/PJ2026-01/specs/PJ2026-010205-hwlab-dispatch.md @@ -19,7 +19,7 @@ | 短名 | HWLAB接入 | | 层级 | L2 课题 | | 状态 | 已生效 | -| 实现引用版本 | draft-2026-06-17-r0 | +| 实现引用版本 | draft-2026-06-17-r0; PJ2026-0104010803 唯一投影 draft-2026-06-18-p0-unique-projection | | 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) | | 上级规格 | [PJ2026-0102 Agent编排](PJ2026-0102-agent-orchestration.md) | | 规格治理索引 | [规格治理](spec-governance.md) | @@ -56,6 +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 的组件。 | | 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。 | @@ -118,6 +119,8 @@ 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。 + 同一次用户提交、steer 或 retry 应在 admission 时生成稳定 turnId、traceId、userMessageId 和 assistantMessageId。初发 UI 可以基于这些标识做 optimistic 展示;AgentRun events/result 到达后必须用同 ID 确认或更新对应 message/part/turn/trace,而不是创建另一条会话消息。页面刷新、session 切换、SSE 重连和 CLI inspect/result 都必须恢复同一组标识和同一语义结果。 ### 6.4 AR-HWLAB-REQ-004 HWPOD Runtime Context 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 4037d47d..60d16e4b 100644 --- a/project-management/PJ2026-01/specs/PJ2026-010401-web-workbench.md +++ b/project-management/PJ2026-01/specs/PJ2026-010401-web-workbench.md @@ -19,7 +19,7 @@ | 短名 | Web工作台 | | 层级 | L2 课题 | | 状态 | 已生效 | -| 实现引用版本 | draft-2026-06-18-r1 | +| 实现引用版本 | draft-2026-06-18-r1; PJ2026-0104010803 唯一投影 draft-2026-06-18-p0-unique-projection | | 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) | | 上级规格 | [PJ2026-0104 客户端](PJ2026-0104-client.md) | | 规格治理索引 | [规格治理](spec-governance.md) | @@ -75,6 +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 前端只消费该投影。 | | 初发刷新一致性 | 同一 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 映射与敏感字段脱敏后,用于浏览器回归验证的数据集。 | @@ -200,6 +201,70 @@ flowchart LR 浏览器回归验证的数据流必须保证:fixture 优先来自目标 node/lane 的真实受控样本;脱敏后保留 conversationId、sessionId、turnId、traceId、messageId 和 sourceSeq 之间的关系;mock server 只重放和变形这些事实,不成为新的业务事实来源;D601 远程 Playwright route 只负责执行与截图 artifact 回传,功能正确性仍由 Web工作台规格定义。 +### 5.4 PJ2026-0104010803 唯一投影切片 + +```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 的唯一投影边界是: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 分别推断终态。 + ## 6. 原子需求 ### 6.1 CLIENT-WB-REQ-001 工作台框架 @@ -306,6 +371,8 @@ 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。 + 初发刷新一致性是 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 共同竞争当前消息面板。 @@ -320,7 +387,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 state;UI 组件不得直接合并 REST/SSE 响应;projection 模块不得发请求或写状态。 -新增或重构的核心前端文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如 `SPEC: PJ2026-010401 Web工作台 draft-2026-06-18-r1; PJ2026-010403 API契约 draft-2026-06-18-r1`,并简述文件职责。实现文件不得只写 issue 编号、`latest` 或 `current` 作为规格引用。 +新增或重构的核心前端文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如 `SPEC: PJ2026-0104010803 唯一投影 draft-2026-06-18-p0-unique-projection; 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 浏览器回归 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 5847870d..b02e27e9 100644 --- a/project-management/PJ2026-01/specs/PJ2026-010403-api-contract.md +++ b/project-management/PJ2026-01/specs/PJ2026-010403-api-contract.md @@ -19,7 +19,7 @@ | 短名 | API契约 | | 层级 | L2 课题 | | 状态 | 已生效 | -| 实现引用版本 | draft-2026-06-18-r1 | +| 实现引用版本 | draft-2026-06-18-r1; PJ2026-0104010803 唯一投影 draft-2026-06-18-p0-unique-projection | | 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) | | 上级规格 | [PJ2026-0104 客户端](PJ2026-0104-client.md) | | 规格治理索引 | [规格治理](spec-governance.md) | @@ -65,6 +65,10 @@ 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 的唯一读模型。 | +| 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。 | ## 4. 系统边界和接口 @@ -91,6 +95,41 @@ 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 唯一投影数据流 + +```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 +``` + +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。 + ## 6. 原子需求 ### 6.1 CLIENT-API-REQ-001 同源路由 @@ -154,9 +193,9 @@ Trace resource 必须支持按事件位置继续读取,例如 `sinceSeq` / `cu | ProviderProfile | `GET /v1/workbench/provider-profiles` | project/workspace 可选 | profile summary list | 200/401/403 | 配置摘要,不输出 Secret | | Diagnostic resource | `GET /v1/workbench/diagnostics/{resource}` | resource id/query | redacted health/status summary | 200/401/403/404 | 诊断可见性,不改变业务事实 | -所有 GET path 必须无业务副作用。需要 repair、finalize、sync 或 migration 时,应由后台 finalizer、显式 mutation 或持久化投影入口执行,不能隐藏在 workspace、conversation、turn 或 trace GET 中。所有分页响应必须包含稳定 cursor 或 seq 边界;所有错误响应必须包含 route、status、code/blocker、redacted actor、target resource 和下一步建议。 +所有 GET path 必须无业务副作用。需要 repair、finalize、sync 或 migration 时,应由后台 finalizer、显式 mutation 或持久化投影入口执行,不能隐藏在 workspace、conversation、turn 或 trace GET 中。所有分页响应必须包含稳定 cursor 或 seq 边界;trace event page 的分页 cursor 使用 HWLAB `projectedSeq`,并保留 AgentRun `sourceSeq/sourceEventId` 作为来源审计字段,二者不得重叠或互相替代。所有错误响应必须包含 route、status、code/blocker、redacted actor、target resource 和下一步建议。 -新增或重构的核心后端文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如 `SPEC: PJ2026-010403 API契约 draft-2026-06-18-r1; PJ2026-010205 HWLAB接入 draft-2026-06-17-r0`,并简述文件职责。实现文件不得只写 issue 编号、`latest` 或 `current` 作为规格引用。 +新增或重构的核心后端文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如 `SPEC: PJ2026-0104010803 唯一投影 draft-2026-06-18-p0-unique-projection; 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 资源与管理接口