Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Required steps:
3. Run tray tests:
- `dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --no-restore`

This is the required local closeout subset for agents. CI also builds and runs additional connection, setup, CLI, UI, integration, and E2E suites; see `docs/TEST_COVERAGE.md` for the broader inventory.
This is the required local closeout subset for agents. CI also builds and runs additional connection, setup, CLI, UI, accessibility, integration, and E2E suites; see `docs/TEST_COVERAGE.md` for the broader test inventory and `.github/workflows/ci.yml` for the workflow source of truth.

If a command fails:

Expand Down Expand Up @@ -77,6 +77,7 @@ Start with these docs before changing connection, pairing, node, MCP, or tray UX
- `docs/MCP_MODE.md` - local MCP server mode and the `EnableNodeMode` / `EnableMcpServer` matrix.
- `docs/WINDOWS_NODE_TESTING.md` - Windows node capabilities, manual smokes, and gateway-dependent behavior.
- `docs/ONBOARDING_WIZARD.md` - first-run setup flow, setup-code/bootstrap pairing, and test isolation.
- `docs/SETUP_ENGINE_REDESIGN.md` - setup pipeline, rollback/logging, Windows node context injection, and setup CLI contract.
- `docs/WSL_EXE_ARGV_PITFALL.md` - wsl.exe argv variable-expansion pitfall; required reading before adding any multi-line WSL script through `RunInWslAsync`.

## Architecture Guardrails for Large Refactors
Expand Down
56 changes: 41 additions & 15 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ openclaw-windows-hub/
│ │
│ ├── OpenClaw.SetupEngine/ # Local WSL gateway setup and setup-code support
│ │
│ ├── OpenClaw.SetupEngine.UI/ # WinUI setup wizard pages hosted by the tray app
│ │
│ ├── OpenClawTray.FunctionalUI/ # Small in-repo declarative WinUI helper
│ │ └── FunctionalUI.cs # Components, hooks, elements, host control
│ │
── OpenClaw.Tray.WinUI/ # WinUI 3 system tray application (primary)
── OpenClaw.Tray.WinUI/ # WinUI 3 system tray application (primary)
│ │ ├── App.xaml.cs # Main application, tray icon, gateway connection
│ │ ├── Services/ # Settings, logging, hotkeys, deep links
│ │ ├── Windows/ # UI windows (Settings, WebChat, Status, etc.)
Expand All @@ -71,8 +73,11 @@ openclaw-windows-hub/
│ ├── OpenClaw.Connection.Tests/ # Gateway registry and connection manager tests
│ ├── OpenClaw.Tray.Tests/ # Tests for tray helpers (menu, settings, deep links)
│ ├── OpenClaw.WinNode.Cli.Tests/ # winnode CLI contract tests
│ ├── OpenClaw.SetupEngine.Tests/ # Setup engine tests
│ └── OpenClaw.Tray.UITests/ # Native WinUI/A2UI UI tests
│ ├── OpenClaw.SetupEngine.Tests/ # Setup engine tests
│ ├── OpenClaw.Tray.UITests/ # Native WinUI/A2UI UI tests
│ ├── OpenClawTray.FunctionalUI.Tests/ # FunctionalUI smoke tests
│ ├── OpenClaw.Tray.IntegrationTests/ # Real-process tray/MCP integration tests
│ └── OpenClaw.E2ETests/ # Gateway-mediated setup/connect E2E suites
├── .github/workflows/
│ └── ci.yml # GitHub Actions CI/CD workflow
Expand All @@ -85,8 +90,9 @@ openclaw-windows-hub/
### Project Dependencies

```
OpenClaw.Tray.WinUI ──depends on──▶ OpenClaw.Shared + OpenClaw.Connection + OpenClaw.Chat
OpenClaw.Tray.WinUI ──depends on──▶ OpenClaw.Shared + OpenClaw.Connection + OpenClaw.Chat + OpenClaw.SetupEngine.UI
OpenClaw.WinNode.Cli ──depends on──▶ OpenClaw.Shared
OpenClaw.SetupEngine.UI ──wraps──▶ OpenClaw.SetupEngine
OpenClaw.SetupEngine ──supports──▶ local WSL gateway setup
OpenClaw.*.Tests ──test──▶ corresponding shared, connection, tray, setup, and CLI surfaces
```
Expand All @@ -110,11 +116,10 @@ OpenClaw.*.Tests ──test──▶ corresponding shared, connection, tray, s
From the repository root:

```bash
dotnet restore
dotnet build
./build.ps1
```

