diff --git a/.agents/skills/unidesk-webdev/SKILL.md b/.agents/skills/unidesk-webdev/SKILL.md index 9d3ba6ab..8801c193 100644 --- a/.agents/skills/unidesk-webdev/SKILL.md +++ b/.agents/skills/unidesk-webdev/SKILL.md @@ -141,13 +141,16 @@ bun scripts/cli.ts web-probe observe analyze webobs-xxxx - `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 --sample-seq ` 是第二层 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 生成表格,避免 `trans` stdout 截断后 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|analyze` artifacts 为准。 +- Web 哨兵 public dashboard/origin 必须以 issue/SPEC/YAML 既定计划为准;当前 P6 计划沿用 `monitor.pikapython.com`,不要未经明确变更改成 `hwlab-monitor.pikapython.com` 或其他新域名。验证 report 时记录 `publicOrigin`,但不要把域名硬编码到 runner/analyzer 逻辑里。 - `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 分位表和超过 YAML `webProbe.alertThresholds` budget 的慢路径 finding;项目管理页还必须输出 DOM readiness、source/file/task 计数、缺失 public task ref、Workbench launch success/failure、captured OTel trace header、自然 project-management API 分组和超过 YAML `webProbe.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` 仍运行在 UniDesk `trans` 60s 最外层短连接约束内;能在一轮内完成的 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 行为失败。 diff --git a/docs/reference/observability.md b/docs/reference/observability.md index 8da12276..0de197b1 100644 --- a/docs/reference/observability.md +++ b/docs/reference/observability.md @@ -21,6 +21,8 @@ UniDesk 的可观测性优先级高于静默成功。CLI、服务日志、Docker 每次发现隐式 fallback,都应优先修上游 source of truth:先定位第一个吞错点,删除吞错 fallback,补 OTel/error 透传,再复测原入口。只有确认上游事实已经正确产生后,才允许清理前端展示或 CLI 表格。不得通过增加更多采样器判断、前端兜底字段或 analyzer 自动仲裁来“修好”业务结果。 +Web/Workbench trace、Web 哨兵和 `web-probe observe` 的人工判定入口以 `$unidesk-webdev` 为准:先用采样器保存的 artifact 渲染 `turn-summary` 和 `trace-frame` CLI 视图,再解释 analyzer finding。自动判别器、聚合计数或额外截图保存源不能压过同一采样帧的 CLI trace 视图;若二者冲突,应登记 analyzer/tooling 精度问题或上游投影问题,而不是用 fallback 视图修业务结论。 + ## CLI Logs 异步 job 的 stdout 和 stderr 位于 `.state/jobs/`。`job list` 默认只返回最新 50 条摘要,并为已知异步工作流返回轻量 `progress.summary`;`job status` 会返回结构化 `progress` 与有限尾部,避免输出爆炸,同时保留完整日志文件路径便于继续排查。实现必须只读取日志尾部字节,不得先把完整 job 日志读入 CLI 内存;长时命令的阶段、关键对象名和下一步查询命令应优先沉淀到 `progress`,不能要求调用者先阅读完整日志才能知道是否卡在提交、构建、发布或观测阶段。