# HWLAB Cloud Workbench Reference

Cloud Workbench is the default user-facing frontend at
`http://74.48.78.17:17666/`. It must serve the #99 workbench direction and the
#108 UX constraints while respecting the M3 boundary from
`DC-DCSN-P0-2026-003`.

## Default Route

- `/` must show the Cloud Workbench, not Gate, status, help, or diagnostics.
- The default first screen must not show Gate, `BLOCKED`, `M0-M5`, or
  acceptance-review copy. Those terms may remain in hidden/internal views.
- Checked-in Gate reports and aggregator summaries are read-only support data.
  They must not be rendered as the default homepage or used to rename the
  default route away from Cloud Workbench.
- Gate and diagnostics are secondary routes or right-panel support views.
- `/gate` and `/diagnostics/gate` are internal diagnostic aliases served by the
  same Cloud Web app router. They may carry Gate, blocker, and M0-M5 evidence
  because they are not the default homepage.
- `http://74.48.78.17:17667/` remains the API/edge boundary.
- Browser data sources are same-origin `/v1`, read-only `/json-rpc`, source
  reports, gate reports, and blocked reports.
- Code Agent conversation 使用受控同源 `POST /v1/agent/chat` 通道。直接
  API/edge 访问、source reports、本地 echo、mock replies 或 provider
  credential gaps 不能被写成真实 assistant reply；readiness 权威文档是
  [code-agent-chat-readiness.md](code-agent-chat-readiness.md).
- Cloud Web 的 Code Agent 非视觉业务路径必须能被 `hwlab-cli client agent`
  复现。Web 发现 AgentRun、session continuation、trace/result 或 provider
  问题时，先用 CLI 通过同一 Cloud Web base URL、同一 `/v1/agent/chat`、同一
  显式 `conversationId/sessionId/threadId/retryOf` 复现，再进入前端状态机或样式修复。
  Code Agent session 管理必须手动化：无 session 时先显式创建 session，session failed/stale
  时保留失败证据并要求显式新建或选择 session；不能用只覆盖首轮自动新会话的 CLI 验收
  替代 Web continuation 验收。

## Required Layout

The default workbench follows the #99 VS Code-style structure:

| Region | Required role |
| --- | --- |
| Left | Activity rail, project/function/resource navigation, hardware resources. |
| Center top | Agent messages, execution process, trace, selected operation context. |
| Center bottom | Agent input or equivalent command composer. |
| Right top | BOX-SIMU, Gateway-SIMU, and patch-panel hardware state. |
| Right bottom | Controls, wiring, trusted records, Audit, and Diagnostics tabs. |

Unavailable or future controls must be disabled with blocker context. The
frontend must not imply generic direct hardware control.

The center-bottom command composer is the primary user action surface. Topbar
runtime summaries, live-build indicators, dialogs, and status chips may report
context, but they must never cover or intercept clicks intended for the command
composer, Code Agent input, send controls, or quick-prompt buttons. If a fixed
or visually persistent status surface can overlap after `scrollIntoView`, mobile
reflow, or trace updates, the command composer must keep quick prompts inside
its own flow below the primary input controls, and non-interactive summary text
must not become a pointer target. Layout/browser smoke should treat this as a
real hit-target failure, not as a test flake.

The left resource explorer is a controlled resizable column on desktop-class
viewports. Its width defaults to `292px`, clamps inside a bounded range
(`220px` to `420px` before viewport-specific clamping), and is changed through
the `#explorer-resize` separator. The separator has a Chinese accessible name,
supports pointer drag plus Arrow/Page/Home/End keyboard adjustment, and stores
only the clamped width in versioned `localStorage` key
`hwlab.workbench.layout.v1`. Collapsing the resource tree hides the column but
keeps the saved width so expanding restores it. At `<=860px`, the resize handle
is removed from the focus/hit-target flow and the mobile drawer/collapse flow
owns the layout.

The `panel-wiring` / `hwlab-patch-panel` view must use a two-column long table
instead of an eight-column wide table. The first table row/header names the two
connected devices, for example `res_boxsimu_1` and `res_boxsimu_2`; following
rows map IO ports, for example `DO1` to `DI1`. The patch-panel service,
status, evidence source, and trace/evidence details remain visible in Chinese
summary or row detail text, but they must not become separate horizontal
columns that force the right sidebar to scroll sideways.

## UX Constraints

The #108 constraints are current baseline:

- no page-level vertical scroll on the outer shell; scrolling belongs inside
  workbench panels;
- user-visible UI text is Chinese except machine identifiers, protocol names,
  API paths, IDs, commits, endpoints, and source labels that need their exact
  spelling;
