feat: add unidesk hwpod operations skill

This commit is contained in:
Codex
2026-07-10 11:51:30 +02:00
parent b9e804014b
commit 22f0a2c884
4 changed files with 188 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
---
name: unidesk-hwpod-ops
description: UniDesk HWLAB HWPOD 节点运维技能,覆盖 Windows 单文件 Python UI `hwlab-node.py` 的发现、安装、GUI/托盘、连接、更新、日志、诊断、nodeId、workspace、HWPOD node-ops、MDTODO source 和 legacy Bun runner 漂移。用户提到 hwpod-node、hwlab-node、Python UI node、HWPOD 节点上下线、D601/G14-WSL 硬件节点、workspace 绑定或 HWLAB Web MDTODO 读取时使用。
---
# UniDesk HWPOD Ops
以当前 HWLAB v0.3 Python UI node 为默认运维对象。旧 `$hwpod-ops` 中的 TypeScript/Bun `serve|connect` 只用于历史漂移调查,不作为新节点完成态。
## P0 Boundaries
- 当前 HWLAB 固定运行面由 UniDesk `config/hwlab-node-lanes.yaml` 选择;先运行 `cicd status``source-workspace status`,不要复用旧 G14/v0.2 URL。
- Python UI node 权威源码是选中 HWLAB source workspace 的 `tools/hwlab-node.py`;发布版本和 SHA 由选中 origin 的 `/v1/hwlab-node/update``/v1/hwlab-node/download/hwlab-node.py` 给出。
- 节点、workspace、HWPOD resource、MDTODO source、endpoint 和 Secret 都必须进入 owning YAML/configRef。`~/.hwlab/config.json` 是桌面应用配置,不是平台资源真相。
- Secret 只通过 YAML `sourceRef`/`targetKey` 和受控入口下发。状态、日志和 issue 只披露 presence、fingerprint 和脱敏摘要。
- Windows 节点使用主动出站 WebSocket;不要为用户 PC 增加入站端口或 direct-url fallback。
- Windows Python UI node 必须优先用目标 Windows 交互用户可见的原生 `python.exe` 启动。不要用 WSL Python、SSH helper 自带解释器、Bun runner 或非交互 Windows service 替代;解释器路径/版本必须进入 node profile 与状态证据。
- 调查可只读访问现场。安装、注册、更新、停止旧 runner 或改 MDTODO source 属于运行面变更,必须先加载 `$dad-dev`;部署/rollout 同时加载 `$unidesk-cicd`YAML 变更同时加载 `$unidesk-ymalops`
- 远端操作走 `$unidesk-trans`。普通 `trans` 保持短连接;GUI 进程不得作为透传子进程长挂。
- Python node 当前若没有 workspace allowlist/规范化、注册认证或 capability parity,不得把“WebSocket 已连接”报告为 HWPOD/MDTODO 可用。
## Read-Only Triage
```bash
bun scripts/cli.ts cicd status --node NC01
bun scripts/cli.ts hwlab nodes control-plane source-workspace status --node NC01 --lane v03
trans <provider>:win ps '[ordered]@{home=$HOME; python=(python --version 2>&1 | Out-String).Trim(); config=(Test-Path (Join-Path $HOME ".hwlab\\config.json")); log=(Test-Path (Join-Path $HOME ".hwlab\\logs\\hwlab-node.log"))} | ConvertTo-Json -Compress'
trans <provider>:win ps 'Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match "hwlab-node|hwpod-node" } | Select-Object ProcessId,Name,CommandLine | ConvertTo-Json -Compress'
trans <provider>:win ps 'Get-ScheduledTask -ErrorAction SilentlyContinue | Where-Object { $_.TaskName -match "HWLAB|HWPOD" } | Select-Object TaskName,State | ConvertTo-Json -Compress'
```
Classify results separately:
- `desktop-ready`: Python/tkinter and an interactive Windows session are available.
- `process-ready`: exactly one intended Python UI process is alive; no conflicting Bun authority.
- `registered`: cloud registry acknowledges the expected nodeId.
- `workspace-ready`: `node.inventory` and bounded workspace read target the YAML-selected root.
- `mdtodo-ready`: Project Management source save/probe/reindex succeeds through public HWPOD workspace ops.
Read [references/python-ui-node.md](references/python-ui-node.md) for the current application contract, update flow and known gaps. Read [references/workspace-mdtodo.md](references/workspace-mdtodo.md) when adding a node, binding a workspace or validating HWLAB Web MDTODO.
## Change Workflow
1. Observe the selected HWLAB node/lane, public origin, Python release metadata, Windows user/session, current node process, task/Run key, config presence and legacy runners.
2. Update the owning spec first when node identity, workspace root, resource binding, authentication, capabilities or MDTODO source changes.
3. Render/validate config before touching Windows. Keep nodeId, URL, workspace and retry/update settings out of generated helper code.
4. Install or update the published Python artifact by verified SHA. Resolve the target interactive user's Windows `python.exe`, record its path/version, and use it to launch the file in that Windows session so GUI and tray are visible; use a login-start mechanism only when declared by YAML.
5. Prove one active authority, expected version/nodeId, registration, `node.health`, `node.inventory`, bounded workspace read and structured diagnostics.
6. Validate MDTODO through the HWLAB Web-equivalent path: source save, probe, reindex, files/tasks visible. Direct `trans cat` is only P1 diagnosis.
7. Record source commit, artifact SHA, nodeId, workspace fingerprint/path summary, registration state, operation request/trace IDs and MDTODO source/reindex result. Never record raw Markdown or credentials by default.
## Stop Conditions
- Stop before mutation if the selected lane/source authority is unclear or stale.
- Stop before starting a second runner if an existing process controls the same nodeId/resource.
- Stop before MDTODO write/reindex if workspace containment is not enforced or the source can escape its declared root.
- Treat node mismatch, auth failure, missing workspace, capability mismatch, legacy drift and source projection failure as different blockers.
- Do not close an HWPOD issue on process health alone; use the user's original HWLAB Web/CaseRun/MDTODO entrypoint.
## References
- Python UI node contract, local files, update endpoints and drift: [references/python-ui-node.md](references/python-ui-node.md).
- Node onboarding, workspace binding and MDTODO verification: [references/workspace-mdtodo.md](references/workspace-mdtodo.md).
@@ -0,0 +1,4 @@
interface:
display_name: "UniDesk HWPOD 运维"
short_description: "运维 Python UI HWPOD 节点、连接、工作区与 MDTODO"
default_prompt: "使用 $unidesk-hwpod-ops 调查并运维指定 HWLAB Python UI HWPOD 节点。"
@@ -0,0 +1,64 @@
# Python UI Node
## Current Source
- HWLAB source: `tools/hwlab-node.py` on the YAML-selected v0.3 source workspace.
- Application: single-file Python/tkinter GUI with Windows tray, reconnect loop, rotating log and self-update.
- Local state: `%USERPROFILE%\.hwlab\config.json`, `state.json`, `logs\hwlab-node.log`, `update\`.
- Default public origin: `https://hwlab.pikapython.com`.
- Update metadata: `GET /v1/hwlab-node/update?platform=windows&channel=stable&current=<version>`.
- Artifact: `GET /v1/hwlab-node/download/hwlab-node.py`; verify the metadata SHA before replacement.
- Node transport: active outbound `wss://<origin>/v1/hwpod-node/ws` registration and heartbeat.
- Node-ops contract: `hwpod-node-ops-v1`.
Do not copy version numbers or SHA values into long-lived instructions. Read them from the selected runtime/source during each operation.
## Desktop Configuration
The current application exposes `serverUrl`, `nodeId`, `autoConnect`, update settings and logging settings. It intentionally accepts no CLI arguments or `HWLAB_*` environment variables.
Run the application with the target Windows user's native interpreter. Resolve `python.exe` from the same interactive login context that owns `%USERPROFILE%\.hwlab` and the tray, then persist the selected interpreter path in the owning node profile/start declaration. `python --version`, `Get-Command python` and a tkinter import are discovery evidence; a WSL `/usr/bin/python`, SSH-side helper interpreter or hidden service account is not an acceptable runtime.
Treat local config as operator preference only. Platform declarations still own:
- node/lane and unique nodeId;
- HWPOD resource and capability binding;
- allowed workspace roots;
- WebSocket/auth Secret sourceRef;
- managed login/start policy;
- Windows interpreter path/version and interactive user;
- Project Management MDTODO sources.
## Status Evidence
Collect bounded, redacted facts:
```powershell
$root = Join-Path $HOME ".hwlab"
[ordered]@{
home = $HOME
configExists = Test-Path (Join-Path $root "config.json")
stateExists = Test-Path (Join-Path $root "state.json")
logExists = Test-Path (Join-Path $root "logs\hwlab-node.log")
interactiveShell = (Get-Process explorer -ErrorAction SilentlyContinue | Measure-Object).Count
} | ConvertTo-Json -Compress
```
Read config fields only when needed and redact any unknown future Secret-bearing field. Prefer cloud `node.health`, `node.version`, `node.inventory` and `node.diagnostics` results for registration/runtime evidence.
## Known Gaps To Check
Never assume the newest published file has solved these items; inspect the selected source/version:
- Default nodeId may still be D601-specific.
- Workspace operations may accept request-provided absolute paths without a configured allowlist or containment check.
- WebSocket registration may lack a node credential even when cloud-api supports a token.
- Capabilities may lag the cloud contract, especially apply-patch, UART write/JSON-RPC, Keil and structured blockers.
- GUI close-to-tray is not equivalent to login persistence; a scheduled task in a non-interactive session can hide the UI/tray.
- A legacy Bun runner may remain active under another task, Run key or runtime directory.
Surface each gap separately. Do not add local fallback paths to conceal it.
## Legacy Drift
Legacy evidence includes `bun.exe tools\hwpod-node.ts connect`, old IP/port cloud URLs, `hwpod-node-runtime`, and old scheduled task names. Before stopping anything, compare nodeId, cloud URL, resource binding and active hardware work. Any change that can interrupt a hardware operation requires an explicit maintenance window and `$dad-dev` workflow.
@@ -0,0 +1,56 @@
# Workspace And MDTODO
## Required Declarations
Add a node/workspace only through owning YAML/configRef. Keep these concepts distinct:
| Concept | Required fact |
| --- | --- |
| Desktop node | HWLAB node/lane, unique nodeId, Python artifact source, Windows pythonPath/version, managed interactive user/start policy |
| HWPOD resource | hwpodId/resourceId, nodeId, capabilities, workspaceRootRef |
| Workspace policy | allowed Windows roots, containment/normalization policy, read/write capabilities |
| MDTODO source | sourceId, projectId, hwpodId, nodeId, workspaceRootRef, mdtodoRootRef |
| Service routing | public/service node-ops configRef and Secret sourceRef |
For a Windows Python UI node, `workspaceRootRef` must use the Windows path visible to that process. A WSL `/mnt/<drive>/...` route may prove the same files exist, but it is not the Python node's path authority.
## Onboarding Sequence
1. Confirm the Windows path exists, is a directory and contains the intended MDTODO root.
2. Allocate a nodeId distinct from D601 and all existing nodes.
3. Add YAML declarations for desktop node, HWPOD resource/workspace policy and MDTODO source.
4. Ensure the Python node enforces declared workspace roots with canonical-path containment; reject absolute paths outside them, `..`, symlink/junction escape and undeclared roots.
5. Configure registration authentication from SecretRef without printing credentials.
6. Install the SHA-verified Python artifact and launch in the selected interactive Windows user session.
7. Prove cloud registration and expected capabilities.
8. Run `node.inventory` against the declared root, then bounded `workspace.ls`/`workspace.cat` under the MDTODO root.
9. Save/probe/reindex the Project Management source and verify files/tasks in HWLAB Web.
## MDTODO Acceptance
Use the public Project Management path and selected source:
1. Open `/projects/mdtodo` on the YAML-selected origin.
2. Save the source with its declared `hwpodId`, `nodeId`, workspace root and relative MDTODO root.
3. Probe the source and require a structured ready result.
4. Reindex and record document/task counts plus fingerprint, not raw Markdown.
5. Confirm direct `.md` files and their tasks are visible.
6. When requested, launch Workbench from one task and verify the resulting task/session link.
The equivalent API family is `/v1/project-management/mdtodo/*`; use the repo-owned web-probe commands when available. Never make direct filesystem reads the completion evidence.
## Failure Classification
| Code family | Meaning |
| --- | --- |
| node-offline | Python process absent or WebSocket not registered |
| node-id-mismatch | plan targets a different node identity |
| node-auth | credential missing/rejected |
| workspace-policy | root absent, outside allowlist or containment failure |
| capability-mismatch | node cannot execute the requested public operation |
| workspace-op | bounded operation failed inside an allowed root |
| source-probe | Project Management could not read/parse the source |
| source-projection | reindex or DB projection failed after source read |
| web-visibility | API state exists but HWLAB Web does not expose it correctly |
Preserve requestId/traceId and node diagnostics for the failing layer. Fix the owning layer instead of adding SSH, direct filesystem, local mount or private API fallbacks.