diff --git a/.planning/phases/02-ui-performance/02-PERF-BASELINE.json b/.planning/phases/02-ui-performance/02-PERF-BASELINE.json
new file mode 100644
index 00000000..86a02bff
--- /dev/null
+++ b/.planning/phases/02-ui-performance/02-PERF-BASELINE.json
@@ -0,0 +1,1784 @@
+{
+ "baseUrl": "http://archi-dev-box",
+ "takenAt": "2026-07-30T10:30:40.048Z",
+ "commit": "a75b6709",
+ "runs": 3,
+ "notes": "Skipped/errored surfaces: mesh: locator.waitFor: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.mesh-status-grid').first() to be visible\u001b[22m\n\u001b[2m 44 × locator resolved to hidden
…
\u001b[22m\n; chat: locator.click: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.chat-close-btn').first()\u001b[22m\n\u001b[2m - locator resolved to … \u001b[22m\n\u001b[2m - attempting click action\u001b[22m\n\u001b[2m - waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - …
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is not stable\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 20ms\u001b[22m\n\u001b[2m 2 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 100ms\u001b[22m\n\u001b[2m 37 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 500ms\u001b[22m\n",
+ "results": [
+ {
+ "id": "home",
+ "label": "Home (wallet figures)",
+ "path": "/dashboard",
+ "kind": "main-tab",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 354,
+ "revisitMs": 1348,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 20,
+ "revisitRpcCalls": [
+ {
+ "method": "node.did",
+ "startedAtMs": 191,
+ "durationMs": 113
+ },
+ {
+ "method": "auth.totp.status",
+ "startedAtMs": 191,
+ "durationMs": 123
+ },
+ {
+ "method": "webhook.get-config",
+ "startedAtMs": 197,
+ "durationMs": 117
+ },
+ {
+ "method": "analytics.get-status",
+ "startedAtMs": 198,
+ "durationMs": 116
+ },
+ {
+ "method": "backup.list",
+ "startedAtMs": 198,
+ "durationMs": 116
+ },
+ {
+ "method": "system.kiosk-display.get",
+ "startedAtMs": 198,
+ "durationMs": 116
+ },
+ {
+ "method": "system.settings.get",
+ "startedAtMs": 199,
+ "durationMs": 115
+ },
+ {
+ "method": "node.nostr-pubkey",
+ "startedAtMs": 314,
+ "durationMs": 17
+ },
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 338,
+ "durationMs": 13
+ },
+ {
+ "method": "system.stats",
+ "startedAtMs": 1049,
+ "durationMs": 257
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 1049,
+ "durationMs": 276
+ },
+ {
+ "method": "openwrt.get-status",
+ "startedAtMs": 1049,
+ "durationMs": 281
+ },
+ {
+ "method": "update.status",
+ "startedAtMs": 1053,
+ "durationMs": 277
+ },
+ {
+ "method": "lnd.getinfo",
+ "startedAtMs": 1053,
+ "durationMs": 277
+ },
+ {
+ "method": "wallet.ecash-balance",
+ "startedAtMs": 1054,
+ "durationMs": 276
+ },
+ {
+ "method": "wallet.fedimint-balance",
+ "startedAtMs": 1054,
+ "durationMs": 277
+ },
+ {
+ "method": "wallet.ark-balance",
+ "startedAtMs": 1054,
+ "durationMs": 277
+ },
+ {
+ "method": "lnd.gettransactions",
+ "startedAtMs": 1054,
+ "durationMs": 277
+ },
+ {
+ "method": "lnd.lightning-history",
+ "startedAtMs": 1054,
+ "durationMs": 278
+ },
+ {
+ "method": "wallet.ecash-history",
+ "startedAtMs": 1054,
+ "durationMs": 278
+ }
+ ],
+ "maxConcurrentRpc": 11,
+ "rpcWallClockMs": 1141,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 362,
+ "revisitMs": 390,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 93,
+ "durationMs": 8
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 8,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 195,
+ "revisitMs": 251,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 61,
+ "durationMs": 14
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 14,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 354,
+ "revisitMs": 390,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 93,
+ "durationMs": 8
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 8,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "apps",
+ "label": "Apps (My Apps)",
+ "path": "/dashboard/apps",
+ "kind": "main-tab",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 539,
+ "revisitMs": 1136,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 292,
+ "durationMs": 56
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 56,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 359,
+ "revisitMs": 267,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 70,
+ "durationMs": 6
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 6,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 266,
+ "revisitMs": 155,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": false,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 359,
+ "revisitMs": 267,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 70,
+ "durationMs": 6
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 6,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "marketplace",
+ "label": "Marketplace (App Store)",
+ "path": "/dashboard/marketplace",
+ "kind": "main-tab",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 1228,
+ "revisitMs": 750,
+ "firstVisitRpcCount": 1,
+ "revisitRpcCount": 13,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 108,
+ "durationMs": 14
+ },
+ {
+ "method": "system.stats",
+ "startedAtMs": 323,
+ "durationMs": 98
+ },
+ {
+ "method": "openwrt.get-status",
+ "startedAtMs": 323,
+ "durationMs": 98
+ },
+ {
+ "method": "update.status",
+ "startedAtMs": 323,
+ "durationMs": 98
+ },
+ {
+ "method": "wallet.ecash-balance",
+ "startedAtMs": 324,
+ "durationMs": 97
+ },
+ {
+ "method": "wallet.fedimint-balance",
+ "startedAtMs": 324,
+ "durationMs": 97
+ },
+ {
+ "method": "wallet.ark-balance",
+ "startedAtMs": 324,
+ "durationMs": 101
+ },
+ {
+ "method": "lnd.getinfo",
+ "startedAtMs": 323,
+ "durationMs": 119
+ },
+ {
+ "method": "wallet.ecash-history",
+ "startedAtMs": 324,
+ "durationMs": 137
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 323,
+ "durationMs": 163
+ },
+ {
+ "method": "lnd.gettransactions",
+ "startedAtMs": 324,
+ "durationMs": 163
+ },
+ {
+ "method": "lnd.lightning-history",
+ "startedAtMs": 324,
+ "durationMs": 163
+ },
+ {
+ "method": "vpn.status",
+ "startedAtMs": 323,
+ "durationMs": 272
+ }
+ ],
+ "maxConcurrentRpc": 12,
+ "rpcWallClockMs": 487,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 1168,
+ "revisitMs": 2033,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 13,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 16,
+ "durationMs": 59
+ },
+ {
+ "method": "system.stats",
+ "startedAtMs": 376,
+ "durationMs": 133
+ },
+ {
+ "method": "openwrt.get-status",
+ "startedAtMs": 399,
+ "durationMs": 110
+ },
+ {
+ "method": "update.status",
+ "startedAtMs": 399,
+ "durationMs": 112
+ },
+ {
+ "method": "wallet.ecash-balance",
+ "startedAtMs": 399,
+ "durationMs": 113
+ },
+ {
+ "method": "lnd.getinfo",
+ "startedAtMs": 399,
+ "durationMs": 113
+ },
+ {
+ "method": "wallet.fedimint-balance",
+ "startedAtMs": 400,
+ "durationMs": 112
+ },
+ {
+ "method": "wallet.ark-balance",
+ "startedAtMs": 400,
+ "durationMs": 119
+ },
+ {
+ "method": "lnd.gettransactions",
+ "startedAtMs": 400,
+ "durationMs": 132
+ },
+ {
+ "method": "wallet.ecash-history",
+ "startedAtMs": 400,
+ "durationMs": 136
+ },
+ {
+ "method": "lnd.lightning-history",
+ "startedAtMs": 400,
+ "durationMs": 141
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 394,
+ "durationMs": 151
+ },
+ {
+ "method": "vpn.status",
+ "startedAtMs": 394,
+ "durationMs": 237
+ }
+ ],
+ "maxConcurrentRpc": 12,
+ "rpcWallClockMs": 615,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 1800,
+ "revisitMs": 2035,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 13,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 67,
+ "durationMs": 5
+ },
+ {
+ "method": "system.stats",
+ "startedAtMs": 257,
+ "durationMs": 98
+ },
+ {
+ "method": "openwrt.get-status",
+ "startedAtMs": 257,
+ "durationMs": 98
+ },
+ {
+ "method": "update.status",
+ "startedAtMs": 257,
+ "durationMs": 98
+ },
+ {
+ "method": "wallet.fedimint-balance",
+ "startedAtMs": 265,
+ "durationMs": 90
+ },
+ {
+ "method": "wallet.ark-balance",
+ "startedAtMs": 266,
+ "durationMs": 89
+ },
+ {
+ "method": "wallet.ecash-balance",
+ "startedAtMs": 258,
+ "durationMs": 99
+ },
+ {
+ "method": "lnd.getinfo",
+ "startedAtMs": 257,
+ "durationMs": 100
+ },
+ {
+ "method": "wallet.ecash-history",
+ "startedAtMs": 266,
+ "durationMs": 101
+ },
+ {
+ "method": "lnd.gettransactions",
+ "startedAtMs": 266,
+ "durationMs": 101
+ },
+ {
+ "method": "lnd.lightning-history",
+ "startedAtMs": 266,
+ "durationMs": 102
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 257,
+ "durationMs": 117
+ },
+ {
+ "method": "vpn.status",
+ "startedAtMs": 257,
+ "durationMs": 208
+ }
+ ],
+ "maxConcurrentRpc": 12,
+ "rpcWallClockMs": 398,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 1228,
+ "revisitMs": 2033,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 13,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 16,
+ "durationMs": 59
+ },
+ {
+ "method": "system.stats",
+ "startedAtMs": 376,
+ "durationMs": 133
+ },
+ {
+ "method": "openwrt.get-status",
+ "startedAtMs": 399,
+ "durationMs": 110
+ },
+ {
+ "method": "update.status",
+ "startedAtMs": 399,
+ "durationMs": 112
+ },
+ {
+ "method": "wallet.ecash-balance",
+ "startedAtMs": 399,
+ "durationMs": 113
+ },
+ {
+ "method": "lnd.getinfo",
+ "startedAtMs": 399,
+ "durationMs": 113
+ },
+ {
+ "method": "wallet.fedimint-balance",
+ "startedAtMs": 400,
+ "durationMs": 112
+ },
+ {
+ "method": "wallet.ark-balance",
+ "startedAtMs": 400,
+ "durationMs": 119
+ },
+ {
+ "method": "lnd.gettransactions",
+ "startedAtMs": 400,
+ "durationMs": 132
+ },
+ {
+ "method": "wallet.ecash-history",
+ "startedAtMs": 400,
+ "durationMs": 136
+ },
+ {
+ "method": "lnd.lightning-history",
+ "startedAtMs": 400,
+ "durationMs": 141
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 394,
+ "durationMs": 151
+ },
+ {
+ "method": "vpn.status",
+ "startedAtMs": 394,
+ "durationMs": 237
+ }
+ ],
+ "maxConcurrentRpc": 12,
+ "rpcWallClockMs": 615,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "discover",
+ "label": "Discover (App Store tab)",
+ "path": "/dashboard/discover",
+ "kind": "secondary",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 1184,
+ "revisitMs": 1386,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 18,
+ "durationMs": 69
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 69,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 1117,
+ "revisitMs": 1083,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 5,
+ "durationMs": 1
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 1,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 664,
+ "revisitMs": 1053,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 77,
+ "durationMs": 4
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 4,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 1117,
+ "revisitMs": 1083,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 5,
+ "durationMs": 1
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 1,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "cloud",
+ "label": "Cloud / Files",
+ "path": "/dashboard/cloud",
+ "kind": "main-tab",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 581,
+ "revisitMs": 458,
+ "firstVisitRpcCount": 1,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 463,
+ "revisitMs": 205,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 233,
+ "revisitMs": 247,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": false,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 463,
+ "revisitMs": 247,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "mesh",
+ "label": "Mesh",
+ "path": "/dashboard/mesh",
+ "kind": "main-tab",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.waitFor: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.mesh-status-grid').first() to be visible\u001b[22m\n"
+ },
+ {
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.waitFor: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.mesh-status-grid').first() to be visible\u001b[22m\n\u001b[2m 28 × locator resolved to hidden …
\u001b[22m\n"
+ },
+ {
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.waitFor: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.mesh-status-grid').first() to be visible\u001b[22m\n\u001b[2m 44 × locator resolved to hidden …
\u001b[22m\n"
+ }
+ ],
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.waitFor: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.mesh-status-grid').first() to be visible\u001b[22m\n\u001b[2m 44 × locator resolved to hidden …
\u001b[22m\n"
+ },
+ {
+ "id": "server",
+ "label": "Server (Network)",
+ "path": "/dashboard/server",
+ "kind": "main-tab",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 1662,
+ "revisitMs": 738,
+ "firstVisitRpcCount": 5,
+ "revisitRpcCount": 8,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 24,
+ "durationMs": 1
+ },
+ {
+ "method": "tor.list-services",
+ "startedAtMs": 554,
+ "durationMs": 157
+ },
+ {
+ "method": "router.list-forwards",
+ "startedAtMs": 565,
+ "durationMs": 147
+ },
+ {
+ "method": "network.dns-status",
+ "startedAtMs": 565,
+ "durationMs": 147
+ },
+ {
+ "method": "network.list-interfaces",
+ "startedAtMs": 566,
+ "durationMs": 151
+ },
+ {
+ "method": "system.disk-status",
+ "startedAtMs": 570,
+ "durationMs": 149
+ },
+ {
+ "method": "vpn.list-peers",
+ "startedAtMs": 570,
+ "durationMs": 149
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 570,
+ "durationMs": 168
+ }
+ ],
+ "maxConcurrentRpc": 7,
+ "rpcWallClockMs": 714,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 969,
+ "revisitMs": 808,
+ "firstVisitRpcCount": 7,
+ "revisitRpcCount": 11,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 94,
+ "durationMs": 21
+ },
+ {
+ "method": "node-messages-received",
+ "startedAtMs": 210,
+ "durationMs": 23
+ },
+ {
+ "method": "mesh.peers",
+ "startedAtMs": 211,
+ "durationMs": 51
+ },
+ {
+ "method": "mesh.messages",
+ "startedAtMs": 211,
+ "durationMs": 51
+ },
+ {
+ "method": "mesh.deadman-status",
+ "startedAtMs": 217,
+ "durationMs": 45
+ },
+ {
+ "method": "mesh.status",
+ "startedAtMs": 211,
+ "durationMs": 51
+ },
+ {
+ "method": "mesh.block-headers",
+ "startedAtMs": 217,
+ "durationMs": 89
+ },
+ {
+ "method": "tor.list-services",
+ "startedAtMs": 770,
+ "durationMs": 15
+ },
+ {
+ "method": "network.list-interfaces",
+ "startedAtMs": 771,
+ "durationMs": 14
+ },
+ {
+ "method": "system.disk-status",
+ "startedAtMs": 771,
+ "durationMs": 14
+ },
+ {
+ "method": "vpn.list-peers",
+ "startedAtMs": 771,
+ "durationMs": 14
+ }
+ ],
+ "maxConcurrentRpc": 6,
+ "rpcWallClockMs": 691,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 634,
+ "revisitMs": 563,
+ "firstVisitRpcCount": 4,
+ "revisitRpcCount": 7,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 127,
+ "durationMs": 106
+ },
+ {
+ "method": "tor.list-services",
+ "startedAtMs": 518,
+ "durationMs": 25
+ },
+ {
+ "method": "router.list-forwards",
+ "startedAtMs": 518,
+ "durationMs": 25
+ },
+ {
+ "method": "network.dns-status",
+ "startedAtMs": 522,
+ "durationMs": 22
+ },
+ {
+ "method": "network.list-interfaces",
+ "startedAtMs": 522,
+ "durationMs": 22
+ },
+ {
+ "method": "system.disk-status",
+ "startedAtMs": 522,
+ "durationMs": 22
+ },
+ {
+ "method": "vpn.list-peers",
+ "startedAtMs": 522,
+ "durationMs": 22
+ }
+ ],
+ "maxConcurrentRpc": 6,
+ "rpcWallClockMs": 417,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 969,
+ "revisitMs": 738,
+ "firstVisitRpcCount": 5,
+ "revisitRpcCount": 8,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 24,
+ "durationMs": 1
+ },
+ {
+ "method": "tor.list-services",
+ "startedAtMs": 554,
+ "durationMs": 157
+ },
+ {
+ "method": "router.list-forwards",
+ "startedAtMs": 565,
+ "durationMs": 147
+ },
+ {
+ "method": "network.dns-status",
+ "startedAtMs": 565,
+ "durationMs": 147
+ },
+ {
+ "method": "network.list-interfaces",
+ "startedAtMs": 566,
+ "durationMs": 151
+ },
+ {
+ "method": "system.disk-status",
+ "startedAtMs": 570,
+ "durationMs": 149
+ },
+ {
+ "method": "vpn.list-peers",
+ "startedAtMs": 570,
+ "durationMs": 149
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 570,
+ "durationMs": 168
+ }
+ ],
+ "maxConcurrentRpc": 7,
+ "rpcWallClockMs": 714,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "web5",
+ "label": "Web5",
+ "path": "/dashboard/web5",
+ "kind": "main-tab",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 394,
+ "revisitMs": 606,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 231,
+ "revisitMs": 255,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 307,
+ "revisitMs": 566,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 307,
+ "revisitMs": 566,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "fleet",
+ "label": "Fleet",
+ "path": "/dashboard/fleet",
+ "kind": "main-tab",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 1054,
+ "revisitMs": 548,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 376,
+ "revisitMs": 305,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 295,
+ "revisitMs": 330,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 376,
+ "revisitMs": 330,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "chat",
+ "label": "Chat (AIUI)",
+ "path": "/dashboard/chat",
+ "kind": "main-tab",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.click: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.chat-close-btn').first()\u001b[22m\n\u001b[2m - locator resolved to … \u001b[22m\n\u001b[2m - attempting click action\u001b[22m\n\u001b[2m 2 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 20ms\u001b[22m\n\u001b[2m 2 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 100ms\u001b[22m\n\u001b[2m 36 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 500ms\u001b[22m\n"
+ },
+ {
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.click: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.chat-close-btn').first()\u001b[22m\n\u001b[2m - locator resolved to … \u001b[22m\n\u001b[2m - attempting click action\u001b[22m\n\u001b[2m - waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - …
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is not stable\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 20ms\u001b[22m\n\u001b[2m 2 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 100ms\u001b[22m\n\u001b[2m 37 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 500ms\u001b[22m\n"
+ },
+ {
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.click: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.chat-close-btn').first()\u001b[22m\n\u001b[2m - locator resolved to … \u001b[22m\n\u001b[2m - attempting click action\u001b[22m\n\u001b[2m - waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - …
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is not stable\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 20ms\u001b[22m\n\u001b[2m 2 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 100ms\u001b[22m\n\u001b[2m 37 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 500ms\u001b[22m\n"
+ }
+ ],
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.click: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.chat-close-btn').first()\u001b[22m\n\u001b[2m - locator resolved to … \u001b[22m\n\u001b[2m - attempting click action\u001b[22m\n\u001b[2m - waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - …
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is not stable\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 20ms\u001b[22m\n\u001b[2m 2 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 100ms\u001b[22m\n\u001b[2m 37 × waiting for element to be visible, enabled and stable\u001b[22m\n\u001b[2m - element is visible, enabled and stable\u001b[22m\n\u001b[2m - scrolling into view if needed\u001b[22m\n\u001b[2m - done scrolling\u001b[22m\n\u001b[2m - Disk usage at 80.2% (threshold: 80%)
from …
subtree intercepts pointer events\u001b[22m\n\u001b[2m - retrying click action\u001b[22m\n\u001b[2m - waiting 500ms\u001b[22m\n"
+ },
+ {
+ "id": "app-details",
+ "label": "AppDetails (secondary)",
+ "path": "/dashboard/apps/:id",
+ "kind": "secondary",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 1405,
+ "revisitMs": 1864,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 8,
+ "revisitRpcCalls": [
+ {
+ "method": "node.nostr-pubkey",
+ "startedAtMs": 160,
+ "durationMs": 242
+ },
+ {
+ "method": "auth.totp.status",
+ "startedAtMs": 160,
+ "durationMs": 252
+ },
+ {
+ "method": "webhook.get-config",
+ "startedAtMs": 160,
+ "durationMs": 427
+ },
+ {
+ "method": "analytics.get-status",
+ "startedAtMs": 161,
+ "durationMs": 426
+ },
+ {
+ "method": "backup.list",
+ "startedAtMs": 161,
+ "durationMs": 426
+ },
+ {
+ "method": "system.kiosk-display.get",
+ "startedAtMs": 161,
+ "durationMs": 426
+ },
+ {
+ "method": "system.settings.get",
+ "startedAtMs": 161,
+ "durationMs": 433
+ },
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 594,
+ "durationMs": 51
+ }
+ ],
+ "maxConcurrentRpc": 7,
+ "rpcWallClockMs": 485,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 1040,
+ "revisitMs": 1204,
+ "firstVisitRpcCount": 1,
+ "revisitRpcCount": 1,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 86,
+ "durationMs": 4
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 4,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 876,
+ "revisitMs": 1065,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 2,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 35,
+ "durationMs": 12
+ },
+ {
+ "method": "package.credentials",
+ "startedAtMs": 1002,
+ "durationMs": 26
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 993,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 1040,
+ "revisitMs": 1204,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 2,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 86,
+ "durationMs": 4
+ }
+ ],
+ "maxConcurrentRpc": 1,
+ "rpcWallClockMs": 4,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "marketplace-app-details",
+ "label": "MarketplaceAppDetails (secondary)",
+ "path": "/dashboard/marketplace/:id",
+ "kind": "secondary",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 1752,
+ "revisitMs": 1718,
+ "firstVisitRpcCount": 1,
+ "revisitRpcCount": 14,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 89,
+ "durationMs": 7
+ },
+ {
+ "method": "system.stats",
+ "startedAtMs": 315,
+ "durationMs": 11
+ },
+ {
+ "method": "openwrt.get-status",
+ "startedAtMs": 315,
+ "durationMs": 11
+ },
+ {
+ "method": "update.status",
+ "startedAtMs": 315,
+ "durationMs": 11
+ },
+ {
+ "method": "wallet.ecash-balance",
+ "startedAtMs": 315,
+ "durationMs": 11
+ },
+ {
+ "method": "wallet.ark-balance",
+ "startedAtMs": 315,
+ "durationMs": 11
+ },
+ {
+ "method": "wallet.fedimint-balance",
+ "startedAtMs": 315,
+ "durationMs": 17
+ },
+ {
+ "method": "lnd.getinfo",
+ "startedAtMs": 315,
+ "durationMs": 22
+ },
+ {
+ "method": "wallet.ecash-history",
+ "startedAtMs": 316,
+ "durationMs": 84
+ },
+ {
+ "method": "lnd.lightning-history",
+ "startedAtMs": 315,
+ "durationMs": 111
+ },
+ {
+ "method": "lnd.gettransactions",
+ "startedAtMs": 315,
+ "durationMs": 111
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 315,
+ "durationMs": 119
+ },
+ {
+ "method": "vpn.status",
+ "startedAtMs": 315,
+ "durationMs": 303
+ },
+ {
+ "method": "package.versions",
+ "startedAtMs": 868,
+ "durationMs": 278
+ }
+ ],
+ "maxConcurrentRpc": 12,
+ "rpcWallClockMs": 1057,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 1978,
+ "revisitMs": 1868,
+ "firstVisitRpcCount": 2,
+ "revisitRpcCount": 14,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 57,
+ "durationMs": 11
+ },
+ {
+ "method": "system.stats",
+ "startedAtMs": 293,
+ "durationMs": 124
+ },
+ {
+ "method": "openwrt.get-status",
+ "startedAtMs": 296,
+ "durationMs": 121
+ },
+ {
+ "method": "update.status",
+ "startedAtMs": 296,
+ "durationMs": 121
+ },
+ {
+ "method": "wallet.ecash-balance",
+ "startedAtMs": 296,
+ "durationMs": 122
+ },
+ {
+ "method": "wallet.fedimint-balance",
+ "startedAtMs": 296,
+ "durationMs": 122
+ },
+ {
+ "method": "wallet.ark-balance",
+ "startedAtMs": 296,
+ "durationMs": 122
+ },
+ {
+ "method": "lnd.getinfo",
+ "startedAtMs": 296,
+ "durationMs": 124
+ },
+ {
+ "method": "wallet.ecash-history",
+ "startedAtMs": 296,
+ "durationMs": 143
+ },
+ {
+ "method": "lnd.lightning-history",
+ "startedAtMs": 296,
+ "durationMs": 163
+ },
+ {
+ "method": "lnd.gettransactions",
+ "startedAtMs": 296,
+ "durationMs": 166
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 295,
+ "durationMs": 170
+ },
+ {
+ "method": "vpn.status",
+ "startedAtMs": 295,
+ "durationMs": 363
+ },
+ {
+ "method": "package.versions",
+ "startedAtMs": 1008,
+ "durationMs": 408
+ }
+ ],
+ "maxConcurrentRpc": 12,
+ "rpcWallClockMs": 1359,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 2175,
+ "revisitMs": 1793,
+ "firstVisitRpcCount": 1,
+ "revisitRpcCount": 14,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 83,
+ "durationMs": 25
+ },
+ {
+ "method": "openwrt.get-status",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "update.status",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "lnd.getinfo",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "wallet.ecash-balance",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "wallet.fedimint-balance",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "wallet.ark-balance",
+ "startedAtMs": 356,
+ "durationMs": 92
+ },
+ {
+ "method": "lnd.gettransactions",
+ "startedAtMs": 356,
+ "durationMs": 191
+ },
+ {
+ "method": "wallet.ecash-history",
+ "startedAtMs": 360,
+ "durationMs": 187
+ },
+ {
+ "method": "system.stats",
+ "startedAtMs": 354,
+ "durationMs": 227
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 355,
+ "durationMs": 227
+ },
+ {
+ "method": "lnd.lightning-history",
+ "startedAtMs": 356,
+ "durationMs": 228
+ },
+ {
+ "method": "vpn.status",
+ "startedAtMs": 354,
+ "durationMs": 371
+ },
+ {
+ "method": "package.versions",
+ "startedAtMs": 1459,
+ "durationMs": 286
+ }
+ ],
+ "maxConcurrentRpc": 12,
+ "rpcWallClockMs": 1662,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 1978,
+ "revisitMs": 1793,
+ "firstVisitRpcCount": 1,
+ "revisitRpcCount": 14,
+ "revisitRpcCalls": [
+ {
+ "method": "system.get-hostname",
+ "startedAtMs": 83,
+ "durationMs": 25
+ },
+ {
+ "method": "openwrt.get-status",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "update.status",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "lnd.getinfo",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "wallet.ecash-balance",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "wallet.fedimint-balance",
+ "startedAtMs": 355,
+ "durationMs": 93
+ },
+ {
+ "method": "wallet.ark-balance",
+ "startedAtMs": 356,
+ "durationMs": 92
+ },
+ {
+ "method": "lnd.gettransactions",
+ "startedAtMs": 356,
+ "durationMs": 191
+ },
+ {
+ "method": "wallet.ecash-history",
+ "startedAtMs": 360,
+ "durationMs": 187
+ },
+ {
+ "method": "system.stats",
+ "startedAtMs": 354,
+ "durationMs": 227
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 355,
+ "durationMs": 227
+ },
+ {
+ "method": "lnd.lightning-history",
+ "startedAtMs": 356,
+ "durationMs": 228
+ },
+ {
+ "method": "vpn.status",
+ "startedAtMs": 354,
+ "durationMs": 371
+ },
+ {
+ "method": "package.versions",
+ "startedAtMs": 1459,
+ "durationMs": 286
+ }
+ ],
+ "maxConcurrentRpc": 12,
+ "rpcWallClockMs": 1662,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "cloud-folder",
+ "label": "CloudFolder (secondary)",
+ "path": "/dashboard/cloud/:folderId",
+ "kind": "secondary",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.waitFor: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('.cloud-folder-container h1').first() to be visible\u001b[22m\n"
+ },
+ {
+ "firstVisitMs": 9794,
+ "revisitMs": 1056,
+ "firstVisitRpcCount": 4,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 438,
+ "revisitMs": 1368,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 5116,
+ "revisitMs": 1212,
+ "firstVisitRpcCount": 2,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "openwrt-gateway",
+ "label": "OpenWrtGateway (secondary)",
+ "path": "/dashboard/server/openwrt",
+ "kind": "secondary",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": null,
+ "revisitMs": null,
+ "firstVisitRpcCount": null,
+ "revisitRpcCount": null,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": null,
+ "rpcWallClockMs": null,
+ "remounted": null,
+ "error": "locator.waitFor: Timeout 20000ms exceeded.\nCall log:\n\u001b[2m - waiting for locator('h1:has-text(\"OpenWrt Gateway\")').first() to be visible\u001b[22m\n"
+ },
+ {
+ "firstVisitMs": 5904,
+ "revisitMs": 895,
+ "firstVisitRpcCount": 4,
+ "revisitRpcCount": 4,
+ "revisitRpcCalls": [
+ {
+ "method": "vpn.list-peers",
+ "startedAtMs": 558,
+ "durationMs": 307
+ },
+ {
+ "method": "network.list-interfaces",
+ "startedAtMs": 558,
+ "durationMs": 307
+ },
+ {
+ "method": "tor.list-services",
+ "startedAtMs": 553,
+ "durationMs": 312
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 553,
+ "durationMs": 312
+ }
+ ],
+ "maxConcurrentRpc": 4,
+ "rpcWallClockMs": 312,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 522,
+ "revisitMs": 432,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 4,
+ "revisitRpcCalls": [
+ {
+ "method": "vpn.list-peers",
+ "startedAtMs": 182,
+ "durationMs": 238
+ },
+ {
+ "method": "network.list-interfaces",
+ "startedAtMs": 182,
+ "durationMs": 238
+ },
+ {
+ "method": "tor.list-services",
+ "startedAtMs": 182,
+ "durationMs": 238
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 182,
+ "durationMs": 238
+ }
+ ],
+ "maxConcurrentRpc": 4,
+ "rpcWallClockMs": 238,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 3213,
+ "revisitMs": 663.5,
+ "firstVisitRpcCount": 2,
+ "revisitRpcCount": 4,
+ "revisitRpcCalls": [
+ {
+ "method": "vpn.list-peers",
+ "startedAtMs": 558,
+ "durationMs": 307
+ },
+ {
+ "method": "network.list-interfaces",
+ "startedAtMs": 558,
+ "durationMs": 307
+ },
+ {
+ "method": "tor.list-services",
+ "startedAtMs": 553,
+ "durationMs": 312
+ },
+ {
+ "method": "fips.status",
+ "startedAtMs": 553,
+ "durationMs": 312
+ }
+ ],
+ "maxConcurrentRpc": 4,
+ "rpcWallClockMs": 312,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "id": "wallet-send",
+ "label": "Wallet / send flow (Home wallet card, SendBitcoinModal)",
+ "path": "/dashboard",
+ "kind": "secondary",
+ "runs": 3,
+ "samples": [
+ {
+ "firstVisitMs": 857,
+ "revisitMs": 2562,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 735,
+ "revisitMs": 2619,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ },
+ {
+ "firstVisitMs": 607,
+ "revisitMs": 2607,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ }
+ ],
+ "firstVisitMs": 735,
+ "revisitMs": 2607,
+ "firstVisitRpcCount": 0,
+ "revisitRpcCount": 0,
+ "revisitRpcCalls": [],
+ "maxConcurrentRpc": 0,
+ "rpcWallClockMs": 0,
+ "remounted": true,
+ "error": null
+ }
+ ]
+}
\ No newline at end of file
diff --git a/neode-ui/e2e/perf/measure.ts b/neode-ui/e2e/perf/measure.ts
index 95b88d24..b5327263 100644
--- a/neode-ui/e2e/perf/measure.ts
+++ b/neode-ui/e2e/perf/measure.ts
@@ -231,10 +231,24 @@ async function dismissOverlays(page: Page): Promise {
async function goHome(page: Page, timeoutMs: number): Promise {
// DashboardSidebar.vue is `v-show="!chatFullscreen"` — if a prior surface's
// run ended sitting on /dashboard/chat (e.g. chat's own revisit re-opened
- // it as its last step), the sidebar is hidden and unclickable. Back out of
- // chat first so the sidebar reappears before relying on it below.
+ // it as its last step, or a prior run errored out mid-chat), the sidebar is
+ // hidden and unclickable. Back out of chat first so the sidebar reappears
+ // before relying on it below.
if (new URL(page.url()).pathname === '/dashboard/chat') {
- await page.locator('.chat-close-btn').first().click({ timeout: timeoutMs }).catch(() => {})
+ const closed = await page
+ .locator('.chat-close-btn')
+ .first()
+ .click({ timeout: 5_000 })
+ .then(() => true)
+ .catch(() => false)
+ // On real AIUI hardware the close pill can sit behind AIUI's own
+ // "connecting" overlay for longer than any reasonable click budget — if
+ // the close button itself is unreachable, this is a recovery path, not a
+ // measurement, so a hard reload to break out is preferable to leaving
+ // every remaining surface stuck behind a permanently hidden sidebar.
+ if (!closed) {
+ await page.goto('/dashboard', { waitUntil: 'domcontentloaded' }).catch(() => {})
+ }
}
await clickWithGuard(page, '[data-controller-zone="sidebar"] a[href="/dashboard"]', timeoutMs)
await page.waitForURL((url) => url.pathname === '/dashboard', { timeout: timeoutMs })
diff --git a/neode-ui/e2e/perf/surface-perf.spec.ts b/neode-ui/e2e/perf/surface-perf.spec.ts
index 80d8f9e7..f47ab22f 100644
--- a/neode-ui/e2e/perf/surface-perf.spec.ts
+++ b/neode-ui/e2e/perf/surface-perf.spec.ts
@@ -39,7 +39,12 @@ async function login(page: Page): Promise {
function currentCommit(): string {
try {
- return execSync('git rev-parse --short HEAD', { cwd: __dirname }).toString().trim()
+ // `__dirname` is unavailable under this package's `"type": "module"` ESM
+ // runtime (Playwright's own transform swallows the ReferenceError into
+ // the catch below, silently yielding 'unknown') — use `process.cwd()`
+ // instead, which Playwright always sets to the project root it was
+ // invoked from.
+ return execSync('git rev-parse --short HEAD', { cwd: process.cwd() }).toString().trim()
} catch {
return 'unknown'
}