docs: add unidesk webdev skill
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
---
|
||||
name: unidesk-webdev
|
||||
description: 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`;本技能只规定如何开发、采集、复现和验收。
|
||||
|
||||
## 核心原则
|
||||
|
||||
- 单一权威入口:先按 issue/CLI 明确的 node + lane 解析 workspace、public origin、namespace、sourceRef 和目标分支。没有明确目标时才读取受控 YAML;不得把 D601、G14、v0.2、v0.3、旧端口或本地 dev server 写成隐藏默认。
|
||||
- 无多路径、无 fallback:这是本技能的核心原则。Web、CLI、fake-server 和线上 web-probe 必须复用同一套 API 契约、同一 route/session/conversation/trace authority 和同一状态投影;不得为了让测试通过增加第二套 dispatcher、localStorage 真相、workspace snapshot 真相、内部 manager 调用、旧 lane 端口、raw request、临时兼容路径或“测试专用后门”。
|
||||
- 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 用例负责可重复红灯和源码回归;线上 `hwlab nodes 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。
|
||||
|
||||
## 工作流
|
||||
|
||||
1. 定位目标:确认 repo、node、lane、workspace、public origin 和目标 SPEC。HWLAB D601 v0.3 例子是 `/home/ubuntu/workspace/hwlab-v03` + `https://hwlab.pikapython.com`,但只能在 issue/CLI 指向该目标时使用。
|
||||
2. 读规则:进入目标 workspace 前读取目标 `AGENTS.md`;涉及规格或测试设计时读取 UniDesk OA 对应 SPEC。
|
||||
3. 线上复现:用 `hwlab nodes web-probe run|script` 在目标 public origin 复现用户现象,保存 `scriptSha256`、`runDir`、截图名、截图 SHA、URL、DOM/API 摘要。
|
||||
4. 建红灯:修 Workbench/Performance 用户可见 bug 前,在目标 HWLAB workspace 的 `web/hwlab-cloud-web` fake-server Playwright 套件中补确定性用例;fixture 从真实采集样本脱敏产生。
|
||||
5. 修源码:保持状态读写单一路径。状态投影类修复优先收敛 server-state/reducer/projection,不在 UI 组件、trace polling、result polling 或 localStorage 中新增竞争事实。
|
||||
6. 验证:先跑 fake-server Playwright 目标用例,再回到同一 node/lane public origin 用 web-probe 复测;截图和报告作为证据回传,不进入源码仓库。
|
||||
7. 写 issue/closeout:问题登记和收口必须写明目标合并分支、node/lane、fixture 来源、Playwright fake-server 用例、线上 web-probe 命令/脚本 SHA、截图 SHA 和剩余边界。
|
||||
|
||||
## HWLAB Web Probe
|
||||
|
||||
线上 Cloud Web DOM 验收优先使用受控入口:
|
||||
|
||||
```bash
|
||||
bun scripts/cli.ts hwlab nodes web-probe run --node D601 --lane v03
|
||||
```
|
||||
|
||||
需要 Playwright route/intercept、延迟 API、读取 in-flight DOM 或截图时使用:
|
||||
|
||||
```bash
|
||||
bun scripts/cli.ts hwlab nodes web-probe script --node D601 --lane v03 <<'JS'
|
||||
export default async ({ page, gotoStable, screenshot, fetchJson, safeEvaluate }) => {
|
||||
await page.route('**/v1/agent/conversations**', route => setTimeout(() => route.continue(), 1000));
|
||||
await gotoStable('/workbench');
|
||||
return {
|
||||
url: page.url(),
|
||||
workspace: await fetchJson('/v1/workbench/workspace?projectId=prj_hwpod_workbench'),
|
||||
screenshot: await screenshot('workbench.png')
|
||||
};
|
||||
};
|
||||
JS
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- web-probe 由 UniDesk CLI 从 YAML 声明的 bootstrap admin sourceRef 读取凭据并建立同源 `hwlab_session`;脚本不得自行读取、打印或复制 Web 登录凭据、cookie、token 或完整 API key。
|
||||
- 脚本构造 URL 时使用 `new URL(path, baseUrl).toString()`;不要拼出 `//v1/...`。
|
||||
- 先通过 `gotoStable`、`waitWorkbenchReady` 或等价导航进入目标 origin,再用 `fetchJson` 读同源 API;不要在 `about:blank` 上请求 `/v1/...`。
|
||||
- Workbench 有 SSE/长轮询时不要用 `networkidle` 判断通过;用明确 DOM/API 条件,如 final URL、route conversationId、active tab、message card、trace row 或 workspace `selectedConversationId`。
|
||||
- Playwright `page.evaluate` 只能传一个可序列化参数;多个值包成对象,或用 `safeEvaluate(fn, { a, b })`。
|
||||
- 失败证据至少保留 `failureKind`、`errorMessage`、`scriptSha256`、`runDir`、`lastUrl`、`lastScreenshot`;默认失败截图是 `failure.png`。
|
||||
|
||||
## Fake-Server Playwright
|
||||
|
||||
Workbench 回归入口在目标 HWLAB repo 的 `web/hwlab-cloud-web`:
|
||||
|
||||
```bash
|
||||
bun run e2e:workbench -- --project=chromium
|
||||
```
|
||||
|
||||
运行面要求:
|
||||
|
||||
- 在 issue/CLI 选中的 node/lane workspace 或其独立 worktree 上运行,不在 master server 本地运行。
|
||||
- 同源 fake-server 只提供正式 API 契约,覆盖 `/auth/*`、workspace、conversation list/detail、turn snapshot、trace event page、Workbench event stream、Performance summary 等当前用例所需端点。
|
||||
- 测试断言优先使用用户可见文本、ARIA role 和稳定 DOM 标识;不要通过内部 store、localStorage、数据库或 live API 直接判定通过。
|
||||
- 失败必须保留截图、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` 一致性;
|
||||
- Trace 阅读按事件顺序渲染可读 row,正确处理分页、终态、失败、自动展开和终态折叠;
|
||||
- deep link 与普通点击 session 走同一 authority path;
|
||||
- Performance 页的摘要、错误态、刷新、移动端表格可达性和低基数脱敏展示。
|
||||
|
||||
## Fixture 采集与脱敏
|
||||
|
||||
- 采集范围至少包括 workspace selection、conversation list、conversation detail、session/turn snapshot、trace event page、Workbench event stream 和 Web performance summary。
|
||||
- 产物必须记录 `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 判定口径
|
||||
|
||||
- Session rail 会话集合只消费 `/v1/agent/conversations`;当前 conversation 消息本体只消费 `/v1/agent/conversations/{conversationId}`;turn 状态只消费 `/v1/agent/turns/{traceId}`;trace 阅读只消费 trace event page/result snapshot。不要让 workspace snapshot、列表摘要、localStorage、trace polling 或 result polling 互相覆盖。
|
||||
- UI transient state 只保存 route、显式选择、composer draft、scroll、展开状态和临时交互状态;服务端事实进入 server-state/reducer/projection。
|
||||
- running turn 必须同时反映在主任务区、composer 主按钮、session tab 和可取消入口;清空、切换、刷新不得把 running trace 隐藏成空态。
|
||||
- terminal failure、blocked、canceled 都是最终结果;若 API 返回可读 error/blocker,final response 展示区必须直接显示,不能只放在 trace rows 或详情面板中。
|
||||
- session 切换验收必须覆盖点击态和持久化恢复态:选择目标 session、确认 workspace `selectedConversationId` 持久化、刷新后同一 session 仍 active。
|
||||
- completed turn / Trace 重放 / deep link 验收必须用 fresh browser context 或等价 fresh login 直接打开 `/workbench/sessions/<conversationId>?projectId=<projectId>`,不能只用同页 reload。
|
||||
- Trace 实时性要用间隔采样,区分“加载中”和“思考中”;终态卡片不得继续保留“思考中”空态。
|
||||
|
||||
## 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,按锁文件和目标执行面补依赖后继续。
|
||||
|
||||
## 跨 Host Playwright
|
||||
|
||||
非 HWLAB 或确实需要把截图/PDF 自动回传到本机时,使用 `trans <route> playwright`:
|
||||
|
||||
```bash
|
||||
trans D601 playwright --local-dir /tmp <<'PW'
|
||||
playwright-cli screenshot https://example.com "$UNIDESK_PLAYWRIGHT_SCREENSHOT" --full-page
|
||||
PW
|
||||
```
|
||||
|
||||
多步交互必须写在同一个 heredoc,并显式等待关键 HTTP response 和稳定 selector。该入口只负责短生命周期浏览器执行和 artifact 回传,不提供长驻 browser daemon;HWLAB node/lane Cloud Web 验收仍优先使用 `hwlab nodes web-probe script`。
|
||||
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "UniDesk WebDev"
|
||||
short_description: "UniDesk Web 开发、Playwright 与 web-probe 验证"
|
||||
default_prompt: "Use $unidesk-webdev to validate a node/lane Web bug with Playwright and same-path fake-server coverage."
|
||||
Reference in New Issue
Block a user