This builds all projects (shared library, tray app, setup engine, and CLI tools).
This restores prerequisites as needed and builds the shared library, tray app, setup engine, and CLI tools with the required Windows runtime identifiers.

### Build Individual Projects

Expand All @@ -125,7 +130,7 @@ dotnet build src/OpenClaw.Shared

**Tray App (WinUI):**
```bash
dotnet build src/OpenClaw.Tray.WinUI
dotnet build src/OpenClaw.Tray.WinUI -r win-x64
```

### Platform and Architecture Notes
Expand All @@ -152,7 +157,7 @@ dotnet build
The WinUI Tray app is Windows-only but can be built on Linux using:

```bash
dotnet build -p:EnableWindowsTargeting=true
dotnet build src/OpenClaw.Tray.WinUI -r win-x64 -p:EnableWindowsTargeting=true
```

### Running in Debug Mode
Expand All @@ -166,13 +171,13 @@ dotnet build -p:EnableWindowsTargeting=true
#### Command Line

```bash
dotnet run --project src/OpenClaw.Tray.WinUI
dotnet run --project src/OpenClaw.Tray.WinUI -r win-x64
```

For verbose output:

```bash
dotnet run --project src/OpenClaw.Tray.WinUI -c Debug
dotnet run --project src/OpenClaw.Tray.WinUI -c Debug -r win-x64
```

### Publishing (Self-Contained)
Expand Down Expand Up @@ -202,6 +207,26 @@ Use the local helper to build unsigned installer EXEs without waiting for CI:

`-Fast` uses ZIP/no-solid compression for quick local iteration. CI release builds keep the default LZMA solid compression and Azure signing.

#### Dev identity and side-by-side installs

Release identity is the default for every configuration. Use `-DevBuild` on `build.ps1` or `-Dev` on `run-app-local.ps1` when you explicitly want the side-by-side dev identity:

```powershell
.\build.ps1 -Project WinUI -DevBuild
.\run-app-local.ps1 -Dev -Isolated
```

`-DevBuild` passes `-p:DevBuild=true` to the WinUI project and produces the dev app identity marker that CI verifies in the **Verify DevBuild identity marker** step. `installer.iss` also accepts `/DDevBuild=1` for side-by-side dev installers; `.\scripts\build-inno-local.ps1 -Dev` wires that flag for local installer iteration.

#### Onboarding and setup workflow helpers

The first-run Windows gateway onboarding wizard lives in `OpenClaw.SetupEngine.UI` and is hosted by `OpenClaw.Tray.WinUI`; see [docs/ONBOARDING_WIZARD.md](docs/ONBOARDING_WIZARD.md) for the page flow. The setup pipeline itself is documented in [docs/SETUP_ENGINE_REDESIGN.md](docs/SETUP_ENGINE_REDESIGN.md), including the Windows node context step that injects agent instructions into the WSL workspace.

Useful local scripts:

- `.\scripts\dev-reset-rebuild-launch.ps1` resets tray data, rebuilds, and optionally launches the app; add `-WipeWslDistro` for a full local WSL gateway reset.
- `.\scripts\validate-mxc-e2e.ps1` runs the formal WSL Gateway -> Windows node -> `system.run` MXC proof path for MXC-sensitive changes.

## Architecture Overview

### Native chat surface (FunctionalUI + OpenClaw.Chat)
Expand Down Expand Up @@ -461,7 +486,7 @@ prompts.

### Running Unit Tests

Two test projects cover the shared library and tray helpers:
The repository has multiple unit, UI, integration, and E2E test projects. Use [docs/TEST_COVERAGE.md](docs/TEST_COVERAGE.md) as the inventory of record.

```bash
# Run local-dev tests. E2E is intentionally excluded from the solution and
Expand All @@ -476,9 +501,10 @@ dotnet test --filter "FullyQualifiedName~AgentActivityTests"
```

**Test Coverage:**
- ✅ **1182 tests** in `OpenClaw.Shared.Tests` — models, gateway client, exec approvals, capabilities, URL helpers, notification categorization, shell quoting, MCP, device identity, and WinNode client coverage
- ✅ **388 tests** in `OpenClaw.Tray.Tests` — settings round-trip, deep link parsing, onboarding state, setup code decoder, gateway health/chat helpers, security validation, wizard step parsing, gateway discovery, localization validation
- ✅ All tests are pure unit tests (no network, no file system, no external dependencies)
- `OpenClaw.Shared.Tests` covers models, gateway client behavior, capabilities, URL helpers, notification categorization, shell quoting, MCP, device identity, and WinNode client contracts.
- `OpenClaw.Tray.Tests` covers settings isolation, deep link parsing, onboarding state, setup code decoding, gateway health/chat helpers, security validation, wizard step parsing, gateway discovery, localization, and tray UI helpers.
- Additional projects cover connection management, setup engine behavior, `winnode`, FunctionalUI, native UI/A2UI, integration, and gateway-mediated E2E flows.
- See [docs/TEST_COVERAGE.md](docs/TEST_COVERAGE.md) for current method counts, runtime totals, and which lanes require network, WSL, real-process, or desktop prerequisites.

