Skip to content

Rebuild Nodes page as cross-platform Instances page#407

Merged
shanselman merged 2 commits into
openclaw:masterfrom
bkudiess:instances-page-rebuild
May 15, 2026
Merged

Rebuild Nodes page as cross-platform Instances page#407
shanselman merged 2 commits into
openclaw:masterfrom
bkudiess:instances-page-rebuild

Conversation

@bkudiess
Copy link
Copy Markdown
Contributor

Replaces NodesPage (959 LOC, Windows-paired-only) with a single presence-driven InstancesPage modelled on macOS InstancesSettings. One card per gateway entity: the gateway itself, Mac / iPhone / iPad / Android beacons, and paired Windows nodes. All NodesPage management (capabilities, commands, PATH, Rename, Forget) is preserved inline on paired Windows rows. Operator / node pairing relocates to the Connection page.

New

  • OpenClaw.Shared.InstanceMerger — pure presence × node-list merge. Conservative two-pass matching (strong DeviceId / InstanceId before weak host fallback), dedup, stable sort. 45 unit tests.
  • InstancesPage — Fluent card layout: 4px state stripe (Active / Idle / Inactive / Disconnected / Gateway), role pills, identity caption, icon-row metadata, hover affordance, refresh ProgressRing.
  • InstanceManagementControls — inline management body for paired Windows rows; reuses existing NodesPage_* resource keys so translations carry over.
  • 4 localized InstancesPage_TimeAgo_* keys across all 5 locales.

Gone

  • NodesPage (959 LOC).

Validation

  • ./build.ps1 clean (Shared / Cli / WinNodeCli / WinUI)
  • OpenClaw.Shared.Tests 1620 passed (+45 new)
  • OpenClaw.Tray.Tests 1210 passed
  • Two rounds of adversarial dual-model review (Claude Opus + GPT-5 Codex) → 11 findings, 9 fixed, 2 dismissed as false reads.

Notes

  • ConnectionPage delta (+161 LOC: NodePairingCard + UpdatePairingRequests) was added knowing another contributor is also editing this file — expect a small merge.
  • Branch is based on 95cfcfb and may need a rebase onto current master.

Replaces NodesPage (959 LOC, Windows-paired-only) with a single
presence-driven InstancesPage modelled on macOS InstancesSettings:
one card per gateway entity (gateway + Mac/iPhone/iPad/Android beacons
+ paired Windows nodes). All NodesPage management surface (capabilities,
commands, PATH, Rename, Forget) is preserved inline on paired Windows
rows. Operator/node pairing relocated to ConnectionPage.

- Add OpenClaw.Shared.InstanceMerger: pure presence x node-list merge
  with conservative two-pass matching (strong DeviceId/InstanceId before
  weak host fallback), dedup, stable sort. 45 unit tests.
- Add InstancesPage with Fluent card layout: 4px state stripe, role
  pills, identity caption, icon-row metadata, hover affordance, refresh
  ProgressRing.
- Add InstanceManagementControls helper for inline node management;
  reuses existing NodesPage_* resource keys so translations carry over.
- Add localized InstancesPage_TimeAgo_* keys across all 5 locales.
- Delete NodesPage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@shanselman shanselman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the big cleanup here. The current-master merge validates locally for me (.\build.ps1, Shared tests, Tray tests), and I agree the GitHub test failure appears to be the existing flaky CanvasEval_ReturnsResultOrWellFormedError timeout rather than something specific to this branch.

I don't think this is safe to merge yet because the new Instances merge can still attach destructive node management actions from a weak identity match.

TryWeakMatch(...) matches a presence row to a node using only unique hostDisplayName. Once that happens, BuildFromPresence(...) stores the GatewayNodeInfo on the row, MergedInstance.IsManaged returns Node != null, and InstancesPage renders InstanceManagementControls.BuildManagementBody(...), including Rename and Forget. That means a presence row matched only by display name/host can expose destructive actions for a paired Windows node. The comment above TryStrongMatch says "Only this kind of match should attach Rename/Forget to a presence row", but the implementation and HostFallback_Matches_When_BothSides_Unique test currently allow weak matches to be managed.

Please track match strength and gate the management surface separately from Node != null. Strong ID matches (DeviceId/InstanceId to NodeId/ClientId) and orphan node rows are okay to manage. Weak host/display-name matches should either be presence-only plus a separate manageable node row, or use node data only for non-destructive enrichment while suppressing Rename/Forget.

One more user-visible regression to fix: legacy ShowHub("nodes")/deep-link paths load InstancesPage, but NavigateTo("nodes") calls FindAndSelectNavItem("nodes") before aliasing, and the nav item is now tagged instances. The page opens through the fallback path with no selected nav item. Normalize nodes to instances before FindAndSelectNavItem(...) runs, and add a small regression test if possible.

The pairing approval move to Connection looks otherwise wired correctly: LastNodePairList/LastDevicePairList are replayed in InitializeCurrentPage, and the old nodes page type references appear cleaned up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@shanselman shanselman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer-side follow-up e2e1cf0 addresses the requested blockers: weak host/display-name matches now keep node data for enrichment but do not enable management actions, orphan/strong ID-matched rows remain manageable, and legacy
odes\ navigation is normalized before nav selection so the Instances nav item highlights correctly.\n\nValidated locally in \D:\github\moltbot-windows-hub.pr407-review: .\build.ps1; Shared tests 1620/1648 with 28 skipped; Tray tests 1211/1211.

@shanselman shanselman merged commit e9c5de3 into openclaw:master May 15, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants