# PJ2026-010401080313 Workbench实时权威

## 修改历史

| 版本 | 对应 commit id | 更新日期 | 变更说明 |
| --- | --- | --- | --- |

当前正文仍在规格治理草稿中；未定稿前不新增版本号，不为单次编辑追加 `待提交` 版本。

## 正文

## PJ2026-010401080313 Workbench实时权威需求规格

## 1. 文档控制

| 字段 | 内容 |
| --- | --- |
| 编号 | PJ2026-010401080313 |
| 短名 | Workbench实时权威 |
| 层级 | L4 专项规格切片 |
| 状态 | 已生效 |
| 实现引用版本 | draft-2026-07-08-p0-workbench-realtime-authority-v2; draft-2026-07-09-p1-single-step-debug; draft-2026-07-14-p0-pure-kafka-authority; draft-2026-07-20-p0-kafka-sse-single-projection; draft-2026-07-20-p0-process-session-index; draft-2026-07-20-p0-user-submit-clock |
| 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) |
| 上级规格 | [PJ2026-010401 Web工作台](PJ2026-010401-web-workbench.md) |
| 废弃规格 | [PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) |
| 关联规格 | [PJ2026-0106050514 Workbench实时运行面](PJ2026-0106050514-workbench-realtime-runtime.md)、[PJ2026-010403 API契约](PJ2026-010403-api-contract.md)、[PJ2026-01060508 Web哨兵](PJ2026-01060508-web-probe-sentinel.md) |
| 规格治理索引 | [规格治理](spec-governance.md) |

本文承载 Workbench Realtime Authority v2 的长期裁决。GitHub issue 记录阶段执行和证据；本文定义长期稳定的实时权威、禁止路径、回归和调试工作台边界。

## 2. 目的和范围

### 2.1 目的

Workbench实时权威负责把 Workbench 主 timeline、session rail、turn card、Final Response、Trace detail 和 transport diagnostic 收敛到纯 Kafka 事件权威：

- 固定数据流为 `agentrun.event.v1 -> mapper -> hwlab.event.v1 -> 实时 SSE / Kafka retention 回放 SSE`。
- 浏览器只消费同一 SSE 合同。
- 断线、刷新和 cursor 缺口由服务端按 Kafka retention 回放后继续 live tail。
- `/v1/workbench/sync` 或业务 REST 补链不得成为 correctness path。

PostgreSQL 可以保存查询优化所需的派生读模型，但不是 `agentrun.event.v1` 与 `hwlab.event.v1` 之间的 inline authority，也不是实时或回放 SSE 的启动前置。读模型 schema 缺失、迁移未执行或投影器退化必须形成 warning/diagnostic，不能关闭 direct publish、live SSE、Kafka replay，不能阻塞 Cloud API 启动或滚动上线。

本规格同时定义单步调试工作台。调试工作台必须能在不接触真实运行面、不触发 automatic recovery 和不污染生产 Workbench store 的前提下，用 fake SSE 数据逐条驱动同一 reducer，暴露每一步的 authority decision、entity version、state diff、DOM triad 和禁止请求。

### 2.2 范围内

- `/v1/workbench/events` 交付的 `hwlab.event.v1` schema、Kafka topic/partition/offset、
  stable event identity 和 terminal event 语义。
- Kafka retention 回放 SSE 的 cursor、去重、顺序和回放到 live tail 的切换语义。
- 同一 Cloud API 进程从 Kafka retention 构建并由共享 live fanout 更新的有界
  session 查询索引。
- 首次进入、刷新、切页和重连使用同一 Kafka retention→live SSE 重建 session、message、turn、terminal、Final Response 和 Trace 主状态。
- 上游或基础设施故障、有限重试进度、恢复和耗尽通过同一 Kafka retention→live SSE 重建并持续更新。
- 前端 reducer/adapter 的事件去重、顺序、detail-only rejection 和 diagnostic 输出。
- 自动恢复、SSE error、cursor gap、cross-tab projection signal 和 refresh/reconnect 的允许动作与禁止动作。
- fake SSE 单步调试页、fixture 来源、调试子标签页、请求禁用规则、可视化证据和 Playwright 回归口径。
- web-probe/OTel/analyzer 对 legacy fan-out、sync/replay authority、cross-page convergence 和 fresh submit terminal/final 的判定口径。

### 2.3 范围外

