diff --git a/.agents/skills/unidesk-hwpod-ops/SKILL.md b/.agents/skills/unidesk-hwpod-ops/SKILL.md new file mode 100644 index 00000000..55eb5bb0 --- /dev/null +++ b/.agents/skills/unidesk-hwpod-ops/SKILL.md @@ -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 :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 :win ps 'Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match "hwlab-node|hwpod-node" } | Select-Object ProcessId,Name,CommandLine | ConvertTo-Json -Compress' +trans :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). diff --git a/.agents/skills/unidesk-hwpod-ops/agents/openai.yaml b/.agents/skills/unidesk-hwpod-ops/agents/openai.yaml new file mode 100644 index 00000000..a68a1df1 --- /dev/null +++ b/.agents/skills/unidesk-hwpod-ops/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "UniDesk HWPOD 运维" + short_description: "运维 Python UI HWPOD 节点、连接、工作区与 MDTODO" + default_prompt: "使用 $unidesk-hwpod-ops 调查并运维指定 HWLAB Python UI HWPOD 节点。" diff --git a/.agents/skills/unidesk-hwpod-ops/references/python-ui-node.md b/.agents/skills/unidesk-hwpod-ops/references/python-ui-node.md new file mode 100644 index 00000000..8ed4c494 --- /dev/null +++ b/.agents/skills/unidesk-hwpod-ops/references/python-ui-node.md @@ -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¤t=`. +- Artifact: `GET /v1/hwlab-node/download/hwlab-node.py`; verify the metadata SHA before replacement. +- Node transport: active outbound `wss:///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. diff --git a/.agents/skills/unidesk-hwpod-ops/references/workspace-mdtodo.md b/.agents/skills/unidesk-hwpod-ops/references/workspace-mdtodo.md new file mode 100644 index 00000000..f587415f --- /dev/null +++ b/.agents/skills/unidesk-hwpod-ops/references/workspace-mdtodo.md @@ -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//...` 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.