docs: update workbench projector resume spec

This commit is contained in:
Codex
2026-06-19 04:36:43 +00:00
parent 34e8e7df05
commit 870aac9075
@@ -19,7 +19,7 @@
| 短名 | Workbench唯一投影 |
| 层级 | L4 专项规格切片 |
| 状态 | 已生效 |
| 实现引用版本 | draft-2026-06-18-p0-zero-repair |
| 实现引用版本 | draft-2026-06-19-p0-projector-resume |
| 需求规格模板 | [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) |
@@ -33,7 +33,7 @@
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 推进事实。Workbench 必须满足 0repair:页面、GET、SSE、fake-server 和 web-probe 都不得通过 reload、切换 session、`sessionRepair``realignFreshSession`、localStorage truth 或 read-through repair 把已经分裂的 route/session/message/trace 状态补成看起来正确。
本专项的目标状态是:AgentRun run、command、event 和 result 只作为执行事实输入;HWLAB 只有 `WorkbenchProjectionWriter``WorkbenchProjectionFinalizer` 写入 Workbench factscloud-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 状态补成看起来正确。
### 2.2 范围内
@@ -70,7 +70,10 @@ Workbench唯一投影负责把 AgentRun 执行事实收敛成 HWLAB 自有的 du
| 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 重启或后台任务丢失后继续追平。 |
| sourceLatestSeq | finalizer 在本次或最近一次拉取中观察到的 AgentRun command 最新 sourceSeq,用于诊断投影 lag;它不得替代 lastSourceSeq 成为已提交事实。 |
| projection diagnostic | 暴露 projection lag、blocker、lastProjectedSeq、sourceRunId、sourceCommandId、updatedAt 和恢复状态的可诊断字段。 |
| 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。 |
| read-through repair | GET 路径为了让页面“看起来正确”而同步调用 AgentRun、Code Agent manager、workspace repair、trace/result polling 或 billing finalizer 推进事实;本专项禁止该模式。 |
| 读侧推理 | 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 或 elapsed timeout 推断 turn/session/message lifecycle、terminal、running 或 final response 的行为;本专项禁止该模式。 |
@@ -208,8 +211,8 @@ sequenceDiagram
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->>Store: load open checkpoints / running-projecting turns
Store-->>Boot: sourceRunId/sourceCommandId/lastSourceSeq/lastProjectedSeq
Boot->>Finalizer: resume checkpoint
Finalizer->>AR: fetch events/result after source checkpoint
AR-->>Finalizer: source facts or still-running status
@@ -219,7 +222,7 @@ sequenceDiagram
Store-->>Read: caught-up facts or explicit lag/blocker
```
重启恢复要求 finalizer 不依赖进程内 90s 轮询作为唯一推进机制。进程内任务丢失、cloud-api 重启或慢任务超过短轮询预算后,finalizer 必须能从 durable checkpoint 找回需要追平的 sourceRun/sourceCommand,并以同一 writer 逻辑提交或记录 blocker。
重启恢复要求 finalizer 不依赖进程内 90s 轮询作为唯一推进机制。进程内任务丢失、cloud-api 重启或慢任务超过短轮询预算后,boot/background scheduler 必须能从 durable checkpoint 和 running/projecting turn 找回需要追平的 sourceRun/sourceCommand,并以同一 writer 逻辑提交或记录 blocker。GET、SSE、Web 页面、fake-server 和 probe 只能观察恢复状态,不能触发恢复。
## 6. 原子需求
@@ -240,10 +243,12 @@ Facts schema 至少包含以下事实:
| 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 状态,不推进事实。 |
| 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 状态,不推进事实。 |
Facts store 必须支持幂等 upsert、terminal commit、projection checkpoint、diagnostic update 和按 owner visibility 过滤的分页查询。`agent_sessions.session_json` 可作为迁移期 metadata 来源,但不得继续承载业务 projection 真相
Checkpoint 唯一键必须包含 `sourceRunId``sourceCommandId` 和对应 `turnId`/`traceId`,或等价的 command-scoped 唯一键。同一 AgentRun run 的不同 command 不得共享 cursor;旧 command 的历史事件不得误投到新 turn。`lastSourceSeq` 表示已经成功投影的来源位置,`sourceLatestSeq` 只表示最近观察到的来源最新位置;二者差值可用于 lag/health 诊断,但不得让读侧推断 terminal
Facts store 必须支持幂等 upsert、terminal commit、projection checkpoint、diagnostic update、open checkpoint 扫描、running/projecting turn 扫描和按 owner visibility 过滤的分页查询。`agent_sessions.session_json` 可作为迁移期 metadata 来源,但不得继续承载业务 projection 真相。
### 6.2 WB-PROJ-REQ-002 projection writer
@@ -265,6 +270,10 @@ WorkbenchProjectionFinalizer 应以 checkpoint 为驱动追平 AgentRun facts。
Finalizer 不得伪造 terminal、不取消 AgentRun、不用日志尾部推断 completed,也不得让 GET route 临时同步执行 finalization。若 AgentRun 事实暂不可取或映射失败,finalizer 应写入 diagnostic blocker,保留 retry 所需 sourceRun/sourceCommand/checkpoint。
Startup/resume authority 只属于 cloud-api boot/background scheduler。该 scheduler 启动后必须扫描 durable open checkpoint、`projectionStatus=projecting` 或等价 running/projecting turn,按 bounded concurrency、attempt、lastAttemptAt 和 backoff 推进;它只能调用同一 `WorkbenchProjectionFinalizer/Writer`,不得新增第二套 result polling、manager shortcut 或 GET repair。恢复任务失败时必须写入 `lastError/blocker` 和下一次 retry 所需 cursor,不能静默丢弃。
Finalizer 的 cursor 必须以 command 和 checkpoint 为边界追平。对同一 run 的第二个及后续 commandfinalizer 必须从该 command 自己的 checkpoint 或 command-scoped event/result window 继续,避免每次从 run head 扫描大量旧事件;当只能获得 run-level event page 时,也必须用 `sourceCommandId`、稳定幂等键和 source checkpoint 过滤旧 command 事件。result 先到、events 后到、terminal event 缺失但 command result terminal、source event 缺口或 sourceSeq 回退都必须进入 diagnostic/blocker 或补洞路径,不得在读侧修正。
### 6.4 WB-PROJ-REQ-004 read model and pure GET
| 编号 | 短名 | 主责模块 | 关联模块 |
@@ -277,6 +286,10 @@ 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 修复源头;不得在读取时临时合成“看起来正确”的状态。
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` 只作为来源审计字段;二者不得混用。
### 6.5 WB-PROJ-REQ-005 compat wrapper
| 编号 | 短名 | 主责模块 | 关联模块 |
@@ -307,6 +320,8 @@ SSE 只作为 projection commit 后的通知和加速,不是事实来源。SSE
Workbench唯一投影必须有后端和浏览器两层回归:后端用 Workbench-only HTTP 用例证明 submit 后不访问旧 `/v1/agent/turns` 或 result polling 也能自然 completeddurable recovery 用例证明进程内 sync 丢失或 cloud-api 重启后 finalizer 能从 checkpoint 追平;terminal atomicity 用例证明 session rail、session detail、messages、turn snapshot 和 trace event page 不出现 running/completed 组合矛盾。
Durable recovery 红灯必须覆盖长 run、多 command 和大量旧事件场景。fixture 应优先从 D601 v0.3 真实样本脱敏派生,至少覆盖同一 run 中后续 command 已 completed、eventCount 大于 2000、Workbench 只投影早期 seq、GET 保持纯读、随后后台 resume 从 command-scoped checkpoint 追平并展示 final response 的路径。用例还必须断言 GET 没有调用 AgentRun 或 result polling。
回归还必须覆盖读侧推理清零。后端和前端测试应构造最后一条 trace event 为非终态 `completed`、message text 为空、result/trace/session summary 字段互相矛盾或投影暂时滞后的样本,断言 API 与 DOM 不从这些原始字段推断 terminal/final/running。收口证据应包含负向源码扫描,至少覆盖 `result?.status ?? trace?.status``trace.status` 终结 turn、last event `completed` 终结 turn、message/session/list 状态覆盖 turn、elapsed timeout 改写 terminal 和 no-final-response 占位 final text 等读侧推理路径。
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 收敛。
@@ -322,7 +337,7 @@ fake-server Playwright 应使用目标 node/lane 的真实采集脱敏 fixture
本专项范围内新增或重构的核心源码文件,文件头部必须标注遵循的 SPEC 编号、短名和实现引用版本,例如:
```text
SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-18-p0-zero-repair
SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-19-p0-projector-resume
```
同一文件同时承载 API契约、HWLAB接入、Web工作台或 Agent编排职责时,应在同一头部追加对应 SPEC 编号与实现引用版本。实现文件不得只写 issue 编号、`latest``current`。自动生成文件、第三方 vendored 文件、纯配置、锁文件和无法承载注释头的二进制产物可例外,但对应生成器、渲染器或配置入口必须能追溯到本 SPEC。