- AgentRun run/command/runner job、provider stream 和 Code Agent 执行事实仍由 Agent编排定义。
- Workbench Temporal workflow/activity 只负责 durable orchestration、retry、cancel 和 worker restart recovery，不拥有 message、Final Response、turn terminal、Trace 或 realtime projection；Temporal history 和 activity result 不得写成第二主状态权威。
- PostgreSQL 派生读模型的内部存储细节不改变本规格的数据权威，也不得成为 admission、实时或回放链路的前置。
- 浏览器内存、freeze blocker、RUM 和 web-probe 运行策略由 [PJ2026-0106050514 Workbench实时运行面](PJ2026-0106050514-workbench-realtime-runtime.md) 和 Web哨兵规格定义。
- 调试工作台不是用户业务入口，不拥有 session lifecycle、权限、Secret、真实 mutation 或运行面修复权。

## 3. 术语表

| 术语 | 定义 |
| --- | --- |
| Realtime Authority v2 | Workbench 主状态只能由 `hwlab.event.v1` 的 retention/live SSE typed event 更新；首次进入、刷新、切页和重连不接受 HTTP 业务快照。 |
| 纯 Kafka+SSE | Workbench 主状态只由 Kafka retention→live SSE 驱动；断线、重复、乱序和缺口通过同一事件合同与 reducer 处理，不存在业务 REST 快照参与、竞争或仲裁。 |
| Kafka replay SSE | SSE 服务按客户端 cursor 从 `hwlab.event.v1` retention 回放 typed event，追上水位后在同一连接继续 live tail；replay 与 live 使用同一事件 schema 和 reducer。 |
| 进程内 session 索引 | Cloud API 进程从 `hwlab.event.v1` retention 一次构建、由同一 shared live fanout 持续更新的有界查询加速器；索引只保存原始 envelope 与 Kafka transport identity，不产生业务事实，不改变 SSE schema、顺序、barrier 或 reducer。 |
| 多源补洞 | 前端在 automatic recovery 中同时或顺序调用 `/turns`、`/sessions/:id/messages`、`/traces/:id/events`、旧 `/v1/agent/*` 等端点来推断 terminal/final/message/session 主状态。该模式禁止。 |
| detail-only | 只服务 Trace detail、历史页、诊断和审计的 payload。它可以展示过程，不能覆盖主 message/finalResponse/turn/session authority。 |
| terminal event | 在同一 `hwlab.event.v1` 顺序中写入 message terminal status、turn terminal、Final Response、timing 和 session running=false 的业务事件；它与其他业务事件使用同一路径，不建立第二种状态权威。 |
| 语义故障事件 | AgentRun 写入并经 mapper 无损投影的上游或基础设施故障事实，包含组件、代码、脱敏摘要、可重试性和执行标识。 |
| 重试阶段事件 | 同一事件流中的重试安排、开始、恢复和耗尽事实，包含当前与最大次数、退让时长和下次重试时间。 |
| cross-page convergence | control page、observer page、刷新页和多标签页在同一 Kafka retention/live SSE 输入下收敛到同一 message count、trace ids、turn status 和 Final Response digest。 |
| 单步调试工作台 | Cloud Web 内的独立调试路由，用 fake fixture 逐条喂入 Kafka SSE typed event，展示 reducer 决策和 UI 投影，不访问真实 Workbench mutation。 |

## 4. 权威输入和禁止路径

Workbench 主状态只接受以下输入：

- `Kafka replay SSE`：首次进入、刷新、切页和重连时，服务端从 `hwlab.event.v1` retention 回放当前授权 session 的完整事件序列。
- `live SSE`：回放追上 barrier 后，在同一连接、同一 event schema 和同一 reducer 上继续交付 `hwlab.event.v1`。
- `explicit detail/history`：用户显式打开的 trace detail、历史分页或详情读取，只能写 detail bucket 或 diagnostic bucket；声明 `detailProjection=true` 或 `authority=trace-detail-only` 时必须拒绝写主状态。
- `optimistic local echo`：submit admission 后的瞬时交互反馈；首个正式 Kafka 事件到达后必须移除或以同一 stable id 收敛，且不得进入跨页面、刷新或重连状态。

禁止路径：