See [tests/OpenClaw.Shared.Tests/README.md](tests/OpenClaw.Shared.Tests/README.md) for detailed test documentation.

Expand Down
19 changes: 4 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ This monorepo contains the Windows hub, shared client libraries, and CLI utiliti
| **OpenClaw.Cli** | CLI validator for WebSocket connect/send/probe using tray settings |
| **OpenClaw.WinNode.Cli** | `winnode` CLI for invoking local Windows node/MCP capabilities |
| **OpenClaw.SetupEngine** | Local gateway setup, WSL installation, and setup-code support |
| **OpenClaw.SetupEngine.UI** | WinUI setup wizard pages hosted by the tray app |
| **OpenClawTray.FunctionalUI** | In-repo declarative WinUI helper used by native chat and newer UI surfaces |

## 🚀 Quick Start

Expand Down Expand Up @@ -401,21 +403,8 @@ Shared library containing:
## Development

### Project Structure
```
openclaw-windows-node/
├── src/
│ ├── OpenClaw.Shared/ # Shared gateway library
│ └── OpenClaw.Tray.WinUI/ # System tray app (WinUI 3)
├── tests/
│ ├── OpenClaw.Shared.Tests/ # Shared library tests
│ └── OpenClaw.Tray.Tests/ # Tray app helper tests
├── docs/
│ └── images/ # Screenshots
├── openclaw-windows-node.slnx # Solution file
├── README.md
├── LICENSE
└── .gitignore
```