- an internal help page exists, but it is not the homepage;
- help content is maintained as `web/hwlab-cloud-web/help.md` and rendered by
  the frontend instead of being only a JS string.

## Evidence And Labels

Visible runtime or evidence state must keep `SOURCE`, `LOCAL`, `DRY-RUN`,
`DEV-LIVE`, and `BLOCKED` distinct. Loading the page from `17666` proves only
that Cloud Web is reachable. It does not prove DB readiness, M3, M4, M5, or a
hardware loop.

The frontend may show read-only DEV observations when they are tied to the
exact route or component. It must not upgrade source fixtures, dry-run output,
front-end state, or edge-only health into M3 DEV-LIVE.

The default workbench runtime label must not expose raw `degraded` as the
user-facing conclusion. `live-status` maps current probes into four Chinese
states:

| State | Visible label | Required attribution |
| --- | --- | --- |
| Pass | `API 正常` | The exact service and API that proved readiness, normally `hwlab-cloud-api /health/live`. |
| Error | `API 错误` | Concrete service/API/reason, for example `hwlab-cloud-api /v1/agent/chat provider_http_504` or `hwlab-patch-panel /v1/m3/io m3_wiring_missing`. |
| Unverified | `等待验证` | The service/API still waiting for observation; it must not be treated as pass. |
| Read-only | `只读模式` | Explicit permission, fallback, DB persistence, or runtime durable reason, for example `runtime_durable_adapter_schema_blocked`, `runtime_durable_false`, or `fallback_text_chat_only`. |

Raw `degraded` may be retained in internal details, reports, and `/gate`, but
the main workbench status must translate it into one of these actionable
states. Real `/v1/agent/chat` failures, provider timeouts, text-chat-only
fallback, runner blockers, and M3 `cloud-api -> gateway-simu -> box-simu ->
hwlab-patch-panel` failures must name the responsible microservice/API and the
error category. When the response carries trace, operation, audit, evidence, or
session identifiers, the visible detail must include a short redacted
`trace=`/`evidence=` style summary.

如果 `/v1/agent/chat` 返回 `provider_unavailable` 或报告缺少
`OPENAI_API_KEY`，可见状态必须保持 `BLOCKED/credential`。在同源 DEV 请求按
[Code Agent readiness](code-agent-chat-readiness.md) 合同返回 completed
且非空的 assistant response 前，Workbench 不得暗示已有真实 assistant reply。

Code Agent trace 在消息卡片内使用独立滚动容器展示。SSE、轮询或“回放 trace”
更新只能刷新内容，不得重置用户已展开/折叠状态，也不得把 `#conversation-list`
或 `.message-trace-events` 的滚动位置跳回顶部；渲染前后必须保存并恢复外层
conversation list 和按 `messageId/traceId` 记录的 trace list
`scrollTop/scrollLeft`。`#conversation-list` 需要绑定 scroll listener 持续记录用户
位置，并在 DOM 替换后立即恢复一次、下一帧再恢复一次，避免布局重算或 scroll
anchoring 把列表拉回顶部。

Trace 展示遵循 UniDesk commander loop 的低噪声完整可读事件线原则：原始 trace
JSON 仍是复制/下载和追责的完整来源；页面内默认展示每个有意义的 agent message、
command/tool completed、stderr/error、turn/status 和 gateway JSON-RPC 结果。token
delta、assistant chunk、command output chunk、reasoning delta 等噪声可以聚合或隐藏，
但聚合不得吞掉中间的可读 message/tool call。命令和工具行必须至少保留状态、exit
code、耗时、输出体量、关键 operation/evidence id 和可读摘要。

Workbench 面向用户的 trace 视图不得展示“压缩窗口”作为可读事件列表，也不得把
result polling 返回的 head-tail 窗口或少量摘要冒充完整 trace。只要发现
`eventsCompacted=true`，前端必须自动请求 `/v1/agent/chat/trace/<traceId>` 回放完整
trace；回放期间只能显示“完整 trace 回放中/当前已载入”状态，回放完成后才显示
“显示全部可读事件”。如果完整 trace 已过期或后端缺失，必须显式展示缺失状态。
assistant chunk、token delta、command output chunk 可以在同一 message/tool output 内
合并成一条高可读行，但不能隐藏任意 assistant message、tool call、tool completed、
stderr/error 或 turn/status 边界。