- 页面初始加载、刷新、切页或重连通过 session list/detail/messages、turn、trace 或 result HTTP 响应写入 Workbench 主状态。
- automatic recovery、SSE error、cursor gap、submit reattach、terminal projection 或 cross-tab signal 直接调用 `/v1/workbench/turns/:id`、`/v1/workbench/sessions/:id/messages`、`/v1/workbench/traces/:id/events` 或旧 `/v1/agent/turns|traces|chat/result` 写主状态。
- 用 trace tail、trace detail 末行、message text、session list preview、elapsed timeout、localStorage、DOM active card 或 analyzer fallback 推断 `running`、terminal、Final Response 或 session active。
- 为 session list/detail/messages、detail-only trace payload、transport diagnostic、requestfailed 或 stale running snapshot 建立主状态仲裁、优先级或 sealed guard。
- 用 reload、切换 session、自动 repair helper、测试后门或 probe analyzer suppress 把已经分裂的页面补成通过。
- 用 `/v1/workbench/sync`、数据库 outbox replay、HTTP polling 或读模型查询替代 Kafka retention replay，或在 Kafka replay 可用前要求 PostgreSQL schema 就绪。
- 用 Temporal workflow status、activity result、worker 日志、CLI local result 或 native fixture 推断或覆盖 Workbench running、terminal、Final Response、Trace 和 session rail 主状态。

### 4.1 进程内 session 索引

Kafka retention 回放可以使用进程内 session 索引降低重复全 topic 扫描开销，但必须保持同一权威和同一输出合同：

- 进程启动后从 `hwlab.event.v1` 当前 retention 窗口执行一次有界 bootstrap：
  - bootstrap 先固定 topic/partition/end-offset barrier；
  - 每条记录只按原 Kafka key、原 envelope session identity 和 transport identity
    归入 session bucket；
  - bootstrap 与 live handoff 的重叠只按 topic、partition、offset 和稳定 event
    identity 去重。
- bootstrap 完成后只由现有 shared live fanout 更新索引：
  - 不为每个浏览器或 session 创建常驻 consumer；
  - 不新增数据库、HTTP snapshot、compacted topic、projector 或第二 reducer；
  - 不改变 `hwlab.event.v1 retention -> live SSE -> Web reducer` 的业务路径。
- session 查询必须在调用时固定索引当前 barrier：
  - 只返回该 barrier 及之前属于目标 session 的原始 envelope；
  - 结果继续经过现有 retention-to-live handoff、SSE ingress 和 Web reducer；
  - 索引命中与原 Kafka retention 扫描必须具有相同的事件顺序和 transport
    identity。
- 索引必须有界：
  - 总事件数、单 session 事件数、bootstrap timeout、scan limit 和失败后的
    rebuild cooldown 由 owning YAML 配置；
  - 代码不得为选中 node/lane 隐藏覆盖这些数值。
- 索引是非核心查询优化：
  - 配置缺失、bootstrap 未就绪、超时、offset gap、总量溢出、单 session
    溢出或 rebuild 失败时，必须输出 `blocking=false` warning；
  - 上述退化不得阻塞 Cloud API、admission、live SSE 或 Kafka retention 回放；
  - 请求必须回退现有有界 retention 扫描，禁止返回已知不完整的索引结果；
  - warning、fallback count、bootstrap/rebuild 耗时、indexed event/session 数和
    查询命中耗时必须进入受控 CLI、日志或 OTel 可见性。

### 4.2 用户可见时间基准

纯 Kafka 回放中的用户可见时间必须来自原业务事件时间，不能来自历史帧到达浏览器的时间：

- 每轮 `startedAt` 以该 trace 最后一条用户消息的发送时间为准；
- 用户发送时间必须在浏览器提交时生成，并以 `submittedAt` 随现有
  Workbench command、AgentRun command 和 `user_message` Kafka 事件原样透传：
  - 实时 optimistic row 与正式 Kafka user event 使用同一个 `submittedAt`；
  - refresh/reconnect 只从该 Kafka user event 恢复 `submittedAt`；
  - `user_message` 事件自身的创建时间、AgentRun command 创建时间和 HWLAB
    admission 完成时间不能替代用户发送时间；
  - 旧事件缺少 `submittedAt` 时允许回退到 user event 业务时间并报告
    `blocking=false` warning，不得阻塞核心业务。
