55 KiB
name, description
| name | description |
|---|---|
| unidesk-webdev | UniDesk Web 开发与浏览器验证技能。用户处理 UniDesk/HWLAB Cloud Web、Workbench、Performance 页、前端状态投影、Playwright、fake-server、web-probe、截图、响应式布局、Web E2E 回归或线上 Web bug 复测/提 issue 时使用。 |
UniDesk WebDev
本技能是 UniDesk/HWLAB Web 开发、浏览器复测和 Playwright 回归的唯一操作面。需求真相源仍是 UniDesk OA 规格,例如 project-management/PJ2026-01/specs/PJ2026-010401-web-workbench.md 和 PJ2026-01060505-workbench-performance.md;本技能只规定如何开发、采集、复现和验收。
P0 防分叉原则
- 单一权威入口:先按 issue/CLI 明确的 node + lane 解析 workspace、web-probe origin、public origin、namespace、sourceRef 和目标分支。没有明确目标时才读取受控 YAML;不得把 D601、G14、v0.2、v0.3、旧端口、ClusterIP 或本地 dev server 写成隐藏默认。
- 防分叉原则:Web/Workbench 修复必须先确定唯一 authority、唯一 API 契约和唯一状态投影入口;不得写成“当字段缺失/请求失败/状态不符/超时/刷新后,再改走另一个 endpoint、旧 workspace/conversation 模型、localStorage、trace polling、result polling、GET read-through repair、内部 manager、legacy route 或测试专用后门”。字段缺失、状态滞后或投影不完整时,修 schema、projector、read model 或正式 mutation 源头;代码里只能保留单一路径内的输入规范化、校验和错误暴露,不能用
A ?? B、if missing then fallback、兼容分支或双写双读把缺口遮住。 - 禁止状态竞争行为:不得在代码、API、reducer、read model、fake-server 或测试中保留两个事实源,再用“覆盖、压过、override、优先级、优先采用、以 A 为准否则 B、A 赢过 B”等仲裁规则决定展示状态;这就是条件分叉和竞争投影。必须先定义唯一投影对象、唯一归属字段和唯一生成时机,让 UI/API 只消费该投影对象的单一状态;其他原始字段只能作为审计输入、诊断字段或待收敛数据,不能参与展示状态仲裁。
- 严禁读侧推理: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 推断 turn/session/message 的 lifecycle、terminal、final response 或 running 状态。读侧只能读取唯一投影对象已经写好的字段;字段缺失、投影滞后或多字段矛盾时必须暴露 diagnostic/blocker 并修 projection writer/finalizer/schema,不得用
result?.status ?? trace?.status、最后一条 eventcompleted、message fallback、session fallback、elapsed timeout 或 UI heuristic 补造事实。 - Sealed final response 不可被读侧诊断覆盖:assistant final response 一旦由唯一 durable projection 写入 terminal/sealed 字段,主消息正文、finalResponse、message status 和 turn terminal 就是 sealed 用户结果;turn polling、trace hydration、SSE gap、realtime timeout、transport close、compat wrapper error 或 read model lag 只能进入 trace detail、transport diagnostics、projection diagnostics、session health 或消息详情入口,不能替换主 timeline 正文。
- 无多路径、无 fallback:这是本技能的核心原则。Web、CLI、fake-server 和线上 web-probe 必须复用同一套 API 契约、同一 route/session/conversation/trace authority 和同一状态投影;不得为了让测试通过增加第二套 dispatcher、localStorage 真相、workspace snapshot 真相、内部 manager 调用、旧 lane 端口、raw request、临时兼容路径或“测试专用后门”。
- 严禁事后 repair / 0repair:Web、Workbench、fake-server 和 web-probe 不得通过 reload、切换 session、realign、
sessionRepair、workspace selection repair、active tab repair、GET read-through、SSE gap repair、localStorage truth 或测试 helper 自动点击,把已经分裂的 route/session/message/trace 状态补成看起来正确。合法页面必须在首次进入、刷新、deep link、session 切换和 SSE 重连时按同一权威自然收敛;不一致必须暴露为 blocker/diagnostic,并修 schema、projector、read model、reducer 或 route authority 源头。允许 session-bound hydrate/gap-fill 只写目标 session 自己的 cache/read model,不得改变 active selection、URL 或当前消息区。 - Workbench GET 纯读投影:
GET /v1/workbench/*只能读取已持久化的 Workbench 投影事实并组装摘要;不得在 GET 中调用 AgentRun、Code Agent 或其他上游执行面做同步、补事件、修 trace、finalize terminal、改 running/completed 或写 message/session。投影滞后必须显式暴露projectionStatus、lastProjectedSeq、sourceRunId、blocker或等价诊断字段,并由后台 projector/finalizer 或显式受控 mutation 处理;刷新页面、切换 session 或打开详情不能成为事实推进入口。 - Workbench session lifecycle:空消息/无活动 session 的回收只能由后端 lifecycle GC、后台 finalizer 或显式受控 mutation 完成,TTL 和开关从选中 node/lane 的受控配置进入运行面;Web、fake-server 和 web-probe 不得靠隐藏 tab、前端 DELETE timer、GET read-through 或 deep link repair 清理。归档/删除后的 session deep link 必须观察同一 authority 的 404/archived diagnostic,不能补建或复活 session。
- Workbench 前端无破坏性投影权:删除 session、清空 active session、清空当前消息页、清空 tabs、把 composer 降成
session_required,或把 route session 标记为 not-found/archived/deleted,都是 lifecycle mutation;Web reducer/selectors、route hydrate、GET/list/detail/messages/SSE consumer、fake-server 和测试 helper 都不能由读侧失败、404、空列表、网络瞬断或 late response 触发这些 mutation。只有用户显式 mutation 成功,或后端 canonical lifecycle projection,能改变 session lifecycle。需求真相见 UniDesk OAPJ2026-010401 Web工作台的“破坏性投影权”。 - fake-server 不是第二后端:它只按正式 API 契约重放脱敏 fixture 和必要边界变形。未 mock 的
/auth/*、/v1/*、/health*请求应失败并暴露 path;不得访问 live Cloud API、AgentRun、HWPOD、数据库或 Kubernetes 作为通过条件。 - 真实数据优先:fixture seed 优先从目标 node/lane 的受控真实样本采集。合成 fixture 只补真实样本难以稳定覆盖的边界,并标明
derivedFrom与syntheticReason。 - 原入口闭环:fake-server Playwright 用例负责可重复红灯和源码回归;线上
web-probe负责同一 node/lane public origin 的 P4 原入口验收。二者不能互相替代。 - Master server 禁重型验证:不要在 master server 跑仓库级 check、Web build、Playwright/browser smoke 或镜像构建。HWLAB Web 验证走目标 node/lane workspace、k3s/Tekton、D601 runner 或受控 web-probe。
- 禁止裸写 Playwright:UniDesk/HWLAB Web 复现、截图、DOM/API 采样、长程 Workbench 观测和线上 closeout 默认必须走
web-probe run|script|observe;不得直接写trans <route> playwrightheredoc、playwright-cli、临时 Node Playwright 脚本或本地 browser daemon 作为正式证据入口。确有非 HWLAB 外站截图/PDF 等 web-probe 不覆盖的短生命周期需求时,必须说明例外原因,且可复用动作要回收进 web-probe。
工作流
- 定位目标:确认 repo、node、lane、workspace、public origin 和目标 SPEC。HWLAB D601 v0.3 例子是
/home/ubuntu/workspace/hwlab-v03+https://hwlab.pikapython.com,但只能在 issue/CLI 指向该目标时使用。 - 读规则:进入目标 workspace 前读取目标
AGENTS.md;涉及规格或测试设计时读取 UniDesk OA 对应 SPEC。 - 线上复现:短动作用
web-probe run|script,长程 Workbench/session 观测用web-probe observe start|command|status|stop|analyze;保存scriptSha256、runDir、observer id、stateDir、截图名、截图 SHA、URL、DOM/API 摘要、prompt hash、trace/session/run id。 - 建红灯:修 Workbench/Performance 用户可见 bug 前,在目标 HWLAB workspace 的
web/hwlab-cloud-webfake-server Playwright 套件中补确定性用例;fixture 从真实采集样本脱敏产生。 - 修源码:保持状态读写单一路径。状态投影类修复优先收敛 server-state/reducer/projection,不在 UI 组件、trace polling、result polling 或 localStorage 中新增竞争事实。
- 验证:先跑 fake-server Playwright 目标用例,再回到同一 node/lane public origin 用 web-probe 复测;多轮任务必须用同一个 observer/session 采样到终态。截图、report hash 和 analyze finding 作为证据回传,不进入源码仓库。
- 写 issue/closeout:问题登记和收口必须写明目标合并分支、node/lane、fixture 来源、Playwright fake-server 用例、线上 web-probe 命令/脚本 SHA、截图 SHA 和剩余边界。
HWLAB Web Probe
线上 Cloud Web DOM 验收优先使用受控入口:
bun scripts/cli.ts web-probe run --node D601 --lane v03
web-probe 入口分三类:
run:repo-owned 标准 DOM probe,适合固定 P4 验收和已有脚本。script:受控 Playwright 托管脚本,适合一轮 55 秒内完成的 DOM/API 断言、截图、route/intercept 和边界采样。observe:纯客户端长程观测,适合同一 Workbench session 多轮任务、realtime/projection 问题、长时间 trace/DOM/network 采样和无副作用报告生成。长程 Workbench 观测默认同时打开两个浏览器页面:control 页面只执行显式observe command用户动作,observer 页面只打开同一个 session 做被动观察,并默认每 3 分钟整页刷新一次同一 session,模拟用户离开后返回,用来抓多用户/多页面下同一 session 的投影差异、历史 trace 丢失、耗时跳变和 loading 差异。
工测优先级:Workbench trace 乱序、完成行位置、耗时不一致、时间跳变、final response flicker、session 不刷新、性能慢路径和多轮可靠性问题,默认先用 observe 采样并跑 observe analyze;不要把临时 Playwright spec、裸 DOM 调试脚本或单次 script 结果当作主要工测证据。script/run 只作为短路径断言、截图/API 摘要或 observe/analyze 后的补充复核。
需要 Playwright route/intercept、延迟 API、读取 in-flight DOM 或截图时仍使用受控 web-probe script,不要裸写 Playwright:
bun scripts/cli.ts web-probe script --node D601 --lane v03 <<'JS'
export default async ({ gotoStable, screenshot, fetchJson, fetchApiMatrix, recordStep }) => {
await gotoStable('/workbench');
const sessionsResponse = await fetchJson('/v1/workbench/sessions?limit=5');
const firstSession = sessionsResponse.body?.sessions?.[0] ?? sessionsResponse.body?.items?.[0] ?? null;
const sessionId = firstSession?.sessionId ?? firstSession?.id ?? null;
const apiMatrix = await fetchApiMatrix([
'/v1/workbench/sessions?limit=5',
...(sessionId ? [
`/v1/workbench/sessions/${encodeURIComponent(sessionId)}`,
`/v1/workbench/sessions/${encodeURIComponent(sessionId)}/messages`
] : []),
'/auth/session'
]);
recordStep('workbench-ready', { sessionsOk: sessionsResponse.ok, sessionId, apiMatrixOk: apiMatrix.ok });
return {
sessionsOk: sessionsResponse.ok,
sessionCount: sessionsResponse.body?.sessions?.length ?? sessionsResponse.body?.items?.length ?? null,
sessionId,
screenshot: await screenshot('workbench.png')
};
};
JS
长程 Workbench 观测使用 observe 命令组:
bun scripts/cli.ts web-probe observe start --node D601 --lane v03 --target-path /workbench --sample-interval-ms 5000 --screenshot-interval-ms 60000 --command-timeout-seconds 55
bun scripts/cli.ts web-probe observe command webobs-xxxx --type newSession
bun scripts/cli.ts web-probe observe command webobs-xxxx --type selectProvider --provider codex-api
bun scripts/cli.ts web-probe observe command webobs-xxxx --type sendPrompt --text 'ping'
bun scripts/cli.ts web-probe observe command webobs-xxxx --type steer --text '继续观察当前 trace'
bun scripts/cli.ts web-probe observe command webobs-xxxx --type cancel
bun scripts/cli.ts web-probe observe command webobs-xxxx --type sendPrompt --text-stdin <<'EOF'
long prompt
EOF
bun scripts/cli.ts web-probe observe status webobs-xxxx --tail-lines 6
bun scripts/cli.ts web-probe observe collect webobs-xxxx --view turn-summary
bun scripts/cli.ts web-probe observe collect webobs-xxxx --view timeline --command-id cmd-xxxx
bun scripts/cli.ts web-probe observe collect webobs-xxxx --view trace-frame --trace-id trc_xxx --sample-seq 42
bun scripts/cli.ts web-probe observe stop webobs-xxxx
bun scripts/cli.ts web-probe observe analyze webobs-xxxx
bun scripts/cli.ts web-probe sentinel plan --node D601 --lane v03 --dry-run
bun scripts/cli.ts web-probe sentinel status --node D601 --lane v03
bun scripts/cli.ts web-probe sentinel image status --node D601 --lane v03
bun scripts/cli.ts web-probe sentinel image build --node D601 --lane v03 --dry-run
bun scripts/cli.ts web-probe sentinel control-plane plan --node D601 --lane v03 --dry-run
bun scripts/cli.ts web-probe sentinel control-plane status --node D601 --lane v03
bun scripts/cli.ts web-probe sentinel control-plane trigger-current --node D601 --lane v03 --dry-run
bun scripts/web-probe-sentinel-service.ts --node D601 --lane v03 --state-root .state/web-probe-sentinel-smoke --scheduler-disabled --once
observe analyze 的 duplicate final response 判定必须以 trace-frame 可见行事实为准。observe collect --view trace-frame 固定渲染的 Final Response 区块是 summary,不是第二条业务 assistant message;只有同一 trace-frame 中出现两个可见 assistant final rows 且内容重复时,才应报告 duplicate finding,并在证据中写明 finalResponseSummaryBlockCounted=false。
observe collect --view timeline 用于 issue closeout 前的 artifact drill-down:它只读取现有 control.jsonl、samples.jsonl 和 commands/{pending,processing,done,failed,abandoned}/*.json,默认输出 bounded timeline、关键 metadata、脱敏 disclosure 和下一步命令。按 --command-id、--turn、--trace-id、--sample-seq、--timestamp 或 --window-ms 缩小窗口;需要完整原始内容时必须显式使用 --raw 或 --view files --file ...。
项目管理 / MDTODO 页面同样优先使用 observe,不要退回一次性 Playwright 脚本。MDTODO 主动编辑验收必须把常见动作沉淀成 observe command,同一 observer 串联 source 配置、HWPOD probe/reindex、文件/任务选择、Rxx 树操作、编辑写回和 Workbench launch:
bun scripts/cli.ts web-probe observe start --node D601 --lane v03 --target-path /projects/mdtodo --sample-interval-ms 5000 --screenshot-interval-ms 60000 --command-timeout-seconds 55
bun scripts/cli.ts web-probe observe command webobs-xxxx --type gotoProjectMdtodo
bun scripts/cli.ts web-probe observe command webobs-xxxx --type configureMdtodoHwpodSource --hwpod-id d601-f103-v2 --node-id node-d601-f103-v2 --root docs/MDTODO/
bun scripts/cli.ts web-probe observe command webobs-xxxx --type probeMdtodoSource
bun scripts/cli.ts web-probe observe command webobs-xxxx --type reindexMdtodoSource
bun scripts/cli.ts web-probe observe command webobs-xxxx --type closeMdtodoSourceConfig
bun scripts/cli.ts web-probe observe command webobs-xxxx --type selectMdtodoSource --source-id <opaque-source-id>
bun scripts/cli.ts web-probe observe command webobs-xxxx --type selectMdtodoFile --file-ref <opaque-file-ref>
bun scripts/cli.ts web-probe observe command webobs-xxxx --type selectMdtodoFile --filename <direct-mdtodo-file-name.md>
bun scripts/cli.ts web-probe observe command webobs-xxxx --type selectMdtodoTask --task-ref <opaque-task-ref-or-rxx>
bun scripts/cli.ts web-probe observe command webobs-xxxx --type openMdtodoReportPreview --task <rxx-or-task-ref> --link <report-label-or-path-fragment>
bun scripts/cli.ts web-probe observe command webobs-xxxx --type toggleMdtodoReportFullscreen --text toggle
bun scripts/cli.ts web-probe observe command webobs-xxxx --type editMdtodoTaskInline --task <rxx-or-task-ref> --field title --text 'web-probe interactive edit acceptance'
bun scripts/cli.ts web-probe observe command webobs-xxxx --type editMdtodoTaskInline --task <rxx-or-task-ref> --field body --text 'body updated through web-probe command'
bun scripts/cli.ts web-probe observe command webobs-xxxx --type editMdtodoTaskTitle --task <rxx-or-task-ref> --text 'web-probe interactive edit acceptance'
bun scripts/cli.ts web-probe observe command webobs-xxxx --type editMdtodoTaskBody --task <rxx-or-task-ref> --text 'body updated through web-probe command'
bun scripts/cli.ts web-probe observe command webobs-xxxx --type toggleMdtodoTaskStatus --task <rxx-or-task-ref> --status completed
bun scripts/cli.ts web-probe observe command webobs-xxxx --type addMdtodoSubTask --parent <rxx-or-task-ref> --title 'web-probe command subtask'
bun scripts/cli.ts web-probe observe command webobs-xxxx --type continueMdtodoTask --task <rxx-or-task-ref> --title 'web-probe sibling task'
bun scripts/cli.ts web-probe observe command webobs-xxxx --type deleteMdtodoTask --task <rxx-or-task-ref>
bun scripts/cli.ts web-probe observe command webobs-xxxx --type launchWorkbenchFromMdtodo --task <rxx-or-task-ref>
bun scripts/cli.ts web-probe observe collect webobs-xxxx --view project-mdtodo-summary
bun scripts/cli.ts web-probe observe analyze webobs-xxxx
MDTODO 或 Project Management 的 Web 重写/布局 closeout 不能只引用组件 diff、PipelineRun 成功或一张默认截图。最小证据应按 SPEC 覆盖:默认深链任务正文可见、Source/File 下拉显示 direct MDTODO 文件名、Rxx 任务树为 outline 辅助视图、右侧报告栏可打开且不挤爆主工作区、报告全屏可读并可关闭。涉及报告渲染时,先用有 reportLinkCount > 0 的任务执行 openMdtodoReportPreview,再执行 toggleMdtodoReportFullscreen,并在 closeout 中记录 command id、reportPreviewVisible、reportFullscreenVisible、报告 deep link、截图 SHA 和 analyze report SHA。
observe 的 Project Management 采样可能同时包含 control 页和 observer 页。control 页是显式用户动作所在页面;observer 页用于被动对照和周期刷新。若 project-mdtodo-summary 或 observe analyze 的最新汇总被 observer 周期刷新、stop 命令或根路由样本带成 SRC=0/FILES=0/TASKS=0,不得直接推翻已完成 command result 和 control 页面截图;必须按 pageRole、command JSON、control URL、screenshot path/SHA 和相邻 samples 解释。反过来,若 control command 失败、command backlog 未清空或截图 URL 不在目标 source/file/task/report 深链上,也不能用 observer 的健康样本替代用户入口证据。
observe command --type newSession 是显式用户/control action:它通过当前 Workbench UI 点击 #session-create 创建新 session,等待 active session id 改变和 composer ready,并把前后 snapshot 写入 control log。它只能用于采样开始时建立目标 session,或作为用户明确的新建会话动作;不得在 route/session mismatch 后当作 repair 手段。
约束:
web-probe script不运行默认探针,必须通过 stdin heredoc 或--script-file <path>提供脚本;只需要 repo-owned 标准 DOM probe 时使用web-probe run。web-probe run|script|observe start的默认 URL、browser proxy mode、observe/analyze 报警阈值和 project-management 采样/命令 allowlist 必须来自config/hwlab-node-lanes.yaml的webProbe;需要排除公网/FRP/跨国 proxy 抖动时,在 YAML 里把目标 node/lane 的webProbe.defaultOrigin配成内部 Service ClusterIP origin,不要在命令行长期手写--url或裸 Playwright。web-probe observe start默认是被动观测:记录 DOM 摘要、自然页面 request/response/requestfailed、截图和 performance 样本,不主动 fetch Workbench API、不切换 control session、不拦截路由、不调用 repair helper。长程 Workbench 观测必须保留 control/observer 双页面模型:control 页面执行显式 command,observer 页面只同步到同一 session URL 后被动采样,并按默认 180000ms 周期整页刷新同一 session 来模拟用户往返;周期刷新只作用于 observer,不得改变 control active session 或作为通过条件。两页的pageRole、pageId、sampleGroupSeq必须进入样本和 analyzer 报表。任何newSession、selectProvider、sendPrompt、steer、cancel、goto、screenshot、mark、stop都必须通过observe command显式下发,并进入control.jsonl;长 prompt 必须优先用sendPrompt --text-stdin或steer --text-stdin,不要为了绕开 shell quoting 退回裸 Playwright 或临时脚本。MDTODO 高频操作也必须优先沉淀为observe command;同类动作第二次出现时不要继续写临时web-probe script。observe command --type steer和--type cancel是显式用户/control action:steer 复用当前 Workbench composer 的运行中 turn 引导路径,cancel 复用同一 composer 主按钮的取消路径。二者必须进入control.jsonl,不能用后端私有 API、AgentRun direct cancel 或测试后门替代。configureMdtodoHwpodSource、probeMdtodoSource、reindexMdtodoSource、closeMdtodoSourceConfig、selectMdtodoSource、selectMdtodoFile、selectMdtodoTask、editMdtodoTaskTitle、editMdtodoTaskBody、toggleMdtodoTaskStatus、addMdtodoSubTask、continueMdtodoTask、deleteMdtodoTask和launchWorkbenchFromMdtodo也是显式用户/control action,只能使用页面公开data-*id、正式按钮和 YAML 允许的自然 API;它们通过 public source/file/task id 与 Workbench 关联,不能读取内部 store、私有后端或把 MDTODO 页面包含进 Workbench。observe collect --view turn-summary是第一层 CLI 阅读视图:只从samples.jsonl、control.jsonl和已有analysis/report.json按需渲染同一 session 的多 turn 摘要,包含用户消息 preview/hash、traceId、状态、耗时/最近更新时间、steer/cancel 标记和 Final Response 摘要。observe collect --view trace-frame --trace-id <id> --sample-seq <n>是第二层 CLI 阅读视图:从同一采样帧渲染单帧 trace 文字截图,并固定输出Final Response区块。observe collect --view project-summary|project-mdtodo-summary从同一 artifact 渲染项目管理 / MDTODO DOM 采样、Source/File/Task 计数、command/mutation 结果、Workbench launch、捕获到的x-hwlab-otel-trace-id和 OTel/Tempo drill-down 线索;project collect 的远端 payload 必须保持 bounded compact rows,由本地 renderer 生成表格,避免transstdout 截断后 JSON parse 失败。collect 视图不是采样器新增保存物,不构成第二事实源。observe start/status/command/collect/analyze默认输出包含Wrapper contract区块;该区块证明 Web 哨兵只能 wrap 现有 observe CLI verb、现有 runner/analyzer 和既有 artifact contract,不新增第二套 Playwright runner、analyzer、状态机或私有 web-probe API。web-probe sentinel plan|status只读取observability.webProbe.sentinel.enabled/configRefs和 owning YAML,渲染 redacted 配置引用图、文件 hash、缺失字段和跨 ref 冲突;web-probe sentinel image|control-plane继续从 owning YAML 渲染 image、GitOps、Argo 和 manifest 计划,并在远端 publish job 接通前拒绝报告部署 mutation。它不启动浏览器、不读取 Secret 值、不保存采样结果,也不是第二套 runner/analyzer。真正的采样和判定仍以observe start|command|collect|analyzeartifacts 为准。- Web 哨兵 public dashboard/origin 必须以 issue/SPEC/YAML 既定计划为准;当前 P6 计划沿用
monitor.pikapython.com,不要未经明确变更改成hwlab-monitor.pikapython.com或其他新域名。验证 report 时记录publicOrigin,但不要把域名硬编码到 runner/analyzer 逻辑里。 - 验证 sentinel public dashboard 页面 DOM/截图(区别于 CI/CD
sentinel status|plan|image|control-plane)时,web-probe script的默认 origin 是 lane 的 HWLAB Cloud Web(gotoStable('/')进入 hwlab workbench),不是 sentinel dashboard origin;必须用显式page.goto('<sentinel publicBaseUrl>/')(publicBaseUrl来自config/hwlab-web-probe-sentinel/public-exposure.*.yaml#sentinel.publicExposure.publicBaseUrl,如https://monitor.pikapython.com)进入 dashboard 页面,再用safeEvaluate/screenshot采样,不能用gotoStable('/')期望落到 sentinel dashboard。这是 web-probe 缺少 sentinel dashboard DOM 验证受控入口的临时绕过,根因见 pikasTech/unidesk#1030;dashboard DOM 验证脚本不要复用 hwlab workbench 的waitWorkbenchReady/session helper 作为通过条件。 scripts/web-probe-sentinel-service.ts是 Web 哨兵 Pod entrypoint;--once只做 config/PVC/SQLite/scheduler/analyzer-command health 快照,--scheduler-disabled仅用于本地服务健康冒烟,不能作为生产运行参数。HTTP 服务只提供/api/health、/api/status、/api/runs、/api/maintenance、/metrics和 redacted dashboard 外壳,底层采样仍只能经 observe CLI adapter。trace-frame出现(无 trace rows;这是 blocker...)时,必须先看同一输出中的TRACE DIAGNOSTIC:记录 pageRole/pageId、traceRows/turns/messages 数量、sampleTraceIds、尾部 traceRow/turn/message 归属。若目标 trace 的 turn/message/final 存在但 traceRows 全部属于旧 trace,应按 Workbench read model authority 分裂登记到架构/业务 issue(例:HWLAB #2124),不得把旧 traceRows 当作新 turn 通过证据,也不得让 analyzer 的聚合计数压过 CLI trace 视图。- analyzer finding 不得压过 CLI
trace-frame人工视图。尤其trace-assistant-message-duplicates-final-response只有在trace-frame中同一 completed turn 可见多条相同 assistant final rows 时才按业务 bug 处理;如果trace-frame只有一条 assistant final row、后面固定Final Response区块正确且 API messages/turns 对齐,该 amber 归类为 analyzer 精度问题,应登记/修工具,不得阻止业务 closeout。 - 若
observe status显示 PID still alive 但 heartbeat/sample 不推进、commands/pending/*.json不被消费,或observe stop --force只是继续排队 stop command,应先按 web-probe runner 工具缺陷处理(例:UniDesk #874),用 route 只读确认 PID/heartbeat 后清理进程;不要把 pending command、未触发的 cancel 或 runner stale 混入 Workbench 业务结论。 web-probe observe的 issue evidence 优先记录 observer id、stateDir、report JSON/Markdown SHA、samples/control/network/artifact 计数、routeSessionId、activeSessionId、prompt hash/textBytes、traceId、AgentRun runId/commandId、最终 status 和必要摘要;不要把 prompt 原文、assistant 大段正文、完整 stdout/stderr 或 provider payload 粘贴到 issue。- 多轮 Workbench 采样必须证明同一个
sessionId连续承载所有轮次;每轮至少记录 prompt hash、traceId、终态、最终回答摘要和性能/产物表。若 Web UI 投影卡住但 Code Agent/AgentRun result 已 terminal,应同时登记“执行终态”和“Workbench 投影未收敛”,不得用goto、reload、切 session 或 result polling 把 UI 失败伪装成通过。 observe command --type sendPrompt是普通新 turn 路径,composer 主按钮应处于data-action=turn;如果仍是steer或cancel,必须作为工具/页面状态不一致失败暴露,不能点击后再等待错误接口。空输入状态下 submit disabled 可以为 true,不能把 disabled 当作新 turn 不可用的唯一依据;应先看 input present/enabled、warning absent 和 action=turn,再由正式填入 prompt 后提交。observe analyze是离线分析,只读取 artifact JSONL 并写analysis/report.md与analysis/report.json,不访问 Workbench API、不驱动浏览器。observe start每次启动必须先把同一 stateDir 中已有的根目录 JSONL 轮转到带时间戳的archive/文件;observe analyze默认只分析当前根目录 JSONL,不扫描历史 archive,只有显式指定 archive prefix 时才分析历史轮转窗口。报告必须输出采样点 vs 每个 turn 的总耗时/最近更新时间表、trace row 视觉顺序异常、terminal/轮次完成 row 是否最后、Code Agent 卡片耗时与 trace/轮次完成总耗时一致性、可见“加载中”的数量/归属/并发 owner/连续出现区间、DOM diagnostic/HTTP/console/requestfailed/runtime execution error 分组、page asset provenance segment、同源 API Resource Timing 分位表和超过 YAMLwebProbe.alertThresholdsbudget 的慢路径 finding;项目管理页还必须输出 DOM readiness、source/file/task 计数、缺失 public task ref、Workbench launch success/failure、captured OTel trace header、自然 project-management API 分组和超过 YAMLwebProbe.projectManagement.slowApiBudgetMs的慢路径 finding。页面/API 加载、可见“加载中”、长连接打开耗时、turn timing 跳变、trace row 顺序、卡片耗时/轮次完成耗时一致性、session fallback 标题比例和项目管理 API 慢路径阈值只能改 YAML,不能在 analyzer/renderer 中写死。修复必须降低真实请求、投影、渲染或后端路径耗时,禁止为了减少“加载中”出现时间而提前展示未加载完的内容,也不能靠下游 retry/reload/fallback 掩盖。报告里的trace-row-order-nonmonotonic、trace-completion-row-not-last、round-completion-elapsed-mismatch、code-agent-card-duration-underreported、final-response-flicker、uncommanded-visible-state-change、mdtodo-workbench-launch-otel-trace-missing、project-management-api-slow、session changed、network 503 等 finding 是排障线索;用于 closeout 时必须结合原始 session/trace/DOM 证据解释,避免把采样噪声直接当作业务结论。sentinel validate --quick-verify超过 120s 是严重超时,必须保持 warning/red 并优先从 envreuse、git mirror、warm runner 复用、first tool execution、Workbench 投影和 observe/analyze 开销排查;不要通过提高 budget、减少轮数、放宽 analyzer 或绕过 CLI trace 视图来让场景变绿。quick-verify 等待每轮终态时应读取既有 sampler artifacts 和 bounded collect 视图,不能反复启动完整 collect 或新增第二份“trace 截图”保存来源。- 自定义
web-probe script仍运行在 UniDesktrans60s 最外层短连接约束内;能在一轮内完成的 P4 验收优先把--command-timeout-seconds控制在 55 秒以内,并减少无界 selector/network 等待。确需等待更久时,改用web-probe run的异步 job/status 语义,或把动作拆成“提交/采样/截图/状态读取”多次短 probe。若输出出现UNIDESK_SSH_RUNTIME_TIMEOUT但同时恢复了reportPath、reportSha256、screenshots 或 DOM steps,先按远端报告判断脚本/页面实际状态;最终关闭证据仍优先用一次未触发短连接超时的 bounded rerun。 - issue closeout 优先引用
web-probe script输出的顶层issueEvidence或summary.issueEvidence;只有需要展开调查时才粘贴probe.script.result、probe.steps或完整reportPath,避免 stdout、summary 和 report 多层重复同一证据。 - stdin heredoc 与
--script-file都按 ES module 加载,脚本必须导出export default async ({ page, gotoStable, recordStep, ... }) => { ... };不要在模块顶层直接写return。失败为Illegal return statement、does not provide an export named default或 finalUrl 仍是about:blank且 stepCount=0 时,先按 probe 脚本入口误用处理,不要归因成 Cloud Web 行为失败。 - 自定义脚本需要主动失败时,优先返回
{ ok: false, failedCondition: "..." }或抛出错误;兼容返回{ pass: false }、{ success: false },且{ ok: true, pass: false }仍按失败处理。failedCondition、errorMessage、message、error、reason或summary会进入失败摘要;不要只把失败埋在普通业务字段里。 - web-probe 由 UniDesk CLI 从 YAML 声明的 bootstrap admin sourceRef 读取凭据并建立同源
hwlab_session;脚本不得自行读取、打印或复制 Web 登录凭据、cookie、token 或完整 API key。 - 需要禁用
EventSource、mockDate/clock、注入 preload hook 或修改浏览器启动前全局对象时,page.addInitScript()必须在目标页面整页加载前注册,并用page.goto(new URL(path, origin).toString(), { waitUntil: "domcontentloaded" })进入目标 deep link;不要依赖gotoStable()复用当前 SPA 页面后再期待 init script 生效。若只在已加载页面上 route/block 请求,既有 SSE 或 store 状态可能继续更新,不能作为“无后端刷新依赖”的验收。 - 脚本构造 URL 时使用
new URL(path, baseUrl).toString();不要拼出//v1/...。 - 先通过
gotoStable、waitWorkbenchReady或等价导航进入目标 origin,再用fetchJson读同源 API;不要在about:blank上请求/v1/...。fetchJson返回包装对象{ ok, status, body, failureKind, ... },业务字段必须从.body读取,并同时记录ok/status/failureKind;如果返回status=0且页面还不是目标 origin,先按 probe 脚本误用处理,不要归因成 Cloud API 或 Workbench 投影失败。 - Workbench 有 SSE/长轮询时不要用
networkidle判断通过;用明确 DOM/API 条件,如 final URL、route sessionId、active tab、message card、trace row 或 durable session detail/messages。 - 当前 HWLAB v0.3 Workbench durable read model 的验收端点是
/v1/workbench/sessions、/v1/workbench/sessions/{sessionId}、/v1/workbench/sessions/{sessionId}/messages、/v1/workbench/turns/{traceId}和/v1/workbench/traces/{traceId}/events;提交 mutation 可用正式/v1/agent/chat产生真实 turn。/v1/workbench/workspace只在当前 API 契约声明为选择/config 快照时采集,不作为消息或 trace authority;/v1/agent/conversations属于旧模型,不得作为 v0.3 Workbench durable projection 的通过条件。 - 需要稳定 running message、timing、SSE 或 projection 样本时,优先通过正式同源 mutation 创建样本:
POST /v1/agent/sessions建 session,再按前端同一路径提交/v1/agent/chat,轮询/v1/workbench/sessions/{sessionId}/messages等待 durable projection。不要把历史 session 是否仍 running 当作验收前提,也不要用旧 conversation/workspace 端点造样本。验收结束后能取消的 turn 必须调用/v1/agent/chat/cancel清理,并在 issue evidence 只记录 trace/session、status、script/report SHA 和必要摘要,避免粘贴完整 provider payload。 - HWLAB v0.3
fa2ad4845a111e0f9e86d473eb4204ed1b2b0a3c后,repo-ownedscripts/web-live-dom-probe.mjs的默认web-probe run --fresh-session已使用 durable Workbench session 端点,不应再依赖/v1/workbench/workspace或/v1/agent/conversations作为消息/trace authority。若session-not-selected复现,先确认目标 workspace 已包含该提交,再对 helper 做旧端点扫描;只有扫描仍命中旧端点时才按工具链回归处理。 web-probe run --fresh-session空消息路径的基线证据是 D601 v0.3 jobweb-live-dom-probe-1781842424721-44066:freshSessionAligned=true、messageCount=0、report SHAd34c6765943e14bbd639b91bfc17139d582f670ed5cf409a957acd40fae7871f、screenshot SHA8d341b7c30293baa9be8f1e63e147ea0fdafbdbcfc43f0b05e4fb9f316ef996c。- 若带
--message的 fresh-session 路径已经达到freshSessionAligned=true、promptSubmitted=true、messageCount>0和 session API 200,但随后报trace-id-missing、Workbench turn is not visible to the current actor或 trace 面板同类不可见文案,应登记为 Workbench turn/trace actor visibility 问题,不再归因到 fresh-session 选择 helper 或旧端点。 - Playwright
page.evaluate只能传一个可序列化参数;多个值包成对象,或用safeEvaluate(fn, { a, b })。 safeEvaluate返回结构化包装对象;脚本断言前必须解包,例如const evaluated = await safeEvaluate(...); const dom = evaluated?.value ?? evaluated;。recordStep可以记录包装对象用于诊断,但行为断言不要直接读包装对象的业务字段,避免把已通过的 DOM 误判成undefined。- 脚本用
page.evaluate模拟滚动、resize、click 或派发 DOM event 后,若断言 Vue/React 绑定出的data-*、ARIA、按钮状态或 scroll-follow 状态,必须先等待一次浏览器/框架更新,例如await wait(300)、page.waitForFunction(...)或下一次明确 DOM 条件;不要在同一个 evaluate 内写完事件就立刻读取状态,否则会把尚未 flush 的响应式状态误判为业务失败。验证用户滚动暂停/恢复时优先记录操作前后 scroll metrics 和data-following的延迟稳定值。 web-probe script顶层/default export 运行在 Node 上下文,浏览器全局window、document、location、CSS只在safeEvaluate/page.evaluate回调内可用。Node 侧 deep link 用const origin = new URL(page.url()).origin; await page.goto(new URL('/workbench/sessions/' + encodeURIComponent(id), origin).toString()),或直接用gotoStable('/workbench/sessions/<id>');不要在 Node 侧写location.origin、CSS.escape(...),也不要用没有 baseURL 的page.goto('/relative/path')。若失败为location is not defined、CSS is not defined或相对 URL invalid,先按脚本误用处理;工具提示改进跟踪见 pikasTech/unidesk#479。- 脚本中用
recordStep(name, data)保存关键 DOM/API partial evidence;API 批量探测优先用fetchApiMatrix(paths),单个 API 失败不应让后续证据丢失。 - deleted/archived/not-found session deep link 验收用
web-probe script直接gotoStable('/workbench/sessions/<id>'),再用同源fetchJson('/v1/workbench/sessions/<id>')、messages 和 list API 断言 404/不在列表;不要调用要求 active session selection、composer readiness 或 workspace repair 的 helper 作为通过条件。 - 验证 Cloud Web runtime config 或 HTML 注入时,优先加 cache-busting query 和
cache-control: no-cache,并按层拆开判断:Deployment env、Pod 内127.0.0.1HTML、公网原始 HTML、浏览器 DOM。不要只凭一次 web-probe DOM 缺字段就判定 rollout 失败;先确认是运行面未渲染、Pod 未滚动、边缘缓存,还是脚本读取层级错误。 - web-probe 只能观察、截图和断言,不得用
sessionRepair、realignFreshSession、自动点击 session、reload 循环或 workspace selection repair 作为通过条件。发现routeSessionId、activeSessionId、activeConversationId、message session 或 trace session 不一致时,必须记录 mismatch 并失败;截图和 API 摘要是证据,不是修复动作。 - 失败证据至少保留
failureKind、errorMessage、scriptSha256、runDir、lastUrl、lastScreenshot、probe.summary和reportPath/reportSha256;默认失败截图是failure.png。
Fake-Server Playwright
Workbench 回归入口在目标 HWLAB repo 的 web/hwlab-cloud-web:
bun run e2e:workbench -- --project=chromium
运行面要求:
- 在 issue/CLI 选中的 node/lane workspace 或其独立 worktree 上运行,不在 master server 本地运行。
- 同源 fake-server 只提供正式 API 契约,覆盖
/auth/*、session list/detail/messages、turn snapshot、trace event page、Workbench event stream、Performance summary 等当前用例所需端点。 - 测试断言优先使用用户可见文本、ARIA role 和稳定 DOM 标识;不要通过内部 store、localStorage、数据库或 live API 直接判定通过。
- 非终态瞬时不变量必须用立即 DOM 快照断言:例如 running/pending 阶段要求 final response 为空时,先定位当前 agent card,再用
locator.evaluate/page.evaluate直接读取.message-markdown.message-text数组并立刻判断;不要用会自动等待的expect(locator).toHaveCount(0)、not.toContainText或类似负向 locator 断言,否则测试可能等到 terminal DOM 替换后误通过,掩盖 running 阶段污染。 - 失败必须保留截图、Playwright trace 或等价 artifact;关键路径可生成命名截图。
Workbench 至少覆盖:
- session 切换后主工作区 loading 和目标 conversation 恢复;
- 刷新页面后以同一 message/turn/trace 标识还原 timeline;
- SSE 断线、丢事件或重连后通过 REST snapshot 与 trace page 补洞;
- session tab、workspace card、message card、composer 主按钮、Trace detail 的
running/completed/failed/canceled一致性; - completed assistant 已 sealed 后,turn snapshot、trace event page、SSE 或 realtime diagnostic 失败不覆盖主消息正文,诊断只进入详情/感叹号/transport health;
- Trace 阅读按事件顺序渲染可读 row,正确处理分页、终态、失败、自动展开和终态折叠;
- deep link 与普通点击 session 走同一 authority path;
- Performance 页的摘要、错误态、刷新、移动端表格可达性和低基数脱敏展示。
Fixture 采集与脱敏
- 采集范围至少包括 session list/detail/messages、session/turn snapshot、trace event page、Workbench event stream 和 Web performance summary;workspace selection/config 只有在当前 API 契约仍声明该读模型时才采集。
- 产物必须记录
capturedFrom、capturedAt、schema/redaction 版本和valuesPrinted=false。 - 使用稳定伪 ID 映射保留 conversation、session、thread、turn、trace、message、sourceSeq 的关系。
- 删除或替换
HWLAB_API_KEY、cookie、Authorization header、DB DSN、provider token、真实用户身份、非公开 prompt、stdout/stderr 大段原文和完整 provider payload。 - 真实样本难以覆盖的延迟响应、SSE 断线、分页缺口、列表缺少当前选中项、可选字段异常、空集合和特定 HTTP 错误可以合成,但必须说明来源和原因。
Workbench 判定口径
- Workbench API 的 GET 路径不是修复入口。若 session/messages/turn/trace 出现状态不一致,应登记为投影唯一性或投影延迟问题,修 backend projector/read model;不得用前端轮询、session 切换、reload、read-through sync 或 GET 内部修复把问题掩盖。
- Workbench 读侧不得推理生命周期。
turn.status、message.status、session.running、trace terminal、finalResponse、projectionStatus只能来自唯一 durable projection;trace event row 的completed只表示该 event/tool row 完成,不能终结 turn;message 文本为空只表示无可展示正文,不能生成占位 final response;list summary、session detail、turn snapshot、trace page 之间的差异只能作为 diagnostic,不得用优先级函数在读侧“选一个看起来合理的状态”。 - Workbench sealed final response 必须与读侧诊断分仓。
messageProjection承载 role/status/text/finalResponse/sealedAt,traceDetail承载 events/page hydration/trace diagnostics,sessionStatus承载 rail/card 运行摘要,transportDiagnostics承载 SSE/poll/hydration timeout 等可见性诊断;等价结构可以使用不同命名,但主消息投影和 diagnostic 不能竞争同一字段。showMessageText()、message diagnostic selector 和组件模板不得让 diagnostic 压过 sealed final response。 - Workbench trace 视觉顺序的唯一权威是 durable projection 分配的
projectedSeq。projectedSeq必须由持久化 runtime store 在 trace 内全局递增分配,并按traceId + sourceEventId幂等复用;本地event.seq、sourceSeq、事件到达顺序、时间戳、DOM 顺序和 renderer 输入顺序只能作为审计输入或源游标,不能直接派生视觉位置或参与仲裁。重复源事件不能分配新projectedSeq;不同源事件即使局部event.seq重置为 1 也必须分配新的全局projectedSeq,这个幂等性需要有最小单元测试覆盖。 - Workbench trace 时间字段的 source truth 是后端和 trace event page 暴露的 ISO/UTC 时间戳;后端 projector、durable read model 和共享 renderer 默认行为不得改成本地时区字符串。Web 展示北京时间或其他用户时区时,只能在 Vue/Web 渲染层从 runtime
displayTime注入 formatter;CLI、CaseRun 和原始 trace API 仍显示/返回 UTC,不通过多字段仲裁、默认 fallback 或后端补写时区字符串修显示。 - Trace event page 检测到同一 trace 内历史
projectedSeqcollision 时必须暴露projectionStatus=blocked、projectionHealth=degraded和稳定 blocker code,不能把损坏序列交给 CLI/Web renderer 继续展示。CLI/Web trace renderer 只能按 projection 已给定的位置一次渲染;不得通过 assistant 文本相等/包含、final response 匹配、尾部排序、terminal row 合并或 completion row 追加来事后修正视觉顺序。 - Workbench durable projection 验收必须覆盖同一 session/trace 的 list、detail、messages、turn、trace events 和 DOM session tab/message card;尤其要用 fresh browser 或 runtime 重启后的历史 terminal 样本证明 read model 能从 durable trace events 恢复终态。若内存 trace 仍显示 running 而 durable trace 已 terminal,应修唯一 read model 的投影对象,不得在 GET handler、前端 reducer 或 probe 脚本里做临时状态仲裁。
- HWLAB #1585/#1596/#1690 是 Workbench 投影禁令的固定判例:AgentRun 已 terminal 但 Workbench 停在旧 seq 时,不得用 GET/read-side 补 result;turn/card completed 但 TraceEventPage seq/range 不合法时,不得用 completed 状态压过 trace 不可读事实;Trace timeline 乱序或 terminal row 重排时,不得让
sourceSeq、局部event.seq、输入顺序和 renderer 文本匹配多来源仲裁。合法修复是后台 projector/resumer 补 durable projection,在同一 trace event 快照内修正分页/顺序契约,或暴露 historical projection blocker;不得推断 lifecycle、补写 GET、切 session/reload 修页面、添加多来源优先级或在 renderer 做事后 repair。 - Session rail 会话集合只消费
/v1/workbench/sessions;当前 session detail 只消费/v1/workbench/sessions/{sessionId};消息本体只消费/v1/workbench/sessions/{sessionId}/messages;turn 状态只消费/v1/workbench/turns/{traceId};trace 阅读只消费/v1/workbench/traces/{traceId}/events或正式 trace event page。不要让 workspace snapshot、列表摘要、localStorage、trace polling 或 result polling 互相覆盖。 - 空消息 session 回收验收必须同时证明:未超过 TTL 的空 session 保留,有消息、running/admitting、terminal result 或 active trace 的 session 不被回收;超过 TTL 的空 idle session 由后端 GC 归档/删除后,rail/list/detail/messages/deep link 都按同一 canonical lifecycle 状态表现。
- UI transient state 只保存 route、显式选择、composer draft、scroll、展开状态和临时交互状态;服务端事实进入 server-state/reducer/projection。
- running turn 必须同时反映在主任务区、composer 主按钮、session tab 和可取消入口;清空、切换、刷新不得把 running trace 隐藏成空态。
- 显式新建或选择 session 是 active selection 的 mutation authority;
POST /v1/agent/sessions返回 201 或用户点击目标 session 后,URL、active tab、当前消息区和 composer 必须立即归属目标 session。目标 session detail/messages 慢只能表现为该目标 session 的 loading/empty 态;旧 session 的 list refresh、detail、turn、trace、SSE 迟到事件只能更新旧 session 自己的 cache/status,不得继续占据或夺回 active route、message area、composer/cancel 状态。 - 读侧没有破坏性投影权。
GET /v1/workbench/sessions、session detail、messages、SSE、route hydrate 或 refreshSessions 的失败、404、空列表、网络错误和迟到响应,只能显示 loading/degraded/unknown/blocker 或保留上一份成功投影;不得forgetSession()、replaceActiveSessionSelection(null)、清空 messages/tabs,或把 composer 改成session_required。deleted/archived/not-found 必须来自后端 canonical lifecycle projection,或来自用户显式 DELETE mutation 成功后的展示更新。 - terminal failure、blocked、canceled 都是最终结果;若 API 返回可读 error/blocker,final response 展示区必须直接显示,不能只放在 trace rows 或详情面板中。
- completed、failed、canceled、blocked 的 sealed final result 一旦显示,后续 polling/hydration/SSE/realtime 的 timeout、500、gap、close 和 lag 只能改变诊断区,不得把已显示 final response 闪回
Code Agent 代理暂时无法连接上游、turn 超时无新活动、projection-resume:sync-failed或同类读侧错误态。 - session 切换验收必须覆盖点击态和持久化恢复态:选择目标 session、确认 route/session list/detail/messages 归属同一
sessionId、刷新后同一 session 仍 active。 - completed turn / Trace 重放 / deep link 验收必须用 fresh browser context 或等价 fresh login 直接打开
/workbench/sessions/<sessionId>,不能只用同页 reload。 - 0repair 验收必须用 fresh context 直达 session/deep link,或从当前 session 显式切换到目标 session;不得依赖测试 helper 选择、reload、切走再切回、
sessionRepair或realignFreshSession修正页面后再判通过。旧 session 的延迟 detail、turn、trace、SSE 或 refreshSessions 晚到,只能更新该 session cache/list,不能改变 active URL、active tab、current messages 或 composer。 - Workbench reducer/selectors/0repair 收敛类 closeout 必须做负向源码扫描并在 issue/PR 证据里写明结果;至少覆盖直接写服务端事实和旧 repair 名称,例如
messages.value =、messages.value.push、sessions.value =、previousMessages、previousSessionId、restorePrevious、restoreMessagesTraceAuthority、repairWorkbenchMessagePage、findMessageTextFallback、projectionCatchup、PROJECTION_CATCHUP和组件侧workbench.messages。这些扫描是辅助证据,不能替代 fake-server Playwright 与 public web-probe。 - Trace 实时性要用间隔采样,区分“加载中”和“思考中”;终态卡片不得继续保留“思考中”空态。
- 用户反馈“当前 session 不刷新、切走再切回才刷新”时,证据必须成对采集:直达目标 URL、原地等待、切到其他 session、切回目标 session 的 DOM 截图;同时记录 session list、session detail、messages、turn snapshot 和 trace event page 的状态。issue 正文要明确这是事件投影/重放问题,不能只登记成普通 deep link 或单接口 404。
Performance 页判定口径
/performance只展示低基数、脱敏的 Workbench/RUM/API/long task 汇总;不得泄露conversationId、sessionId、traceId、runId、prompt、assistant 正文、tool 参数、stdout/stderr、Secret 或用户身份。- 单位以 API
unit为准;后端若以 seconds 存储,前端显示 ms 时必须只做一次换算。 - 移动端和窄屏断言要检查目标表格/按钮是否可见、可点击、layout rect 非零且可触达;不要只用 desktop selector readiness 代表所有 viewport。
- 刷新按钮应有明确 loading/error/empty 状态,重复点击不能制造 stuck loading、旧数据冒充新数据或未捕获 console/page error。
UniDesk Frontend E2E
UniDesk 主前端交付门禁仍由 bun scripts/cli.ts e2e run 承担;本技能规定浏览器侧如何选取和解释验证。
- 先跑最小相关选择集,例如
bun scripts/cli.ts e2e run --only frontend:pipeline;目标检查通过后再跑完整bun scripts/cli.ts e2e run。选择集是真执行,不是输出过滤。 - 浏览器必须打开
config.json/ publicHost 派生的公开 frontend 或 dev frontend proxy;不要用 localhost、Docker internal URL 或后端 API 直调替代用户入口。 - 前端断言优先使用用户可见文本、ARIA role、稳定 DOM 标识和 React 控件状态;禁止用 raw JSON、内部 store、localStorage 或后端数据库绕过 UI。
- 高信息密度区域如 Pipeline 右侧栏、Trace timeline、详情抽屉、甘特图坐标、资源监控表和 Performance 面板,必须显式检查总高度、横向滚动条、关键控件可见可点、文本不重叠。
- 用户服务页必须等待真实后端数据,而不是只看页面骨架;Todo Note、OA Event Flow、Code Queue、FindJob、Pipeline、MET Nonlinear、ClaudeQQ 等页面的通过条件以当前 E2E check 名称和 issue scope 为准,不在文档里复制所有字段清单。
- raw JSON 只能在用户显式点击
查看原始JSON后出现;默认页面必须把 JSON 渲染为表格、卡片、徽章、树、图或其他可读控件。 - 任何 frontend E2E 失败都应保留截图路径、resultPath、failedChecks 和关键 console/page error 摘要;不要把 missing browser/deps 当作 skip,按锁文件和目标执行面补依赖后继续。
受控 web-probe 代替裸 Playwright
UniDesk/HWLAB Web 工作不再把裸 Playwright 当作默认操作面。需要截图、DOM 断言、API matrix、route/intercept、SSE 降级、长程 session 采样、性能页面复测或 Workbench 多轮任务时,统一选择 web-probe run|script|observe。
web-probe observe analyze 必须把 Workbench session 列表标题纳入默认采样与报告:可见列表中 Session ses_... fallback 标题超过一半时输出红灯 finding。修复方向必须让上游 session list projection 直接携带名称;点击详情后的下游补名、reload repair 或多来源仲裁不能作为修复。
trans <route> playwright、playwright-cli 和临时 Node Playwright 脚本只允许作为非 HWLAB 外站短生命周期截图/PDF、或 web-probe 尚未覆盖且一次性不可复用的诊断例外。例外使用前必须写明为什么 web-probe script 或 web-probe observe 不适用;同类动作出现第二次就应补进 web-probe CLI 或 repo-owned probe。
需要把截图回传到本机时,优先用 web-probe script 的 screenshot(name),或长程观测中使用 observe command --type screenshot --label <label>,并在 issue 中引用截图 SHA、report SHA、observer id 和 stateDir。不要把本地 Playwright artifact 当作 HWLAB node/lane 原入口验收替代品。