Code Agent 工作台状态必须跨浏览器刷新持久化。前端至少保存
`conversationId/sessionId/threadId/sessionStatus`、最近消息、traceId 和必要的 runtime
摘要，刷新或重新打开页面后继续使用同一 HWLAB session/thread 和 AgentRun `SessionRef`/PVC
workspace；除非运行面无法恢复或用户显式清空对话或登出，不得把下一轮
请求降级成“首轮新会话”。登录态采用 server cookie 与本地 session 双轨：server session
可用时优先使用；server 内存 session 因 Pod/replica 切换丢失时，只要本地 session 未过期，
刷新页面不得要求用户重新登录。

当后端使用 AgentRun v0.1 短连接 runner 时，Web 必须把当前 conversation 的 `threadId` 作为
唯一会话连续性字段提交；HWLAB adapter 必须把它写入 AgentRun command `payload.threadId`
和 `SessionRef.threadId`，runner 只按该标准字段执行 Codex app-server `thread/resume`。resume 失败
必须作为标准 `threadId` 路径上的结构化错误/trace 事件暴露。

恢复出的历史消息如果携带 `traceId`，前端必须先对 `/v1/agent/chat/result/<traceId>` 做
终态归一，再回放 `/trace`。旧的 `running` 消息不能只因为 localStorage restore 被降级成
`source` 后停留在“处理中”文本；如果后端 result 已经完成，消息卡片必须替换为真实
reply/blocker/session/providerTrace。如果 trace 只显示 `result:*` 终态事件而消息仍未完成，
也必须立即查 result，而不是把 `Code Agent result is ready for short-connection polling.` 当成
最终回复或让用户手工重试。

Cloud Workbench 的 Code Agent 单元测试不得依赖真实 token、真实公网 provider 或真实硬件。
前端状态机测试应使用固定 fixture/mock fetch 覆盖 submit accepted、result completed、result
failed、session busy、partial timeout、trace compacted、SSE 断流和页面恢复；后端测试应使用
fake Codex app-server client 覆盖长耗时和缺失 `turn/completed`。真实 DEV `--live` smoke 只用于
发布后读写边界明确的验收，不作为 PR 默认回归测试。

## Lightweight Checks

Use the existing lightweight checks unless a task explicitly authorizes a
heavier browser run:

```sh
node web/hwlab-cloud-web/scripts/check.mjs
node web/hwlab-cloud-web/scripts/build.mjs
node scripts/dev-cloud-workbench-smoke.mjs --static
node scripts/dev-cloud-workbench-layout-smoke.mjs --static
node scripts/dev-cloud-workbench-smoke.mjs --dom-only --url http://74.48.78.17:17666/
```

`npm run web:check` 是 Cloud Workbench 的 repo-owned 前端检查入口。它会
运行源码合同、移动视口 smoke、本地 Code Agent fixture，以及 #273
SOURCE/static layout smoke；默认不访问公网 DEV，不部署、不重启服务，也不调用
M3 IO。

默认 `web:check` 只把当前工作台主路径、Code Agent/trace/quick-prompt、布局命中和
安全边界作为阻断检查。历史 auth fixture、演示 fixture 或与当前改动无关的浏览器
> **门禁最小化见 AGENTS.md P0** — 以下检查为一次性验证入口，非长期保留门禁。

默认 `web:check` 只把当前工作台主路径、Code Agent/trace/quick-prompt、布局命中和
安全边界作为阻断检查。历史 auth fixture、演示 fixture 或与当前改动无关的浏览器
journey 可以继续产出诊断报告，但不得因为 Playwright `scrollIntoView` 与固定命令栏、
顶部状态摘要等布局细节耦合而阻塞 G14 CI/CD。需要恢复为阻断检查时，必须先证明该
fixture 代表真实用户入口问题，而不是旧检查假设。

The static smoke checks both sides of the route contract: `/` remains the
user-facing workbench, while `/gate` and `/diagnostics/gate` remain available
for internal diagnostics. This PR-class check is intentionally source-only and
does not deploy, restart services, call public DEV, or run the full live Code
Agent browser journey.

Live checks against `http://74.48.78.17:17666/` are read-only and must report
blocked/skip instead of false green when the browser or network path is not
available.

`--dom-only` keeps the runtime and web-asset identity preflight checks, then
continues with read-only DOM/help validation for the deployed workbench even
when identity drift blocks the full journey. It never sends `POST
/v1/agent/chat`; the Code Agent journey is recorded as `not_applicable` and
must not be used as a DEV-LIVE reply, Secret, mutation, or M3/M4/M5 acceptance
claim.

## Layout Smoke