- terminal `finishedAt` 以同一 Kafka 事件链的 terminal 业务事件时间为准；
- terminal `durationMs` 只由上述两个时间相减得到；
- session rail 的更新时间以该 session 最后一条用户消息发送时间为准；
- SSE `serverSentAt`、浏览器 `receivedAt`、重放开始时间和索引 bootstrap 时间
  只属于 transport diagnostic，不能写入 message、turn 或 session 的用户可见
  `startedAt`、`finishedAt`、`durationMs`、`lastUserMessageAt` 或 `updatedAt`。

## 5. 单步调试工作台

Cloud Web 应新增独立根导航入口，例如 `/workbench/debug`，navId 可为 `workbench.debug`。该入口面向开发和验收，不是普通用户任务入口。它必须使用隔离的 debug store 或 reducer harness，默认不复用生产 Workbench store，不写真实 session，不调用真实 mutation，不读取 Secret，不通过 localStorage 伪造权威。

调试页应采用左侧 fixture/场景栏、顶部子标签页、右侧 evidence 面板的工作态布局。根侧边栏入口是合理方案，因为单步调试需要独立路由、深链恢复、Playwright 直达和与真实 Workbench 页面并列观察；不应继续塞进现有 topbar 诊断弹窗。

建议子标签页如下：

| 子标签页 | 目标 | 必备能力 |
| --- | --- | --- |
| 纯 SSE 单步 | 单独测试 fake SSE 数据且禁用补洞 | 加载事件序列，`Next`/`Back`/`Run`/`Reset`，每步只调用 reducer，禁止 `/sync` 和 detail REST，显示 state diff、message order、turn status、Final Response digest。 |
| Schema Gate | 验证唯一业务事件合同 | 输入非 `hwlab.event.v1`、缺 stable identity、detail-only、重复或乱序 Kafka transport identity 等样本，展示 accept/reject reason 和 diagnostic。 |
| Terminal Event | 验证同一路径终态 | 从空 store 顺序重放 user、progress、assistant、terminal 事件，断言正文、status、duration 和 Final Response 由同一 reducer 形成。 |
| Reconnect/Cursor | 验证重复、断线和 replay | 模拟 duplicate、missing seq、out-of-order 和 reconnect；只允许重新建立 retention→live SSE，不调用 `/sync` 或业务 REST 补洞。 |
| Cross Page | 验证 control/observer 收敛 | 两个隔离 reducer/page model 接收同一 Kafka retention/live SSE 输入，比较 message count、trace ids、turn status 和 Final Response digest。 |
| Detail Only | 验证 Trace detail 隔离 | 显式展开 trace detail，喂 `trace-detail-only` payload，证明只更新 detail/diagnostic，不写主 message/final/turn/session。 |
| Fresh Store Replay | 验证刷新重建 | 每次从空 store 开始，仅重放 Kafka SSE typed event，证明 session、message、turn、terminal、Final Response 和 Trace 完整重建。 |
| Fake Provider | 验证 fake-echo/fake model 场景 | 使用 redacted fixture 或 fake provider 生成事件序列，检查 submit -> event -> terminal 的高纯度 SSE 路径，不以真实 provider 成败作为通过条件。 |
| Request Ledger | 验证禁止请求 | 记录 debug harness 中所有网络意图；纯 SSE 模式下任何 `/sync`、`/turns`、`/messages`、`/traces` 自动请求都必须红灯。 |

### 5.1 fake 数据来源

fake 数据优先来自真实受控样本脱敏后的 fixture。合成 fixture 只能补足边界条件：

- 非 `hwlab.event.v1` 输入；
- stable identity 缺失或冲突；
- Kafka topic/partition/offset 重复或乱序；
- detail-only payload；
- retention→live handoff 重叠；
- provider stream disconnect。

每个 fixture 必须记录 `fixtureId`、`schemaVersion`、`capturedFrom` 或
`derivedFrom`、`syntheticReason`、redaction 状态和 expected verdict。

纯 SSE 调试的 fixture 应使用 typed event 数组作为第一等输入，不要求启动 fake server。需要浏览器级验证时，可以用 fake EventSource adapter 或 Playwright route 提供 `text/event-stream`，但调试页 reducer 必须能脱离真实 Cloud API 独立运行。

### 5.2 判定输出

每个单步场景必须至少输出：

- event header：schema、eventName、type、sessionId、traceId、eventId、
  sourceEventId、Kafka topic/partition/offset 和 detail-only 状态。
