docs(oa): ban UI timing fabrication

This commit is contained in:
Codex
2026-06-24 11:23:12 +00:00
parent 6663c8a35f
commit 5af496aac7
3 changed files with 10 additions and 6 deletions
@@ -19,7 +19,7 @@
| 短名 | Web工作台 |
| 层级 | L2 课题 |
| 状态 | 已生效 |
| 实现引用版本 | draft-2026-06-20-p0-long-running-workbench; draft-2026-06-20-p0-error-diagnostics; draft-2026-06-20-p0-passive-web-probe-observer; draft-2026-06-20-p1-view-local-timing-ticker; PJ2026-0104010803 唯一投影 draft-2026-06-20-p0-durable-facts-model; draft-2026-06-20-p1-zero-split-durable-realtime; draft-2026-06-20-p2-terminal-outbox-recovery |
| 实现引用版本 | draft-2026-06-20-p0-long-running-workbench; draft-2026-06-20-p0-error-diagnostics; draft-2026-06-20-p0-passive-web-probe-observer; draft-2026-06-20-p1-view-local-timing-ticker; draft-2026-06-24-p0-no-ui-timing-fabrication; PJ2026-0104010803 唯一投影 draft-2026-06-20-p0-durable-facts-model; draft-2026-06-20-p1-zero-split-durable-realtime; draft-2026-06-20-p2-terminal-outbox-recovery |
| 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) |
| 上级规格 | [PJ2026-0104 客户端](PJ2026-0104-client.md) |
| 规格治理索引 | [规格治理](spec-governance.md) |
@@ -80,7 +80,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 的渲染投影,不发请求也不写事实状态。 |
| 显示层本地 now | 浏览器组件为了展示“最近 X 秒前”和运行中“耗时 X 秒”而读取的当前时间;它只能作为渲染输入,不能写回 Server State、投影、session/message/turn lifecycle 或诊断事实。 |
| 显示层本地 now | 浏览器组件为了展示“最近 X 秒前”和运行中“耗时 X 秒”而读取的当前时间;它只能作为直接渲染输入,不能写回 Server State、投影、session/message/turn lifecycle 或诊断事实,也不能通过平滑、滤波、单调 floor、跳变 cap 或二次缓存伪造一个更好看的时间事实。 |
| 唯一投影 | [PJ2026-0104010803 Workbench唯一投影](PJ2026-0104010803-workbench-unique-projection.md) 定义的状态链路:AgentRun 执行事实只经 HWLAB projection writer/finalizer 写入 durable Workbench factsREST、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 可以改变这些事实。 |
@@ -254,7 +254,7 @@ flowchart LR
[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 projectionSSE 只是 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。运行中相对时间展示是唯一允许的显示层本地 now 使用场景:`startedAt``lastEventAt``finishedAt` 和 sealed `durationMs` 仍来自 durable projection,浏览器只用本地 now 计算当前渲染字符串,不产生新事实。详细架构图、数据流图、关键时序图、0repair 和严禁读侧推理约束以专项规格为准,本文不再维护第二份投影架构正文。
Web工作台在本规格中只保留前端消费边界:Cloud Web reducer、selectors、session rail、timeline、composer 和 Trace detail 只能消费该专项定义的 durable projectionSSE 只是 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。运行中相对时间展示是唯一允许的显示层本地 now 使用场景:`startedAt``lastEventAt``finishedAt` 和 sealed `durationMs` 仍来自 durable projection,浏览器只用本地 now 对这些权威字段做直接格式化,不产生新事实。前端严禁为了掩盖跳变、归零、非单调、投影滞后或后台 tab 抖动而加入平滑、滤波、单调 floor、跳变 cap、二次缓存、最近更新时间重算或“看起来连续”的时间造假;发现此类异常必须暴露 diagnostic 并修 durable projection、read model、SSE/outbox 或上游时间源。详细架构图、数据流图、关键时序图、0repair 和严禁读侧推理约束以专项规格为准,本文不再维护第二份投影架构正文。
长程可靠 Workbench 的用户可见验收矩阵如下,后续实现和回归验证必须直接引用这些稳定场景,而不是用单次 canary 或局部截图替代。
@@ -363,7 +363,7 @@ Web 工作台在会话恢复、session 切换、turn running、turn completed
工具调用和命令输出行必须正文优先:时间、状态、tool 名称和耗时只作为紧凑 header,不得占用独立左列或固定半屏宽度;stdout、stderr、error、patch、命令结果和助手 Markdown 应获得完整可用宽度。终端完成行和 Agent 最终消息应显示真实轮次耗时,耗时来源应使用 trace 事实、首尾事件时间或服务端 elapsed 字段,不得在已完成运行中显示 `00:00:00` 这类伪完成耗时。
运行中的 Agent 消息头部可以用浏览器本地 now 推进“最近”和“耗时”文案,但计算输入只能是唯一投影返回的 `startedAt``lastEventAt` 时间戳。`lastEventAgeMs`、本地 `updatedAt`、trace tail、events 数组长度或轮询间隔不得进入用户可见相对时间显示路径。消息进入 completed、failed、canceled、blocked 等终态后,耗时必须使用 sealed projection 的 `durationMs` 或等价 sealed `finishedAt - startedAt` 口径,且停止随浏览器 now 增长。
运行中的 Agent 消息头部可以用浏览器本地 now 推进“最近”和“耗时”文案,但计算输入只能是唯一投影返回的 `startedAt``lastEventAt` 时间戳,并且必须是可解释的直接计算`lastEventAgeMs`、本地 `updatedAt`、trace tail、events 数组长度或轮询间隔不得进入用户可见相对时间显示路径。消息进入 completed、failed、canceled、blocked 等终态后,耗时必须使用 sealed projection 的 `durationMs` 或等价 sealed `finishedAt - startedAt` 口径,且停止随浏览器 now 增长。前端不得保存 per-message timing floor、sealed duration cache、recent age cache 或其他本地状态来修正权威时间;若页面可见时间出现跳秒、归零、非单调或与 trace/轮次完成不一致,web-probe 应报告异常,修复点必须回到 projection writer/finalizer/read model 或上游事件时间戳。
Trace阅读视图属于工作态高密度界面。重复 trace row、message card、trace panel、warning 和 inline code 的圆角、间距和 padding 应保持紧凑;默认视觉层级以内容可扫读为主,不使用大圆角、大留白、嵌套卡片或装饰性布局制造工作区浪费。原始 trace 仍必须可审计,但只能作为消息详情入口中的主动展开内容,不得成为默认阅读面或 Trace 展开体的一部分。
@@ -19,7 +19,7 @@
| 短名 | Workbench唯一投影 |
| 层级 | L4 专项规格切片 |
| 状态 | 已生效 |
| 实现引用版本 | draft-2026-06-20-p0-durable-facts-model; draft-2026-06-20-p1-view-local-timing-ticker; draft-2026-06-20-p1-zero-split-durable-realtime; draft-2026-06-20-p2-terminal-outbox-recovery; draft-2026-06-22-p1-workbench-redis-derived-cache |
| 实现引用版本 | draft-2026-06-20-p0-durable-facts-model; draft-2026-06-20-p1-view-local-timing-ticker; draft-2026-06-20-p1-zero-split-durable-realtime; draft-2026-06-20-p2-terminal-outbox-recovery; draft-2026-06-22-p1-workbench-redis-derived-cache; draft-2026-06-24-p0-no-ui-timing-fabrication |
| 需求规格模板 | [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-01060505 Workbench性能](PJ2026-01060505-workbench-performance.md)、[PJ2026-010205 HWLAB接入](PJ2026-010205-hwlab-dispatch.md)、[PJ2026-0102 Agent编排](PJ2026-0102-agent-orchestration.md) |
@@ -90,7 +90,7 @@ D601 v0.3 可以在 `hwlab-v03` namespace 内为 `hwlab-workbench-runtime` 使
| AgentRun execution diagnostic | AgentRun durable ledger 对 runner job observation、stale lease、terminalReportState、reconciler backlog 和不可恢复 blocker 的诊断输出;Workbench 只能把它作为 projection diagnostic 输入,不拥有执行状态写权。 |
| 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。 |
| timing display input | Workbench ReadModel 输出的 `startedAt``lastEventAt``finishedAt` 和 sealed `durationMs` 等投影时间字段;它们是浏览器相对时间文案的唯一事实输入。浏览器本地 now 只能参与渲染计算,不成为 Workbench facts。 |
| timing display input | Workbench ReadModel 输出的 `startedAt``lastEventAt``finishedAt` 和 sealed `durationMs` 等投影时间字段;它们是浏览器相对时间文案的唯一事实输入。浏览器本地 now 只能参与直接渲染计算,不成为 Workbench facts,也不得通过 UI 侧平滑、滤波、单调 floor、跳变 cap、二次缓存或本地推断伪造更连续的 `elapsed/recent` 事实。 |
| 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 推进事实;本专项禁止该模式。 |
@@ -267,6 +267,8 @@ Workbench durable facts 是唯一投影的持久对象模型。后续实现可
对象模型必须支持下列 DTO 投影:session rail summary、session detail、message/part page、turn snapshot、trace event page、projection diagnostic 和 transport diagnostic。DTO 可以裁剪字段,但不得合并 authority;例如 trace detail 可展示 `sourceSeq/sourceEventId` 审计信息,主 timeline 的 finalResponse 只能来自 sealed message/part/turn facts。
运行中和终态 timing DTO 必须保持可审计:`elapsed``recent update`、轮次完成耗时和 trace 首尾耗时的用户可见差异只能来自 durable projection 或上游事件时间戳,不能由 Web reducer、组件、ticker、fake-server、web-probe 或 CLI renderer 在读侧修正。前端只允许把 `now - startedAt``now - lastEventAt` 或 sealed `durationMs` 格式化成中文文案;不得保存 per-message timing floor、recent age cache、sealed duration cache、monotonic repair state 或后台 tab resume 补偿状态。若这些值在采样中出现归零、非单调、跳秒或和 terminal commit 不一致,系统必须暴露 projection/timing diagnostic 并修 writer/finalizer/read model、SSE/outbox 或 AgentRun source event,而不是在 UI 层滤波。
### 5.6 durable projection outbox 与 reconciler
@@ -386,6 +386,8 @@ Workbench 前端、Cloud API 投影层和性能监控不得维护或展示“运
总 elapsed time 只可作为诊断字段、性能分布统计或长任务说明展示,不能作为 timeout 判定条件、关闭依据、自动重派依据或用户可见失败文案。性能指标应分别记录 `elapsedMs``idleMs``lastActivityAt``lastActivitySeq``activitySource`,告警和前端退化只使用 idle/no-response 口径。
Workbench 性能观测必须把“页面可见 timing 是否真实”作为一等指标。web-probe 应采样每个 Code Agent 卡片的 `耗时``最近更新`、轮次完成行耗时、trace 首尾耗时和 terminal sealed duration,并输出采样点表与异常 finding。前端、fake-server、CLI renderer 和 analyzer 不得为了让曲线更好看而平滑、滤波、补零、限速、单调修复或用多来源仲裁替换页面真实值;发现归零、非单调、跳秒、终态后继续增长或与 terminal commit 不一致时,应登记为上游 projection/timing 问题并修权威时间源。
该需求不得削弱功能正确性:terminal result、billing finalize、session owner record、conversation fact 和 trace terminal evidence 仍由最终同步或后续 poll 完成;快速返回只限制单次用户可见 poll 的等待预算,不丢弃 AgentRun 事实、不伪造 final response、不把未完成 turn 标记为完成。
### 6.8 OPS-WBPERF-REQ-008 Performance dashboard 可视化