`scripts/dev-cloud-workbench-layout-smoke.mjs` 是 #273 前端布局/遮挡护栏的
runner 入口。它使用 Playwright 覆盖 `1366x768`、`1024x768` 和 `390x844`
三档视口，检查 M3 控制区、Code Agent 输入区、右侧硬件/可信记录容器、当前
`/gate` 内部页、外层滚动锁和内部面板滚动。命中测试使用真实 Playwright
点击与 `document.elementsFromPoint()`；不得使用 `force: true` 或纯 DOM
dispatch 绕过用户命中。

Layout smoke also covers #278 resize behavior. Desktop and narrow desktop runs
drag `#explorer-resize`, exercise Arrow/Home/End keyboard changes, assert
min/max/clamp and versioned storage restore, then collapse and expand the
resource tree to prove width state is retained. The mobile run asserts the
handle is not displayed or focusable and that no horizontal overflow appears.

常用命令：

```sh
npm run web:check
npm run web:layout
npm run web:layout:build
npm run web:layout:live
```

三种模式分工：

| Mode | Command | When |
| --- | --- | --- |
| SOURCE/static | `npm run web:check` 或 `npm run web:layout` | PR/source gate 默认运行，不依赖公网 DEV。 |
| local-build | `npm run web:layout:build` | Cloud Web build/publish 前运行；会先刷新本地 `dist`。 |
| DEV live | `npm run web:layout:live` | DEV deploy 后对 `http://74.48.78.17:17666/` 运行，只证明 UI layout/clickability。 |

报告字段必须能定位 `status=pass|blocked|skip`、`viewport`、`selector`、
`failureType` 和 artifact 路径。当前允许的 `failureType` 包括 `overlap`、
`covered-hit-target`、`overflow`、`outer-scroll-regression`、`screenshot-diff`
以及未上线覆盖项的 `skip`。脚本会保存右侧面板、M3 控制表单、Code Agent
输入区和 `/gate` 当前页局部截图，但不做整页像素 diff 门禁。

默认 `web:check` 失败时会把完整 JSON 报告写入
`tmp/dev-cloud-workbench-layout-web-check.json`，终端断言只输出 compact
blockers/failures：`viewport`、`selector`、`failureType`、summary 和 artifact
路径。`/tmp/hwlab-dev-gate/dev-cloud-workbench-layout*.json` 是显式 `web:layout*`
命令的报告路径；它们属于 #273 UI layout blocker 证据，不属于 M3 trusted green
证据。

#287 的硬件状态标签化和 #288 的 `/gate` 单一大表如果尚未上线，layout smoke
只能把对应覆盖项记录为 `skip`，同时继续检查当前可见容器的溢出、遮挡和外层
滚动。该 UI smoke 只能证明布局/可点击性护栏通过，不等于 M3 DEV-LIVE 硬件
闭环通过，也不能替代 #227 的 DO/DI 功能验收。

该脚本同时覆盖 #276 的接线面板：打开右侧 `接线` 标签，断言
`panel-wiring` 是两列长表、表头为 `res_boxsimu_1` / `res_boxsimu_2`、IO
行为 `DO1` 对 `DI1`，并记录右侧接线面板 `scrollWidth <= clientWidth`，禁止
内部横向滚动。该证据仍只证明 UI 布局，不等于 M3 trusted green。

## Stable Sources

- [pikasTech/HWLAB#99](https://github.com/pikasTech/HWLAB/issues/99): default
  Cloud Workbench direction.
- [pikasTech/HWLAB#108](https://github.com/pikasTech/HWLAB/issues/108): no
  outer scroll, Chinese UI, internal Markdown help.
- [pikasTech/HWLAB#273](https://github.com/pikasTech/HWLAB/issues/273):
  Playwright layout and overlap guardrail.
- [pikasTech/HWLAB#276](https://github.com/pikasTech/HWLAB/issues/276):
  patch-panel wiring panel two-column long-table feedback.
- [pikasTech/HWLAB#278](https://github.com/pikasTech/HWLAB/issues/278):
  resource explorer collapse and controlled resize feedback.
- [code-agent-chat-readiness.md](code-agent-chat-readiness.md): Code Agent
  chat 同源 readiness 和 provider credential blocker 边界。
- [spec-v02-services.md](spec-v02-services.md): Cloud Web runtime wrapper and browser-side TypeScript migration boundary.
- [pikasTech/HWLAB#532](https://github.com/pikasTech/HWLAB/issues/532): archived historical `docs/cloud-web-workbench.md` content.
- [node-gitops-cicd.md](node-gitops-cicd.md): Cloud Web rollout through node-scoped Tekton, GitOps and Argo CD
  path.