- event decision：accepted/rejected、reason、diagnostic code、是否写主状态。
- state diff：session rail、message list、turn status、Final Response digest、trace detail rows、transport diagnostics。
- request ledger：本步允许和实际发生的网络请求族；纯 SSE 模式必须显示 no-sync/no-backfill。
- triad verdict：DOM-like projection、server-state projection、expected fixture verdict 三者是否一致。
- export：可复制为 Playwright fixture 或 issue closeout 的 bounded JSON/Markdown 摘要，不输出 Secret 或完整敏感 prompt。

## 6. 验收标准

静态验收：

- 自动恢复路径只允许 live/replay `SSE typed event` 或 diagnostic；不得出现 `/v1/workbench/sync`、旧 `/turns`、`/sessions/:id/messages`、`/traces/:id/events` automatic fan-out 写主状态。
- 首次进入、刷新和切页不得用 session list/detail/messages、turn、trace 或 result HTTP 响应初始化或修改主状态。
- 前端主状态代码不得保留 HTTP 快照与 Kafka SSE 之间的优先级、sealed guard 或 merge 仲裁。
- 前端只格式化故障和重试事件，不得自行分类、计数、调度重试或按 elapsed time 推断耗尽。
- `traceHydration*` 命名和运行时口径必须收敛为 `traceDetail*` 或显式 detail read；旧配置字段如保留，只能作为 deprecated alias。
- 非 `hwlab.event.v1` 业务输入以及 `detailProjection=true`、
  `authority=trace-detail-only` 的输入必须被 reducer 拒绝写主状态，
  并产生可见 diagnostic。
- 进程内 session 索引不得新增业务 topic、数据库 authority、HTTP snapshot、
  projector、per-session 常驻 consumer 或第二 reducer。
- replay projection 不得把 `serverSentAt`、浏览器 `receivedAt` 或 bootstrap
  时间写成用户可见 message、turn 或 session 时间。

行为验收：

- fresh submit 能在真实入口中自然 terminal/final 收敛，或明确暴露 provider/adapter blocker；不能靠旧补洞掩盖。
- refresh/reconnect/cross-tab signal 后，control/observer/fresh page 不出现 persistent `cross-page-projection-divergence`。
- `workbench-automatic-recovery-fanout-authority`、旧 agent read-through 和旧 Workbench detail fan-out 不回归。
- fake SSE 单步调试可以在无真实 API、无 `/sync`、无补洞的模式下从空 store 完成 session、message、terminal、Final Response、detail-only rejection 和两页收敛测试。
- L0 从空 store 重放故障和重试 fixture 后，必须显示故障域、组件、代码、当前与最大次数以及下次重试时间；恢复或耗尽必须由对应事件收敛。
- L1 遇到可重试基础设施故障时，必须在策略窗口内显示有限指数退让进度；恢复后继续执行，耗尽后显示语义化终态，不能停留在无解释的 running。
- Cloud API 在 Workbench 数据库 schema 缺失或读模型迁移未完成时仍能启动，并继续 direct publish、live SSE 与 Kafka retention replay；退化项只形成可见 warning/diagnostic。
- 同一 session 首次索引查询与后续命中必须返回相同顺序和 transport identity；
  索引未就绪、溢出或重建失败时原 retention 扫描仍可完成核心回放。
- L0 固定旧业务事件时间和较晚 replay receipt time 时，terminal duration 与
  session rail 更新时间只使用用户消息和 terminal 业务事件时间。
- L0 对同一 `submittedAt` 和 terminal 事件分别模拟实时接收与延迟回放时，
  两者的 `startedAt`、`finishedAt` 和 `durationMs` 必须完全相同。
- L1 对已存在 session 重复切换时，索引命中不得再次扫描完整 topic，连接摘要
  必须披露 index hit/fallback、indexed event/session 数和分阶段耗时。

## 7. 过程控制

本规格由 pikasTech/unidesk#1582 承载架构裁决入口，阶段 issue 包括 #1583 后端合同、#1584 前端接入、#1585 Colada key、#1586 web-probe/OTel 判定、#1587 原入口验收，以及后续 #1591/#1592/#1600/#1606/#1608 等 blocker 和残余收敛。后续代码实现和 closeout 必须引用本 SPEC 编号与实现引用版本，不得只写 issue 编号或“按最新方案”。
