docs: add unidesk webdev skill
This commit is contained in:
+3
-47
@@ -82,59 +82,15 @@ AgentRun terminal `failed`、`blocked` 或 `canceled` 也是最终结果,不
|
||||
|
||||
### Workbench 浏览器回归专项
|
||||
|
||||
Workbench 浏览器回归需求以 UniDesk OA [PJ2026-010401 Web工作台](../../project-management/PJ2026-01/specs/PJ2026-010401-web-workbench.md) 的浏览器回归小节为权威;UniDesk 指挥侧只记录运行入口和边界。HWLAB repo 中的专项入口位于 `web/hwlab-cloud-web`,通过 `bun run e2e:workbench -- --project=chromium` 构建 Cloud Web,并由 `playwright.workbench.config.ts` 启动同源 fake server 和 Playwright Chromium。该命令必须在 issue/CLI 选中的目标 node/lane workspace 或其独立 worktree 上运行,例如 D601 `v0.3` 的 `/home/ubuntu/workspace/hwlab-v03`;不要在 master server 本地运行浏览器或仓库级前端 check。
|
||||
|
||||
该套件验证 Web 工作台用户可见行为:session 切换和刷新恢复、SSE/REST 事件重放、`running`/`completed`/`failed`/`canceled` 状态一致性、Trace readable rows、deep link hydration 和延迟会话列表最终状态。fake server 只重放脱敏 fixture 和最小边界变形,不得访问 live Cloud API、AgentRun、HWPOD、数据库或 Kubernetes 作为通过条件;任何未 mock 的 `/auth/*`、`/v1/*` 或 `/health*` 请求都应失败并暴露 path。
|
||||
|
||||
通过 `hwlab nodes web-probe run|script` 在线上 public origin 发现的 Workbench 用户可见 bug,修复前必须先进入上述 fake-server Playwright 套件形成独立红灯,再改源码。issue 正文应明确写出对应 fake-server 复现要求、fixture 来源、目标 viewport 或用户路径、修复后需要运行的 `bun run e2e:workbench -- --project=chromium`,以及最终回到同一 node/lane public origin 的 `web-probe` 验收命令。线上 web-probe 是 P4 原入口验收,不替代本地可重复的 Workbench 回归用例。
|
||||
|
||||
线上环境不易稳定触发或不应主动制造的负向分支,例如跨 project 详情读取、过期 session 权威、上游 5xx、auth rollout 瞬态和 list/window 缺项,应由 fake-server fixture 提供确定性复现和断言;live `web-probe` 关闭时证明同一 node/lane public origin 的部署版本、自然路径和健康状态即可,并在 closeout 中说明该负向分支的确定性覆盖来自 fake-server。不要为了证明 5xx、rollout 中间态或第三方瞬态而故意破坏线上服务。
|
||||
|
||||
移动端、窄屏、session rail、按钮可见性和 selector readiness 类问题必须在 Playwright viewport 中表达可见性断言:目标入口应可见、可点击、具有非零 layout rect,并且与用户实际操作路径一致。不要把桌面 selector(例如 session rail 的某个固定 id)假定为所有 viewport 的稳定 readiness;若移动端存在等价折叠菜单或替代按钮,fake-server 用例和线上 `web-probe script` 都应验证该等价入口。
|
||||
|
||||
fixture seed 优先来自目标 node/lane 的受控真实样本;采集脚本只能输出脱敏后的 workspace/conversation/session/turn/trace shape、stable pseudo ids、sourceRef/presence/fingerprint 和 `valuesPrinted=false`。不得提交或打印 `HWLAB_API_KEY`、cookie、Authorization header、DB DSN、provider token、真实用户身份或非公开 prompt。截图、Playwright trace 和 HTML report 是 issue/PR closeout 证据,默认保存在 `.state/workbench-e2e/` 或通过受控远程 artifact 回传;它们不替代 OA spec,也不替代真实 public runtime 的 `hwlab nodes web-probe` 登录/DOM/Trace smoke。
|
||||
Workbench 浏览器回归需求以 UniDesk OA [PJ2026-010401 Web工作台](../../project-management/PJ2026-01/specs/PJ2026-010401-web-workbench.md) 为权威;具体 Web 开发、fake-server Playwright、fixture 采集脱敏、移动端断言、截图 artifact 和线上 web-probe 闭环统一见 `$unidesk-webdev`。HWLAB repo 只保留入口边界:专项代码位于 `web/hwlab-cloud-web`,命令必须在 issue/CLI 选中的目标 node/lane workspace 或独立 worktree 上运行,不得在 master server 本地跑浏览器或仓库级前端 check。
|
||||
|
||||
### Web Live DOM Probe 验收
|
||||
|
||||
`scripts/web-live-dom-probe.mjs` 是 Cloud Web 原入口的 DOM 级等价验收 helper。它必须在 issue/CLI 选中的 node/lane workspace 上运行,并打到同一 public origin;例如 D601 `v0.3` 使用目标 workspace 的脚本和 `https://hwlab.pikapython.com`,不能在 master server 本地跑浏览器 smoke,也不能用旧端口或其他 lane fallback。跨 node/lane 的日常指挥验收优先使用 UniDesk `bun scripts/cli.ts hwlab nodes web-probe run --node <node> --lane <lane>`,由该入口解析 workspace、public origin 和 Web 登录 sourceRef,再把凭据作为一次性 stdin/env 注入目标 helper。需要自定义 Playwright route/intercept、延迟 API、读取 in-flight DOM 或生成专项 artifact 时,使用 `bun scripts/cli.ts hwlab nodes web-probe script --node <node> --lane <lane> <<'JS' ... JS`;该入口由 UniDesk 先通过同源 `/auth/login` 建立 `hwlab_session`,脚本只接收已认证的 `browser/context/page/baseUrl` 和 artifact helper。只修改该 helper 时属于无服务交付,按目标 HWLAB repo `AGENTS.md` 选择直接提交或 PR,关闭证据写明 `rollout=not-applicable`。
|
||||
|
||||
`web-probe script` 注入的 `baseUrl` 是 public origin,并且可以带尾随 `/`。自定义脚本构造 API 或页面 URL 时必须使用 `new URL(path, baseUrl).toString()`;不要用 `` `${baseUrl}${path}` `` 直接拼接以 `/` 开头的 path,否则会生成 `//health`、`//v1/...` 这类双斜杠路径,可能被 edge-proxy 当成上游绝对 URL/异常代理路径处理,造成与真实浏览器页面不同的 502 或误判。
|
||||
|
||||
`web-probe script` 的 `fetchJson` 依赖已认证页面所在 origin。自定义脚本必须先通过 `waitWorkbenchReady`、`gotoStable` 或等价页面导航进入目标 public origin,再调用 `fetchJson` 读取 `/v1/...`;不要在 `about:blank` 上先发 API 请求,否则 status 0 只说明浏览器上下文尚未进入同源页面。Workbench 页面存在长连接、轮询或 SSE 时,不要用 Playwright `networkidle` 作为 reload/切换通过条件;应使用 `domcontentloaded` 加明确 DOM/API 条件,例如 final URL、route conversationId、active tab、message card、trace row 或 workspace `selectedConversationId`。
|
||||
|
||||
Workbench 历史会话 deep link 可能属于非默认 project。打开 `/workbench/sessions/<conversationId>` 时如果默认 project 返回 `conversation_project_mismatch`、页面提示 conversation 不可见,不能立即判定原 issue 失效;应先从 workspace/conversation 摘要确认该会话 projectId,再用等价 URL `/workbench/sessions/<conversationId>?projectId=<projectId>` 做 DOM 断言。closeout 证据应写明实际 projectId、finalUrl、terminal agent card 数量和负向文本断言,避免用默认 project 的 404 掩盖真实页面状态。
|
||||
|
||||
Web 登录凭据必须从目标 node/lane 的受控 source 解析并作为一次性进程环境注入,例如先用 `bun scripts/cli.ts hwlab nodes secret status|ensure --node <node> --lane <lane> --name hwlab-v03-bootstrap-admin` 确认 bootstrap admin sourceRef,再运行受控 `hwlab nodes web-probe run` / `hwlab nodes web-probe script`。目标 host 没有 owner-only source 文件时,受控入口应快速返回 `web_login_secret_missing`;不要依赖脚本历史默认密码,不要把凭据复制到目标 host、shell 启动文件、issue、日志或 Git 文档。若 sourceRef/fingerprint 已确认但 public `/auth/login` 仍不接受 source 密码,应先区分 API rollout、user-billing 回退和用户表状态;只有明确需要按 YAML source 重灌 bootstrap admin hash 时,才使用受控 `secret ensure --confirm --force`。
|
||||
|
||||
排查 probe 登录误报时,优先看 JSON 里的 `actions`、`dom.authState`、`finalUrl`、`failureDom` 和 `dom.requiredSelectors`。新版登录页 fallback 必须先等待真实登录 surface(`#workspace`、legacy id 或 `.login-card input`)再判断 input count;提交前还要确认表单值已经落到 DOM,例如 `actions.login.valuesReady=true`。只在 `authState=login` 的瞬间立即 `count()`,或在 Vue 尚未更新 input value 时 submit,都可能把前端填表时序误判成凭据错误。关闭 Workbench 登录/DOM helper 问题时,证据至少包含原命令、目标 URL/lane、登录 `selectorMode`、`valuesReady`、`finalUrl` 和 `workspace`/`commandInput` 等关键 selector 结果。
|
||||
|
||||
Trace 实时性问题必须使用间隔采样,而不是只看静态截图或终态 DOM。`hwlab nodes web-probe run` 可用 `--trace-sample-count` 和 `--trace-sample-interval-ms` 采集运行中样本;自定义场景使用 `hwlab nodes web-probe script` 在同一 public origin 上读取 `.message-card[data-role="agent"]`、`.trace-timeline`、`.trace-render-row`、`data-status` 和 `.trace-empty`。采样判断要区分“加载中”和“思考中”:加载中表示页面仍在拉取已有 trace 或 trace 资源未就绪;思考中表示 trace 容器已挂载、turn 正在运行,但还没有第一条可读 Code Agent 事件。终态 message card(completed/failed/blocked/timeout/canceled)不得继续保留“思考中”空态;若 full trace 为空,应显示与终态一致的空 trace 文案,并且该 article 的可读 `textContent` 不应包含“思考中”。通过证据应包含连续样本里的 `agentStatus`、`tracePresent`、`traceStatus`、`rowCount`、`emptyLabel` 和最后一行预览;终态空 trace 类 issue 还应统计 terminal agent card、terminalWithThinking 和 terminal trace-empty label。
|
||||
|
||||
浏览器控制台中的随机文件名脚本、扩展注入脚本或浏览器实验功能警告不得直接归因到 HWLAB Cloud Web。遇到 `Permissions policy violation`、`unload is not allowed` 或类似 console 噪声时,先用 `hwlab nodes web-probe script` 在干净 Playwright 上记录 `document.scripts`、同源响应 header 和相关 console 过滤结果;只有脚本实际来自 HWLAB public origin、部署产物或响应 header 明确由 HWLAB 设置时,才把它登记为 HWLAB Web bug。Edge/Copilot、浏览器扩展或用户侧注入脚本产生的随机 bundle 名称,应作为浏览器环境噪声记录,不阻塞已通过的 Web 功能验收。
|
||||
`scripts/web-live-dom-probe.mjs` 和 UniDesk `hwlab nodes web-probe run|script` 是 Cloud Web 原入口 DOM 验收底座。登录 sourceRef、同源 page helper、URL 构造、readiness、Trace 采样、浏览器噪声分类和 artifact 规则统一见 `$unidesk-webdev`;本文件不复制使用细则,避免与 UniDesk WebDev 操作面分叉。只修改该 helper 时属于无服务交付,按目标 HWLAB repo `AGENTS.md` 选择直接提交或 PR,关闭证据写明 `rollout=not-applicable`。
|
||||
|
||||
### Cloud Web Workbench Prompt 浏览器闭环
|
||||
|
||||
Workbench prompt、TraceTimeline、final response、详情弹窗或工具调用展示类 issue 关闭前,必须同时有浏览器 UI 证据和同一 trace 的 typed CLI 交叉验证。浏览器侧优先使用 `trans <node>:<workspace> playwright --local-dir <local-dir>` 在选中 node/lane workspace 执行,并打到同一 public origin;不要在 master server 本地跑浏览器,也不要用其他 lane 的旧端口代替。heredoc 内应显式等待 `/auth/login`、`#workspace`、`#code-agent-provider-profile`、session 选择、`/v1/agent/chat` 和目标 trace selector,而不是只靠页面标题或宽泛 input count 判断成功。截图、PDF 或 summary artifact 必须通过 `--local-dir` 或 `trans <node> download` 回传,并在 closeout 中记录本地路径、bytes 和 SHA-256 verification。
|
||||
|
||||
一次完整的 Workbench prompt UI 证据应覆盖:Web session 登录成功;模型通道选择符合目标 provider profile;显式创建或选择 session;prompt 被 `/v1/agent/chat` 接受并得到 `traceId/sessionId/conversationId/threadId`;页面可见用户消息、Agent message、final response;若 TraceTimeline 初始是 compact/result 压缩态,应在 Web 上触发 `回放 Trace` 后展开 timeline,让页面本身可见 `commandExecution` 等工具行。随后在同一 node/lane public origin 上,用 `hwlab-cli client agent result <traceId>`、`trace <traceId>` 和必要的 `inspect <traceId>` 交叉确认 terminal status、toolCalls、finalResponse、AgentRun run/command/runner ID 和脱敏状态。
|
||||
|
||||
对于失败终态的 final response UI 验收,浏览器证据必须读取 final response 正文或 `.message-text` 中的用户可见错误,并与同一 trace 的 `client agent result` / turn endpoint 的 `finalResponse.text` 对齐。若 API 已返回 `error.message` 但没有 `finalResponse.text`,问题在 HWLAB API/adapter 结果映射;若 API 已返回 `finalResponse.text` 但页面仍显示空 final、通用 fallback 或只在 trace row 中展示错误,问题在 Cloud Web 恢复/terminal 文本选择。两类问题都不能用 trace timeline 展示正常来关闭。
|
||||
|
||||
详情弹窗和恢复会话类验收还应覆盖“从持久化 conversation 恢复”的路径,而不是只在刚完成 turn 的内存态截图。若用户报告的原始 conversation 对当前验收 actor 不可见,但同一 trace 的 `result` 可读,可以创建当前 actor 可见的临时 conversation,消息中挂载同一个真实 `traceId` 和最小 terminal agent message,再在 Web 中选择该临时会话、打开运行详情并等待 result 诊断自动补齐;验收后删除临时 conversation。closeout 必须写明这是同 trace 的恢复路径验证,不能声称修改或读取了原始用户 conversation。
|
||||
|
||||
Completed turn、Trace 重放或 session deep link 类 issue 关闭前,必须用新的浏览器上下文或等价 fresh login 直接打开 `/workbench/sessions/<conversationId>?projectId=<projectId>`。同一 SPA 页面内发送后再 `reload` 只能证明当前内存态和同页缓存没有立即丢失,不能替代 fresh deep link 复测;fresh deep link 必须重新通过 conversation detail、turn/trace replay 或等价事件重放恢复用户消息、terminal agent message、Trace rows、active tab 和 `running=false` 终态。若同页 reload 正常但 fresh deep link 下 `/v1/agent/conversations/<conversationId>` 或 `/v1/agent/turns/<traceId>` 返回 404,且 DOM `messageCount=0` / `traceRowCount=0`,该 issue 仍未通过,必须保持打开或重开。
|
||||
|
||||
Session 切换、session rail 或 Workbench 恢复路径类问题必须同时验证点击态和持久化恢复态。浏览器证据应在同一 public origin 中选择一个非当前 session,等待足够覆盖 `hydrate`、`select-conversation`、active trace repair 等异步返回的空闲窗口,确认 active tab 没有回退;随后读取 `/v1/workbench/workspace?projectId=<projectId>` 确认后端 `selectedConversationId` 已改变并持久化;最后刷新页面并再次等待 session tabs,确认同一个 session 仍是 active。若当前 selected conversation 没有出现在 `/v1/agent/conversations` 当前列表窗口中,前端必须把 workspace 当前选中 conversation 合入 session rail;刷新后没有 active tab、状态显示“等待 workspace”,或只靠内存态显示成功,均不能作为通过证据。session rail 的刷新列表只是候选窗口,不是 selected session 的完整真相;list API 临时缺当前 conversation 时,不得清空当前 tab、取消 active 状态或让标签在刷新/深链恢复中闪烁消失。自定义 Playwright 验收不要只按 tab index 或重复标题判断,应锁定唯一 title、conversationId 或后端 selected id,并记录 `select-conversation` response;与 session 切换无关的 health/RPC 噪声应拆成独立 issue,不阻塞已经通过的切换闭环。
|
||||
|
||||
线上 session rail 当前列表窗口可能只有空会话,或包含已经过期的 stale conversation。选择非空、running 或 terminal 会话作为验收候选时,应先通过 `/v1/agent/conversations?projectId=<projectId>&limit=<N>` 扩大候选范围,再对候选逐个读取 `/v1/agent/conversations/<conversationId>?projectId=<projectId>`;只有 detail 200 且消息/trace shape 满足目标场景的会话才可作为正向切换、reload 或 terminal replay 证据。detail 404 的候选本身是 stale/list-window 负向信号,应用于验证隔离路径,而不能继续当作正向 reload 样本。
|
||||
|
||||
Code Agent turn 运行状态的权威入口是 `/v1/agent/turns/:traceId`,`traceId` 是单一查询键;`hwlab-cli client agent result <traceId>`、Web composer、cancel 按钮、session 标签动效和最终消息状态都应消费同一 turn snapshot 的 `running`、`terminal`、`status`、`finalResponse`、`error` 和 AgentRun provenance。`/v1/agent/trace*`、conversation list、workspace summary、message status、runnerTrace rows 和 currentRequest 只能作为详情、列表或上下文来源,不能再反向推断 turn 是否运行中、是否完成或是否失败,也不能作为 fallback 与 turn endpoint 竞争覆盖 UI 状态。CLI 等待 terminal 时也应优先使用 submit 返回的 `turnUrl` 或 `/v1/agent/turns/:traceId`,只有详情展示才读取 trace rows。
|
||||
|
||||
Code Agent 会话恢复的状态权威必须以最新 message 和同 turn trace 为准。conversation 顶层 `status=idle` 只能表示当前没有进行中的 turn,不能覆盖 message 自身的 `running` / `completed` / `failed`,也不能把 agent message 降级成 `source`;conversation 顶层 `lastTraceId` 若与最新 user/agent message trace 脱节,后端 summary 应按最新同 turn user/agent trace 修正,前端 hydrate/select/retry 后也应从最新 active message reattach trace。关闭刷新、deep link 或切换 session 后丢消息/卡住类 issue 时,验收必须同时看 DOM 最后一条 agent 的 `data-status`、conversation API 顶层 `lastTraceId`、最后 user/agent message 的 `traceId`、`runnerTrace.status` 和 `/v1/agent/turns/:traceId` 的 `running` / `terminal`,不能只看 session rail 文案或 trace 面板是否出现占位文本。
|
||||
|
||||
Workbench session URL 是恢复路径的一部分。每个可见或当前选中的 session 都应能映射到 `/workbench/sessions/<conversationId>`,`/workspace/sessions/<conversationId>` 仅作为兼容 alias;从 `/workbench` 进入、创建 session 或点击 session rail 后,地址栏应反映当前 active `conversationId`,复制 session 信息时也应包含可直接打开的 session URL。直接打开 deep link 时,Cloud Web 静态层必须返回 SPA `index.html` 而不是 404;登录 redirect 必须保留原 path;登录后或 hydrate 后应通过 `/v1/agent/conversations/<conversationId>` 与 workspace select 路径把后端 `selectedConversationId` 收敛到 URL 中的 id。关闭 session URL/恢复类 issue 时,浏览器证据至少包含最终 URL、workspace API 的 `selectedConversationId`、active tab 判断,以及一次无 cookie direct GET 或等价探针确认 deep link 是 `200 text/html`。
|
||||
|
||||
Cloud Web 登录页的中文错误可能会把 API upstream 502、rollout 中间态或真实 401 都表现成登录失败。遇到登录失败先看 `web-probe script` 的 `probe.auth.retryCount`、`transientObserved`、`retryable`、`fallbackUsed`、`fingerprint` 和 `commanderAction`,再用目标 public origin probe `/health/live`、`/auth/login` 状态和选中 namespace 的 API/Web/edge-proxy rollout;只有 API 已 ready 且 `/auth/login` 明确返回 401 时,才把它归类为凭据或用户状态问题。rollout 瞬态恢复后重跑同一短生命周期 Playwright 验收即可,不要把 transient `upstream_unavailable` 写成长期功能缺陷。
|
||||
Workbench prompt、TraceTimeline、final response、详情弹窗、session 切换、deep link 和运行态一致性问题的浏览器证据要求统一见 `$unidesk-webdev`;typed CLI 交叉验证仍见 `$hwlab-code-agent`。这里不再复制 selector、fresh context、turn authority 或登录排障细则,避免与 WebDev 操作面产生多路径。
|
||||
|
||||
## HWLAB FRP 维护
|
||||
|
||||
|
||||
Reference in New Issue
Block a user