See [DEVELOPMENT.md](DEVELOPMENT.md#project-structure) for the complete and current `src/` and `tests/` project inventory.

### Configuration

Expand Down
18 changes: 11 additions & 7 deletions docs/A2UI_NATIVE_WINUI.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
# Native WinUI A2UI Canvas — Design Spec

> **Status:** Draft / proposal
> **Audience:** Contributors implementing a native A2UI renderer for the Windows node
> **Status:** Implemented; historical design rationale
> **Audience:** Contributors maintaining the native A2UI renderer for the Windows node
> **Target version:** A2UI v0.8 (parity with current openclaw clients), with a v0.9 migration path

The native WinUI renderer is implemented under `src\OpenClaw.Tray.WinUI\A2UI\`. This file preserves the original design rationale; the current source of truth for protocol and component details lives in `docs\a2ui\` (`README.md`, `protocol.md`, `components.md`, and grading notes). Phase 4 / A2UI v0.9 migration has not started.

## 1. Motivation

Today the Windows node renders A2UI by hosting a WebView2 control (`CanvasWindow`) that navigates to an HTTP page served by the openclaw gateway at `/__openclaw__/a2ui/`. That page bundles `@a2ui/lit` and openclaw's bridge JS. Pushed messages travel `agent → gateway → node (canvas.a2ui.push) → WebView2 → window.__a2ui.receive(msg)`.
Before the native renderer landed, the Windows node rendered A2UI by hosting a WebView2 control (`CanvasWindow`) that navigated to an HTTP page served by the openclaw gateway at `/__openclaw__/a2ui/`. That page bundled `@a2ui/lit` and openclaw's bridge JS. Pushed messages traveled `agent → gateway → node (canvas.a2ui.push) → WebView2 → window.__a2ui.receive(msg)`.

That works, but it has costs:
That worked, but it had costs:

- **Hard gateway dependency.** A node running in MCP-only mode (no gateway connection) silently drops A2UI pushes — `OnCanvasA2UIPush` bails when `_a2uiHostUrl` is null. The renderer code physically lives at the gateway.
- **Hard gateway dependency.** A node running in MCP-only mode (no gateway connection) could silently drop A2UI pushes because the WebView2 renderer code lived at the gateway.
- **WebView2 surface area.** Drag/drop, IME, accessibility, focus, DPI, and keyboard shortcuts inherit WebView2 quirks instead of XAML's native behavior. The canvas always feels like an embedded browser.
- **Bootstrapping latency.** Each cold start has to ensure WebView2 is ready, navigate, and wait for `window.__a2ui` to register before any message can be delivered (`EnsureA2UIHostAsync` + `ensureA2uiReady` polling).
- **Theming drift.** WinUI windows around the canvas use Mica/Fluent; the canvas uses Lit components styled with CSS. Achieving consistent visuals requires duplicate theme work.
- **Hardening.** Surface area for arbitrary script execution remains larger than necessary for what is fundamentally a declarative UI tree.

A native WinUI renderer renders A2UI surfaces directly into XAML — no WebView, no HTTP host, no JS bridge. The node becomes self-contained: it can render A2UI whether it's connected to a gateway, an MCP client, or both.
The implemented native WinUI renderer renders A2UI surfaces directly into XAML — no WebView, no HTTP host, no JS bridge. The node is self-contained: it can render A2UI whether it's connected to a gateway, an MCP client, or both.

## 2. Goals & non-goals

Expand Down Expand Up @@ -267,12 +269,14 @@ Mirror what `CanvasCapability` already logs:

## 13. Phasing

This table is historical. Phases 0-3 are now implemented by the native renderer path; no `--canvas=web` coexistence flag shipped. Phase 4 / v0.9 migration has not started.

| Phase | Scope | Exit criteria |
|---|---|---|
| **0 — Spike** | `Text`, `Column`, `Button` only; one surface; no data model | Single button click round-trips to agent |
| **1 — Catalog parity** | All v0.8 standard catalog types; data model + bindings; modal/tabs | Full conformance fixtures pass |
| **2 — Polish** | Theming, transitions, focus management, accessibility (Narrator), keyboard nav | A11y audit clean; UX review against Lit version |
| **3 — Coexistence** | Native window default; WebView2 path retained behind `--canvas=web` flag for parity testing | No regressions in WebView2 path |
| **3 — Native default** | Native window default for A2UI rendering | Native path covers the v0.8 surface without the WebView2 host |
| **4 — v0.9 migration** | Bidirectional messages, modular schemas, prompt-first | Tracks Google A2UI v0.9 release |

## 14. Open questions
Expand Down
28 changes: 28 additions & 0 deletions docs/ACCESSIBILITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Accessibility validation

OpenClaw Companion treats accessibility as a CI quality gate for the WinUI app. The Build and Test workflow runs real-process Axe.Windows scans against the tray UI test project after the normal native UI tests.

## What CI enforces

The `.github\workflows\ci.yml` **Run Accessibility Tests (Axe.Windows)** step runs:

```powershell
dotnet test tests\OpenClaw.Tray.UITests --no-build -c Debug -r win-x64 --filter Category=Accessibility
```

Those tests launch the app in a real Windows desktop process and scan pages for WCAG violations through Axe.Windows. Failures are summarized in the GitHub Actions step summary and written to `Accessibility.trx`.

## Running locally

From the repository root:

```powershell
dotnet build tests\OpenClaw.Tray.UITests -c Debug -r win-x64
dotnet test tests\OpenClaw.Tray.UITests -c Debug -r win-x64 --no-build --filter Category=Accessibility
```

Run this lane for UI changes that add or modify pages, dialogs, controls, focus behavior, labels, contrast-sensitive visuals, or keyboard navigation.

## Relationship to other validation

Accessibility scans do not replace the required agent closeout validation in `AGENTS.md`. They are an additional focused lane for WinUI accessibility work and a formal CI gate documented in `docs\TEST_COVERAGE.md`.
2 changes: 1 addition & 1 deletion docs/CONNECTION_PROTOCOL_RESEARCH.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Public upstream gateway sources reviewed:
- `https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/nodes.ts`
- `https://github.com/openclaw/openclaw/blob/main/packages/gateway-protocol/src/schema/frames.ts`

The setup engine currently pins gateway LKG `2026.6.1` in
The setup engine currently pins gateway LKG `2026.6.11` in
`src/OpenClaw.SetupEngine/GatewayLkgVersion.cs`. Before implementing behavior
that depends on newer upstream `main`, compare the installed LKG against the
reviewed upstream docs/code.
Expand Down
2 changes: 1 addition & 1 deletion docs/DATA_FLOW_ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ src/OpenClaw.Tray.WinUI/Services/AppState.cs

### GatewayService (`Services/GatewayService.cs`)

Owns all 27 operator gateway client event subscriptions. Moved from App.xaml.cs to separate concerns.
Owns the operator gateway client event subscriptions, including data events and connection lifecycle events. Moved from App.xaml.cs to separate concerns.

```
src/OpenClaw.Tray.WinUI/Services/GatewayService.cs
Expand Down
Loading